Translate

2016年9月27日火曜日

TensorFlowサイトのチュートリアル「Sequence-to-Sequence Models」を翻訳してみた

TensorFlowもいれたので、そろそろ応用してみたいなあ..
とおもい
TensorFlowサイトのチュートリアルにある

Sequence-to-Sequence Models
https://www.tensorflow.org/versions/r0.10/tutorials/seq2seq/index.html

を翻訳してみた。

拙い英語力なので参照される場合は、At your own risk でお願いします。

-----

Sequence-to-Sequence モデル


既に RNNチュートリアル (もし迄読んでいない場合は、このチュートリアルを始める前にこちらへ進んでください)で論じられているように、言語のモデル化を学習することができます。ここには興味深い問題があがっています:いくらかのインプットを条件にして、意味のあるレスポンスを生成することができますか?たとえば、ニューラルネットワークを英語からフランス語への翻訳を訓練することができますか?答えはyesであることがわかります。


このチュートリアルでは、いかにしてそのようなシステムをエンドtoエンドでビルドおよび訓練するかについて紹介します。TensorFlow git リポジトリにクローンのルートにあるpipパッケージを通じて既にインストールされている前提とします。

翻訳プログラムは次のコマンドで開始できます:

cd tensorflow/models/rnn/translate
python translate.py --data_dir [データディレクトリパス]
訓練の準備および訓練のために WMT'15ウェブサイト から英語-フランス語翻訳データをダウンロードします。ディスク容量約20GBが必要となりますので、ダウンロードして準備します(詳細は 後述 )。このチュートリアルを読んでいる間、開始することができます。

このチュートリアルのリファレンスはmodels/rnnにあります。

ファイル内容
seq2seq.pysequence-to-sequence モデルを構築するためのライブラリ
translate/seq2seq_model.pyニューラル翻訳 sequence-to-sequence モデル
translate/data_utils.py翻訳データ準備のためのヘルパー関数
translate/translate.py翻訳モデルの訓練および実行用バイナリ


訳者注:上記ファイルは、tensorflowをインストールした環境には入っています。Dockerコンテナを使っている場合は/usr/local/lib/python2.7/dist-packages/tensorflow/models/rnn/にあります。

Sequence-to-Sequence の基礎

Cho氏が2014年に寄稿した論文PDF )に記載されている、基本的なsequence-to-sequenceモデルは、インプットデータを処理するエンコーダとアウトプットを生成するデコーダの2つのRNNで構成されています。基礎的なアーキテクチャは次の図の通りです。



上図の四角はRNNセルを表しています。またこれらの四角は、最も一般的にはGPUセルもしくはLSTMセル(説明は RNNチュートリアル を参照のこと)を表しています。エンコーダおよびデコーダは重みを共有するかもしくは、より一般的には、異なるパラメータセットを使用します。多層セルが sequence-to-sequence モデルにおいてもうまく使われています。例: 翻訳向け Sutskeverほか 2014年 ( PDF )

ここで表されている基本的なモデルにおいて、あらゆるインプットは、デコーダに引き継がれる唯一のものである、固定サイズのベクトルにエンコード されなければなりません。インプットへの直接アクセスをデコーダに与えるために、注意メカニズム(attention mechanism)は、 Bahdanauほか、2014 ( PDF )にて導入されました。注意メカニズム(attention mechanism)の詳細については記述しませんが(論文を参照のこと)、デコーダに対しあらゆるデコーデング手順におけるインプットを覗くことを許す ために、詳細について十分理解しておいてください。LTSMセルや注意メカニズム(attention mechanism)による多層 sequence-to-sequence ネットワークは、次の図のように表すことができます。


TensorFlow seq2seq ライブラリ


上図において、多数の異なる sequence-to-sequence モデルで構成されています。各モデルはそれぞれ異なるRNNのセルで構成されていますが、それら全てエンコーダインプットとデコーダインプットを受け取り ます。これはTensorFlow seq2seqライブラリ( models/rnn/seq2seq.py )のインターフェイスに動機づけします。基本的な RNN encoder-decoder sequence-to-sequence モデルは、次のようにして動かします。

outputs, states = basic_rnn_seq2seq(encoder_inputs, decoder_inputs, cell)
 
上記の呼び出しにおいて、 encoder_input は、エンコーダへのインプット(最初に登場した絵の ABC )をあらわすtensorflowのリストです。同様に、 decoder_input は、エンコーダへのインプット(最初に登場した絵の WXYZ )をあらわすテンソルです。
セル引数は、どのセルがモデル内部で使用されるかを示す models.rnn.rnn_cell.RNNCell クラスのインスタンスです。 GRUCellLSTMCell のような既存のセルもしくは独自に記述したものを使用することができます。さらに、 rnn_cell は多層セルの構築や、セルインプットもしくはアウトプットへのドロップアウト、もしくはその他の翻訳実行のためのラッパーを提供します。例は RNN チュートリアル を参照してください。

basic_rnn_seq2seq へのセルは二つの変数( outputsstates )を返します。両方の変数は decode_inputs と同じ長さのテンソルのリストです。当然のことながら、 outputs は、タイムステップごとのデコーダのアウトプットと一致します。そして、 outputs は、最初の絵の WXYZEOS と一致します。返却値 states は、それぞれのタイムステップにおけるデコーダの内部の状態をあらわします。
たくさんのsequence-to-sequence モデルのアプリケーションでは、時刻 tのデコーダのアウトプットは、フィードバックされ時刻 t+1 のデコーダのインプットとなります。テストの際にsequenceをデコーディングする場合、これはシーケンス構築方法となります。訓練中、他方では、た とえデコーダが前に間違えていたとしても、タイムステップごとに正しいインプットをデコーダへ提供することは一般的です。 seq2seq.py 内の関数は両方のモデルでの変数 feed_previous 使用をサポートしています。例として、次のような埋め込みRNNモデルの使用で分析してみましょう。

outputs, states = embedding_rnn_seq2seq(
    encoder_inputs, decoder_inputs, cell,
    num_encoder_symbols, num_decoder_symbols,
    output_projection=None, feed_previous=False)
embedding_rnn_seq2seq モデルにおいて、全てのインプット( encoder_inputs と 
decoder_inputs の両方 )は離散値をあらわす整数テンソルです。それらには密度表現が
埋め込まれています(埋め込みについての詳細は ベクトル表現チュートリアル を参照
のこと)が、これらの埋め込みを構築するために別々のシンボルの最大値、エンコーダ
側の num_encoder_symbols とデコーダ側の num_decoder_symbols を指定する必要があり
ます。

 
上記の起動により、 feed_previousFalse がセットされます。これは、デコーダが decoder_inputs テンソルが提供されてるものとして使用することを意味しています。もし feed_previousTrue がセットされているのであれば、デコーダは decoder_inputs の最初の要素のみ使用します。このリストのその他のテンソルはすべて無視され、前のエンコーダのアウトプットをかわりに使用します。これは翻訳モデルの翻訳デコーディングのために使用されますが、訓練中にも使用され、自身の間違いにより強力な Bengioほか,2015年 ( PDF )に類似したモデルを構築します。

上のリストで使用されているもう一つの重要な変数は、 output_projection です。もしこれが指定されていない場合は、埋め込みモデルのアウトプットは、生成されたシンボルごとの ロジット を表すので、 num_decoder_symbols によるバッチサイズ型をしたテンソルとなります。長いアウトプット語彙を使ったモデルの訓練時(たとえば num_decoder_symbols が長い場合)、これらの長いテンソルとしては実用的ではありません。その代わりよいこととして、より小さなアウトプットテンソルを返します。そして後で output_projection を使った長いアウトプットテンソルへ反映されます。これは、 Jeanほか 2014年 ( PDF )にて説明されている、sampled softmax 損失を seq2seq モデルにて使用することを許可します。

basic_rnn_seq2seq embedding_rnn_seq2seqに加えて、 seq2seq.py 内にはいくつかの sequence-to-sequence モデルが存在しますので、確認してみてください。それらは類似したインタフェースを持っているので、ここでは詳細を説明しません。ここでは翻訳モデルとして、 embedding_attention_seq2seq を、以下のように使います。


ニューラル翻訳モデル

sequence-to-sequence モデルのコアは models/rnn/seq2seq.py 内の関数によって構築され
ており、そこには models/rnn/translate/seq2seq_model.py 内の翻訳モデルが使用される
ことに言及する価値があるいくつかのトリックがまだ存在します。
 

sampled softmax と output projection


ひとつめ(samples softmax)は既に説明していますが、ここではsampled 
softmaxを長いアウトプット語彙を操作するために使用したいと考えています。
デコードするためには、output projection の結果を追う必要があります。
sampled softmax 損失 と output projection 両方とも、 seq2seq_model.py 内の
以下のコードによって構築されます。

 if num_samples > 0 and num_samples < self.target_vocab_size:
    w = tf.get_variable("proj_w", [size, self.target_vocab_size])
    w_t = tf.transpose(w)
    b = tf.get_variable("proj_b", [self.target_vocab_size])
    output_projection = (w, b)

    def sampled_loss(inputs, labels):
      labels = tf.reshape(labels, [-1, 1])
      return tf.nn.sampled_softmax_loss(w_t, b, inputs, labels, num_samples,
                                        self.target_vocab_size)
 
はじめに、もしサンプル数(デフォルトは512)がターゲット語彙サイズより小さいのであれば、sample softmax のみ構築します。語彙が512より小さい場合、標準softmax損失を使うことは良いアイディアであるかもしれません。
次に、output projection を構築します。それは重み行列とバイアスベクトルから構成されるペアです。使用する場合、rnn セルは target_vocab_size によるバッチサイズよりももしろ、sizeによるバッチサイズ型のベクトルを返却します。ロジットを回復するために、重み行列を掛け、バイアスを加える必要があります。そしてこれらは、seq2seq_model.py の124~126行目で実行されます。
 
