20190506のDeepLearningに関する記事は7件です。

[2019年5月版] 機械学習・深層学習を学び、トレンドを追うためのリンク150選

これは何?

5月11日発刊の :books: 図解速習DEEP LEARNINGの書籍中で参照しているリソースをサポートページ用にまとめたものです。
(実行できる.ipynbノートブックへのリンクなど、書籍自体のサポートページは https://github.com/tomo-makes/dl-in-a-sec です)

もともとは本を読みながら各リンクを眺めてもらうため、飛びやすくしようとリンクを整理しましたが、本が手元にない方にも役立つのではと思い、Qiitaで公開することにしました。

凡例

:movie_camera: YouTubeなどのビデオ
:pencil: 論文、サーベイ資料
:bar_chart: プレゼンスライド
:books: 書籍
:octocat: GitHubリポジトリ
:newspaper: ニュース
:mailbox: メールニュース

  • リンクは本の章立てに沿って並んでいます

さて、学会、勉強会、発表会などの1年にあるように、ゴールデンウィーク明けからイベントラッシュ。様々な発表が期待されます :smile:

  • 5/6-9 ICLR 2019
  • 5/6-8 Microsoft Build
  • 5/7-9 Google I/O

1章 機械学習・深層学習を学ぶための地図を持とう

1.1 「知る・わかる」から「できる」へのロードマップ

機械学習・深層学習を学ぶみちすじ

Jupyter Lab/ Colaboratoryなどの対話型環境、それをPaaS/ SaaSとして提供するサービス、チュートリアルが増えてきたので、まず「習うより慣れる」で取り組んで見ると良い、という図。

image.png

「Why/What/How」 - 地図3: 適用分野と手法

「必要な道具と実装」 - 地図6: システム、アーキテクチャと権利

1.2 さまざまな分野と最先端の事例

この節は、表形式・画像/映像・文章/言語・音声/音楽・その他の分野別、また認識・生成・行動といった種類別に追ってみる、事例のシャワーです。

image.png

各分野の広がりと最新状況を知る

数値・表形式 - 推論: データから、対象を予測する

表(テーブル)形式のデータを対象とした機械学習の概要、現状紹介。

画像/映像系 - 認識: AIの目にうつるもの

一般物体認識・特定物体認識の概要、現状紹介。

画像/映像系 - 生成: AIの描き出すもの

GANなどの深層生成モデルの紹介。各デモムービーをざっと見るだけでも面白いです。

画像/映像系 - 認識と生成の間

深層生成モデルの持つ可能性、リスク、解釈性について。こちらも前半のビデオが興味深いです。後半に解釈性の説明があります。

文章/言語系 - 言葉を操るAI

代表的な対話ボットから、文章生成のデモまでを取り上げます。

音声/音楽系 - AIが聴き・話し・演奏するもの

スマートスピーカに代表される音声認識・合成から、音楽の生成まで事例を取り上げます。

グラフを扱う

数理的にグラフとして構造が表されるものはたくさんあります。グラフを扱った深層学習の現状について。

その他の領域

ここまでの紹介に入らない、触覚、3次元モデルなどの深層学習事例について。

強化学習: 行動を学ぶAI

Atariゲーム、碁、最近では多人数プレイのリアルタイム戦略ゲームまで、強化学習の幅が広がりました。その事例について。

1.3 最新の知見についていくために

自分の追いたい抽象度を意識しながら、上のトレンドに終わらせず、継続して最新情報を追いかけてみます。その際のリソース・考え方紹介です。

image.png

新しい情報を取り入れるには

フォローすべきメディア

日次、週次、四半期、年次と鮮度に応じてフォローすると良いメディアの紹介。特にWeekly Machine Learning, Rumors of MLのメールニュース2点はおすすめです。

学会、勉強会、発表会などの1年

歳時記。このGW明けから6月は、色々な発表が楽しみです。

機械学習系の学会

image.png

新製品発表・技術カンファレンス系

image.png

多様な講座と学びのアプローチ

代表的なオンライン講座・動画を取り上げます。

英語情報をうまく活用するには

鮮度の高い英語情報の活用には割り切りも必要。機械翻訳の活用について。

2章 機械学習・深層学習の基礎を学ぼう

2.1 手書き数字識別で機械学習の流れを体感する

Colaboratoryを使ってみる

まとめと発展

2.2 インタラクティブに学ぶ機械学習の舞台裏

2.3 画像認識コンペの世界を覗く

2.4 機械学習の流れ

3章 さまざまな事例を実践してみよう

こちらにはリンクを紹介します。メインはノートブックで26事例を実行し、触れてみることです。ノートブックは、サポートページ https://github.com/tomo-makes/dl-in-a-sec から試せます。

3.1 数値・表形式のデータを使った機械学習を試す

東大松尾研データサイエンス講座に取り組む

まとめと発展

3.2 画像/映像を扱う深層学習を試す

概要

まとめと発展

3.4 自然言語を扱う深層学習を試す

概要

まとめと発展

3.5 音を扱う深層学習を試す

概要

まとめと発展

3.6 強化学習系を試す

概要

まとめと発展

3.7 深層学習を使ったアプリのPrototyping

JavaScriptのMLライブラリ

プロトタイプの開発環境

いろいろな作例を動かしてみる

既存のアプリ作例を見る

まとめと発展

4章 Colaboratory使いこなしガイド

Colaboratoryの概要、詳細は 【秒速で無料GPUを使う】深層学習実践Tips on Colaboratory - Qiita をご覧ください。

Colabを開いてみよう

ノートブックの基本操作

ノートブックのランタイム

ファイルの読み込みと保存

Colabの制約を外したい

おわりに

各分野を概観し、お役にたつものがあれば幸いです。

リンクはリファレンス的に使っていただいても嬉しいですし、

image.png

こんな考え方で、機械学習・深層学習のトレンドをひとっ飛びに追い、理解できる :books: 図解速習DEEP LEARNINGも、よろしければ手にとってくださいまし :smiley:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[2019年5月版] 機械学習・深層学習を学び、トレンドを追うための厳選リンク150選

これは何?

5月6日週に発刊予定の :books: 図解速習DEEP LEARNINGの書籍中で参照しているリソースをサポートページ用にまとめたものです。

もともとは本を読みながら各リンクを眺めてもらうため、飛びやすくしようとリンクを整理しましたが、本が手元にない方にも役立つのではと思い、Qiitaで公開することにしました。

凡例

:movie_camera: YouTubeなどのビデオ
:pencil: 論文、サーベイ資料
:bar_chart: プレゼンスライド
:books: 書籍
:octocat: GitHubリポジトリ
:newspaper: ニュース
:mailbox: メールニュース

  • リンクは本の章立てに沿って並んでいます
  • .ipynbノートブックへのリンクは掲載していません
  • 書籍自体のサポートページは GitHub です(準備中)

1章 機械学習・深層学習を学ぶための地図を持とう

「知る・わかる」から「できる」へのロードマップ

「Why/What/How」 - 地図3: 適用分野と手法

「必要な道具と実装」 - 地図6: システム、アーキテクチャと権利

さまざまな分野と最先端の事例

各分野の広がりと最新状況を知る

数値・表形式 - 推論: データから、対象を予測する

画像/映像系 - 認識: AIの目にうつるもの

画像/映像系 - 生成: AIの描き出すもの

画像/映像系 - 認識と生成の間

文章/言語系 - 言葉を操るAI

音声/音楽系 - AIが聴き・話し・演奏するもの

グラフを扱う

その他の領域

強化学習: 行動を学ぶAI

最新の知見についていくために

新しい情報を取り入れるには

フォローすべきメディア

学会、勉強会、発表会などの1年

多様な講座と学びのアプローチ

英語情報をうまく活用するには

2章 機械学習・深層学習の基礎を学ぼう

手書き数字識別で機械学習の流れを体感する

Colaboratoryを使ってみる

まとめと発展

インタラクティブに学ぶ機械学習の舞台裏

Playgroundで学習とチューニングを行う

画像認識コンペの世界を覗く

下ごしらえ

学習、評価、チューニングを繰り返す

まとめと発展

機械学習の流れ

データセットを準備する

3章 さまざまな事例を実践してみよう

数値・表形式のデータを使った機械学習を試す

東大松尾研データサイエンス講座に取り組む

まとめと発展

画像/映像を扱う深層学習を試す

概要

まとめと発展

自然言語を扱う深層学習を試す

概要

まとめと発展

音を扱う深層学習を試す

概要

まとめと発展

強化学習系を試す

概要

まとめと発展

深層学習を使ったアプリのPrototyping

JavaScriptのMLライブラリ

プロトタイプの開発環境

いろいろな作例を動かしてみる

既存のアプリ作例を見る

まとめと発展

4章 Colaboratory使いこなしガイド

Colabを開いてみよう

ノートブックの基本操作

ノートブックのランタイム

ファイルの読み込みと保存

Colabの制約を外したい

以上

各分野を概観し、お役にたつものがあれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

機械学習でよく出てくる関数のオーバーフローを防ぐ

はじめに

シグモイドやソフトプラス等の指数関数を含む関数を自分で実装すると,指数関数部でオーバーフローになり正しく計算できなくなることがあります。

関数によっては簡単な工夫で防げる場合があるので紹介します。

シグモイド関数

シグモイド関数は

f(x) = \frac{1}{1+\exp(-x)}

で表され,$(-1,1)$の値域をとります。
sigmoid
(画像はWikipediaより引用)

$x$がマイナス方向に行きすぎると,理論的には$f(x)\simeq 0$ですが$\exp(-x)$がオーバーフローします。

$x< 0$のときは分母分子に$\exp(x)$を掛けて変形し,

f(x)=
\begin{cases}
\displaystyle\frac{1}{1+\exp(-x)} & \text{if $x\geq 0$} \\
\displaystyle\frac{\exp(x)}{\exp(x)+1} & \text{if $x< 0$}
\end{cases}

と場合分けすれば常に正しく計算できます。
また,場合分けをまとめると

f(x) = \frac{\exp(\min(0,x))}{1+\exp(-|x|)}

とできます。

ソフトプラス関数

ソフトプラス関数は

f(x) = \log \left( 1+\exp(x) \right)

で表されます。
softplus
(画像はWikipediaより引用)

この関数も$x$が大きくなりすぎると$\exp(x)$がオーバーフローします。

$x\geq 0$のときは$\log$の中身を$\exp(x)$で括り,$\log\exp(x)=x$であることを利用して$\exp(x)$を消します。

\begin{align}
f(x) &= \log\left\{ \exp(x)(\exp(-x)+1) \right\} \\
&= \log\exp(x) + \log(\exp(-x)+1) \\
&= x+\log(\exp(-x)+1)
\end{align}

つまり,

f(x) = 
\begin{cases}
\log(1+\exp(x)) & \text{if $x<0$} \\
x+\log(\exp(-x)+1) & \text{if $x\geq 0$}
\end{cases}

を計算すれば良いことになります。

また,場合分けを上手くまとめると

f(x) = \max (0,x) + \log(1+\exp(-|x|))

と書けます。

ソフトマックス関数

ソフトマックス関数は上記とは異なりベクトルを受け取ってベクトルを返します。
入力を${\bf x} = [x_1, \ldots, x_N]$とすると

{\bf f}({\bf x}) = \left[ \frac{\exp(x_i)}{\sum_j \exp(x_j)} \right]_{i=1}^N

で表されます。

入力${\bf x}$の中で最大の値を持つ要素を

x^{\rm m}=\max(x_1,\ldots,x_N)

とし,分母分子を$\exp(x^{\rm m})$で割った

{\bf f}({\bf x}) = \left[ \frac{\exp(x_i-x^{\rm m})}{\sum_j \exp(x_j - x^{\rm m})} \right]_{i=1}^N

を計算することでオーバーフローを回避できます。

おわりに

いずれも指数関数の引数が0以下になるようにするのがポイントです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【特徴部位可視化】Grad-CAMとGuided Grad-CAMで遊んでみた♬「DLの不安定問題」

前回の大きな問題は、
「※なぜか、上で一個だけ得たときのものはここでは二番目の候補になっていますが、このまま掲載することとします(バグがありそうですが見つけた時点で修正します)」
という問題です。

特に何か変更していないのに、結果が異なるというのはちょっと勘が働きます。

ということで原因調査してみた結果、「DLの不安定問題」という大発見をしたので、掲載しておきます(笑)
(1)オリジナル画像;論文等の画像から処理したもの
※入力画像を元画像としています。番号は予測ランキングを示します。
 モデルはmodel = VGG16(weights='imagenet')であり、なんら変更していません。

元画像
cat_dog 242boxer 243bull_mastiff 282tiger_cat 292tiger 246Great_Dane
cat_dog.png gradcam242boxercat_dog.png.jpg gradcam243bull_mastiffcat_dog.png.jpg gradcam282tiger_catcat_dog.png.jpg gradcam292tigercat_dog.png.jpg gradcam246Great_Danecat_dog.png.jpg
cat_dog.png guided_gradcam242boxercat_dog.png.jpg guided_gradcam243bull_mastiffcat_dog.png.jpg guided_gradcam282tiger_catcat_dog.png.jpg guided_gradcam282tiger_catcat_dog.png.jpg guided_gradcam292tigercat_dog.png.jpg

(2)ダウンロード画像;ウワンの記事からダウンロードしてそのまま利用
※ちょっとフチがあります

元画像
dog_cat 243bull_mastiff 242boxer 292tiger 246Great_Dane 247Saint_Bernard
dog_cat.png gradcam243bull_mastiffdog_cat.png.jpg gradcam242boxerdog_cat.png.jpg gradcam292tigerdog_cat.png.jpg gradcam246Great_Danedog_cat.png.jpg gradcam247Saint_Bernarddog_cat.png.jpg
dog_cat.png guided_gradcam243bull_mastiffdog_cat.png.jpg guided_gradcam242boxerdog_cat.png.jpg guided_gradcam292tigerdog_cat.png.jpg guided_gradcam246Great_Danedog_cat.png.jpg guided_gradcam247Saint_Bernarddog_cat.png.jpg

(3)フチなし画像;(2)の画像のフチを処理してフチなしにしたもの

元画像
dog_cat_noframe 242boxer 243bull_mastiff 246Great_Dane 292tiger 247Saint_Bernard
dog_cat_noframe.png gradcam242boxerdog_cat_noframe.png.jpg gradcam243bull_mastiffdog_cat_noframe.png.jpg gradcam246Great_Danedog_cat_noframe.png.jpg gradcam292tigerdog_cat_noframe.png.jpg gradcam247Saint_Bernarddog_cat_noframe.png.jpg
dog_cat_noframe.png guided_gradcam242boxerdog_cat_noframe.png.jpg guided_gradcam243bull_mastiffdog_cat_noframe.png.jpg guided_gradcam246Great_Danedog_cat_noframe.png.jpg guided_gradcam292tigerdog_cat_noframe.png.jpg guided_gradcam247Saint_Bernarddog_cat_noframe.png.jpg

(4)フチあり画像;(2)の画像にさらにフチを広げたもの

元画像
dog_cat_Bigframe 163bloodhounddog 166Walker_hounddog 246Great_Dane 161basset 167English_foxhound
dog_cat_Bigframe.png gradcam163bloodhounddog_cat_Bigframe.png.jpg gradcam166Walker_hounddog_cat_Bigframe.png.jpg gradcam246Great_Danedog_cat_Bigframe.png.jpg gradcam161bassetdog_cat_Bigframe.png.jpg gradcam167English_foxhounddog_cat_Bigframe.png.jpg
dog_cat_Bigframe.png guided_gradcam163bloodhounddog_cat_Bigframe.png.jpg guided_gradcam166Walker_hounddog_cat_Bigframe.png.jpg guided_gradcam246Great_Danedog_cat_Bigframe.png.jpg guided_gradcam161bassetdog_cat_Bigframe.png.jpg guided_gradcam167English_foxhounddog_cat_Bigframe.png.jpg

同じ画像にフチがあるか無いか程度の差で予測が異なっています。
ただし、Grad-CAMやGuided-Grad-CAMの絵はそれほど大きく変わっているわけではなく、そうなんだろうという程度の結果を出力しています。
つまり、元々カテゴリが近すぎて、混在しやすいというリスクがあるものと想像できます。
この辺りは、まだまだ研究が必要だと思います。
「DLといえども、ほどほどなカテゴリ数なり、特徴が異なるカテゴリでの適用が無難なのかもしれません」

まとめ

・バグだと思っていたが、「DLの不安定問題」という結論でした
・入力画像のちょっとした違いにより、同じ画像も異なった分類をする危険性があることが判明

・騙しとの関連で、カテゴリ間類似性の問題をさらに研究する必要がある
・「DLといえども、ほどほどなカテゴリ数なり、特徴が異なるカテゴリでの適用が無難なのかもしれません」⇒容認できる(誤答しない)基準が必要なので目安を見つけたいと思う

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ElixirでDeep Learningに再挑戦 (最終回)将来構想

はじめに

DLの基本部分はできました。Elixirらしい外観、仕様を持たせようと思っています。将来構想についてまとめました。

ElixirでDeep Learningに再挑戦 (1)
|> ElixirでDeep Learningに再挑戦 (2)
|> ElixirでDeep Learningに再挑戦 (3)
|> ElixirでDeep Learningに再挑戦 (4) 誤差逆伝播法
|> ElixirでDeep Learningに再挑戦 (5) 畳み込み
|> ElixirでDeep Learningに再挑戦 (6)勾配確認 バックプロパゲーション完全動作
|> ElixirでDeep Learningに再挑戦 (7)MNIST
|> ElixirでDeep Learningに再挑戦 (8) 並列動作
|> ElixirでDeep Learningに再挑戦 (9)バッチで並列

Elixirときたらこれでしょう

Elixirのコードでとても印象的なものというと |> パイプ演算子でしょう。ニューラルネットワークを記述するのにもこれを利用します。マクロを使って実装します。

defnetwork foo(x) do
  x |> f(2,2) |> sigmoid |> pool(2)
  |> w(8,4) |> b(4) |> sigmoid 
  |> w(4,2) |> b(2) |> sigmoid
end

下記はざっとした仕様です。

ネットワークの生成
マクロであり内部データに変換したうえでdef endで定義する。
f(m,n) m行、n列のガウス分布行列を生成、その行列をフィルターにして畳み込み演算をする。
pool(s) ストライドをsとしてプーリングする。
w(r,c,f) はr行c列のガウス分布乱数を要素とする行列を生成する。
fはその平均値指定、省略可
b(c) バイアス用の行ベクトルを生成する。値はゼロ。

内部データ構造
DL.network([[c1,cf1,p1]...],[[r1,c1,f1,g1,r1],[r2,c2,f2,g2,r2] ....]])
入力層より順にスペックを記述する。
r行、c列で要素がガウス分布の乱数である行列を生成する。バイアスは要素0でc列
fは活性化関数
gはfの微分関数
rは学習率
DL.batch(image,train,n,c)
教師データからランダムにn個を選択してc回学習する。
DL.save(failname,network)
networkをファイルに保存する。
DL.load(filename)
ファイルからnetworkデータを読み込む

