Raspberry Pi上でTensorFlowで簡単にディープラーニングを試せるツール「tensorflow-pi」でロボホンの幻の顔認識機能に挑戦してみた

f:id:karaage:20170726015040j:plain:w640

Raspberry PiとTensorFlowを使ったディープラーニング開発環境

 以下の記事でRaspberry PiとTensorFlowを使ったディープラーニングの開発環境の構築方法を紹介しました。

 記事の最後の方に、自前データの学習から、学習したニューラルネットワークで判別まで実施できる自前のパッケージ「tensorflow-pi」を紹介させていただきました。

 ただ、READMEだけ見ても、意味不明な英語で良くわからないと思いますので、今回は実例を交えながらこのソフトの使い方を紹介しようと思います。

 例題ですが、以前ネットで話題になった「ロボホン」の幻の顔認識機能があります。詳しくは以下参照下さい。

 開発決定!というニュースは話題になったものの、その後続報がとんと聞かれません。そもそも技術的に不可能なんじゃという噂も聞こえてきたりしました。

 奇しくもロボホンとRaspberry Piは、ARMベースの1.2GHzのクアッドコアCPU、カメラ 800万画素と性能的には似通っています。ロボホンのOS(Android)上で、TensorFlowの学習データも扱えるらしいので、Raspberry Piで実現できれば、ロボホンで同じことができる可能性は高そうです。ということで、Raspberry Piで顔認識機能開発して、ロボホンで顔認識が実現できるかどうかをRaspberry Piでプロトタイピングして事前検証してみることにしました。そんなわけでロボホンは使いません、タイトルで期待した方はすみません!(もしロボホン手に入ったらハックしてみたい!)。

 そして、一応最初に書いておきますが、私は機械学習やディープラーニングの専門家でも何でも無く、趣味でやっているだけですので、内容に不正確な箇所が含まれる可能性あることはご容赦下さい(自分なりには頑張っているつもりですが)。勉強中の身ですので、もし気づかれた方は、優しく教えていただけたら嬉しく思います。

 あと、たいした結果得られなかった割に、長くてマニアックなので興味ある方のみご覧下さい。これほんと。

顔認識機能の開発

仕様定義

 ここらへんは、詳しい仕様が決まっているわけではないのと、ここではあくまでディープラーニングの実験が目的なので、以下のざっくり仕様とします

  • ハードウェアはRaspberry Piと専用カメラモジュールを使用
  • 学習する対象は、とりあえず家族3人(増やすことは可能にしておく)
  • カメラで定期的に撮影し、人の顔が撮影されたら誰かを判別して教えてくれる
  • 学習、判別は基本Raspberry Pi上で行う
  • 顔写真の収集及び前処理は手動でやる(ここの自動化は後で考える)

 製品のことを考えると、本当はここが一番大切なんですけどね。

顔認識機能の概要

 顔認識機能の概要に関しては、下図のようになります。 f:id:karaage:20170811163405j:plain:w640

 大きく、学習と認識の2つのフローに分かれます。学習フローでは、認識したい人の顔が含まれた大量の写真を、顔検出して切り抜くソフトで顔写真を切り出します。そして、集めた顔写真を誰の写真か分類(ラベル付け)してやった上で、学習を行い学習モデル(ニューラルネットワーク)を得ます。学習フェイズの作業は、1部を除くとほぼ手動の作業になります。

 認識のフローでは、Raspberry Piで撮影した写真を、学習のときと同じ要領で顔検出+切り抜きを行い、切り出した顔写真を学習したニューラルネットワークを使い判別します。認識に関しては、プログラムを開始したら、基本的に自動で繰り返し行われます。

Raspberry PiとTensorFlowの環境構築

 まずは、以下記事を参考にRaspberry PiにTensorFlowの環境を構築します。

 次に、自前データの学習から判別までできる自作ソフトtensorflow-piを、以下のGitHubのリポジトリからダウンロード(clone)します。

 具体的には、Raspberry Pi上のターミナルで以下コマンドを実行してダウンロード下さい

$ cd
$ git clone https://github.com/karaage0703/tensorflow-pi
$ cd tensorflow_pi

 GitHubって何?って人は、以下を参照して下さい。

サンプルデータ(入力写真)取得

 自分と愛する妻と娘と自分の顔写真が入ったサンプルデータを集めます。ここは、Raspberry Piで撮影して集めてもよかったのですが、色んな条件のものがあった方がよいだろうということで、過去写真などを活用することにしました。

 バックアップに使用していたflickrやGoogleフォトから探してみます。それぞれのサービスとも顔写真を自動で検出する機能を持っています。詳細は以下参照ください。

 flickrはカメラロールのmagic viewから、複数選択して一括ダウンロードできます。

 GoogleフォトはGoogle フォトのアルバム->人物で、一つずつShift+Dでダウンロードできます。

 使ってみた感触としては、Googleフォトが個別の人物まで識別してくれるので一番良い感じでした。flickrは一括ダウンロードがあるのは良いのですが、ダウンロードが死ぬほど重いです(タイミングによっても変わるかも)。

 Googleフォトは、サイズを制限すれば容量は無制限なので、Googleへのアップロードに抵抗がなければ、手持ちの画像を全部アップロードしてGoogleフォトに分類してもらうのが、一番手軽な顔写真をゲットする方法かなと感じました。

 こうして大量のフリー素材が集まりました。

f:id:karaage:20170701103525p:plain:w640  サンプルはイメージです

 今回の記事、ネット非公開の私の家族写真の代わりに、イメージ画像として、フリー素材のロンスタ(id:lonestartx) さんの写真を使わさせていただいております。いつもありがとうございます。

顔の切り出し

 顔写真を収集したら、次は顔の部分に限定して切り出してやる必要があります。以前作った顔検出のプログラムをベースに顔を切り出すソフトを作成しました。顔検出に関しては、以下参照下さい。

 今回は、上記のプログラムのままでは、あまりに検出精度が悪かったので、色々なサイトを参考にして目の位置などを判定に加える等して精度向上し、以下のpythonの画像処理プログラム集のリポジトリにface_crop.pyという名前で追加しました。参考にさせていただいたサイトは、本記事の末尾からリンクを貼っています。

 使い方は、READMEにも書いてありますが簡単に解説します。以下は、MacかLinux(Raspberry Pi含む)のターミナルでの操作を前提として記載していますのでご注意下さい。

 環境準備は以下参照にセットアップして下さい。

 次に、顔を切り出したい画像のあるフォルダに移動したあと、ターミナルで以下コマンドを実行してプログラムをコピーします。

$ wget https://raw.githubusercontent.com/karaage0703/python-image-processing/master/face_crop_simple.py https://raw.githubusercontent.com/karaage0703/python-image-processing/master/face_crop_simple-all.sh
$ chmod 755 face_crop_simple-all.sh

 あとは、以下を実行すれば、顔写真がface_imagesディレクトリに自動的に切り出されて行きます。

$ ./face_crop_simple-all.sh

 以下のような感じです。

f:id:karaage:20170701110114g:plain:w640
 ※最新の顔切り出しソフトでは、多少表示が異なります

 切り出した顔は、カテゴリ(今回だと人毎)にフォルダ分けして、Raspberry Piのtensorflow-pi/data/以下にまとめていきます。例えば karaage lemon necogistaだと以下のように配置します。

tensorflow-pi
 |- data/
     image_data/
       |--- etc/face_etc_01.jpg, face_etc_02.jpg, ...
       |--- karaage/face_karaage_01.jpg, face_karaage_02.jpg, ...
       |--- lemon/face_lemon_01.jpg, face_lemon_02.jpg, ...
       |--- necogista/face_necogista_01.jpg, face_necogista_02.jpg, ...

 フォルダ名、ファイル名は何でもOKです(ただし、日本語とか特殊な記号はダメかも)。

 PC上でみると以下のようなイメージです。 f:id:karaage:20170809143523p:plain:w640

 ちなみに、etcというのは、顔以外のものが検出された画像(ノイズ)を入れています。これを入れることで、実際に使う際、顔検出に失敗したとき無理やり誰かに当てはめることなく、etc(顔以外のもの)として判定することで、誤認識を減らす効果を期待しています。  以下はetcカテゴリの写真の1例です。

f:id:karaage:20170809144716j:plain:w480

