エンジニアMのAI学習記録(2017年12月分)
当社のWeb関連技術の公開と採用活動のために掲載しています。
(2017年12月28日更新)
みなさんこんにちは、エンジニアのMです。
これは当社の技術やAIに興味のある方に向けた日誌になります。
今月も毎週更新していきます、よろしくお願いします。
この記事の目次
12月4日
■ 類似度計算をいじる
行列の生成コストが高すぎるので、類似度計算の際にレーベンシュタイン距離も含めて計算するようにして、掛かる時間を比較してみる。
実際は小規模なデータセットを想定しているので、行列を作って使いまわしたほうがいい気はする。大規模なデータセット向けの案となる。
■ 結果
行列作成の時間がほぼ無くなり、類似度の計算時間も多少長くなった程度で済んだ。疎行列にメモリを大量消費していたのも解消された。
この位の計算量なら、初めからこれで良かったのかもしれない。
ついでに作業の過程で、行列の参照先が間違っていたバグも見つかった。
まだまだ課題はありそうだが、これ以上改善・改良するアイデアがすぐ出てこないので、ひとまずここまでとする。全体として目的は達成できたので、満足している。
■ チャットボットをいじる
前回、あまりうまく動いてくれなかったチャットボットを改善できないか試してみる。
こちらは一回のトライ&エラーに数時間かかってしまうので、アイデアを2,3試してみる程度とする。
■ 辞書に含む単語の種類を増やす
50,000に設定されているものを、100,000に増やしてみる。
未知語が多いために、UNK(Unknown)で返ってくる確率が高くなっているのではと考えた。
変更前と比べると1Stepに掛かる時間は2倍近くなったが、以前試した時と同じくらいのStep数までは進めておきたい。
自分のコードを見返したり、調べ物をしながら待つことにする。
増やした結果、未知語が返ってくる割合は減ったように感じる。
これはどうやら有効な方法のようなので、次はMeCabの辞書としてNEologdを使うようにして試してみる。
12月5日
■ NEologdを使って形態素解析→学習させる
辞書を見る限り、ネットスラングなどにもかなり対応して分かち書きできている。このあたりは、ネット上の情報を積極的に取り込んでいる強みが発揮されている。
あとは学習を回して結果を待ちたい。いつものように5時間コースだ。
■ Webニュース記事から
- マイナビニュース:2018年オープンソース技術トレンド10選 [リンク]
に名前のあったプログラミング言語、「Rust」について調べる。
今のところPythonに不満があるわけではないが、Mozillaが開発している言語ということで少し興味がある。
特徴とコードの雰囲気を学んでおきたいと思う。
- 参考:Rustは何が新しいのか(基本的な言語機能の紹介) [リンク]
コード例を眺めていてもなかなかピンとこない。並列化プログラミングとC++の経験が無いので、良さがなかなか分からないのが問題か。
■ チャットボットを試す
step 29,000まで来たが、学習用データのPerplexityは30あたりが下限で、バリデーション用データに関しては60から下にはなかなか行かず。
単語数50,000で試した時はPerplexityが15(バリデーション用に関しては変わらず60)あたりまで下がっていたので、扱う単語が増えた分、学習の進みが遅いようだ。
対話してみたが、まだUnknownで返ってくることが多い。
総単語数を確認したが、8割くらいはカバーできているようだったので、ひとまず手を加えずにもうしばらく回してみることにする。
■ さらに試す
Step 41,500、Perplexityが20前後のところでもう一度試してみた。
サンプルがTwitterなので、それらしい応答が来るように意識して会話してみる。
(※B = BOT)
私:おはよう
B:おは よ
私:今日学校行った?
B:そ ー よ
私:えらい
B:なつかしい
私:なつかしい?
B:なるほど ?
私:明日寒いらしいよ
B:わかる
私:寒いの平気?
B:そう だ よ !
私:元気だなー
B:キレ てる ん ?
私:寒さにキレてる
B:よろしく ね ♡
私:寒さの原因は貴様かw
B:え ?
私:草
B:草
妙な味が出てきたように感じる。脈絡はあまり無い。
Twitterのやり取りというノイズ過多のようなデータでも、これくらいのレベルまでになることに驚く。
私:今日何食べた?
B:今日 は 寒い よ 。
私:知ってるw
B:さすが w
何とも言えない人間味を感じる。ELIZA効果というものを実感する。
私:最近の経済界で不正が次々見つかってる件
B:そういう こと や
私:そういうことなら仕方ないな
B:え ぇ
時事問題を振ってみたが、そういうことらしい。
こういう返答が来るということは、対話データの中にこんなやり取りも含まれていたのだろうか。
単語数100,000+NEologdという設定はうまくいっているようなので、学習を継続させて変化があるか見ていくことにする。
12月6日
■ 外部メモリーつきニューラルネット(DNC)に小説を生成させたらどうか
RNNで小説を学習させて自動生成する、ということをしている記事は以前にいくつか見てきた。
そこに外部メモリーの概念を持ち込んだら、より流れ、ストーリーのある小説を出力するのでは無いかと思った。
改めてDNCについて解説している記事を読んで、なんとか実装できないか考えてみる。
12月7日
■ チャットボットに使ったSeq2Seqを活用できないか考える
小説であっても、文が入力されて文が出てくるという流れには違いないので、使ったSeq2Seqモデルのコードを流用してなんとかできないか考えてみる。
大部分を流用して学習させる目処がついたので、あとはうまく動くことを願うばかり。
12月8日
■ まずは手元にあるデータで試してみる
小説のデータセットというと、まず「青空文庫」が出てくる。
だがせっかくなので趣の違うデータで試してみたい、ということで途中までダウンロードして放置していた、
- 小説家になろう:「Re:ゼロから始める異世界生活」(作者:鼠色猫/長月達平) [リンク]
をお借りして試してみる。
- source.txt:適宜正規化を済ませた1行1文で、全文を含むもの。
- target.txt:source内の各文の次に来る文を並べたもの。各文書の最終行に対するtargetは終了コードENDとして扱う。1文書の区切りについて学習することを期待する。
チャットボットのコードを流用するので、このような形式を取った。
ある文に対する次の文というペアを全てデータ化することによって、bucket化、バッチ処理による順序のランダムな学習でも、問題なく機能するはず。
bucketはソースが小説であることを考慮し、[ 5,10 ]を削除して、[ 80,100 ]を追加した。
■ 機械学習における著作物の扱いについて
- ITmedia NEWS:「日本は機械学習パラダイス」 その理由は著作権法にあり[リンク]
- STORIA法律事務所ブログ:第三者のデータやデータセットを利用して適法にAIを生成するための基礎知識 [リンク]
- ディープラーニングと著作物 [リンク]
上に挙げたのは現段階での解釈の一部に過ぎないし、今後事情が変わってくる可能性もある。
とりあえず今のところは、契約の有無が重要なポイントのようだ。
■ 試してみたが
学習用データとバリデーションデータに分割せずに学習を行い、perplexity = 2 前後になったところで実験してみる。
しかし、無限ループに陥ってしまうか、すぐにENDコードが出力されてしまうケースが多かった。
データセットの再確認とコードの見直しをする。
また新たにダウンロードした部分も投入して、改めて回してみることにする。
■ 悪戦苦闘
結果が悪化してしまったので、正規化処理を強化し、長文を捨てた上でバリデーションデータに一部を隔離することに。
GPUのメモリ量が足りず、コード内のLAYER_SIZEやNUM_LAYERSの値を大きくすることもできないので、色々と削って少しでも結果を出す方向でいく。
外部メモリを使って実験するには、メモリの管理的にかなり厳しいことになりそうな予感がする。
過学習の解消もしなければならないとなると、ハードなタスクになりそうだ。
12月11日
■ Seq2Seqモデルによる小説生成の続き
API Overviewを眺めていたら、tf.contrib.rnn.DropoutWrapperクラスを使って、RNNセルにドロップアウトを適用できることが分かった。
この変更によって、過学習の回避にどれほどの効果があるか検証する。
効果がありそうなら、チャットボットの学習にも適用して試してみても良さそうだ。
■ 学習を回してみたが
同じワードの繰り返しを出力することは避けられたが、記事で見かけた「出力がEOSに引きずられる問題」に直面した。
どちらか一方が短すぎる文のペアを除外し、改めて学習させてみることに。
また同様の理由でENDフラグを文に仕込むのをやめた。
Seq2Seqによる文章生成は想像以上に難しい。
12月12日
■ 引き続きSeq2Seq
まだ意味のある(ように見える)文章の生成には至っていないので、試行錯誤を続けていく。
とりあえず昨日の変更によって過学習は回避することができているので、もっとデータを集めて回してみても良さそうだ。
■ そのまま回し続けた結果
データを収集したり、他の調べ物をしている間に回し続け、27000 Stepに到達したところで予測させてみた。
意味はよく分からなくとも、だいぶ文として成立するようにはなってきているようだ。
しかし、辞書内で17番目(制御文字含む)の「スバル」や、65番目の「レム」といった人名が頻繁に出現する傾向が見られた。
登場頻度もさることながら、部分的に妥当な繋がりを作りやすいのが理由であると考えられる。
それっぽい文章を生成するためには、やはり複数の作品からなるデータセットが偏りを防止する上でも不可欠か。
・出力例
開始文)
精神的に優位をとられて、思わず席をフェルトに譲ってしまうスバル。(第一章9より)
出力文)
スバルは明らかに悲壮な存在していたのだ。
それを、スバルのふりに越しな。
彼女は、その口元にしてできなかった。
だが、スバルはスバルはわからない。
彼は、戦っては純粋にやっている。
スバルは、彼女に成功させばいえさせないと、
レムは、交渉権にき方にした。
そのスバルは十分にしてスバルは、ひかっている。
スバルは、この世界を感じると、
(以下略)
当初の惨状を思えば、随分と文を出力できるようになったとは思う。意味は通らないが。
12月13日
■ 複数の小説に対して回してみる
昨日3作品に対して学習を回した時に、変数average_perplexity(expのn乗におけるn)の値がNaNになる問題に直面した。
今日になって活性化関数をReLUからtanhに戻したら学習が進んだ(RNNの活性化関数は本来tanh)ので、3作品からなるデータセットを用意して回してみる。
各作品について、学習に都合がいいように正規化を施してある。
また、学習がなかなか進まないことを想定して初期の学習率を1.0として開始した。
■ 経過
tanhにして学習は動いたが、結局過学習に陥っていることが分かった。
ReLUに戻し、MAX_GRADIENT_NORM = 1.0として学習させることで、とりあえずperplexityの値が発散することは避けられた。
なお、MAX_GRADIENT_NORMの値は、tf.clip_by_global_normのclip_normの値として与えられている(gradientの上限を決め、正規化する際に使われる)。
■ 経過2
ReLUでも過学習が起こったので、正規化する範囲、勾配の上限値、ドロップアウトのレート、活性化関数まで含めた調整で解決を図る。
そもそも小説の出力は、3層256ノードで表現しきれるものでは無いと思うので、あくまでもこのマシン上で学習をうまく進ませるための勉強である。
小説を対象としたSeq2Seqでの知見を活かして、より高精度なチャットボットにできないか、もう一度試行錯誤したいところ。
ひとまず学習の進み具合を見守りたい。
12月14日
■ 今日のSeq2Seq
- ドロップアウト率:0.5
- 初期学習率:0.5
- 活性化関数:tanh
で30,000stepまで粘ってみたが、結果は芳しくなかった。
毎回半分のノードを無視するという極端な設定で試してみたが、さすがに無理があったようだ。
次はドロップアウト率0.3(キープ率0.7)で試してみることにする。
延々と続く待ち時間には統計分析の勉強をする。
12月15日
■ Seq2Seq
色々と試してみたがこれ以上は厳しい気がしたので、チャットボットのほうに戻ろうと思う。
データの正規化やパラメータの調整で以前の物より良い会話ができることを目指す。
■ 試してみる
しっかり正規化したつもりだったが、「・」と「ω」に学習が引きずられてしまった。
顔文字を顔文字として認識できているわけではないので、何度も同じ並びで出る単語列と勘違いしてしまったか。
なかなかうまく学習させることができず、非常にもどかしい。
12月18日
■ チャットボットの追試
統計学の復習をしている間に学習の続きを進めて、結果を見ようと思う。
step数33,000のモデルに対して会話してみたが、何故か高確率で「ありがとうございました」と言われる。
そんなにTwitterのリプライはお礼が多いのだろうか。
少なくとも、短文を削除、元データの文字化け対策などは十分機能しているように感じる。文末に顔文字を入れるなど、Twitterらしいやり取りも見受けられる。
チャットボットの実験はひとまずここまでとする。
■ R言語について学ぶ
統計処理に強い言語、Rについて勉強していく。
R言語を使った統計処理の基礎について書かれた本は一通り読んだが、初心者向けに解説しているブログなどで追加の情報を得る。
■ おまけ:Step数50,000のモデルと会話した
私:おはようございます
B:おはようございます(*´ω・食べる・おやすみなさい
私:まだ寝ないでw
B:そんなことは、勘弁しね。。
私:気分はどう?
B:おめ
私:明日は何する予定?
B:今日は、、、、、、、、、
私:出身はどこ?
B:そうなんんんんんんんんんんんん
私:一発ギャグおねがい
B:ありがとうございました!よろしくお願いします。
私:あんまりおもしろくない
B:リッキーはそれだと思っては、、
私:もっと面白いやつをおねがい
B:そちのホンモノのかなんー」
私:意味わからんw
B:ぎぃぃやぁぁぁぁぁぁあああああああああああああああω・・・(笑)
意味が通らないことも多いが、バリエーション豊かな返答は得られている(=同じ言葉を繰り返さない)。
ハイパーパラメータはうまく設定できていたと考えていいだろう。
12月19日
■ 統計の勉強
統計学についての勉強を続ける。
Rに手を出してデータセットを使って分析するのは、もう少し後になりそうだ。
並行して、自然言語処理についても復習しておく。
12月20日
■ Rの練習
実際のデータを教材として、Rを使った分析方法について学ぶ。
とりあえず地震が起きた緯度経度について散布図を描くと、きれいに断層の地図が浮かび上がった。
他にも色々試しつつ勉強していく。
データ分析には背景知識が不可欠なので、関係する知識についても軽く触れながら進める。
12月21日
■ Rの勉強
kaggleのデータセットを眺めていて、知らない分野について集計したり図示したところで結論がイメージできないのでは、と思った。
映画のキャストや監督に関するデータがあって、この人はたくさん賞にノミネートされているのになかなか受賞していないな、という情報が得られたとする。
その人がどういう役を演っているか、あるいはどういう作品を作っているか。その上で結果は意外なのかそうでもないのか、そもそも判断がつかないわけだ。
これで、データを集計したので後はよろしく、というのでは勿体無い。
■ ひとまずどう進めていくか
とりあえずRの基本的な関数やパッケージの使い方を習得して、数字の意味を理解できるようにする。
前提知識がどうとかについては、しばらく脇に置いておく。
12月22日
■ Rの勉強続き
本を参考にしながら進めているが、基本的にデータ整形をする部分が面倒な感じがする。
各種分析に使えるライブラリのおかげで、そのライブラリの存在と使い方さえ分かっていれば、一番時間が掛かるのがデータ整形の部分になる。
ということで、データ操作に関する部分を重点的に見ていきたいと思う。
■ Tensorflowのメモリ周りについて
Tensorflowは基本的に使える物(GPU、メモリなど)は限界まで使うのだが、そのせいで実際のメモリ消費量が見えにくい。
そこでallow_growthオプションというものがあることが分かったので、Seq2Seqの学習でのメモリ使用量について調べてみた。
- 専用GPUメモリ:1.1GB
- 共有GPUメモリ:0.6GB
こうしてみると思ったより少ないという印象。
むしろPC側のメモリ量が大いに不足していたことがよく分かる(PyCharmが最大6GB程確保する)。
今後はallow_growthオプションを基本的にTrueとして、随時使用量を見ながらやっていくことにする。
■ 裏で回し続けていたSeq2Seq
Step数が100,000を超え、ほぼ収束したモデルに文章を出力してもらった。
(「転生したらスライムだった件」 129話 より)
入力:ヒナタの言葉を聞きやる気全開になったフューズ
出力:そんな遣り取りを統合が行ったのだが良いのだ
そんな遣り取りを自覚していたのであるのだとは
それを余りにも眺めて受け止めようと思ったのだ
だがそれをしただろうというならないだろうと思う
そんな遣り取りをしてしてめェのだろうか
そんな遣り取りを真面目だと溜息を通り越した事に気付いたのか
というかリムル様のは勝てないだろうと思った
そうやって紳士的には思いを進める事だったのだが
その事を見て遥かには思わずにはならないのだが
だがそれを見ていたのだろうと思う
(以下略)
「めェ」という語尾は、同時に学習させた「Re:ゼロから始める異世界生活」に頻出する。残念ながらうまく使えていないようだが。
しかし間にいくつか文を挟んだ後、「転生したらスライムだった件」に出てくる「リムル」という名が出てきている。
つまり、ある登場人物の名に関連して、同作の違う登場人物の名が出てくるように学習できているということ。
意味は相変わらずよく分からないが、文法も破綻せず関連する人名が出てくるという結果が得られたわけだ。
Seq2Seq+Attentionモデル(+ReLu)の可能性を感じられるし、延々と回した甲斐があったというものだ。
■ せっかくなのでもう一文
「リゼロ」に含まれる文についても試してみる。
(「Re:ゼロから始める異世界生活」第三章25 より)
入力:だがしかしその縋るようなスバルの思いはエミリアには理解されない
出力:それはそれを歪に手にして断ずるようにはわからない
それはラインハルト・ヴァン・アストレアのなんなんだと理解したのように決まって
スバルの言葉にガーフィールは陰のようにしなとやったのだ
それを受けたのだろうとしたのだろうとしてもわからない
それもまたスバルはいけなかったことを通り越してめ
それを受けスバルのはならないのだ
そんなスバルのことにしてもわからないのだろうとして
それはそれを通り越したのことをしてスバルはいたんだ
それをスバルの裏に手を見られてはしないだろうと問いを見られない
(以下略)
こちらも出てくる人物は正しい。
私はほとんど読んでいないのでどちらの作品も分からないが、読了済みの方ならどのあたりを学習して出力しているのか分かるかもしれない。
12月25日
■ 統計学の勉強
ビジネス寄りの実例中心でやってきたので、より基本的な概念回りについて学ぶ。
頻度論者とベイズ論者の対立という話まで出てきたが、いいところは認め合う関係であって欲しいものである。
12月26日
■ 統計学
計算は基本的にライブラリに投げることになると思われるので、細かいところはうろ覚えでも気にせず進めているが、概念や考え方の部分は少しずつ馴染んできたように感じる。
12月27日
■ 統計学
今日は主にWeb上の情報で勉強する。
- 全人類がわかる統計学 [リンク]
各公式の証明も載っているが、今はあまり必要ないのでざっと目を通す程度にする。
12月28日
■ 視点を変えて解説書を読み返す
前提知識が増えてきたところで、本を読み返してみる。
余裕ができた分だけ細かい所に気をつけて読んでいけるので、新たな発見に期待する。
同時に極端に多層化したNNによるSeq2Seqを回して実験する。
3層から10層に変えたことで、GPUのメモリはフル(3.3GB)に、Pythonが20GB(仮想メモリ含む)使用するようになり、このPCの限界ギリギリの学習となる。しばらく結果が出ないことは承知の上で、様子を見る。
■ 仮想メモリについて
物理8GB+仮想32GBという状態でも問題なく動作することに驚く。
そもそも、物理メモリで足りない分を仮想メモリで補うくらいの知識しかないので、少し調べてみることにした。
種々の用語について確認できた。
その役割などを考えると、一見物理メモリが足りていそうでも、ページファイルを無効化するのは良くないように感じた。
スーパーマーケットに例えたら、売り場が広い代わりに倉庫が無いようなものだろうか。