ニューラルネットワークを用いた手書き数式画像認識

ネットワークシステム研究室
指導教員:坂本 直志
13EC064 田部井 佑馬

目次

1 はじめに
1.1 本研究の背景
1.2 ニューラルネットワークとは
2 関連研究
3 本研究の目的
4 ニューラルネットによる実験
4.1 実験方法
4.2 手書き数字(MNIST)の学習実験
4.3 手書き風フォントによる数式の学習実験(1)
4.4 手書き風フォントによる数式の学習実験(2)
5 考察
6 付録:ソースコード
参考文献

1 はじめに

1.1本研究の背景

近年, 深層学習(Deep Leaning) が広く知られるようになった. 深層学習を用いた技術として, 特に囲碁におけるAI であるAlpha GO の活躍[1] や, Microsoft 社によって開発されたAI「りんな」[2]は大きな話題となった.

深層学習とは, ニューラルネットワークを用いた機械学習における学習手法の1 つである. 膨大なデータを学習するために多層のニューラルネットワークを構築したものが深層学習である. ライブラリが開発されたことで, ニューラルネットワークによる機械学習は容易になっている. また, タブレットの教育現場への導入, e-Learning の利用など, 教育分野においてコンピュータが使われる場面が多くなった.

そこで本研究では, ニューラルネットワークによる画像認識を用いた手書き数式の正誤判定を取り上げ, ニューラルネットワークによる学習実験を行う. Python のライブラリ“Chainer'”を用いてニューラルネットワークを構築し, 機械学習の基本的な手順を確かめると共に, 機械学習の教育分野への活用について考える.

1.2 ニューラルネットワークとは

本研究で用いるニューラルネットワークについて述べる. ニューラルネットワークとは, 人間の神経細胞(ニューロン)をモデル化した計算素子である, ニューロセルを組み合わせて構成されるネットワークである. ニューロンは, 他のニューロンから信号を受けとり, 他の多数のニューロンに信号を送っている. これをモデル化したものがニューロセル(図1)であり, ニューラルネットワークはこのニューロセルを図2 のように層状に結合させた, 人間の神経構造を模したネットワークである.

ニューロセル
図1 ニューロセル
ニューラルネットのモデル
図2 ニューラルネットのモデル

ニューロセルは, 複数の入力と各入力に対応した重みを持つ. 各入力に対し重みを乗算することで重み付けを行い, それぞれの総和を求める. その総和からしきい値を減算し, 伝達関数で処理した結果を出力とする. この出力は複数の方向に出力でき, 次の層のニューロセルへの入力となる. 伝達関数は, 次の層のニューロセルに値を渡す際に入力された値に適応する関数であり, 学習の効率や内容に影響する.

ニューラルネットワークによる学習について述べる. 学習の際には, 入力として学習・認識したいデータと, ニューラルネットに出力させたい値を示すデータラベルをそれぞれ組にして用意する. そのデータをデータセットと呼ぶ. 学習するデータをニューラルネットに入力すると, 各層のニューロセルによって計算された情報が出力される. 出力された値とデータラベルとの誤差を求め, データラベルの値に近づくように各ニューロセルの重みやしきい値を調整する. この過程を複数の既知のデータを用いて繰り返すことで, 未知のデータに対しても正しい出力を行うようなニューラルネットに調整していく.

2 関連研究

関連研究として, コンピュータによる正誤判定の分野に関連して, 篠田ら[4]による記述式問題の自動採点についての研究と, ニューラルネットワークによる数字認識に関連する藤木ら[5]による研究を紹介する.

篠田らの研究では, eラーニングにおける記述式問題の自動採点について取り上げている. 正解・不正解の判定を必要としているeラーニングにおいては, 選択式や穴埋め式の出題形式が多く見られる. これは記述式問題の正確な採点が難しいことによるものだと考えられる. この研究では回答の文章構造から, 同義語辞書の導入と文章の意味を縮約する2つの手法を用いて文章の意味を評価するシステムを構築している.

文章中に現れる語の意味は, 文脈に依存して変化するが, 限られた出題分野においては肯定的な表現・否定的な表現といったように, 意味情報を考慮できる. 例えば, 数学の回答では「2つの解を持つ」という表現と, 「解が2つある」という表現は, 採点者にとっては同じ意味を持っていると考えられる. このように出題する分野に現れる語に対して, 肯定的もしくは否定的意味を設定した同義語辞書を作成する.

文章中には, 上記の同義語辞書によって意味付けされた語が多く存在する. 採点のためには, あるキーワードに対する文が何を意味しているかを理解する必要がある. 次のような例題を考える.

ここで, 「ある」や「簡単」は肯定的(Positive)表現, 「困難」や「ない」は否定的(Negative)表現とすると, 肯定的な表現の重ね合わせによって, キーワードは肯定される. また, 否定的な表現の重ね合わせは, キーワードを肯定していると解釈される. 一方, 肯定的な表現と否定的な表現の組み合わせは, 順序によらず否定的な表現とされる.