f:id:karaage:20170809144725j:plain:w480

 全然顔じゃないですね。

 今回は、それぞれのクラスに30枚程度の写真、合計120枚程度の写真を集めました。

データのN増し

 ディープラーニングで学習させる際は、データをN増し(水増し)した方がよいという話をよく聞くので、N増しするソフトもtensorflow-piに用意しました。ソフトは、自作しようかと思ったのですが、すでに便利なソフトを作っている人が多数いたので、以下のサイトなどを参考にさせていただきました。ありがたやありがたや。

機械学習のデータセット画像枚数を増やす方法 - Qiita

 ただ、実は今回の場合はN増し前の120枚程度の画像で学習わりとうまくいったので、最終的にはN増ししませんでした。N増しの効果は、もっとクラスが多いと必要になってきそうなので、別の課題で改めて検証したいなと思っています。

 N増しをする方法は、N増ししたいフォルダに移動して、コマンドを実行するだけです。例えば、~/tensorflow-pi/data/image_data/karaageのデータをN増ししたい場合は以下です。

$ cd ~/tensorflow-pi/data/image_data/panda
$ ../../increase_picture-all.sh

 実行するとtrans_... というN増しデータが大量に生成されていきます。

 これをN増ししたい全てのフォルダで行います。イメージ的には、この1つの写真が

f:id:karaage:20170709220722j:plain:w640

 以下のようにN増しされます。

f:id:karaage:20170808151956p:plain:w640  まさに地獄!!

 ちなみに、TensorFlowでは、プログラム上で画像を簡単にN増ししてくれるような機能も用意されているので、それを使うのも簡単ですが、TensorFlow以外のフレームワークを使いたいときのことを考慮したのと、極力前処理で何をやっているか、自分で把握しておきたかったので、あえて独立したスクリプトを用意しました。

 TensorFlowのN増しに関して知りたい方は、以下のTensorFlowのcifar10という画像認識のサンプルプログラムのdistorted_inputsあたりの関数が参考になると思います。

ラベル作成

 次に面倒なラベル付けですが、これも一括でできるスクリプトを用意しています。以下実行するだけです。

$ cd ~/tensorflow-pi/data
$ python make_train_data.py image_data

 これで /tmp/tensorflow_pi/ 以下に labels.txt , train.txtといったファイルが生成されます。また、最後にclass number= 4といった表示がされます。これは、分類するクラスの数です。今回は、3人の顔 + その他の合計4クラスに分類されるので4が表示されます。

 ~/tensorflow-pi直下のcnn.pyというプログラムは、分類するクラスの数を直接入力してやる必要があります。5行目をみるとNUM_CLASSES = 4となっているので、今回は変更不要ですが、もしクラスの数が4以外だったらその数に書き換えてやって下さい(できればここは自動でやりたいので、誰かこっそり良い方法教えていただくか、GitHubにPRいただけると助かります)。

 make_train_data.pyは、id:shi3z さんのdeelというChainerのラッパープログラムのツールの一部を活用させていただきました。Chainer用のツールではありますが、TensorFlowにも活用できる素晴らしいツールです。めちゃめちゃ感謝です。

GitHub - uei/deel: Deel; A High level deep learning description language

学習

 いよいよ学習です。といっても、ディレクトリ移動してコマンド1発です、簡単。具体的には以下です。

$ cd ~/tensorflow-pi
$ python train.py

 しばらく待つと、学習が進んでいきます。

step 0, training accuracy 0.144286, loss 39156.7
step 1, training accuracy 0.158571, loss 24045.2
step 2, training accuracy 0.200714, loss 16943.1
step 3, training accuracy 0.330357, loss 11338.4

 lossが下がってaccuracyが上がっていけばOKです。lossnanになった場合は、学習失敗していますので、やり直してください。

 今回は、3人+その他(etc)の4カテゴリで約120枚の画像で学習しました。このくらいだと、Raspberry Piでも30分程度で学習できました。step 200まで行くと学習が終わります。最後にかかった時間と認識率が出てきます。

結果は以下です。