if output_projection is not None:
  self.outputs[b] = [tf.matmul(output, output_projection[0]) +
                     output_projection[1] for ...]
 

バケッティングとパディング(埋め込み)

 
sampled softmax に加えて、翻訳モデルもまたバケッティングを利用しています。バケッティングは、異なる長さの文を効果的に操作するための手法のひとつです。まず最初に問 題をはっきりさせましょう。英語からフランス語へ翻訳する場合、インプット上の異なる長さ L1 の英文と、アウトプット上の異なる長さ L2 のフランス語文を持っています。英文は encoder_inputs に渡されると、フランス語文が decoder_inputs (GOシンボルが先頭文字につく)としてかえってきます。

こ のため原則英文とフランス語文の長さの各ペア( L1, L2 + 1)のための seq2seq モデルを作成しなくてはなりません。結果としてこれは類似する大量のサブグラフを含む巨大なグラフとなります。他方では、ちょうどそれぞれの文に特別な PADシンボルをつめることができます。そうすれば我々は、詰められた長さの、seq2seq モデルを1つだけ必要するだけです。ただし短文では、役に立たないたくさんのPADシンボルをデコードするため、能率が悪くなります。

それぞれの長さのペアのためのグラフ構築と単一の長さに詰めることの妥協策として、大量のバケットを使って各文をバケットの長さに詰めます。 translate.py 内の以下の箇所でデフォルトのバケットを使っています。

buckets = [(5, 10), (10, 15), (20, 25), (40, 50)]
これは、3トークンの英文でこのアウトプットが6トークンのフランス語文であったとすると、最初のバケットに格納して、エンコーダインプットのため に長さ5になるまで、デコーダインプットのために長さ10になるまで詰めることを意味しています。もし英文が8トークンでフランス語文が18トークンとな る場合、例えば英文を20まで、フランス文を25までつめるとするなら、(10, 15) のバケットには適合せず、(20, 25)のバケットが使用されます。

デコーダインプットを作成する際にインプットデータにGOシンボルを前につめることを思い出してください。これは seq2seq_model.py内の get_batch() 関数で処理されます、そしてこの関数でインプット英文もまた反転します。インプットの反転は、 Sutskeverほか、2014年 ( PDF )のニューラル翻訳モデルにおけいて結果が改善されることが示されました。これは一旦置いて、ここでは"I go."という文で想像します。トークン化して[ "I", "go", "." ] をインプットとし、アウトプットの文"Je vais."をトークン化すると [ "Je", "vais", "." ] となります。これを (5, 10) のバケットに格納し、インプットは [ PAD PAD "." "go", "I" ] となり、デコーダインプットは [ GO "Je" "vais" "." EOS PAD PAD PAD PAD PAD ]となります。
 
 

動かしてみよう


これまで説明していたモデルを訓練するために、長い英語-フランス語コーパスが必要に
なります。 WMT15 Website から 10^9-Fench-English コーパスを訓練のために使い、
同じサイトから 2013 new test を開発セットとして使います。以下のコマンドを実行する
と、両方のデータセットは data_dirにダウンロードされ、訓練が始まり、チェックポイント
train_dir に保存されます。

python translate.py
  --data_dir [your_data_directory] --train_dir [checkpoints_directory]
  --en_vocab_size=40000 --fr_vocab_size=40000
約18GBの空き容量を消費し、訓練コーパス準備に数時間かかります。解凍され、語彙ファイルが data_dir 内に作成され、そしてコーパスがトークン化され整数idに変換されます。語彙サイズを定義するパラメータに注意してください。上の実行例では、40Kの最も一般的な用語を除く単語はすべて未知の単語を意味する UNK トークンに変換されます。そして、もし語彙サイズを変更したいのであれば、バイナリは再度コーパスをid型にリマップします。

データが準備できたら、訓練が始まります。翻訳のデフォルトパラメータは極めて長い値がセットされています。長いモデルが良い結果を与えるまで長 い時間かかります。長くかかりすぎるか、もしくはGPUを使ってとても多くのメモリを消費するかになります。以下の例では、小さなモデルを訓練することを 指示できます。

python translate.py
  --data_dir [your_data_directory] --train_dir [checkpoints_directory]
  --size=256 --num_layers=2 --steps_per_checkpoint=50
 
上記コマンドは、各レイヤが256個のユニット(デフォルトは1024個)の2層のモデル(デフォルトは3層)を訓練し、そして50ステップ(デ フォルトは200ステップ)ごとにチェックポイントとしてセーブします。あなたのGPUのメモリがどのくらいの大きさのモデルが適合することができるかを 発見するためにこれらのパラメータを操作することができます。

訓練中、それぞれの steps_per_checkpoints ステップでこれまでのステップの統計結果を表示します。デフォルトパラメータ(サイズが1024で3層)で、最初のメッセージはこのように表示されます。

global step 200 learning rate 0.5000 step-time 1.39 perplexity 1720.62
  eval: bucket 0 perplexity 184.97
  eval: bucket 1 perplexity 248.81
  eval: bucket 2 perplexity 341.64
  eval: bucket 3 perplexity 469.04
global step 400 learning rate 0.5000 step-time 1.38 perplexity 379.89
  eval: bucket 0 perplexity 151.32
  eval: bucket 1 perplexity 190.36
  eval: bucket 2 perplexity 227.46
  eval: bucket 3 perplexity 238.66
 
各ステップが1.4秒未満で、それぞれのバケットに訓練セットの予測性能と開発セットの
予測性能を確認することができます。30Kステップ後、短文(バケット0と1)の予測性能が
一桁になっていることが確認できます。訓練コーパスが~22Mの文を含んでおり、
1 epoch(訓練データを1回通す)は64バッチサイズで約340Kステップかかっています。
この時点で、モデルが--decodeオプションで英語をフランス語に翻訳されていることが
わかります。


python translate.py --decode --data_dir [your_data_directory] --train_dir [checkpoints_directory] Reading model parameters from /tmp/translate.ckpt-340000 > Who is the president of the United States? Qui est le président des États-Unis ?
 
 

次は何?

 
ここまでで、どうやって独自のEnglish-to-French翻訳機を隅から隅まで構築するかを紹介しました。実行してどのようにモデルが振る 舞うのかを自分自身で確認しました。合理的な品質をもつほど、デフォルトパラメータではベストな翻訳モデルを提供しませんでした。ここにあたなが改善する ことがのこっています。

まず第一に、とても原始的なトークナイザである data_utils 内の basic_tokenizer を使いました。より良いトークナイザは、 WMT'15 ウェブサイト で見つけることができました。そのトークナイザと多くの語彙を使って、翻訳を発展させるべきです。

また、翻訳モデルのデフォルトパラメータは未調整です。モデルの学習率、劣化、もしくは重みの初期値うぃ異なった方法で変更してみることが可能です。また seq2seq_model.py内のデフォルト GradientDescentOptimizer を、 AdagradOptimizer のようなより先進的なものに変更することも可能です。これらを試して、結果の向上方法を確認してみましよう!

最後に、ここで紹介されたモデルを、翻訳のためでなくほかの sequnece-to-sequence 作業に使うことが可能です。たとえあなたがsequenceをtreeにかえたとしても、 Vinyals、Kaiserほか 2014年 ( PDF )にて試行されたように、分析木の生成において同じモデルが最新技術の結果をあたることができます。独自の翻訳機をビルドするだけでなく、構文解析、チャットボット、もしくはあなたが考えるどんなプログラムをビルドすることができます。実験してみてください!
-------- 


やっぱりサンプルは、最新の翻訳モデルではないのか..

基礎的なモデルだけチュートリアルやサンプルコードで紹介して、
Google翻訳につかっているモデルは..
 
..そりゃ、当然教えてはくれないわなあ..


ただ、日本語は単語間に隙間がないから、
このモデルをそのまま使うわけには行かないよな..

書籍「はじめてのディープラーニング」にかいてあった
バイドゥのBi-Directed RNNモデルか..


というか、RNNもきちっと理解してないしな..

RNN、調べるか..

2016年9月21日水曜日

書籍「初めてのディープラーニング」を読んでディープラーニングに関する基礎的な用語集をつくってみる

TensorFlowのドキュメントを読むにしても
ディープラーニングの基礎単語をそもそも理解していないと
どうにもならない..

ということで日本語書籍の力を借りることにした。

買ったのはこれ。



何故この本をえらんだのかというと、

数式が可能な限り書いていない初心者本

ということ。

ディープラーニングの定義はほんの中盤くらいまででてこないが、順番建てて説明してくれていてよくわかった。

以下、上記書籍から引用して用語集を作ってみた。



