AWS に関する投稿を表示しています

GPU で動く Tensorflow をセットアップする

この記事は公開されてから1年以上経過しており、情報が古い可能性があります。

こんにちは。ごみばこです。

ちょっと思い立って、TensorflowをGPUで動かしたくなったので、その構築メモを残しておきます。

カンタンなまとめ

  • AWS EC2 で g2.2xlarge を スポットインスタンスで使った
  • Tensorflow の学習データを 60GB の付属するストレージに置いた
  • crontab と aws-cli を使って定期的に AWS S3 に学習データ(の一部)を転送した
  • tensorflow と tensorflow_gpu を間違えるとかなしい
  • 2日くらいで試行錯誤した成果は得られなかった

 

マシンの調達

ローカルPCでも NVIDIA なグラフィックが搭載されているので実行はできたのですが、せっかくなので AWS を利用することにしました。インスタンスタイプとしては g2.2xlarge を利用しています。さらに、せっかくなので スポットインスタンス を利用したのですが、ちょっと高めの金額設定をして、2日ほど安定して稼働できました。高めとはいえ、普通に EC2 のオンデマンドインスタンスを立てるよりも圧倒的に安くできています。

オンデマンドインスタンス: $0.898 / 1時間
(参考:https://aws.amazon.com/jp/ec2/pricing/on-demand/

スポットインスタンス: およそ $0.09 - $0.15 / 1時間
(参考:https://aws.amazon.com/jp/ec2/spot/pricing/

入札前に過去の金額を見ていると、なぜか ap-northeash-1a のリージョンだけ天井価格?まで跳ねることがあるようだったので ap-northeast-1c を利用しました。

 

スポットインスタンスならではの注意点ですが、データ消失の可能性があったので、実際に学習を進めてみたとき、中間データを S3 にファイルとして保存するようにしていました。仕組みとしては crontab を利用して aws-cli を実行する程度のカンタンなものになっています。

Tensorflow 自体が中間データを保存・読み込みできるので、非常に便利でした!(※実際には TFLearn を利用)

 

また g2.2xlarge ならでは…?かわからないのですが 60GB ほどのストレージが付属しています。このストレージはそのまますぐに利用することが出来るのですが、マシンを再起動したりするとデータが消失するので Tensorflow の中間データや、出て来るログや、前処理した後などの一時ファイル置き場として利用していました。

 

環境構築

Linux + GPU 周辺に知識があるわけでもないので、参考になりそうで、よさそうな記事を探して、それどおりに進めたところ、実に上手く行きました。

(参考:http://qiita.com/yukoba/items/3692f1cb677b2383c983

// 下準備
$ sudo apt update
$ sudo apt upgrade -y

$ wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
$ cat 7fa2af80.pub | sudo apt-key add -

$ wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_8.0.44-1_amd64.deb
$ sudo dpkg -i cuda-repo-ubuntu1604_8.0.44-1_amd64.deb
$ sudo apt update

$ sudo apt install -y linux-generic
$ sudo apt install -y cuda nvidia-367
$ sudo reboot

$ sudo apt remove -y linux-virtual
$ sudo apt-get -y autoremove

$ rm 7fa2af80.pub cuda-repo-ubuntu1604_8.0.44-1_amd64.deb

// bashrcに追加
$ vi ~/.bashrc

export PATH="/usr/local/cuda-8.0/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/cuda-8.0/lib64:$LD_LIBRARY_PATH"

// 確認
$ nvidia-smi

// CuDNN の追加
//
// NVIDIA Developer に登録するとダウンロードできる
// https://developer.nvidia.com/
//
// ローカル PC でダウンロードして scp などで転送するとよい

$ tar xzf cudnn-8.0-linux-x64-v5.1.tgz
$ sudo cp -a cuda/lib64/ /usr/local/lib/
$ sudo cp -a cuda/include/ /usr/local/include/
$ sudo ldconfig

$ rm -R -f cuda cudnn-8.0-linux-x64-v5.1.tgz

// grub編集
// 12行目
sudo vi /etc/default/grub

GRUB_CMDLINE_LINUX="systemd.unit=multi-user.target"

$ sudo update-grub
$ sudo reboot

// 後処理
$ sudo apt-get clean

CuDNN をインストールするとき NVIDIA Developer に登録しなくてはいけなかったところがちょっとつまりかけたところです。登録するときいくつか分野?を選べるのですが、適当なものを選んでもダメで「Accelerated Computing with NVIDIA ComputeWorks」で登録する必要がありました。ここまで行くと nvidia 系のコマンドが利用できるようになり GPU の動作具合を確認することができます。

 

Python + Tensorflow の準備

こちらも Python に詳しいわけではないので、良さそうな記事をいくつか見ながら統合した結果で進めました。

// pip で入れる python ライブラリに必要なライブラリ、ツールを入れる
$ sudo apt-get install -y libpng-dev libjpeg-dev libhdf5-serial-dev libatlas-base-dev libopenblas-dev build-essential autoconf libtool pkg-config

// python3 を入れる
$ sudo apt-get install -y python3-pip

// aws-cli を入れる
$ sudo apt-get install -y awscli

// pip を更新する
$ sudo pip3 install -U pip

// 公式サイトを要確認し Tensorflow を入れる
// https://www.tensorflow.org/get_started/os_setup#pip_installation
$ sudo pip3 install -U https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-0.12.1-cp35-cp35m-linux_x86_64.whl

// 各種ライブラリを入れていく
// tflearn Tensorflow のラッパ。カンタンに Tensorflow を扱うことができるようになる。
// pandas  カンタンに csv を扱える
// Image   画像処理を行う
// h5py    Tensorflow が高速に動くために必要らしい
// scipy   科学技術計算ライブラリ。Tensorflow が高速に動くために必要らしい
$ sudo pip3 install -U tflearn
$ sudo pip3 install -U pandas
$ sudo pip3 install -U Image
$ sudo pip3 install -U h5py
$ sudo pip3 install -U scipy

// もう一度入れ直すと numpy が早くなるらしい...?未検証
$ sudo pip3 install -U --force-reinstall numpy

// g2.2xlarge の場合 60GB がついてくるのが /mnt
// ここにテンポラリを用意していく
$ sudo mkdir /mnt/tmp/

// 学習データの記録
$ sudo mkdir /mnt/tmp/checkpoint/

// Tensorflow が動作していく様子を web 上で確認できるようにするため
$ sudo mkdir /mnt/tmp/tensorboard/

// 全許可!
$ sudo chmod 777 -R /mnt/tmp/


// Tensorflow の動作確認
// GPUに関する出力がもりもりでてくるとOK
$ python3
> import tflearn

途中 Tensorflow を入れるところで、うっかり違うバージョンの Python 、 CuDNN の URL を指定すると動作しません。さらに GPU を利用しないバージョンをこれまたうっかり選んでしまうと CPU で動作する Tensorflow が入ってしまい GPU が使えません。pip3 list などで確認をしても Tensorflow としか出てこないのでどちらが入っているか確認するのがわかりづらく…。。

実際に import tensorflow とかを実施し、GPU 初期化したよ!という結果を見るのが一番でしょうか。

 

肝心の成果は…?

ここまでで、環境構築が出来たので、あとは MNIST のチュートリアルなどをすすめると、ディープラーニングの凄さ、GPU の凄さを体験できます。

ぼくはディープラーニングって何者?を体験したかったので MNIST チュートリアルをして、以前思いついていたレシートの判別(https://gomiba.co.in/blog/archives/587)をやってみてました。ニューラルネットワークやアルゴリズムがよく分からず、それっぽくニューラルネットワークを組んでみたのですが、思ったように loss が下がらず。。これはデータや組み方が悪いんだなーと思い、ディープラーニングむずかしいね、という結論でインスタンスを終了しました。

費用は2日間で $2 くらいでしたが何の成果もあげられませんでした!(もうちょっとがんばろう)

最近のやったこと

この記事は公開されてから1年以上経過しており、情報が古い可能性があります。

機械学習してる気持ちになっている

雑にTensorflowからこの世界に入門したけど、わからなさすぎたので
Python+scikit-learnから出直そうとしている。

https://www.tensorflow.org/

http://scikit-learn.org/stable/

そしてこのあたりを読んだ。

[amazonjs asin="4873116988" locale="JP" title="実践 機械学習システム"]

[amazonjs asin="B01HGIPIAK" locale="JP" title="Python機械学習プログラミング 達人データサイエンティストによる理論と実践 impress top gearシリーズ"]

用語や仕組みがわかってきたので、一段と楽しくなってきた。

機械学習すげーーーーーー

 

AWSぽちぽちしてる

某所でLINEBOTやろうぜ!みたいな話になって、環境用意することになった。
Terraformを使いたかったので、いい感じに使ってAWSぽちぽちした。

TerraformでAPIGatewayとEC2をもりもり立てて、Itamaeでプロビジョニングした。

https://www.terraform.io/

http://itamae.kitchen/

これがめっちゃ楽しすぎて、LINEBOTの記憶がない…。

 

 

エンジニアってたのしいなー

話題のLINE BOTでちょっとだけ遊んでみた

この記事は公開されてから1年以上経過しており、情報が古い可能性があります。

目次

  • ムムッ!8秒に1人登録者が増えるんです!
  • 実装について
  • SSLが通らない
  • API Gatewayの設定を間違える
  • でばっぐがむづかしい
  • 画像サイズ制限
  • 構成上の問題
  • おわりに

Qiitaやはてブでよく見るほどに巷で話題のLINE BOTですが、私も参戦してみました。

BOT API Trial Accountのご紹介 | LINE BUSINESS CENTER

ムムッ!8秒に1人登録者が増えるんです!

できたbotがこちらです。
13000133_1058043724268365_4544060361943443361_n

顔写真を送るとムムッなカードを結合して送り返してくれます。

ちゃんと複数人も認識してます。

1460689208363

(社内の人に協力してもらいました。ありがとうございます!)

出来たこのbotを公開したい気持ちはやまやまですが、ムムッな版権や、アーキテクチャやら実装の問題もあってちょっとNGです。

コードなら公開できるので、またのちほど。。

実装について

LINE BOTのコールバックとして、画像の場合はテキストとは異なるデータがやってきます。
そのとき、LINE側に対してメッセージIDでリクエストをすると、そのデータに紐づくコンテンツ(画像、動画、スタンプ…)を受け取ることができます。
(詳細はドキュメント参照: LINE Developers - BOT API - API reference

こうして受け取った画像をそのまま顔認識に送っています。この部分には、Face++というサービスを利用しています。

Face++: Leading Face Recognition on Cloud

戻ってきた情報には、顔の位置を始め、目の位置や口の位置、さらには表情データなども含まれています。
この顔の位置、目の位置を計算し、カードの画像に対してサイズ調整・回転を施して、合成しています。

出来上がった画像を、LINEに送信することで、BOTのレスポンスになります。


はてさて、参戦していくなかで、初めてやることだらけで非常にわくわくするとともに、
すごい詰まったことがいくつかあったので、それらを書き綴っておきます。

SSLが通らない

LINE BOTには、コールバックとしてSSLなURLを指定しなければいけません。
しかし、すでに各所で話題に上がっているように、Let’s Encryptでは通信の確立がうまくできないいようです。

そこで、今回はAWSのAPI Gatewayを利用してみることにしました。

Amazon API Gateway (API を容易に作成・管理) | AWS

「ひとまず試してみる」というこで構成としては以下のようになっています。

<span class="hljs-constant">LINE </span>-> <span class="hljs-constant">AWS API Gateway </span>-> <span class="hljs-constant">VPS </span>-> <span class="hljs-constant">LINE</span>

API Gatewayの設定を間違える

これは完全にうっかりミスです。

LINE BOTのコールバックはPOSTメソッドで飛んでくるのですが、GETメソッドしかAPI Gatewayに登録してなくて、数時間を無駄にしました。。ちゃんとドキュメントを読もう!

また、API Gatewayでは指定したHTTPヘッダがプロキシされていくので、シグネチャについても指定しないといけません。

でばっぐがむづかしい

LINEでメッセージや画像を送ってはサーバのログをみて、という結構無駄な開発作業をしていました。

よくよく考えれば、メッセージやりとり部分は後で繋ぐようにし、コアな処理を別に実装したほうがよいですきっと。
メッセージやりとりをあとで繋ぐようにすることで、LINE以外にも各種bot系に組み込むことも簡単にできると思います。
そしてテストも書きやすくなるので…。。

画像サイズ制限

これもドキュメント読もう案件です。。

LINEにメッセージを送る際、画像はJPEG限定、1024px x 1024px以下にしないといけないようです。
また、プレビュー用の画像を用意する必要があり、こちらもJPEG、240px x 240px以下にしないといけません。

どちらの画像もURLとしてアクセスできる場所に設置し、そのURLをLINEに伝えることでbotが送信してくれます。

構成上の問題

いまはお試しということで、コールバックへのリクエストが来たら、メッセージを送信を含むすべての処理をしています。しかし、この方法では、人が増えてきたときにサーバ負荷が上がり、快適なレスポンスが得られなくなってしまいます。
(※現状でも顔認識や画像処理でラグがあるので快適とそうでないのぎりぎりくらいです。。)

どうすれば快適なレスポンスが得られるかについては、すごい分かりやすく深い記事が上がっています。

大量メッセージが来ても安心なLINE BOTサーバのアーキテクチャ - Qiita

今の構成は以下のようになっています。

<span class="hljs-constant">LINE </span>-> <span class="hljs-constant">AWS API Gateway </span>-> <span class="hljs-constant">VPS </span>-> <span class="hljs-constant">LINE</span>

これを・・・例えばこう、えいやっと・・・

<span class="hljs-constant">Callback </span>     <span class="hljs-symbol">:</span> <span class="hljs-constant">LINE </span>-> <span class="hljs-constant">AWS API Gateway </span>-> <span class="hljs-constant">AWS Lambda </span>-> <span class="hljs-constant">AWS SNS </span>-> <span class="hljs-constant">AWS SQS</span>
<span class="hljs-constant">Execute Batch </span><span class="hljs-symbol">:</span> <span class="hljs-constant">AWS SQS </span>-> <span class="hljs-constant">AWS Lambda </span>-> <span class="hljs-constant">Another API </span>-> <span class="hljs-constant">AWS SNS </span>-> <span class="hljs-constant">AWS SQS</span>
<span class="hljs-constant">Response Batch:</span> <span class="hljs-constant">AWS SQS </span>-> <span class="hljs-constant">AWS Lambda </span>-> <span class="hljs-constant">LINE</span>

うーん、どうなんでしょうかね…w

あとは記事に書かれているように、メッセージに対する並列処理をできるようにすると、快適なレスポンスが得られるようになってくるのかなあ、と思います。


おわりに

Facebookもメッセンジャーbotやるよ!と発表があったように、botの波が来ています。

みなさんが開発したり運営しているようなWebサービスであったり、流行りつつあるIoT、TensorFlowといった機械学習、などなどなどに加えたメッセンジャー系botのコラボは、きっと新たなユーザー獲得やユーザー体験をもたらすと思います。

まずは触ってみて、どんなことができそうかを考えていくときっと楽しいとおもいます!