DLもElixirらしくやりたいのでした。

心臓部

DLの学習には時間がかかります。いかに高速に行えるのかというは重要な要素です。

山崎先生のグループが開発しているHastegaを利用します。現在の行列積はSpawnを使った並列によるものです。これですとicore5で逐次処理の2.9倍程度が限界です。しかし、HastegaはGPUを利用するので80程度の高速化があるとのことです。

その他

学習率について様々な知見、技法があります。これらを取り入れます。初期値についてもいろいろとバリエーションがあるそうです。できるだけこれらを取り入れます。

並列の時代

いずれ量子コンピューターが使われる時代が到来するのでしょうが、それまでは現状のCPU技術の延長上で発展していくものと予想されます。動作クロックは電子回路の物理的な上限に達しており、マルチCPUの方向になることでしょう。GPUもさらに高性能化することと予想されます。こうなると並列を駆使できる言語処理系であるElixirにかなりアドヴァンテージがあるように思います。現在、Elixirは次世代WEBのための言語処理系として注目されています。しかし、その潜在能力は高く、科学技術計算など他分野でもその並列を活かして発展することが期待されます。

おわりに

長々と投稿にお付き合いいただきましてありがとうございました。今後はジワジワとDLの実装を仕上げていく予定です。

参考文献

1「深層学習」 岡谷貴之 著 
2「ゼロから作る Deep Learning」 斉藤 康毅 著
3「Excelでわかるディープラーニング 超入門」 涌井良幸 涌井貞美 著
4「Hastega: Elixirプログラミングにおける超並列化を実現するためのGPGPU活用手法 」
https://zeam-vm.github.io/GPU-SWoPP-2018-pr/#/

全コード

GitHubにおいてあります。
https://github.com/sasagawa888/DeepLearning

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

胸部X線画像を対象とした敵対的生成ネットワーク - DCGAN -

やりたいこと

参考書やGithubを見ながら、見様見真似でまずDCGANを試してみたい。
今回は簡易的なDCGANで、胸部X線画像を入力して、似たような画像が生成できるか試す。

環境

  • Ubuntu 18.04
  • Anaconda 1.9.6
  • Tensorflow-gpu 1.12.0
  • Keras-gpu 2.2.4
  • GeForce GTX 1050 Ti(totalMemory: 3.95GiB freeMemory: 3.89GiB) + AkiTiONODE

必要なもの

日本放射線技術学会「標準ディジタル画像データベース[胸部腫瘤陰影像]」SuperResolution01
http://imgcom.jsrt.or.jp/minijsrtdb/

画像サイズ 256*256、色深度 Gray 8 bitのデータ(一番上段のもの)を選択してダウンロード。
ダウンロードしたら解凍。ここではわかりやすくデスクトップへ。
SuperResolution01.zipをデスクトップに移動して、右クリックから「ここで展開」を実行。

画像の前処理

  1. デスクトップに新しく「DCGAN01」フォルダを作成する。
  2. さらに、この「DCGAN01」フォルダの中に「org」フォルダを作成する。
  3. SuperResolution01内にある「train/org」内のすべての画像と、SuperResolution01内にある「test/org」内のすべての画像とを「DCGAN01/org」にコピー&ペーストする。おそらく、画像は全部で247枚になるはず。
  4. その後、「DCGAN01/org」内のすべての画像をリネームする。リネームは、画像を全選択して、右クリックなどで名前の変更を行う。この際、ベースになるファイル名は同じになるようにして、末尾に番号が振られるようにすると後の作業がやりやすい。例えば、small_1.png small_2.png small_3.png ...など。
  5. そして、「DCGAN01/org」内の画像数を「32」で割れる数に合わせる。ここでは例として「224」枚の画像を残すようにする。つまり、225〰247枚目の画像は削除してしまう。
  6. 次に、新しく「DCGAN01」内に「small_org」フォルダを作る。(この時点で、「DCGAN01」フォルダの直下には、「org」と「small_org」の2つのフォルダができた。)
  7. 続けて、「DCGAN01/small_org」のフォルダに、「train」フォルダを作成する。ここは重要なので注意(ImageDataGenerater(class_mode=None)への対応)。
  8. ここまでできたら、このままでは画像のマトリクスが256*256となっており、練習には重いので、マトリクスを32*32まで落とす。方法はいくつかある。

方法1:ImageJ

ImageJで224枚の画像を一遍にスタックとして開き、リサイズ(補間法は任意でいい)して、任意の一般画像フォーマットで保存する。(おそらく、スクリプトを書かないとマンパワーが、、。)

方法2:コードを書く

'''
Created on 2019/05/05

@author: tatsunidas
'''
import glob, os
import numpy as np
from skimage.io import imread
from scipy.misc import imresize
from PIL import Image

#ここは自分の環境に合わせて下さい
org_dir = '/home/tatsunidas/デスクトップ/DCGAN01/org/'
small_dir = '/home/tatsunidas/デスクトップ/DCGAN01/small_org/'

datasets = glob.glob(org_dir+'*.png')
for data in datasets:
    img = imread(data,as_gray=True)
    #array to PIL
    img = Image.fromarray(np.uint8(img))
#     img = imresize(img,(32, 32), interp='bicubic')# return as ndarray
    img = img.resize((32,32), Image.BICUBIC)
    img.save(small_dir+'train/'+os.path.basename(data))

ここまでで、このような状態になる。

Screenshot from 2019-05-06 01-30-36.png

画像はすべて32*32マトリクスになっている。
Screenshot from 2019-05-06 01-33-33.png

コード

今回はほぼすべて参考URLを参考にさせていただき、組んでみた。DCGANの中でも比較的シンプルでわかりやすい。

