しんさんのブログ

科学や技術のこと読書のことなど

Kerasのコーディングではまったこと集

Kerasのsessionはきちんとclearさせてないとエラーがでます

Tensoflow + Keras のコードの実行で、

TypeError: 'NoneType' object is not callable

というエラーがでて原因がわからず少しはまりました。
どうやら、kerasのバックエンドのTensorFlowのsessionをclearしていないのが原因だったようです。
以下の記事を参考にしましたら、エラーが消えました。
keras+tensorflowで終了処理でエラーが発生する | CodeLab技術ブログ

ネットワークの可視化に関して

ネットワークを可視化したかったので、以下のドキュメントを参考にしました。
可視化 - Keras Documentation

from keras.utils import plot_model
plot_model(model, to_file='model.png')

たったこれだけなら簡単だと思ったのですが、必要なパッケージがインストールされていなくてそのままでは動かなかったです。

私の環境では、以下のようにすれば動作しました。

conda install graphviz
conda install pydot

さらに、以下のサイトから"Stable 2.38 Windows install packages"をダウンロードしインストールしました。
http://www.graphviz.org/download/
そして、Windows環境変数のPathに C:\Program Files (x86)\Graphviz2.38\bin を追加しました。
以上で無事、ネットワークのグラフが表示されました。

Google のTPU v3について

Google I/O 2018で発表された、機械学習を効率よく演算できる専用ASICチップのTPUについてです。
第3世代の発表が今回行われていたので、メモってみます。

彼らのアナウンスをまとめると:

TPUには4つのTPU演算ユニットが載っている。
TPU v2: 180Tera ops per second per one TPU chip which include 4 TPU units.
TPU v3は8倍?とアナウンスされているので、
TPU v3: 180 * 8 = 1.44Peta ops per second per one TPU chip which include 4 TPU units.
さらに TPU v3を束ねたサーバーは256 TPUs なので、
1.44Peta * 256TPU = 369Peta ops per second

という計算で、100Peta以上というアナウンスになっているのでしょうか。
8bit int の演算だと思っていましたが、100Peta flops と書いてあるし、floatの計算なのでしょうか。

よく読むと、Podが8倍の性能になって100kTeraFloposと書いてあり、チップの演算速度8倍になったとは言ってないですね。
逆算すると、
100Peta / 256 = 390 TeraFlops なので、チップそのものはv2 の2倍程度の速度向上のようです。

TensorflowのTutorial "Deep MNIST for Experts"を試した時のメモ

wshinya.hatenablog.com

前回は"MNIST For ML Beginners"の解説を読みプログラムを実行してみました。
今回は、以下のリンクから"Deep MNIST for Experts"の解説を読みプログラムを実行してみます。
Deep MNIST for Experts  |  TensorFlow

前回のBeginners編と今回のExperts編の一番大きな違いは、Beginners編では画像のローカル構造を無視してしまい、1次元のベクトルに展開してしまいましたが、Exprets編では2次元の画像の2次元のまま扱う手法としてCNNを用いているところです。
CNNを用いることで数字の形の特徴をとらえることができ、認識率が大きく向上することが期待されます。

  • 今回のネットワーク構成

畳み込み層
プーリング層
畳み込み層
プーリング層
全結合層
Softmax層

となっています。

2回の畳み込み層により画像のローカルな構造とよりグローバルな構造をとらえることができます。
そのあとは、多値分類問題として、全結合層+Softmax regressionという前回と同じような構造になっています。

まずはmnist_deep.py を実行してみました。
するとWARNINGがずらずらと表示されいますが、
"xxx is deprecated and will be removed in a future version."
という将来のバージョンでこのコマンドは使えなくなりますよという警告ですので、当面は無視しておいても問題なさそうです。
そして実際に学習が進み最終的には、
step 19900, training accuracy 1
test accuracy 0.9913
今度は、testデータで99%の精度を超えてきます。簡単なCNNですがかなりの精度がでますね。

1層目の畳み込み層の
W_conv1 = weight_variable([5, 5, 1, 32])
は、5x5x1(channel数、いまはgray scaleなので1)の畳み込みフィルターが32種類あるということを示しています。
2層目では、
W_conv2 = weight_variable([5, 5, 32, 64])
となっており、5x5x32のフィルターが64種類あることを意味しています。
ここでの32や64はネットワークの途中で学習して特徴量の数に対応しています。
また各層ごとに2x2でMax poolingしていますので,画像サイズは
28 x 28 -> 14 x 14 -> 7x7 と順次スケールされていきます。

2層目のmax poolingが終わった時点では7x7の画像が64枚出力されています。
これをreshapeして1次元ベクトルに変換しているのが
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
です。fully connected layerを構成するためのweight, W_fc1とバイアスb_fc1
をこれに作用させることで、全結合層計算ができます。
最後に活性化関数としてreluを適用してのが以下の行です.
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

このネットワークでは過学習を防止するためにdropout、つまり適当にネットワークの重みWをゼロにするという操作を行います。
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
初めの行はdropoutの際に接続が保持される確率を格納するためのplaceholderで学習時には0.5で推論時にはdropoutしないように1.0にセットしています。
最後に10種類の数値に対応するように単層のsoftmax回帰に相当する層を追加しています。

最適化は
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
とAdamを使用しています。

GradientDescentとAdamで結果がどれくらいちがうのかちょっと実験してみました。
学習率はどちらも0.0001
ADAM:
step 100, training accuracy 0.88
test accuracy 0.9195
SGD:
step 100, training accuracy 0.26
test accuracy 0.2062
まあ、予想通りですが、SGDに比べるとADAMの方がかなり収束が早いです。

TensorflowのTutorial "MNIST For ML Beginners"を試した時のメモ

Tensorflowを勉強するにはTensorflowのTutorialを自分で入力して実行しながら理解するのが一番手っ取り早いです。
特に初めてTensorflowを動かすときには、以下のリンク先のMNIST for ML BeginnersというTutorialがおすすめです。
MNIST For ML Beginners  |  TensorFlow

このチュートリアルは、単純な1層のネットワークで手書き文字を認識するというものです。
1層ですので、重みとバイアスも一つしかありませんが、それでもニューラルネットワークに必要な最小限の要素をすべて含んでいます。

TensorflowのtutorialにはMNISTの手書きデータを使うものはこのbiginner用とCNNを使ったものの2種類があります。
以下に、実際にコードを理解して実行したときの自分用のメモを残しておきます。

                  • -

mnist.train.images は [画像の数, 28x28=784] の shapeで値は0-1の画素の輝度
ラベルは 0~9 の数字でone-hot表現されています。
one-hot表現は例えば、
3 なら [0,0,0,1,0,0,0,0,0,0]
というふうに表現されます。
従ってラベルは
mnist.train.labels [画像の数, 10]というshapeで、値はfloatです。

> x = tf.placeholder(tf.float32, [None, 784])

xは学習データ(手書き数字の画像データを1次元にしたもの), Noneは画像の数は任意の長さを取りうることを意味する。
placeholderはこのように、学習データなどを入れる入れ物。

重みやバイアスは、実行時に随時更新されますので、tfのvariable変数として以下のように定義しています。
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

wは入力が784次元で出力が10次元なので[784, 10]となります。 
784列10行の行列と思えばいい。

ニューラルネットワークの計算のcoreの部分です。
> y = tf.nn.softmax(tf.matmul(x, W) + b)

tf.matmul(x, W)の部分ですが、データ数をNとすると
xは N x 784 の行列で, Wは 784 x 10の行列なので、結果のyはN行10列の行列です。
つまり各行にxの各行にたいする画像データを0から9のどの数値と予測したかの確率がyの各行に入ります。

この予想された出力yと正解とを使って表されたロス関数を最小化することで、適切なW,bを決めます。
従って正解も上記yと同じshapeである必要があるので、
> y_ = tf.placeholder(tf.float32, [None, 10])
というように、N行10列の行列としてplaceholderを用意しておきます。