上記の同義語辞書と縮約ルールを適用し, 回答文を分析する. 表1の例文を分析した結果, 図3に示すような木構造になる. このように文章中のキーワードと肯定的・否定的な意味付けによって正誤判定を行うシステムを構築した.

表1 入力する例文
例文1解は存在しない.
例文2上に凸ならば不安定である.
例文3計算は時間がかかるが, 困難ではない.
例文4(2, 3)と(1, 3)に交点を持つ.
分析例(出典:篠田[4], 2007)
図3 分析例(出典:篠田[4], 2007)

藤木らの研究では, 複合型ニューラルネットワークを用いた手書き数字の認識実験を行った. 3層からなるニューラルネットを用いた学習実験を行うが, 中間層のニューロセルの個数をランダムに変化させ, 複数のネットワークに学習を行う. これによって, 初期条件の異なる複数の学習済みネットワークを構築することができる.

これらのネットワークに手書き数字を認識させると, 同じ数字を認識させていても正しく認識できるネットワークと, 誤った認識をしてしまうネットワークが存在する. 誤答の中にも, 例えば3という数字であれば, 5や8という似ている数字に認識することが明らかになった. 藤木らはこのような数字の類似性を示す情報も判断材料として活用できると考え, 複数のネットワークを併用する認識方法を考案した. 初期条件を変えた複数のネットワークを図4のように並列に結合し, 1つの学習済みネットワークとして構築した. そこでは構築した複合型ネットワークについて「小さなネットワークサイズであっても高い能力を持たせることができることが明らかにされた[5]」とあり, ネットワークの構造や学習の方法によって結果が向上されることがわかる.

複合型ネットワークの模式図(出典:藤木[5], 2009)
図4 複合型ネットワークの模式図(出典:藤木[5], 2009)

3 本研究の目的

本研究では, ニューラルネットワークモデルに対し手書きの数式画像を学習させ, 数式の答えの導出や, 解かれた数式の正誤判定を行う. 学習させるのは数式の答えや数式の正誤のみで, 数式に含まれる数や演算子についての情報は持たない. 数や演算子を認識してコンピュータが解くのではなく, 数式を見るだけでその数式の答えや正誤を識別することができるかを実験する.

コンピュータによる正誤判定については, チェックボックスやフォームに入力した情報を判定したり, あるいは枠内に書かれた数字が何かを認識することでその数字が正答と一致しているかを判定したりする方法がある. しかし, 書かれた数式が成立しているかどうか, 正しいかについては人間の目で判断される. ここでは, 数式を数字や演算子に分割することなく, 数式の書かれた画像のみで学習させる. その中で, 学習の効率, 精度について考え, 向上させるための手法を用いながら, 学習の効率・精度を比較していく.

4 ニューラルネットによる実験

ニューラルネットを構築し, 手書き数式の学習を行う. 実験の目標は手書き数式画像の正誤判定であるが, 手書き数字の学習, 数式の解答学習を行い, 手書き数式画像の正誤判定実験に活かす.

実験にはニューラルネットを構築, 学習ができるPython用ライブラリ“Chainer”をPython3.4.3上で用いる. Chainer上のニューラルネットは, ネットワーク構造を表すモデルとニューロセルのパラメタを調整するオプティマイザで構成され, Chainerではニューラルネットの構造(モデル)の定義と, 活性化関数をネットワークの層に割り当て, オプティマイザの最適化手法の定義を行うことでニューラルネットを構築, 容易に学習が可能である. また, モデル・オプティマイザは保存, 読み込みが可能で, 学習済みモデルを保存しておき, 認識の際には復元, 利用することができる.

Chainerで扱えるデータはPythonのnumpy配列であるため, 画像認識においても画像データをnumpy配列に変換して入力する必要がある. 画像データは, 1ピクセル毎の色情報を要素とするnumpy配列に変換する.

なお, Chainerを用いたニューラルネットワークモデル構築, 学習に用いるプログラムに関して, 「【機械学習】ディープラーニング フレームワークChainerを試しながら解説してみる。」から一部引用した. 引用部分は付録[6章]にて示すソースコード内にコメントアウトにて示す.

ニューラルネットによる学習経過の評価として, loss(損失)とaccuracy(正答率)がある. lossはニューラルネットによる出力値と, 教師データの与える正解との誤差を表す. accuracyはニューラルネットによる出力値の正答率を表す. 2値分類の場合を考えると, ニューラルネットによる出力結果は, 教師データの正答に応じて表2のように分類される.

表2 ニューラルネットによる出力結果の分類
出力
教師データ
ab
cd

この4つに分類された中で, どれだけ正答と一致しているかを示すのがaccuracyであり, 以下の式で表される. \[ Accuracy = \frac{a+d}{a+b+c+d} \]

学習においては, テストデータで検証した際のlossを下げることを目標とし, テストデータ時のlossの少ない学習モデルをより良いモデルと評価する.

4.1 実験方法

Pythonを用いた実験方法を示す.

4.1.1 データセットの準備

学習する教師データとそのデータの正解ラベルを組にしたデータセットを読み込む. データセットは学習用とテスト用を用意し, 教師データと正解ラベルは対応付けられるようにする.

4.1.2 ニューラルネットの構築