'''
Created on 2019/05/05

設定
モデル構築(GAN)
モデルトレーニング
モデル保存

@author: tatsunidas
'''

import os
from keras.preprocessing import image
from keras.preprocessing.image import ImageDataGenerator
import keras
from keras import layers
import numpy as np

#トレーニングデータの場所
TRAIN_DIR = '/home/tatsunidas/デスクトップ/DCGAN01/small_org/' #trainまで指定しないことに注意
#生成画像の保存先:任意の場所へ(コードを実行する前にフォルダを作っておいて下さい。)
save_dir = '/home/tatsunidas/デスクトップ/DCGAN01/dcgan_sampling/' 
latent_dim = 32 # 殆どの場合、height,widthと同じ値に。
height = 32
width = 32
channels = 1

batch_size=16#とりあえず

#贋作生成(ジェネレータ)モデルを構築
generator_input = keras.Input(shape=(latent_dim,))
# 入力を16*16,128 channelの特徴マップへ
x = layers.Dense(128*16*16)(generator_input)
x = layers.LeakyReLU()(x)
x = layers.Reshape((16,16,128))(x)
#畳み込み層を追加
x = layers.Conv2D(256,5,padding='same')(x)
x = layers.LeakyReLU()(x)
#32,32へアップサンプリング
x = layers.Conv2DTranspose(256,4,strides=2,padding='same')(x)
x = layers.LeakyReLU()(x)
#さらに畳み込み層を追加
x = layers.Conv2D(256,5,padding='same')(x)
x = layers.LeakyReLU()(x)
x = layers.Conv2D(256,5,padding='same')(x)
x = layers.LeakyReLU()(x)
#32.32.1の特徴マップへ
x = layers.Conv2D(channels,7,activation='tanh',padding='same')(x)

generator = keras.models.Model(generator_input,x)
generator.summary()

'''
discriminator(贋作判別器)
'''
discriminator_input = layers.Input(shape=(height,width,channels))
x = layers.Conv2D(128,3)(discriminator_input)
x = layers.LeakyReLU()(x)
x = layers.Conv2D(128,4,strides=2)(x)
x = layers.LeakyReLU()(x)
x = layers.Conv2D(128,4,strides=2)(x)
x = layers.LeakyReLU()(x)
x = layers.Conv2D(128,4,strides=2)(x)
x = layers.LeakyReLU()(x)
x = layers.Flatten()(x)
#ドロップアウトを追加。重要
x = layers.Dropout(0.4)(x)
#判別分類
x = layers.Dense(1,activation='sigmoid')(x)
#discriminatorモデルをインスタンス化
discriminator = keras.models.Model(discriminator_input,x)
discriminator.summary()

#オプティマイザで勾配刈り込み(clipvalue)
discriminator_optimizer = keras.optimizers.RMSprop(lr=0.0008,clipvalue=1.0,decay=1e-8)
discriminator.compile(optimizer=discriminator_optimizer,loss='binary_crossentropy')

#生成と判別をつなぎ合わせる(つまり、GANを構築する)
#discriminatorの重みを凍結
discriminator.trainable = False
gan_input = keras.Input(shape=(latent_dim,))
gan_output = discriminator(generator(gan_input))
gan = keras.models.Model(gan_input,gan_output)
gan_optimizer = keras.optimizers.RMSprop(lr=0.0004,clipvalue=1.0,decay = 1e-8)
gan.compile(optimizer=gan_optimizer,loss='binary_crossentropy')

#training dataの作成
data_gen = ImageDataGenerator(rescale=1./255)
data_gen = data_gen.flow_from_directory(TRAIN_DIR,
                                        target_size=(32,32),
                                        batch_size=batch_size,
                                        class_mode=None,
                                        color_mode= "grayscale")