多値分類問題なのでロス関数としてcross entropyを使用します。
> cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
tf.reduce_meanは指定されたshapeの成分についての和をとる関数で、今の場合は、reduction_indices=[1]となっているので
1番目の要素についての和をとります。
つまり、0から9の予想された数値の方向に和をとり、N個の要素をもつ1次元配列にします。
この1次元配列は、N個の学習データそれぞれに対するロス関数の値を格納しています。
最後に、tf.reduce_meanで、N個の学習データ(バッチ処理1回分)のそれぞれのロス関数すべての平均をとってこれを最適化関数として使用しています。

ここが少し混乱しやすいのですが、実際のtutorialのコードでは上記の部分が以下のようにsoftmax_cross_entropy_with_logitsという関数で書かれています。
>cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
解説を読むと、前者の書き方のほうが数値的に不安定するそうです。

実施のコードで試してみると、前者の場合の精度は私の実行環境では、約0.92、後者では、0.91でほぼ同じ結果になりました。
実行時間は前者では約0.77sec, 後者では0.90secでlogits関数の計算の分だけ速度が落ちているようです。
(実際のコードを一番最後に添付しておきます)

logits関数とは、L = log(p/(1-p)) のことで変形するとp= 1/(1+exp(-L))で、p=0.5の時0,P>0.5のときL>0, p<0.5のときL<0となる関数。
確率p [0, 1.0] -> [-inf, inf]にマップする。
softmaxで確率[0, 1.0]の出力を得て、それをlogitsに通すことで正解の確率が大きければ値はより大きくなる。マイナスが掛かっているのでloss関数としては値が小さくなるということです。
確率が0や1に近い時に勾配が数値的に消失したり不安定にあったりするのを防ぐ効果があります。
stackoverflow.com


最適化はGradientDescentで学習率は0.5に設定しています。
>train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

学習結果の評価
>correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
tf.argmaxは引数の配列の中で一番値の高いもののindexを返す。yは[教師データの数, 正解の確率]という配列になっているので、
1番目の要素(数値の0から9のそれぞれの予測確率)から一番高いもの一つが選ばれます。
tf.equalで教師データと一致しているときにTrue, 異なっているときにFalseをセットします。

# 精度の計算
>accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
tf.castはTrue, Falseを以下のように数値に変換
[True, False, True, True] -> [1,0,1,1]
tf.reduce_meanでこの1,0,1,1,・・・の平均をとり結果を全体の精度とする。

今回試してみた実際のコードは以下のようになります。

import tensorflow as tf
import time

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

start_time = time.time()

x = tf.placeholder(tf.float32, [None, 784])

W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x, W) + b)

y_ = tf.placeholder(tf.float32, [None, 10])
#cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
# interactiveSessionでtfのsessionを作成
sess = tf.InteractiveSession()
# global変数の初期化
tf.global_variables_initializer().run()

print ("--- start training ---")
for _ in range(1000): # 1000ステップの学習を行う
    # 1 batch = 100個のデータでbatch学習を行う
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
print ("--- finish training ---")

# 予測yと正解ラベルy_が同じ値であればTrue、ことなればFalseがセットされる
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
# 精度の計算
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print("精度:")
print( sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

end_time = time.time()
print ("time: " + str(end_time - start_time) + "sec")

深層学習でよく使われる学習用データセットまとめ

3D系のデータセットは別の記事にまとめました
wshinya.hatenablog.com

arXivTimesに素晴らしいまとめがあります。
github.com

商用利用可能な6種類の最大4Kサイズの人物の肌テクスチャが無料配布されています

商用利用可能な6種類の最大4Kサイズの人物の肌テクスチャが無料配布されています • 3DCG最新情報サイト MODELING HAPPY

MNIST:

手書き文字認識学習用データ
28pixel x 28pixel x 1channel
60000枚:training用
10000枚:test用
クラス: 10個の数字

機械学習におけるHello World的なデータ
ちなみに、MNISTとはMixed National Institute of Standard Technologyの省略形で、日本語に訳せば"国立標準技術研究所"でしょうか。
日本では旧通産省工業技術院、今の産業技術研究所に相当するアメリカの研究機関です。

CIFAR-10:

一般物体認識のベンチマークとしてよく使われている写真データ
32pixel x 32pixel x 3channel
50000枚:training用
10000枚:test用

画像は10種類にラベル付けされている
クラス:airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck

AlexNet(SuperVision)のAlex Krizhevskyさんが整備
(AlexさんはILSVRC2012で優勝)
以下のサイトに詳しく解説されています
aidiary.hatenablog.com

CIFAR-100:
CIFAR-10の100種類のクラス分け版
qiita.com

Microsoft COCO ( MS COCO ):

画像と、画像の認識、セグメンテーション、画像を説明する短いキャプションがセットになったデータ
以下の解説を参照のこと
qiita.com

Imagenet:

ダウンロードできるのは学術関係者に限定される
ImageNetとはスタンフォード大学がインターネット上から画像を集め分類したデータセット。一般画像認識用に用いられる。ImageNetを利用して画像検出・識別精度を競うThe ImageNet Large Scale Visual Recognition Challenge(ILSVRC)などコンテストも開かれる
現在、1400万枚以上のデータが集まり、2万クラス以上あるらしい
ネット上の画像を集めてきているので結構リンク切れがあったりするらしい。

GoogleのOpen Image Dataset v4

Googleが用意した1,540万のバウンディングボックス含む190万画像600カテゴリのデータセット
Open Images V7
ai.googleblog.com
ダウンロードは以下のサイトから
github.com

Caltech101

101個にカテゴリー分類されたデータ.
画像の品質がいい。
http://www.vision.caltech.edu/Image_Datasets/Caltech101/

The PASCAL Visual Object Classes Homepage

Yoloの学習済みモデルが公開されている.
http://host.robots.ox.ac.uk/pascal/VOC/

YFCC100M

flickerから収集した画像、動画データ.
http://yfcc100m.appspot.com/?

OpenImageDataset v4

物体検出用のデータ。オブジェクトの位置・サイズ、名前がつけられている。
ライセンス:The annotations are licensed by Google Inc. under CC BY 4.0 license. The images are listed as having a CC BY 2.0 license.
https://storage.googleapis.com/openimages/web/index.html

顔画像のデータセット

約13000枚の顔画像で、人の名前がフルネームでつけられている。
人は5000人以上、1680人は2枚以上の画像あり。
人種、表情、顔の向き、撮影の状態はランダムで、多様性あり。
http://vis-www.cs.umass.edu/lfw/

Celebの顔写真のデータセット

20万枚の画像
http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html

102種類の花の画像データセット

データサイズは8189枚
Visual Geometry Group - University of Oxford

              • -

他のデータセットもKerasのドキュメントで解説されています
https://keras.io/ja/datasets/

Kerasを使っていてPILが必要になったときの対処法

conda install PILとやったらpythonのversionが3.5だと怒られてしまいます。
PILの代わりに、

conda install Pillow

とすればいいようです。

以下のサイトを参考にしました。
qiita.com

Pillowについては以下を参照
qiita.com

Tensorflow2.0 CPU/GPU版 + Keras + OpenCV ver3.0の環境構築

2019年10月 更新

  • インストール環境

- Windows64Pro
- Nvidia Geforce2080Ti

Anacondaでよく使うコマンドは以下のサイトが便利です.
qiita.com

                          • -

Windows: tensorflow CPU版

1) anaconda の仮想環境の作成
まずは、pipのアップデート
python -m pip install --upgrade pip
そして、anacondaの仮想環境の作成
conda create -n tensorflowCPU200 python=3.5 anaconda
pythonのバージョンを3.5にしたのは、OpneCVを動かすため(追記にあるようにpython: ver.3.6.*でも動くかもしれません)

2) tensorflow2.0.0のインストール
> pip install tensorflow==2.0.0

> python -m pip install --upgrade pip
をやってpipもアップグレードした

これでようやくtensorflow2.0 CPU版のインストールが成功した。
> python
>> import tensorflow as tf
で正常にtensorflowがimportできるか確認した。
次のようにすれば、実際にtensorflowのバージョンを確認できます。
print(tf.__version__)
>>> print(tf.__version__)
2.0.0
となれば成功.

