頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


TensorFlowの学習結果をiOSのMPSで使う

PythonでTensorFlow使って簡単な方(つまり畳み込みじゃない方ね)のMNISTをやって、計算結果の係数(重み、バイアス)を出力して、iOSのMetal Performance Shadersで使い、手書き数字認識させるのにえらくハマったのでそのあたりのメモ。ちなみにiOSで使うのはObjective-Cです、はい。Swiftだったらサンプルコード(MPSCNNHelloWorld)もあるのでだいぶラクだったとは思いますけどね。

iOSでもTensorFlowが使えるんだけど、ここはやっぱりMPSの方がアプリの容量も小さくなるらしいのでMPSで。

iOSのMPSCNNに渡すモデルパラメータのフォーマット / TensorFlowからの書き出し - Qiita
↑基本こちらを参考にさせていただきました。

まず、Pythonでの学習後に係数を出力するところ。
{
	with open(filePath_iOS+'weights.dat', 'wb') as f:
            W_trans = tf.transpose(W, perm=[1,0])
            f.write(sess.run(W_trans).tobytes())
	with open(filePath_iOS+'bias.dat', 'wb') as f:
            f.write(sess.run(b).tobytes())
}
参考のページと違って open( , ‘w’) → open( , ‘wb’) にしないとダメだった。
あと、重みは順番を変更。

次にiOS側。
わかりにくいのがGPUでの結果が16bitの浮動小数点数で出てくるけどCPUで使う場合にはfloatは32bitだというところ。
Swift で 半精度浮動小数点数 (16 bit Float) を扱う - Qiita
↑こちらなどを参考に16bit→32bitとして読む、というのをできるようにならないとデバッグが進みませんでした。

-(float)getFloatFromUInt16:(UInt16)value
{
    UInt16 *input = calloc(1, sizeof(UInt16));
    input[0] = value;
    float *output = calloc(1, sizeof(float));
    output[0] = 0.0;
    
    vImage_Buffer sourceBuffer;
    sourceBuffer.data = input;
    sourceBuffer.height = 1;
    sourceBuffer.width = 1;
    sourceBuffer.rowBytes = sizeof(UInt16);
    
    vImage_Buffer destinationBuffer;
    destinationBuffer.data = output;
    destinationBuffer.height = 1;
    destinationBuffer.width = 1;
    destinationBuffer.rowBytes = sizeof(float);

    vImageConvert_Planar16FtoPlanarF(&sourceBuffer, &destinationBuffer, 0);
    
    float floatValue = output[0];
    
    free(input);
    free(output);
    
    return floatValue;
}
↑こういうのを作っといて入出力画像のMTLTextureの中身なんぞを確認してました。

無駄にハマったのが入力画像をセットする
replaceRegion:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage:
のwithBytes:のところに context と書いてて正しく動かず(実行可能だけど正解が出ない)悩んでた。
正解はCGBitmapContextGetData (context)

サンプルコード(Swift)で
context!.data!
となってるのに、contextとするだけで必要なデータが取れると思ってたのよ。


ともかくこれで、Pythonで学習させ係数を出力、iOSのMPSで使う、って流れの第一段階はクリアできたかな。
次は畳み込みの場合でできるようにならねば。

<< TensorFlowのlrn層ってMPSではどう記述するの?  TopPage  3Dのボーン付き人体モデルをSceneKitで使う >>

コメント


管理者にだけ表示を許可する
 

トラックバック

トラックバックURL
http://ringsbell.blog117.fc2.com/tb.php/1057-72572d9f




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad