手書き文字のMnistデータセットをPythonで分類して使い方を理解していこう!

目次
ウマたん当サイト【スタビジ】の本記事では、Mnistという手書き文字のデータセットをPythonで分類してどのように扱っていけばよいか見ていきます。Mnistはディープラーニングとはじめとした手法の分類精度を比較するのによく使われるんです。
こんにちは!
データサイエンティストのウマたん(@statistics1012)です。
データサイエンスの世界では最終的には実データを使っていくことになりますが、手法を簡易的に実装してみたり手法の精度を比較する上で既存のデータセットが存在します。
そんな既存のデータセットの中でもディープラーニングの画像分類精度を測る上で非常によく使われるデータセットがMnist。
ロボたん既存のデータセットを使って意味あるのー?
ウマたん実データはしっかりデータ整形されていないことが多いから、実装してみるだけだったら既存のデータセットを使った方がよいよ
データセットは色んなタイプがありますが、Mnistの扱い方を知っておくことは非常に重要です。
ということで、この記事ではMnistというデータセットについて見ていきたいと思います。
Mnistデータとは?
まずは、Mnistデータとは何か見ていきましょう!
MnistはMixed National Institute of Standards and Technology databaseの略で、手書き数字画像60,000枚とテスト画像10,000枚を集めた、画像データセット。
0~9の手書き数字が教師ラベルとして各画像に与えられています。
つまりデータセットの構造は以下のようになっています。
ロボたん1つの画像はどのようなデータとして入っているの?
ウマたん1つ1つの画像は28×28のピクセル単位で格納されているんだ!
1つ1つの画像は、文字画像をタテヨコ28×28のピクセルに分け、1つのピクセルあたり0~255の数値で白黒のスケールを表します。
非常に扱いやすくて、データセットとしての完成度が高いので多くの論文やカリキュラムで取り上げられるデータセットです。
画像分類問題に取り組むのであればまずはMnistを使ってディープラーニングを実装してみるのが良いと思います。
画像認識に関しては以下の記事で詳しく取り上げているのであわせてチェックしてみてください。
【サンプルコード付き】画像認識をPython×機械学習で実装していこう!本記事では、画像認識についてPythonでプログラムを実装しながら簡単に解説していきます。画像認識の領域はディープラーニングの発展とともに盛り上がり、今でも様々な研究が盛んです。そんな画像認識の領域についてサンプルコードを参考にしながらPythonで実装していきましょう!
PythonでMnistデータを使って分類精度を比較
そんなMnistデータを使ってPythonで分類を行っていきましょう!
比較する手法は以下の4つ!
CNN(畳み込みニューラルネットワーク)
ディープラーニングに畳み込み層を組みあわせた画像分類には定番の手法です。
まずは、必要なライブラリをインストールしていきます!
import numpy as np
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow import keras
from tensorflow.keras.layers import Dense, Activation
from tensorflow.keras.models import Sequential
from tensorflow.keras.utils import to_categorical
tensorflowなどのライブラリはあらかじめpip installしておいてくださいね!
続いてMnistのデータを学習データとテストデータに分けます。そしてさらに学習データからパラメータチューニングのための検証データを取り出します。
# Kerasに付属の手書き数字画像データをダウンロード
np.random.seed(0)
(X_train_base, labels_train_base), (X_test, labels_test) = mnist.load_data()
# Training set を学習データ(X_train, labels_train)と検証データ(X_validation, labels_validation)に8:2で分割する
X_train,X_validation,labels_train,labels_validation = train_test_split(X_train_base,labels_train_base,test_size = 0.2)
この時画像データは、描画がしやすいように28×28の行列になっているのですが、学習するために1×784に直しましょう!さらに0~255のスケールを正規化しましょう!
# 各画像は行列なので1次元に変換→X_train,X_validation,X_testを上書き
X_train = X_train.reshape(-1,784)
X_validation = X_validation.reshape(-1,784)
X_test = X_test.reshape(-1,784)
#正規化
X_train = X_train.astype('float32')
X_validation = X_validation.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_validation /= 255
X_test /= 255
続いてラベルをダミー変数化します。
# labels_train, labels_validation, labels_test をダミー変数化して y_train, y_validation, y_test に格納する
y_train = to_categorical(labels_train)
y_validation = to_categorical(labels_validation)
y_test = to_categorical(labels_test)
ここでデータの成型が終了したので、ディープラーニングのネットワーク構築に入ります。
隠れ層では、RELU(ランプ)関数を用いて出力層ではソフトマックス関数を用いています。
Model.addを使うことで隠れ層をいくつも積み重ねることが可能です。
# パラメータの設定
n_features = 784
n_hidden = 100
bias_init = 0.1
# 学習率
rate = 0.01
# Sequentialクラスを使ってモデルを準備する
model = Sequential()
# 隠れ層を追加
model.add(Dense(n_hidden,activation='relu',input_shape=(n_features,)))
model.add(Dense(n_hidden,activation='relu'))
model.add(Dense(n_hidden,activation='relu'))
# 出力層を追加
model.add(Dense(10,activation='softmax'))
ネットワークの構築が終了した後は、最適な重みを見つけていきます。AdamOptimizerは最近よく使われている最適化手法です。
Early stoppingとはもう精度が改善しないようなら学習を止めてしまう条件です。これによってムダな学習を省くことが可能です。最後のvalidation_dataで過学習が起こらないように検証を行っています。
# TensorFlowのモデルを構築
model.compile(optimizer=tf.train.AdamOptimizer(rate),
loss='categorical_crossentropy', metrics=['mae', 'accuracy'])
# Early stoppingを適用してフィッティング
log = model.fit(X_train, y_train, epochs=3000, batch_size=100, verbose=True,
callbacks=[keras.callbacks.EarlyStopping(monitor='val_loss',
min_delta=0, patience=10,
verbose=1)],
validation_data=(X_validation, y_validation))
最後にテストデータで予測を実行して実測値と予測値の正解率を求めます!
# Test dataで予測を実行。
pred_test = model.predict_classes(X_test)
validation = (pred_test == labels_test)
size = validation.size
size
correct = np.count_nonzero(validation)
print(f"{correct}/{size} correct ({correct*100/size:.3f}%)")
最終的な結果は・・・・96.96%!!
そこそこな精度をたたき出すことができました。パラメータをいじることで精度を99%まで伸ばしてみてください!
最後にまとめてコードを載せておきます。
import numpy as np
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow import keras
from tensorflow.keras.layers import Dense, Activation
from tensorflow.keras.models import Sequential
from tensorflow.keras.utils import to_categorical
# Kerasに付属の手書き数字画像データをダウンロード
np.random.seed(0)
(X_train_base, labels_train_base), (X_test, labels_test) = mnist.load_data()
# Training set を学習データ(X_train, labels_train)と検証データ(X_validation, labels_validation)に8:2で分割する
X_train,X_validation,labels_train,labels_validation = train_test_split(X_train_base,labels_train_base,test_size = 0.2)
# 各画像は行列なので1次元に変換→X_train,X_validation,X_testを上書き
X_train = X_train.reshape(-1,784)
X_validation = X_validation.reshape(-1,784)
X_test = X_test.reshape(-1,784)
#正規化
X_train = X_train.astype('float32')
X_validation = X_validation.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_validation /= 255
X_test /= 255
# labels_train, labels_validation, labels_test をダミー変数化して y_train, y_validation, y_test に格納する
y_train = to_categorical(labels_train)
y_validation = to_categorical(labels_validation)
y_test = to_categorical(labels_test)
# パラメータの設定
n_features = 784
n_hidden = 100
bias_init = 0.1
# 学習率
rate = 0.01
# Sequentialクラスを使ってモデルを準備する
model = Sequential()
# 隠れ層を追加
model.add(Dense(n_hidden,activation='relu',input_shape=(n_features,)))
model.add(Dense(n_hidden,activation='relu'))
model.add(Dense(n_hidden,activation='relu'))
# 出力層を追加
model.add(Dense(10,activation='softmax'))
# TensorFlowのモデルを構築
model.compile(optimizer=tf.optimizers.Adam(rate),
loss='categorical_crossentropy', metrics=['mae', 'accuracy'])
# Early stoppingを適用してフィッティング
log = model.fit(X_train, y_train, epochs=3000, batch_size=100, verbose=True,
callbacks=[keras.callbacks.EarlyStopping(monitor='val_loss',
min_delta=0, patience=10,
verbose=1)],
validation_data=(X_validation, y_validation))
# Test dataで予測を実行。
pred_test = model.predict_classes(X_test)
validation = (pred_test == labels_test)
size = validation.size
size
correct = np.count_nonzero(validation)
print(f"{correct}/{size} correct ({correct*100/size:.3f}%)")
CNNに関しては以下の記事で詳しくまとめていますのでチェックしてみてください!
畳み込みニューラルネットワーク(CNN)をわかりやすく解説!Pythonで画像認識を実装してみよう!当サイト【スタビジ】の本記事では、ディープラーニングのド定番である畳み込みニューラルネットワーク(CNN)についてわかりやすく解説します。CNNの仕組みを解説した後にPythonにて画像認識タスクを解いていきますよ!
Xgboost
アンサンブル学習と決定木を組み合わせた手法で非常に高い汎化能力を誇ります。
Xgboostでは、アンサンブル学習の中でもブースティングを用いています。
バギングは並列学習なのですが、ブースティングは直列で学習していくイメージです。
前期に上手く学習できなかったら誤差を目的変数にして次の学習を行います。

