Have an amazing solution built in RAD Studio? Let us know. Looking for discounts? Visit our Special Offers page!
DelphiRAD Studio

Tensorflowで数字の分類器を構築する方法

how to build a digit classifier

この記事は、Muminjon 氏のブログの抄訳です

MNIST (Modified National Institute of Standards and Technologyの略)は、包括的なコンピュータビジョンデータベースのるつぼです。1999年のリリース以来、MNISTの古典的な手書きのイメージのデータセットは、分類アルゴリズムのベンチマークの基盤として受け入れられてきました。

mnist 7851794 2
画像のソース元 researchgatenet

ほとんどの場合、はじめて学習する方はMNISTで与えられた数字を分類することから始めます。このブログでは、RAD Studio(Delphi)とTensorFlowを使用して、数字の分類を行なう方法を紹介いたします。

このチュートリアルで学べることは?

  • 簡単なニューラルネットワークを含むコンピュータビジョンの基礎
  • 分類する方法

MNISTとは?

MNISTは、0から9までの手書きの1桁の数字で、28×28ピクセルの範囲に収まるようにサイズが正規化されたグレースケール画像 6万枚のデータセットです。20年以上の歴史があるため、様々なトップパフォーマンスのモデルがディープラーニングの畳み込みニューラルネットワークの分野で、99%以上の分類精度を達成しています。

画像内の手書きの数字を認識するには?

「TensorFlow」は、Google Brainラボが開発した深層学習研究のためのオープンソースのライブラリです。通常、プロジェクトの新しいモデルをトレーニングするのに時間がかかりますが、物体やパターンなどを検出するための学習済みモデルがすでに存在するため、モデルをロードし、データを入力するだけで簡単に高い結果が得られます。

TensorFlow Liteモデルとは?

TensorFlow Liteモデルは、「FlatBuffers」と呼ばれる独特の効率的なポータブルフォーマットで提供される。このTensorFlow Liteモデルは、開発者がモバイル デバイス、組み込みデバイス、IoT デバイス上でモデルを実行できるようにすることで、デバイス上の機械学習を可能にするツールセットです。
TensorFlow Liteモデルについては、こちらで紹介しています。

DelphiでTensorFlowを使用するには?

DelphiおよびC++開発者の素晴らしいコミュニティのおかげで、現在 TensorFlow LiteはDelphiで利用可能で、こちらのリンクから「TensorFlow Lite Model for Delphi」のリポジトリにアクセスできます。

TFLITEダイナミックリンクライブラリ(DLL)は、TensorFlow Liteのモデル機能を利用する際に役立ちます。TensorFlow Lite全体で使用される共通の列挙型、型、およびメソッドが含まれています。これには、エラーコードからカーネルおよびデリゲートAPIなど全ての機能が含まれています。

tensorflow lite delphi delphi machine learning machine learning in delphi programming language 1730262 2

プロジェクト全体をダウンロードしてテストすることができます。下図のように、手書きの数字を描くと、TensorFlowはそのデータを28×28ピクセルの画像として取得し、それを変換して0から9までの数字として返します。

machine learning in delphi digit classification in delphi tensorflow lite model 7445733 2

実際の画像を再現するために、28×28ピクセルの入力は、784ピクセルの1次元ベクトルにフラット化しています。つまり、画像を構成する784ピクセルのそれぞれは、0〜255のの範囲の値として格納されます。これは、画像が白黒で表示されるため、ピクセルのグレースケールを判断するのに役立ちます。入力画像の黒いピクセルは255で表され、白いピクセルは0で表されます。

digit classifier for delphi tensorflow lite for delphi delphi machine learning building neural networks with delphi 3493358 2
digit classifier for delphi tensorflow lite model for delphi machine learning in delphi programming language 3221555 2
procedure TForm1.Button2Click(Sender: TObject);
var
  i, X, Y: DWORD;
 
  fLibrary: HMODULE;
  fModel: Pointer;
  fInterpreterOptions: Pointer;
  fInterpreter: Pointer;
  fStatus: TfLiteStatus;
  fInputTensorCount, fOutputTensorCount, fNumDims: Int32;
  fInputTensor, fOutputTensor: Pointer;
  fInputDims: Integer;
  fTensorName: PAnsiChar;
  fTensorType: TfLiteType;
  fTensorByteSize: SIZE_T;
 
  // 28x28 pixel image as input
  fInput: array [0 .. 28 * 28 - 1] of Float32;
 
  // output 0 to 9
  fOutput: array [0 .. 10 - 1] of Float32;
 
  fValue: Extended;
