maminusのメモか何か

2018-10-14

KerasでLeakyReLUを使った

| 22:07

完全に自分用のメモ。KerasでLeakyReLUを使おうとしたら怒られたので正しい(?)書き方をメモしておく。

環境

警告を食らったコード

import plaidml.keras
plaidml.keras.install_backend()

from keras.models import Sequential
from keras.layers.core import Dense
from keras.layers import LeakyReLU

def make_mlp():
	model = Sequential()
	model.add(Dense(256, activation=LeakyReLU(alpha=0.01), input_shape=(3,), kernel_initializer='he_normal'))
	model.add(Dense(3, activation='linear'))
	model.compile(optimizer='adam', loss='mean_squared_error', metrics=['mse'])
	return model

警告メッセージ

keras\plaidml-env\lib\site-packages\keras\activations.py:197: UserWarning: Do not pass a layer instance (such as LeakyReLU) as the activation argument of another layer. Instead, advanced activation layers should be used just like any other layer in a model.

identifier=identifier.__class__.__name__))

修正後のコード

def make_mlp():
	model = Sequential()
-	model.add(Dense(256, activation=LeakyReLU(alpha=0.01), input_shape=(3,), kernel_initializer='he_normal'))
+	model.add(Dense(256, input_shape=(3,), kernel_initializer='he_normal'))
+	model.add(LeakyReLU(alpha=0.01))
	model.add(Dense(3, activation='linear'))

解説(のような何か)

Dense()の引数activationにLeakyReLUのインスタンスをわたすとダメらしい。他に試したこととしてmodel.add()でActivation()をわたして引数にLeakyReLUのインスタンスをわたしてみたが、同じ警告メッセージが表示された。

警告メッセージの英文がよくわからなかったけど、どうやら「直接LeakyReLUのインスタンスをadd()せよ」ってことらしい。

2018-10-03

XavierにTensorFlowをインストール。ついでにjupyter notebookも入れる

| 01:15

Jetson AGX XavierにTensorFlowとJupyter notebookをインストールしたのでメモ。

基本的に公式サイト*1とフォーラム*2に書いてある通り。

前提

JetPack-4.0インストール済みの状態から始める

インストール

# 熱くなるのでファン全開で冷やす
ubuntu@jetson-0423018055036:~$ sudo ./jetson_clocks.sh
# コンパイルが重いので本気を出させる
ubuntu@jetson-0423018055036:~$ sudo nvpmodel -m 0

# pipを入れる。依存パッケージでpython3-devも入る
ubuntu@jetson-0423018055036:~$ sudo apt-get install python3-pip

# venv入れて環境を作る
ubuntu@jetson-0423018055036:~$ sudo apt-get install python3-venv
ubuntu@jetson-0423018055036:~$ python3 --version
Python 3.6.6
ubuntu@jetson-0423018055036:~$ python3 -m venv py366env
ubuntu@jetson-0423018055036:~$ source py366env/bin/activate
(py366env) ubuntu@jetson-0423018055036:~$ pip install -U pip

# TensorFlowを入れる
(py366env) ubuntu@jetson-0423018055036:~$ pip install --extra-index-url https://developer.download.nvidia.com/compute/redist/jp40 tensorflow-gpu

# matplotlibとkerasの依存パッケージを入れる
(py366env) ubuntu@jetson-0423018055036:~$ deactivate
# freetypeを入れるときにlibpng-devも一緒に入る
ubuntu@jetson-0423018055036:~$ sudo apt-get install libfreetype6-dev
ubuntu@jetson-0423018055036:~$ sudo apt-get install libhdf5-dev
# KerasというよりSciPyの依存パッケージ
ubuntu@jetson-0423018055036:~$ sudo apt-get install liblapacke-dev
ubuntu@jetson-0423018055036:~$ sudo apt-get install gfortran
ubuntu@jetson-0423018055036:~$ source py366env/bin/activate               

# matplotlibとKeras、Jupyterを入れる
(py366env) ubuntu@jetson-0423018055036:~$ pip install matplotlib
(py366env) ubuntu@jetson-0423018055036:~$ pip install -U keras==2.2.0
(py366env) ubuntu@jetson-0423018055036:~$ pip install jupyter

[2018/10/14 追記]

liblapack-devは「static version」らしい。ヘッダファイル類は「e」付きのliblapacke-devが正解っぽい。

Jupyterの初期設定

以前の記事*3とほぼ同じ。

差分は

c.NotebookApp.ip = '0.0.0.0'

と設定するところ。「*」だとエラーになる。参考*4

あとnotebookのアクセス先URLはXavierのホスト名でアクセスできるみたい。自分の環境だと以下のアドレスだった。

http://jetson-0423018055036:8888/

f:id:maminus:20181014214350p:image

f:id:maminus:20181014214414p:image

importできたので大丈夫そう。

2018-09-13

Jetson AGX Xavier買いました

| 22:38

Jetson AGX Xavier、早期注文が可能になったのでさっそく買ってみた。不在だった荷物の引き取りに手間取ったので今日受け取ったけど、9/11に到着したみたい。

[2018/09/15 02:15追記]なんかGTC Japan以降、名称に「AGX」がつくようになったらしい。

JetPackのファイルダウンロード中なので所感とかそういうのを書いておこうと思う。

工場出荷の状態

Ubuntuインストール済みの状態だった。ただ、起動させるとCUIが立ち上がってSSHで接続できない状態だった。

HDMIディスプレイをつなぎ、付属の変換ケーブルでUSBキーボードをつないで作業した。

/home/nvidia/NVIDIA-INSTALLER/README.txtに書かれている通りにインストーラを実行してJetsonを再起動するとGUIモードで起動してSSHもつながった。

$ cd NVIDIA-INSTALLER
$ sudo ./installer.sh

ただ、この状態だとCUDA Toolkitとかサンプルアプリとかが入ってない状態なので遊べない。結局JetPackを入れる感じになりそう。

確認できたツール

  • nvpmodel
  • jetson_clocks.sh
  • tegrastats

は入ってた。jetson_clocks.shをたたいておかないと、何もしてなくてもヒートシンクが熱い。

nvpmodelのモード

/etc/nvpmodel.confの設定が書かれているっぽい。デフォルトはID=3「MODE_30W_ALL」ってモードでCPUは8コアともonlineだけど4つだけ1.2GHz設定、GPUは最大900MHz、EMC(メモリのバス?)は1.6GHz。DLAとPVAのクロックも設定されるっぽい。

tegrastatsを打つとこんな感じ。

RAM 2100/15820MB (lfb 3000x4MB) CPU [0%@1190,0%@1190,0%@1190,0%@1190,0%@1190,0%@1190,0%@1190,0%@1190] EMC_FREQ 0%@1600 GR3D_FREQ 0%@905 APE 150 MTS fg 0% bg 0% AO@33C GPU@32.5C Tboard@34C Tdiode@35.75C AUX@31.5C CPU@34C thermal@32.55C PMIC@100C GPU 619/619 CPU 309/309 SOC 1548/1548 CV 0/0 VDDRQ 0/0 SYS5V 1851/1851

CPUのクロック設定が4つしか入ってないのはなぜだろう。。。

一番本気っぽい設定はID=0「MAXN」でクロック設定が全部「-1」になってる。

MAXN is the NONE power model to release all constraints

ってことなので「特に制限しないモード」ってことだと思う。

cpuinfo

今気づいたけど、v8lってv8.1ってこと?XavierのCPUってv8.2じゃなかったっけ???

[2018/09/15 02:15追記]よく見たら「いち」じゃなくて「える」ですね。kernelソースを見たら取りうる値がv8bかv8lってことなのでlittle endianってことかな。

nvidia@jetson-0423018055036:~$ cat /proc/cpuinfo
processor       : 0
model name      : ARMv8 Processor rev 0 (v8l)
BogoMIPS        : 62.50
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer : 0x4e
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0x004
CPU revision    : 0
MTS version     : 42272872

processor       : 1
model name      : ARMv8 Processor rev 0 (v8l)
BogoMIPS        : 62.50
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer : 0x4e
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0x004
CPU revision    : 0
MTS version     : 42272872

processor       : 2
model name      : ARMv8 Processor rev 0 (v8l)
BogoMIPS        : 62.50
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer : 0x4e
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0x004
CPU revision    : 0
MTS version     : 42272872

processor       : 3
model name      : ARMv8 Processor rev 0 (v8l)
BogoMIPS        : 62.50
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer : 0x4e
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0x004
CPU revision    : 0
MTS version     : 42272872

processor       : 4
model name      : ARMv8 Processor rev 0 (v8l)
BogoMIPS        : 62.50
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer : 0x4e
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0x004
CPU revision    : 0
MTS version     : 42272872

processor       : 5
model name      : ARMv8 Processor rev 0 (v8l)
BogoMIPS        : 62.50
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer : 0x4e
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0x004
CPU revision    : 0
MTS version     : 42272872

processor       : 6
model name      : ARMv8 Processor rev 0 (v8l)
BogoMIPS        : 62.50
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer : 0x4e
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0x004
CPU revision    : 0
MTS version     : 42272872

processor       : 7
model name      : ARMv8 Processor rev 0 (v8l)
BogoMIPS        : 62.50
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer : 0x4e
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0x004
CPU revision    : 0
MTS version     : 42272872

とりあえず今日はここまで。(ダウンロードエラーで止まっとる・・・)

2018-09-08

Fancy Indexingが使えるリストを実装してみた

| 20:35