Chainerを用いて, ニューラルネットのモデル及びニューラルネットのパラメタを調整するオプティマイザを定義する. ネットワークは入力層・中間層・出力層の3層からなり, それぞれの層は全結合のネットワークを構成している. 各層からの出力の個数は, 次の層のニューロセルの個数と一致している必要がある.

4.1.3 ニューラルネットの学習

準備したデータセットと構築したニューラルネットのモデルを用いて学習を行う. ニューラルネットの学習の流れは以下のとおりである.

  1. 教師データを入力層に入力し, 各ニューロセルが計算した値を次の層に渡す. これを出力層が値を出力するまで行う.
  2. 出力層からの出力と教師データのデータラベルの誤差を求める.
  3. 求まった誤差を出力層から入力層に伝播させ, 各ニューロセルがパラメタを更新する.

ここで1.の過程を順伝播と呼び, 3.の過程を誤差の逆伝播と呼ぶ.

順伝播の構造は, ニューロセルの活性化関数を定義することで実装する. 活性化関数は, relu関数とdropout関数を併用している. relu関数はニューラルネットにおいて良い結果が得られるとされる関数であり, 以下の式で定義される. \[ H(x)=max(0,x) \]

Chainerによる学習の概念図を図5に示す.

4.1.4 ニューラルネットによる識別

学習済みニューラルネットモデルを用いた, データの識別実験の手順を示す. 学習したモデルとオプティマイザは, ファイルで保存することができる. 保存したモデルやオプティマイザは, 別のプログラムで復元することで, 学習済みのニューラルネットモデルを利用することができる.

データの識別は, 学習時と同様にニューラルネットにデータを入力する. ニューラルネットからは, データの示す値として考えられるそれぞれの値について, その値である確率が出力される. 例えば, 0~9の画像を識別するのであれば, 入力した画像が0~9である確率がそれぞれ出力される. ここで, ニューラルネットは出力された確率が最も高くなったものを識別の結果とする.

ニューラルネットによる出力を求めた後に, 確率の最も高い値が求まる. これが入力したデータのラベルと一致していれば識別が成功したことになり, そうでなければ識別は失敗となる.

4.2 手書き数字(MNIST)の学習実験

MNISTと呼ばれる手書き数字データセットを用いて, 学習と認識を行う. MNISTは“Mixed National Institute of Standards and Technology database”の略で, 機械学習による画像認識で頻繁に使われるデータセットであり, 7万個の手書きの数字(0~9)にそれぞれ正解ラベルが与えられている. ChainerにはこのMNISTデータを取得するメソッドがあり, numpy配列で手書き数字画像データを得ることができる. このMNISTによる実験を基に, オリジナルのデータセットでの実験を進めていく.

4.2.1 ニューラルネットモデルの構築

画像の学習, 認識に用いるニューラルネットを, 扱うデータに適したものに定義する. 各層のニューロセルの個数, ニューロセルの活性化関数の定義を行う.

入力データになる配列の次元数とニューラルネットの入力層の個数を同じにする必要がある. MNISTで得られるデータは1ピクセル辺り1値のデータで構成されるため, 28*28の画像データでは784次元の配列データが入力となる.

画像データのnumpy配列への変換
図6 画像データのnumpy配列への変換

そのため, ニューラルネットの入力層は784個となる. ニューラルネットの出力層は望む出力の個数で良いため, 0~9の数字の個数である10個となる. 続いて, 中間層のユニット数を定める. 中間層が多くなればその分学習に時間がかかるが, 少なすぎても十分な学習ができないため, ここでは1000個で学習を行わせている.

4.2.2 モデルによる学習

構築したモデルに学習を行う. 学習は画像データとその画像がどの数字であるかを表すラベルをセットにしたデータセットを用いて行われる. また, データセットには学習用データとテスト用データがあり, 学習用データを基にパラメタを更新しつつ, テストデータを認識して正答率を出しながら学習していく.

ニューラルネットによる学習では, 同データによる学習を繰り返し行い, その度にパラメタを更新する. MNISTの学習は単純な手書き数字の学習であり, 学習する特徴量は少ない. そのため, 学習の繰り返し数(epoch数)は20回とする. 識別実験の為に, 繰り返し毎のモデルを保存しておく. 学習の成果を確認する識別では, 保存されたモデルを読み込んで識別を行う. 学習を繰り返すことで学習による精度は向上するが, 回数が多すぎると与えられたデータでのみ精度が向上し, テストがうまくいかなくなる過学習という現象が起きてしまう. 過学習が起きていると, 学習データでのloss値が減少するのに対し, テストデータでのloss値が増加する. そのため, 学習の経過を確認し, 過学習の起きていない繰り返し数のモデルを使用し, 識別を行う.

mnist/train.pyを実行し,ニューラルネットの学習を行う. 各繰り返し毎のモデル及びオプティマイザが保存される. 学習を行った結果を表3に示す. 以下のデータにおけるaccuracyは, そのデータでの正答率を表す.