begin
  fLibrary := LoadLibrary(LibraryName);
 
  if fLibrary = 0 then
  begin
    ShowMessage('Error: Load tensorflow lite library ' + LibraryName + ' - ' +
      SysErrorMessage(GetLastError));
    Exit;
  end;
 
  try
    fModel := TfLiteModelCreateFromFile(PAnsiChar(AnsiString(Edit1.Text)));
 
    if fModel = nil then
    begin
      ShowMessage('Error: Create model from file - ' +
        SysErrorMessage(GetLastError));
      Exit;
    end;
 
    fInterpreterOptions := TfLiteInterpreterOptionsCreate;
 
    if fInterpreterOptions <> nil then
    begin
      TfLiteInterpreterOptionsSetNumThreads(fInterpreterOptions, 2);
 
      fInterpreter := TfLiteInterpreterCreate(fModel, fInterpreterOptions);
 
      // parameters / model can be removed immediately after the interpreter is created
      TfLiteInterpreterOptionsDelete(fInterpreterOptions);
      TfLiteModelDelete(fModel);
 
      if fInterpreter <> nil then
      begin
        fStatus := TfLiteInterpreterAllocateTensors(fInterpreter);
 
        fInputTensorCount := TfLiteInterpreterGetInputTensorCount(fInterpreter);
        fOutputTensorCount := TfLiteInterpreterGetOutputTensorCount
          (fInterpreter);
 
        // fLiteTensor* TfLiteInterpreterGetInputTensor(const TfLiteInterpreter* interpreter, int32_t input_index);
        // returned structure TfLiteTensor
        // an example is simple, there is no need to translate everything from the
        // in general, the source of the: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/c
        { typedef struct TfLiteTensor {
          TfLiteType type;
          TfLitePtrUnion data;
          TfLiteIntArray* dims;
          TfLiteQuantizationParams params;
          TfLiteAllocationType allocation_type;
          size_t bytes;
          const void* allocation;
          const char* name;
          struct TfLiteDelegate* delegate;
          TfLiteBufferHandle buffer_handle;
          bool data_is_stale;
          bool is_variable;
          TfLiteQuantization quantization;
          TfLiteSparsity* sparsity;
          const TfLiteIntArray* dims_signature; }
        fInputTensor := TfLiteInterpreterGetInputTensor(fInterpreter, 0);
        fOutputTensor := TfLiteInterpreterGetOutputTensor(fInterpreter, 0);
 
        if fInputTensor <> nil then
        begin
          // info about tensor
          // fNumDims := TfLiteTensorNumDims(fInputTensor);
          // fTensorName := TfLiteTensorName(fInputTensor);
          // fTensorType := TfLiteTensorType(fInputTensor);
          fTensorByteSize := TfLiteTensorByteSize(fInputTensor);
 
          // writing pixels to fInput, top to bottom, left to right
          for Y := 0 to Image1.Picture.Bitmap.Height - 1 do
          begin
            for X := 0 to Image1.Picture.Bitmap.Width - 1 do
            begin
              if (Image1.Canvas.Pixels[X, Y] > 0) then
                fInput[X + (Y * Image1.Picture.Bitmap.Width)] := 1
              else
                fInput[X + (Y * Image1.Picture.Bitmap.Width)] := 0;
            end;
          end;
 
          // fTensorByteSize = Length(fInput) * SizeOf(Float32)
          fStatus := TfLiteTensorCopyFromBuffer(fInputTensor, @fInput,
            fTensorByteSize);
 
          fStatus := TfLiteInterpreterInvoke(fInterpreter);
 
          if fStatus = kTfLiteOk then
          begin
            for i := 0 to High(fOutput) do
              fOutput[i] := 0;
 
            fOutputTensor := TfLiteInterpreterGetOutputTensor(fInterpreter, 0);
 
            // info about tensor
            // fNumDims := TfLiteTensorNumDims(fOutputTensor);
            // fTensorName := TfLiteTensorName(fOutputTensor);
            // fTensorType := TfLiteTensorType(fOutputTensor);
            fTensorByteSize := TfLiteTensorByteSize(fOutputTensor);
 
            if fOutputTensor <> nil then
            begin
              // fTensorByteSize = Length(fOutput) * SizeOf(Float32)
              fStatus := TfLiteTensorCopyToBuffer(fOutputTensor, @fOutput,
                fTensorByteSize);
 
              if fStatus = kTfLiteOk then
              begin
                ListView1.Items.Clear;
 
                for i := 0 to Length(fOutput) - 1 do
                begin
                  // ingenious solution, coolest conversion
                  fValue := StrToFloat(Copy(FloatToStr(fOutput[i]), 1, 17));
 
                  if fValue <= 1 then
                  begin
                    with ListView1.Items.Add do
                    begin
                      Caption := FloatToStrF(fValue, ffNumber, 17, 17);
                      SubItems.Add(IntToStr(i));
                    end;
                  end;
                end;
 
                ListView1.AlphaSort;
 
                Beep;
              end;
            end;
          end;
        end;
      end;
    end;
  finally
    FreeLibrary(fLibrary);
  end;
end;

下記のリンクにアクセスしてサンプルコードをダウンロードし、実際に試してみてください。

https://github.com/qq33095304/TensorFlow-Lite-Delphi

RAD Studio 13.1 Florence Now Available See What's New in RAD Studio 13.1 Delphi is 31 - Webinar Replay

Reduce development time and get to market faster with RAD Studio, Delphi, or C++Builder.
Design. Code. Compile. Deploy.

Start Free Trial   Upgrade Today

   Free Delphi Community Edition   Free C++Builder Community Edition

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

IN THE ARTICLES