step 198, training accuracy 0.988095, loss 3.84672
step 199, training accuracy 0.988095, loss 3.51081
elapsed_time:1472.91347504[sec]
test accuracy 0.961538

 最終的に認識率は96%と言っていますね。良すぎじゃない?本当!?

 30分も待ちきれないというせっかちな人は、MacやLinuxマシンを使って同じことをしましょう。MacやLinuxでの環境の構築方法は以下参照下さい。

 参考までに、以下くらいのスペックのCorei5を積んだMac Book Proで実行すると 3分程度でした。

$ system_profiler SPHardwareDataType
Hardware:

    Hardware Overview:

      Model Name: MacBook Pro
      Model Identifier: MacBookPro12,1
      Processor Name: Intel Core i5
      Processor Speed: 2.7 GHz
      Number of Processors: 1
      Total Number of Cores: 2
      L2 Cache (per Core): 256 KB
      L3 Cache: 3 MB
      Memory: 16 GB

 他、XeonのCPUとNVIDIA Quadro積んだ以下程度のスペックのワークステーションを借りて試してみたのですが、CPUで1.5分、CUDA入れてGPU使うとなんと20秒でした。というか、GPUとか何も意識してプログラム組んでないのにちゃんと早くなるんですね、TensorFlow凄い。並列化とかしたら、もっと早くなるんでしょうかね。

$ lscpu
Architecture:          x86_64
CPU 操作モード:   32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
コアあたりのスレッド数:2
ソケットあたりのコア数:4
Socket(s):             1
NUMA ノード数:     1
ベンダー ID:       GenuineIntel
CPU ファミリー:   6
モデル:             94
Model name:            Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz

 学習にかかる速度差は、Raspberry Piと一般的なマシンのCPUだと10倍、ちょっとしたGPU積んだマシンだったら100倍くらい違うという印象ですね(もちろん条件によって変わってきますのであくまで目安です)。

Tensor Boardによる可視化

 TensorFlowにはTensor Boardという可視化ソフトが付属していて、学習の様子やニューラルネットワークの構造などを可視化することが可能です。Raspberry Pi上で学習している場合は、Raspberry Piで以下コマンドを実行して下さい。

$ tensorboard --logdir=/tmp/tensorflow_pi/

 あとは、ifconfig等で自分のIPアドレスを調べて、ブラウザで<ip address>:6006にアクセスすれば可視化情報が見れます。例えばIPアドレスが192.168.0.10だったら192.168.0.10:6006のアドレスにアクセスしましょう。

 ブラウザはRaspberry Pi上のChromeブラウザでアクセスしてもOKですし、ネットワークに繋がっている他のマシンのブラウザでアクセスしてもOKです。ただ、MacのSafariは私の環境ではうまく表示されなかったので、ブラウザはFireFoxかChromeがよいかもしれません。

f:id:karaage:20170725234109p:plain:w640
 Raspberry Pi上でTensor Boardを動かしている様子

 ただ、Tensor BoardはRaspberry Pi上で動かすとかなり重いので、あまり実用的ではないかもしれません。その場合は、matplotlibで可視化するのが軽くて便利です。

matplotlib/pandas による可視化

 train.pyを使って学習すると、学習の様子が/tmp/tensorflow_pi/train_graph.csvというファイルに書き出されています。これを可視化するには、以下コマンドを実行して下さい。

$ cd ~/tensorflow-pi
$ python plot_graph.py

 以下のように、学習の様子が表示されます。このようにlossが下がりaccurarcyが上がっていると、正常に学習できていることになります。

f:id:karaage:20170813010936p:plain:w640

 matplotlib/pandasの可視化に関しては、以下の記事を参照下さい。

 matplotlibがどうしてもよく分からない、苦手という人は、/tmp/tensorflow_pi/train_graph.csvをエクセルなどの表計算ソフトで好きにグラフにしてもOKです。

判別テスト

 これで90%くらいの精度で認識できることが分かったわけですが、なんか嘘くさいですよね。信じられますか?(私は信じられません)。ほんとにちゃんと学習できているか、新しく撮影した顔写真でテストしてみたいですよね。もちろんそんなテスト用のプログラムも用意しています。

 まずは、テストしたい顔写真を、顔の切り出しのところで行ったのと同じ要領で顔を切り出します。写真は、今回は~/tensorflow-pi以下にtest.jpgというファイル名でおきます。後は、以下コマンドで判別できます。今回は私の写真を使いました。