表3 MNIST学習実験での学習結果
epochtrain losstrain accuracytest losstest accuracy
10.2760.9150.1110.965
20.1360.9580.0870.973
30.1080.9660.0760.976
40.0920.9720.0750.977
50.0840.9730.0660.980
60.0790.9750.0590.982
70.0730.9780.0590.982
80.0660.9790.0600.982
90.0630.9790.0600.982
100.0600.9820.0600.983
110.0600.9810.0660.983
120.0530.9830.0660.983
130.0550.9830.0610.983
140.0490.9850.0600.985
150.0510.9850.0580.985
160.0480.9860.0640.984
170.0490.9850.0570.985
180.0490.9860.0760.983
190.0460.9860.0670.984
200.0460.9860.0630.985

この実行結果から, epoch 17ではテストデータでのloss値が少ない. 17回目のepochでのモデルを用いて認識を行う.

4.2.3 データ識別による正答率確認

学習済みモデルを用いて, 画像データの識別を行う. 識別を行うデータも, テスト時と同様にChainerで得られるMNISTデータセットを用いる. 学習と同じデータを用いているため, 学習時の正答率と同様の値が得られると予想されるが, ここではモデルを用いた識別の方法を確認する.

識別の際には, 学習時に用いたものと同じ構造のニューラルネットモデルを構築する. そのモデルに対して, 保存された学習済みモデルと, パラメタを操作するオプティマイザを読み込み, 割り当てる. これによって, 学習済みモデルを用いた画像の識別を行うことができる. モデルに識別したいデータを入力させると, 出力層ではそのデータがある出力である確率を得ることができる. 例えば今回の実験であれば, データラベルの値が画像データの表す数字であるため, 出力層ではその数字である確率を得ることができる. この確率が最も高い, つまり出力層での値が最も大きいものを識別の結果とする.

mnist/predict.pyを実行して, 画像の識別を行う. 得られたデータからランダムに1000個を取り出して識別させ, 正答率を確認する. 結果を表3に示す.

表4 MNIST学習実験での識別結果
認識結果正答データ
68
09
03
19
68
35
58
56
86
38
86
56
97

誤認識したのは1000個のうち13個で, 正答率は98.7%と高い数値が確認できる. このように, モデルの構築・学習・識別を基本的な流れとして実験を行う.

4.3 手書き風フォントによる数式の学習実験(1)

手書き風フォントを用いた, 数式画像の学習実験を行う. 扱う数式の画像データは, フリーの手書き風フォントを使用し, Javaプログラムで作成する.

ここでは, 1桁の数字同士の足し算の数式を入力し, その答えを出力データとする. 数値や演算記号をそれぞれ認識, 数式を処理するのではなく, 数式を入力して学習させることによって学習が可能かどうかを確かめる. 学習に用いる画像データは単一のフォントでなく複数のフォントを組み合わせて数式を生成し, 画像量を増やしている. テストデータは同じフォントで数式を書いたものを, 全てのフォントに対して生成している.

用意したフォント数は50種類で, これを各数字・記号に対してランダムに割り当て, 100種類の数式画像をそれぞれ0+0から9+9の100枚ずつ生成した. ラベルデータは数式の計算結果とし, 数式を計算した結果を学習し, データ認識では数式の画像データを入力すると計算結果を出力させる.

手書き数式学習実験(1)で用いる画像の例 (1)
図7 手書き数式学習実験(1)で用いる画像の例 (1)
手書き数式学習実験(1)で用いる画像の例 (2)
図8 手書き数式学習実験(1)で用いる画像の例 (2)

4.3.1 ニューラルネットモデルの構築

実験で扱うデータに適するように, ニューラルネットのモデルを構築する. 活性化関数やモデルの基本構造は変わらないが, 入力・出力層の個数を変更する必要がある.

前回と同様, 画像データを1ピクセル毎のnumpy配列に変換してネットワークに入力する. そのため, 今回扱うデータのサイズに合わせたモデルを構築する. 入力データは28*84のサイズであるため, 入力層の個数は28×84=2352個となる. 対して出力は1桁の足し算の結果の個数になるため, あり得る値の0~18である19個を出力層の個数とする.

4.3.2 画像データへの前処理・読み込み

オリジナルのデータセットを扱うに当たって, 学習の効率向上のための処理や, Chainerで扱えるnumpy配列への変換等が必要になる. この前処理と, 画像データの読み込みを, Python上でOpenCVを用いて行う.

画像データに適用する前処理としては, リサイズ・グレースケール化・白黒反転・2値化がある.

リサイズ処理は, ニューラルネットに入力する際のデータ量を統一するものである. 本実験では画像のサイズを統一して生成しているため必要ない処理ではあるが, 今後の実験でも同様の処理を行うため, リサイズを行っている. グレースケール化は, 学習する画像データが数字や演算子であり, 色を問わない画像であるため, 行うことができる処理である. グレースケール化を行うと各ピクセルの情報がRGBの3次元から白黒の1次元になり, 不要な情報量を取り除くことができる.

2値化は, グレースケールで表されている画像を, しきい値を定めて白か黒の2値に変換する処理である. これによって画像の輪郭が明確になり, 学習の効率が向上する. ここでは, しきい値を128とし, 黒白の画素値を0と255の2値に変換している.