#GANのトレーニング開始
iterations = 10000 #エポックと同意。とりあえず10000
for step in range(iterations):
    #贋作を作るために、無作為にベクトルを作成
    random_latent_vectors = np.random.normal(size=(batch_size,latent_dim))
    #偽物画像にデコーディング
    generated_images = generator.predict(random_latent_vectors)
    #本物の画像を取得
    real_images = data_gen.next()
    combined_images = np.concatenate([generated_images,real_images])
    #本物の画像と偽物の画像を区別するラベルを組み立て
    labels = np.concatenate([np.ones((batch_size,1)),np.zeros((batch_size,1))])
    #ラベルにランダムノイズを追加,重要なトリック
    labels += 0.05 * np.random.random(labels.shape)
    #discriminator(判別器)を訓練
    d_loss = discriminator.train_on_batch(combined_images, labels)
    #潜在空間から点をランダムに抽出
    random_latent_vectors = np.random.normal(size=(batch_size,latent_dim))
    #これらは全て本物というラベルを作成
    misleading_targets = np.zeros((batch_size,1))
    #ganモデルを通じて、generatorを訓練
    a_loss = gan.train_on_batch(random_latent_vectors, misleading_targets)
    #訓練過程でモデルと結果を保存
    if step % 1000 == 0 or step == iterations-1:
        gan.save_weights('gan-discloss_%s_advloss_%s.h5' %(d_loss,a_loss))
        #成果を出力
        print('discriminator loss at step %s: %s' %(step,d_loss))
        print('adversarial loss at step %s: %s'%(step,a_loss))
        #生成画像を保存
        img = image.array_to_img(generated_images[0]*255.,scale=False)
        img.save(os.path.join(save_dir,'generated_chest_'+str(step)+'.png'))
        #比較のために本物も保存
        img = image.array_to_img(real_images[0]*255.,scale=False)
        img.save(os.path.join(save_dir,'real_chest_'+str(step)+'.png'))
        if step == iterations-1 :
            print('finish iterations')
        else:
            print('now training gan ..., last step is %s'%(step))

結果

Montage-1.jpg
Montage-11.jpg
上段は生成画像、下段はオリジナル画像。
左からエポック0,1000,2000,3000,4000,5000,6000,7000,8000,9000

この記事を書いたモチベーション

勉強のために。

その他

誤記などありましたらご指摘下さい。

参考URL

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WCSC29うさぴょん外伝評価関数部詳細

ネットワーク構造

アピール文書で公開したとおり、基本は256Filter 13層のResNetです。
通常のResNetにはBatchNormalize Layerが噛んでるかと思いますが、mEssiah評価関数では使用していません。

計算量内訳.png

今回のmEssiah評価関数の肝はMagic Vec部分です。これを思いつくまで3年かかりました。
最初の発想は通常のDQNの例のように将棋でも合法手全ての評価値を一気に出す方法はないだろうか?ということでした。
将棋ではなぜこれができないのかというと、合法手の数が局面によって可変である、ということと、合法手の種類がとても多いということです。
まず、合法手全ての評価値を一気に出すには、ネットワークの出力次元を合法手の数にする必要があるわけですが、それを可変にすることは基本的にできません。
そうすると、合法手の最大数をネットワークの出力とする、という選択が考えられるのですが、これもまた問題が発生します。
合法手をどうやって表現するか?という問題がまず立ちふさがります。
将棋の合法手は最大約600個であると証明されています。
ですので600次元用意しとけばいいや、ってわけにはいかないのが大変なところなんです。
最大600個であっても600種類ではない、ってところが大問題なんですね。
将棋の合法手の種類はだいたい(移動開始位置81マス+駒台の駒7種類)×(移動先位置81マス)×(成るか成らないか)の14256種類あります。(実際には移動開始位置と移動先が同じということはありえない、とかいろいろあるのでもう少し減ります)
じゃあ14256次元出力すればいいんじゃないか、という話なんですが、これにはこれで問題が発生します。
学習時には14256次元のうちの1個しか教師が与えられません。
これがどうして困るかはなかなかぴんと来ないかもしれませんが、分類問題で1万以上のクラスがある場合には学習が非常に困難になる、というのとほぼ同じ理屈で学習が難しくなります。
そこで次に考えたのが、別に1個だけ1にするんじゃなくて、3個1使えば次元削減できるじゃないか、という発想です。
出力を88+81+2次元にして、合法手を3つの1を立てることによって表現するってことですね。
これでもそこそこうまくいってたのですが、よくよく考えると合法手の評価値を3つの数の線形和で表現してることになるんですね。
で、よ~く考えると絶対表現できない組み合わせがあることに気づきます。
開始位置が同じで移動先が違う手で勝ちと負けな場合で、なおかつ、開始位置が違って移動先が同じ場合で勝ちと負けな場合という場合はどうやってもたぶん無理じゃないかと思ったわけですね。
実際に数学的に証明したわけではないのであれなんですが。
で、残念ながらこれではだめだということで2年ほどこの方向性は封印されます。
2年ほど通常の方法でやってきたわけですが、やはりどうしても評価の大幅なスピードアップが必要である、と感じました。
そこでまたこの方向性を引っ張り出してきたんですが、DeepLearning技術もだいぶ発展してきて、いろんな技術も出てきただろうから超多クラス分類の手法とかもあるんじゃないか?といろいろぐぐってみたわけですね。
そこでヒットしたのが出力の圧縮という技術です。
超多クラス分類の世界だと1万以上の次元の1hot vectorをなんらかの学習法によって低次元に圧縮して、それを分類問題を解くためのネットワークの出力とする、みたいな手法があるということがわかりました。
これは使えそうだと思ったのですが、その圧縮したものを作る方法が将棋では見つからなかったんですね。
そこで最後のキーワード「Word2Vec」の登場です。
この手法はEmdeded Layerを利用して単語の1Hot Vecを分散ベクトルに変えてしまって学習を行う、というものです。
これはいける!と思ったんですが、Word2VecもEmbeded Layerを学習するには本番とは別の学習を必要とすることがわかりました。
この「本番とは別の学習」ってのが何かあればできるわけですが、そんなものは将棋では思いつかなかったわけです。
しょうがないのでとりあえず本番と同じ方法で学習させてみて、ダメだったらあきらめようと思いました。
ですが、本番と同じ方法の学習でできちゃったんですね。あら不思議。
なんでもやってみるもんですね。こんな感じでMagic Vecが誕生しました。