コードをみていきましょう!
import xgboost as xgb
import pandas as pd
import numpy as np
from tensorflow.keras.datasets import mnist
from sklearn.model_selection import train_test_split
# Kerasに付属の手書き数字画像データをダウンロード
np.random.seed(0)
(X_train_base, labels_train_base), (X_test, labels_test) = mnist.load_data()
# Training set を学習データ(X_train, labels_train)と検証データ(X_validation, labels_validation)に8:2で分割する
X_train,X_validation,labels_train,labels_validation = train_test_split(X_train_base,labels_train_base,test_size = 0.2)
# 各画像は行列なので1次元に変換→X_train,X_validation,X_testを上書き
X_train = X_train.reshape(-1,784)
X_validation = X_validation.reshape(-1,784)
X_test = X_test.reshape(-1,784)
#正規化
X_train = X_train.astype('float32')
X_validation = X_validation.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_validation /= 255
X_test /= 255
# 訓練・テストデータの設定
train_data = xgb.DMatrix(X_train, label=labels_train)
eval_data = xgb.DMatrix(X_validation, label=labels_validation)
X_data = xgb.DMatrix(X_test, label=labels_test)
#経過時間計測
import time
start = time.time()
xgb_params = {
# 多値分類問題
'objective':'multi:softmax',
# クラス数
'num_class': 10,
# 学習用の指標 (Multiclass logloss)
'eval_metric': 'mlogloss',
}
evals = [(train_data, 'train'), (eval_data, 'eval')]
gbm = xgb.train(
xgb_params,
train_data,
num_boost_round=100,
early_stopping_rounds=10,
evals=evals,
)
preds = gbm.predict(X_data)
from sklearn.metrics import accuracy_score
print('accuracy_score:{}'.format(accuracy_score(labels_test, preds)))
#経過時間
print('elapsed_timetime:{}'.format(time.time()-start))
精度・・0.976!!非常に高い!
以下の記事で詳しくまとめています!
【わかりやすく解説】XGboostとは?理論とPythonとRでの実践方法!当ブログ【スタビジ】の本記事では、機械学習手法の中でも非常に有用で様々なコンペで良く用いられるXgboostについてまとめていきたいと思います。最後にはRで他の機械学習手法と精度比較を行っているのでぜひ参考にしてみてください。
LightGBM
続いてXgboostを改良した手法として発表されたLightGBM。
データコンペでもよく使われる手法です。
Xgboostを含む通常の決定木モデルは以下のように階層をあわせて学習していきます。
それをLevel-wiseと呼びます。

