Translate

2017年1月19日木曜日

Keras の概要を読んで、邪推する

TensofFlowを勉強している私に
簡単にコードが書ける Kersa というものがあり、
TensorFlowをラップしているらしいよ
と教えてくれる人がいたので
Kerasの概要を勉強してみた。

TensorFlow のときとは違って既に日本語化ドキュメントが
用意されており、
6~7割TensorFlowサイトをGoogle翻訳して読んでいたので
サクリと読むことができた。

TensorFlowのAPIをラップしたライブラリなので
基本機械学習フレームワークであるのだけど、
たしかに

むっちゃ簡単

なのである。

何が簡単かというと、なによりコードが読みやすい


TensorFlowは設計者の意図を理解するまで
なかなか把握しにくいAPIになっている。

高速なC/C++実装をPythonコードでモデル記述し、セッションを実行するため、
TensorFlow は上から下に必ずしも処理されない。

しかもPython上のリテラルをC/C++実装上の変数・配列格納領域へrunする時に渡す
というところが、ベタ読みする開発者にとって無駄としか思えない。


だが Kerss のライブラリは、
オブジェクト指向
設計を行っている。


Modelをインスタンス化して、
シーケンシャルな多層パーセプトロンの場合
順番にインスタンス化したLayerインスタンスadd()していき、
できあがったModelインスタンスに対して、
compile()/fit()で学習、evaluate()で評価する。

上から下に読めば簡単に理解できる

Layerは独自のものも作れるコンポジットな設計だし、
add()して一気に処理するアタリはApplet/Swingなどの設計と同じだ。



IBMやSBのWatsonや
Google API、
Microsoft Cognitive APIなどの他力を嫌う
オンプレミス至上主義の多い日本企業では
機械学習の独自実装はじつは喉から手が出るほど欲しい


で TensorFlow をためそうとするのだけど、
先程書いたとおり
コードの可読性が極めて悪い

しかもキチンと機械学習を理解していないと
何をインプットにして、何をアウトプットにすれば良いのか
どのパターンでどういうモデルを使い分ければ良いのかすら
わからない..

勉強するには TensorFlowのチュートリアルコード
読まないといけないのだけど、
TensorFlowはガンガンバージョンアップして
チュートリアルコードがdeprecatedされた関数で
動かないものも少なくない。

しかもGoogleの提供するTensorFlowサイトは
機械学習に関する知識ベースで解説を組んでいて
こまかいどの変数がどういう意味を持ってここで加算してるのかとか
ちくちく説明してくれていない..


そこでこのKeras
そらみんな飛びつくよなあ..



個人的には TensorFlow の Java実装になってくれないか..

!そうか
Kerasの狙いは

Java機械学習標準ライブラリ狙い

か!


..ありうる話だ。


という与太話で記事を終えるのも申し訳ないので
KerasサンプルコードのGitてっぺんにある README.mdを翻訳した
以下にリストを残しておく。

参照の際は、
At your own riskでお願いします。
----

Keras サンプルディレクトリ


[addition_rnn.py]
2つの(文字列としての)数値の加算実行によるSequence-to-Sequence 実装の学習

[antirectifier.py]
Kerasにおけるカスタムレイヤの記述方法のデモ

[babi_memnn.py]
文章読解のための、bABlデータセット上のメモリネットワークのトレーニング


[babi_rnn.py]
文章読解のための、bAbIデータセット上の 2 分岐 recurrent networkのトレーニング

[cifar10_cnn.py]
CIFAR10の小さな画像データセットを使った、シンプルなディープCNNのトレーニング

[conv_filter_visualization.py]
入力スペースの勾配降下法によるVGG16フィルタの可視化

[conv_lstm.py]
畳み込みLSTMネットワークを使ったデモ

[deep_dream.py]
Kerasの深い夢(実行例)

[image_ocr.py]
畳み込みスタックとそれに続く反復スタックとCTCログ損失機能をトレーニングすることによる光学式文字認識(OCR)の実行

[imdb_bidirectional_lstm.py]
IMDBセンチメント分類タスク上において双方向LSTMをトレーニング

[imdb_cnn.py]
Convolution1Dをテキスト分類に使用するデモ

