ツインテールdeエンジェルモード!! で、MNISTデータセットの推論体験の
その3です。前は、推論体験用スクリプトの作成まででした。
その、推論体験用スクリプトを実行すると、こんな感じになります。
出力されたそれぞれの数字は、
(1)画像データの番号(何枚目か?)と、
(2)認識した文字の確率となります。
具体的には、
y[0] = 文字が0の確率
y[1] = 文字が1の確率
...
y[9] = 文字が9の確率
となります。では、実行してみます。
% tt forward-test
0
y[0]=0.000084,y[1]=0.000003,y[2]=0.000715,y[3]=0.001259,y[4]=0.000001,y[5]=0.000045,y[6]=0.000000,y[7]=0.997065,y[8]=0.000009,y[9]=0.000818
1
y[0]=0.004836,y[1]=0.001105,y[2]=0.944252,y[3]=0.014309,y[4]=0.000001,y[5]=0.006676,y[6]=0.027533,y[7]=0.000001,y[8]=0.001286,y[9]=0.000000
2
y[0]=0.000000,y[1]=0.988973,y[2]=0.004289,y[3]=0.001783,y[4]=0.000132,y[5]=0.000759,y[6]=0.000469,y[7]=0.002270,y[8]=0.001238,y[9]=0.000087
3
y[0]=0.994115,y[1]=0.000000,y[2]=0.001591,y[3]=0.000190,y[4]=0.000004,y[5]=0.003371,y[6]=0.000407,y[7]=0.000232,y[8]=0.000048,y[9]=0.000042
4
y[0]=0.000207,y[1]=0.000007,y[2]=0.002890,y[3]=0.000033,y[4]=0.954773,y[5]=0.000482,y[6]=0.002039,y[7]=0.005487,y[8]=0.001437,y[9]=0.032645
5
y[0]=0.000000,y[1]=0.988501,y[2]=0.001731,y[3]=0.002239,y[4]=0.000084,y[5]=0.000299,y[6]=0.000035,y[7]=0.004772,y[8]=0.001913,y[9]=0.000426
6
y[0]=0.000004,y[1]=0.000045,y[2]=0.000020,y[3]=0.000144,y[4]=0.974587,y[5]=0.008694,y[6]=0.000577,y[7]=0.000686,y[8]=0.005344,y[9]=0.009899
7
y[0]=0.000001,y[1]=0.001753,y[2]=0.000099,y[3]=0.005684,y[4]=0.019845,y[5]=0.002439,y[6]=0.000026,y[7]=0.006572,y[8]=0.013704,y[9]=0.949877
8
y[0]=0.001885,y[1]=0.000035,y[2]=0.005790,y[3]=0.000007,y[4]=0.033811,y[5]=0.007377,y[6]=0.949990,y[7]=0.000009,y[8]=0.001003,y[9]=0.000094
9
y[0]=0.000017,y[1]=0.000010,y[2]=0.000091,y[3]=0.000054,y[4]=0.038234,y[5]=0.000249,y[6]=0.000009,y[7]=0.038915,y[8]=0.004120,y[9]=0.918302
(以下、略)
たとえば、最初の画像は、
0
y[0]=0.000084,y[1]=0.000003,y[2]=0.000715,y[3]=0.001259,y[4]=0.000001,y[5]=0.000045,y[6]=0.000000,y[7]=0.997065,y[8]=0.000009,y[9]=0.000818
となっていますので、y[7] の確率が99%以上と認識しています。
つまり、99%以上で数字の「7」と判断しているとみることが出来ます。
念の為、最初の画像データとラベル情報を確認してみると、
% mk-mnistbmp ../test.image ../test.label 0 > 0.bmp
[7]
File=2406[Byte] (Head=54/Data=2352)
> X=28*3+0
> Y=28
となっていて、確かにラベル情報は 7 でした。
画像も、7 を描いていました。
BLOGでは、BMP形式のファイルがUPLOADできないので、
JPEGに変換してUPLOADしてみます。
% bmptoppm 0.bmp > 0.ppm
bmptoppm: Windows BMP, 28x28x24
bmptoppm: WRITING PPM IMAGE
% ppmtojpeg 0.ppm > 0.jpg
とりあえず推論はできているみたいなので、
スクリプトを少し修正して、「画像の通し番号」と「正解ラベル」と「推論結果」
を並べて表示してみます。 あと、ついでに推論が間違ったときにわかるような
目印もつけてみます。
修正部分ですが、こんな感じです。
# 推論の実行
y=predict(x,W1,b1,W2,b2,W3,b3)
p=argmax(y)
print("I=%04d L=%d P=%d %s\n",idx,a_lbl[idx],p,a_lbl[idx]==p?"":"*** NG ***")
実行してみます。(出力長いので、最初の10個だけ)
% tt forward-test
I=0000 L=7 P=7
I=0001 L=2 P=2
I=0002 L=1 P=1
I=0003 L=0 P=0
I=0004 L=4 P=4
I=0005 L=1 P=1
I=0006 L=4 P=4
I=0007 L=9 P=9
I=0008 L=5 P=6 *** NG ***
I=0009 L=9 P=9
数字は、左から「通し番号」「正解ラベル」「推論結果」です。
最初の10個をみた感じ、8番目以外はうまく推論できているみたいです。
ちょっと気になるので、8番目の画像を見てみます。
% mk-mnistbmp ../test.image ../test.label 8 > 8.bmp
[5]
File=2406[Byte] (Head=54/Data=2352)
> X=28*3+0
> Y=28
% bmptoppm 8.bmp > 8.ppm
bmptoppm: Windows BMP, 28x28x24
bmptoppm: WRITING PPM IMAGE
% ppmtojpeg 8.ppm > 8.jpg
正解ラベルは 5 ですが、推論では 6 と出しています。
実際に手書き画像をみてみると、確かに汚い字ですね。(笑)
無理して見ると 6 に見えなくもないですが、やっぱり 5 ですね。
さらに、先頭から100枚目までの認識状態を確認すると、
% tt forward-test | grep NG
I=0008 L=5 P=6 *** NG ***
I=0033 L=4 P=6 *** NG ***
I=0066 L=6 P=2 *** NG ***
I=0092 L=9 P=4 *** NG ***
(以下略)
と、8番目の他に、33番目、66番目、92番目の画像も間違えていました。
これらの画像も見てみます。その前に、画像変換がめんどくさいので、
alias bmp2jpg='bmptoppm | ppmtojpeg'
といったエイリアスを作成してみました。
% mk-mnistbmp ../test.image ../test.label 33 | bmp2jpg > 33.jpg
% mk-mnistbmp ../test.image ../test.label 66 | bmp2jpg > 66.jpg
% mk-mnistbmp ../test.image ../test.label 92 | bmp2jpg > 92.jpg
みてみたら、なんですか33番の字は!
正解ラベルを見たら 4 とのことですが、記号にしか見えませんよ!(笑)
66番は 6 とのことで、これは認識して欲しい字ですね!
推論結果が 2 というのは、ちょっと???な感じです。
あと 92 番は 9 とのことで、これも認識して欲しいところですが、
推論結果が 4 とのこと。何か、わかるような気がします。(笑)
最後に、全画像データ(1000枚)の認識率を出したいと思います。
スクリプトの修正箇所は、このあたりです。
n_ok=0
n_ng=0
loop( idx<size(a_lbl) ){ # 全てのテスト画像について ( 0,1,2, ... , 999 )
# 入力データの設定と正規化 ( 0-255 -> 0.0-1.0 )
loop( i<28*28 ){ x[i]=a_img[idx][i]/255.0 }
# 推論の実行
y=predict(x,W1,b1,W2,b2,W3,b3)
p=argmax(y)
if( a_lbl[idx]==p ){ n_ok++ }else{ n_ng++ }
print("I=%04d L=%d P=%d %s\n",idx,a_lbl[idx],p,a_lbl[idx]==p?"":"*** NG ***"
}
print("Total=%d OK=%d NG=%d Accuracy=%.2f[%%]\n",idx,n_ok,n_ng,n_ok*100.0/idx)
早速、実行してみます。(結果がずらずらと表示されるので、log ファイルに
リダイレクトして実行します。)
% tt forward-test >& log
先頭を確認すると、こんな感じでした。
% head log
I=0000 L=7 P=7
I=0001 L=2 P=2
I=0002 L=1 P=1
I=0003 L=0 P=0
I=0004 L=4 P=4
I=0005 L=1 P=1
I=0006 L=4 P=4
I=0007 L=9 P=9
I=0008 L=5 P=6 *** NG ***
I=0009 L=9 P=9
末尾を確認すると、こんな感じでした。
% tail log
I=9991 L=8 P=8
I=9992 L=9 P=9
I=9993 L=0 P=0
I=9994 L=1 P=1
I=9995 L=2 P=2
I=9996 L=3 P=3
I=9997 L=4 P=4
I=9998 L=5 P=5
I=9999 L=6 P=6
Total=10000 OK=9352 NG=648 Accuracy=93.52[%]
最終的な認識率は、93.52[%]だったようです。
とりあえず、ここまで。