Generatorの戻り値としては、以下のようにデータとラベルに関するデータが生成される。Generatorの戻り値としては、以下のようにデータとラベルに関するデータが生成される。9}train_generator(ジェネレータ)により、(10,28,28,1)のデータと、ラベルとして(10,10)のデータが生成されます。わかりやすく言い換えると、データが「バッチサイズ、縦、横、グレースケール」ラベルが「バッチサイズ分のラベル」です。最初の「10」はバッチサイズが10なので、(10,28,28,1)→28x28ピクセルでグレースケール(1)のデータが10セットずつ生成されているということです。ラベル(10,10)は、0~9の10個が10セットで(10,10)ずつラベルデータが生成されているような感じです。indicesには以下のような形式でラベルデータが保存されるので、この値を確認することで実際にラベル付けされた値を確認できます。・辞書型のデータ・{label:番号}で保存されている。以下の例だとフォルダ名「0」にラベル「0」を割り当てる、フォルダ名「1」にラベル「1」を割り当てる・・・・ということをしてくれています。9}以上で学習の準備ができたので学習していきます。batch_size)学習が終わったらモデルを保存しておきます。model.save('mnist.h5')12#モデルの保存model.save('mnist.h5')念のためモデルのロードを確認します。load_model('mnist.h5')学習結果も可視化して確認しておきます。label='Validation損失')plt.title('Training&validation損失')plt.xlabel('エポック数')plt.legend()plt.show()今回はこんな感じの精度になりました。新しいデータで試しに予測してみましょう。steps=None)).argmax()print(result)8上記のコードでは以下を実施しています。1テスト用の画像ファイル「C:\django\ML\mnist\data\pred\test\sample.jpg」を読み込む。2imgでOpenして、img.convert('L')でグレースケール化3img.resizeでファイルサイズを28x28ピクセルにリサイズ4reshapeで(1,28,28,1)次元に変換(定義したCNNモデルの入力形状に合わせるため)5最後にpredictでimgを渡して、学習済みモデルを使って予測結果を受け取り、argmax()で最大値のINDEXデータを取得しています。※predictの結果は[0,0,0,0,0,0,0,0,1,0]のようなOne-Hot情報になっているのでargmaxで最大(=1)のINDEX番号を取得しています。以上で、学習モデルの準備が完了しました。この学習モデルをDjangoに組み込んでウェブアプリを作っていきます。Djangoの開発Django側で実施するのは以下の3つだけです。1Djangoのビュー(views.py)の作成2URLパターン(urls.py)の設定3テンプレートの作成(htmlファイル)まずビューの設定です。導入部で必要なモジュールをImportしておきます。osポイントだけ説明すると、Imageは画像データを読み込むために利用する。numpyは画像データをベクトル化する際に利用する。base64は画像データをテンプレート側のimgタグのsrcに直接読み込ませるために利用する。続いて、前もって学習させておいた学習モデルをImportします。tf.get_default_graph()tf.get_default_graph()の部分で、ロードした学習モデルの計算グラフ情報を取得しています。この辺はよくわかっていなかったのですが、計算グラフ情報を利用しないと以下のようなエラーが出るケースがありました。Tensor」エラーが出るようになった。わからないけどググったら「load_modelを使って読み込んだモデルは、tf.get_default_graph()を使ってスレッド間で共有できるようにする必要がある。ソースを真似して買えたら直った。2018続いて入力を受け取って結果を返す関数「mnist」の定義です。graph.as_defaultの部分で、最初に取得しておいたTensorFlowの計算グラフを使うような宣言をしています。次のコードでは、model.predict(入力データ).argmax()という形式で入力データに対して予測値(例えば数字の4だと[0,0,0,0,1,0,0,0,0,0])が返ってくるので、argmaxで最大値のIndex(4)を取得して、その値をreturnします。続いて、ファイルをアップロードした際に呼ばれる関数を定義していきます。以下、途中を省略してupload関数の全体を記載しています。="【ERROR】jpg以外の拡張子ファイルが指定されています。="【ERROR】jpg以外の拡張子ファイルが指定されています。redirect('index')「判定」ボタンを押したときにupload関数が呼ばれるようにします。引数にリクエスト(request)を受け取ります。request.FILES.getlist("files[]")のように記載すると、複数ファイルのアップロードができるようになります。何かアップロードがあり、POSTメソッドならば学習モデルに画像データを渡して戻り値を取得してテンプレートへ渡す、そうでなければindexページへ単にリダイレクトするというフローにしています。filesにはリスト型でファイル情報が入ってくるので、forループで1つずつ取り出し、拡張子が「.jpg」であるかどうかを判定して、jpgではない場合はエラーメッセージをテンプレートに返しています。os.path.splitext(memory_file.name)」の部分でアップロードされたファイル名からファイル拡張子「.xxx」の部分をext変数に格納しています。その後、extが「.jpg」と一致しない場合にエラーメッセージをテンプレートに渡しています。="【ERROR】jpg以外の拡張子ファイルが指定されています。="【ERROR】jpg以外の拡張子ファイルが指定されています。message,})続いて以下の部分。np.array(img).reshape(1,28,28,1)labels.append(mnist(img))ファイルがアップロードされていた場合(POSTメソッド&filesが存在する)、filesから1つずつファイル情報を取り出し以下の処理を繰り返します。・最後にmnist(img)でminist関数にimgデータを渡して、判定結果を行け取り、labelsリストに戻り値を追加forループで全ファイル分処理が回ると、labels変数に画像の判定結果がリストとして格納されます。labels=[0,1,4,9,5]のような感じです。label))アップロードされた画像データ(src)と推論した結果(labels)をタプル形式でresult変数に追加していきます。この辺のノウハウはnaritoさんのblog記事を参考にさせていただきました。最後に以下の部分で画像データ(src)と推論結果(result)をテンプレートへ渡しています。context)views.pyの全体コードは以下の通りです。="【ERROR】jpg以外の拡張子ファイルが指定されています。="【ERROR】jpg以外の拡張子ファイルが指定されています。result続いてURLパターン(urls.py)の設定です。プロジェクト直下のURLは以下の通りです。include('mnist.urls')),]ここは単純にmnistアプリケーションのurls.pyをインクルードしているだけです。続いてアプリケーション(mnist)直下のurls.pyの設定です。name='upload'),]TemplateViewを使ってTOPページ(index.html)を定義しています。1つは「判定」ボタンが押されたときに呼ばれるuploadのURLパターンを定義しています。URLパターンの設定は以上です。URLの設定については特段難しい点はないと思います。最後にテンプレートの設定です。テンプレートは以下の3つを用意します。1base.html(共通テンプレート)2index.html(TOP画面)3result.html(判定結果画面)1base.htmlまずは共通テンプレートです。全体コードは以下の通りです。src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js"></script></body></html>特段難しい部分はないです。以下の部分でbootstrapのcssとjsファイルを読み込んでいるくらいですね。src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js"></script>2index.html(TOP画面)続いてindex.html(TOP画面)です。ボタンを押してください。color=red>「白」</font>で作成してください。した画像は正しく判定されません。align="left">画像サイズは28*28ピクセルにすると判定確率が高くなります。align="left">画像ファイルは複数同時に選択してアップロードすることができます。align="left">数字(0~9)を手書きしたjpgファイル画像をアップロード後に「判定」ボタンを押してください。color=red>「白」</font>で作成してください。align="left">アップロードされた画像の特徴を解析してAIが数字の0~9いづれかを自動判定します。align="left">チュートリアル簡易用の学習モデルのため、上記以外のルールで作成した画像は正しく判定されません。align="left">画像サイズは28*28ピクセルにすると判定確率が高くなります。align="left">画像ファイルは複数同時に選択してアップロードすることができます。%}デザイン部分の詳細説明は割愛して、ポイントだけ説明します。以下の部分で、POSTメソッドでupload関数を呼び出すように逆引き設定しています。enctype="multipart/form-data">次に以下のコード。typeをfile、nameをfiles[]に設定しています。views.pyの以下のコードでこのnameに指定したfiles[]を使用しています。request.FILES.getlist("files[]")以下の部分で、jpgファイル以外をアップロードした場合にエラーメッセージを表示させています。%}以下は、サンプルの手書き数字画像をWEZ上に表示しているだけです。-->以上でindex.htmlは完了です。3result.html(判定結果画面)最後にresult.htmlです。}}</font></b>です。}}</font></b>です。%}まずは最初の3行。extendsで共通テンプレートを拡張します。staticはサンプル例の画像ファイルを表示させるのに利用します。content以下に結果を表示するコードを書いていきます。%}続いて以下の部分。}}</font></b>です。}}</font></b>です。%}という感じで、views.pyから受け取った画像データと推論結果が格納されているresultオブジェクトを受け取り、結果を表示していきます。{{data.0}}で画像ファイルを取り出し、{{data.1}}で推論結果情報を取り出します。画像データの表示部分は、以下の通りimgタグに「data:image/jpg;base64,」をつけます。src="data:image/jpg;base64,{{data.0}}">以上で完了です。これで、「http://127.0.0.1:8000/mnist/」にアクセスして以下のような画面が表示されればOKです。今回のWEBアプリを作成する際に参考にした書籍を紹介しておきます。楽天市場調べ-詳細)Amazon楽天市場Yahooショッピングこの書籍は、DeapLearningの基礎的な説明から始まり、実際のコードを理解する上で必須となるベクトル等の数学的概念、この記事でもでてくるkerasのImageDataGeneratorの扱い方も説明されていて、これまで購入した書籍のなかで一番のお勧めで、現在も学習に使っています。Djangoの書籍は、やっぱりakiyokoさんの以下の書籍がお勧めで、私も2冊とも所有しています。教科書《実践編》あとは、naritoさんのblogもよく利用させて頂いております。(質問にも丁寧に回答していただけます!)まとめ後半はちょっと駆け足になってしまいましたが、MNISTデータを使った前処理~学習~ウェブアプリ化まで一通り説明しました。今回は簡易的な学習モデルなので、28x28以外の画像サイズを与えた場合はちょくちょく判定を誤りますが、通常のMNISTチュートリアル通りにやるよりは多少汎用性があると思います。あとは、これをベースとして以下のようなアプローチも試していきたいな~と思っています。・データ拡張で精度をアップさせる。・背景が黒だけでなく、白の場合等でも正確に判定できるモデルを作る。・ネットワークのモデルをいろいろチューニングしてみる。Dropout等)・手書き数字画像ではなく他の事例への応用を試してみる。与えた際に、回答として「これは星です。「これは白い四角です。」といった回答をするアプリを作ってみる。例2)違反品と正常品の画像を入力データに与えて学習させておき、新規のデータが来た場合にその画像が違反品かどうかを自動判定させる。これはメルカリなんかで実装されている違反品の出品を投稿された画像から自動検知させるような例ですね。こんな感じで、今回のMNISTデモアプリをベースにいろいろと発展させていけるのではないかなと思っています。※この記事が良かったと思う方はTwitterフォロー(shiny)とリツイート頂けると嬉しいです!FacebookTwitterGoogle+はてブPocketFeedlyこの記事を書いた人siny現在の仕事は社内SEのお仕事です。趣味でDjango,Python,機械学習、ディープラーニングなどをやってます。CLIの使い方こんにちは。CLIの導入と簡単な使い方についてご紹介します。C...PythonPythonで仮想通貨レートのスクレイピングと異常検知入門こんにちは。最近、Pythonでスクレイピングの勉強を始めたのですが、思った以上にいろんなことが簡単にできることがわかり、ワ...DjangoDjangoでロギング(logging)を行う方法こんにちは。この記事では、Djangoにおけるロギング方法についていくつかの方法をまとめてみました。DjangoCongr...Pythonたったの3ステップでJupyterNotebookをブラウザで利用できる環境...こんにちは。この記事では、JupyterNotebookをWEBブラウザ上から利用できる環境構築の手順をご紹介します。通常...PythonDjango+Python+スクレイピングで書籍情報管理サイトを作ってみたこんにちは。pythonスクレイピングの書籍を購入して勉強していますが、スクレイピングを利用すると前々からあったらいいなと思...Pythonデータ分析入門におすすめなpythonライブラリ(コーディング不要)こんにちは。この記事では、データ分析入門におすすめなpythonライブラリーを紹介します。pandas_profiling...DjangoDjagnoで複数フォームを1テンプレート内に表示する方法こんにちは。notebookを使う方法こんにちは。Notebookを利用する方法を紹介します。