[imdb_cnn_lstm.py]
IMDBセンチメント分類タスクにおいてrecurrent stack networkが後続する畳み込みスタックのトレーニング

[imdb_fasttext.py]
IMDBセンチメント分類タスクにおけるFastTextモデルのトレーニング

[imdb_lstm.py]
IMDBセンチメント分類タスクにおけるLSTMをトレーニング

[lstm_benchmark.py]
IMDBセンチメント分類タスクにおいて異なるLSTM実装を比較

[lstm_text_generation.py]
ニーチェの著作からテキストを生成

[mnist_acgan.py]
MNISTデータセットにおけるAC-GAN(Auxiliary Classifier GAN)の実装

[mnist_cnn.py]
MNISTデータセットを使った簡単なconvnetの作成

[mnist_hierarchical_rnn.py]
MNIST数字分類において階層型RNN(HRNN)をトレーニング

[mnist_irnn.py]
Le氏ほかによる論文「整流化された線形単位の再帰的ネットワークを初期化する方法」における pixcel-by-pixcel のシーケンシャルなMNIST実験の再現

[mnist_mlp.py]
MNISTデータセットにおける単純なディープな多層パーセプトロンのトレーニング

[mnist_net2net.py]
「Net2Net:知識移転による加速学習」におけるMNISTによるNet2Net実験の再現

[mnist_siamese_graph.py]
MNISTデータセットからの数字のペアを入力とした Siamese(シャム人の) 多層パーセプトロンをトレーニング

[mnist_sklearn_wrapper.py]
sklearnラッパ使用方法のデモ

[mnist_swwae.py]
MNISTデータセットの残りのブロックに基づいた スタックされたWhat-Where AutoEncoderのトレーニング

[mnist_transfer_cnn.py]
翻訳学習玩具の例

[neural_doodle.py]
ニューラルいたずら書き

[neural_style_transfer.py]
ニューラルスタイル変換

[pretrained_word_embeddings.py]
凍結したKeras 埋め込みレイヤに事前トレーニング済みの単語埋め込み(GloVe埋め込み)をロードし、20 ニュースグループデータセット上のテキスト分類モデルの訓練への使用

[reuters_mlp.py]
ロイターニュースワイヤトピック分類タスクにおける簡単なMLPのトレーニングと評価

[stateful_lstm.py]
stateful RNNsを使った長いシーケンスを効率的にモデル化する方法のデモ

[variational_autoencoder.py]
variational autoencoder 構築方法のデモ

[variational_autoencoder_deconv.py]
Kerasにおけるデコンボリューションレイヤを使ったvariational autoencoderの構築方法のデモ

-------


p.s.

映画「君の名は。
を見た人はほぼ100%
売れるニオイしかしない
と思ったはずだと思うけど、

TensorFlowをかじった人が
この
Kerasを読んだら
きっとTensorFlowより
流行るニオイしかしない
と思うはず..

2017年1月18日水曜日

TensorFlow の tf.strided_slice() を調べる

TensorFlow の チュートリアル RNN サンプルである ptb_word_lm.py を動かしてみたのだけど、

TypeError: strided_slice() missing 1 required positional argument: 'strides'

というエラーメッセージが表示され動作しない..

で、調べてみると..

strided_slice() missing 1 required positional argument: 'strides' #752

で読む限り、どうも tensorFlow 0.12になってから stride_slice()の引数strideを指定しないと動かないらしい..

ほかにも、困ってる人がいるみたい..

tensorflow0.12でcifar10を動かす時のエラー

CIFARのサンプルにも影響でてるのか..

tf.slided_slice() は多次元テンソルデータを矩形(?)に切り出す関数らしく、
下手にstrideを指定すると間違えるおそれがある..

