Python
機械学習
DeepLearning
Chainer

『日本人「だけ」読めないフォント』が本当に日本人だけ読めないのか、ニューラルネットの力を借りて確認してみた

More than 3 years have passed since last update.

掲題の件、ちょっと気になったのとちょうどいい勉強ネタということで確認してみます。

発端

Twitterで流れてきた 日本人「だけ」読めないフォント!? そんなバカなと思ったけどホントに読めそうで読めない!(http://togetter.com/li/887973) を見てふと、

 「本当にカタカナ(とかそれに近い形状)に関する認識機能の有無で、読める読めない(=判別できるできない)が変わるのだろうか?」

と思ったことがきっかけで、畳み込みニューラルネットを使って確認してみることにしました。
既にどこかの誰かが試しているかもしれませんが、お勉強ということでひとつ。

なおここでは畳み込みニューラルネットの説明は割愛します。あしからず。

仮説

カタカナ+英語を分類できる分類器より、英語のみの分類しかできない分類器の方が精度よく文字を当てられる

手法

以下5パターンを比較することで、知っている文字の差分が精度に与える影響を評価します。

No. 学習データ 出力クラス数
1 アルファベット+数字のみ 62(大文字小文字を区別)
2 No.1+ひらがなのみ 62+48 = 110
3 No.1+カタカナのみ 62+48 = 110
4 No.1+ひらがな+カタカナ 62+48*2 = 158
5 No.1+ヘブライ文字 62+28 = 89

No.5については http://dic.nicovideo.jp/a/%E3%83%98%E3%83%96%E3%83%A9%E3%82%A4%E6%96%87%E5%AD%97 に記載の「文字」と「語尾形」を別クラスとして扱っています。
(そもそもなんでヘブライ文字やねん、というツッコミに対しては、togetterに「ヘブライ文字にもちょっと似てる気がする。」というコメントがあったため比較用に入れた、という程度の理由です。)

使用データ

OCR向けの無料データを使わせていただこうかと思いましたが、どうもちょうどよいものがなかったので自作しています。

Pillow(PIL)で1文字の画像をたくさん生成する(http://qiita.com/lazykyama/items/65bcce351f3d1cf07d8e) に記載のスクリプトで1文字だけの画像を対象文字数分作っておき、それにランダムなノイズを乗せてデータを水増ししました。
今回の検証では1文字あたり30枚のノイズつき画像を動的に生成し、学習データとしています。

また、テスト用の画像は http://www.dafont.com/electroharmonix.font のサンプル画像から手動で切り出したものを使いました。

学習データ・テストデータとも、64x64のグレースケール画像を使用しています。

ネットワーク構造

分類器の構成は以下のコードの通りです。
各種パラメータなどは適当です。

self.__model = chainer.FunctionSet(
     conv1=F.Convolution2D(1, 16, 5), 
     conv2=F.Convolution2D(16, 16, 5), 
     l3=F.Linear(784, 784), 
     softmax4=F.Linear(784, class_num))

# 中略

x = chainer.Variable(source)

h = F.max_pooling_2d(F.relu(self.__model.conv1(x)), ksize=2, stride=2)
h = F.max_pooling_2d(F.relu(self.__model.conv2(h)), ksize=3, stride=4)
h = F.dropout(F.relu(self.__model.l3(h)), train=train)
y = self.__model.softmax4(h)

なおご覧のとおり、今回の実装に際しては Chainer を使っています。
http://qiita.com/hogefugabar/items/312707a09d29632e7288 を参考にさせていただきました。ありがとうございます。)

実験結果

今回の実験は全パターン共通して、以下のパラメータを使用しています。
(他にもいろいろ試してはいます)

  • epoch: 10
  • mini-batch: 10

この条件下での結果は以下の通りとなりました。

No. 学習データ 正答率
1 アルファベット+数字のみ 46.2% (12 / 26)
2 No.1+ひらがなのみ 34.6% ( 9 / 26)
3 No.1+カタカナのみ 15.4% ( 4 / 26)
4 No.1+ひらがな+カタカナ 26.9% ( 7 / 26)
5 No.1+ヘブライ文字 23.1% ( 6 / 26)

そもそもあんまり正答率高くないですけど、それにしてもカタカナ混ざった時の精度がヒドいことになっていますね。。。
やはり日本人には読みづらいのかもしれません。

最後にテスト時のログを以下に記載しておきます。
(ログ中、「capsV」などとなっているのは大文字であることを表します。今回対象としたelectroharmonixは大文字も小文字も同じ形状のようなので、どちらにマッチしても正解として扱っています。)

test models.
[PATTERN1]: English only.
2015-10-19 08:08:39,112 [INFO] #data: 26
2015-10-19 08:08:39,186 [INFO] correct: v, answer: capsV => RIGHT
2015-10-19 08:08:39,186 [INFO] correct: g, answer: capsT => WRONG
2015-10-19 08:08:39,186 [INFO] correct: s, answer: capsE => WRONG
2015-10-19 08:08:39,187 [INFO] correct: o, answer: capsD => WRONG
2015-10-19 08:08:39,187 [INFO] correct: i, answer: capsZ => WRONG
2015-10-19 08:08:39,187 [INFO] correct: r, answer: capsR => RIGHT
2015-10-19 08:08:39,187 [INFO] correct: u, answer: capsU => RIGHT
2015-10-19 08:08:39,187 [INFO] correct: a, answer: capsA => RIGHT
2015-10-19 08:08:39,187 [INFO] correct: h, answer: capsH => RIGHT
2015-10-19 08:08:39,188 [INFO] correct: l, answer: capsD => WRONG
2015-10-19 08:08:39,188 [INFO] correct: k, answer: capsN => WRONG
2015-10-19 08:08:39,188 [INFO] correct: n, answer: capsO => WRONG
2015-10-19 08:08:39,188 [INFO] correct: q, answer: capsT => WRONG
2015-10-19 08:08:39,188 [INFO] correct: d, answer: capsD => RIGHT
2015-10-19 08:08:39,188 [INFO] correct: m, answer: capsM => RIGHT
2015-10-19 08:08:39,189 [INFO] correct: t, answer: n => WRONG
2015-10-19 08:08:39,189 [INFO] correct: e, answer: capsE => RIGHT
2015-10-19 08:08:39,189 [INFO] correct: x, answer: x => RIGHT
2015-10-19 08:08:39,189 [INFO] correct: p, answer: capsF => WRONG
2015-10-19 08:08:39,189 [INFO] correct: w, answer: capsQ => WRONG
2015-10-19 08:08:39,189 [INFO] correct: z, answer: capsZ => RIGHT
2015-10-19 08:08:39,189 [INFO] correct: y, answer: capsY => RIGHT
2015-10-19 08:08:39,189 [INFO] correct: c, answer: capsT => WRONG
2015-10-19 08:08:39,190 [INFO] correct: b, answer: capsZ => WRONG
2015-10-19 08:08:39,190 [INFO] correct: f, answer: capsF => RIGHT
2015-10-19 08:08:39,190 [INFO] correct: j, answer: capsZ => WRONG
2015-10-19 08:08:39,190 [INFO] test accuracy: 0.461538461538 (12 / 26)
[PATTERN2]: English and hiragana.
2015-10-19 08:08:39,314 [INFO] #data: 26
2015-10-19 08:08:39,387 [INFO] correct: v, answer: capsV => RIGHT
2015-10-19 08:08:39,387 [INFO] correct: g, answer: capsT => WRONG
2015-10-19 08:08:39,387 [INFO] correct: s, answer: capsB => WRONG
2015-10-19 08:08:39,387 [INFO] correct: o, answer: capsB => WRONG
2015-10-19 08:08:39,388 [INFO] correct: i, answer: capsZ => WRONG
2015-10-19 08:08:39,388 [INFO] correct: r, answer: ほ => WRONG
2015-10-19 08:08:39,388 [INFO] correct: u, answer: capsU => RIGHT
2015-10-19 08:08:39,388 [INFO] correct: a, answer: l => WRONG
2015-10-19 08:08:39,388 [INFO] correct: h, answer: わ => WRONG
2015-10-19 08:08:39,388 [INFO] correct: l, answer: capsU => WRONG
2015-10-19 08:08:39,388 [INFO] correct: k, answer: capsT => WRONG
2015-10-19 08:08:39,389 [INFO] correct: n, answer: capsD => WRONG
2015-10-19 08:08:39,389 [INFO] correct: q, answer: capsT => WRONG
2015-10-19 08:08:39,389 [INFO] correct: d, answer: capsD => RIGHT
2015-10-19 08:08:39,389 [INFO] correct: m, answer: capsM => RIGHT
2015-10-19 08:08:39,389 [INFO] correct: t, answer: す => WRONG
2015-10-19 08:08:39,389 [INFO] correct: e, answer: capsE => RIGHT
2015-10-19 08:08:39,390 [INFO] correct: x, answer: x => RIGHT
2015-10-19 08:08:39,390 [INFO] correct: p, answer: capsT => WRONG
2015-10-19 08:08:39,390 [INFO] correct: w, answer: い => WRONG
2015-10-19 08:08:39,390 [INFO] correct: z, answer: capsZ => RIGHT
2015-10-19 08:08:39,390 [INFO] correct: y, answer: capsY => RIGHT
2015-10-19 08:08:39,390 [INFO] correct: c, answer: capsE => WRONG
2015-10-19 08:08:39,391 [INFO] correct: b, answer: capsT => WRONG
2015-10-19 08:08:39,392 [INFO] correct: f, answer: capsT => WRONG
2015-10-19 08:08:39,392 [INFO] correct: j, answer: capsJ => RIGHT
2015-10-19 08:08:39,392 [INFO] test accuracy: 0.346153846154 (9 / 26)
[PATTERN3]: English and katakana.
2015-10-19 08:08:39,517 [INFO] #data: 26
2015-10-19 08:08:39,591 [INFO] correct: v, answer: capsV => RIGHT
2015-10-19 08:08:39,591 [INFO] correct: g, answer: capsQ => WRONG
2015-10-19 08:08:39,591 [INFO] correct: s, answer: ラ => WRONG
2015-10-19 08:08:39,591 [INFO] correct: o, answer: ワ => WRONG
2015-10-19 08:08:39,591 [INFO] correct: i, answer: ヱ => WRONG
2015-10-19 08:08:39,592 [INFO] correct: r, answer: ワ => WRONG
2015-10-19 08:08:39,592 [INFO] correct: u, answer: capsU => RIGHT
2015-10-19 08:08:39,592 [INFO] correct: a, answer: ム => WRONG
2015-10-19 08:08:39,592 [INFO] correct: h, answer: r => WRONG
2015-10-19 08:08:39,592 [INFO] correct: l, answer: capsQ => WRONG
2015-10-19 08:08:39,592 [INFO] correct: k, answer: ワ => WRONG
2015-10-19 08:08:39,592 [INFO] correct: n, answer: ワ => WRONG
2015-10-19 08:08:39,593 [INFO] correct: q, answer: capsR => WRONG
2015-10-19 08:08:39,593 [INFO] correct: d, answer: ワ => WRONG
2015-10-19 08:08:39,593 [INFO] correct: m, answer: capsO => WRONG
2015-10-19 08:08:39,593 [INFO] correct: t, answer: l => WRONG
2015-10-19 08:08:39,593 [INFO] correct: e, answer: ラ => WRONG
2015-10-19 08:08:39,593 [INFO] correct: x, answer: メ => WRONG
2015-10-19 08:08:39,593 [INFO] correct: p, answer: ア => WRONG
2015-10-19 08:08:39,593 [INFO] correct: w, answer: capsQ => WRONG
2015-10-19 08:08:39,593 [INFO] correct: z, answer: capsZ => RIGHT
2015-10-19 08:08:39,593 [INFO] correct: y, answer: capsY => RIGHT
2015-10-19 08:08:39,594 [INFO] correct: c, answer: capsE => WRONG
2015-10-19 08:08:39,594 [INFO] correct: b, answer: カ => WRONG
2015-10-19 08:08:39,594 [INFO] correct: f, answer: 5 => WRONG
2015-10-19 08:08:39,594 [INFO] correct: j, answer: capsT => WRONG
2015-10-19 08:08:39,594 [INFO] test accuracy: 0.153846153846 (4 / 26)
[PATTERN4]: English and hiragana and katakana.
2015-10-19 08:08:39,718 [INFO] #data: 26
2015-10-19 08:08:39,792 [INFO] correct: v, answer: ノ => WRONG
2015-10-19 08:08:39,792 [INFO] correct: g, answer: capsQ => WRONG
2015-10-19 08:08:39,792 [INFO] correct: s, answer: ラ => WRONG
2015-10-19 08:08:39,793 [INFO] correct: o, answer: capsQ => WRONG
2015-10-19 08:08:39,793 [INFO] correct: i, answer: capsT => WRONG
2015-10-19 08:08:39,793 [INFO] correct: r, answer: ア => WRONG
2015-10-19 08:08:39,793 [INFO] correct: u, answer: capsU => RIGHT
2015-10-19 08:08:39,793 [INFO] correct: a, answer: ム => WRONG
2015-10-19 08:08:39,793 [INFO] correct: h, answer: わ => WRONG
2015-10-19 08:08:39,793 [INFO] correct: l, answer: り => WRONG
2015-10-19 08:08:39,794 [INFO] correct: k, answer: ワ => WRONG
2015-10-19 08:08:39,794 [INFO] correct: n, answer: ワ => WRONG
2015-10-19 08:08:39,794 [INFO] correct: q, answer: capsQ => RIGHT
2015-10-19 08:08:39,794 [INFO] correct: d, answer: capsD => RIGHT
2015-10-19 08:08:39,795 [INFO] correct: m, answer: capsM => RIGHT
2015-10-19 08:08:39,795 [INFO] correct: t, answer: ナ => WRONG
2015-10-19 08:08:39,795 [INFO] correct: e, answer: capsE => RIGHT
2015-10-19 08:08:39,795 [INFO] correct: x, answer: メ => WRONG
2015-10-19 08:08:39,795 [INFO] correct: p, answer: ア => WRONG
2015-10-19 08:08:39,796 [INFO] correct: w, answer: ロ => WRONG
2015-10-19 08:08:39,796 [INFO] correct: z, answer: capsZ => RIGHT
2015-10-19 08:08:39,796 [INFO] correct: y, answer: ノ => WRONG
2015-10-19 08:08:39,796 [INFO] correct: c, answer: capsQ => WRONG
2015-10-19 08:08:39,796 [INFO] correct: b, answer: capsZ => WRONG
2015-10-19 08:08:39,796 [INFO] correct: f, answer: テ => WRONG
2015-10-19 08:08:39,796 [INFO] correct: j, answer: capsJ => RIGHT
2015-10-19 08:08:39,796 [INFO] test accuracy: 0.269230769231 (7 / 26)
[PATTERN5]: English and Hebrew.
2015-10-19 08:08:39,921 [INFO] #data: 26
2015-10-19 08:08:39,994 [INFO] correct: v, answer: capsV => RIGHT
2015-10-19 08:08:39,995 [INFO] correct: g, answer: ם => WRONG
2015-10-19 08:08:39,995 [INFO] correct: s, answer: capsZ => WRONG
2015-10-19 08:08:39,995 [INFO] correct: o, answer: capsH => WRONG
2015-10-19 08:08:39,995 [INFO] correct: i, answer: capsZ => WRONG
2015-10-19 08:08:39,995 [INFO] correct: r, answer: capsK => WRONG
2015-10-19 08:08:39,995 [INFO] correct: u, answer: capsH => WRONG
2015-10-19 08:08:39,996 [INFO] correct: a, answer: capsA => RIGHT
2015-10-19 08:08:39,996 [INFO] correct: h, answer: b => WRONG
2015-10-19 08:08:39,996 [INFO] correct: l, answer: ם => WRONG
2015-10-19 08:08:39,996 [INFO] correct: k, answer: ל => WRONG
2015-10-19 08:08:39,996 [INFO] correct: n, answer: capsH => WRONG
2015-10-19 08:08:39,997 [INFO] correct: q, answer: capsH => WRONG
2015-10-19 08:08:39,997 [INFO] correct: d, answer: capsD => RIGHT
2015-10-19 08:08:39,997 [INFO] correct: m, answer: capsM => RIGHT
2015-10-19 08:08:39,997 [INFO] correct: t, answer: l => WRONG
2015-10-19 08:08:39,997 [INFO] correct: e, answer: z => WRONG
2015-10-19 08:08:39,997 [INFO] correct: x, answer: capsX => RIGHT
2015-10-19 08:08:39,997 [INFO] correct: p, answer: capsT => WRONG
2015-10-19 08:08:39,998 [INFO] correct: w, answer: capsQ => WRONG
2015-10-19 08:08:39,998 [INFO] correct: z, answer: capsZ => RIGHT
2015-10-19 08:08:39,998 [INFO] correct: y, answer: capsV => WRONG
2015-10-19 08:08:39,998 [INFO] correct: c, answer: capsQ => WRONG
2015-10-19 08:08:39,998 [INFO] correct: b, answer: capsM => WRONG
2015-10-19 08:08:39,998 [INFO] correct: f, answer: capsM => WRONG
2015-10-19 08:08:39,998 [INFO] correct: j, answer: 5 => WRONG
2015-10-19 08:08:39,999 [INFO] test accuracy: 0.230769230769 (6 / 26)

英語のみのモデルでも「g」を「T」と間違えていたりして、なんとも言えない感じです。
electroharmonics_g_img.png
↑electroharmonixの「g」

Arial_capsT_img.png
↑学習データの「T」

とはいえ、英語+カタカナのモデルだと「s」を「ラ」と間違えていてよりダメ…
electroharmonics_s_img.png
↑electroharmonixの「s」

Osaka_ラ_img.png
↑学習データの「ラ」

…そうでもないですね。これは間違えそう。

まとめ

  • そもそも英語圏の人でもそこまで読みやすいフォントではないっぽい
  • カタカナを知っていると極端に読みづらくなることが定量的に計測できた(ことにします)
  • 「似てるんでは?」といわれていたヘブライ語圏の人にも辛そう
  • 漢字入れたり、手書き文字を学習させた場合にどうなるか気にになります

追記

いくつか書き忘れていたので追記しときます。

  • 人間の脳は意味のある文章になるよう補完かけているフシがあるようなので、そのへん込みで確認するとどうなるかも気になっています(どなたか…)
  • ちゃんとやるなら出力クラス数が極力近くなるようにして、かつ有意差があるかとか検定すべきでしょうね

備考

ソース一式置いておきます。
https://gist.github.com/lazykyama/f586419cd72d5312288e