KaggleのDigit Recognizerで画像分析(Keras編)

今回はDigit Recognizerという入門コンペに参加してみます。

Digit_Recognizer_Pic

これは機械学習用の画像データとしては最も基本的かつよく使われるMNISTデータセットを用いた画像の分類コンテストです。

手書きで数字の0~9が書かれた28×28ピクセルの画像を教師有機械学習で学習させ、その学習器に、テスト用の画像データを読み込ませ、それぞれの画像がどの数字を表しているかを予測させるものです。

なお、Python3.8にアップデートしましたが、Tensorflowが未だ3.8に対応していないようです。

As you can refer from this page Tensorflow is only supported till python 3.7 as of now.

can’t install with python3.8 #33374

Python3.7以前の環境が必要です。消さなくてよかった・・・。

探索的データ解析(EDA:Exploratory Data Analysis)

MNISTのデータフォーマットは理解しているので、簡単に確認して次に進みます。

データの各特徴名とその意味の確認

Digit Recognizer は、MNISTと呼ばれる 0 ~ 9 の手書き文字画像(28 x 28 px)のデータセットを用いて、そのラベル(どの数字が書かれているか)を分類するタスクです。

表の一部分表示(pandasの.head())

0(黒)~255(白)でグレースケールの画像(画像形式は「PGM」)を表しています。

画像で出力してみましょう。

結果は次のようになります。

数字の「4」が現れます。

次に、PBM(2値画像)で出力してみます。

「1」と「0」の数字で「4」を表しています。

データの可視化(snsの.countplot())

画像が4200種類存在し、28×28 pixel(784カラム)+ラベル=785カラム存在しています。

テストデータにはラベル(を推測するため)振られておらず、画像は28000種類です。

データ自体はほぼ均等に用意されているようです。

欠損値の確認

画像データなので欠損値はないと思いますが定石通り確認します。

欠損値はありません。

データの準備(Feature Engineering)

通常であれば、ラベル付けが大変な作業となります。

がMNISTなので、既にラベル付けが完了しています。

各要素の正規化

MNISTデータを加工します。ここでは、28ピクセル×28ピクセルのデータを28×28=784次元のベクトルに変換し、ベクトルの成分を0~1の範囲に正規化します。

ラベルをone hot ベクトルにする

機械学習の特徴量や正解ラベルをone-hotベクトルにするには色々な方法があります。

  • 自分で実装する
  • sklearnのOneHotEncoderを使う
  • pandasのget_dummiesを使う
  • kerasのto_categoricalを使う

今回は、Kerasを使うので「to_categorical」を使ってみます。

番目の引数(num_classes)として、数値を渡すと、データの最大値を指定できます。

結果は次のようになります。

モデル作成

画像処理は2000年代前半まではLinear kernelを用いたsupport vector machineが最も高い精度を出していましたが、2012年以降は、Deep Learningの方が高い精度を出すようになりました。

特に、画像認識・画像分類では「畳込みニューラルネットワーク(Convolutional Neural Network:CNN)」が高い精度を誇るアルゴリズムとしてよく利用されます。

今回は、Kerasを使って「MLP」と「CNN」を使ったディープラーニングの両方を試してみます。

MLP:MultiLayer Perceptronを試す

全結合層のみのもっとも単純なモデルです。

(単純)パーセプトロンを複数繋いで多層構造にしたニューラルネットで、MLP(多層パーセプトロン)と呼ばれます。

おもに音声認識での実用が進められています。

以前作った学習モデルを適用してみます。

Dense()で全結合層を2層追加しています。

計算時間は10分程度です。

では、結果を提出してみます。

スコアは「0.97357」で「Top 70%」となりました。

単にKerasを使っただけなのに、今までの入門コンペの中では一番高いスコアとなりました。

CNN:Convolutional Neural Networkを試す

CNNは、入力層と出力層の中間に位置する「畳み込み層(Convolution Layer)」と「プーリング層(Pooling Layer)」を交互に配置することで、特徴量を抽出し、全結合層で認識するニューラルネットワークのことです。

画像認識の分野で実用化が進んでおり、畳み込みニューラルネットワークと呼ばれます。

「畳み込み層」は、複数の最小データをまとめた特徴量を検出する層です。また「プーリング層」は、入力情報を圧縮する目的で使われる層です。

サンプルコードがあるので、それを見ながら作成してみます。

keras/mnist_cnn.py at master · keras-team/keras · GitHub

畳み込みニューラルネットでは、入力する画像の形状を保つために画像集合を4次元テンソル(4次元配列)で入力するのが一般的です。

なお、Kerasでは、4次元テンソルの各次元の位置がkeras.backend.image_data_format()(バックエンドのエンジン)によって変わります。

  • th(Theano)では(サンプル数, チャネル数, 画像の行数, 画像の列数)
  • tf(TensorFlow)では(サンプル数, 画像の行数, 画像の列数, チャネル数)

MNISTの入力数は白黒画像なのでチャネル数は1です。

学習モデルは次のようになっています(Sequential)。

モデルを図示化すると次のようになります、長い・・・。

知らないモジュールが色々と出てきました。

  • Conv2d: 2次元畳み込み層のモジュール
  • MaxPool2D: 2次元最大プーリング層のモジュール
  • Dropout: ドロップアウトモジュール
  • Flatten: 入力を平滑化するモジュール

また、Adadeltaという最適化アルゴリズムが出てきています。

以前も「最適化手法(optimizer)」紹介しましたが、今回も後学に回します。

[引用] 勾配降下法の最適化アルゴリズムを概観する

Adagrad、Adadelta、RMSprop、Adamは最適で最良の収束するようです。なので、ディープラーニングと同じく今回はAdamを使ってみます。

結果は次のようになります。

計算時間は18分程度です。

では、結果を提出してみます。

スコアは「0.98700」で「Top 50%」となりました。

Functional API で試す

Sequentialではなく、Functional API を使って学習モデルを構築してみます。

結果は次のようになります。

Sequentialと学習モデルが変わってしまいました・・・。

「input_2 (InputLayer)」が追加されてしましましたが、「Input(shape=(28, 28, 1))」以外の書き方が分かりません(誰か教えて下さい)。

ただし精度が上がり、提出するとスコアは「0.98757」で「Top 49%」となりました。

まとめ

今まで参加した入門コンペティションの中では、結果提出までの時間は短かったです。

当初計画していた入門コンペティション参加はこれで終わりとなります。

今後は、入門コンペの精度を高めるか次のステージに進むかは未定です。

ソースコード

GitHub」にも公開しています。

タイトルとURLをコピーしました