続いて, Chainerで扱える配列に変換する. OpenCVで読み込んだ画像はnumpy配列で扱えるため, numpyで与えられるメソッドを用いて入力として望まれる次元に変換することができる. numpy.arrayメソッドは多次元配列に変換するメソッドである. また, reshapeメソッドは要素数を指定して多次元配列の次元数を変換するメソッドである. これらの変換を行った要素を全て255で除算することで, 0と255の2値であった画素値が0と1の2値に変換される. このように情報を0-1に変換することを正規化という.

図9 画像データの配列のイメージ
図9 画像データの配列のイメージ

これらの前処理を行った上で, ニューラルネットによる学習を行う.

4.3.3 モデルによる学習

前述のデータセットを用いて学習を行う. ex1/train_tegaki.pyを実行して学習を行う.

epoch数は100とし, テストデータでのloss値が最も少ない学習済みモデルを優秀なものとして選ぶ. 学習の結果, 繰り返し回数50まででloss値とaccuracy値が収束した. 繰り返し回数50までの結果を表5に示す.

表5 手書き数式学習実験(1)での学習結果
epochtrain losstrain accuracytest losstest accuracy
12.6900.9902.3850.185
22.2290.1832.1280.278
31.8630.2911.7950.421
41.5480.4081.5210.536
51.2070.5441.3230.629
60.9270.6571.1440.707
70.6970.7511.0090.755
80.5100.8220.9450.802
90.3820.8660.9330.817
100.2910.9030.8930.835
110.8730.9220.8730.847
120.2000.9320.8260.854
130.1650.9450.8500.865
140.1360.9570.8540.868
150.1150.9650.8260.878
160.1120.9640.8420.878
170.1230.9590.8050.879
180.1030.9660.8060.888
190.0980.9700.8050.880
200.0830.9760.8340.885
210.0770.9760.8380.892
220.0800.9740.8380.881
230.0830.9720.8790.889
240.0780.9740.8490.887
250.0900.9720.8360.891
260.0840.9730.8850.890
270.0810.9760.8330.894
280.0740.9760.9100.886
290.0820.9750.8430.896
300.0680.9790.8790.895
310.0610.9800.8620.901
320.0730.9770.8620.901
330.0720.9770.8500.899
340.0810.9770.8510.899
350.0670.9800.8700.901
360.0570.9810.8700.902
370.0560.9810.9540.899
380.0580.9820.9090.894
390.0610.9800.9220.894
400.0650.9780.8740.897
410.0870.9740.9390.896
420.0720.9780.9270.898
430.0720.9780.9170.904
440.0800.9780.9390.904
450.0730.9800.9690.903
460.0760.9790.9490.902
470.0590.9820.8770.906
480.0650.9820.9210.905
490.0620.9820.9570.904
500.0720.9800.9760.900

以降の繰り返しでは, loss値とaccuracy値が変動せずに学習が進んだ. テストデータでのloss値が最も少ないモデルはepochが17のものである. よって, 17回目の繰り返しで作られたモデルが最も優秀である.

ここで, MNIST学習実験と比べると, 繰り返しを重ねるにつれてテスト時のloss値が大きく増加している. これは過学習が起きているため, 学習データの学習のみが過多になり, 学習時と異なるデータでの精度が向上しなくなってしまっている. MNIST学習実験で扱ったデータ量が7万枚(うち学習用データが6万, テストデータが1万)であり, 各数字に対して7000枚程度あるのに対し, ここでは学習用データの個数は各式に対して100種類となっている. これによって, 繰り返しによる学習が過多になってしまい, 結果としてテストデータでの精度が上がらなくなってしまう.

4.3.4 データ識別による正答率の確認

テストデータを用いてデータの識別を行う. ex1/predict_tegaki.pyを実行して, 5000個用意したテストデータのうちランダムに1000個を抽出し, 正しい答えが出力されるかを確認する.

識別を行った結果, 正答だったものは1000個のうち878個であった. よって正答率は87.8%であった. MNISTの実験と比べると正答率は低いが, 数式を学習して識別できていることは確認できる.

4.4 手書き風フォントによる数式の学習実験(2)

ここでは, 画像に書かれた手書き数式を判定するための実験を行う. 数式の正誤判定を行うために, 学習する画像データは完結した数式を表し, それが正答であるかどうかをラベルデータとする. 正答のデータには1を, 誤答のデータには0を与え, 出力は0か1の2種である.

誤答として考えられるものには, 数式の形は合っているが答えが誤っているものと, 答えの数しか書かれていいない等で数式として成り立っていないものの2つが考えられる. よって, 誤答のデータの半数は答えが誤っているもの, もう半数は数式が成立していないものをデータセットに用意しておく.

画像データのフォント数は50種類用意し, 正答データは1桁の数字の足し算の全てのパターンを作成, それぞれのフォントについて100枚になる. よって正答の学習データは全5000枚用意する. 誤答のデータは前述した2つの場合についてそれぞれ2500枚ずつ, 全5000枚を用意した. テストデータも学習データと同様に生成したものを利用する. 正答データとして, 1桁の足し算のそれぞれの式について5種類ずつ, 全500枚. 誤答データは2つの誤答パターンで250枚ずつ, 全500枚を用意した.