(引用元:Light GBM公式リファレンス)
一方Light GBMは以下のように葉ごとの学習を行います。これをleaf-wise法と呼びます。

(引用元:Light GBM公式リファレンス)
これにより、ムダな学習をしなくても済むためより効率的に学習を進めることができます。
Light GBMの解到達スピードが速いゆえんはここにあるのです。
では実装していきましょう!
import lightgbm as lgb
import pandas as pd
import numpy as np
from tensorflow.keras.datasets import mnist
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# Kerasに付属の手書き数字画像データをダウンロード
np.random.seed(0)
(X_train, labels_train), (X_test, labels_test) = mnist.load_data()
# 各画像は行列なので1次元に変換→X_train,X_validation,X_testを上書き
X_train = X_train.reshape(-1,784)
X_test = X_test.reshape(-1,784)
#正規化
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
# 訓練・テストデータの設定
train_data = lgb.Dataset(X_train, label=labels_train)
eval_data = lgb.Dataset(X_test, label=labels_test, reference= train_data)
params = {
'task': 'train',
'boosting_type': 'gbdt',
'objective': 'multiclass',
'num_class': 10,
'verbose': 5,
}
gbm = lgb.train(
params,
train_data,
valid_sets=eval_data,
num_boost_round=50,
)
preds = gbm.predict(X_test)
preds
y_pred = []
for x in preds:
y_pred.append(np.argmax(x))
accuracy_score(labels_test, y_pred)
結果的に0.972という推定精度が得られました!
結果はXgboostに負けていますが、処理時間ではXgboostの8分の1ほどで終了しています。
LightGBMに関しては以下の記事で詳しくまとめています!
【図解で解説】LightGBMの仕組みとPythonでの実装を見ていこう!当サイト【スタビジ】の本記事では、最強の機械学習手法「LightGBM」についてまとめていきます。LightGBM の特徴とPythonにおける回帰タスクと分類タスクの実装をしていきます。LightGBMは決定木と勾配ブースティングを組み合わせた手法で、Xgboostよりも計算負荷が軽い手法であり非常によく使われています。
Catboost
Catboostは、「Category Boosting」の略であり2017年にYandex社から発表された機械学習ライブラリ。
発表時期としてはLightGBMよりも若干後になっています。
ポイントは2つ。
まあ、要はデータセットによるけどXgboostやLightGBMよりも精度が高くなる可能性があるよってことですね。
では、実装していきましょう!
import pandas as pd
import numpy as np
from tensorflow.keras.datasets import mnist
from sklearn.model_selection import train_test_split
# Kerasに付属の手書き数字画像データをダウンロード
np.random.seed(0)
(X_train_base, labels_train_base), (X_test, labels_test) = mnist.load_data()
# Training set を学習データ(X_train, labels_train)と検証データ(X_validation, labels_validation)に8:2で分割する
X_train,X_validation,labels_train,labels_validation = train_test_split(X_train_base,labels_train_base,test_size = 0.2)
# 各画像は行列なので1次元に変換→X_train,X_validation,X_testを上書き
X_train = X_train.reshape(-1,784)
X_validation = X_validation.reshape(-1,784)
X_test = X_test.reshape(-1,784)
#正規化
X_train = X_train.astype('float32')
X_validation = X_validation.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_validation /= 255
X_test /= 255
# 訓練・テストデータの設定
from catboost import Pool
train_pool = Pool(X_train, labels_train)
validate_pool = Pool(X_validation, labels_validation)
#経過時間計測
import time
start = time.time()
from catboost import CatBoostClassifier
params = {
'early_stopping_rounds' : 10,
'iterations' : 100,
'custom_loss' :['Accuracy'],
'random_seed' :42
}
# パラメータを指定した場合は、以下のようにインスタンスに適用させる
model = CatBoostClassifier(**params)
cab = model.fit(train_pool, eval_set=validate_pool)
preds = cab.predict(X_test)
from sklearn.metrics import accuracy_score
print('accuracy_score:{}'.format(accuracy_score(labels_test, preds)))
#経過時間
print('elapsed_timetime:{}'.format(time.time()-start))
推定精度は0.9565!
Catboostについては以下の記事でまとめています!
Catboostとは?XgboostやLightGBMとの違いとPythonでの使い方を見ていこうー!!当サイト【スタビジ】の本記事では、XgboostやLightGBMに代わる新たな勾配ブースティング手法「Catboost」について徹底的に解説していき最終的にPythonにてMnistの分類モデルを構築していきます。LightGBMやディープラーニングとの精度差はいかに!?
結果は・・・以下のようになりました!
| CNN | Xgboost | LightGBM | Catboost |
| 96.96% | 97.60% | 97.20% | 95.65% |
絶妙な差ですが、Xgboostが最も高くCatboostが最も低いという結果に!
ぜひ色んな手法でMnistを分類して精度比較してみてください!
ウマたん自信のある人はパラメータチューニングまで行ってみよう!
Mnistデータまとめ
ここまでご覧いただきありがとうございました!
本記事では、Mnistデータの特徴とPythonでの分類実装を見てきました。
ロボたんMnistデータってこんなに簡単に使えるんだね!
ウマたんこのレベルのデータセットがフリーで使えるのは本当にありがたいよねー!
Mnistの特徴をもう一度まとめておきましょう!
Mnist以外のデータも分析してみたい!という方はデータ分析コンペティションに挑戦してみることをオススメします!
データ分析コンペを開催するサービスといえばKaggleが有名ですが、それ以外にも国産のSignateや、僕が開設したDataDojoなどのデータ分析コンペがあります。
ウマたんどれも無料だからとりあえず登録してどんな分析課題があるかチェックしてみよう!
今回精度比較に用いたディープラーニングをはじめとする機械学習手法やPythonやデータサイエンス全般についての勉強は以下の記事でまとめています。
【初心者向け】ディープラーニングの勉強ロードマップまとめ!当サイト【スタビジ】本記事では、ディープラーニングの学習方法について詳しくまとめていきます!ディープラーニングは難しいと思われがちですが、アルゴリズムは意外とシンプルで実装自体も非常に簡単なんです!Pythonでの実装もおこなっていきますよー!
【5分で分かる】機械学習の独学勉強ロードマップを徹底的にまとめていく!当サイト【スタビジ】の本記事では、機械学習の独学勉強ロードマップについて徹底的にまとめていきます。機械学習をいきなり理論からしっかり勉強しようとすると挫折しかねません。そこで、この記事ではなるべく挫折しないロードマップをお伝えしてきますよ!
【Python独学勉強法】Python入門を3ヶ月で習得できる学習ロードマップ当サイト【スタビジ】の本記事では、過去僕自身がPythonを独学を駆使しながら習得した経験をもとにPythonを効率よく勉強する方法を具体的なコード付き実装例と合わせてまとめていきます。Pythonはできることが幅広いので自分のやりたいことを明確にして勉強法を選ぶことが大事です。
【5分で分かる】データサイエンティストに必要なスキルと独学勉強ロードマップ!当サイト【スタビジ】の本記事では、データサイエンティストに求められるスキルとそれを身に付けるための勉強法について徹底的にまとめていきます!入門者でも、しっかりデータサイエンティストについて理解しある程度独学で駆け出しの状態までいけることを目指します。読んだ内容を、スタアカの「Python基礎」コースで身につける
データサイエンス・AIを、動画と課題で体系的に学べるオンラインスクール。最初のレッスンは無料で見られます。