conda-build関連のwarningが出ることがあるが、放置したほうがいい。下手にconda-buildを
インストールするとcondaのバージョンが古いというエラーではまるので注意。

その他必要なモジュールをインストール。例えば以下のようなモジュール。
> conda install -c menpo opencv3
> conda install h5py
> conda install matplotlib
> conda install scikit-learn
> conda install pillow
> conda install pydot -> pydotは開発がおわっているらしい
pydotの代わりにpydotpluをインストール
> conda install pydotplus
> conda install seaborn


Windows: tensorflow GPU
1) anaconda の仮想環境の作成
conda create -n tensorflowGPU200 python=3.5 anaconda
>[WinError 193] %1 は有効な Win32 アプリケーションではありません。
というエラーがでてコマンドラインからは仮想環境が作れないときは、anaconda navigatorから作成する。

2) Nvidia GPUドライバーをアップデートする
ドライバーのバージョンは26.21.14.3160(NVIDIA 431.60)/Win10.64です.

3)CUDAとcuDNNのアップデート
現在のCUDAのバージョンがCUDA 9.xなので10.0にアップデートする必要がある。
(tensorflow 2.0 のインストールドキュメントにはCUDA10.0と書いてあるので、10.1はインストールしないように注意)

https://developer.nvidia.com/cuda-toolkit-archive
からCUDA 10.0をダウンロードしてインストール

nvcc -V
で見ると
release 10.0, V10.0.130
となり、CUDA10.0であることがわかる。

  • CUDNNのインストール

https://www.tensorflow.org/install/gpu
上記ページを改めてよく読むと、
cuDNN SDK (>= 7.4.1)
と書いてあるのでインストールする。
CUDA10.0に対応するバージョンを選ぶこと。
今回は、
cuDNN v7.6.3 (August 23, 2019), for CUDA 10.0
を選択しました。

4) tensorflow2.0.0 GPU版のインストール
> pip install tensorflow-gpu==2.0.0

後の作業はCPU版と同じです.
Ubuntuでもほぼ同じプロセスでCUP版,GPU版の構築が可能でした。

                                                          • -

おまけ:
仮想環境は新たにつくらず、tensorflowのバージョンのみアップデート
CPU版:
pip install -U tensorflow==2.0.0

                                                          • -

(2019/5/10追記)
Ubuntuで上記と同じようにしてpython+openCV環境を構築すると、WindowsではOKだった、
>cv2.namedWindow() 
を使用して新しいwindowを開こうとするとエラーになりました。openCVのビルド時にgtkがONになっていないためのようです。
以下の手順でpython+openCV環境を構築するとうまく動きました。
>conda create -n tensorflowCPUKerasOpenCV3 anaconda
>conda activate tensorflowCPUKerasOpenCV3
>conda install -c menpo opencv3
>conda install keras
これで、
python: ver.3.6.8
opencv: 3.1.0
tensorflow: 1.13.1
keras 2.2.4
がセットアップできます。

ひょっとしたら以下のライブラリのインストールも必要かもしれません。
GUI操作のためのGTKライブラリ:
sudo apt-get install libgtk-3-dev

JPEG, PNG, TIFFなどの画像処理に対応するためのライブラリ:
sudo apt-get install libjpeg-dev libpng-dev libtiff-dev

ムービー処理に対応するためのライブラリ:
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
sudo apt-get install libxvidcore-dev libx264-dev

様々なOpenCVの関数を最適化するためのライブラリ:
sudo apt-get install libatlas-base-dev gfortran

デベロッパーツールのインストール:
sudo apt-get install build-essential cmake unzip pkg-config

上記は以下のサイトを参考にしました。
avinton.com


(参考)
OSError: Unable to open file (unable to open file: name =
というエラーが出るとき、
C:\Users\username\.keras\datasets に残っている以前ダウンロードしたデータをいったん消去すれば解決することがあるようです

proxyの設定は、
C:\Users\username\.condarc

proxy_servers:
http: http://proxyservername:portNum
https: https://proxyservername:portNum
を追加し、Windows環境変数
HTTP_PROXY = http://proxy-server:portNum
HTTPS_PROXY = https://proxy-server:portNum
を追加すればいいです。