mEssiah学習.png

入力について

入力についてはいろいろ精査しました。
その結果、このような形になりました。

基本は1チャンネル9*9の盤面+4*9の駒台の計13*9=117です。

チャンネル0~7 駒種ごとの入力。先手駒は+1、後手駒は-1、持ち駒は左上寄せで1枚ずつ

チャンネル0 歩
チャンネル1 香車
チャンネル2 桂馬
チャンネル3 銀
チャンネル4 角
チャンネル5 飛車
チャンネル6 玉
チャンネル7 金

チャンネル8 成り駒チャンネル。その駒が成り駒である場合、先手+1、後手-1

チャンネル9~10 効き(方向なし) そのマスに効きがあるかどうか

チャンネル9 先手効き 先手の駒の効きがある場合+1
チャンネル10 後手効き 後手の駒の効きがある場合-1

チャンネル11~50 効き(方向あり)この入力は先手、後手ともONの場合は+1

チャンネル11~30まで先手の効き
チャンネル31~50まで後手の効き

チャンネル11 右下からの効き
チャンネル12 下からの効き
チャンネル13 左下からの効き
チャンネル14 右からの効き
チャンネル15 左からの効き
チャンネル16 右上からの効き
チャンネル17 上からの効き
チャンネル18 左上からの効き
チャンネル19 右下からの桂馬の効き(先手のみ)
チャンネル20 左下からの桂馬の効き(先手のみ)
チャンネル21 右上からの桂馬の効き(後手のみ)
チャンネル22 左上からの桂馬の効き(後手のみ)

ここから飛び効き
飛び効きは香車、飛車、龍、角、馬の効きで、飛び効きラインの効きは効きを発生させる駒のとなりのマスの効きであってもこのチャンネルに入力される。
龍、馬の効きで飛び効きラインではない効きは上記11~22チャンネルに入力される。
方向の並びは、チャンネル11~18と同じ。

チャンネル23 右下からの飛び効き
チャンネル24 下からの飛び効き
チャンネル25 左下からの飛び効き
チャンネル26 右からの飛び効き
チャンネル27 左からの飛び効き
チャンネル28 右上からの飛び効き
チャンネル29 上からの飛び効き
チャンネル30 左上からの飛び効き

チャンネル31~50 後手の効き 並びは先手と同じ。入力はONのときは+1

チャンネル51~54 効き(ひもと当たり)

チャンネル51 先手の駒の先手の効きがついている(ひもがついている)場合+1
チャンネル52 先手の駒に後手の効きがついている(あたっている)場合-1
チャンネル53 後手の駒に先手の効きがついている(あたっている)場合+1
チャンネル54 後手の駒に後手の効きがついている(ひもがついている)場合-1

チャンネル55 手番 先手番である場合、117全面+1、後手番である場合全面-1

以上0~55チャンネルの計56チャンネル*117の6552次元の入力です。

マイナスの入力を使うことによって駒位置の次元数を約半分にしたんですが効きの入力は同じチャンネルにプラスとマイナスを使うことができず、結局あまり次元数は削減できていません。

学習方法

基本はDQNですが、限りなく雑巾しぼりに近くなっています。
試行を256スレッドで行い、メモリーにためていきます。
100万局面たまったところで学習フェイズに移行し、BatchSize64を2万Iterationします。
これは、GPUメモリ的にBatchSize64が限界なこと、BatchSize64で100万局面使いきるのに約2万Iterationかかること、ということでこの値が決定されています。
また、メモリーへの登録は1手ごとではなく1局ごとに行い、λ収益の計算が可能なようになっています。
ですので、メモリーに登録される教師値は1局ごとに集計されたλ収益を使っています。
λ収益の計算は前方参照ではなく後方参照でできるので簡単です。
以下、各種パラメータです。

Mini Batch size 64
1cycle iteration 20000
割引率 1.0
λ 0.5
Optimizer Adam
学習率 0.03
1cycle Avg Time 3700sec(Play Phase 1000sec,Learn Phase 2700sec)

これをだいたい800cycle行ったものがWCSC29版です。
本当は最低2000cycleはやりたかったんですが、時間が足りませんでした。

来年までにはもう少し学習を進めようかと思ってます。

mEssiah開発者は開発資金援助及び投げ銭を常に募集しています。@messiah_ai に欲しいものリストもありますのでぜひ!

追伸:mEssiah開発者は相変わらず仕事も募集しています。専門はなんちゃって強化学習です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む