機械学習訓練データを学習器に投入して学習モデルを作成し、その学習モデルを利用して処理を行う仕組み
学習器データから規則性やパターンを抽出する仕組み
訓練データ規則性やパターンを見つけ出すためのもとになるデータ
学習モデル学習器が訓練データから抽出した規則性やパターン
学習処理訓練データの投入から学習モデル作成までの一連のコンピュータ処理
教師あり機械学習訓練データに教師データがあること、入力データと教師データを組みにして学習器へ投入し機械学習を行う
教師なし機械学習訓練データに教師データがないこと。精度は学習器の設計にかかっている
教師データ入力データがどのような種類であるかを示す正解データのこと
回帰データを入力すると、出力として数値を返す。機械学習における代表的な用途のひとつ
分類データを入力すると、出力としてそのデータの属性または種類を返す手法。機械学習における代表的な用途のひとつ
クラスタリングデータを入力すると、そのデータのグルーピング結果を返す手法。機械学習における代表的な用途のひとつ
ニューラルネットワーク生物の脳の神経ネットワークをモデルとしたコンピュータ処理の仕組み。ニューラルネットワークには入力層、隠れ層、出力層と呼ばれる層がある。隠れ層は複数となることもある
ノードニューラルネットワークの各層はノードを持ち、各ノードは値を持つ。人体におけるニューロンに相当する
エッジある層と次の層の間のノードを結ぶ。人体における神経細胞の樹状突起・軸索に相当する
重み各エッジは重みと呼ばれる数値を持つ
活性化関数各層は活性化関数と呼ばれる関数を持つ。あるノードの値は、そのノードとエッジで接続されている前の層のノードの値にもとづいて計算する。人体におけるシナプスに相当する。htan、シグモイド、ReLUが主に使用される
ReLU関数0より小さい値では勾配が0になる関数
weakly ReLU0より小さい値では勾配が0に近い値になる関数
確率ベクトルベクトル(v1, v2,..,vn)の各値が0から1.0の間の数値であり、合計すると1となるようなベクトル
CNNConvolution Neural Networkの略。ニューラルネットワークのノードのつながり方パターンのひとつ。隠れ層として1つ以上の畳み込み層とプーリング層で構成される
畳み込み層前の層の中で近くにあるノード同士の集合が、次の層のノードと接続するような構造を持つ層。局所的な部分の特徴を浮き立たせる役割をはたす
プーリング層前の層のノードの局所的な部分をまとめあげる処理をになう。まとめ上げる処理方法の一つとして最大値をとる場合、最大プーリングと呼ばれる。画像分析に使用する場合、位置変更への感度をさげる役割をはたす。前の層の中で近くにあるノード同士の集合が、次の層のノードと接続するような構造を持つという点は畳み込み層と同じ
AutoEncoder入力層と出力層が同一サイズのノードを持つニューラルネットワークを利用したアルゴリズムのこと。一般的に隠れ層は、入力層や出力層よりも小さいサイズにする。一般的に学習に使用される
Stacked AutoEncoder隠れ層が2層以上あるAutoEncoder
RNNRecurrent Neural Network(回帰結合ニューラルネットワーク)とRecursive Neural Network(再帰ニューラルネットワーク)のいずれもRNNと略される。再帰ニューラルネットワークは隠れ層において再帰的なノード接続があるニューラルネットワーク。このため可変長データをあつかうことができる。回帰結合ニューラルネットワークは回帰結合入力を持つネットワークで、系列データのモデル化に有効
GPUGraphical Processor Unit。描画計算を専用に行うためのハードウェア。CPUよりも10倍以上高速な浮動小数点演算能力を持つ。単純で並列性の高い処理に強い
GPGPU一般の計算にもGPUを利用すること
CUDANVIDIA社が提供するGPGPU開発のためのフレームワーク
隠れマルコフモデルディープラーニングが流行するまで音声認識で使用されていた機械学習アルゴリズムの一つ
Bi-Direction Recurrent Newral Networkバイドゥ社が音声認識で採用しているRNN拡張。手前の層だけでなく直後の層からも入力されるネットワーク構造を持つ。双方向から入力があるためBi-がつく
LeCun画像認識(MNIST)におけるCNN活用モデルのひとつ。層数8、総ノード数9118
SuperVison画像認識(ILSVRC2012)におけるCNN活用モデルのひとつ。LeCunより後に登場。隠れ層が上下2つにわかれており、それぞれの隠れ層ごとにGPUを割り当てる。層数13、総ノード数831304
GoogLeNet画像認識(ILSVRC2012)におけるCNN活用モデルのひとつ。ILSVRC2015優勝。層数22
ノイズ除去画像の中の雑音部分(ノイズ)を取り除く処理
インペインティング処理画像の中から不要な部分を除去する処理。取り除いた後どう自然に埋めるかが課題
超解像処理解像度の低い画像から解像度の高い画像を作成する処理。スパースコーディングという方法を用いることが多い
輝度値きどち。各ピクセルの明るさを0から255の整数で表した値
RGB値各ピクセルの色について、赤・緑・青の割合をそれぞれ0から255の整数で表した値
画像特徴点隣り合う画素同士の間で、輝度値の差が大きい箇所を指す
画像特徴量画像特異点をベクトル値で表した値
Bag-of-featureディープラーニングを用いた画像認識手法が登場する以前に使われていた手法。同じ種類の物体が映っている画像同士は、似たような部分をたくさん持っているという考え方を元にしている。
Visual Word特徴を表す画像により作成されたグループの中の代表となるひとつの画像
正規化長さの値が1になるようにすること
ディープラーニング画像認識処理につよいニューラルネットワークを用いた手法。Bag-of-featureでは特徴量抽出の方法として、画像特徴量を利用するという約束を人が決めていたが、ディープラーニングでは自動で決めている。テストデータが少ないと姓のが出ないこと、識別結果のチューニングがむずかしいという欠点がある
バイアスノードディープラーニングにおけるニューラルネットワークの入力層および隠れ層はバイアスノードという特別なノードを持つ
全結合層ディープラーニングにおけるニューラルネットワークで利用される層のひとつ。前のノードと自分のノードが、すべてエッジで結ばれている(ただし自分のバイアスノードは除く)。隠れ層の後半や出力層に利用される
勾配法数値計算で関数の最小値を算出するときによく利用される方法の一つ。「ある値の勾配をもとめその勾配の方向に動かす」を繰り返す
学習量勾配法における「ある値の勾配をもとめその勾配の方向に動かす」際の動かす値を学習率という
確率的勾配法訓練データからひとつづつ適当に選んで更新処理を行う方法
ミニバッチ法訓練データから少数のデータを適当に選んで更新処理を行う方法
バッチ法すべてのデータを利用して更新処理を行う方法
順伝播ニューラルネットワークを用いて計算を行うときには、入力層から順番に隠れそうのノードの値が決まり、最後に出力層の値がきまる。この順番で計算されることを順伝播という
逆伝播順伝播の逆で、出力層から最後の隠れ層、その前の隠れ層..と逆に進み最後に入力層のノードの値が決まることをいう
誤差逆伝播法正しい値と評価結果の誤差を逆伝播することを誤差逆伝播法という。逆誤差電波法により、ニューラルネットワークの学習に勾配法を使うことができるようになる
Dropoutある更新で層の中のノードのうちいくつかを無効にして学習を行い、次の更新では別のノードを無効にして学習を行うことを繰り返す
Drop Connectエッジをランダムに無効化するDropout
Adaptive Dropoutランダムにノードを無効化するのではなく、適応的に無効化を行うDropout

よし、これで整理できたな..

2016年9月16日金曜日

Azure Machine Learning Studio 環境上でTensorFlowが動くか試してみた、が..だめだった..

#本記事には、一部翻訳がのっていますが
#つたない英語力で日本語化しているので
#参照される方は at your own risk でお願いします。

Azure Machine Learning Studioでは(Rや)Pythonが使えるとのこと。
実際にExecute Python Scriptというノードが有り、これを使うとAnaconda環境を使うことができるらしい。
ノードプロパティには、Anaconda2.7/Pythoin2.7.7Anaconda4.0/Python2.7.11Anaconda4.0/Python3.5のいずれかが動作するらしい。

プロパティ内には、以下のPythonスクリプトが編集可能な状態になっていた。


# The script MUST contain a function named azureml_main
# which is the entry point for this module.
# スクリプトには、このモジュールのエントリポイントになっている
# 関数うazureml_main()を必ず含めておかなくてはならない。

# imports up here can be used to
# インポートする場合はココに書けます

import pandas as pd

# The entry point function can contain up to two input arguments:
#   Param: a pandas.DataFrame
#   Param: a pandas.DataFrame
# エントリポイント関数は最大で2つの引数を指定できる:
#   Param: pandas.DataFrame値
#   Param: pandas.DataFrame値
def azureml_main(dataframe1 = None, dataframe2 = None):

    # Execution logic goes here
    # ココからロジックが実行される
    print('Input pandas.DataFrame #1:\r\n\r\n{0}'.format(dataframe1))

    # If a zip file is connected to the third input port is connected,
    # it is unzipped under ".\Script Bundle". This directory is added
    # to sys.path. Therefore, if your zip file contains a Python file
    # mymodule.py you can import it using:
    # import mymodule
    # もしZipファイルを3番めの入力ポートに接続した場合、
    # ".\Script Bundle"フォルダ下に解凍される。このフォルダは
    # sys.pathに追加される。このため、もしZipファイルにPython
    # ファイル mymodule.pyが含まれていたなら、それをimportに使用する
    # ことができます。


    # Return value must be of a sequence of pandas.DataFrame
    # pandafs.DataFrameシーケンスを必ず返却すること
    return dataframe1,

これつかえば、TensorFlowで書いたコードをかんたんにWebサービス化できるんちゃうの?

で、import tensorflow as tfazureml_main()の中に簡単なTensorFlowコードを入力してみた。


..が、動かなかった。

その時出たエラーは以下の通り。

Error 0085: The following error occurred during script evaluation, please view the output log for more information:
---------- Start of error message from Python interpreter ----------
Caught exception while executing function: Traceback (most recent call last):
  File "C:\server\invokepy.py", line 189, in batch
    mod = import_module(moduleName)
  File "C:\pyhome\lib\importlib\__init__.py", line 37, in import_module
    __import__(name)
  File "C:\temp\2aaf8e0ab30244b2880f412042c39f62.py", line 20, in
    import tensorflow as tf
ImportError: No module named tensorflow
Process returned with non-zero exit code 1

---------- End of error message from Python  interpreter  ----------
Start time: UTC 09/16/2016 05:06:38
End time: UTC 09/16/2016 05:06:57

そもそもTensorFlowがAnaconda上にインストールされていない。

自由にpip/condaできればいいのだけど、Studioからはいまのところ操作できないようだ。
そうか、プロパティでPythonバージョン指定のところがcondaコマンド代替なんだ..
 condaする前にTensorFlowをpipしてほしいのだけど..

Azureのヘルプを調べると、フォーラムに以下の質問がのっていた。



Tensorflow in AzureML

Question

I've seen a  blog post that says tensorflow can be used using docker in Azure.

Is there any way to use tensorflow as a python package inside AzureML,so that finally I can use it to build model and call it using web service.

Tuesday, September 06, 2016 2:25 PM TanayC



質問

私は、Azure上のdockerを使ってTensorFlowがつかえるというブログ記事を読みました。
最終的に私はモデルをビルドしてWebサービスとして呼び出せるようにするために、AzureML内部でpythonパッケージとしてtensorflowを使う方法がありますか?
2016年9月6日(火) PM2:25 TanayC


良い質問だ..で答えは..


Answer

TensorFlow is not supported on Windows OS right now. Hence we can't run it in Azure ML yet.

Marked as answer by Hai NingMicrosoft employee, Moderator Wednesday, September 07, 2016 1:12 PM Hai Ning (MSFT,Partner)


回答

現時点では、TensorFlowはWindowsOS上ではサポートされていません。このため、Azure ML上ではTensorFlowは動作しません。
2016年9月7日(水) MS社員 Hai Ning(MSFT, パートナ)

スクリプトにZipファイルにのくだりのコメントがデフォルトのスクリプトにあるので、てっきりZipファイルをAzure Blob Storageとかに置いておけば使えるのかと思っていたのに..

ひょっとしたら質問のほうにかいてあったようなDockerコンテナを使った実装になっていないからじゃないからかな..

..がっかり..
 

2016年9月15日木曜日

書籍「さわってわかる機械学習 Azure Macine Learning 実践ガイド」を読む


Watson APIはREST APIさえ知ってれば、
機械学習の知識ゼロでも始められる
ド素人向け開発だ。
こんなのお客様に出したらすぐバレる。

とはいえ、イチからごりがきするTensorFlowは難しい..



ユーザであるお客様にも機械学習全く知りませんよってことがバレないで、
もっと薄くうすーく機械学習をなめ、
いかにもやった感じになるような開発はできないものか..

ということで見つけたのが
MicrosoftのAzure Machine Learning Studio。

Microsoft Azure Machine Learning Studio
https://studio.azureml.net/

Node-REDのようにWeb UIでフローを組み立てて
(TensorFlowのdockerコンテナで動くjupyterのように)手動実行の統合開発環境と、
さらに機械学習を使った REST APIをつくってしまおうという
夢のサービスだ。

Free版もあるのだが、登録には
メールアドレスと携帯電話によるショートメッセージ認証だけでなく
Azureサブスクリプションを要求される。

男気ある人は有料サブスクリプションをここで即購入できるが
私はもちろん無料枠のサブスクリプションを使った。

それでもクレジットカード情報を要求してくるのは
何故だろう..

この辺りの手順が怖いという超ビビリの方は表題の書籍のAppendixに一挙手一投足の手順が書かれているので、こちらで確認のこと。



つくったアカウントでサインインして、Studioにログインして、

Machine Learning のチュートリアル: Azure Machine Learning Studio で初めてのデータ サイエンス実験を作成する
https://azure.microsoft.com/ja-jp/documentation/articles/machine-learning-create-experiment/

に従ってチュートリアルを実行してみた。

ところどころノード(?)のありかがちがうのと
"Project Columns"というノードが現在のAzure ML Studioにはみあたらず
"Select Columns in Dataset"を代わりに使ったくらいで
すんなり終わる。

非常にわかりやすいし、関数名ではなくツリー上になったリストからノードを貼りつけてフローを組み立てるので視覚的にもわかりやすい。

これならゴリゴリの人工知能屋でなくても
お客様にいかにも人工知能知ってますよ的な顔して開発できそうだ..


アマゾンで検索すると以下の日本語書籍も出版されていたので
購入して読んでみた。





にしても、もう本が出てるとは..さすがマイクロソフト、商売上手だ..

 1章は概要なのでななめ読みで読み飛ばす。

2章は、TwitterAPIをVisual Studioで使ってデータを集めようというもの。
Visual Studio Community版は無料だからこの章の内容をやれるけど、
実はこの章の内容は他の章では使用しないので無視。

4~6章は、先ほど紹介したチュートリアルをぱくった^H^H オマージュした内容となっており、日本人向けにデータも日本語化して、ノードの個々の説明や使っているプロパティ、画面の説明をことこまかくおしえてくれるないようになっている。

一部の価格欄が空欄になっている自動車情報を、線形回帰の学習モデルをつかって予測価格情報をもとめ、その制度を上げるため線形回帰のパラメータをかえたりベイズ線形回帰にかえたりして精度を上げたり、学習済みモデルを保存してそれを使い回したりする流れだ。

7章は、Classificationの例で、個人情報の年収を2つの分類に分ける(機械学習ではないが)操作を学習する。

8章は、クラスタリングの例で、アイリス(あやめ)の分類をK-Mean法を使った機械学習で分類する。

ここまでの章は、一挙手一投足で書かれていて、Project ColumnsをSelect Columns in Datasetに読み替えることだけわかっていれば、ド素人でもできるようになっている。

のに、9章のWeb APIは前の章とのつながりもないし、一挙手一投足でなくなっている..

たぶん8章で力尽きたんだろうなあ..ということでそうぞうしながらやってみた。

まず5-3章で学習済みモデルを使ってCSV出力するExprerienseを編集してAPI化することとして、該当Experienseを三角ビーカアイコンを選択して選ぶ。

 次に、Data Transaction>Manipulation>Select Columns in Dataserをドラッグしてノード「クルマ情報予想したいデータ.csv」と「Score Model」の間にはさんで接続し、Lunch column selectorボタンを押す。

 BY NAMEを選択し「価格」以外のすべての項目をSELECTED COLUMNSへ移動し、vアイコンを押す。
 Runを実行する。
 Runが完了したら、ノード「Convert to CSV」下部のポートを右クリックして「Download」を選択。
ダウンロードしたファイルをExcelではなく、UTF-8を表示できるエディタで開き、 価格欄の代わりにScored Labelsに予測自動車価格(車価)がでていることを確認する。

ノード「Convert to CSV」を削除して代わりに Data Transaction>Manipulation>Select Columns in Dataserをドラッグしてノード「クルマ情報予想したいデータ.csv」と「Score Model」の間にはさんで接続する。
 Lunch column selectorボタンを押し、「Scored Labels」のみSELECTED COLUMNSに移動し、vマークを選択する。
 Web Service>Inputをドラッグして、ノード「Web service input」をノード「Select Columns in Dataset」の横に配置して、ノード「Score Model」の右上ポートと接続する。Web Service>Outputをドラッグして、一番下のノード「Select Columns in Dataset」の更に下に配置し接続する。
 この状態でRunする。Runが終わったら、DEPLOY WEB SERVICEを選択する。

REQUEST/RESPONSE行のTestボタンを押す。

 パラメータに予測したいクルマの情報を入力し、vマークを選択。
 結果が画面下の方にJSON形式で先頭だけ表示される。ので、DETAILSを選択。
 JSON形式データが全部見えていることを確認する。


..超簡単だ..

これはナンチャッテ機械学習アプリ量産できそうだなあ..

最後の10章やろうとしたら、Azure Blob Storageが必要になり、Azureサブスクリプションが結局必要になるのだけど、実は10章やるまでに無料版が切れてしまい、試すことができませんでした..

10章は、9章でやらなかったBATCH EXCUTIONのところだったのになあ..

でも、このためだけに従量課金サブスクリプションを契約するのも癪だ..

別のMicrosoftアカウントとったけど、無料サブスクリプションを有効化しようとするとエラーになる..
同じクレジットカードだと作れないのか、同じ携帯電話番号だとだめなのか..

ということでココで諦めてしまいました。



でも、機械学習いっちょかみのカッコけたがりには、Azure Machine Learning Studioはいいサービスだと思うなあ..

2016年9月9日金曜日

書籍「TensorFlowはじめました」を3章まで読んでみる

TensorFlowをインストールして、
TensorFlowのチュートリアルをとりあえずなんとか勉強したら、
本くらい読めるようになっているかな..ということで
TensorFlowの本を読んでみた。

読んでみた本は、これ。
注意:以降の記事内容は本を持っている前提で書いてます。持ってない人が読んでもちんぷんかんぷんに終わると思います。


正直、夏と冬に2回しか店を開かないトコで入手したかのような
表紙かつ薄さ..

実はインストールする前にこの本を買ったのだけど、
この本インストール手順すら書かれてない
いきなりチュートリアルが始まる体だし、

実行するコード全体を表示していないので、
サンプルコードのダウンロードページから落としてこないと
全部のコードを入手できない。

なんとかよめんたのは2章の終わりp45まで。
ここまでで1週間かかりました..

GPUなしマシンのCoreOS上で

docker run -it p 8888:8888 - 6006:6006 gcr.io/tensorflow/tensorflow

でJupyter(PythonのWeb UI開発環境)があがるのでポート8888を
ブラウザで開いて、1章は難なく読み切る。

ちなみに8月中旬ごろ上記コマンドで実行したTensorFlowは0.9版のほうだった。

ちなみにTensor Boardは、

docker exec -it <コンテナID> /bin/bash

して、

tensorboard --logdir=/notebooks/

してからポート6006をブラウザで開くと見ることができる。

この本、電子版は治ってるのかもしれないが、オプションのハイフンが1個だけになっているが、pythonコードの引数指定ではハイフンは2個必要だ。以降も同じ。

で、2章。CIFAR10データセットを使って画像分類するチュートリアル。

ホームディレクトリ/notebooksdataディレクトリを切り、ダウンロードしたファイルを置く。

data_batch_?.bin という形式のファイルだが、bmpやpng形式ではない。
そのためpythonプログラムを書いてpngに変換してみようというのが最初の部分。

そして、ホームディレクトリに、reader.pyconvert_cifar10_png.pyを本にある通りそのまま打ち込む。外部エディタで作る場合はUTF-8に変換しないとjupytoerに配置できない。

python convert_cifar10_png.py --file ./data/data_batch_1.bin

を実行すると、/notebooks/data/data_batch_1.bin-??-?.png というファイルが16個でてきた。開いてみると、猫や、自動車、商用車、馬など10種類のちいさな画像を分類していくというものらしい。
それをCNN(畳み込みニューラネットワーク)をTensorFlowで実装するというのが、この後の流れ。

model.pyも本に全コードがのっているので、写しとった(先頭の方にあるリンクからコードをダウンロードしたほうがてっとりばやい)。

本の解説からconv1conv2pool1pool2fc3fc4の6層からなるニューラルネットワークモデルであり、conv1conv2が畳み込み層、pool1pool2がプーリング層、fc3fc4が全結合層(Full-Connectedの略でfc)。

このファイルmodel.pyはネットワークモデルを実行する関数inferrence()が定義されているだけなので、これを呼び出して、Cifar10データセットを食らわせるinferrence.pyを作る必要がある。

ホームディレクトリ上から

scrppt inferrence.py && python inferrence.py && exit

を実行すると、正解ラベルと予測確率配列(分類0である確率、分類1である確率..分類9である確率)が1行毎に表示される。

ただこの段階だと、一切学習していないので、正解も何も、賽の目降ったほうが合ってるんじゃってくらいにひどい..

この本では、それを実際に学習させ、そのあと実行したら正答率がこれだけになりましたよってシナリオになっている。

学習用の計算モデルとTensorflowセッション実行するファイルがtrain.py。

同様にして実行してじりじり正解していく様子を確認する。

pythonコマンドで実行したら、プロセスの終わりにヒープが消えすっかり馬鹿になるが、そのあたりは3章でわかってくるようになっている。
正解と予測確率配列がずらずらでるだけだとわかりずらいので、関数eval()を作成し、正答率がでるようにtrain.pyを改良、できあがったものがtrain_with_eval.py

本では、結構学習できてるように書かれていたが、私の結果はこうなった。



..0.1って10種類だからランダムで選んだのと同じじゃん..

ただ、コードをいじらず2度めやってみたらもっといい正答率をだすようになった。このあたりの曖昧さが、 機械学習のマネタイズしにくいところだ..


で、2章はここまで。ここまでのPythonコードに、1行1行コメントを入れて、実際に何をやっているかを勉強しなおし、復習。で、よむと結構考えられて設計されているのよ。ただ後続の章を読まないと理解できない。変数空間をなぜ切っているのかとかは3章にいかないとわからない。なのでなんでまわりくどいことを..とおもうところはそのままにしてコードを読んだほうが良い。


ここまでは、実行したら消えていた。3章でデータ保存についてとフィルタ(weights)の可視化について書かれている。

3章先頭でtrain.pyを書き直しているが、これはやめてダウンロードページからtrain_with_eval.pyを落としてそのまま使用した。
次のvisualize_weights.pyがダウンロードページにないので、似たファイルvisualize_filter.pyをコピペして本に書いてあるとおりに書き直す。

フィルタというのは畳み込み層で使用した5×5の小窓(3チャネル(色))で、CIFAR10データを畳み込む場合ステップ1で合計64枚必要になる。

機械学習の学習はウェイトWとバイアスbの値を調整していく作業なので、このWの値がどう学習で変化していくかを可視化するために、3章ではfloatを0~255のuint8に変換して、ビットマップの色データにかえ、これをタイル上にしたビットマップを作るという視覚化のやりかたを教えてくれているのだ。

実際にやってみた結果を順番にならべgifアニメにしてみたのがこれ(ビットマップはgifアニメ変換時に勝手に拡大されている)。



こんなかんじに学習していってるのね..

と、ここまでのコードにコメントをつけてまる7日..

この薄い本、1ページ1ページが重い..

先は長いなあ..


それより、勉強を初めてずーっと気になっていること。

「なんでニューラルネットワークモデルを構築して学習させていくと、分類やら予測やらができるの?」

実はよくわかってないらしい..

コラム:注意事項
本章で実施する工夫については、筆者はその原理を理解しているわけではありません
TensorFlowのチュートリアルを見たり、先行して効果があるとされているモデルを参考にして実施しています。もし原理に興味がある人は、専門書などを参考にしてください。
また、畳込みニューラルネットワーク(CNN)を勉強していると「なぜうまく行くのかよくわかっていない」ということがあります。層の数や組み合わせや設定する値のベストプラクティス、なぜそれが高い効果をもたらすのか理論的な裏付けなどを皆で探しているのが現状のようです。

※書籍「TensorFlowはじめてみました」第4章p46より引用


..一部はわかっているものもあるのだろうけど、
結果としてうまく行っているから使ってしまおう
ってことのようです。

それって...

ディープラーニングって丸山ワクチン村井ワクチンとおんなじじゃないの?!

村井のクスリはよく効く


からって..

自動車や飛行機を運転させたり、


病気診断させたり、



自動投資につかったり、


いいのかね、倫理的に..

2016年9月8日木曜日

TensorFlowの"GET STARTED"を翻訳してみた

とりあえずCoreOS環境上にTensorFlowコンテナを上げたので
チュートリアルをやってみることにした。

TensorFlowトップページの上にある"GET STARTED"へ進んだIntroductionと
赤と青の錠剤画像リンク先のチュートリアルを翻訳してみた。

以下、参照される方は At your own risk でお願いします。

----------

イントロダクション


TensorFlowを動かせるようにしましょう!

ただ、はじめる前にPython APIを使ったTensorFlowのコードを見てみましょう、そしてどこを目指しているかを感じ取ってみましょう。

ここに、いくつかの2次元データを作成し、一本の線に合わせる小さなPythonプログラムがあります。

import tensorflow as tf
import numpy as np

# Create 100 phony x, y data points in NumPy, y = x * 0.1 + 0.3
x_data = np.random.rand(100).astype(np.float32)
y_data = x_data * 0.1 + 0.3

# Try to find values for W and b that compute y_data = W * x_data + b
# (We know that W should be 0.1 and b 0.3, but TensorFlow will
# figure that out for us.)
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.zeros([1]))
y = W * x_data + b

# Minimize the mean squared errors.
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

# Before starting, initialize the variables.  We will 'run' this first.
init = tf.initialize_all_variables()

# Launch the graph.
sess = tf.Session()
sess.run(init)
# Fit the line.
for step in range(201):
    sess.run(train)
    if step % 20 == 0:
        print(step, sess.run(W), sess.run(b))
# Learns best fit is W: [0.1], b: [0.3]

このコードの最初の部分は、データフローグラフをビルドしています。セッションが構築され関数が呼び出されるまで、TensorFlowは実際に計算を実行しません。

さらにあなたの食欲をそそらせるために、古典的な機械学習問題がTensorFlowによってどのように実現するのかを確認することを提案します。ニューラルネットワークの国で最も「古典的な」古典問題は MINST手書き数字分類 です。ここで二つのイントロダクションを出します、一つは機械学習初心者向き、もう一つはプロむきのものです。他のパッケージで何十ものMINST実装を 経験した方は、赤いピルを手にとってください。MINSTって何という方は、間違いなく青いピルを飲んでください。どっちかわからない場合は、まず青い方 をざっと眺め、次に赤い方を選んでください。

※上記の2つのリンク先はこの後に翻訳文を掲載しています


TensorFlowを勉強しインストールしたい方は、これらをスキップして前へ進む事もできます。気にしないでください、あなたはまたMNISTを勉強 することになります--TensorFlowの機能を詳しく調べる際の技術的チュートリアル内の例示でMNISTを使っています。


(イントロダクションページ:おわり)
 ----------
青いピル(初心者向け):

MNIST for Beginners


このチュートリアルの読者は機械学習やTensorFlowに不慣れな人向きを対象としています。MINSTとは何かを知っており、softmax (多変量ロジスティック)回帰とはなにか、を知っているのであれば、ペースの早いチュートリアル のほうがよいとおもいます。どちらのチュートリアルも開始前に、 TensorFlowのインストール を実施してください。

プログラムの書き方を学ぶ時、最初に"Hello, World"を表示するチュートリアルがあります。機械学習のMNISTはちょうどこのHello Worldに似ています。

MNISTは単純なコンピュータ画像データセットです。次のような手描きのイメージが含まれています:




それぞれのイメージにはラベルがあり、それがどの数字であるかがわかります。たとえば、上のイメージは、5、0、4、1です。

このチュートリアルでは、イメージを参照してそれがどの数字かを予測するためのモデルとして学習させます。ゴールは、(後でそのようになるコードを提供しますが)最新技術のパフォーマンスを成し遂げるような本当に精巧なモデルを学習させることではなく、むしろTensorFlowにつま先を浸すことにあります。Softmax回帰と呼ばれるとても単純なモデルからはじめます。

実際のコードはとても短く、最も興味のある部分はたった3行です。しかし、その裏には理解するためにはとても重要なことが潜んでいます;TensorFlowがどのように動くのか、そしてコアの機械学習のコンセプトです。このため、注意深くコード見ていく必要があります。


このチュートリアルについて


このチュートリアルでは、コード mnist_softmax.py にてなにがおこっているのかを、1行ごとに説明しています。

このチュートリアルを幾つかの使い方があります:

    Python環境内で、各行の説明をとおして、行ごとに、コードの断片をコピー&ペーストする。
    不明確なコード行を理解するために、説明を読む前もしくは後に、Pythonファイルmnist_softmax.py全体を実行する

どのようにして、このチュートリアルを完遂するのでしょうか:

    MNISTデータやsoftmax回帰について学習する
    イメージの各ピクセルを読み込むことで、数値を理解するモデルの関数を作成する
    TensorFlowを使って数千の例を 見て 数値を理解するモデルを学習させる(そして最初のTensorFlowセッションで語っていたことを実現する)
    テストデータを使ってモデルの精度をチェックする

MNIST データ


MNISTデータは、Yann LeCunのWebサイト にあります。このチュートリアルからコードをコピー&ペーストしたら、この2行のコード、自動的にダウンロードして読み込む、からはじめてください。

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


MNISTデータは3つの部分にわかれます:55,000点の学習データ(mnist.train)、10,000点のテストデータ(mnist.test)、5,000点の評価データ(mnist.validation)。この分割はとても重要です:学習しないデータを分けて実際に学習したものを汎化することは、機械学習の本質です。

前述したとおり、MINSTデータポイントは、手書き数字のイメージと関連するラベルの2つの部分があります。イメージを"x"ラベルを"y"とよびます。学習セットとテストセットは共にイメージとラベルを含んでいます;たとえば、学習セットのイメージはmnist.train.images、学習セットのラベルはmnist.train.labelsにわかれています。

それぞれのイメージは28ピクセル×28ピクセルです。これを数字の大きな配列に解釈することができます。

 

この配列をフラットにすると、28×28=784個の数字になります。イメージ間で一貫した方法であるかぎり、配列をいかに平にするかが重要ではありません。この展望から、MNISTイメージは784次元という、大変リッチな構造 のベクトル空間のたくさんの点であるといえます(警告:計算としては集中的な視覚化)。

データをフラット化することはイメージの2次元構造を捨て去ることになります。それは悪いことでしょうか?もっともよい画像計算手法はこの構造を活用します、それはチュートリアルの後ろのほうでとりあげます。しかし我々がここで使用する、softmax 回帰(定義は後述)では、このシンプルな方法を使います。

結果として、mnist.train.imagesは形が[55000, 784]のテンソル(n次元配列)となります。最初の次元はイメージリストのインデックスで、次の次元は各イメージのそれぞれのピクセルのインデックスです。テンソルの各エンティティは、あるイメージのあるピクセルの強さを、0から1の間で表しています。



MNISTの各イメージは、イメージ上に描かれた0から9までの数字をあらわすラベルをもっています。

このチュートリアルのために、「 one-hot なベクトル(one-hot vector)」としてのラベルを望んでいます。one-hot vectorは、1つの次元だけ1でほかはすべて0であるベクトルのことをいいます。この場合、n番目の数字はn時限目が1であるベクトルをあらわしています。たとえば、3は[0, 0, 0, 1, 0, 0, 0, 0, 0]となります。したがって、mnist.train.labelsは、ある[55000, 10] 次元浮動小数配列です。

これでモデル構築のための準備ができました。

Softmax 回帰(後退)


MNIST内のそれぞれのイメージは、0から9までの手書き数字であると知られています。このため、与えられたイメージはたった10の可能性があるものだけです。我々は、イメージを参照し、それぞれの数字である確率を知りたいということになります。例えば、我々のモデルはある写真に対して、9である確率が80%だが、8である確率が5%(上部のループの判断から)、そしてその他の数字である確率が残り、といったように100%正解をみつけられない場合があります。

これは、softmax回帰が自然で単純なモデルである、古典的なケースです。幾つかの異なったものにから一つを選びたい場合は、softmaxが使われます。なぜならsoftmaxは0と1の間の値のリストを返します。

softmax回帰には、2つのステップがあります:最初に特定のクラス内にあるインプットのエビデンスを追加します。次にエビデンスを確率に変換します。与えられたイメージはある特定のクラスに所属するエビデンスを総計するために、ピクセル強度を荷重和します。高い強度を持つあるピクセルがあるクラスに分類されるイメージに反するエビデンスであれば荷重は否定的(負)となり、正となるエビデンスであれば肯定的(正)となります。

次に続く図は、ある一つのモデルがこれらの分類それぞれから学習した荷重をあらわしています。赤い部分は否定的(負)荷重であることを表し、青い部分は肯定的(正)荷重であることを表しています。



またいくつかのバイアスと呼ばれる追加のエビデンスも加えています。基本的に、若干数のものが無所属のインプットであると言えるようになりたいのです。クラスiに対するインプットをxとすると、エビデンスは次の式で表すことができます:



ここで W_i はクラスiのウェイト(荷重)を、 b_i はクラスiのバイアス、jは入力イメージxのピクセル値の総和をとるためのインデックスをあらわします。次に、"softmax"関数を使って、エビデンス束を予測確率yに変換します:



ここでのsoftmaxは、"活性化(activation)"関数もしくは"リンク(link)"関数として用いられており、我々が望んでいる(ここでは10ケースにおける確率分布)アウトプットを1次関数として作っている。エビデンスの束をインプットがそれぞれのクラスである確率に変換すると判断することができます。次のように表します:



これを展開すると、次の式になります:



しかしsoftmaxを最初の方法(インプットのエキスポネンシャル(指数乗)をとり、正規化する)として判断することはしばしばより役立つことがあります。エキスポネンシャル(指数乗)は、エビデンスの1つ以上の単位がどんな推測(hypothesis)によって与えられるウェイト(荷重)を乗算的に増やすことを意味しています。そして逆に言えば、エビデンスの1に満たない単位は推測(hypothesis)が初期のウェイト(荷重)のわずかを得ることを意味します。推測(hypothesis)は、0以下のウェイト(荷重)を持つことはありません。そしてsoftmaxは、ウェイト(荷重)を正規化します。そのため1加算し、妥当な確率分布としてフォーマットします。(softmax関数についてより直感的に理解するために、Michael Nielsenの書籍のセクション 、双方向可視化による完全性をチェックしてください)

実際にはもっと多くのxが存在しますが、softmax回帰(後退)を次のように図示できます。アウトプットごとに荷重和を計算し、バイアスを加え、その後softmax関数を適用します。



この絵を方程式で書くと、次のようになります:



このプロシージャは、行列の掛け算とベクトル加算に変換して、 "ベクトル化"が可能です。これはわかりやすく計算に便利です。



更にコンパクトに書くと、次のようになります:



TensorFlowが使えるように、変えてみましょう。


回帰(後退)の実装


一般的に、Pythonで効果的な数値計算を実行するために、行列の掛け算のようなコストの掛かる処理を、Pyhton の外部で別の言語で実装された非常に効果的なコードを使って実行する NumPy のようなライブラリを使います。残念なことに、それぞれの処理がPythonに戻ってくることから多くのオーバヘッドが残ります。データ転送のためのコストが高いため、GPU 上や配信された方法で計算を実行したい場合、オーバヘッドは特に悪くなります。

TensorFlow もまた Python 外部で重いリフティングを実行しますが、それは将来オーバヘッドを回避するステップです。Pyhtonから独立して単一のコストのかかる処理を実行する代わりに、TensorFlowは完全にPython外部で実行する双方向処理のグラフで表現させます。(このような手法は、いくつかの機械学習ライブラリでみうけられます)。

TensorFlowを使用するために、最初にインポートが必要になります。

import tensorflow as tf

記号的な変数を操作することにより、これらの双方向処理を表現します。1つ作成してみましょう:

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

xは特定の値ではありません、TensorFlowへ計算の実行を問い合わせる際に入力する値、placefolderです。我々は、フラットにするとそれぞれ784次元ベクトルになるMNISTイメージを大量に入力可能にしたいと考えています。このMNISTイメージを、フォーマットが[None, 784]Noneは任意の長さとする)である浮動小数点数の2次元テンソルとして表現します。

またモデルのために、ウェイト(荷重)とバイアスも必要です。追加のインプットのようにこれらをあつかうように創造することも可能ですが、TensorFlowにはそれらをあつかう更によい方法Variableがあります。Variableは、双方向処理のTensorFlowのグラフに登場する修正可能なテンソルです。計算処理に使用でき、変更することができます。機械学習アプリケーションでは、それを一般的にモデルパラメータをもつ変数(Variables)にします。

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

初期値を与えられたtf.VariableとしたVariableを作成します:この場合、Wbをともにすべて0のテンソルとして初期化しています。一旦学習を始めてしまうと、初期値はあまり重要ではありません。
Wのフォーマットが[784, 10]であることに注意してください。なぜなら、我々は複数の784次元のイメージベクトルに対して、異なるクラスのエビデンスとして10次元ベクトルを作成して増やしたいためです。bのフォーマットは[10]であるため、アウトプットへ追加することができます。

これでモデルを実装することができるようになりました。定義するためには1行だけですみます!

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

最初にtf.matmul(x, W)により、xをWで掛け算します。複数のインプットでxを2次元テンソルとしてあつかうための小さなトリックとして、方程式にてWxとして増やした時にはじき出されました。そして、bを加え、最後にtf.nn.softmaxを適用しています。

それはそれとして。短い2行のセットアップコードの後ろに1行記述するだけでした。それはTensorFlowはsoftmax回帰(後退)は特に簡単に記述できるよう設計されているからではありません。機械学習モデルから物理学シミュレーションまで、多くの種類の数値計算を記述するために非常に柔軟な方法となっています。一度記述したら、どのマシンでも実行することができます:あなたのCPU、GPU、そして携帯電話でさえも!


