この記事は、Muminjon 氏のブログの抄訳です
MNIST (Modified National Institute of Standards and Technologyの略)は、包括的なコンピュータビジョンデータベースのるつぼです。1999年のリリース以来、MNISTの古典的な手書きのイメージのデータセットは、分類アルゴリズムのベンチマークの基盤として受け入れられてきました。
ほとんどの場合、はじめて学習する方はMNISTで与えられた数字を分類することから始めます。このブログでは、RAD Studio(Delphi)とTensorFlowを使用して、数字の分類を行なう方法を紹介いたします。
Table of Contents
このチュートリアルで学べることは?
- 簡単なニューラルネットワークを含むコンピュータビジョンの基礎
- 分類する方法
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はそのデータを28×28ピクセルの画像として取得し、それを変換して0から9までの数字として返します。
実際の画像を再現するために、28×28ピクセルの入力は、784ピクセルの1次元ベクトルにフラット化しています。つまり、画像を構成する784ピクセルのそれぞれは、0〜255のの範囲の値として格納されます。これは、画像が白黒で表示されるため、ピクセルのグレースケールを判断するのに役立ちます。入力画像の黒いピクセルは255で表され、白いピクセルは0で表されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
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
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition