合理主義的グルメブログ

学生起業家の日常をツラツラと書いています。主に食事情報です。

tf-debuggerのことはじめ

Deep Learningを動かしていると,時々naninfなどの計算不能な値が生まれてしまう.
そんなときに,便利なのがtf-debuggerだよって聞いて使ってみたいと思った.

前提として,名前の通り,tensorflowで動作します.
個人的に便利だと思ったのは説明にあったこれですね.

TensorFlow の ML モデルの開発中によく起きる問題は、オーバーフローやゼロによる除算、ゼロの対数などによって不適切な数値(無限大や NaN)が発生することです。巨大な TensorFlow グラフでは、そのようなノードの発生元を見つけるのは非効率で時間もかかります。tfdbg CLI と条件付きブレークポイントを使うと、すばやく問題のノードを特定できます。

やっぱり,みんな詰まるポイントは同じなんですね.

とりあえず,以下の動作テスト用のプログラムを用意します.
デバッガーの導入は,既存のsessを,tf_debug.LocalCLIDebugWrapperSessionでラッピングするだけですね.

import numpy as np
import tensorflow as tf
from tensorflow.python import debug as tf_debug

xs = np.linspace(-0.5, 0.49, 100)
x = tf.placeholder(tf.float32, shape=[None], name="x")
y = tf.placeholder(tf.float32, shape=[None], name="y")
k = tf.Variable([0.0], name="k")
y_hat = tf.multiply(k, x, name="y_hat")
sse = tf.reduce_sum((y - y_hat) * (y - y_hat), name="sse")
train_op = tf.train.GradientDescentOptimizer(learning_rate=0.02).minimize(sse)

sess = tf.Session()
sess.run(tf.global_variables_initializer())

sess = tf_debug.LocalCLIDebugWrapperSession(sess)
for _ in range(10):
    sess.run(train_op, feed_dict={x: xs, y: 42 * xs})

実行し,sess.run()メソッドが呼び出されると,
tfdbgコマンドラインインターフェースが起動し,
こんな画面が現れます.

f:id:GoKIDS:20181104082550p:plain

使い方は,この動画を見ればだいたいわかります.

youtu.be

上のタブをクリックできるのが,便利ですね.

とりあえず,runさせてみましょう.

tfdbg> run

f:id:GoKIDS:20181104084406p:plain

矢印の部分をクリックすると,こんな画面に切り替わって, learning_rateの状態を確認することが出来ます. f:id:GoKIDS:20181104084531p:plain

上のタブでそれぞれの情報も確認できるので,便利ですね.

これから,積極的に使っていこうと思います.

デバッガーのCLI内のスクロールは,PgUpPgDwを使うけど,もっと便利なキーバインドはないのかなぁ...

参考リンク

【Python】argparseで,選択肢を与える方法

python使っている人なら,コマンドライン引数の取得に,argparseを使うと思います.

僕も使っているので,その際に,
このオプションは,一定の選択肢の中から選んでほしいときに使えるオプションがあるので紹介します.

choices

--choicesオプションにより,引数には許される値を指定することができます.

import argparse

parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--mode', help='set mode, [real] or [sim]', type=str, choices=['real', 'sim'])
args = parser.parse_args()

このようにすると,--modeオプションは,realsimをしていなければいけなくなります.

御影瑛路『空ろの箱と零のマリア』を読んだ

この前に読んだ,「Fランクの暴君」が面白かったので,
同じ作者の作品で評判が良かった「空ろの箱と零のマリア」を読んでみました.

いわゆるループものなので,
最初から最後までずっと同じ状況を繰り返しています.

最初は読んでて退屈すると思っていましたが,
話が非常に凝っていて,全然ダレずに読み終える事ができました.

主人公の主な目標は,ループを引き起こしている犯人を見つけることですが,
細かい違和感などが,文章内に上手く織り込まれていており,
精読しているのに全然わからなかったです.

話全体は,おすすめですが, 個人的にはドンピシャなジャンルじゃないので,続きは読まないと思います.

このようなジャンルが好きな人は絶対にハマると思います.

docker: Error response from daemon: create nvidia_driver_410.73: VolumeDriver.Create: internal error, check logs for details.

nvidia-dockerをインストールして実行してみたら,
こんなエラーが出た.

$ nvidia-docker run --rm nvidia/cuda nvidia-smi
docker: Error response from daemon: create nvidia_driver_410.73: VolumeDriver.Create: internal error, check logs for details.
See 'docker run --help'.

対処法を探して,解決したのでメモします.

ソースはここです.

github.com

まずは,nvidia-dockerの状態を書き換えます.

$ systemctl edit nvidia-docker

これで,下記を追記します.

[Service]
ExecStart=
ExecStart=/usr/bin/nvidia-docker-plugin -s $SOCK_DIR -d /usr/local/nvidia-docker-test

っで,ザザッと設定を行うことで,動くようになりました.

$ sudo mkdir /usr/local/nvidia-docker-test
$ sudo chown nvidia-docker /usr/local/nvidia-docker-test
$ sudo systemctl restart docker nvidia-docker

動作確認するとこんな感じです.

$ nvidia-docker run --rm nvidia/cuda nvidia-smi
Tue Oct 30 03:46:20 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 410.73       Driver Version: 410.73       CUDA Version: 10.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla V100-SXM2...  Off  | 00000000:04:00.0 Off |                    0 |
| N/A   35C    P0    51W / 300W |    417MiB / 16130MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

【Pybullet】接触を検知する

pybulletを使っていて,ロボットが何かと接触したことを検知したかったです.

ロボットの足が地面と接地しているかは,よく強化学習における観測データとして利用されます.

命令としては,p.getContactPoints()を使えば出来ます.

docs.google.com

こんな感じで使います.
robotは対象のbodyのid番号で,right_footが対象linkのidです.

result = p.getContactPoints(robot, -1, right_foot, -1)

この場合,robotright_foot接触している座標を返します.

値があるとこんな感じです.

print(result)
-> ((0, 1, 0, 5, -1, (0.306818108432366, -0.20726071519498707, -2.237793284010081e-16), (0.30681810843236623, -0.20726071519498718, 0.0004359660735957366), (-5.697036571337818e-13, 2.3927553599618834e-13, -1.0), 0.00043596607359596036, 14.825712481037616),)

何とも接触していなければ,空のタプルを返します.

print(result)
-> ()

NVIDIA Driverをアップデートして,nvidia-docker 2.0に以降する

古いGPUドライバーを使っていると,
時々わけわからん警告が発生します.

僕は以下のリンクのWarningに当たりました.

https://devtalk.nvidia.com/default/topic/1027077/container-pytorch/-quot-unexpected-end-of-proc-mounts-line-overlay-quot-on-p3-8xlarge/

解決策として,「バージョン396以降にしろよ」っと言っています.

っということで,ドライバーをアップデートしたのでメモしておきます.

対応バージョンを確認

以下のサイトから,自分のGPUに対応したドライバーのバージョンを確認します.

Download Drivers | NVIDIA

既存ドライバー確認

すでにドライバーがインストールされているか確認します.

$ dpkg -l | grep nvidia

僕自身,詳しくないので,勉強しながら行きます.
dpkgとはDebianのパッケージである.debファイルを扱うコマンドです.
これが先日買収されたRedhat系だとrpmコマンドになります.

-lオプションは,パッケージを一覧表示します.
今回は後ろに何も指定していないので,インストールされているパッケージが一覧表示されます.

その後,パイプ(|)でつないで,grepコマンドで,「nvidia」を含むパッケージだけを取り出しています.

古いドライバーの削除

もし,既存ドライバーが存在していた場合は,そいつを削除します.

$ sudo apt-get purge nvidia-*

なぜか僕の環境だと,正規表現が使えなかったので,こんな感じで全部手打ちしました.

$ sudo apt-get purge  -y nvidia-384 nvidia-390 nvidia-410 nvidia-docker nvidia-opencl-icd-384 nvidia-opencl-icd-390 nvidia-opencl-icd-410 nvidia-prime nvidia-setting

リポジトリの登録

Ubuntuのドライバーを提供しているリポジトリを登録します.

$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt-get update

ドライバーのインストール

事前に調べたバージョンを指定してインストールします.

$ sudo apt-get install -y nvidia-<最新バージョン>

再起動

$ sudo reboot

確認

nvidia-smiを使って,GPUが見えているか確認します.

$ nvidia-smi

nvidia-dockerのインストール

僕は機械学習用にGPUを利用しているので, CUDAはホスト環境には入れないで, すべて仮想環境で管理しています.

そのために,nvidia-dockerをインストール)します.
(dockerのインストールは,ここ

nvidia-docker 1.0 を削除

前に,nvidia-docker 1.0を使っていたので,最初にそいつを削除します.

$ docker volume ls -q -f driver=nvidia-docker | xargs -r -I{} -n1 docker ps -q -a -f volume={} | xargs -r docker rm -f
$ sudo apt-get purge nvidia-docker

リポジトリの登録

$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list |  sudo tee /etc/apt/sources.list.d/nvidia-docker.list
$ sudo apt-get update

nvidia-docker 2.0 をインストール

$ sudo apt-get install -y nvidia-docker2
$ sudo pkill -SIGHUP dockerd

pkillコマンドは,プロセス名を指定して,シグナルを送信するコマンドです.
詳しくは以下のリンクを参照くだいさい.

www.atmarkit.co.jp

【Python】locals()とglobals()

gym baselinesのPPOのプログラムを読んでいたら,
よく知らない関数が出てきたのでメモする.

引っかかったのは,callback部分で,locals()globals()ってやつです.

locals()は,自身のローカル領域の変数群の値を辞書型で返してくれる.

globals()は,グローバル変数群の値を辞書型で返してくれる.