画像に対する前処理は前実験と同様であり, ニューラルネットモデルは出力層を望む出力の個数に合わせて2つとした.

ex3/train.pyを実行して学習を行う. ここでは, プログラム内の変数n_extendを0とする.

手書き数式学習実験(2)で用いる正答画像の例(1)
図10 手書き数式学習実験(2)で用いる正答画像の例(1)
手書き数式学習実験(2)で用いる正答画像の例(2)
図11 手書き数式学習実験(2)で用いる正答画像の例(2)
手書き数式学習実験(2)で用いる正答画像の例(3)
図12 手書き数式学習実験(2)で用いる正答画像の例(3)

4.4.1 学習の結果

データ量が多く, 一回の繰り返しにかかる時間が長いため, epoch数は50とした. 表6に学習の結果を示す.

表6 手書き数式学習実験(2)での学習結果
epochtrain losstrain accuracytest losstest accuracy
10.5000.7340.4470.798
20.4370.7910.4620.782
30.4000.8180.4630.782
40.3820.8280.4700.800
50.3660.8430.4180.818
60.3490.8510.3810.842
70.3340.8600.4020.834
80.3220.8670.3720.852
90.3080.8720.3700.852
100.2950.8810.4380.861
110.2980.8770.4020.849
120.2760.8890.3980.859
130.2700.8900.3620.870
140.2630.8960.3790.852
150.2510.9000.4270.855
160.2420.9030.3960.857
170.2360.9050.3990.870
180.2280.9080.4150.862
190.2210.9130.4350.854
200.2110.9200.3970.871
210.2070.9190.3880.869
220.2060.9180.3920.868
230.1900.9240.4410.862
240.1980.9190.4060.856
250.1840.9240.4730.867
260.1790.9280.4270.869
270.1750.9280.4830.873
280.1700.9300.4700.875
290.1700.9330.4460.873
300.1580.9360.4490.879
310.1570.9370.5060.874
320.1500.9400.4620.870
330.1490.9400.5330.871
340.1390.9450.5300.871
350.1400.9440.5380.876
360.1310.9450.4920.869
370.1330.9480.5210.880
380.1310.9480.5010.873
390.1300.9500.4760.880
400.1160.9540.6150.878
410.1200.9540.6150.876
420.1040.9600.5920.879
430.1150.9540.5690.881
440.1190.9540.5680.870
450.1130.9580.5270.872
460.1030.9610.5940.877
470.1050.9600.6420.875
480.0990.9620.5250.872
490.1000.9620.6520.875
500.0920.9650.6140.868

テストデータも学習データと同じ様に自動生成したものであるため, 正答率は85%程度ある.

このモデルを用いて, 画像から数式を読み込み, 正誤判定ができるかどうかを確認する.

画像から読み込んだ数式の正誤判定

数式の書かれた画像から数式を読み込み, その数式の正誤判定を行う. 数式の読み取りの為に数式を書く画像の書式は固定し, ある範囲内に数式が書かれていれば自動的にトリミング, 処理できるようにした. これについても, Python上のOpenCVを用いた.

数式の範囲をトリミングする際には, 上下左右位置に余白を追加する. 余白を追加することでニューラルネットによる識別の精度が上がる他, 後に行うデータ拡張の際にも利用できる. また, ここでは画像に手書き風フォントで記載した数式を書き込んだものを利用して正誤判定を行う. 正誤判定を行う画像を図13,14に示す.

手書き数式の書かれた画像(1)
図13 手書き数式の書かれた画像(1)
手書き数式の書かれた画像(2)
図14 手書き数式の書かれた画像(2)

学習したモデルを用いて, 画像の正誤判定を行う. ex3/predict.pyを実行し, 画像を数式毎に分割して正誤判定を行った結果を以下に示す.

表7 手書き数式の正誤判定結果 問題1(1)
判定正答
問題1×
問題2×
問題3×
問題4××
問題5××
問題6××
表8 手書き数式の正誤判定結果 問題2(1)
判定正答
問題1×
問題2×
問題3×
問題4×
問題5×
問題6×

画像(1)の問題1~3は正答, 4~6は誤答であり, 画像(2)の問題は全て正答であるが, 全て誤答と判定されている.

学習時のデータセットやテストデータに用いた画像は手書き風フォントで自動生成したもので, 余白や文字の位置が統一されているが, ここでは1つの画像から数式を切り取って識別しているため, 学習時とは数式の位置が異なる. そのため, 学習したものとは異なる画像を判別できず, 正答率が低くなってしまったと考えられる.

そこで, 1つの画像に対して, 平行移動や回転の操作を加えることにより, データの幅を拡張させる. この拡張によって学習の効率, 精度の向上が図れるかを確認する.

4.4.3 拡張したデータを用いた学習

データ操作のためのPythonプログラムを作成し, 読み込んだ画像に対して操作を行う. 操作はOpenCVを用いて行った.

