1. HOME
  2. ブログ
  3. IT技術
  4. KerasとKivyを使って手書き数字認識アプリを作ってみた!

KerasとKivyを使って手書き数字認識アプリを作ってみた!

手書き数字認識アプリを作りたい

前回の 自作の誤差逆伝播学習法で手書き数字を認識させてみよう! では、自作プログラムで自分で書いた任意の手書き数字認識を試みました。

ほとんどの手書き数字では認識がうまくできていたものの、学習が遅く、あまり精度は良いとは言えませんでした。

そこで、本記事では既存の優秀な機械学習フレームワーク「Keras(ケラス)」を使って性能の良いネットワークを作成します。

さらに、もっと使いやすいように「Kivy(キビー)」というフレームワークを用いてGUIアプリケーション化しようと思います。

最終的に作れるアプリケーション

この記事を読んで最終的に完成するのは、「手書きで数字を書くと、その数字を認識するというアプリ」です。

【図 最終的に作れるアプリケーション】

それでは、作成していきましょう!

こちらの記事もオススメ!

準備するもの

まずは、環境整備です。

今回使うフレームワーク

  1. Keras : 機械学習
  2. Kivy : GUI
  3. NumPy : 数値計算
  4. Pillow (PIL) : 画像処理

以上のフレームワークがまだインストールされていなければ、次に紹介する方法でインストールしてください。

もうインストール済みの方は、読み飛ばしてください。

インストールされているか確認する方法は、ご存知のコレですね。

Keras(ケラス)のインストール

Kerasは、機械学習の有名なフレームワークの一つで、「Tensorflow(テンソルフロー)」などの有名な機械学習フレームワークを扱いやすく、シンプルにコードが書けるようになっています。

インストール方法

Kerasは、Tensorflowに依存しているので、Tensorflowもインストールしておきましょう。

また、 pip がver. 9.x系だとエラーを吐くことがあるらしいので、ついでに pip も最新のものにしておきましょう。

Kivy(キビー)のインストール

Kivyは、GUIフレームワークの一つで、オープンソースで開発されています。

さらに扱いやすく、さまざまなOSで動作するためKivyを使うことにしました。

Kivyは、Pythonファイルの他に「*.kv」ファイルで簡単にGUIをデザインすることができます。

インストール方法

このモジュールも pip でインストールできます。

これで、もし動かなかったら、追加で以下のモジュールもインストールしてください。

Pillow(PIL)のインストール

Pillowは、とても使い勝手が良い画像処理系のモジュールです。

これも先のモジュールと同じようにインストールできます。

いざ開発!

それでは、お楽しみの開発に移ります。

開発の流れとしては、以下の通りです。

  1. Kivyで「キャンバス画面・ペイント機能 」を実装
  2. Kerasで「機械学習部 」を実装

コードとともに解説していきますが、冗長になるため一行ずつ全て解説することはせず、重要な部分を中心に解説をしていきますのでご了承ください。

Kivy (GUI)部分について

まずは、キャンバス機能ペイント機能を作ります。

main.py と MyPaint.kv という2つのファイルを作って、これらにKivyを用いたGUIを管理するコードを書いていきます。

ここで、「*.kv」の名前は重要になってくるので、必ず同じ名前にしてください。

コード

とりあえず、コードは以下のようになります。

上記のコードを $ python main.py と実行してみてください。

黒いキャンパスに白い線で文字や数字が書けると思います。

また「Clear」でキャンパスがリセットできることも確認できます。

しかし、まだこの時点で「Predict」は未実装なので押してもなにも起こりません

*.pyと*.kv

それでは、コードを簡単に解説していきます。

まずは「この2種類のファイルの関係」について説明します。

「MyPaint.kv」でボタンのデザインを作っていることは、コードを見るとなんとなく理解できると思います。

しかし、肝心の「main.py」では、「MyPaint.kv」を参照しているらしきコードは見つかりません。

これは、「main.py」のクラス名 “***App” の名前から勝手に参照してくれる機能があるからです。

つまり、今回の場合、「main.py」MyPaintApp というクラスが定義されているので、Kivyが勝手に「MyPaint.kv」を探し参照してくれています。

そのため、Kivyでは、「ファイル名が重要」なのです。

キャンバスレイアウト

ウィンドウとキャンバスのレイアウトは、主にKivy.ConfigというモジュールWindowモジュールで行われています。

ウィンドウサイズ

以下のコード冒頭で、ウィンドウサイズを決めています。

ウィンドウの背景色

以下コードのmain関数でコメントしてあるように、ウィンドウの背景色を指定してます。

キャンバス全体の管理

ちなみにキャンバス全体の管理は、以下コードで行なっており、ここではキャンバスを初期化する関数だけ定義しておきます。

キャンバス内のボタンは MyPaint.kv で定義していきます。

ペイント部分

大事なペイント機能は、 class MyPaintWidget というクラスが担っています。

持つべき機能としては「クリックしてドラッグしたら線を引く」ことです。

線の太さ

このクラスでは、それに必要な「線の色」「線の太さ」をメンバ変数として保持しています。

そして、マウスクリックダウン時とマウスドラッグ時の機能を以下の関数で実現しています。

やっていることは、取得した座標に線を追加しているだけです。

また、キャンバスをクリアした時に色情報を再度セットするための関数があって、ペイント機能は完成です。

ボタン類

ボタン類はすべて「MyPaint.kv」が担っています。

「*.kv」ファイルの書き方は、 < > でどのウィジェットに配置したいかを指定し、その中に(Pythonと同じようにインデントを下げて)ボタン類を記述していきます。