学習


モデルを学習させるために、何がモデルにとって良いのかを定義する必要があります。機械学習において、実際には何がモデルにとって悪いのかを定義します。これをコスト、もしくは損失と呼び、モデルに対して我々の望む結果からいかにかけ離れているかを表します。我々はエラーを最小化しようとします、そしてエラーマージンがより少ないほど、モデルがより良くなります。

モデルの損失を決定するとても一般的な、とてもすばらしい機能を 交差エントロピー (cross-entropy)といいます。交差エントロピーは、情報学上において情報圧縮コードについての考察を起源としていますが、ゲーミングから機械学習まで多くの領域で重要であると注目されていました。次のように定義されます:



ここで、yは予測された確率分布を表し、y'は実際の分布(数字ラベルのついた one-hot ベクトル)を表しています。若干の粗い感覚として、交差エントロピーは、真実を記述するための我々の予測がいかに能率が悪いかを計測します。交差エントロピーの詳細に立ち入ることは、このチュートリアルのスコープ範囲外ですが、理解する 価値はあります。

交差エントロピーを実装するために、まず最初に正しい答えを入力するための新しいplaceholderを加えます:

y_ = tf.placeholder(tf.float32, [None, 10])

そして、交差エントロピー関数 を実装することができます:

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

最初にtf.logは要素ylog計算を実行します。次に、各要素y_と関連する要素tf.log(y)を掛け算します。そしてtf.reduce_sumは、reduction_indices=[1]パラメータにより、yの第2次元要素を加算します。最後にtf.reduce_meanは束内のすべてのexampleから平均を計算します。

ここでは、モデルに何をして欲しいかがわかっているので、TensorFlowに学習させることはとても簡単です。なぜならTensorFlow は計算グラフ全体を知っているので、誤差逆伝播法(バックプロパゲーション) アルゴリズムを自動的に使って、損失が最小となるよう影響するようにどのように変数を定義するかを、効果的に定義します。そして、損失を低減するように最適化アルゴリズムを適用して、変数を修正します。

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

この場合、勾配高価アルゴリズム を学習レート0.5で適用し、cross_entropyが最初になるようにTensorFlowに問い合わせています。勾配高価法は簡単な手順であり、単にTensorFlowがコストを下げる方向にすこし各々の変数をシフトするだけです。しかし、TensorFlowは、その他多くの最適化アルゴリズム も提供します:1行つまむのと同じくらい簡単に使うことができます。

ここで、TensorFlowが実際に舞台裏でなにをしていることは、誤差逆電波法(バックプロパゲーション)と勾配降下法を実装するグラフに新しい処理を追加しています。そして、勾配降下学習の1ステップ(損失を低減させるように変数を微調整する)を実行する処理を1つ後ろにします。

これで、モデル学習のためのセットアップができました。学習を開始する前の最後の作業として、作成した変数の初期化するための処理を生成する必要があります。これは定義しますが、まだ実行されないことに注意してください:

init = tf.initialize_all_variables()

Session内でモデルを起動します、そして変数の初期化処理を実行します:

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

さあ1000回学習ステップを実行しましょう!

for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

ループ行にて、学習セットから100個のランダムデータポイントの"batch"を取得しています。train_stepを実行し、バッチ内でデータをフィードしてplaceholderに変換しています。

ランダムデータの小さなバッチを使うことを確率的訓練(stochastic training)-ここの場合は、確率的勾配降下法(SGD:Stochastic Gradient Descent)-と呼びます。
理想的には、よりよい答えをえるために、すべてのデータを学習に使用したいのですが、それはとても(コストが)高くなります。このため代わりに、毎回異なるサブセットを使用します。これは(コストが)安く、同一の利益を得ることができます。


モデルの評価


モデルをどのようにして評価しましょうか?

ます最初に、正しいラベルをどこで予測したかを見つけてみましょう。tf.argmaxは、いくつかの軸に沿ってテンソル内の最も高いエントリのインデックスを取得するとても役に立つ関数です。たとえば、tf.argmax(y_,1)がただしいラベルである間、tf.argmax(y,1)は、我々のモデルがそれぞれのインプットに最適であると考えるラベルです。tf_equalは予測が真実に合致するかをチェックするために使うことができます。

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

それは、真偽値のリストを返します。どんな分数が正しいかを決めるために、浮動小数点数としてキャストして、平均をとります。例えば[True, False, True, True]は、まず[1,0,1,1]となり、0.75となります。

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

最後に、テストデータ上の精度を問い合わせます。

print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

これはおよそ92%でなければなりません。

これは良い値ですか?本当に?実際この値はかなり悪いです。これはとても簡単なモデルを使っているからです。幾つかの細かい変更を加えると、97%になります。もっともよいモデルは99.7%の精度を超える事ができます!(詳細は、この 結果リスト を見てください。)

我々はこのモデルから学んだということが重要です。これらの結果から少し気持ちが下がったのであれば、もっとよい勉強ができる 次のチュートリアル Deep MINST for Experts をチェックしてください。そして、TensorFlowを使ってより洗練されたモデルをビルドする方法を学んでください!

(青いピル:終わり)
----------
赤いピル(経験のある人向け):

Deep MNIST for Experts



TensorFlow は大規模数値計算のための強力なライブラリです。優れているタスクの一つがディープニューラルネットワークの実装と学習です。このチュートリアルでは、深層畳み込みMNIST分類の構築における TensorFlow モデルの基礎的なビルディング部を学習します。

このチュートラルでは、ニューラルネットワークとMNISTデータセットについて熟知していることを前提としています。もし、それらのバックグラウンドを知らないのであれば、初心者向けの概要( MINST For ML Beginners )を確認してください。開始前に、 TensorFlowのインストール を実施してください。


このチュートリアルについて


このチュートリアル解説における最初の部分は、mnist_softmax.py コードにて実行されます。2番めの部分では、精度向上のための幾つかの方法を紹介します。

チュートリアルからコード断片をPython環境へコピー&ペーストしてもよいですし、コードを読み通してもよいでしょう。

このチュートリアルでは次のことを実施します:

    イメージ内の各ピクセルを参照することを元にした、MNIST数字の理解のためのモデルとなるソフトマックス回帰(後退)関数の作成
    TensorFlowを使って数千もの例を"見る"ことで数字を理解するモデルを学習(そして最初のTensorFlowセッションで実行)
    テストデータを使ったモデル精度のチェック
    結果向上のための多層畳み込みニューラルネットワークのビルド、学習、テスト


セットアップ


モデルを作成する前に、まずMNISTデータセットをロードし、TensorFlowを開始します。


MNISTデータのロード


このチュートリアルからコードをコピー&ペーストする場合、データのダウンロードと読み込みを自動で行うこの2行から開始してください:

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

上記コードの、mnistはNumPy配列の学習セット、妥当性検査セット、テストセットを格納する軽量クラスです。後続で使用するデータミニバッチを通してのイテレーティングのための関数も提供します。


TensorFlow相互対話セッションの開始


TensorFlow は計算実行のために非常に効果的なC++バックエンドに頼っています。バックエンドとの通信はセッションと呼ばれています。TensorFlowプログラムの一般的な使い方は、最初にグラフを作成し、次にセッション内で起動します。

ここでは、TensorFlowコードをより柔軟に構築するために便利なInteractiveSessionクラスを代わりに使います。TensofFlowで実行するための 計算グラフ のビルド操作を対話式で行うことができます。特にIPythonのように対話を行いながら作業するため便利です。InteractiveSessionを使用しないのであれば、セッション開始や グラフの起動 前に全体の計算グラフをビルドすべきです。

import tensorflow as tf
sess = tf.InteractiveSession()


計算グラフ


Pythonを使って効果的に数値計算を行うために、一般的にNumPyライブラリを使います。NumPyは、Python外部で行列の掛け算のようなコストの高い処理を実行することができ、その他の言語による非常に効果的なコード実装が使えます。不運なことに、スイッチバックからPythonそれぞれの処理へのオーバーヘッドが未だとても大きいです。GPU上での計算や配信された方法では特にオーバヘッドが悪く、データ変換のために高いコストがかかります。

TensorFlowもPython外部でその重いリフティングを実行します。しかし将来的にはこのオーバヘッドを避ける方法がとられるでしょう。Pythonから独立した単一の高コストな処理の実行の代わりに、TensorFlow はPythong外部で全体的に実行する双方向操作のグラフとして記述させます。このアプローチは Theano や Toach に似ています。

Pythonコードの役割はそれゆえこの外部の計算グラフのビルドと、計算グラフのどの部分を実行すべきかの命令です。詳細は、Basic Usage Computation Graph セクションを参照のこと。


ソフトマックス回帰(後退)モデルのビルド


このセクションでは、単一の線形レイヤを使ったsoftmax回帰モデルをビルドします。次のセクションでは、これを複数の畳込みネットワークを使ったsoftmax回帰のケースに拡張します。


Placeholders


インプットイメージやターゲットとなるアウトプット分類のためのノード生成による計算グラフのビルドをはじめます。

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

ここでxやy_は特定の値ではなく、むしろ、placeholder(TensorFlowに計算の実行を問い合わせる時に入力する値)をさします。

インプットイメージxは浮動小数点数の2次元テンソルで構成されています。ここではx[None, 784]形式で割り当てています。ここで、784は28ピクセル×28ピクセルのMNIST入力イメージをフラットに1次元の配列にしており、Noneはバッチサイズに依存してサイズが決まる1次元目をあらわしています。ターゲットアウトプットクラスy_も2次元テンソルで構成されています。そして、それぞれの列が one-hotな 10次元ベクトルとなっており、関連するMNISTイメージが所属する数字分類(0~9)をあらわしています。
placeholderの形式はオプションですが、この指定によりTensorFlow にテンソル形状の矛盾から発生するバグを自動で受け取らせることになります。