$ cd ~/tensorflow-pi
$ python predict.py test.jpg 

 実行すると、以下のように表示されます。

2017-08-09 22:01:12.554877: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
2017-08-09 22:01:12.554923: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
2017-08-09 22:01:12.554936: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX2 instructions, but these are available on your machine and could speed up CPU computations.
2017-08-09 22:01:12.554946: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use FMA instructions, but these are available on your machine and could speed up CPU computations.
karaage

 ちゃんと最後にkaraageって出ている!凄い!賢い!

 判別されるまでの時間、マシンによってはそこそこ時間かかるかもしれませんが、ほとんどはTensorFlowの読み出しにかかる時間のはずです。今回使用したくらいの学習モデルであれば、Raspberry Piでも実時間(1,2秒程度)で認識できるはずです。

顔認識実験

 テストできたら、いよいよRaspberry Pi上のカメラで顔認識をさせてみましょう。Raspberry Pi以外のマシンで学習した場合は、学習したモデルのデータとラベルデータをRaspberry Piにコピーしておいて下さい。

 具体的には、~/tensorflow-pi/data/model 以下のすべてのファイル(checkpoint , model.ckpt.data-00000-of-00001, model.ckpt.index, model.ckpt.meta, labels.txt)となります。コピーしたら、Raspberry Piにカメラモジュールを接続して、カメラを撮影できる状態にしておいて以下を実行しましょう(Raspberry Piでカメラ撮影する方法は、ここでは詳細は省略しますのでご自身で調べて下さい)

 準備ができたら、以下コマンドを実行するだけです。

$ cd ~/tensorflow-pi
$ python face_recog_pi.py

 このプログラムでは、Raspberry Piのカメラで撮影して、顔検出を実施し顔検出に成功したら顔を切り出し、顔認識を行うということを、ほぼリアルタイムで実施してくれます。以下が実行の様子です。

f:id:karaage:20170810133738g:plain:w640

 Raspberry Piのカメラで、私(karaage)の顔と、娘(lemon)の顔を交互に見せると、ちゃんとそれっぽくリアルタイムに認識してくれます。

 ただ、結構誤認識は多い感じでした。カメラにアップで顔をうつすと割とうまくいくのですが、カメラからの距離が離れるほど間違えてしまうようです。感覚的には精度は6〜8割といったところでしょうか。こういった実際のカメラに組み込んだときの精度の評価は難しいですね。誤認識の要因は色々考えられます。

  • 学習したデータと実際にテストしたデータの違い(Raspberry Piカメラとそれ以外のカメラ、撮影場所)
  • 写真の解像度不足(リアルタイムで顔検出するため、解像度落として保存している)
  • データ不足 or 過学習
  • プログラムにバグがある

 実用段階にもっていくためには、上記の要因を1個1個つぶしていく必要がありますね。もちろん他にも問題は山積みと思います。

ロボホンの幻の顔認識機能は実現できるのか?

 はっきり言ってしまえば、この実験だけでは良く分かりませんでした(しょうもない結論ですみません…)。ただ、少なくとも実際に一般ユーザーが使えるようなものを作るには、大きな課題が沢山ありそうだなということは分かりました。具体的には以下です。

  • 教師データの集め方
  • 性能の問題
  • 学習の問題

 教師データは、一般ユーザに顔を切り出して用意してもらうわけにはいかないので、色々なパターンの顔写真をロボホンに撮らせるような工夫が必要なのですが、学習に耐えれる沢山の写真をユーザに撮影してもらうというのは、中々難しいかなと思います。

 また、性能の問題として、認識率以外の問題として、顔が正面を向いていないとうまく検出できなかったりもします。解決策として、検出までディープラニングにやらせる方法もありそうですね(そういう技術はある)。ただ、それはそれで色々大変そうです。

 逆に、実験する前に懸念していた学習時間は、とりあえず家族分くらいなら思ったほどかかりませんでした。ただ、10人、20人と増えていくと計算量が比例して増えていくのと、ネットワークを変えないとうまく学習できないといった問題が出てきそうです。実際、101クラスに分類するCaltech101という有名なデータセットでの学習を試してみたのですが、ニューラルネットの構造を変更しないとうまく学習できませんでした。Caltech101はtensorflow-piを使って以下コマンドでダウンロードできるので興味がある方はネットワークを変えて色々試してみてください。

