20210427のTensorFlowに関する記事は1件です。

黙々とMNISTを見るPython(CNN)

上記のCNN版です。黙々とやります。 CNNとMLPとの違いは入力ベクトルの次元です。チャネルの概念を持つため深くなっています。他は大体同じようにコーディングできます。学習にかかる時間が大幅に長くなりますが予測精度は上がりました。 今回はランダムシードを固定しています。 import tensorflow as tf tf.__version__ '2.5.0-rc1' tf.set_random_seed = 42 準備と前処理 import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Activation, Dense, Dropout from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten from tensorflow.keras.utils import to_categorical, plot_model from tensorflow.keras.datasets import mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() ラベルYを2進数表記にする(one-hot vector) y_train = to_categorical(y_train) y_test = to_categorical(y_test) データXの次元を拡張する グレースケールの画像なので1チャネルあればOK。 x_train = np.reshape(x_train, [-1,28,28,1]) x_test = np.reshape(x_test, [-1,28,28,1]) データXを0から1のfloatにする (normalization) x_train = x_train.astype('float32')/255 x_test = x_test.astype('float32')/255 CNNモデルの構築 input_shape = (28,28,1) batch_size = 128 kernel_size = 3 pool_size = 2 filters = 64 dropout = 0.2 model = Sequential() model.add(Conv2D(filters=filters, kernel_size=kernel_size, activation='relu', input_shape=input_shape)) model.add(MaxPooling2D(pool_size)) model.add(Conv2D(filters=filters, kernel_size=kernel_size, activation='relu')) model.add(MaxPooling2D(pool_size)) model.add(Conv2D(filters=filters, kernel_size=kernel_size, activation='relu')) model.add(Flatten()) model.add(Dropout(dropout)) model.add(Dense(10)) model.add(Activation('softmax')) model.summary() Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 26, 26, 64) 640 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 13, 13, 64) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 11, 11, 64) 36928 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 3, 3, 64) 36928 _________________________________________________________________ flatten (Flatten) (None, 576) 0 _________________________________________________________________ dropout (Dropout) (None, 576) 0 _________________________________________________________________ dense (Dense) (None, 10) 5770 _________________________________________________________________ activation (Activation) (None, 10) 0 ================================================================= Total params: 80,266 Trainable params: 80,266 Non-trainable params: 0 _________________________________________________________________ plot_model(model,show_shapes=True) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(x_train,y_train,epochs=10,batch_size=batch_size) Epoch 1/10 469/469 [==============================] - 133s 278ms/step - loss: 0.5884 - accuracy: 0.8230 Epoch 2/10 469/469 [==============================] - 198s 422ms/step - loss: 0.0708 - accuracy: 0.9780 Epoch 3/10 469/469 [==============================] - 149s 318ms/step - loss: 0.0468 - accuracy: 0.9856 Epoch 4/10 469/469 [==============================] - 130s 277ms/step - loss: 0.0374 - accuracy: 0.9879 Epoch 5/10 469/469 [==============================] - 120s 256ms/step - loss: 0.0318 - accuracy: 0.9895 Epoch 6/10 469/469 [==============================] - 141s 300ms/step - loss: 0.0254 - accuracy: 0.9925 Epoch 7/10 469/469 [==============================] - 125s 267ms/step - loss: 0.0206 - accuracy: 0.9933 Epoch 8/10 469/469 [==============================] - 144s 307ms/step - loss: 0.0193 - accuracy: 0.9936 Epoch 9/10 469/469 [==============================] - 156s 331ms/step - loss: 0.0152 - accuracy: 0.9950 Epoch 10/10 469/469 [==============================] - 148s 315ms/step - loss: 0.0152 - accuracy: 0.9952 _,acc = model.evaluate(x_test,y_test,batch_size=batch_size,verbose=0) acc * 100 99.12999868392944 的中率99.1%の学習済みモデルが作成できた。 予測 model.predict(np.reshape(x_test[1],(1,28,28,1))).argmax() 2 y_test[1].argmax() 2 テストデータの1番目による予測値はラベルと一致しているようです。 from PIL import Image Image.fromarray((np.reshape(x_test[1],(28,28))*255).astype(np.uint8),'L') 肉眼で見ても正しく感じられます。 Confusion Matrix from sklearn import metrics metrics.confusion_matrix(y_test.argmax(axis=1), model.predict(x_test).argmax(axis=1)) array([[ 974, 0, 1, 0, 0, 1, 2, 1, 1, 0], [ 0, 1130, 1, 1, 0, 0, 0, 3, 0, 0], [ 0, 0, 1030, 0, 0, 0, 0, 1, 1, 0], [ 0, 0, 1, 1004, 0, 5, 0, 0, 0, 0], [ 0, 0, 0, 0, 967, 0, 2, 0, 4, 9], [ 0, 0, 1, 4, 0, 886, 1, 0, 0, 0], [ 2, 3, 0, 0, 2, 8, 942, 0, 1, 0], [ 0, 1, 6, 2, 0, 0, 0, 1013, 1, 5], [ 0, 0, 2, 2, 0, 0, 0, 0, 969, 1], [ 1, 0, 0, 0, 2, 4, 1, 0, 3, 998]], dtype=int64) from sympy import Matrix Matrix(metrics.confusion_matrix(y_test.argmax(axis=1), model.predict(x_test).argmax(axis=1))) $$\displaystyle \left[\begin{matrix} 974 & 0 & 1 & 0 & 0 & 1 & 2 & 1 & 1 & 0\\ 0 & 1130 & 1 & 1 & 0 & 0 & 0 & 3 & 0 & 0\\ 0 & 0 & 1030 & 0 & 0 & 0 & 0 & 1 & 1 & 0\\ 0 & 0 & 1 & 1004 & 0 & 5 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 967 & 0 & 2 & 0 & 4 & 9\\ 0 & 0 & 1 & 4 & 0 & 886 & 1 & 0 & 0 & 0\\ 2 & 3 & 0 & 0 & 2 & 8 & 942 & 0 & 1 & 0\\ 0 & 1 & 6 & 2 & 0 & 0 & 0 & 1013 & 1 & 5\\ 0 & 0 & 2 & 2 & 0 & 0 & 0 & 0 & 969 & 1\\ 1 & 0 & 0 & 0 & 2 & 4 & 1 & 0 & 3 & 998 \end{matrix}\right]$$ 誤りの箇所をよく見る fails = [(i,(np.reshape(x_test[i],(28,28))*255).astype(np.uint8),x.argmax(),y.argmax()) for i,(x,y) in enumerate(zip(model.predict(x_test),y_test)) if x.argmax()!=y.argmax()] len(fails) 87 誤っているときの予測値とラベルの組み合わせとその出現数をまとめてみました。 dict(zip(*np.unique([str({'predict':x.argmax(),'label':y.argmax()}) for x,y in zip(model.predict(x_test),y_test) if x.argmax()!=y.argmax()],return_counts=True))) {"{'predict': 0, 'label': 6}": 2, "{'predict': 0, 'label': 9}": 1, "{'predict': 1, 'label': 6}": 3, "{'predict': 1, 'label': 7}": 1, "{'predict': 2, 'label': 0}": 1, "{'predict': 2, 'label': 1}": 1, "{'predict': 2, 'label': 3}": 1, "{'predict': 2, 'label': 5}": 1, "{'predict': 2, 'label': 7}": 6, "{'predict': 2, 'label': 8}": 2, "{'predict': 3, 'label': 1}": 1, "{'predict': 3, 'label': 5}": 4, "{'predict': 3, 'label': 7}": 2, "{'predict': 3, 'label': 8}": 2, "{'predict': 4, 'label': 6}": 2, "{'predict': 4, 'label': 9}": 2, "{'predict': 5, 'label': 0}": 1, "{'predict': 5, 'label': 3}": 5, "{'predict': 5, 'label': 6}": 8, "{'predict': 5, 'label': 9}": 4, "{'predict': 6, 'label': 0}": 2, "{'predict': 6, 'label': 4}": 2, "{'predict': 6, 'label': 5}": 1, "{'predict': 6, 'label': 9}": 1, "{'predict': 7, 'label': 0}": 1, "{'predict': 7, 'label': 1}": 3, "{'predict': 7, 'label': 2}": 1, "{'predict': 8, 'label': 0}": 1, "{'predict': 8, 'label': 2}": 1, "{'predict': 8, 'label': 4}": 4, "{'predict': 8, 'label': 6}": 1, "{'predict': 8, 'label': 7}": 1, "{'predict': 8, 'label': 9}": 3, "{'predict': 9, 'label': 4}": 9, "{'predict': 9, 'label': 7}": 5, "{'predict': 9, 'label': 8}": 1} さいごに、一体どんな画像を読み誤っていたのかを列挙します。 import matplotlib.pyplot as plt plt.figure(figsize=(4,9),dpi=200) for n,(i,img,x,y) in enumerate(fails): plt.subplot(10,9,n+1) plt.title(str(i)+':\npred:'+str(x)+'\nlabel:'+str(y),fontsize=4) plt.imshow(img,cmap='gray') plt.axis('off') plt.show() このデータセットに限って言えば、ざっくりとモデルを作るだけならMLPで充分で、時間はかかっても少しでも精度をあげようという場合にはCNNがよいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む