- 投稿日:2021-01-03T13:30:34+09:00
Kaggle / MNIST で予測精度向上を目指す ((1) チュートリアル通りにCNN を作る)
Kaggle / MNIST で予測精度向上を目指す ((1) チュートリアル通りにCNN を作る)
要約
- TensorFlow の CNN のチュートリアル 通りに CNN を作成
- 予測精度は 0.98792 となり,Kaggle / MNIST をサポートベクターマシンで頑張る の結果の 0.98375 をあっさり越えた
はじめに
Kaggle の Digit Recognizer というコンペティションは,MNIST という有名な手書き数字の画像を使って学習・予測するタスクである。ここでは学習に畳み込みニューラルネットワーク (Convolutional Neural Network, CNN) を使って,予測精度向上を目指す。
MNIST 向けの CNN の事例はネットなどで数多く見つけることができるが,ネットワーク構造やパラメータの選択理由がよく分からなかった。そこで,私自身がシンプルな CNN からスタートし,予測精度向上のために何を考えてネットワーク構造やパラメータを変えていったのかを書き残すことで,私自身の考えの振り返りと,他の方にとって多少の参考になれば幸いである。
もし誤りや勘違いなどあれば,指摘してもらえるとありがたいです。
対象読者
- CNN の基本事項 (CNN の畳み込み計算や,max pooling,batch normalization など) を一応知っている方
基本の CNN
データの準備
Kaggle で用意されたデータを読み込んで,学習用に整形していく。ポイントは…
- CSV ファイルを
pandas.DataFrame
で読み込み,TensorFlow で処理するためにそれをnumpy.ndarray
に変換する- 数字の範囲を 0 ~ 1 に変換するために,255.0 で割る
digit-recognition_CNN1a.py# This Python 3 environment comes with many helpful analytics libraries installed # It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python # For example, here's several helpful packages to load import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv) # Input data files are available in the read-only "../input/" directory # For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory import os for dirname, _, filenames in os.walk('/kaggle/input'): for filename in filenames: print(os.path.join(dirname, filename)) # You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using "Save & Run All" # You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session # データ読み込み train_data = pd.read_csv("/kaggle/input/digit-recognizer/train.csv") test_data = pd.read_csv("/kaggle/input/digit-recognizer/test.csv") # データ数を確認 train_data_len = len(train_data) test_data_len = len(test_data) print("Length of train_data ; {}".format(train_data_len)) print("Length of test_data ; {}".format(test_data_len)) # Length of train_data ; 42000 # Length of test_data ; 28000 # ラベルとデータを分離 train_data_y = train_data["label"] train_data_x = train_data.drop(columns="label") # TensorFlow で処理するため,panda.DataFrame を numpy.ndarray に変換する # 意図的にデータ型を float64 に変換する train_data_x = train_data_x.astype('float64').values.reshape((train_data_len, 28, 28, 1)) test_data = test_data.astype('float64').values.reshape((test_data_len, 28, 28, 1)) # データを 0 ~ 1 の範囲にする train_data_x /= 255.0 test_data /= 255.0CNN を作る
CNN は TensorFlow の CNN のチュートリアル をそのまま活用する。
digit-recognition_CNN1a.pyimport tensorflow as tf from tensorflow.keras import layers, models model = models.Sequential() model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1))) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.Flatten()) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(10, activation='softmax')) model.summary()できあがった CNN は下記の通り。
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 26, 26, 32) 320 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 13, 13, 32) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 11, 11, 64) 18496 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 3, 3, 64) 36928 _________________________________________________________________ flatten (Flatten) (None, 576) 0 _________________________________________________________________ dense (Dense) (None, 64) 36928 _________________________________________________________________ dense_1 (Dense) (None, 10) 650 ================================================================= Total params: 93,322 Trainable params: 93,322 Non-trainable params: 0 _________________________________________________________________コンパイルして学習を実行する
引き続き TensorFlow のチュートリアル の通りに,できたモデルをコンパイルして,学習を実行する。
digit-recognition_CNN1a.pymodel.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(train_data_x, train_data_y, epochs=5)ちなみに,ここではラベルの one-hot encoding は行っていない。この場合,コンパイル時のオプションは
loss='sparse_categorical_crossentropy'
を指定する。もし one-hot encoding する場合は,
loss='categorical_crossentropy'
を指定する。(参考 ; 目的関数の利用方法)予測と結果保存
学習したモデルを使って,テストデータの予測をして,結果を保存する。
tensorflow.keras.models.predict_classes
を使って,予測結果のラベルを取得する。もし各ラベルの確率を知りたいなら,
tensorflow.keras.models.predict_proba
を使う。得られた結果から
pandas.DataFrame
を作って,CSV ファイルで保存する。digit-recognition_CNN1a.pyprediction = model.predict_classes(test_data, verbose=0) output = pd.DataFrame({"ImageId" : np.arange(1, 28000+1), "Label":prediction}) output.to_csv('digit_recognizer_CNN1a.csv', index=False) print("Your submission was successfully saved!")結果
No 説明 スコア Ref SVM 0.98375 01 チュートリアル通り 0.98792 前回,Kaggle / MNIST をサポートベクターマシンで頑張る の結果は 0.98375 だったが,それをあっさり越えてきた。さすが CNN。
今後,このスクリプトをベースにして,予測精度向上を目指す。
参考
web site
サンプルスクリプト
- digit-recognition_CNN1a.py ; この記事で紹介したスクリプトです
- 投稿日:2021-01-03T13:30:34+09:00
Kaggle / MNIST で予測精度向上を目指す (1. チュートリアル通りにCNN を作る)
要約
- TensorFlow の CNN のチュートリアル 通りに CNN を作成
- 予測精度は 0.98792 となり,Kaggle / MNIST をサポートベクターマシンで頑張る の結果の 0.98375 をあっさり越えた
はじめに
Kaggle の Digit Recognizer というコンペティションは,MNIST という有名な手書き数字の画像を使って学習・予測するタスクである。ここでは学習に畳み込みニューラルネットワーク (Convolutional Neural Network, CNN) を使って,予測精度向上を目指す。
MNIST 向けの CNN の事例はネットなどで数多く見つけることができるが,ネットワーク構造やパラメータの選択理由がよく分からなかった。そこで,私自身がシンプルな CNN からスタートし,予測精度向上のために何を考えてネットワーク構造やパラメータを変えていったのかを書き残していく。「おっ!」という凄いことは書いていないけど,私自身の考えの振り返りと,他の方にとって多少の参考になれば幸いである。
もし誤りや勘違いなどあれば,指摘してもらえるとありがたいです。
対象読者
- CNN の基本事項 (CNN の畳み込み計算や,max pooling,batch normalization など) を一応知っている方
基本の CNN
データの準備
Kaggle で用意されたデータを読み込んで,学習用に整形していく。ポイントは…
- CSV ファイルを
pandas.DataFrame
で読み込み,TensorFlow で処理するためにそれをnumpy.ndarray
に変換する- 数字の範囲を 0 ~ 1 に変換するために,255.0 で割る
digit-recognition_CNN1a.py# This Python 3 environment comes with many helpful analytics libraries installed # It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python # For example, here's several helpful packages to load import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv) # Input data files are available in the read-only "../input/" directory # For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory import os for dirname, _, filenames in os.walk('/kaggle/input'): for filename in filenames: print(os.path.join(dirname, filename)) # You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using "Save & Run All" # You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session # データ読み込み train_data = pd.read_csv("/kaggle/input/digit-recognizer/train.csv") test_data = pd.read_csv("/kaggle/input/digit-recognizer/test.csv") # データ数を確認 train_data_len = len(train_data) test_data_len = len(test_data) print("Length of train_data ; {}".format(train_data_len)) print("Length of test_data ; {}".format(test_data_len)) # Length of train_data ; 42000 # Length of test_data ; 28000 # ラベルとデータを分離 train_data_y = train_data["label"] train_data_x = train_data.drop(columns="label") # TensorFlow で処理するため,panda.DataFrame を numpy.ndarray に変換する # 意図的にデータ型を float64 に変換する train_data_x = train_data_x.astype('float64').values.reshape((train_data_len, 28, 28, 1)) test_data = test_data.astype('float64').values.reshape((test_data_len, 28, 28, 1)) # データを 0 ~ 1 の範囲にする train_data_x /= 255.0 test_data /= 255.0CNN を作る
CNN は TensorFlow の CNN のチュートリアル をそのまま活用する。
digit-recognition_CNN1a.pyimport tensorflow as tf from tensorflow.keras import layers, models model = models.Sequential() model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1))) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.Flatten()) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(10, activation='softmax')) model.summary()できあがった CNN は下記の通り。
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 26, 26, 32) 320 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 13, 13, 32) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 11, 11, 64) 18496 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 3, 3, 64) 36928 _________________________________________________________________ flatten (Flatten) (None, 576) 0 _________________________________________________________________ dense (Dense) (None, 64) 36928 _________________________________________________________________ dense_1 (Dense) (None, 10) 650 ================================================================= Total params: 93,322 Trainable params: 93,322 Non-trainable params: 0 _________________________________________________________________コンパイルして学習を実行する
引き続き TensorFlow のチュートリアル の通りに,できたモデルをコンパイルして,学習を実行する。
digit-recognition_CNN1a.pymodel.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(train_data_x, train_data_y, epochs=5)ちなみに,ここではラベルの one-hot encoding は行っていない。この場合,コンパイル時のオプションは
loss='sparse_categorical_crossentropy'
を指定する。もし one-hot encoding する場合は,
loss='categorical_crossentropy'
を指定する。(参考 ; 目的関数の利用方法)予測と結果保存
学習したモデルを使って,テストデータの予測をして,結果を保存する。
tensorflow.keras.models.predict_classes
を使って,予測結果のラベルを取得する。もし各ラベルの確率を知りたいなら,
tensorflow.keras.models.predict_proba
を使う。得られた結果から
pandas.DataFrame
を作って,CSV ファイルで保存する。digit-recognition_CNN1a.pyprediction = model.predict_classes(test_data, verbose=0) output = pd.DataFrame({"ImageId" : np.arange(1, 28000+1), "Label":prediction}) output.to_csv('digit_recognizer_CNN1a.csv', index=False) print("Your submission was successfully saved!")結果
No 説明 スコア Ref SVM 0.98375 01 チュートリアル通り 0.98792 前回,Kaggle / MNIST をサポートベクターマシンで頑張る の結果は 0.98375 だったが,それをあっさり越えてきた。さすが CNN。
今後,このスクリプトをベースにして,予測精度向上を目指す。
参考
web site
- Kaggle / Digit Recognizer
- TensorFlow の CNN のチュートリアル
- Kaggle / MNIST で予測精度向上を目指す (2. フィルタサイズを変える) ; 次の記事です
サンプルスクリプト
- digit-recognition_CNN1a.py ; この記事で紹介したスクリプトです