ということで、TensorFlowの tf.stlide_slice()のドキュメントを勝手訳してみた。
----
tf.strided_slice(input_, begin, end, strides=None, begin_mask=0, end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=0, var=None, name=None) {#strided_slice}


テンソルから、ストライドされたスライスを抽出します。

最初の順番では、この操作はテンソル `input` の `begin` から始まる位置から、サイズ `end - begin` のスライスを抽出します。スライス抽出は、すべての次元が `end`より小さくなるまで、` begin`インデックスに `stride` を追加することによって継続されます。ストライドのコンポーネントは負の値にすることができ、これは逆のスライスを引き起こすことに注意してください。

この操作は、numpyスタイルのスライスされた範囲のエンコーディングと考えることができます。Pythonスライス input[、...、] が与えられた場合、この関数は次のように呼び出されます。

`begin`、` end`、 `strides`はすべて長さ n になります。 n は一般に `input`と同じ次元ではありません。

i番目の仕様では、 `begin_mask`、` end_mask`、`ellipsis_mask`、` new_axis_mask`、`shrink_axis_mask`は、i番目の仕様に対応するi番目のビットを持ちます。

`begin_mask`のi番目のビットがゼロでない場合、` begin [i] `は無視され、そのディメンション内の可能な最大範囲が代わりに使用されます。
`end_mask`は、終了範囲を除いて同様に機能します。

7 x 8 x 9 型テンソルの `foo [5:、:、::3]`は `foo [5:7,0:8,0:3]`と同じです。
`foo [:: - 1]`は8のテンソルを逆転させます。

`ellipsis_mask`のi番目のビットが必要ならば、指定されていない次元数だけ他の次元の間に挿入されます。 `ellipsis_mask`には1つの非ゼロビットだけが許されます。

たとえば、 10 x 3 x 3 x 10 型テンソルの形の `foo [3:5, ...,4:5]``foo [3:5, :, :4:5]`と `foo [3:5, ...] `は` foo [3:5, :, :, :]]` と等価です。

`new_axis_mask`のi番目のビットが 1 の場合、` begin`、 `end`、` stride`は無視され、出力テンソルのこの時点で新しい長さ 1 次元が追加されます。

たとえば、 10 x 8 型テンソルの `foo [3:5,4]` は 2 型テンソルの形状を生成し、 `foo [3:5,4:5]` は `shrink_mask` が `1 << 1 == 2` の 2 x 1 型テンソルを生成します。

`shrink_axis_mask`のi番目のビットが 1 ならば、適切な次元でスライスを実行するために `begin` 、 `end [i]` 、 `stride [i]` が使われますが、出力テンソルは次元が 1 つ小さくなります。 これは、slice [i]i番目のエントリ== 1の場合にのみ有効です。


注: `begin`と` end` はゼロインデックス化されています。 `strides`エントリはゼロでなければなりません。


```python
# 'input' は [[[1, 1, 1], [2, 2, 2]],
#             [[3, 3, 3], [4, 4, 4]],
#             [[5, 5, 5], [6, 6, 6]]]
tf.strided_slice(input, [1, 0, 0], [2, 1, 3], [1, 1, 1]) ==> [[[3, 3, 3]]]
tf.strided_slice(input, [1, 0, 0], [2, 2, 3], [1, 1, 1]) ==> [[[3, 3, 3],
                                                               [4, 4, 4]]]
tf.strided_slice(input, [1, 1, 0], [2, -1, 3], [1, -1, 1]) ==>[[[4, 4, 4],
                                                                [3, 3, 3]]]

引数:



*  `input_`: `Tensor`.
*  `begin`: `int32` もしくは `int64` の `Tensor` 。
*  `end`:  `int32` もしくは `int64` の `Tensor` 。
*  `strides`: `int32` もしくは `int64` の `Tensor` 。
*  `begin_mask`: `int32` のマスク値。
*  `end_mask`: An `int32` のマスク値。
*  `ellipsis_mask`: `int32` のマスク値。
*  `new_axis_mask`: `int32` のマスク値。
*  `_masshrink_axisk`: `int32` のマスク値。
*  `var`: `input_` に関連する変数、もしくは None
*  `name`: operation (操作)名 (オプション)。


戻り値:


 `input`と同じ型の `Tensor` 。

既存アプリケーションをK8s上でコンテナ化して動かす場合の設計注意事項メモ

既存アプリをK8sなどのコンテナにして動かすには、どこを注意すればいいか..ちょっと調べたときの注意事項をメモにした。   1. The Twelve Factors (日本語訳からの転記) コードベース   バージョン管理されている1つのコードベースと複数のデプロイ 依存関係 ...