$ cd ~/tensorflow-pi/data
$ ./getCaltech101.sh

まとめ

 ロボホンの幻の顔認識機能にディープラーニングで挑戦してみました。わざわざ私がやるまでもなく、シャープの優秀なエンジニアさんなら既にこのくらいの実験はとっくに済ませていると思います。そして、あまりの難易度に絶望しているのじゃないかな、と勝手に同情しています(笑)もしこの機能が高い性能で実現したら、開発したシャープさんのエンジニアには惜しみない賞賛を送りたいなと思います。

 ディープラーニングというと、なんでもできるような気がしてしまいますが、限られたリソースで有用なアプリケーションを作ろうとするとまだまだ課題があることがわかります。今後は、そういった実用的な部分の技術の発展も重要になっていくのかもしれませんね。

 最後に、今回実際に実験してみてわかったことのまとめです。

  • 教師データ集めるのが大変。とにかく大変
  • ハイパーパラメータは重要(特に学習率)
  • ディープラーニングのフレームワークは色々あるが、自前データの活用するには、結構自分で作らないといけないものが多い
  • Raspberry Piでディープラーニング結構色々できそうだけど、モンスターマシンは欲しい

 教師データ集めは、実際にやっている人に聞くと誰しもが言うのですが、これが本当に大変です。前処理まで含めて言うならこれがほぼ全てかもしれません。今回だと、まず顔検出して切り出すソフトから作り始めましたからね。

 もちろんニューラルネットワークの構造だったり、学習率といったハイパーパラメータも重要です。最初、全然学習がうまくいかなかったのですが、学習率を変えるだけで学習が収束するようになったりして、なかなか面白かったです。学習率の値は、train.pyの18行目のlearning_rateを変えることで変更できますので、興味あれば色々試してみて下さい。

flags.DEFINE_float('learning_rate', 1e-5, 'Initial learning rate.')

 クラスの数だったり、解く問題によって最適なネットワークが変わってくるのは、先ほど述べた通りですね。

 最後に、Raspberry Piでディープラーニングですが、個人的には結構可能性を感じました。世の中にあるディープラーニングのstate-of-artなモデルは、とにかく多くのクラスに正確に分類することを目指して、馬鹿でかいニューラルネットワークになっていることが多いのですが、Raspberry Piで動くような小さなニューラルネットワークでも、用途によっては十分な精度を出せそうなので、工夫すればもの凄い安く身近な問題を解決する超小型な人工知能が作れてしまうかもしれません(キュウリの仕分け機もその一例ですね)。

 一方で、本格的にディープラーニングのパラメータチューニングや、ニューラルネットワークの設計をしたいとなると、どれだけ試行錯誤できるかが勝負になってくるので、Raspberry Piで物足りなくなったら、入門は卒業してGPU積んだマシンの購入やクラウドなどが必要になってくるのかなと感じました。ちなみに大量のデータ学習させようとするとGPUのメモリも重要ですね(Caltech101のデータを2GBのGPUで学習させようとしたらメモリが溢れてエラーになりました)。

Raspberry Pi + Chainerで同じようなことを試したい人へ

 今回私はRaspberry PiとTensorFlowの組み合わせで顔認識を試しましたが、Raspberry PiとChainerの組み合わせで同じようなことを、私よりずっと前に試している人がいました。実際のアプリケーションは以下のような感じです。ChainerでもTensorFlowと同様に、小さめのニューラルネットワークならリアルタイムな認識はできるようですね。

IoT司書育成 中間報告

 顔認識のソフトのリポジトリは以下になります。

 コードの書き方、再学習の仕方、レポートのまとめ、ドキュメントの書き方など全てが参考になりました。オススメです。

関連記事

参考リンク

TensorFlowでアニメゆるゆりの制作会社を識別する - kivantium活動日記

tensorflow/mnist_deep.py at r1.2 · tensorflow/tensorflow · GitHub

TensorFlow の "AttributeError: 'module' object has no attribute 'xxxx'" エラーでつまづいてしまう人のための移行ガイド - Qiita