画像データの平行移動は, 上下左右それぞれ5ピクセルの範囲でランダムに, 回転は-10~10度の範囲でランダムに行い, データ拡張の際には1画像に対し平行移動及び回転の操作をどちらも行う.

各画像について9回拡張を行い, 学習を行う. ex3/train.pyを実行して学習を行う. ここで, データの拡張を行うため, プログラム内のn_extendを9として実行する. 学習の結果を表9に示す.

表9 データ拡張を行った画像の学習結果
epochtrain losstrain accuracytest losstest accuracy
10.5500.6950.4640.771
20.5140.7240.4530.770
30.5030.7310.4190.805
40.4980.7370.4060.806
50.4910.7420.4090.817
60.4870.7440.3890.831
70.4840.7470.3850.829
80.4790.7500.3730.832
90.4740.7520.4090.819
100.4690.7570.3760.845
110.4620.7610.3990.833
120.4590.7610.3840.837
130.4520.7680.3810.835
140.4460.7710.4120.834
150.4400.7760.3800.845
160.4350.7780.3840.847
170.4290.7820.3850.839
180.4200.7880.3920.848
190.4150.7910.4280.836
200.4050.7980.3980.851
210.3990.8000.3830.852
220.3930.8060.4080.844
230.3840.8090.3900.851
240.3790.8140.4150.852
250.3710.8180.4050.839
260.3640.8200.4060.851
270.3600.8240.4450.859
280.3510.8300.4130.849
290.3440.8330.4940.843
300.3380.8370.4210.852
310.3320.8400.4470.848
320.3270.8430.4410.851
330.3210.8460.4370.833
340.3130.8520.4380.852
350.3090.8540.4260.850
360.3030.8570.4530.850
370.3000.8590.4650.849
380.2930.8620.4980.854
390.2870.8660.4330.844
400.2840.8690.4480.858
410.2800.8700.5470.843
420.2740.8730.4740.859
430.2700.8760.4780.849
440.2660.8770.5040.858
450.2620.8810.5270.843
460.2600.8820.5110.855
470.2540.8850.4840.836
480.2510.8850.5400.850
490.2470.8880.5770.856
500.2440.8890.5470.854

bestepochは8で, 学習データでの正答率は0.75006, テストデータでの正答率は0.83200であった このモデルを用いて正誤判定を行った結果を以下に示す.

表10 手書き数式の正誤判定結果 問題1(2)
判定正答
問題1
問題2
問題3
問題4×
問題5×
問題6××
表11 手書き数式の正誤判定結果 問題2(2)
判定正答
問題1
問題2×
問題3×
問題4
問題5
問題6

画像(1)については4, 5問目を正答と判断しており, 画像(2)でも問題2と3を誤答と判断しているが, 拡張の無い場合と比べて正答率は向上している. このように, データに幅を持たせることで, 学習の精度の向上が期待できる.

加えて, 学習の際に画像に不要な黒点, 汚しを加え, 同様に学習を行う. 学習したいデータとは直接的な関係のない黒点をランダムに与えることによって, 学習にどのような影響があるかを確かめる. データ拡張の回数は同様の9回とし, 拡張の際にランダムな黒点を0~10個の範囲で画像に加えた上で学習をさせる.

ex3/train.pyを実行して学習を行う. n_extendは前回と変わらず9とする. ここでプログラム内の変数f_dirtをTrueとして実行し, 汚しの処理を行う. 汚し処理を行った画像の学習結果を表12に示す.

表12 データ拡張を行った画像の学習結果
epochtrain losstrain accuracytest losstest accuracy
10.6140.6280.4700.745
20.5770.6700.4940.753
30.5540.6930.4410.787
40.5340.7140.4110.808
50.5100.7360.4090.810
60.4830.7590.4000.825
70.4520.7810.3820.834
80.4210.8000.3900.828
90.3910.8200.4100.822
100.3610.8380.3810.835
110.3370.8520.3920.830
120.3140.8640.3920.833
130.2920.8740.3720.847
140.2720.8860.4110.820
150.2580.8920.3800.835
160.2430.8980.3870.833
170.2300.9060.3900.832
180.2210.9090.3710.849
190.2080.9160.3980.835
200.2010.9210.3810.854
210.1920.9250.3810.843
220.1840.9270.3770.844
230.1780.9300.4140.834
240.1720.9330.3720.850
250.1630.9470.3970.838
260.1620.9370.4020.843
270.1590.9390.3760.850
280.1530.9410.4180.842
290.1480.9430.3820.854
300.1450.9450.4120.847
310.1410.9460.4390.850
320.1400.9470.4430.850
330.1360.9490.4140.849
340.1310.9510.4550.837
350.1280.9520.4210.842
360.1250.9530.4320.840
370.1240.9550.4490.840
380.1220.9530.4200.848
390.1180.9560.4280.852
400.1180.9560.4440.857
410.1150.9580.4400.856
420.1120.9590.4260.853
430.1090.9600.4470.844
440.1090.9600.4610.841
450.1070.9610.4740.842
460.1060.9610.4790.847
470.1060.9610.4900.846
480.1020.9630.4370.854
490.1010.9630.5030.851
500.1000.9640.5060.858