今回弄るのは、 MyCanvasWidget クラスですので、 <MyCanvasWidget> の中に記述していきます。

上下に分割

ペイント領域とボタン領域を上下に分割することにしましたが、 BoxLayout: でレイアウトの調整が可能です。

まずは、上下に分割したいので、以下のように記述します。

さらに今回は、ボタンを2つ配置するので、下部のブロックを左右に1:1で分割します。

左右の分割

左右の分割は、以下のように指定します。

しかし、このままでは、ペイント領域とボタン領域が1:1なので、 size_hint_y: で調整しています。

今回は、0.80.1にしました。

また、ボタンがクリックされたときの挙動は、 on_release: で関数を指定してあげます。

Keras (機械学習)部分

今回のアプリの要である、機械学習部分と識別部分を作成していきます。

イメージとしては、このような流れで作っていきます。

  1. ① アプリが立ち上がる
  2. ② 機械学習を始める
  3. ③ キャンパスが表示される
  4. ④ 手書き数字を学習済みネットワークに流す

ここでは、Kerasの学習部は別の learning.py というファイルに実装していきます。

それでは、まず、アプリを実行した後の「②機械学習を始める」の部分から考えていきたいと思います。

学習部分の大枠

アプリ実行時、すなわち最初に呼び出されるクラスのコンストラクタで機械学習を行い、そのネットワークをメンバ変数として保持しておきます。

したがって、以下のようにコードを加筆します。

このとき、 learning.py にMNISTデータセットを学習する learn_MNIST() という関数がある前提で加筆します。

したがって、このような関数を実際に learning.py に作っていきましょう!

ネットワークを作成

今回は、以下のようなネットワークを作成していきます。

【図 ネットワーク構成】

ここでDenseとは、全結合層を指し、Dropoutとは過学習を抑制するための手法の一つを指します。

簡単に説明すると、Dropoutは訓練パターンが入力される度にランダムでニューロンを非活性にし、そのニューロンと接続しているシナプス結合は学習を行わないという手法です。

こうすることにより、学習の自由度を下げて訓練パターンへの過学習を防ぐことができます。

活性化関数

また、今回のネットワークで用いるReLUと呼ばれる活性化関数は、以下のような形をしており、画像識別ではよく使われます。

【図 ReLU関数の概形】

最終層の活性化関数であるsoftmaxは、出力値の合計を1にする関数、つまり確率を出力にする関数です。

Kerasで実装

ひとまず、ここまでをKerasで実装してみます。

このような形になりますが、教師信号のOne-hot-encodeingとはもともとのクラスラベルを[0, 1]の配列にすることを指します。

例えばクラスラベル「3」であれば、 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0] のようになります。

この方が、機械学習では扱いやすいためです。

学習部分の実装

次に、学習部分を実装していきます。

ですがその前に、どのような目的関数を使い、どのような最適化手法を使うかを明示的に設定する必要があります。

今回は、最適化手法にAdamと呼ばれる学習の収束を早める手法を使い、目的関数はクロスエントロピーという関数を用いることにします。

  1. 最適化手法に「Adam」
  2. 目的関数は、「クロスエントロピー」という関数

その次に、実際に学習をしていくのですが、Kerasには、 fit() という関数一つで学習が行えます。

実装

これらの実装例は以下のようになります。

これで学習部分の実装完了です。

ちなみに verbose は学習過程をログとして出力するかを指定しています。

0ならログなし、1ならプログレスバーを表示、2ならエポックごとにログを出力させます。

あとは、これによって作られたネットワーク(model)を戻り値として返すだけです。

ですが折角なので、テスト精度も表示させるようにしましょう。

これで学習部分は完成です!

識別部分

最後に、キャンパスに描いた手書き数字をネットワークに流してネットワークの答えを出力させるだけです。

main.py の predict() を作っていきましょう!

流れ

  1. ① キャンパスを画像として保存
  2. ② Pillowでその画像を読み込み、不要な部分(ボタン類)を切り取る
  3. ③ グレースケール、28×28に変換
  4. ④ 画像を配列に変換
  5. ⑤ ネットワークに流す

実装

これらを実装してみます。

以上で実装は終わりです!

お疲れ様でした!

こちらの記事もオススメ!

関連記事

最終的なコード

main.py

MyPaint.kv

learning.py

 

ライトコードよりお知らせ

にゃんこ師匠にゃんこ師匠
システム開発のご相談やご依頼はこちら
ミツオカミツオカ
ライトコードの採用募集はこちら
にゃんこ師匠にゃんこ師匠
社長と一杯飲みながらお話してみたい方はこちら
ミツオカミツオカ
フリーランスエンジニア様の募集はこちら
にゃんこ師匠にゃんこ師匠
その他、お問い合わせはこちら
ミツオカミツオカ
   
お気軽にお問い合わせください!せっかくなので、別の記事もぜひ読んでいって下さいね!

一緒に働いてくれる仲間を募集しております!

ライトコードでは、仲間を募集しております!

当社のモットーは「好きなことを仕事にするエンジニア集団」「エンジニアによるエンジニアのための会社」。エンジニアであるあなたの「やってみたいこと」を全力で応援する会社です。

また、ライトコードは現在、急成長中!だからこそ、あなたにお任せしたいやりがいのあるお仕事は沢山あります。「コアメンバー」として活躍してくれる、あなたからのご応募をお待ちしております!

なお、ご応募の前に、「話しだけ聞いてみたい」「社内の雰囲気を知りたい」という方はこちらをご覧ください。

ライトコードでは一緒に働いていただける方を募集しております!

採用情報はこちら

関連記事