数値解析系

2017年5月15日 (月)

HPC 夏・秋キャンペーンちらし!今回のキーワードはやはり”ディープラーニング”

年に3回ほどのSCSKキャンペーンちらし。夏を前にやってまいりました。

Scsk170503

今年のトレンドはやはり”ディープラーニング”。NVIDIA製GPU搭載のHPCが紹介されてます。

そして、隠れキーワードとして”AMD”も登場。

Scsk170501

とはいえ、まだワークステーション/HPC向けのAMD CPU”Naples”は発表前。同時期に発表予定のIntelの次世代コア”Skylake”と合わせて後日情報を送ってくれるとのことです。

AMDの新コアにIntelがどういう攻勢をかけてくるかが楽しみですよね。システム提案側としては、なによりも安くなってほしい・・・

Scsk170504

まずはワークステーションから。

最大22コア×2=44コア88スレッド、メモリは最大1TBまで搭載可能なHPのZ840というワークステーション。

64GBでこのお値段です。

その下に書かれてますが、Windows 7へのダウングレードが今年の10月で終了。それ以降は7をインストールすることが不可能になるそうで。

実はCAE界隈ではまだWindows 10がだめなところがあって、未だにWindows 7へのダウングレードが必要な環境が多いんです。てことで、今年の10月までにソフトウェアベンダーさんは10に対応しなきゃいけないはずですけど、間に合うんでしょうかね・・・

Scsk170502

さてこちらが最近力を入れているディープラーニング用マシン。

Tesla P100 16GB(GPUコア数3584)を一基搭載。これでお値段約300万円。

スターターキットといいますけど、結構な計算能力。

Scsk170505

これにNVIDIA CUDA Toolkit、cuDNNをプリインストールし、TensorFlowをつけてこのお値段だそうです。

Scsk170506

GPUボードはこの3年で60倍もの高速化。まだまだ伸びしろがあるようです。

NVIDIAもうまくこのディープラーニングブームに乗れたものです。果たしてIntelなど他社の入り込む余地はあるんでしょうか?

昨年まではCPUのコア数くらいしか見るべきところがありませんでしたが、今年はAMDのRyzenのHPC版とGPUが盛り上げてくれてます。再び科学技術計算の世界があわただしくなりそうですね。

玄人志向 ビデオカードGEFORCE GTX 1050Ti搭載 GF-GTX1050Ti-4GB/OC/SF

2017年5月 8日 (月)

誰でも人工知能なガジェットが作れる!?GoogleからAIのDIYを支援する”AIY Projects”始動!

第1弾はRaspberry Pi 3用のボイスキット”Voice Hardware Accessory Top”をリリースだそうです。

Google、誰でも人工知能プロダクトを制作できる「DIY AI」を目指すプロジェクト「AIY Project」を発表。第一弾はボイスキット | Seamless

公式サイト:AIY Projects

Googleが発表したこの”AIY Projects”とは、自身の問題解決にAIを使いたい人を支援し、だれでもAIプロダクトを作れるようにするプロジェクト。DIYとAIをひっかけて”AIY”のようです。

で、第1弾のこのボイスキット、マイク、スピーカー、ボタン・スイッチ類が付いたRaspberry Pi用HATに段ボール製のケースを組み合わせたキット。そして、これらを使うための専用のOSイメージをダウンロードして使います(専用イメージはこちら)。

製作手順・動作テスト方法はここ(Voice Kit | AIY Prjects)にあります。はんだごても不要で、1時間半くらいで作れるとか。楽ですね。

”誰でも”と謳われてますが、まず上のドキュメントが読める最低限の英語力、そして多少のLinux・プログラミング知識は必要かと思われます。

ところで、これってどうやって入手するんでしょうか?

下記記事を見る限り、Raspberry Piの公式雑誌「MagPi」の最新号を入手すると付録についてくるそうです。

このGoogle HomeのDIYキットはRaspberry Piとボール紙でできた魔法のボックス | TechCrunch Japan

Raspberry Pi 3は別途必要。

上の動画ではいきなり会話してますが、どうやらGoogle Assistant SDKやGoogle Cloud Speech APIあたりを使ってるようです。

人工知能ってやつを使って何かをさせたいという願望がある方なら、要注目です、AIY Projects。第2、第3弾は何が出てくるんでしょうか?ちょっと楽しみです。

Raspberry Pi 3 MODEL B

2017年4月15日 (土)

OpenCVでLBP特徴を使った”物体検出器”を作成してみた

TensorFlowによる”物体認識”と、ネット上に存在するアニメ顔検出器を組み合わせて「けものフレンズの動画からフレンズさんの顔を検出するやつ」を作ってみましたが。

自分の認識させたいものを検出するためには、この”物体検出器”ってやつを自作できないといけません。

てことで、物体検出器を作ってみることにしました。

参考にしたのはこちらのサイト。

OpenCVで物体検出器を作成する① ~基礎知識~ - 技術者ブログ

ここの⑤、⑥にある手順を参考にすれば完成・・・するはずですが、こちらに載ってるやり方そのままでは動かなかったので、ちょっと工夫してます。

なお、前提は

・たくさんの正解画像から検出器を作成(上のリンクは正解画像1枚で作成)

・LBP特徴を用いた検出器を作成

OpenCVだけでHaar-Like特徴、LBP特徴、HOG特徴を用いた検出器を作成できますが、Haar-Like特徴というのは検出率がいまいちらしい(と思ってるだけ?)という印象があるのと、HOG特徴を用いた検出器はそのままでは使えない模様なので、消去法でLBP特徴になりました。

■ 前準備

まず、検出器を作成する作業フォルダを作ります(英数字でスペースを入れてないフォルダ名)。

そのフォルダ内に”cascade”、”pos”、”neg”、”vec”の4つのフォルダを作成。

さらに”cascade”フォルダ内に”ooo”というフォルダを作っておきます。

不要かもしれませんが、以下のOpenCVの検出器作成に必要な実行ファイルを作業フォルダに入れておきます(私の場合はOpenCV 3)。

・ opencv_calib3d310.dll

・ opencv_core310.dll

・ opencv_createsamples.exe

・ opencv_features2d310.dll

・ opencv_flann310.dll

・ opencv_highgui310.dll

・ opencv_imgproc310.dll

・ opencv_ml310.dll

・ opencv_objdetect310.dll

・ opencv_traincascade.exe

私と同様、Anaconda for WindowsにTensorFlowをインストールしている環境なら、これらのファイルは「(Anaconda3インストールフォルダ)\envs\tensorenv\Library\bin」か「(Anaconda3インストールフォルダ)\Library\bin」のどちらかに入ってるはずです。

”pos”フォルダには正解画像を、”neg”フォルダには不正解の画像(正解でなければなんでもOK)を入れておきます。

参考までに、私は”pos”にけもフレ顔画像を1970枚、”neg”に全く違う画像(城やらクラウンやらの画像)を487枚入れました。

■ 正解画像のベクトル作成(opencv_createsamples.exe)

まず、正解画像を入れた”pos”フォルダ内のファイル一覧を作成します。

コマンドプロンプトを開き、”pos”フォルダに移動後、以下のコマンドを実行。

$ dir *.jpg /b /a-d /s > poslist.txt

これでファイル一覧ができます・・・が、そのままでは使えません。

このとき作成される”poslist.txt”は

C:\(作業フォルダ)\pos\358.jpg
C:\(作業フォルダ)\pos\359.jpg
C:\(作業フォルダ)\pos\360.jpg
C:\(作業フォルダ)\pos\361.jpg


みたいになってますが、各ファイル名の後ろに

C:\(作業フォルダ)\pos\358.jpg 1 0 0 64 64
C:\(作業フォルダ)\pos\359.jpg 1 0 0 64 64
C:\(作業フォルダ)\pos\360.jpg 1 0 0 64 64
C:\(作業フォルダ)\pos\361.jpg 1 0 0 64 64


てな感じの数字を入れる必要があります(スペース区切り)。

一つ目の1は不明、2、3つ目の”0 0”は多分画像切り出しの始点座標、”64 64”は終点座標の模様。

私の使った画像はすべて64×64で切り出し不要だったので、上のような表記になります。

ばらばらのサイズの画像だったり、入れた画像の中に認識させたい部分以外が入ってる場合は・・・下記のサイトにあるGUIツールなどを使うしかなさそうです。

OpenCVでの物体検出器作成 - kivantium活動日記

で、作成した”poslist.txt”を作業フォルダ直下(つまり一つ上のフォルダ)に移動し、以下のコマンドを実行します。

$ opencv_createsamples.exe -info poslist.txt -vec ./vec/ooo.vec -num 1970 -bgcolor 255

■ 検出器学習 (opencv_traincascade.exe)

いよいよ検出器の作成開始ですが、その前に不正解画像の一覧を作っておきます。

コマンドプロンプトで”neg”フォルダに移動し

$ dir *.jpg /b /a-d /s > nglist.txt

を実行。

こっちは”poslist.txt”のようにいちいち後ろに何かつけたり、一つ上のフォルダに移動しなくてOKです。

コマンドプロンプトで作業フォルダに移動し、以下のコマンドを実行します。

$ opencv_traincascade.exe -data ./cascade/ooo/ -vec ./vec/ooo.vec -bg ./neg/nglist.txt -numPos 1700 -numNeg 487 -featureType LBP

中身の詳しい説明は省きますが、”-numPos”の後ろには正解画像の数を、”-numNeg”の後ろは不正解画像の数を入れます。

が、正解画像はたしか1970枚のはずなのに”1700”なのはなぜ?

私もよくわかりませんが、ここは大体8割くらいの数字を入れておくものらしいです。

私の場合は1700くらいでようやく動いてくれました。これはケースバイケースかもしれません。

最後の”-featureType”の後ろに”LBP”と入れてます。省略するとHaar-Like特徴で学習されます。

で、学習開始ですが、私の環境で大体1時間くらいかかりました。

終わると”cascade\ooo\”のフォルダに”cascade.xml”というファイルができてます。

これが”物体検出器”本体。

あとはOpenCVによる”アニメ顔”検出の記事に載せているコードの”lbpcascade_animeface.xml”のところを”cascade.xml”に変えて動かすだけ。

----------------------------------------------------------------

さて、上の手順でけもフレ顔検出器を作りましたが、元のアニメ顔検出器に比べていいところ悪いところがそれぞれ。

・ 誤検出が増加(草むらや模様を”顔”と認識する確率が増加)

・ ハシビロコウちゃんなど従来のアニメ顔検出器では拾えなかった顔が検出可能に

画像データがもう少しあると、あるいはopencv_createsamples.exeのパラメータチューニングなどでもう少し検出率を上げることができるかもしれません。そのあたりは今後やっていこうかと。

もっとも、”けもフレ”の顔検出器を作るのが目的ではないので、これをベースに”本業”で試行錯誤していこうかと思ってます。というか、既にやってますが(会社で)。

そういえば今年初めにTensorFlowを使って”ゴキブリ”探知機を作ろうとしてみたという記事書きました。

撮影した画像を全部検索しようとしたので異様に時間がかかる仕組みになっちゃいましたが。

今ならこの「検出器」作って、高速化できますね。

なんならゴキだけでなくムカデなどの害虫をディープラーニングでより認識精度の高い害虫探知機も作れそう。

てことで、ネットで害虫の画像を集めてそういうのを作ろうかと考えたんですが。

Googleの画像検索した時点で

ヴォエ!!

となり、耐えられなくて断念。

ゴキぐらいならなんとかなりそうですが、私的は特に「ゲジゲジ」の画像検索がダメでしたね。あまり見つめると夢に出てきそう。

検出器作成には少なくとも1000枚は欲しいところ。並大抵の精神力では駄目だと悟りました。だれか害虫画像検出器、作ってくれないかなぁ・・・せめてデータセットだけでもいいので・・・

さらに進化した画像処理ライブラリの定番 OpenCV 3基本プログラミング

2017年4月 9日 (日)

今度のItaniumは最後のモデルか!?

”Itanium”といわれてなんのこっちゃかわからない人も多いかもしれません。

2000年前後に登場したIntelの次世代型64ビットCPUですが、x86と互換性がなくて、AMDが出してきたOpteronシリーズに追いやられて、結局Intelも従来のPentium 4に”EM64T”を組み合わせた64ビットCPUを出すことになり、時代の波にのまれて消えたCPU、Intel最大の大コケ・・・というのが私の認識。

私の職場でも一部サーバーとワークステーションに搭載されましたが、Windowsは動かないしLinux上でも動かせるソフトウェアが限られているしで、せっかくの性能を活かせなかった悲劇のCPUというイメージでしたね。

そんなItaniumですが、このほど最新版が出たそうです。

北川 賢一のIT業界乱反射 - 終焉に向かうItanium、コンピュータ業界にもたらしたもの:ITpro

まだ新型が出るというのにも驚きますが、この先のロードパップが全く示されていないため、これが最後じゃないかとのこと。

ついに終わりなんですねぇItaniumも・・・と感無量になるほどの思い入れもないのが悲しいところ。

ライバルのAMDからはRyzenという強力なCPUが出てきたし、そうでなくてもARM系におされ気味な昨今の情勢。

大コケしたCPUにかまっているほどの余裕はなさそうですし、Itaniumを終わらせるのは致し方ないかもしれません。

Intel CPU Broadwell-EP Xeon E5-2630v4 2.20GHz 10コア/20スレッド LGA2011-3 BX80660E52630V4 【BOX】

2017年4月 6日 (木)

大きさ10×2m 重さ500kgの16ビットプロセッサ

サイズの単位を間違えているわけではありません。また、過去の話ではなく、現代の話です。

全長10m、高さ2mの16ビットプロセッサを作り上げた方が英国にいらっしゃいます。

【やじうまPC Watch】個人が自作したサイズ10×2m、重量500kgの超巨大16bitプロセッサ - PC Watch

総重量は500kg。プロセッサ部に使われている15,300個、LEDは8,500個。RAMには27,000個のトランジスタと2,048個のLEDがを使用。最大消費電力は500Wで、大半はLEDの消費電力なんだとか。

内部バスは16ビットですが、外部バスは8ビット。まるで8088のような仕様です。

2014年から2年がかりで製作、現在はイギリスのCenter for Computing historyという博物館に展示されてるんだとか。

なお、動画中 5:50あたりから”テトリス”をプレーする映像もあります。16ビットですから、ちゃんと動くんですね、テトリス。

しかし、16ビットはおろかスマホでさえ64ビットの時代にどうしてこんな大きな16ビットプロセッサをわざわざ作る必要があったのか??

これを作り上げたJames Newman氏曰く、「プロセッサはあまりにも微細になり、内部で何が行なわれているか把握できなくなってしまった。そこで、逆にデータの動きや論理状態が目で見て分かるほど大きく作ろうと思った」なんだそうで。

確かに、今のプロセッサの構造を人の頭だけで理解することはおよそ不可能ですよね。

もっとも、回路が肉眼で確認できるこのプロセッサを見ても、私にはさっぱりですが。

James Newman氏によるMegaprocessorのサイトもあります。

Megaprocessor

基板の一部の写真もちらっと出てます。デバッグも含めると、途方もない作業だったでしょうね。

プロセッサの進化はとどまるところを知らず、最近は若干頭打ち気味とはいえ、まだまだ伸びることは伸びそうです。

ですが、そろそろ一般レベルにはオーバースペックな感じ。多少スペック的に低くても、安価で手軽に入手できるプロセッサが望まれます。それが今のスマホで使われているARM系プロセッサなのかもしれませんけど。

Raspberry PiやArduinoをいじってみて思うのは、これくらいのスペックの方がいろいろ学ぶのに適切なスペックじゃないかということでしょうか。多少制限があってもその方がいろいろアイデアがわいて楽しいものですし。この辺りが安価なコンピュータボードの人気につながっているのかもしれませんね。

Arduino エントリーキット(Uno版)- Physical Computing Lab

2017年4月 5日 (水)

けものフレンズの動画からフレンズさんの顔を検出するやつを無理やり作ってみた

せっかくGeForce GTX1050Tiという最強のフレンズ・・・いやパーツを入手したのと、最近”物体検出”ってやつに興味を持っているため、とりあえずけものフレンズ版顔検出器ってやつを作ってみました。

やったことは、OpenCVによる”アニメ顔”検出の動画ファイル読み込みとアニメ顔検出器と、TensorFlowで「けものフレンズ」の”フレンズ判別器”作ってみたで作成した学習データと判別用コード(cnn_app_56_a.py)の2つコードを無理やり合体して作りました。

あまりにコードが汚いのと、これが私にとって”物体検出”のゴールではないので、あえてコードは載せません(万一リクエストが多ければ公開します)。

なお、これと同じ方法を使った

で、できた動画はこんな感じ。

Kemono

かばんちゃん、サーバルちゃんがちゃんと認識されてます。

本当はgifアニメじゃなくて、ちゃんとした動画を挙げたいところですが・・・YouTubeにアップしたら公開を拒絶されました。

文字がちょっと読みにくいです。この辺りは要チューニングですね。

こうしてみると一見ちゃんと認識しているようですが、別のシーンでは、なぜか草むらやサンドスターを”Lion”と誤認識したり、かばんちゃんの目をコウテイペンギンちゃんと認識したり。思わず笑っちゃう誤認識が多いですね。ちゃんと認識できてるのは7~8割ほどでしょうか。

また、ハシビロコウちゃんはアニメ顔検出器で引っかからないため、認識してくれませんね。このあたりはけもフレ専用の顔検出器を作成するしかなさそうです。

元の録画データは360pですが、これくらいの動画ならほぼリアルタイム以上の速度で処理できてます。

こいつを足掛かりに、実用的に使える物体検出器を作りたいところですね。

さて、物体検出の手法はいろいろとあるようですが。

Deep Learningによる一般物体検出アルゴリズムの紹介 - ABEJA Tech Blog

今回のやり方に、アルゴリズム的にもっとも近いのは”R-CNN”と呼ばれる手法。

検出器に”selective search”を使うというのが今回との違いになるようです。

このselective searchという検出器、物体らしき候補をとにかく拾ってくれるという仕組みで、大体1画像あたり2000枚ほど拾ってくるんだそうで。

その一つ一つをCNNで分類して物体を認識するという手法ですが、1画像で大量の検出処理をかけるため、検出速度が遅いのが欠点。1枚当たり数十秒かかることもあるようです。

てことで、今主流なのは”SSD”と”YOLOv2”という手法。

今”YOLOv2”が使えないかと画策しているところ。

【Darknet】リアルタイムオブジェクト認識 YOLOをTensorflowで試す - Qiita

この辺を参考に攻めているところですが。

問題は、今のところ”darknet”と呼ばれる別のディープラーニング用プラットフォームで学習させないとだめで、しかもその使い方がわからないため頓挫してます。

この辺りはまたいずれ進捗を書いていく予定。なんとか現実的な速度・精度が出る物体検出をものにしたいところです。

それにしても、いくらやっぱり画像認識力は人間の方がはるかに上をいってますね。

よくまあ、これだけの画像を見つけますねぇ。

【けものフレンズ考察】こっそり仕込まれた小ネタのまとめ!建造物、背景、小物類の作り込みがすごい! | まとめまとめ

12話の最後のシーンに瀬〇大橋っぽいものが写ってるとか、あの観覧車はイー〇ス108だとか・・・3話にはすでにこの観覧車が写っているだの、最後の巨大セルリアンはボストンダイナミクス製ロボット”Big dog”に似ているだの・・・普通、気づきませんわ、そんなこと。

2045年には人工知能が人間を超える、いわゆる”シンギュラリティ”が訪れるとされていますが、人間の(この無駄なまでの)洞察力を果たして手に入れることはできるのでしょうか?

ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装

2017年4月 2日 (日)

Google Japanがドイツ・ハノーバーのCeBIT 2017でTensorFlowの事例として”きゅうり仕分け機”などが展示

ドイツのハノーバーで3月24日まで行われていた国際情報通信技術見本市「CeBIT 2017」にて、TensorFlowを用いたあのきゅうり仕分け機が展示されていたそうです。

「TensorFlow」でから揚げ配膳ときゅうりの仕分けを自動化、Googleがアピール - MONOist(モノイスト)

情報通信の見本市というだけあって、Googleが展示すること自体は決しておかしいわけではありませんが、ドイツの展示会にGoogle Japanが展示するというところがちょっと異例だったようです。

確かに、展示するなら欧州のGoogleじゃないかって気がしますが・・・ちなみに展示されたコーナーは日本が構える”ジャパンパビリオン”内。

ところで、”ジャパンパビリオン”が”ジャパリパーク”に見えてしまうのは、きっと私だけではないんじゃないかなぁと推測。以上、余談です。

TensorFlowの活用事例としてはかなり面白いものには違いないですね。ディープラーニングがいかに凄いといっても、実際に活用されているものを見ないとやっぱり実感がわかないですし。

ドイツでもインパクトは強いんじゃないでしょうか?それにしても、ドイツでもきゅうりって仕分けられてるんでしょうかね・・・

他にはから揚げ配膳ロボット」と「ドローンで撮影した写真の解析」というのが展示されていたようです。

日本のアピールになったかどうかは微妙ですが、ディープラーニングに興味を持ってもらうという意味ではいい展示だったんじゃないかなぁと思われます。実際、私もこの事例を知ってTensorFlowに惹かれたようなものですから。

ラズベリーパイ3 (Raspberry Pi 3B made in JAPAN) 技適対応 日本製 5.1V/2.5A ラズベリー財団公式アダプタ 【本体 アダプタ セット品】

2017年3月18日 (土)

IBMが数年以内に汎用の量子コンピュータを公開!?

スパコンの京でさえ何年もかかる計算を短時間で解いてしまうといわれる量子コンピュータ。

より現実的に使える量子コンピュータを数年以内に完成させようとIBMが取り組んでるそうです。

IBM、現行スパコンを超える「汎用」量子コンピュータを数年内に公開へ - PC Watch

ところでこの量子コンピュータですけど、あらゆる計算でスパコン以上の速度が出せると言わけではありません。

量子コンピュータが期待されているのはいわゆる「巡回セールスマン問題」と呼ばれる”組み合わせ最適化”問題を短時間で解くこと。

例えば、日本中にあるすべての都市を最短でまわるためにはどういう順に回ればいいか?という問題をスパコンを使って総当たりで解こうとすると、それこそ何億年もかかってしまうほどの膨大な組み合わせになるそうですが。

これを「量子アニール」を用いて一発で最適解を探し出せるというのが量子コンピュータの特徴、だそうです。

例えばディープラーニングでは多くの教師データを用いて多層のニューラルネットワークを形成するわけですけど、その際の最適化計算もこれを使えばかなり短時間で終わることができる、かもしれません。

量子コンピュータについてめちゃくちゃ詳しいわけではありませんが、組み合わせ問題の複雑さは目の当たりにしているため、量子コンピュータの登場には期待しております。

この量子コンピュータの性能を決めているのが”量子ビット”の数。従来5qubit(量子ビット)だったものが20qubitとなり、汎用にするためにはこれをさらに50qubitにする必要があるようです。

わりと夢物語だった量子コンピュータですけど、だんだん現実的になりつつあるようですね。ただ、従来のコンピュータでは不可能だった複雑な暗号コードを瞬時に打ち破ることも可能になるかもしれないため、悪用される懸念もあるそうです。便利な反面、そういう厄介な事態を引き起こすというのもまた、コンピュータの宿命でしょうかね?

量子コンピュータが人工知能を加速する

2017年3月11日 (土)

TensorFlowの画像認識コードを高解像度化してみた

Re:ゼロから始めるディープラーニング: EeePCの軌跡で宣言した通り、まったりとディープラーニングの勉強を進めてます。

ついでに職場にある私のワークステーションにもTensorFlowをインストールして、CAEがらみの画像認識実験もちょくちょくやっております。

といっても、コードは以下の記事で使用したものをほぼそのまま使ってるだけ。

TensorFlowで”日本のお城”を識別させてみた: EeePCの軌跡

このコード、画像を28×28で読み込んで学習・認識しているため、ちょっと低解像度過ぎるのが難点。

元々MNISTの手書き文字の認識用のためこの解像度でも行けたんでしょうが、私が使うレベルの画像認識にはもう少し解像度が欲しいところ。

ということで、縦横それぞれ倍の56×56に拡張してみました。

ただ、今までのコードの「28×28」の部分を「56×56」にしただけでは、画像認識の精度がかえって下がります。

このため、この辺りの記事を参考に畳み込み層+プーリング層のペアを一つ増やしてみました。

続・TensorFlowでのDeep Learningによるアイドルの顔識別 - すぎゃーんメモ

TensorFlowによるももクロメンバー顔認識(中編) - Qiita

これで高解像度化&認識率アップできます。

元々が「畳み込み層+プーリング層」×2+結合層×2の6層でしたが。

高解像度化に伴い「畳み込み層+プーリング層」×3+結合層×2の8層になりました。

◆学習用コード「cnn_train_56.py」

#!/usr/bin/env python
import sys
import cv2
import numpy as np
import tensorflow as tf
import tensorflow.python.platform

NUM_CLASSES = 7
IMAGE_SIZE = 56
IMAGE_PIXELS = IMAGE_SIZE*IMAGE_SIZE*3

flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_string('train', 'train.txt', 'File name of train data')
flags.DEFINE_string('test', 'test.txt', 'File name of train data')
flags.DEFINE_string('train_dir', '/mnt/c/linux/data', 'Directory to put the training data.')
flags.DEFINE_integer('max_steps', 300, 'Number of steps to run trainer.')
flags.DEFINE_integer('batch_size', 20, 'Batch size'
                     'Must divide evenly into the dataset sizes.')
flags.DEFINE_float('learning_rate', 1e-4, 'Initial learning rate.')

def inference(images_placeholder, keep_prob):

    def weight_variable(shape):
      initial = tf.truncated_normal(shape, stddev=0.1)
      return tf.Variable(initial)

    def bias_variable(shape):
      initial = tf.constant(0.1, shape=shape)
      return tf.Variable(initial)

    def conv2d(x, W):
      return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

    def max_pool_2x2(x):
      return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                            strides=[1, 2, 2, 1], padding='SAME')

    x_image = tf.reshape(images_placeholder, [-1, 56, 56, 3])

    with tf.name_scope('conv1') as scope:
        W_conv1 = weight_variable([3, 3, 3, 32])
        b_conv1 = bias_variable([32])
        h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)

    with tf.name_scope('pool1') as scope:
        h_pool1 = max_pool_2x2(h_conv1)

    with tf.name_scope('conv2') as scope:         W_conv2 = weight_variable([3, 3, 32, 64])         b_conv2 = bias_variable([64])         h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)     with tf.name_scope('pool2') as scope:
        h_pool2 = max_pool_2x2(h_conv2)

    with tf.name_scope('conv3') as scope:
        W_conv3 = weight_variable([3, 3, 64, 128])
        b_conv3 = bias_variable([128])
        h_conv3 = tf.nn.relu(conv2d(h_pool2, W_conv3) + b_conv3)

    with tf.name_scope('pool3') as scope:
        h_pool3 = max_pool_2x2(h_conv3)

    with tf.name_scope('fc1') as scope:
        W_fc1 = weight_variable([7*7*128, 1024])
        b_fc1 = bias_variable([1024])
        h_pool3_flat = tf.reshape(h_pool3, [-1, 7*7*128])
        h_fc1 = tf.nn.relu(tf.matmul(h_pool3_flat, W_fc1) + b_fc1)

        h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

    with tf.name_scope('fc2') as scope:
        W_fc2 = weight_variable([1024, NUM_CLASSES])
        b_fc2 = bias_variable([NUM_CLASSES])

    with tf.name_scope('softmax') as scope:
        y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

    return y_conv

def loss(logits, labels):

    cross_entropy = -tf.reduce_sum(labels*tf.log(logits))

    tf.summary.scalar("cross_entropy", cross_entropy)
    return cross_entropy

def training(loss, learning_rate):

    train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss)
    return train_step

def accuracy(logits, labels):

    correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(labels, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    tf.summary.scalar("accuracy", accuracy)
    return accuracy

if __name__ == '__main__':

    f = open(FLAGS.train, 'r')
    train_image = []
    train_label = []
    for line in f:
        line = line.rstrip()         l = line.split()
        img = cv2.imread(l[0])
        img = cv2.resize(img, (56, 56))
        train_image.append(img.flatten().astype(np.float32)/255.0)
        tmp = np.zeros(NUM_CLASSES)
        tmp[int(l[1])] = 1
        train_label.append(tmp)
    train_image = np.asarray(train_image)
    train_label = np.asarray(train_label)
    f.close()
    f = open(FLAGS.test, 'r')
    test_image = []
    test_label = []
    for line in f:
        line = line.rstrip()
        l = line.split()
        img = cv2.imread(l[0])
        img = cv2.resize(img, (56, 56))
        test_image.append(img.flatten().astype(np.float32)/255.0)
        tmp = np.zeros(NUM_CLASSES)
        tmp[int(l[1])] = 1
        test_label.append(tmp)
    test_image = np.asarray(test_image)
    test_label = np.asarray(test_label)
    f.close()

    with tf.Graph().as_default():

        images_placeholder = tf.placeholder("float", shape=(None, IMAGE_PIXELS))

        labels_placeholder = tf.placeholder("float", shape=(None, NUM_CLASSES))

        keep_prob = tf.placeholder("float")
        logits = inference(images_placeholder, keep_prob)
        loss_value = loss(logits, labels_placeholder)
        train_op = training(loss_value, FLAGS.learning_rate)
        acc = accuracy(logits, labels_placeholder)

            saver = tf.train.Saver()
        sess = tf.Session()

        sess.run(tf.global_variables_initializer())

        summary_op = tf.summary.merge_all()
        summary_writer = tf.summary.FileWriter(FLAGS.train_dir, sess.graph)

        for step in range(FLAGS.max_steps):
            for i in range(int(len(train_image)/FLAGS.batch_size)):

                batch = FLAGS.batch_size*i

                sess.run(train_op, feed_dict={
                  images_placeholder: train_image[batch:batch+FLAGS.batch_size],
                  labels_placeholder: train_label[batch:batch+FLAGS.batch_size],
                  keep_prob: 0.5})

            train_accuracy = sess.run(acc, feed_dict={
                images_placeholder: train_image,
                labels_placeholder: train_label,
                keep_prob: 1.0})
            print ("step %d, training accuracy %g"%(step, train_accuracy))

            summary_str = sess.run(summary_op, feed_dict={
                images_placeholder: train_image,
                labels_placeholder: train_label,
                keep_prob: 1.0})
            summary_writer.add_summary(summary_str, step)

    print ("test accuracy %g"%sess.run(acc, feed_dict={
        images_placeholder: test_image,
        labels_placeholder: test_label,
        keep_prob: 1.0}))

    save_path = saver.save(sess, "./model.ckpt")

◆認識用コード「cnn_app2_56.py」

#!/usr/bin/env python

import sys
import numpy as np
import tensorflow as tf
import cv2

NUM_CLASSES = 7
IMAGE_SIZE = 56
IMAGE_PIXELS = IMAGE_SIZE*IMAGE_SIZE*3

flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_string('analysis', 'analysis.txt', 'File name of analysis data')

def inference(images_placeholder, keep_prob):

    def weight_variable(shape):
      initial = tf.truncated_normal(shape, stddev=0.1)
      return tf.Variable(initial)

    def bias_variable(shape):
      initial = tf.constant(0.1, shape=shape)
      return tf.Variable(initial)

    def conv2d(x, W):
      return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

    def max_pool_2x2(x):
      return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                            strides=[1, 2, 2, 1], padding='SAME')

    x_image = tf.reshape(images_placeholder, [-1, 56, 56, 3])

    with tf.name_scope('conv1') as scope:
        W_conv1 = weight_variable([3, 3, 3, 32])
        b_conv1 = bias_variable([32])
        h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)

    with tf.name_scope('pool1') as scope:
        h_pool1 = max_pool_2x2(h_conv1)

    with tf.name_scope('conv2') as scope:
        W_conv2 = weight_variable([3, 3, 32, 64])
        b_conv2 = bias_variable([64])
        h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)

    with tf.name_scope('pool2') as scope:
        h_pool2 = max_pool_2x2(h_conv2)

    with tf.name_scope('conv3') as scope:
        W_conv3 = weight_variable([3, 3, 64, 128])
        b_conv3 = bias_variable([128])
        h_conv3 = tf.nn.relu(conv2d(h_pool2, W_conv3) + b_conv3)

    with tf.name_scope('pool3') as scope:
        h_pool3 = max_pool_2x2(h_conv3)

    with tf.name_scope('fc1') as scope:
        W_fc1 = weight_variable([7*7*128, 1024])
        b_fc1 = bias_variable([1024])
        h_pool3_flat = tf.reshape(h_pool3, [-1, 7*7*128])
        h_fc1 = tf.nn.relu(tf.matmul(h_pool3_flat, W_fc1) + b_fc1)
        h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

    with tf.name_scope('fc2') as scope:
        W_fc2 = weight_variable([1024, NUM_CLASSES])
        b_fc2 = bias_variable([NUM_CLASSES])

    with tf.name_scope('softmax') as scope:
        y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

    return y_conv

if __name__ == '__main__':

    test_image = []
    test_filenm = []
#    for i in range(1, len(sys.argv)):
#        img = cv2.imread(sys.argv[i])
#        img = cv2.resize(img, (56, 56))
#        test_image.append(img.flatten().astype(np.float32)/255.0)
#    test_image = np.asarray(test_image)
    f = open(FLAGS.analysis, 'r')
    for line in f:
        line = line.rstrip()
        l = line.split()

        test_filenm.append(l[0])
        img = cv2.imread(l[0])
        img = cv2.resize(img, (56, 56))
        test_image.append(img.flatten().astype(np.float32)/255.0)
    test_image = np.asarray(test_image)
    f.close()

    images_placeholder = tf.placeholder("float", shape=(None, IMAGE_PIXELS))
    labels_placeholder = tf.placeholder("float", shape=(None, NUM_CLASSES))
    keep_prob = tf.placeholder("float")

    logits = inference(images_placeholder, keep_prob)
    sess = tf.InteractiveSession()

    saver = tf.train.Saver()
    sess.run(tf.global_variables_initializer())
    saver.restore(sess, "./model.ckpt")

    for i in range(len(test_image)):
        accr = logits.eval(feed_dict={
            images_placeholder: [test_image[i]],
            keep_prob: 1.0 })[0]
        pred = np.argmax(logits.eval(feed_dict={
            images_placeholder: [test_image[i]],
            keep_prob: 1.0 })[0])
        print (test_filenm[i],pred,accr)

一見すると何の進歩もなさそうに見えますが、以前よりちょくちょくパラメータ値が変わってるところがあります。

まず、Anaconda 4.2.0 for Windows(64bit)+TensorFlow 0.12.0でWarningが出てたのを全部修正しました。

また、認識用コードは複数のファイルを読めるようにしました。

analysis.txt」というファイルに認識させたい画像ファイル名を書き込んでおくと、その中にあるファイルをいっぺんに処理してくれます。

相変わらず学習用コードには”教師データファイル名+ラベル”が書かれた訓練用ファイル一覧「train.txt」とテスト用ファイル一覧「test.txt」の2つも必要です。この辺は先の記事を参考に。

早速、これを使って画像認識させてみました。

使ったのはTensorFlowで”日本のお城”を識別させてみた: EeePCの軌跡で使った画像データ。

Castle02

Anaconda for Windowsのコマンドラインで

> python cnn_train_56.py

と入力して実行。

縦横2倍、データ量にして4倍に増えたため、さすがに時間かかります。

うちのメインPC(Corei3 3220 2コア4スレッド 3.3GHz)で300サイクル回すと40分ほどかかりました。以前は数分で終了。データは4倍ですが、時間は4倍以上かかります。

というのもデータ量が増えただけでなく、収束するまでのサイクルも増加。

以前は70~100サイクルも回せば十分だったのが、今回は最低でも150サイクルは必要で、余裕を見て300サイクル回してます。

学習が終了したら、今度は”認識”させてみます。

認識用に用意したこちらの画像。

Tf_casle01

各お城 3枚づつのデータを準備。

それぞれのお城のラベル(0~6)を各ファイル名の頭につけておきました。

この画像ファイル名を一覧にしたファイル「analysis.txt」を準備して

> python cnn_app2_56.py

と実行。

返ってきた結果は

Tf_casle02

こんな感じになりました。

「判定」の黄色に塗った部分が正解だった画像。

横の%でかかれた数字は、それぞれのラベルの判定率。最も数値の大きかったところをオレンジで塗ってます。

黒枠のところにオレンジが収まっているのが正解。ですが、熊本城、犬山城、大坂城でそれぞれはずれが出てますね。

全21枚中、当たりは17枚。正解率 81.0%。

特に”犬山城”のはずれっぷりが目立ちますが、犬山城の画像のうち、2枚だけは学習に使った画像よりちょっと斜め上から見たものを認識させたんです。

天守閣中央に特徴的な屋根の形があるので少々ずれてても認識するんじゃねぇ?と思って入れたんですが、やはりだめでしたね。

犬山城をのぞけば高解像度化のおかげか、まあまあの正解率。実質9割くらいじゃないかなぁと。なかなかやりますね。

ちなみに職場では「畳み込み層+プーリング層」をさらに一つ増やして112×112まで解像度を増やしたコードを作成してます。

ただ、自宅で用意した教師データは64×64になっているため、自宅用は56×56どまり。

実は112×112にしても正解率がかえって下がってしまってるため、現在いろいろとチューニングの真っ最中。うまく行ったら、またブログにて公開します。

ただ人の顔やお城くらいなら、56×56の解像度でも大丈夫っぽいですね。

しかし勉強の途中でコードをいじりだして大丈夫か?と思われそうですが。

ただ、この動くコードというのは、プログラミングを勉強する上では結構大事。

「ゼロから作るDeep Learning」を読みながらこのコードを読むと、例えば”loss”っていう関数が一体何をやってるのか?など理解が進みます。

本を読むだけでは眠くなっちゃいますが、手を動かしてコードを書き換えてみて実際の動きを確認しながら読み進めると、いろいろとわかって面白いです。

「ゼロから作るDeep Learning」自体はTensorFlowを使っているわけではありませんが、やってることは同じなので、TensorFlowのコードでも非常に参考になるんです。

とりあえず実際に動くコードを手元において、教材片手にいじりながら読むのはおすすめです。

ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装

2017年2月19日 (日)

python上のグラフを漫画風に変えてしまう宣言文”xkcd”

pythonにしてはずいぶん砕けた機能です。

”xkcd”というWeb漫画があるそうですが、python上のグラフをそのxkcd風に変えてしまうという機能があるそうです。

【xkcd】pythonコードにたった一行で漫画のようなグラフを作る! - プロクラシスト

例えばこんなグラフ。

なんだか、手書きのグラフのようですね。

pythonでグラフを書かせる際に、以下のようなコードを先頭につけるといいようです。

import matplotlib.pyplot as plt
plt.xkcd()

これを使えば、3Dグラフもこの通り。

脱力感というか、あまり真面目な数値データに見えませんねぇ。

使い道を聞かれても困っちゃいますが、例えばこういう感じの和んだ雰囲気の資料が作りたいときにはぜひ活用してみてはいかがでしょうか?

今すぐ使える!資料を「一目瞭然」にする グラフの正しい使い方 ~人を動かす!数学的コミュニケーション術2~ (幻冬舎plus+)

より以前の記事一覧

当ブログ内検索

  • カスタム検索

スポンサード リンク

ブログ村

無料ブログはココログ