Variables


モデルのウェイト(荷重)をW、バイアスをbと定義します。これらを追加的なインプットとしてあつかうことを想定できますが、TensorFlowではこれらをあつかうさらなる良い方法Variableがあります。Variableは、TensorFlowの計算グラフ内であつかう変数のことです。計算に使用したり更新する事が可能です。機械学習アプリケーションでは、一般的にモデルパラメータを保持するものはVariablesです。

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

tf.Variableへのコール内の各引数として初期値を渡しています。このケースでは、Wおよびbにすべてゼロのテンソルで初期化しています。Wは784×10の行列(785のインプットと10のアウトプットがあるため)、bは10-次元ベクトル(10種類の分類をもつため)です。

セッション範囲内でVariablesが使用される前に、初期化する必要があります。このステップでは既に特定されている初期値(このケースではすべてゼロのテンソル)を取得し、それらをVariableへ割り当てています。直ちにすべてのVariablesとして実行します:

sess.run(tf.initialize_all_variables())


予測クラスと損失関数


後退モデルを実装することができます。それはたった1行記述するだけです!ベクトル化されたインプットイメージxにウェイトWを掛け算し、バイアスbを加え、それぞれの分類に割り当てられるsoftmax確率を計算します。

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

簡単にちょうどの損失関数を特定することができます。損失はある一つの例におけるモデルの予測がいかに悪いかの指標です:全ての例に対して学習により最小化させることを試みます。ここでの損失関数は、ターゲットとモデルの予測の間の 交差エントロピー (cross-entropy)です:

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

tf.reduce_sumがすべての分類をとおした総和を計算し、tf.reduce_meanがそれらの総計から平均を計算していることに注意してください。


モデルの学習


モデルと学習損失関数の定義をおこなったので、モデルをTensorFlowを使って学習させることは簡単です。なぜなら、TensorFlowは全体の計算グラフを認識しており、それぞれの変数に関しての損失勾配を発見を自動的に定義することができます。TensorFlowは様々なビルトインされた最適化アルゴリズムを持っています。この例では、ステップ長0.5、交差エントロピーで降下する、最急降下法 (steepest gradient descent) を使用します。

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

TensorFlowでは、計算グラフに新しい操作を追加するために実際には1行で実行しました。これらの処理には降下の計算、パラメータ更新ステップの計算、そしてパラメータへステップを更新する処理がふくまれています。

実行時に、戻ってきたtrain_step処理はパラメータへ勾配降下を適用します。それゆえtrain_stepをクリ消し実行することによりモデルの学習を完遂することができます。

for i in range(1000):
  batch = mnist.train.next_batch(100)
  train_step.run(feed_dict={x: batch[0], y_: batch[1]})

100の学習例をそれぞれのイテレーション内でロードします。そしてtrain_step処理を実行します、その際学習例でplaceholderテンソルxとy_を置き換えるためにfeed_dictを使用しています。feed_dict使って計算グラフのテンソル(placeholderに制限されない)を置き換え可能なことに注意してください。


モデルの評価


我々のモデルはどれくらい良いのでしょうか?

まず、どこで正しいラベルを予測したかが分かります。tf.argmaxは、いくつかの軸に沿ってテンソルの最も高いエントリのインデックスを取得する、とても役に立つ関数です。例えば、 tf.argmax(y_,1)が真実のラベルであるとすると、tf.argmax(y,1)はモデルがそれぞれのインプットに最適であると考えるラベルとなります。tf.equalを予測と真実があっているかチェックするために使用することができます。

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

これは、真偽値リストを返します。割合が正しいを決めるために、浮動小数点数にキャストし、平均をとります。たとえば、[True, False, True, True]はやすとにより[1,0,1,1]となるので、平均は0.75となります。

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

最後に、テストデータにおける精度を評価することができます。ここでは約92%正確とでました。

print(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))


多層計算ネットワーク


92%の精度は、MNISTとしては良くありません。というか、気恥ずかしいほど悪い値です。このセクションでは、極めてシンプルなモデルから適度に洗練されたもの、小さな畳み込みニューラルネットワークへ、修正します。これでだいたい99.2%の精度になります--これは最高水準の技術ではありませんが、立派なものです。

ウェイトの初期化


このモデルを作成するためには、たくさんのウェイトやバイアスを作成する必要があります。通常、 対称性の破れ (symmetry breaking)や、0勾配をさけるために、少しノイズの入ったウェイトを初期化します。ReRU ( ランプ関数,正規化線形関数 )ニューロンを使っているので、"dead neurons"を避けるためにそれらをわずかに正値な初期バイアスでそれらを初期化することもよい方法です。モデルのビルド中繰り返しこれを実行する代わりに、二つの便利な関数を作成しましょう。

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)


畳込みとプーリング


TensorFlowもまたconvolution(畳み込み:特徴量の畳み込みを行う層)やpooling(プーリング:レイヤの縮小をおこない扱いやすくする層)に対する多くの柔軟性を提供します。バウンダリ(境界)をどのように扱いますか?ストライドのサイズはいくつにしますか?この例では、たいていバニラバージョン(何も手を加えないデフォルト状態)を選択しています。我々の畳み込みではストライドを1で水増しなしで使用しているため、アウトプットはインプットと同じサイズになります。我々のプーリングは2×2ブロックの単純で古いmax pooling(各領域内の最大値をとって圧縮を行う方法)です。コードをきれいに維持するために、関数のそれらの処理も要約してみましょう。

def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

最初の畳み込み層


最初の層を実装します。最初の層には、max poolingにより畳み込みをふくみ、そしてmax poolingが続きます。畳込みでは5×5パッチごとの32の特徴量を計算します。そのウェイトテンソルは[5, 5, 1, 32]という形式です。最初の2つの次元はパッチサイズです。その次は入力チャネルの数で、最後がアウトプットチャネルの数です。各アウトプットチャネルのための構造のバイアスベクトルも持っています。

W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])

レイヤに適用するために、まずxを、2番めそして3番めの次元がイメージの幅と高さに一致していて、4番めの次元が色チャネルの数に一致している4次元テンソルに変換します。

x_image = tf.reshape(x, [-1,28,28,1])

そしてx_imageをウェイトテンソルで畳み込み、バイアスを加え、ReLU関数を適用し、最後にmax poolしています。

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)


2番めの畳み込み層


深いネットワークを構築するために、このタイプの双をいくつか積み重ねます。2番めのレイヤは各5×5パッチの64個の特徴量を保持します。

W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)


全結合層(密層)


ここまででイメージサイズは7×7に低減されています。この状態で1024ニューロンの全結合層を加えてイメージ全体処理を許可します。テンソルをプーリング層からベク取りの束に変換し、ウェイトマトリクスで掛け算し、バイアスを加え、ReLUを適用します。

W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)


ドロップアウト


過学習 (overfitting)を減らすために、リードアウト層の前に ドロップアウト を適用します。ドロップアウト中ニューロンのアウトプットが維持される確率のためのplaceholderを作成します。これは学習中ドロップアウトをオンにし、テスト中にドロップアウトをオフにすることを許可します。TensorFlowのtf.nn.dropout opはマスキングに加えニューロンアウトプットのスケーリングを自動的に取り扱います、そしてドロップアウトは追加のスケーリングなしで動作します。

keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

この小さな畳み込みネットワークにおいて、パフォーマンスは実際にはドロップアウトあり、なしでほとんど同じです。ドロップアウトはしばしば過学習の低減するにはとても効果的ですが、とても大きなニューラルネットワークの場合とても役に立ちます。



リードアウト層


最後に、前述のsoftmax後退(回帰)を一つの層にしたような、softmax層を加えます。

W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

モデルの学習と評価


このモデルはどのくらいの良さでしょうか?モデルの学習や評価のために、簡単な一つの層のために上のSoftmaxネットワークに近いコードを使用します。

違いは:

    最急勾配降下オプティマイザをより洗練されたADAMオプティマイザに変える
    ドロップアウトレートをコントロールするために、 feed_dict 内にパラメータ keep_prob を追加する
    学習プロセスの各100番めのイテレーションにログ出力を追加する

先にすすみ、このコードを実行してください。20,000繰り返し学習を実施すると、プロセッサによりますが、すこじ時間がかかります(おそらく30分くらい)。

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices=[1]))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
sess.run(tf.initialize_all_variables())
for i in range(20000):
  batch = mnist.train.next_batch(50)
  if i%100 == 0:
    train_accuracy = accuracy.eval(feed_dict={
        x:batch[0], y_: batch[1], keep_prob: 1.0})
    print("step %d, training accuracy %g"%(i, train_accuracy))
  train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

print("test accuracy %g"%accuracy.eval(feed_dict={
    x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

コード実行後の最後のテストセットの正確さはおよそ99.2%になります。

これでTensorFlow を使ったかなり洗練されたディープラーニングモデルをいかに早く、簡単にビルド、学習、評価するかを勉強することができました。

(赤いピルおわり)
----------

青い方はナントカわかった..気がする。
コードをjupyter画面(コンテナ上で8888へアクセス)から入れると動くので、なんとなくわかった気がするが..
赤い方はいろいろ足りない、というか機械学習の本を読まんとわからない。

しかもどんな関数があるのかさっぱりわからない状態だし、活性化関数やらバックプロパケゲーションやら勾配降下法やら..畳み込みやプーリング..

イカン、脳がぷすぷすしてきた..


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

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