前回はWindows上でCNTKとVSCodeによる開発環境構築を行ないました。今回はCNTKを使用して画像認識の実装をしていきます。前回の記事はこちらです。一般的に機械学習には学習過程の教師データが不可欠(*)です。WorldであるところのMNISTデータセットを使用します。CNTKにもMNISTデータセットを使用するサンプルがあり、データ読み込みのための仕組みが用意されているため、これを流用します。ドキュン?)と呼ばれる手法は教師データを必要としませんが、本連載では触れません。興味のある方は調べてみてください。コマンドプロンプトを起動して以下のコマンドを実行してください。install_mnist.pyinstall_mnist.pyはMNISTデータセットをダウンロードし、テキスト形式で保存するスクリプトです。スクリプト終了後、dirコマンドを実行しましょう。作成されていればダウンロードは完了です。MNISTデータセットを使用した様々なニューラルネットワークの実装サンプルが含まれています。本記事の内容もこれらのサンプルを参考に作成したものです。つまづいたら見てみると良いでしょう。開発用のプロジェクトを用意します。いっても、やることは多くありません。適当なフォルダを作成します。ここは各々の環境で読み替えてください。作成したcntk-mnistフォルダを開きましょう。画像のようになっていればプロジェクト作成完了です。前置きが長くなりましたがいよいよ実装です。実装するモデルを図示します。機械学習ライブラリを使ったネットワークモデルの実装は一般に非常にシンプルで小さなコードになります。Pythonコードの全貌は以下のとおりです。])このコードをmodels.pyという名前で保存します。登場する要素について見ていきましょう。activation=activation_default_or_None)Denseはニューラルネットワークの全結合層を表す機能です。shapeに出力数をintで指定します。今回隠れ層ではinit=he_uniform()で初期値としてheの初期値、activation=reluで活性化関数にReLU関数を指定しています。戻り値は、全結合層の入力を受け取り、出力を返す関数です。activation=relu)(feature)このコードは以下の図の実装になります。CNTKの層を表す機能はどれもこれと同じく、層の入力を受け取り出力を返す関数を戻り値とします。大事な性質なので覚えておきましょう。SequentialSequential(layers)Sequentialはニューラルネットワークの複数の層を1つにまとめる機能です。引数layersに、まとめたい層の(関数の)配列を指定します。Sequentialの戻り値もDense同様に層の入力を受け取り出力を返す関数になりますが、Sequentialは最終的な出力を返してくれます。例を挙げると、以下の2つのコードは等価になります。constructor)Forは少々変わり種の機能です。ニューラルネットワークのモデルでは、同じような構造の層を繰り返すことがたびたびあります。そのような構造をForを使用することで簡潔に表現できます。Nに層の集合の繰り返し数、constructorに層の集合のファクトリー関数を指定します。ファクトリー関数の第一引数には現在の繰り返し数が渡されてくるので、層の深さによってパラメータのみを切り替えた同一構造の層を見通しよく記述できます。例を挙げると、以下の2つのコードは等価になります。CNTKは提供してくれています。これによって実装者は内部でどのような数式が使用されているのかさほど意識せずにネットワークモデルを構築することが可能です。ここに挙げたものも含めてより詳細な情報は公式のAPIリファレンスを参照してください。画像認識を実装する前項で作成したMLPのモデルを使用し、画像認識の実装を行ないます。プロジェクトに配置済みのMNISTデータセットファイルが認識の対象とする入力データです。このファイルはCNTKで読み込みやすいように加工されており、以下のような関数(*)で読み込むことができます。FULL_DATA_SWEEP)ここについてはデータ形式を扱いやすいようにパースするのが主な目的で、本記事の主旨とずれるため各機能についての詳細は割愛します。公式のリファレンスを参照してください。次に、読み込んだデータをネットワークモデルに流し込んで行く実装は以下のとおりです。いずれもモデルに与えるパラメータをCNTKの機能でラップするものです。定数をそれぞれラップします。最後の2行で前項で実装したMLPモデルのインスタンスを生成し、入力パラメータと接続しています。Trainerここまでの段階ではまだネットワークモデルに値は流れていません。学習を実行するにはTrainerと呼ばれる、ネットワークモデルの学習を担当するものが必要です。Trainerの生成は以下のコードで行ないます。parameter_learners)Trainerの引数には以下の内容を指定します。ネットワークモデルと入力パラメータを接続した戻り値。今回はcross_entropy_with_softmaxを使います。最終的な出力と正解ラベルの比較を行うもので、今回はclassification_errorを使います。他のライブラリではOptimizer(最適化関数)などと呼ばれるもの。学習関数にはsgdを使用しています。他にmomentum_sgdやadagrad、adam_sgdなどもありますが、それぞれ固有のパラメータが必要となるので使用の際は公式のリファレンスを参照してください。このようにTrainerを作成した後、教師データを対象に学習を実行します。教師データとラベルを対応付けるハッシュ配列。eval_crit))機械学習では入力データをおおよそ1週する学習の単位をepochと言います。教師データは60000件あるため1epochを60000件として、今回は20週分の学習を行ないます。reader_train.next_minibatch()で一括で処理するデータを取り出し、trainer.train_minibatch()の引数に渡すことで、取り出した教師データを対象に学習が実行されます。今回は1epochごとに学習の結果をコンソールに出力しています。グラフ表示も含めてログ関連の機能もCNTKに用意されているため、慣れてきたら使用してみるのも良いと思います。ここまででモデルと学習の実装が完了しました。最後に全体のコードを記載します。学習が終わったモデルを使用してテストデータの推論を行う実装の説明は教師データの実行とさほど変化が無いため割愛します。教師データとラベルを対応付けるハッシュ配列。テストデータとラベルを対応付けるハッシュ配列。error)いかがでしょうか?私自身の不慣れも大いにありますが、あまり読みやすいコードとは言えないかもしれませんね。こなれてくるとライブラリの使用者も増えるのかなと思っていたりします。それではこのスクリプトを実行してみましょう。Terminal」を選択してもよいです。実行するとおそらく最終的に教師データの正解率は99%を越え、テストデータについても98%以上の正解率となると思います。おわりやや駆け足の内容となりましたが、今回はMLPのモデルを実装し、MNISTデータセットの学習を行ないました。正解率98%はその数値だけ見れば十分実用的といえるものです。MNISTデータセットは1つの画像サイズが幅28×高さ28と小さく、シンプルなデータのため今回の実装でも十分な精度が得られます。現実的には入力データ、分類のパターンがもっと複雑なものがほとんどで、単純で層の浅いモデルで認識精度を上げることは難しいでしょう。次回は畳み込みニューラルネットワーク(CNN)の実装を行ない、締めとしたいと思います。