O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

TensorFlowをもう少し詳しく入門

11.409 visualizações

Publicada em

2017/06/30の講義で用いたもう少し踏み込んだ入門です

Publicada em: Tecnologia

TensorFlowをもう少し詳しく入門

  1. 1. 1 シンギュラリティ株式会社 第1章 TensorFlowの様々な機能 6月 TensorFlow講義 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  2. 2. 2 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved  自己紹介 新村拓也 - シーエイトラボ株式会社 代表取締役 - シンギュラリティ株式会社 取締役CTO
  3. 3. 3 普段やっていること  データマイニング案件の受託開発  データ整形〜実行環境におけるPDCAまで 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 要件定義及 びデータ項 目確認 設計 実験計画 データセット準備 モデ ル 実 装 学習・評価& チューニング  論文調査  手法選定  データ選定  インフラ設計 根幹に関わる部分なので慎重に 行う必要がある。  データセット収集  データセット作成  データ前処理  読込プログラム作成 経験上かなりの時間が 取られる  学習  評価  パラメータ変更  データ見直し もっとも時間がかかる フェーズ
  4. 4. 4 普段やっていること  データマイニング案件のコンサル  やりたいことがふわふわしているケースも結構多い 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved とりあえずAI 使っていい感じ にしたい ・・・・ 今あるデータと課題をヒアリング 今できることとできないことを整理して目標の明確化
  5. 5. 5 普段やっていること  データマイニング案件のコンサル  そもそもいきなりやるには無理な課題も多い 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved ドラえもん作って ・・・・ できる部分とできない部分を明確化して ロードマップを引いてお手伝いします 音声認識 文脈理解 感情判断 ・・・ はい、ぼくドラえもん 意味理解
  6. 6. 6 普段やってること  データマイニングエンジニア育成研修  基礎となる数学や統計  機械学習の各種手法  各手法の実装方法 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 短期間のものがほとんどですが、3ヶ月〜6ヶ月かけたフルコースのものも ご相談ください 最近やっていませんが、 たまに無料でもやってます!
  7. 7. 7 最近やっていること  自社サービス開発 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  8. 8. 8 本日の内容  TensorFlowの様々な機能  TensorFlow独自のモジュールや書き方についての解説  modelの保存、TensorBoard、高レベルAPI  それらの機能なども活かしつつ様々なネットワークを実装  DQN, DCGAN  時間があれば最近色々と実装の仕方が変わったりしつつあるRNN の内容も話します  ソースコードは以下 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved https://github.com/TakuyaShinmura/lecture20170630.git
  9. 9. 9 TensorBoardにおけるモデル保存 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  10. 10. 10 TFのモデルの保存方法  TensorFlowから読み込めるCheckpointファイル  基本的な方法はこちら  実行環境にPython/TensorFlowがインストールされている場合に用 いる  ProtocolBuffers形式でのエクスポート  学習したモデルをiOSやAndroidで動かす際に用いる  Pythonで学習したモデルを他の端末で実行するとき 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved ProtocolBuffers Googleが開発したシリアライズフォーマット。JSONやXMLのようなもの。 今回はTFがインストールされていることを前提として Checkpointを用いたモデル保存を説明します。
  11. 11. 11 今回やること  おなじみMNISTを用いた手書き文字認識  学習の過程で一定ステップごとにモデルを保存  訓練が終わって、再び学習した時に今まで学習を行ったステップから再 開できるように 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 学習(1000ステップ) モデル出力 読込 再学習(1000-2000ステップ) 出力 モデル2
  12. 12. 12 割愛 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  13. 13. 13 モデルを保存するには 1. tf.train.Saverオブジェクトを生成 2. 保存したいステップの時にsave 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved saver = tf.train.Saver() with tf.Session() as sess: sess.run(init) for i in range(1000): #step数とイテレーション数を合わせる step = i + 1 (訓練・割愛) if step % 100 == 0: saver.save(sess, ‘models/my_model’, global_step = step) models直下にmy_modelという名前で 名前の後に何step目のモデルかを付与
  14. 14. 14 何が起こるか?  models直下になんかいっぱい出てきます 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  15. 15. 15 ファイルの説明  checkpoint  1ファイルのみ生成  今このディレクトリにどのファイルがあって、最新がどのファイルかを 記載している  エディタで開ける 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved model_checkpoint_path: "my_model-1000” all_model_checkpoint_paths: "my_model-600” all_model_checkpoint_paths: "my_model-700” all_model_checkpoint_paths: "my_model-800” all_model_checkpoint_paths: "my_model-900” all_model_checkpoint_paths: "my_model-1000" 最新のモデル 全てのモデル
  16. 16. 16 ファイルの説明  拡張子metaファイル  例: my_model-1000.meta  構築したモデルの構造を記述したファイル  重みなどのは保持しない  モデル構築をプログラム内で記述する限りは何ステップ目であろう が普通は変更されることはない(ファイル出力するだけ無駄) 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved saver.save(sess, ‘models/my_model’, global_step = step, write_meta_graph=False) こうしておけば生成されなくなる
  17. 17. 17 ファイルの説明  拡張子dataファイル  実際の重みの値が入ったバイナリ  拡張子indexファイル  どのファイルがどのstepのものかを一意に特定するためのバイナリ 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved これらはsaveメソッドを呼んだ数だけ 生成される 100-1000ステップまで10件ずつ出 来上がるはずなのにどうして600- 1000の5件しかないのだろう?
  18. 18. 18 tf.train.Saver()について  無限に増えてディスクを圧縮しないように何世代までは保存するかを制 御してくれている  max_to_keepを0かNoneにすると全て生成される(オススメはしない)  他にも何時間分だけ生成のようなことも可能 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved saver = tf.train.Saver(max_to_keep=3) #3世代までに制限
  19. 19. 19 tf.train.Saver()について  第一引数に何も入れていないと、それまでに出てきたgraph内の全ての 変数を保存するという意味になる  一部だけを保存したい(特定の層だけ保存など)は 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved saver = tf.train.Saver( {'v1': v1, 'v2': v2} )
  20. 20. 20 保存したモデルを読み込むには 1. checkpointファイルがあるかどうかを確認 2. モデル読み込み 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved with tf.Session() as sess: ckpt_state = tf.train.get_checkpoint_state('models/’) if ckpt_state: #読み込み処理 last_model = ckpt_state.model_checkpoint_path saver.restore(sess, last_model) else: #初期化 sess.run(init)
  21. 21. 21 補足 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved model_checkpoint_path: "my_model-1000” all_model_checkpoint_paths: "my_model-800” all_model_checkpoint_paths: "my_model-900” all_model_checkpoint_paths: "my_model-1000" last_model = ckpt_state.model_checkpoint_path saver.restore(sess, last_model) これのこと 残り三つはProtocolBuffers の定義上は配列 model = ckpt_state. all_model_checkpoint_paths[0] saver.restore(sess, model) こうすれば上記だと800ステップ目のファイルを読み込める ※tensorflow/tensorflow/python/training/checkpoint_state.protoをご覧ください
  22. 22. 22 ステップ数の制御  1回訓練が終わってしまうと今何ステップ目かわからない  checkpointのファイルをopenして文字処理してステップ数取得!  現在のステップ数も変数として保存してしまう 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 美しくない global_step = tf.Variable(0, name='global_step', trainable=False) train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss, global_step=global_step) minimizeメソッドにメソッドのglobal_step引数に変数を入れておく とminimizeメソッドを呼ぶ時にincrementしてくれる!
  23. 23. 23 おまけ  TFのモデル構築を同一ファイル内でやらない場合はmetaファイルが入 ります  実行用のプログラム自体はシンプルにしたい時など 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved with tf.Session() as sess: saver = tf.train.import_meta_graph(’models/my_model-1000.meta') last_model = ckpt_state.model_checkpoint_path saver.restore(sess, last_model) その前でグラフが定義されていないのでこれを先に入れないとエラーになる
  24. 24. 24 実行デモ 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  25. 25. 25 まとめ  tf.train.Saver()メソッドでグラフ内の全変数を保存対象に  max_to_keepで世代は制御  saveメソッドでモデルを保存  write_meta_graph=Falseをお忘れなく  ckptファイルの中身を指定してrstoreメソッドで値をロード  ckpt自体がないときは初期化するようにするとよい  ステップ数保持のためにminimizeメソッドのglobal_step引数を利用す る 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  26. 26. 26 TensorBoardについて 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  27. 27. 27 TensorBoard  TensorBoardとは?  Webベースの構築モデル及び各種ログ可視化ツール  Scalars ・・・スカラ情報と時系列情報の関係  Images・・・画像データ  Audio・・・音声データ  Graphs・・・データフロー、使用デバイス、計算量などの可視化  Distributions・・・確率分布情報と時系列情報の関係  Histograms・・・度数分布情報と時系列情報の関係  Embeddings・・・データを空間に組み込んで可視化  Text・・・r1.1から追加。テキスト情報 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved デバッグや結果の考察に利用 することにより機械学習のイテ レーションをサポートする非常に 強力なツール
  28. 28. 28 TensorBoardの使うには? 1. 必要なところにログを取得するオペレーションを定義 2. 定義したらこれらのオペレーションをマージすることも可能 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved loss_summary = tf.summary.scalar(‘loss’, loss) # Scalars img_summary = tf.summary.image(‘input_data’, images, 10) # Images w_histogram = tf.summary.histogram('w', w) # Histograms, Distributions # 全てのログをマージするオペレーション summary_op = tf.summary.merge_all() # 一部のログをマージするオペレーション summary_op = tf.summary.merge([loss_summary, img_summary]) ※出力結果などを得るのと同様、ログもSession内で実行しないとログを取ってくれない
  29. 29. 29 TensorBoardを使うには? 3. Writerを呼び出して対象のグラフと出力先を指定 4. ログ取得のオペレーションを実行してその結果をWriterで書き込み 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved summary_writer = tf.summary.FileWriter( ‘logs’, sess.graph) ※宣言するとGraphsに対象のデータフローが描画される # ログ取得を実行 summary = sess.run(summary_op, feed_dict={x:hoge, y:fuga}) # 取得した結果をwriterで書き込み summary_writer.add_summary(summary, step)
  30. 30. 30 TensorBoardを使うには? 6. 出来上がったログの上位のディレクトリをtensorboardコマンドで指定 7. ブラウザでポート6006番にアクセス 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved tensorboard –logdir ./logs/
  31. 31. 31 Events  スカラ情報と時系列情報を可視  誤差、学習率など  Step、Relative(相対時間)、Wall(絶対時間)ごとに見ることができる。  CSV、JSON形式でのダウンロードも可能 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  32. 32. 32 Images(画像データ出力)  注意点  画像でなければモデル構築時にエラー  (batch_size, width, height, channel)の4階テンソル  チャンネル数は1, 3, 4に対応  活用例  DataAugumentation時の画像確認  いちいち画像出力をしてlocalに落としてきてみる手間の削減  重みの可視化(グレースケール扱い)  畳み込み層のカーネルの可視化 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  33. 33. 33 Distributions  入力項目  数値のテンソルならなんでも可能  活用例  重みや出力の分布観測  重みも誤差も収束しているならうまくいっている、など 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved 100% 93% 84% 69% 50% 色の濃さは分布の割合 をあらわす。
  34. 34. 34 Histogramus  Distributionsが確率分布を可視化するのに対してHistogramsは度数分 布を可視化  Distributionsを別の観点から見たもの 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  35. 35. 35 Graphs(モデル可視化) 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved 定義したグラフの中身を可視化
  36. 36. 36 Graphs(モデル可視化)  計算量やメモリ使用量、どのデバイスによる実行かも可視化可能 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  37. 37. 37 Embeddings  高次元データを、PCAとt-SENを用いて3次元空間に組み込み  中間層の値などを組み込んで分類がうまくいっているかを確認 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved ※ログの取り方が他のものとはかなり違う
  38. 38. 38 Text  TensorFlow1.1から追加  文章情報を保持  各ステップで生成した文章などを確認できる 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  39. 39. 39 これからやること  先ほどのプログラムを改良してTensorBoardのログを取れるようにする  Scalars, Images, Graphs, Distributions, Histogramsを動かしながら 説明  テストデータを用いいて学習済み中間層の値を組み込み  Embeddingを動かしながら説明  おまけでText用のサンプルプログラムを用いてTextを説明 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  40. 40. 40 前準備  定数なども増えてくるのでtf.app.flagsを用いて一元管理 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved import tensorflow as tf FLAGS = tf.app.flags.FLAGS tf.app.flags.DEFINE_string('data_dir', 'data/', "data set directory.") tf.app.flags.DEFINE_float(‘learning_rate’, 0.5, “learning rate.”)’ ・ ・ ・ def main(argv): # 行う処理 if __name__ == '__main__': tf.app.run() こう書くことでargparseなどを用いる必要がなくなる
  41. 41. 41 入力画像のログを取る  画像ではなくバイナリできているので、パーサーがうまく動いているか不 安な時など  第一引数は保存する際のname, 第二引数が画像のTensor  tf.summary.imageの第三引数は最大で何枚保存するかを指定 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #データセット作成 mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True) x = tf.placeholder(tf.float32, [None, 784], name='input') #入力画像を確認 images = tf.reshape(x,[-1,28,28,1]) tf.summary.image("input_data", images, 10) 入力画像は3階テンソルでないといけないのでreshapeする。
  42. 42. 42 name_spaceの活用  そのまま書くと、オペレーションが多すぎてGraphsが訳のわからないこ とになるので、処理単位でname_spaceを切ってあげる  オペレーションにも変数にもnameを振るとあとあと楽  h_1はこの場合「inference/hidden/feature:0」という名前で保存される 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #推論 with tf.name_scope('inference'): with tf.name_scope('hidden'): w_1 = tf.Variable(tf.truncated_normal([784, 64], stddev=0.1), name='w') b_1 = tf.Variable(tf.zeros([64]), name='b') h_1 = tf.nn.relu(tf.matmul(x, w_1) + b_1, name='feature')
  43. 43. 43 分布やスカラーの誤差を取る  tf.summary.histogramを定義するとDistributions, Histograms両方の 画面が活用できる  Tensorのshapeはなんでも良い  Scalarについてはその名の通りスカラー(0階テンソルを入れる必要が ある) 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #誤差 with tf.name_scope('loss'): each_loss = tf.reduce_mean(tf.square(y-out), axis=[1]) loss = tf.reduce_mean(each_loss) tf.summary.histogram('each_loss', each_loss) tf.summary.scalar("loss", loss) 単なる平均誤差時だけでなく、分布を取ると最大誤差や最小誤差 もTensorBoardで確認できる
  44. 44. 44 ログのマージ  本来今まで仕込んだログを、sess.run([log1,log2,・・・])しないといけな いのだが面倒  下記のようにすると、sess.run(summary_op)で全てのログが取得可能  とりたいログを全てグラフ上で定義した後に宣言する必要がある  一部だけマージしたければ以下のように 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #ログのマージ summary_op = tf.summary.merge_all() #ログのマージ summary_op = tf.summary.merge([log1, log2, log3])
  45. 45. 45 Writerの定義  ログ出力先、対象のグラフを引数に与える  複数のwriterを定義(出力先を分離)すればパラメータが異なる場合や 訓練、テストを分けてログ出力可能 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #writerの宣言 summary_writer = tf.summary.FileWriter(FLAGS.log_dir, sess.graph)
  46. 46. 46 一定ステップごとにログ保存  頻繁にとりすぎるとIOがボトルネックになり、学習フェーズがいくら早くて もプログラムの実行が終わらないので注意 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved # 一定ステップごとにログを吐く if step % 10 == 0: run_opt = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE) run_meta = tf.RunMetadata() #ログ取得を実行 summary_str = sess.run(summary_op, feed_dict={x:test_images, y:test_labels}, options=run_opt, run_metadata=run_meta) #結果をログファイルに出力 summary_writer.add_summary(summary_str, step) summary_writer.add_run_metadata(run_meta, 'step%d'%step)
  47. 47. 47 TensorBoardデモ 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  48. 48. 48 Embeddingsを用いるには  注意して欲しいのが、embeddingはTensorBoardのログファイルを見な いで、前章で説明したチェックポイントファイル(.dataファイル)を見てい る  ログファイルはないけど何やら重み、バイアスを組み込もうとしている  見ているのはtf.Variable()の情報 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved tensorboard –logdir ./models/
  49. 49. 49 Embeddingsを用いるには 1. 組み込みたい値をtf.Variableの形で定義 2. チェックポイント形式で保存してあげる([バッチサイズ,要素数]の2階テ ンソル) 3. 各ベクトルとラベルの組み合わせを用意してあげる 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 現状のプログラムだと中間層の値をVariableとして保存していないので 一手間必要 どの画像がどのラベルなのかは順番の変わらないTestデータを用いれば 簡単に作れそう
  50. 50. 50 学習済みのデータからロード 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved with tf.Session() as sess: state = tf.train.get_checkpoint_state(FLAGS.model_dir) #構築済みのmetaデータをロードしてくる。 #グラフを定義していないのでdefaultグラフにロードされる meta_path = FLAGS.model_dir + FLAGS.meta_file saver = tf.train.import_meta_graph(meta_path) #最新の値でモデルをロード saver.restore(sess, state.model_checkpoint_path) 前章ではあまり話さなかった.metaファイルを用いてロードすると楽
  51. 51. 51 必要な値にアクセス  特に定義していないとデフォルトのグラフにロードされる  ネームスペースに注意して必要な情報にアクセス 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #デフォルトグラフにアクセス graph = tf.get_default_graph() #グラフから必要な要素を取得してくる x = graph.get_tensor_by_name('input:0') feature = graph.get_tensor_by_name('inference/hidden/feature:0') test_images = mnist.test.images #feature_valにテストデータを入力した時の実際の値が入る feature_val = sess.run(feature, feed_dict={x: test_images}) name_spaceに注意して値をロード
  52. 52. 52 値を初期化して保存  ロードしたモデルはmodels/だが、今度保存するのはlogs/にするので注 意 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #初期値をfeature_valの値にしてあげて初期化して保存 embed_val = tf.Variable(feature_val, trainable=False, name='embedded') sess.run(tf.variables_initializer([embed_val])) #保存 saver2 = tf.train.Saver([embed_val]) saver2.save(sess, FLAGS.log_dir+'feature') 初期値に実際の値を入れて初期化すると必要な変数が手に入る この場合Saverは変える必要がある
  53. 53. 53 残タスク 1. 組み込みたい値をtf.Variableの形で定義 2. チェックポイント形式で保存してあげる([バッチサイズ,要素数]の2階テ ンソル) 3. 各ベクトルとラベルの組み合わせを用意してあげる 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  54. 54. 54 メタデータとのひもづけ  ややこしそうがやっていることは  下記のファイルを作ること 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved Index Label 0 7 1 2 2 1 3 0 4 4 5 1 meta.tsv embeddings { tensor_name: "embedded:0" metadata_path: "meta.tsv" } projector_config.pbtxt 何番目のベクトルが〇〇の画像だよ 組み込んだベクトルの名前とその対 応ファイルがどこにあるか?
  55. 55. 55 projector_config.pbtxt  おまじないが多いが、要するにtensor_nameとmetadata_pathを設定し ているだけ 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #メタデータと対象のVariable の紐付けを行う summary_writer = tf.summary.FileWriter(FLAGS.log_dir) config = projector.ProjectorConfig() embedding = config.embeddings.add() #Variableの名前を登録 embedding.tensor_name = embed_val.name #メタデータファイル名(TensorBoard起動ディレクトリからの相対パス) embedding.metadata_path = "meta.tsv” #登録 projector.visualize_embeddings(summary_writer, config)
  56. 56. 56 meta.tsv  ただのファイル整形 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  57. 57. 57 TensorBoardデモ 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  58. 58. 58 Text  name_scopeやステップ数を分けて文章を表示する用のもの  まだ、できたばかりであまりあっても個人的にはありがたくない  文章生成などの結果確認を可視化できる 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  59. 59. 59 Textの使い方  Text型のTensorを使うことはあまりないが、普通のテンソルと変わらな い  一応別のname_scopeでもとってみる 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved text_list = ['text0','text1','text2','text3','text4','text5'] # tf.constantを使ってもいい test_string = tf.convert_to_tensor('Test String.') outer_summary = tf.summary.text('out',test_string) with tf.name_scope('scope_test') as scope: text_ph = tf.placeholder(tf.string,name='input') inner_summary = tf.summary.text('in', text_ph) summary_op = tf.summary.merge_all() あとは割愛
  60. 60. 60 TensorBoardデモ 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  61. 61. 61 まとめ  基本はログ取得・マージ・書き込み  name_scopeをうまく活用してより見やすい形にする  Embeddingsは特殊なので注意  様々な機能があるので用途に応じて柔軟に使い分ける  Webベースなので結果をみるだけならTensorFlowの実行環境はいらな いのがいいところ 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  62. 62. 62 TensorFlowの高レベルAPI 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  63. 63. 63 tf.layers.dense  DNNの一般的な隠れ層(中間層)を簡単に実装できる • 重み、バイアスを初期化してreluでの活性化までを1行で記述可能 (tf.Variableの定義を隠蔽できる) • 重み、バイアスの初期値は、kernel_initializer/bias_initializer引数で指定可能 • 活性化関数は、activation引数で指定可能(指定なしの場合は恒等関数) • バイアスが不要な場合は、use_bias引数をFalseにすればよい(デフォルトはTrue) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved # 使わない場合 w_hidden = tf.Variable(tf.truncated_normal([128, 10], stddev=0.1)) b_hidden = tf.Variable(tf.zeros(shape=[10])) out_hidden = tf.nn.relu(tf.matmul(x, w_hidden) + b_hidden) # 使った場合 out_hidden = tf.layers.dense(inputs=x, units=10, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.1), bias_initializer=tf.zeros_initializer())
  64. 64. 64 tf.layers.conv2d  CNNで使用する畳み込み層を簡単に実装できる • 重み、バイアスを初期化して畳み込みを行い、reluでの活性化までを1行で記述可能 (tf.Variableの定義を隠蔽できる) • 重み、バイアスの初期値は、kernel_initializer/bias_initializer引数で指定可能 • 活性化関数は、activation引数で指定可能(指定なしの場合は恒等関数) • バイアスが不要な場合は、use_bias引数をFalseにすればよい(デフォルトはTrue) • ストライドはデフォルトで(1,1)なので指定不要。それ以外の場合はstrides引数で指定する 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved # 使わない場合 w_conv = tf.Variable(tf.truncated_normal([5, 5, 3, 32], stddev=0.1)) b_conv = tf.Variable(tf.zeros(shape=[32])) conv = tf.nn.conv2d(x, w_conv, strides=[1, 1, 1, 1], padding= ’SAME’) out_conv = tf.nn.relu(conv + b_conv) # 使った場合 out_conv = tf.layers.conv2d(inputs=x, filters=32, kernel_size=[5, 5], padding=’SAME’, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.1), bias_initializer=tf.zeros_initializer())
  65. 65. 65 逆畳み込みについて  DCGANなどにもちいられるアーキテクチャ  fractionally-strided convolution 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 元の特徴マップ(3×3) アップサンプリング後の 画像・特徴マップ(5×5) 元となる特徴マップをパディングして拡大してから、カーネル(フィルタ)を適用。
  66. 66. 66 tf.layers.conv2d_transpose  DCGANなどで使用する逆畳み込み層を簡単に実装できる • 重み、バイアスを初期化して逆畳み込みを行い、reluでの活性化までを1行で記述可能 (tf.Variableの定義を隠蔽できる) • 重み、バイアスの初期値は、kernel_initializer/bias_initializer引数で指定可能 • 活性化関数は、activation引数で指定可能(指定なしの場合は恒等関数) • バイアスが不要な場合は、use_bias引数をFalseにすればよい(デフォルトはTrue) • tf.layers.conv2dとほぼ使用感は同じ 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved # 使わない場合 w_deconv = tf.Variable(tf.truncated_normal([5, 5, 64, 32], stddev=0.1)) b_deconv = tf.Variable(tf.zeros(shape=[32])) deconv = tf.nn.conv2d_transpose(x, w_deconv, strides=[1, 2, 2, 1], padding= ’SAME’) out_deconv = tf.nn.relu(deconv + b_deconv) # 使った場合 out_conv = tf.layers.conv2d_transpose(inputs=x, filters=32, kernel_size=[5, 5], strides=[2, 2], padding=’SAME’, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.1), bias_initializer=tf.zeros_initializer())
  67. 67. 67 tf.layers.max_pooling2d  CNNで使用する最大プーリング層を実装できる • pool_sizeを2次元で指定(tf.nn.max_poolの場合は4次元)できるため少し簡略化可能 • stridesを1次元で指定(tf.nn.max_poolの場合は4次元)できるため少し簡略化可能 • padding引数はデフォルトが’VALID’のため、’VALID’を指定する場合は引数不要 (tf.nn.max_poolはデフォルト値がないので、必ず指定) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved # 使わない場合 pool = tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding=’SAME’) # 使った場合 pool = tf.layers.max_pooling2d(x, pool_size=[2, 2], strides=2, padding=’SAME’)
  68. 68. 68 tf.layers.average_pooling2d  CNNで使用する平均プーリング層を実装できる • pool_sizeを2次元で指定(tf.nn.avg_poolの場合は4次元)できるため少し簡略化可能 • stridesを1次元で指定(tf.nn.avg_poolの場合は4次元)できるため少し簡略化可能 • padding引数はデフォルトが’VALID’のため、’VALID’を指定する場合は引数不要 (tf.nn.avg_poolはデフォルト値がないので、必ず指定) • tf.layers.max_pooling2dとほぼ使用感は同じ 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved # 使わない場合 pool = tf.nn.avg_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding=’SAME’) # 使った場合 pool = tf.layers.average_pooling2d(x, pool_size=[2, 2], strides=2, padding=’SAME’)
  69. 69. 69 tf.layers.dropout  過学習抑制効果のあるドロップアウトを実装できる(1) • Dropoutはニューラルネットワークの過学習を防ぐためのテクニック • 一定の確率でランダムにニューロンを無視して学習を進める正則化の一種 • アンサンブル学習といって、複数の認識器の出力結果を利用することで効果が上が ることが分かっているが、ランダムにニューロンを消去することで、毎回異なるニュー ラルネットワークで学習させることができ、アンサンブル学習と同等の効果が見込め る • デメリットとして、学習速度が遅くなるということがあげられる 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 学習時に、一定の確率でニューロンを無視する。 バックプロパゲーション時に、重みの更新はされない。 ミニバッチごとに異なるニューロンを無視する。
  70. 70. 70 tf.layers.dropout  過学習抑制効果のあるドロップアウトを実装できる(2) • tf.layers.dropoutでは、学習時にtraining引数をTrueにすることでドロップアウトを実施し、 テスト時はドロップアウトさせたくないのでFalseにすることで切り替えが可能となる。 • tf.layers.dropoutのrate引数は、ドロップアウトする割合を指定するのに対し、 tf.nn.dropoutのkeep_prob引数はドロップアウトしない割合を指定することに注意。 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved # 使わない場合 drop_out = tf.nn.dropout(x=inpt, keep_prob=0.6) # 使った場合 drop_out = tf.layers.dropout(inputs=inpt, rate=0.4, training=is_training)
  71. 71. 71 tf.contrib.layers.batch_norm  Batch Normalizationを簡潔に実装できる(1) • DNNでは、学習を行うごとに中間層への入力分布が変化(内部の共変量シフト) ⇒ネットワークが不安定になりパラメータがあらぬ方向に更新される恐れ ⇒ネットワークがサチりやすい状態になる ⇒層が深いほど影響は大きい 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved  上記を防ぐため、各中間層で出力を正規化する ⇒これが、Batch Normalization  各層の間に正規化層を追加  ミニバッチごとに各層の出力を平均0,分散1の 分布にする (メリット) • 大きな学習率が使える • 正則化効果がある(Dropoutの必要性が下がる) • 重みの初期値に依存しにくくなる
  72. 72. 72 tf.contrib.layers.batch_norm  Batch Normalizationを簡潔に実装できる(2) (次ページに続く) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved # 使わない場合 def batch_norm_wrapper(inputs, phase_train=None, decay=0.99): epsilon = 1e-5 out_dim = inputs.get_shape()[-1] scale = tf.Variable(tf.ones([out_dim])) beta = tf.Variable(tf.zeros([out_dim])) pop_mean = tf.Variable(tf.zeros([out_dim]), trainable=False) pop_var = tf.Variable(tf.ones([out_dim]), trainable=False) rank = len(inputs.get_shape()) axes = range(rank - 1) # nn:[0], conv:[0,1,2] batch_mean, batch_var = tf.nn.moments(inputs, axes) ema = tf.train.ExponentialMovingAverage(decay=decay)
  73. 73. 73 tf.contrib.layers.batch_norm  Batch Normalizationを簡潔に実装できる(3) • 引数のphase_trainにより、tf.condを使って学習時・テスト時の処理を分岐させる • 学習時(True)の場合は、ミニバッチの平均と分散でバッチ正規化を実施 • テスト時(False)の場合は、それまでの学習データの指数移動平均でバッチ正規化を実施 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved def update(): # 学習時のバッチ正規化 ema_apply_op = ema.apply([batch_mean, batch_var]) with tf.control_dependencies([ema_apply_op]): return tf.nn.batch_normalization( inputs, tf.identity(batch_mean), tf.identity(batch_var), beta, scale, epsilon) def average(): # テスト時のバッチ正規化 train_mean = pop_mean.assign(ema.average(batch_mean)) train_var = pop_var.assign(ema.average(batch_var)) with tf.control_dependencies([train_mean, train_var]): return tf.nn.batch_normalization( inputs, train_mean, train_var, beta, scale, epsilon) return tf.cond(phase_train, update, average)
  74. 74. 74 tf.contrib.layers.batch_norm  Batch Normalizationを簡潔に実装できる(3) • 20~30行のBatch Normalizationの処理を、上記1行で記述可能 • is_training引数で、True(学習時)/False(テスト時)を切り替えることで、 使わない場合と同様の処理が可能 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved # 使った場合 batch_norm = tf.contrib.layers.batch_norm(inputs, decay=0.99, epsilon=1e-5, scale=True, is_training=is_training)
  75. 75. 75 まとめ  ラッピングされた高レベルAPIでを用いることによりコードが簡潔に鳴る  代わりに細かい操作がやりづらくなる  特定の重みの値を可視化など  tf.layersとtf.contrib.layersがあるので使いやすい方を選別  しかしcontribはテスト中でいつ変わってもおかしくない 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  76. 76. 76 シンギュラリティ株式会社 第2章 TensorFlowで様々なネットワークを実装する 6月 TensorFlow講義 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  77. 77. 77 TensorFlowとGymでDQN 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  78. 78. 78 DQNとは?  Deep Q Network  強化学習の一種であるQ学習を深層学習でおこなったもの  2013年にDeepMindが発表  Atariのゲームで人間を超える高パフォーマンス、自動運転への応 用も期待されている  AlphaGoにも用いられている 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved Q学習 + 深層学習
  79. 79. 79 強化学習とは? 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved ・右に進む ・左に進む ・餌が食べられる ・サメに食べられる 行動 報酬 新しい状態 環境 現状を考えて、一番将来的に報酬 が多くなる行動を選択する。 状態
  80. 80. 80 簡単な例(迷路) 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved 下の方がゴールに 近そうだけど・・・ ▼報酬 ・どれだけゴールに近いか ・ゴールしたらもっと沢山 ▼報酬(マイナス) ・かかった時間 ▼状態(s) ・今どこにいるか,左の画面そ のもの ▼行動(a) ・上下左右移動 Try & Errorを繰り返して、「この場所にいた時に」 「こっちに動いた方がいい」ということを学習
  81. 81. 81 Q学習とは  強化学習におけるポリシー決定手法の一つ  当然のことながら、エージェントは状況sにおいて将来まで考えて最も報 酬の合計が多くなりそうな行動aをとる  状況sで行動aを取った際の将来まで考えた報酬の合計を𝑄(𝑠, 𝑎)とする  しかし、そのQは今分かっていない(最初は適当に決める)  Qが本当に正しければ以下の式を満たす 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 𝑄 𝑠, 𝑎 = 𝑅 𝑠, 𝑎 + 𝛾 𝑚𝑎𝑥 𝑎′ 𝑄(𝑠′, 𝑎′)
  82. 82. 82 Q学習とは  式の説明 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 𝑄 𝑠, 𝑎 = 𝑅 𝑠, 𝑎 + 𝛾 𝑚𝑎𝑥 𝑎′ 𝑄(𝑠′, 𝑎′) 𝛾 (0 < 𝛾 ≤ 1): 割引率・・・未来の報酬の影響を少しずつ小さくする 𝑅 𝑠, 𝑎 : 報酬・・・状況sで行動aを取った時の報酬 𝑠′: 次の状態・・・状態sで行動aをとることにより状態s’になる 𝑎′ : 次の行動・・・状態s’の時にとる行動 時刻tの状態sで行動aをとること による将来まで考慮した価値 時刻tの状態sで行動aをとること によりその時だけもらえる報酬 時刻t+1の状態s’で行動a’をとるこ とによる将来まで考慮した報酬
  83. 83. 83 Q学習とは  もちろん最初は適当に決めるので式を満たすはずがない  誤差は以下のようになる(TD誤差という)  TD誤差を計算してQを以下のようにアップデート 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 𝑅 𝑠, 𝑎 + 𝛾 𝑚𝑎𝑥 𝑎′ 𝑄 𝑠′, 𝑎′ − 𝑄 𝑠, 𝑎 𝑄 𝑠, 𝑎 ← 𝑄 𝑠, 𝑎 + 𝛼{𝑅 𝑠, 𝑎 + 𝛾 𝑚𝑎𝑥 𝑎′ 𝑄 𝑠′, 𝑎′ − 𝑄 𝑠, 𝑎 } 学習率
  84. 84. 84 Q学習について  Qを最初にランダムに決めたり、値を計算してアップデートするのは簡単 な問題ならできるけど、、、、 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved こういう迷路程度だったら状 態も迷路のマス目の数くらい に限られるが こういう風になると状態はほぼ無 限に存在するから、結局計算や アップデートができない
  85. 85. 85 DQNについて  Qの計算にニューラルネットワークを用いる 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved conv1 conv2 outfc1 ▼出力 ・この状況で取りうる行動の価値 例) 左・・・10点 右・・・5点 停止・・・5点 出力層の数は取りうる行動 の数になる
  86. 86. 86 DQNにおける訓練  誤差さえ計算できれば確率勾配法とバックプロパゲーションで計算でき る  誤差にTD誤差(を2乗したもの)を用いればいよい 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 𝑤 = 𝑤 − 𝛼𝛻𝐸 𝛻𝐸 = ( 𝝏𝑬 𝝏𝒘 𝟏 , 𝝏𝑬 𝝏𝒘 𝟐 , 𝝏𝑬 𝝏𝒘 𝟑 , ・・・・) 𝑇 ニューラルネットワークの重み更新のルール 𝐸 = 1 2 {𝑅 𝑠, 𝑎 + 𝛾 𝑚𝑎𝑥 𝑎′ 𝑄 𝑠′ , 𝑎′ − 𝑄 𝜃 𝑠, 𝑎 }2 ニューラルネットワークの出力 正解データにあたる部分なのでこちらのQの計算は同じ構成 のネットワークで行うが訓練はしない!
  87. 87. 87 DQNのその他の要素  Experience Replay  ゲームなどの特性上、訓練に使うデータがどうしても時間連続に なってしまい、相関をもってしまう  過去の経験を蓄積させておいて、あとからランダムでミニバッチを構 築  εグリーディー法  普通は、計算したq値が最も高いアクションを取るのだが、いろんな ケースを探索させるために確率εでランダムな動きを取る 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  88. 88. 88 OpenAI Gym  シミュレーション環境を簡単に呼び出し、状況、報酬などを簡単に取得 可能 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  89. 89. 89 DQNを実装するさいのポイント  全く同じ構成だが、VariableScopeの異なるでqとtargetを構築する  訓練するのはqネットワークの方だけ  一定ステップたったらtarget側の重みをq側の値で更新する  始まってすぐは全く同じところから始まるためにたようなデータが増えな いように最初の何フレームかはランダムな数だけ履歴を取らない  ある程度履歴が貯まるまでは学習を開始しない 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  90. 90. 90 ネットワーク 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved  いつもと同じ。ただ、後から簡単に重みにアクセスするために varable_scopeを用いる
  91. 91. 91 環境構築 1行でゲーム環境は構築できてしまいます 名前を変えれば他のゲームやタスクでも実行できます 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved def main(argv): #環境構築 env = gym.make(ENV_NAME) #この環境で取りうるアクション数 num_action = env.action_space.n
  92. 92. 92 placeholder 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #状態s_t x_ph = tf.placeholder(tf.float32, shape=[None, HEIGHT, WIDTH, 1]) #状態s_t+1 x2_ph = tf.placeholder(tf.float32, shape=[None, HEIGHT, WIDTH, 1]) #報酬r r_ph = tf.placeholder(tf.float32,[None,]) #行動a a_ph = tf.placeholder(tf.int32,[None,])
  93. 93. 93 ネットワーク構築 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #qネットワーク、targetネットワークを構築 q_net = inference(x_ph, 'q', num_action) target_net = inference(x2_ph, 'target', num_action) #それぞれの重みを取得してくる q_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='q') target_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='target') それぞれの重みを下記のようにスコープごとに取得してこれる ※q_varsは訓練するために、target_varsは後からq_varsの値 で置き換えるために使う
  94. 94. 94 ネットワーク出力と正解データ 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #ターゲット(正解データ) q_target = r_ph + GAMMA * tf.reduce_max(target_net, axis=1) #予測したq値 a_one_hot = tf.one_hot(a_ph, depth=num_action, dtype=tf.float32) q_val = tf.reduce_sum(q_net * a_one_hot, axis=1) 𝐸 = 1 2 {𝑅 𝑠, 𝑎 + 𝛾 𝑚𝑎𝑥 𝑎′ 𝑄 𝑠′ , 𝑎′ − 𝑄 𝜃 𝑠, 𝑎 }2 の通りに誤差を計算する用意 q_netの出力は「バッチサイズ×アクション数」なので実際に行動を取った値のQ値を 計算する
  95. 95. 95 誤差、訓練 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved #誤差 with tf.variable_scope('loss'): loss = tf.reduce_mean(tf.squared_difference(q_target, q_val)) with tf.variable_scope('train'): global_step = tf.Variable(0, trainable=False, name="global_step") #訓練するのはqネットワークだけ opt =tf.train. RMSPropOptimizer(FLAGS.learning_rate) train_step=opt.minimize(loss, var_list=q_vars, global_step=global_step) minimizeメソッドは引数var_listを指定することでその重みだけを学習してくれる 論文の通りRMSProp
  96. 96. 96 targetのアップデート 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved with tf.variable_scope('update'): #targetネットワークをアップデート update_op = [target_vars[i].assign(q_vars[i]) for i in range(len(q_vars))] forループで回して全ての重みをアサインする
  97. 97. 97 シミュレーション初期化 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved iteration = 0 for _ in range(FLAGS.num_episode): #初期状態の環境を取得 obs = env.reset() last_obs = obs #最初の何ステップかは何もしない(初期状態をランダムにするため) for _ in range(random.randint(0, NO_ACTION_STEP)): last_obs = obs obs, _, _, _ = env.step(0) env.reset()で初期化、env.stepで実行 env.stepの返り値は、次の状態(画面)、得られた報酬、終了したかどうか、メタ情報
  98. 98. 98 画面の前処理 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved # AtariGameは偶数フレームと奇数フレームで映るオブジェクトが違うので前処理 # グレースケール化 def preprocess(obs, last_obs): processed_obs = np.maximum(obs, last_obs) processed_obs = processed_obs.mean(axis=2, keepdims=True) processed_obs = processed_obs/256.0 return processed_obs 偶数フレームと奇数フレームで映るオブジェクトが違うので画素値が大きい方を採用 ブロック崩し程度なのでRGBである必要はない 値も0.0〜1.0に規格化
  99. 99. 99 εグリーディー法 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved while not done: iteration += 1 last_obs = obs #εグリーディー法(簡易版) action = env.action_space.sample() if np.random.uniform() < EPSILON: #qネットワークに状態を入れて次の行動を選択 action_value = sess.run(q_net, feed_dict={x_ph:[state]}) action = np.argmax(action_value) 一定隔離以下の時ランダム、それ以外の時はq値を計算して最も高い行動選択 本来は学習初期はかなり高い確率でランダムに行動選択、学習が進むにつれ その割合を落としていくのが一般的(今回はεを固定)
  100. 100. 100 行動履歴の保存 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved obs, reward, done, _ = env.step(action) next_state = preprocess(obs, last_obs) #行動履歴を保存 replay_memory.append((state, action, reward, next_state)) #状態の更新 state = next_state 状態と観測を毎回アップデートして行動履歴に保存
  101. 101. 101 訓練実行 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved if iteration > LEARNING_START_ITERATION and iteration % LEARNING_EVERY_N == 0: #学習に使う行動履歴を取得してくる x, a, r, x2, cont = sample_memories(FLAGS.batch_size) #訓練実行 sess.run(train_op, feed_dict={x_ph:x, r_ph:r, a_ph:a, x2_ph:x2}) 一定ステップ待たないと行動履歴もたまってない 毎ステップ訓練をすると同じようなデータセットばかりで訓練してしまう
  102. 102. 102 targetのアップデート 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved if step % UPDATE_EVERY_N == 0: #一定時間たったらターゲット側をアップデート sess.run(update_op) print('update at %d step' % step) ただ実行するだけ
  103. 103. 103 実演 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  104. 104. 104 まとめ  DQNはQ学習のQ値計算をニューラルネットワークに置き換えたもの  qネットワークとtargetネットワークの2つに分ける必要があるので注意  学習はqネットワーク、正解データ生成がtargetネットワーク  targetネットワークは一定ステップごとにqネットワークの重みで更新  DQNの実装よりかも実際にそのシミュレーション環境を作る方が大変 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  105. 105. 105 はじめに  最近、コンピュータで写真並みの画像を生成できることで話題になっている。 そこで使用された生成モデル(アルゴリズム)がDCGAN 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 論文[2]より引用  DCGANで、ベッドルーム画像のデータセットを使って学習した結果。 本物の画像と見間違ってしまいそうなレベルで、画像が生成できていることがわかる。
  106. 106. 106 TensorFlowでDCGAN 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  107. 107. 107 はじめに  最近、コンピュータで写真並みの画像を生成できることで話題になっている。 そこで使用された生成モデル(アルゴリズム)がDCGAN 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 論文[2]より引用  DCGANで、ベッドルーム画像のデータセットを使って学習した結果。 本物の画像と見間違ってしまいそうなレベルで、画像が生成できていることがわかる。
  108. 108. 108 はじめに  DCGANってどういう意味? Deep Convolutional Generative Adversarial Networks 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 深い 畳み込み 敵対的生成ネットワーク(GAN) “深い畳み込み”、要するに畳み込みニューラルネットワーク(CNN)を使った敵対 的生成ネットワーク(GAN)ということが読み取れる。
  109. 109. 109 敵対的生成ネットワーク(GAN)  では、敵対的生成ネットワーク(GAN)って何? 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved
  110. 110. 110 敵対的生成ネットワーク(GAN)  学習データと似たような特徴を持つ出力を生成するためのフレームワーク  以下の2つのモデルの訓練を同時に進め、互いに競わせること(敵対的)でより 精度の高い生成モデルを構築することが可能  D():Discriminator(識別モデル) ⇒データが学習データ由来のものか、 それとも生成モデル由来のものかを識別することが目的。  G():Generator(生成モデル) ⇒ランダムノイズを入力として、学習データと同じようなデータを 生成することが目的。 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 警察(D())は、本物の紙幣と偽造紙幣を的確に見分けようとする。 紙幣偽造犯(G())は、識別できないくらい精工な偽札を作ろうとする。 このように、警察(D())と紙幣偽造犯(G())のイタチごっこをさせることで、紙幣偽 造犯(G())の精度が上がり、より本物に近いものを作れるようになる。 分かり易く例えると・・・
  111. 111. 111 敵対的生成ネットワーク(GAN)  GANのネットワーク構成図 • Generator(生成モデル)とDiscriminator(識別モデル)で構成 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved Discriminator (D) z Generator (G) 生成データ G(z)=x 学習データ セット 学習データ x 入力データxが学習 データである確率 ※zはn次元の一様分布に従うランダム変数
  112. 112. 112 敵対的生成ネットワーク(GAN)  GANの学習(Discriminator) • 目的1:学習データとGeneratorの出力物G(z)を正確に識別できる ことを目指す 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved Discriminator (D) 生成データ G(z)=x 学習データ x XかG(z) どちらかが入力される 入力データが 学習データである確率 xが学習データ由来の場合、出力が1 xが生成モデル由来の場合、出力が0 になるように学習
  113. 113. 113 敵対的生成ネットワーク(GAN)  GANの学習(Generator) • DiscriminatorがGeneratorの出力物G(z)を、学習データと誤って認 識する率を高めることを目指す 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved Discriminator (D) z Generator (G) 生成データ G(z)=x 入力データが 学習データである確率 D(G(z))の フィードバック D(G(z))の出力が、1になるように学習
  114. 114. 114 敵対的生成ネットワーク(GAN)  GANの目的関数  下記の関数V(G, D)で表現されるminimaxゲームとして定義できる min 𝐺 max 𝐷 𝑉(𝐺, 𝐷) = 𝔼 𝑥~𝑃 𝑑𝑎𝑡𝑎(𝑥) log 𝐷 𝑥 + 𝔼z~𝑃𝑧(𝑧) log(1 − 𝐷(𝐺(𝑧))) • 一様分布の乱数zを入力としたデータ生成写像G(z)を、ニューラルネットワー クとして訓練 • 入力データxが学習データである確率を与える写像D(x)を、ニューラルネット ワークとして訓練 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 二つのニューラルネットワークD,Gを、 上記式のとおりminimaxを最適化するように訓練させる ☞最終的には、generatorが学習データと同じようなデータを生成することを 期待しているため、discriminatorの正答率は50%になる 要するに −∞~0 −∞~0
  115. 115. 115 敵対的生成ネットワーク(GAN)  GANの目的関数 min 𝐺 max 𝐷 𝑉(𝐺, 𝐷) = 𝔼 𝑥~𝑃 𝑑𝑎𝑡𝑎(𝑥) log 𝐷 𝑥 + 𝔼 𝑧~𝑃𝑧(𝑧) log(1 − 𝐷(𝐺(𝑧))) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved [前提] • 𝑃𝑧はある種の任意の分布(例えば一様分布)を表す。Zは個々のノイズサンプルを表す。 • Gはzを入力とし、 𝑃𝑔に分布させる。 𝑃𝑔はジェネレータGから生成された出力の分布を示す。 • Dは入力が学習データから来た確率を表す。 (1であれば入力は学習データ分布𝑃𝑥 から、0であればGの出力分布𝑃𝑔 からと判断) [左辺] • 目的関数Vは関数DとGを引数に取る、右辺であらわされる関数である。 • 関数Vが最大となるD、および関数Vが最小となるGを定める。 [右辺] • 確率変数xは確率分布𝑃𝑑𝑎𝑡𝑎に従う。 • 確率変数zは確率分布𝑃zに従う。 • このとき、 log 𝐷(𝑥)の期待値と、 log(1 − 𝐷(𝐺 𝑧 ))の期待値の和を誤差関数とする。 (Dが学習データを正しく識別できればlog 𝐷(𝑥) が大きくなり、DがGの出力を学習データだと識別すると log(1 − 𝐷 𝐺 𝑧 )が小さくなる。) この式を日本語で書き下すと・・・ −∞~0 −∞~0
  116. 116. 116 敵対的生成ネットワーク(GAN)  GANの目的関数 min 𝐺 max 𝐷 𝑉(𝐺, 𝐷) = 𝔼 𝑥~𝑃 𝑑𝑎𝑡𝑎(𝑥) log 𝐷 𝑥 + 𝔼 𝑧~𝑃𝑧(𝑧) log(1 − 𝐷(𝐺(𝑧))) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved Discriminator (D) z Generator (G) 生成データ G(z)=x 学習データ セット 学習データ x 入力データxが学習 データである確率 D(x) ※zはn次元の一様分布に従うランダム変数 Dは学習データである確率を最大化する ように学習する。
  117. 117. 117 敵対的生成ネットワーク(GAN)  GANの目的関数 min 𝐺 max 𝐷 𝑉(𝐺, 𝐷) = 𝔼 𝑥~𝑃 𝑑𝑎𝑡𝑎(𝑥) log 𝐷 𝑥 + 𝔼 𝑧~𝑃𝑧(𝑧) log(1 − 𝐷(𝐺(𝑧))) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved Discriminator (D) z Generator (G) 生成データ G(z)=x 学習データ セット 学習データ x 入力データxが学習 データである確率 D(x) ※zはn次元の一様分布に従うランダム変数 Gは、log(1-D(G(z)))を最小化するよう に学習する。
  118. 118. 118 敵対的生成ネットワーク(GAN)  GANのアルゴリズム詳細 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 1. ミニバッチサイズm個のノイズ𝑧1 … 𝑧 𝑚をデータ生成分布𝑃z 𝑧 から生成する 2. ミニバッチサイズm個の学習データ𝑥1 … 𝑥 𝑚を𝑃𝑑𝑎𝑡𝑎 𝑥 から取り出す 3. 下記式の、 𝜃dにおける確率的勾配を上るように識別モデルDを更新する 𝛻𝜃 𝑑 1 𝑚 𝑖=1 𝑚 log 𝐷(𝑥 𝑖 ) + log 1 − 𝐷 𝐺 𝑧 𝑖 4. 1~3をk回繰り返す(※) 5. ミニバッチサイズm個のノイズ𝑧1 … 𝑧 𝑚をデータ生成分布𝑃z 𝑧 から生成する 6. 下記式の、 𝜃𝑔における確率的勾配を下るように生成モデルGを更新する 𝛻𝜃𝑔 1 𝑚 𝑖=1 𝑚 log 1 − 𝐷 𝐺 𝑧 𝑖 7. 1~6を、訓練回数分だけ繰り返す (※)識別モデルDを十分な回数(k)更新したうえで、生成モデルGを1回更新することで、 常に識別モデルが新しいGの状態に適用できるように学習をすすめる。
  119. 119. 119 敵対的生成ネットワーク(GAN)  GANの利点・欠点 • 利点 • 欠点 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved • GANでは、識別モデルと生成モデルとして具体的なネットワークに限定していないため、様々 なモデルを組み合わせることができる。 • 学習データと直接比較するのではなく、識別モデルの評価を介して生成するため、学習データ を生成モデルがそのまま丸覚えすることを避けられる。 • 明示的な𝑃𝑔(生成モデルからの出力分布)が最初は存在しないため、識別モデルは生成モデ ルとシンクロさせて訓練する必要がある。 ⇒識別モデルを更新せずに生成モデルだけを訓練すると、 生成モデルが入力ノイズzの多くを学習データxと同じ値に収束させてしまうなど、 同期タイミングが難しい
  120. 120. 120 Deep Convolutional GANとは  敵対的生成ネットワーク(GAN)を踏まえたうえで、 Deep Convolutional GANとは何? 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved
  121. 121. 121 Deep Convolutional GANとは  DCGAN(Deep Convolutional Generative Adversarial Nets)は、GAN に対して畳み込みニューラルネットワークを適用して、うまく学習が成立 するよう提案されたベストプラクティス。 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved z 生成データ G(z)=x 学習データ セット 学習データ x 入力データxが学習 データである確率 ※zはn次元の一様分布に従うランダム変数 Dは学習データである確率を最大化するように学習する。 Generator(生成モデル)とDiscriminator(識別モデル)に、 畳み込みニューラルネットワーク(CNN)を適用。 ⇒CNNは画像関連を中心に大きな成功を収めているモデ ルであり、画像を生成するのであればGANにも適用すれ ばうまくいくはず!
  122. 122. 122 Deep Convolutional GANとは  DCGANのアーキテクチャ ① プーリング層はやめる 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved  fractionally-strided convolution(分数的にスト ライドする畳み込み)を使いアップサンプリングする ⇒transposed convolution,deconvolutionと呼ば れることもある  一般的なCNNだが、プーリング層はおかない  ダウンサンプリングは、ストライド2の畳み込みで行 う
  123. 123. 123 Deep Convolutional GANとは  DCGANのアーキテクチャ  fractionally-strided convolution 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 元の特徴マップ(3×3) アップサンプリング後の 画像・特徴マップ(5×5) 元となる特徴マップをパディングして拡大してから、カーネル(フィルタ)を適用。
  124. 124. 124 Deep Convolutional GANとは  DCGANのアーキテクチャ ② 全結合層は取り除き、global average poolingに置き換える  discriminatorから全結合層を除去  代わりにglobal average poolingにする 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 一つの特徴マップに一つのクラスを対応させ分類することで、モデルの安定性が 増し過学習を防ぐ効果がある。 (ただし、収束が遅くなる傾向があるため注意が必要)
  125. 125. 125 Deep Convolutional GANとは  DCGANのアーキテクチャ ③ Batch Normalizationを使用する  generatorとdiscriminatorの両方に適用  ただし、generatorの出力層と、discriminatorの入力層には適用しない ⇒画像そのものを正規化することになるため、 適用するとネットワークが不安定になる 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 各層でのデータ分布を正規化することで、 学習速度の向上、パラメータの初期値依存の 軽減、および過学習を防ぐ効果がある
  126. 126. 126 Deep Convolutional GANとは  DCGANのアーキテクチャ ④ 活性化関数  generator • 出力層にTanh • それ以外の層はすべてReLU  discriminatorでは、 • すべての層でLeaky ReLU 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved Leaky ReLUは、x≦0の領域がaxとなる。 ReLUでは、 x≦0の領域で勾配が0になり学習が進まなくなるが、Leaky ReLUは勾配が0に ならないため、この問題を回避できる。(DCGANでは、a=0.2で定義している) また、discriminatorの入力画像である学習画像・生成画像の各ピクセルの値域は-1~1であ り、ReLUだとx≦0の領域がすべて0になってしまうため、Leaky ReLUの方が適している。
  127. 127. 127 DCGANの実装  TensorFlowを用いて、DCGANを実装してみる 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved
  128. 128. 128 DCGANの実装  使用ライブラリ • TensorFlow 1.2 Googleが提供しているオープンソースのディープラーニングライブラリ。 • Numpy 1.12.0 Pythonにおける数値計算用の拡張モジュール。 • Scipy 0.19.0 高度な科学計算を行うためのライブラリ。  使用データセット • CIFAR-10 python version ラベル付けされたサイズが32×32のカラー画像。 ラベルは、飛行機・自動車・鳥・猫・鹿・犬・カエル・馬・船・トラックの10クラス。 Pythonで扱いやすいようにpickle化されたものを使用する。 学習データ50000件、テストデータ10000件が格納されている。 【ダウンロードサイト】 https://www.cs.toronto.edu/~kriz/cifar.html 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved
  129. 129. 129 • 学習回数は25epoch、バッチサイズを128で学習する。 • 入力、出力の画像サイズは32×32とする。 • Generatorの入力ノイズの次元数を100とする。 • Adamオプティマイザの学習率は0.0002、モーメンタムを0.5 flags = tf.app.flagsflags.DEFINE_integer("epoch", 25, "Epoch to train.") flags.DEFINE_integer("batch_size", 128, "The size of batch images.") flags.DEFINE_float("learning_rate", 0.0002, "Learning rate of for adam.") flags.DEFINE_float("beta1", 0.5, "Momentum term of adam.") flags.DEFINE_integer("input_height", 32, "The size of image to use.") flags.DEFINE_integer("input_width", 32, "The size of image to use.") flags.DEFINE_integer("output_height", 32, "The size of the output images to produce.") flags.DEFINE_integer("output_width", 32, "The size of the output images to produce.") flags.DEFINE_integer("c_dim", 3, "Dimension of image color.") flags.DEFINE_integer("z_dim", 100, "Dimension of sample noise.") FLAGS = flags.FLAGS 定数部分 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved
  130. 130. 130 def load_cifar10(self): data = np.empty((0,32*32*3)) for i in range(1,6): fname = os.path.join(self.input_dir, "%s%d" % ("data_batch_", i)) with open(fname, 'rb') as f: cifar_dict = pickle.load(f, encoding='latin-1’) data = np.vstack((data, cifar_dict['data’])) # オリジナル画像は(chanel:3, row:32, column:32)のフラット形式 # リシェイプ後、(row:32, column:32, chanel:3)に次元を入れ替える data = data.reshape(len(data), 3, 32, 32).transpose(0, 2, 3, 1) return np.array(data) / 127.5 - 1. CIFAR-10の読み込み 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved CIFAR-10の学習データファイルは下記5ファイルに 分割されているため、すべて読み込んで配列に連結する。 data_batch_1 data_batch_2 data_batch_3 data_batch_4 data_batch_5 Generatorの出力層の活性化関数はtanh(-1~1)を使用するため、 画像データの各ピクセル値を0~255から-1~1の範囲に変換する。
  131. 131. 131 def discriminator(self, image, reuse=False): with tf.variable_scope("discriminator", reuse=reuse): # 畳み込み層1(フィルター数:64、フィルターサイズ:5、ストライド2) # Batch Normalizationなし conv1 = self.conv2d('d_conv1', image, [5, 5, 3, 64], [1, 2, 2, 1]) conv1 = tf.maximum(conv1, 0.2 * conv1) # 畳み込み層2(フィルター数:128、フィルターサイズ:5、ストライド2) # Batch Normalizationあり conv2 = self.conv2d('d_conv2', conv1, [5, 5, 64, 128], [1, 2, 2, 1]) conv2 = tf.contrib.layers.batch_norm( conv2, decay=0.9, updates_collections=None, epsilon=1e-5, scale=True, is_training=True, scope='d_conv2_bn’) conv2 = tf.maximum(conv2, 0.2 * conv2) Discriminatorの実装(1) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 畳み込み層は4層。 最初の畳み込み層の入力は画像そのものであるため、 Batch Normalizationを適用しない。 畳み込み層の活性化関数にはLeaky ReLUを使用。
  132. 132. 132 # 畳み込み層4(フィルター数:512、フィルターサイズ:5、ストライド2) # Batch Normalizationあり conv4 = self.conv2d('d_conv4', conv3, [5, 5, 256, 512], [1, 2, 2, 1]) conv4 = tf.contrib.layers.batch_norm( conv4, decay=0.9, updates_collections=None, epsilon=1e-5, scale=True, is_training=True, scope='d_conv4_bn’) conv4 = tf.maximum(conv4, 0.2 * conv4) # 出力層 avg_pool = tf.reduce_mean(conv4, [1, 2]) output = self.linear('d_output', avg_pool, 1) return tf.nn.sigmoid(output), output Discriminatorの実装(2) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 出力は恒等関数とする。 全結合層はなくし、average poolingを適用する。 バッチサイズ×フィルタ数のテンソルに縮約される
  133. 133. 133 def generator(self, z, reuse=False, is_training=True): with tf.variable_scope("generator", reuse=reuse): z_shape = z.get_shape().as_list() # 入力ノイズの投射、リシェイプ(2×2×512)、Batch Normalizationあり img_size = int(self.output_width / 16) proj = self.linear('g_proj', z, img_size * img_size * 512) proj = tf.reshape(proj, [-1, img_size, img_size, 512]) proj = tf.contrib.layers.batch_norm( proj, decay=0.9, updates_collections=None, epsilon=1e-5, scale=True, is_training=is_training, scope='g_proj_bn’) proj = tf.nn.relu(proj) Generatorの実装(1) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 100次元の入力ノイズを2×2×512のサイズ にリシェイプする。
  134. 134. 134 # 逆畳み込み層1(フィルター数:256、フィルターサイズ:5、ストライド2) # Batch Normalizationあり img_size *= 2 deconv1 = self.deconv2d('g_conv1', proj, [z_shape[0], img_size, img_size, 256], [1, 2, 2, 1]) deconv1 = tf.contrib.layers.batch_norm( deconv1, decay=0.9, updates_collections=None, epsilon=1e-5, scale=True, is_training=is_training, scope='g_conv1_bn’) deconv1 = tf.nn.relu(deconv1) # 逆畳み込み層2(フィルター数:128、フィルターサイズ:5、ストライド2) # Batch Normalizationあり img_size *= 2 deconv2 = self.deconv2d('g_conv2', deconv1, [z_shape[0], img_size, img_size, 128], [1, 2, 2, 1]) deconv2 = tf.contrib.layers.batch_norm( deconv2, decay=0.9, updates_collections=None, epsilon=1e-5, scale=True, is_training=is_training, scope='g_conv2_bn’) deconv2 = tf.nn.relu(deconv2) Generatorの実装(2) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 逆畳み込み層は全部で4層。 2×2で開始し、32×32のサイズまでアップサンプリングする。 逆畳み込み層の活性化関数にはReLUを使用。
  135. 135. 135 # 逆畳み込み層3(フィルター数:64、フィルターサイズ:5、ストライド2) # Batch Normalizationあり img_size *= 2 deconv3 = self.deconv2d('g_conv3', deconv2, [z_shape[0], img_size, img_size, 64], [1, 2, 2, 1]) deconv3 = tf.contrib.layers.batch_norm( deconv3, decay=0.9, updates_collections=None, epsilon=1e-5, scale=True, is_training=is_training, scope='g_conv3_bn’) deconv3 = tf.nn.relu(deconv3) # 逆畳み込み層4(フィルター数:3、フィルターサイズ:5、ストライド2) # Batch Normalizationなし img_size *= 2 deconv4 = self.deconv2d('g_conv4', deconv3, [z_shape[0], img_size, img_size, 3], [1, 2, 2, 1]) return tf.nn.tanh(deconv4) Generatorの実装(3) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 最後の逆畳み込み層の出力は画像そのものであるため、 Batch Normalizationを適用しない。 Tanhで-1.0~1.0の範囲の出力にする。
  136. 136. 136 モデルの構築(1) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved def build_model(self): # 学習画像用の変数 self.inputs = tf.placeholder(tf.float32, [self.batch_size, self.input_height, self.input_width, self.c_dim], name='real_images’) # 学習用入力ノイズの変数 self.z = tf.placeholder(tf.float32, [self.batch_size, self.z_dim], name='z’) # サンプル画像用入力ノイズの変数 self.z_sample = tf.placeholder(tf.float32, [self.sample_num, self.z_dim], name=‘z’) # 生成モデル self.G = self.generator(self.z) # 識別モデル self.D_t, self.D_logits_t = self.discriminator(self.inputs) self.D_g, self.D_logits_g = self.discriminator(self.G, reuse=True) # サンプル画像の出力 self.sampler = self.generator(self.z_sample, reuse=True, is_training=False) 学習画像用のプレースフォルダー: 128×32×32×3 学習用入力ノイズ用のプレースフォルダー: 128 × 100 サンプル画像用入力ノイズ用のプレースフォルダー: 64 × 100 Discriminatorは「学習用画像」と「Generatorによって生成された画像」で2回繰り返す ことになるので、reuse=Trueにして重みの変数を使いまわす必要がある。
  137. 137. 137 # 誤差関数 ## ↓Discriminatorは、D(G())をすべて0にし D(I)をすべて1にするのが理想 self.global_step = tf.Variable(0, name='global_step', trainable=False) ### 学習画像を入力とした場合の誤差 self.d_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logits=self.D_logits_t, labels=tf.ones_like(self.D_logits_t))) ### Generator生成画像を入力とした場合の誤差 self.d_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logits=self.D_logits_g, labels=tf.zeros_like(self.D_logits_g))) self.d_loss = self.d_loss_real + self.d_loss_fake ## ↓Generatorは、D(G())がすべて1になるのが理想 self.g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logits=self.D_logits_g, labels=tf.ones_like(self.D_logits_g))) モデルの構築(2) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 誤差関数はクロスエントロピーを使用。 Discriminatorは、「学習用画像」であれば1、「Generator生成画像」 であれば0と判定できるのが理想。 つまり、それぞれ誤差合計を最小化するように誤差関数を設計する。 Generatorは、自分が生成した画像がDiscriminatorに 1と判定させるように誤差関数を設計する。
  138. 138. 138 # 訓練時に更新する変数取得 t_vars = tf.trainable_variables() d_vars = [var for var in t_vars if 'd_' in var.name] g_vars = [var for var in t_vars if 'g_' in var.name] # discriminatorの学習 self.d_optim = tf.train.AdamOptimizer(self.learning_rate, beta1=self.beta1) .minimize(self.d_loss, var_list=d_vars, global_step=self.global_step) # generatorの学習 self.g_optim = tf.train.AdamOptimizer(self.learning_rate, beta1=self.beta1) .minimize(self.g_loss, var_list=g_vars) モデルの構築(3) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 学習時に更新対象の変数(重み、バイアス)を、 Discriminator・Generatorそれぞれで取得しておく。 Adam手法で誤差の最小化を行う。 Discriminator・Generatorそれぞれで更新対象の変数を指定しておく。 学習率は両方同じで0.0002とした。
  139. 139. 139 # TensorBoard用ログ出力 ## 入力ノイズの一様分布を確認するヒストグラム z_hist = tf.summary.histogram(“z”, self.z) ## 学習画像を入力した場合のDiscriminator出力(分布が1に近い方が望ましい) d_t_hist = tf.summary.histogram(“d_train”, self.D_t) ## 生成画像を入力した場合のDiscriminator出力(分布が0に近い方が望ましい) d_g_hist = tf.summary.histogram("d_generated", self.D_g) ## 生成画像の出力 g_img = tf.summary.image("G", self.G) ## Generator学習時の誤差 g_loss_scalar = tf.summary.scalar("g_loss", self.g_loss) ## Discriminator学習時の誤差 d_loss_scalar = tf.summary.scalar("d_loss", self.d_loss) ## Discriminator学習時(学習画像を入力とした場合)の誤差 d_loss_real_scalar = tf.summary.scalar("d_loss_real", self.d_loss_real) ## Discriminator学習時(生成画像を入力とした場合)の誤差 d_loss_fake_scalar = tf.summary.scalar("d_loss_fake", self.d_loss_fake) モデルの構築(4) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved tensorboard用のログ出力定義
  140. 140. 140 # TensorBoard用ログのマージ処理 self.d_sum = tf.summary.merge( [z_hist, d_t_hist, d_loss_real_scalar, d_loss_scalar]) self.g_sum = tf.summary.merge( [z_hist, g_img, d_g_hist, d_loss_fake_scalar, g_loss_scalar]) self.writer = tf.summary.FileWriter("./logs", self.sess.graph) # 変数の初期化 tf.global_variables_initializer().run() self.saver = tf.train.Saver() モデルの構築(5) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved DiscriminatorとGeneratorは、別々に学習させるため、 tf.summary.merge_all()が使用できない。 よって、手動でマージ処理を実施する。 定義した変数の初期化
  141. 141. 141 def train(self, config): # 学習データ(CIFAR10)のロード data = self.load_cifar10() # テスト用の入力ノイズ、画像(64画像)の準備 sample_z = np.random.uniform(-1, 1, size=(self.sample_num , self.z_dim)) # チェックポイントファイルのチェック(存在すればロード) ckpt = tf.train.get_checkpoint_state(self.checkpoint_dir) if ckpt and ckpt.model_checkpoint_path: print("Reading checkpoint from %s" % ckpt.model_checkpoint_path) self.saver.restore(self.sess, ckpt.model_checkpoint_path) else: print("Created model with fresh parameters.") 学習(1) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved テスト時に生成するサンプル画像用の入力ノイズ を準備する。 -1~1の範囲でランダムに生成する。 チェックポイントファイルがあればデータをロードし、 途中から再開する。
  142. 142. 142 for epoch in xrange(config.epoch): for idx in xrange(0, batch_idxs): # 1ステップ分の学習データ、入力ノイズ取得 batch_images = data[idx*self.batch_size : (idx+1)*self.batch_size] batch_z = np.random.uniform( -1, 1, size=(self.batch_size, self.z_dim)).astype(np.float32) # discriminatorの学習・更新 _, summary_str = self.sess.run([self.d_optim, self.d_sum], feed_dict={self.inputs: batch_images, self.z: batch_z,}) self.writer.add_summary(summary_str, counter) # generatorの学習・更新 for i in range(2): _, summary_str = self.sess.run([self.g_optim, self.g_sum], feed_dict={self.z: batch_z}) self.writer.add_summary(summary_str, counter) 学習(2) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved Discriminatorの学習・パラメータ更新1回に対し、 Generatorの学習・パラメータ更新は2回とした。 両方1回ずつだと、Discriminatorの方が先に収 束してしまい、Generatorが学習されなくなって しまうため。 データ画像の質によってもことなるため、 DiscriminatorとGeneratorの更新タイミングの 調整がDCGANにおいて最も重要になる。
  143. 143. 143 errD_fake = self.d_loss_fake.eval({self.z: batch_z}) errD_real = self.d_loss_real.eval({self.inputs: batch_images}) errG = self.g_loss.eval({self.z: batch_z}) format_str = ( 'Epoch: [%2d] [%4d/%4d] time: %4.4f, d_loss: %.8f, g_loss: %.8f’) print(format_str % (epoch+last_epoch+1, idx+1, batch_idxs, time.time() - start_time, errD_fake+errD_real, errG)) counter += 1 学習(3) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 学習時の誤差を取得し、1ステップごとに標準出 力する。
  144. 144. 144 # 1epoch毎にサンプル画像生成 samples = self.sess.run(self.sampler, feed_dict={self.z_sample: sample_z}) self.save_images(samples, [8, 8], './{}/train_{:02d}.png'.format(config.sample_dir, epoch+last_epoch+1)) print("[Generato Sample Images]") # モデルの保存 if not os.path.exists(self.checkpoint_dir): os.makedirs(self.checkpoint_dir) self.saver.save(self.sess, os.path.join(self.checkpoint_dir, 'DCGAN.model’), global_step=epoch+last_epoch+1) 学習(4) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved 確認のため1epoch毎にサンプルを64画像生成する。 生成した画像を8×8にマージして1枚の画像ファイル を出力する。 1epoch毎にチェックポイントファイルを生成。
  145. 145. 145 DCGANの実行結果  学習結果1 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved After 1 epoch After 10 epoch After 20 epoch 全体的にぼやけていて、何の画像 か識別できない。 ぼやけてはいるが、ある程度何の 画像か認識できるようになった。 輪郭がシャープになった。
  146. 146. 146 DCGANの実行結果  学習結果(2) 2017/6/29 C8Lab Copyright 2017 C8Lab Inc. All rights reserved After 25 epoch 馬 鳥 猫 鹿 自動車 カエル 犬 船
  147. 147. 147 まとめ  DCGAN とはDiscriminatorとGeneratorのネットワークを共に学習させ ることによって切磋琢磨するネットワーク  どちらを何回づつ学習させるかはデータセット依存  画像生成の際には逆畳み込みを用いる  バッチノーマライゼーションをいれないとおそらくうまくいかない 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  148. 148. 148 TensorFlowにおけるRNN 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  149. 149. 149 RNNとは(一応) 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 入力1 入力2 入力3 中間1 中間2 中間3 出力1 出力2 出力3 中間層を時間方向に展開させることにより時系列 情報をニューラルネットワークで扱えるように。 入力-中間層の重み 中間-中間層の重み 共有重みを用いている
  150. 150. 150 TensorFlowにおけるRNN実装  インポートするべきパッケージ  tf.nn.rnn_cell・・・各時間の中間層における挙動を定義  tf.nn.static_rnnなど・・・入力とrnn_cellを受け取って、その出力を管 理する  基本的なRNN構築手順  入力データ整形  cellを定義してラッピングなどをして各時間での挙動を定義  cellと入力データを元に、RNN全体で順伝播  出力を加工して出力層を作成  誤差計算、学習 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  151. 151. 151  cellを定義してラッピングなどをして各時間での挙動を定義  cellと入力データを元に、RNN全体で順伝播  出力を加工して出力層を作成 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  152. 152. 152 rnn_cell の役割 ニューラルネットワークでcellというと・・・ 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved x1 x2 x3 入力 出力 w1 w2 w3 b 入力を受け取って、一つの値を返す 一方TFにおけるrnn_cellは・・・ 入力 t 状態 t-1 状態 t 出力 t 入力と前の状態を受け取って、出力 と新しい状態を返す、ある一種の層 の役割を持つ。 単層やドロップアウト無しの場合出 力 tと状態 tは同じ ただしLSTMの場合は出力ゲートが あるため出力tと状態tは異なる。
  153. 153. 153 rnn_cellの役割  扱えるrnn_cell  BasicRNNCell・・・基本的なrnn_cell(これを基準に解説)  BasicLSTMCell・・・ピープホールやクリッピングのない基本的な LSTM用のcell  LSTMCell・・・いろんな機能が使えるLSTM用のcell  GRUCell・・・GRUが扱えるcell  tf.contrib.rnnの中にはかなりたくさんある 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  154. 154. 154 rnn_cellの役割  定義したcellのラッピングが可能  MultiRNNCell・・・中間層を多層にできる。  DropoutWrapper・・・中間層にドロップアウト機能を追加  その他、後いくつか  例えば3層のLSTM、ドロップアウトの中間層を定義したければ 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved 1.2から多層化だけはこれではダメになりました
  155. 155. 155  cellを定義してラッピングなどをして各時間での挙動を定義  cellと入力データを元に、RNN全体で順伝播  出力を加工して出力層を作成 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  156. 156. 156 tf.nn.static_rnnなどの役割  実際tf.nn.rnnの機能を使わなくてもcellと、for文、reuse_variablesを駆 使すれば可能(PTBのチュートリアルはそうなってる)  定義したcellを時間方向に展開して各時間でのrnnの出力を行う。  tf.nn.static_rnn・・・固定長のRNN実装。  tf.nn.dynamic_rnn・・・可変長RNN実装  tf.nn. bidirectional_dynamic_rnn・・・双方向RNN実装  tf.nn.raw_rnn・・・完全にdynamicな制御ができるrnn。まだテスト中。 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved これらの関数は出力として、 (各時間の出力, 最後の時間の中間層)のタプルを返却 ※raw_rnnは除く
  157. 157. 157 static_rnnとdynamic_rnn  tf.nn.static_rnnとtf.nn.dynamic_rnnがある  rnn ・・・シーケンス長が固定  dynamic_rnn・・・シーケンス長が動的 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved 入力1 入力2 入力3 中間1 中間2 中間3 出力1 出力2 出力3 ・・・・・・
  158. 158. 158 static_rnnとdynamic_rnn  それぞれのメリット・デメリット  tf.nn.rnnは固定長グラフ構築を行うためモデル構築が遅い。  現状のraw_rnn がテスト中なので、現状もっとも簡単に feed_previousを意識したSeq2Seqを一番簡単に組めるのは static_rnn(個人的な感想)  tf.nn.rnnは入力が(バッチサイズ, 入力サイズ)のTensorのリストで である一方、dynamic_rnnは(バッチサイズ,シーケンス, データ長) のTensor。データによってデータセットを組みやすかったり組みにく かったり 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved 計算効率などの問題上、dynamic_rnnを公式では推奨している
  159. 159. 159 tf.nn.dynamic_rnnの使い方 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved tf.nn.rnn_cellと入力データを引数にして各時間での出力、最終状態を返却 time_majorを用いたのtensor shapeの変更は後ほどの出力の整形でも効いてくる。
  160. 160. 160  cellを定義してラッピングなどをして各時間での挙動を定義  cellと入力データを元に、RNN全体で順伝播  出力を加工して出力層を作成 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved
  161. 161. 161 RNNのややこしいところ  普通のニューラルネットワークなら、、、、 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved 出力を用いてすぐに誤差関数を定義可能
  162. 162. 162 RNNのややこしいところ  一方RNNは  (バッチサイズ, 時間, 中間層ユニット数)のtensorが tf.nn.dynamic_rnnにおける出力  この後出力層を定義するが、そのままoutputを使うことができない 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved 適切にデータを整形する必要がある
  163. 163. 163 様々なRNNの形 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved http://karpathy.github.io/2015/05/21/rnn-effectiveness/ 今日はこれを実装
  164. 164. 164 様々なRNNの形 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved http://karpathy.github.io/2015/05/21/rnn-effectiveness/ 今日は実装の仕方を説明
  165. 165. 165 many to one  必要なのは最終ステップの出力のみ  例:1行ずつ画像を読み込んで行って、その画像のクラス分類 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved 入力1 入力2 入力3 中間1 中間2 中間2 出力3
  166. 166. 166 many to one実装  ポイントはtf.nn.dynamic_rnnの出力の最終時系列のデータだけを引っ 張ってくること 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved Tensor操作になるのでちょっと手間
  167. 167. 167 ちなみに  tf.static_rnn を使うと 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved 時系列インデックスの配列で帰ってくるので普通に配列の最後にアクセスする だけ
  168. 168. 168 プログラム作成  インポートなど 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved #-*- coding:utf-8 -*- from tensorflow.examples.tutorials.mnist import input_data import tensorflow as tf #mnistデータを格納したオブジェクトを呼び出す mnist = input_data.read_data_sets("data/", one_hot=True)
  169. 169. 169 プログラム作成  モデル構築(入力データ整形) 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved #入力データ整形 num_seq = 28 num_input = 28 x = tf.placeholder(tf.float32, [None, 784]) input = tf.reshape(x, [-1, num_seq, num_input]) dynamic_rnnへの入力は[バッチサイズ, sequenceサイズ, 入力長] tf.reshapeで整形 ※num_seq* num_input=784にするように
  170. 170. 170 プログラム作成  モデル構築(rnn cell作成) 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved #ユニット数128個のLSTMセル #三段に積む stacked_cells = [] for i in range(3): stacked_cells.append(tf.nn.rnn_cell.LSTMCell(num_units=128)) cell = tf.nn.rnn_cell.MultiRNNCell(cells=stacked_cells)
  171. 171. 171 プログラム作成  モデル構築(dynamic_rnn構築、最終時間のみのスライス) 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved #dynamic_rnn構築 outputs, states = tf.nn.dynamic_rnn(cell=cell, inputs=input, dtype=tf.float32, time_major=False) #シーケンス軸のランクを最初に来るように入れ替え #type_major=Trueにしていれば必要ない outputs = tf.transpose(outputs,[1, 0, 2]) #最後のシーケンスのデータのみスライス last_output = tf.gather(outputs, int(outputs.get_shape()[0]) -1) Last_outputは最終時間における[バッチサイズ, 出力長]となり、 いつものニューラルネットワークと同じ!!
  172. 172. 172 プログラム作成  モデル構築(出力層) 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved #出力層 w = tf.Variable(tf.truncated_normal([128,10], stddev=0.1)) b = tf.Variable(tf.zeros([10])) out = tf.nn.softmax(tf.matmul(last_output, w ) + b) 以前書いたものと同じ。以降、lossや評価、実行も全て他のプログラムと同じ RNNなので計算時間もかかる上に、収束も遅い。
  173. 173. 173 Seq2Seq 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 入力画像群の特徴を 圧縮した中間層 出力側では、前の層の 出力が入力になる ※訓練時では正解データを与えることもあります
  174. 174. 174 Seq2Seqの実装の難しいところ  デコーダー側での入力は1ステップ前の出力を使う必要がある  dynamic_rnnは中間層の出力までしか計算しないので、出力層の 値を途中で計算できない 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved ここに1層かます必要 がある
  175. 175. 175 それを行う方法  tf.nn.raw_rnnのloop_functionを用いて定義 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved このAPIまだテスト中だから変わるよ!
  176. 176. 176 こんかいはこちらの方法を使いま す  static_rnnのループの仕組みを利用して計算する  モデル構築が重くなる 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  177. 177. 177 データの受け渡し 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved Placeholderを使って受け渡しをする場合 For ループでplaceholderを量産して、後で参照できるようにadd_to_collection
  178. 178. 178 データの受け渡し 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved feed_dictを作るときはget_collectionで引っ張ってくる あくまでplaceholderを用いる場合。 TFRecordにしてTFのreaderメソッドでバッチ作成する方がスマート
  179. 179. 179 モデル構築(encoder) 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved cellを定義して 入力データと一緒に突っ込 むだけ
  180. 180. 180 モデル構築(decoder) 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved cellの定義はencoderと同じだけど、以下の二つを自作で作っていきましょう。  Rnnのループ処理(1ステップ前の出力を次に使えるように)  出力層の挙動
  181. 181. 181 Decoder側のRNNループ 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved 時間長分ループして出力結果をリストにアペンドしていく 重み再利用のために reuse_variables() 前の出力で入力をアップデート
  182. 182. 182 Decoder側出力層 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved いつもやってる重みとバイアスつかって掛け算 ※reuse_variables()をする関係上、variable_scope。そのため、変数宣言も tf.Variable()ではなくてtf.get_variable()
  183. 183. 183 モデル構築(誤差) 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved RNNループのようにfor文で回して誤差Tensorの配列を作る 最後にadd_nで足し合わせ 実際の精度評価のところもほぼ同じ。
  184. 184. 184 まとめ  再帰的ニューラルネットワークの実装の基本と2つくらいの例の実装の 解説してみました  1.0以降でrnn関係は劇的に変更が加えられているので注意  基本出来にはdynamic_rnnを用いることが推奨される  一部楽に実装したい際はstatic_rnnも結構使い勝手が良い 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved
  185. 185. 185 2017/6/29 C8Lab Copyright 2014 C8Lab Inc. All rights reserved ご静聴ありがとうございました!
  186. 186. 186 お問い合わせ ご興味のある企業・団体・個人様は、以下までお問い合わせください。 シンギュラリティ株式会社 http://snglrty.net 東京都港区浜松町 2-7-15 三電舎ビル6F Tel 03-5425-2545 取締役/CTO 新村拓也 E-mail:info@snglrty.net 2017/6/29 Singularity Copyright 2016 Singularity Inc. All rights reserved

×