自分用のメモ。Pythonでlistにデータを入れてnumpyみたいにインデックスをリストでわたして取り出したいと思ったので作ってみた。

実装はこちら。

class FancyIndexingList(list):
	def __getitem__(self, arg):
		if not isinstance(arg, list):
			return super().__getitem__(arg)

		indices = arg
		result = [self[i] for i in indices]
		return FancyIndexingList(result)

listを継承して__getitem__で引数がリストの時だけ自分で処理して他は全部親クラスに任せる。

Fancy Indexingは__getitem__の引数がそのままインデックスのリストになっているので、インデックス引きして新しいリストを作って返すだけ。

使うときはこんな感じ。

>>> sample = FancyIndexingList(range(10))
>>> sample
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> sample[2]
2
>>> sample[ [4, 2, 0] ]
[4, 2, 0]

参考。

>>> class IndexingTest:
...     def __getitem__(self, arg):
...             print(type(arg))
...
>>> i = IndexingTest()
>>> i[1]
<class 'int'>
>>> i[1, 2]
<class 'tuple'>
>>> i[ [0, 1] ]
<class 'list'>
>>> i[0:10:2]
<class 'slice'>

2018-06-27

cv::gemm()のOpenCL実装が小さな行列に対応してなかった件

| 22:19

OpenCV 3.4.0での話。OpenCL有効化済みのOpenCVAMD GPU環境で実行。OSはWin10。

以下のソースコードで行列積を計算しようとしたら結果がぐちゃぐちゃになっていた。

ソースコード

#include <opencv2/core.hpp>
#include <iostream>
int main(void)
{

	constexpr int input_size = 4;  // 行列の行数、列数。これを16にすると期待する計算結果になる
	cv::Size size(input_size, input_size);

	// 入力
	cv::Mat cpu_a(size, CV_32F);
	cv::Mat cpu_b(size, CV_32F);

	// all 0
	cv::Mat  cpu_zero = cv::Mat::zeros(size, CV_32F);
	cv::UMat gpu_zero = cpu_zero.getUMat(cv::ACCESS_READ);

	// 出力
	cv::Mat  cpu_dst(size, CV_32F);
	cv::UMat gpu_dst(size, CV_32F);

	// 入力の行列を一様分布の乱数0.0〜1.0で埋める
	cv::randu(cpu_a, cv::Scalar(0.0f), cv::Scalar(1.0f));
	cv::randu(cpu_b, cv::Scalar(0.0f), cv::Scalar(1.0f));
	cv::UMat gpu_a = cpu_a.getUMat(cv::ACCESS_READ);
	cv::UMat gpu_b = cpu_b.getUMat(cv::ACCESS_READ);

	// 行列積を計算する
	cv::gemm(cpu_a, cpu_b, 1.0, cpu_zero, 1.0, cpu_dst);  // CPU版が呼ばれる
	cv::gemm(gpu_a, gpu_b, 1.0, gpu_zero, 1.0, gpu_dst);  // OpenCL版が呼ばれる

	// CPU版とGPU版の誤差(最大、最小)を表示する
	double min_e, max_e;
	cv::minMaxLoc(cpu_dst - gpu_dst.getMat(cv::ACCESS_READ), &min_e, &max_e);
	std::cout << min_e << ", " << max_e << std::endl;

	return 0;
}

現象

CodeXLで確認するとGlobalWorkSizeが(1, 16, 1)、WorkGroupSizeが(16, 16, 1)となっていた。Globalって確かGroupの倍数じゃないとエラーになったような気がしたけど、実行してもエラーにはならなかった。

代わりに計算結果が合わない。行列Bの2行目以降をall 0にすると計算結果が期待する値になったので、アクセス先のアドレスがおかしくなってるのかも。


OpenCVの実装

OpenCVのソースを確認したところ、

int block_size = (max_wg_size / (32*cn) < 32) ? (max_wg_size / (16*cn) < 16) ? (max_wg_size / (8*cn) < 8) ? 1 : 8 : 16 : 32;

という感じでOpenCLのMaxWorkGroupSizeが

  • 1024以上なら32
  • 256以上なら16
  • 64以上なら8

の固定値がWorkGroupSizeとしてわたされていた。(float 1channelの場合)

dst行列のサイズはガン無視かーい!あ、GlobalWorkSizeはdst行列のサイズをベースにしてますねぇ。

使っているGPUのMaxWorkGroupSizeは256なので行数、列数を最低16にしないとおかしくなりそうな感じだった。


以上

ということで、16に変更したらあっさり動きましたとさ。というかこれ、自分の環境だと16の倍数以外で行列渡したらどうなるかわからないなぁ・・・

苦労して解析した割には、しょうもない理由だった。ま、いいや


ちょっと動かして使い方を確認したかっただけだったのにごっそり時間を持っていかれた・・・orz