bestepochは18で, 学習時の正答率は, 学習データでは0.90945, テストデータでは0.8490であった. 汚しを加えた上で学習したモデルでの正誤判定の結果は以下の様になった.

表13 手書き数式の正誤判定結果 問題1(2)
判定正答
問題1
問題2
問題3
問題4××
問題5×
問題6××
表14 手書き数式の正誤判定結果 問題2(2)
判定正答
問題1
問題2
問題3×
問題4
問題5×
問題6

画像(1)については判定失敗が問題5のみの1つになっているが, 汚しを加える前とは判定を失敗する問題も異なる.

ここで, 正誤判定の為に学習したそれぞれの場合について, 学習の進捗を比較する. 学習の繰り返し毎のテストデータにおけるloss値とaccuracy値のグラフから, 比較, 検討する.

学習におけるloss値, accuracy値の比較のグラフを図15, 16に示す.

学習におけるloss値の比較
図15 学習におけるloss値の比較
学習におけるaccuracy値の比較
図16 学習におけるaccuracy値の比較

loss値について検討すると, epoch数が多くなるにつれて, loss値の差が大きくなっている. データ拡張なしのデータ量が少ない場合の学習では, loss値が顕著に多くなっている. これはデータの種類が少ないことによる過学習の結果である. データ量が同じでも, 汚しの有無によってloss値に違いがあることも確認できる. データの拡張量はどちらも同じであるため, 学習とは無関係にランダムな要素を含むことによって, 過学習を避けることができると考えられる.

accuracy値については, データの拡張を行わない場合で最も高い値が現れている. これはテストデータが学習データと同じく, 数式の位置や角度のズレを伴わないものであるためと考えられ, 事実, 画像から切り取った数式の判定はうまくいかなかった.

データの拡張を行った場合は, 汚しの有無に関わらず正答率はあまり変わらなかった. テストするデータにも汚れを含むものがあれば正答率にも影響したのかもしれないが, 今回のテストデータでは影響は見られなかった.

5 考察

本実験では, 手書き風フォントを用いて数式画像を作成し, 出力となるラベルデータを変えてニューラルネットワークによる学習を行った. 学習モデルを用いた画像認識では, 学習したデータと同様にして生成された数式画像と, 手書きによる回答を想定して作成した画像を切り取った数式の2つを取り上げた. 識別するデータが学習データと同様の形式を持ち, 位置や角度の違い等を考慮しなければ, 高い正答率で認識することが可能であったが, 手書きを想定して画像から切り取ったものは数式自体以外にも学習データとの微妙な差異を生じるため, 数式画像をただ学習させるだけでは画像認識として機能しなかった.

しかしながら, 画像に対して平行移動や回転の操作をランダムに加えることでデータに幅を与えることができ, 位置や角度が一定でない数式についても認識ができたことによって, ニューラルネットを用いた画像認識の有用性を確認することができた. また, 学習データの無関係な要素, 今回は黒点による汚しをランダムに加えることによって, 過学習を軽減することができた. 本実験から, ニューラルネットによる学習では, 認識する対象の様々な場合を考慮し, それに対応して幅広いデータを学習させることが必要であると考える.

本実験で行った正誤判定は, 12問の判定を行った中でも誤判定が起こり, 正確な結果は期待できなかった. しかし, 数式の表す内容を知らずとも, 正答・誤答を教師データとすることで学習ができたことは有用であると考える. 本実験の様に手書き風のフォントによるデータでなく, 実際の正答・誤答のデータを利用し, またそのデータ量もより膨大になっていくことで, より豊富なデータを学習することができれば, 記述式問題の回答評価にも機械学習が利用できると考え, また実際の手書き回答に対してもこの学習実験を応用することを今後の課題としたい.

6 付録:ソースコード

参考文献

  1. Google, “ AlphaGo: Mastering the ancient game of Go with Machine Learning ”, 2016/1/27, https://research.googleblog.com/2016/01/alphago-mastering-ancient-game-of-go.html
  2. 太田智美(ITmedia), 「ついに明かされる「りんな」の“脳内” マイクロソフト、「女子高生AI」の自然言語処理アルゴリズムを公開」, 2016/5/27, http://www.itmedia.co.jp/news/articles/1605/27/news110.html
  3. Yann LeCun, Corinna Cortes and Chris Burges, “MNIST handwritten digit database”, http://yann.lecun.com/exdb/mnist/
  4. 篠田有史・中山弘隆・松本茂樹, 「文の構造を利用した記述式問題の自動採点」『コンピュータ&エデュケーション Vol. 22』, pp.41-45, 甲南大学 知的情報通信研究所・理工学部情報システム工学科, 2007.
  5. 藤木なほみ・大久保武尊・藤木澄義, 「複合型ニューラルネットワークによる文字認識能力の検討」『情報科学技術フォーラム講演論文集』, pp.603-606, 仙台電波工業高等専門学校専攻科・東北文化学園大学化学技術学部, 2009.
  6. 小高知宏著, 「機械学習 (マシンラーニング) と深層学習 (ディープラーニング) : C言語によるシミュレーション」, オーム社, 2016