にほんごのれんしゅう

日本語として伝えるための訓練を兼ねたテクログ

StackGANによるフォントの錬金術

StackGANによるフォントの錬金術

f:id:catindog:20170205152727p:plain

図1. 中央が錬金したフォント

近況

f:id:catindog:20170205152954j:plain

図2. 真理の一撃を放とうとするカリオストロさん(公式絵より)
 グランブルーファンタジーというスマホのゲームでカリオストロというキャラクターがいます。もとは天才錬金術師で、自己の性別を錬金術で男から女に変えた天才です。そんな彼(彼女?)が真理の一撃だー!っていうんですよ、かっこよいですね。
 あまりにも今までの不可能を打開し続けるDeep Learning。自分で言うと甚だ科学としての機械学習が零落しそうですが、まだDeep Learningは体系化された知恵の集合体としての正しい科学の段階にはたどり着いていないように思います。どちらかと言うと錬金術に近い技かも。
 Deep Learningは、いつかまだ見ぬ真理へと人類を導いてくれるんでしょうか。各人、期待しております。

モチベーション

  • 日本語のフォントを作成する際に、デザイナは膨大な時間的・肉体的・精神的な労力を払うことになる[1]
  • フォントのデザインを見ているとある一定の法則があることがわかる。それは、大まかなフォントのデザインの土台があってデザインを装飾するように、なんらかの固有な表現が付加されている
  • これはディープラーニングで情報を付加する特徴を覚えさせ、変換させるのに適した好例である
  • 単純な情報付加では、pix2pixでも可能であろうが、StackGANと呼ばれるGANを複数回重ねることでより高度に近づけたい画像に近づける手法を適応する[2]

先行研究

StackGANについて

 StackGANは少ない情報からよりもとの絵に近い情報を復号するのに適しているネットワークである。
 もとの論文ではSkip Thought Vectorsを用いて文章からの画像の生成であるが、Skip Thought Vectorsの代わりに、画像のベクトルを入力する。条件を同じようにするため、DCGANで用いられるノイズも付与する。
 ネットワーク構成図を書き直した。
f:id:catindog:20170205153835p:plain

図3. 今回用いたネットワーク

実験手法

  • 論文を読んでChainerで実装した
  • 何度か実験したところ、二段目のGANにて勾配消失を起こしてしまうのか、一段目のGANの出力結果に強く引っ張られてしまったので、学習レートを大幅に引き下げるという処理を入れた。本当は一定のiterationが回るまで、学習を遅延させたいのだが、今のところ実装に至っていない。
  • フォントを2種類要した。
  • 書道のようなフォントである青柳隷書フォント、windowsで標準でインストールされているHGP創英角ポップ体の2つを検証対象とした
  • フォントの選択条件は、夏目漱石の「坊っちゃん」、「こゝろ」、「吾輩は猫である」で使用されている3313語を用いた。そのうち、800語を別途検証用データとして学習用データとは区別した。[3]
  • 各種パラメータは、一回目のGANはFacadeと同様で、二階目のGANはそれを1/5にしたものである。詳細なパラメータサーチは別途、本格的な生成タスクで行うことにした。

f:id:catindog:20170205154127p:plain

図4. 青柳隷書フォント、人手で書いたデータをスキャンしたらしい


f:id:catindog:20170205154228p:plain

図5. Windowsに入っているあのダサいフォント

結果

  • Inputが入力ベクトル作成に用いた画像
  • Predictが出力結果
  • Ground Truthが人間の職人が作成したフォントである

f:id:catindog:20170205154409p:plain

図6. 青柳隷書フォント学習による出力結果


f:id:catindog:20170205154501p:plain

図7. HGP創英角ポップフォント学習による出力結果

考察

  • Ground Truthに情報量的に近い習字の字ではないけれど、習字っぽい字が表現可能なのはGAN故にだろう。入出力の誤差の最小化が目的でないので、人間が書いた文字は潜在的に大きなノイズや誤差を含む。その点を吸収してくれているように思う。
  • もともとは同人フォント作家の作成コストを下げられるような仕組みがあればと思って、コーディングを開始したものである。今現在、開発が止まってしまっている東亜重工フォントの足りてないフォントの穴埋めや、人間がフォントを作成する際の下書きに用いられたら良いと思う。[3]

Future Work

  • StackGANのパラメータを調整して、下書きから漫画を一気に作成するなどしたい(データない)
  • 音声の問題にも適応できる気がしてて、周波数成分をルールにしたがって上げたり下げたりする作業を、GANにやらせればより人間っぽくなるっしょって思惑があって、男性でも女性のキャラクタを演じたり、その逆ができるように感じる。
  • パラメータサーチや、ネットワーク構造の問題だけでなく、今回は周りの学習の安定度に応じて学習を開始してほしいというニーズが発生したので、その辺を実装していきたい
  • 一応ConditionalStackGANに簡単にする方法があって、その方法を図示すると、こんなふうになる(と思う)

f:id:catindog:20170205155408p:plain

図8. Conditional StackGAN

参考文献

[1] 文字数14000字! 手書き毛筆フォントができるまで http://portal.nifty.com/kiji/151118195086_1.htm
[2] StackGAN: Text to Photo-realistic Image Synthesis
with Stacked Generative Adversarial Networks https://arxiv.org/pdf/1612.03242v1.pdf
[3] 「シドニアの騎士」に出てくるフォントを再現する「東亜重工電子書体化計画」が公開中止に http://gigazine.net/news/20140702-toa-heavy-industries-font/

謝辞

 インフルエンザか風邪だかわからないが熱が下がらない。隣の席の上司がインフルで休んでいるので、多分インフルなんだろう。つらい。
 そんな中、今週は業務では主にAWSとAnsibleとの戦いに時間を割いていたのだが、やはり機械学習やってる方が気が楽...(エンジニアに向いてない疑惑)
進捗なしかとおもいきや、やっぱり音楽とMMDのちからでなんとか乗り切った。MMDでは艦これで山風のモデルが多数のアーティストによって頻繁なアップグレードが行われている。非常にクオリティが高く、尊い
作品中でも、山風は江風と海風と一緒にいじられることが多いのだが、この三人を組み合わせるとヤバい。それぞれの方向性が異なる性格のベクトルが見事に調和していい感じにまとまっている。興味のある人はYouTubeで「山風 MMD」で検索しよう。
MMD職人に感謝である、GPL v3ライセンスとかにしたほうがいいのではと思う。
f:id:catindog:20170205155704p:plain

この三人組すごい好き

RNNのアンサンブルによる音楽の新規創出

近況

Qiitaに投稿しない理由なのですが、自分はQiitaを技術ナレッジのレポジトリのような使い方を想定してしていて、実際、多くの方が素晴らしい技術的なプラクティスを提供なさっています。
 古い言葉でチラシの裏という表現がありますが、今回の私のは、ブログが良い選択肢であるの思うのです。十全な責任を持てない発信やSNSでの補足が必要になるレベルになるものに関してはブログを利用しています。

モチベーション

 RNNという技術がなんともオワコンと言われているので、手向けに興味があった音楽の生成を行うことにしました。

f:id:catindog:20170129211338p:plain

図1. いーあるふぁんくらぶと千本桜を合成したらどうなるの?

 機械学習が流行りだしてから、まるで機械学習といえば絵を描いたり、音楽を奏でたりということができるという認識がニュースで流行りだしたりしていて、実際にやってみた系の記事が、音楽であったでしょうか。Qiitaではありますが、あれは音楽をRNNに記録させて取り出したというもののような気がします。[0]

 RNNといえども、基本はニューラルネットワークに情報の符号をモデルに刻み込んでいくスタイルなので、どうしてもある程度特徴量の抽出はするものの、そのまま覚え、覚えた内容をそのまま出力するという流れになりがちです。[1][2]

 自然語処理の分野でも、他の方が自分の著書を書いて、その内容を記録させるということをしていますが、その著書の範囲のコンテンツしか創造能力が獲得できません。[11]
 
 特段新しい手法ではない(と思うの)ですが、複数のモデルの結果を合成(この文脈ではアンサンブルと呼ぶ)することで創造能力の獲得を目指します。
 
 CNNなどの識別タスクやGANなどの生成タスクでの応用などが考えられます。

前提

この世に完全なるオリジナルは存在しない

 なんとも哲学的な題材なので、正直これについては述べたくなかったけど、これを最初に言っておかないと後が続かない気がするので言いますと、多くの芸術家が言っていることとして、オリジナルは存在しなく、創作物は何らかの参照と引用で構築されているという意見です。[3][4]
 これは今の私には否定出来ないことなので、正しいと思うのです。

ピカソとポーラ・シェールの本質であるコンビナトリアル・クリエイティビティなど、ネットワーク化された知識です。私たちが真に創造し世界に貢献するためには、無数の点を結びつけ、豊かな分野のアイデアを相互に結びつけ、これらの要素を結合して再結合させ、新しい城を建設することができなければなりません。[4]

提案

複数音楽を学習したモデルを合成することで新規性を獲得する

 人間がいくつかの経験をし、新たに直面する問題に対処するときは、おそらくそれまでの経験の幾つか思い出して手法を組み合わせて対処するかもしれません。それを真似しようという発想です。
 RNNとは、過去の出力状態に依存した確率場を表現する出力をするものというものです。mutableなニューラルネットワークです。
 もう何度も図示しましたが、中二チックに単語を選んだ図を再掲します。
f:id:catindog:20170129211137p:plain

図2. 音楽のRNNの系列

引用になりますが、Conditional Random Fieldとも見れます。
f:id:catindog:20170129211612p:plain

図3. Conditional Random Field(CRF)

 ベイズ系の記事を読んだ時、ヒートマップで表現している方法が分かりやすかったです。
f:id:catindog:20170129211919p:plain

図4. 確率場のヒートマップの遷移

 数式です。
f:id:catindog:20170129212659p:plain
アンサンブルは機械学習では特段珍しい手法ではないのですが、創造系のタスクでアンサンブルは珍しいと思います。
 

 提案したいことは単純で、それぞれの時間系列 t+1に対して次の音が来る確率の中庸点(特定のモデルにバイアスをかけることもある)を求めます。
 
 結果が確定したら、RNNの状態をアップデート(ステップを進める)して次に来る確率をまた予想します。

f:id:catindog:20170129212255p:plain

図5. 出力確率の合成による創造

f:id:catindog:20170129212424p:plain

図6. ヒートマップの合成(イメージ図)

f:id:catindog:20170129212854p:plain

 図では、2つのモデルの合成のみが示されていますが、実際には多くの音楽を学び、たくさんのモデルがあればその組み合わせはかなりの数になります。これは到底人間が一生かかって創造活動しても網羅できないレベルです。

実験環境

音の符号化

 一番苦労した点はこの符号化の点であると感じています。音を記号で示すにはどうしたら良いでしょうか。WaveNet[5]や他の研究では音をそのまま波形として扱うこともあるのですが、精度は高いものの非常に生成するのに時間がかかるということで、よりかんたんなMML(Music Macro Language)を使用しました。
 MMLはかなりの方言があり、一般的と呼ばれる記述を調べるのに非常に苦労しました。a~gのcharactorが音階になっていて、それを装飾するl, p, gなどの符号と量を示す数値で構成されているようだとわかりました。符号の粒度が分かれば、RNNで学習することができます。

いーあるふぁんくらぶの例
liarufanclub$ cat input.txt.org
v100q25o5l1a a a a a a a l2a q100l8d c l4d l8.d d l16d d l8c d l2.d l8d c l4d l8d l16d l8d l8.d l8d f f f g f q66l4.d q100l16d c q50l4d q100l8.d d l16d d l8c d l2.d l16a a a a a a a a l8g g g g f l2^4.d l8d c l4d l8d l16d l8.d l8d c d l2.d l8d c l4d l8d l16d l8.d l8d d l16f f l8f f g f l4.d l16d c q50l4d q100l8.d l16d l8d ...

 また、MIDIMMLは一部互換性があるらしく、運がよいとMIDIMMLに変化することができます。変換に使用したソフトは、テキスト音楽「サクラ」になります。[6]

 これを自作のスクリプトでかなりアドホックですが、一つの素性の単位に分解します。コードは別途転載するので、必要な方は参照してください。[7]

RNNの学習

 ざっくりとですがパラメータサーチを行った結果

  epoch:200
  batch:50
  rnn_unit: 386
  layer: 3
  学習率: 2e-3

ぐらいが曲を丸ごと覚えられる感じだったので、採用しました。
loss errorは10^-3以下になります。

これを一曲一つのモデルで学習させていきます。
学習させた曲は、以下の通りです。
いーあるふぁんくらぶ(最初の冗長なイントロまで再現されています)

バッドアップル  

ロストワンの号哭

千本桜

RNNのアンサンブルのコード

自然言語処理でどうしようもなく、精度が出ないときがあったのでアンサンブルの発想に至ったのですが、まぁ、普通に考えたらno free lunchの定理より、多くのモデルを混ぜると精度は改悪するので、idea賞というレベルのものを今回再利用しました。結構強引な改修を行ったのでコードが汚いです。[8]

結果

いーあるふぁんくらぶ、バッドアップル、ロストワンの号哭、千本桜を合成するのに、それぞれのウェイト(重要度のようなもの)を指定して、任意の割合で合成できるようにしました。
 
いーあるふぁんくらぶ50% + 千本桜50% ○ 新規性ありそう

いーあるふぁんくらぶ50% + Bad Apple50% △ 後半、いーあるふぁんくらぶ強くなってく

Bad Apple50% + 千本桜50% △ Bad Appleから入っていく感じ、似てるけど別物

ロストワンの号哭50% + いーあるふぁんくらぶ50% ○ そういう曲だと言われれば?

いーあるふぁんくらぶ90% + Bad Apple 90% + ロストワンの号哭 100% + 千本桜 100% ○なんか新しい曲調

色々良さそうな音楽を探索したいのもやまやまなんですが、疲れてきたのでこの辺にしときます。
コードを公開するので、自由にしてください。

結論

 任意の組み合わせで、再生に耐えられる音楽を作り出すことはできました。しかし、これが歌詞や音楽を知っているから、違和感なく感じるのか、音楽のプロが見たらどう判断するのか正直なところわかっていないです。
 自分に音楽の才能が著しくないことを理解しているので、どんどんやっていこうというモチベーションは出ないですが、人並みには興味があったのでやってみたというところが事実です。

 途中に介入したり、Conditionalに指定の曲調を作り出すことも、まぁ、可能なのですがデータがないのと手がまわらないのでどうしようもない感じです。

 音楽は画像生成タスクに比べれば楽という印象ですが、前処理、学習、評価、Webのアップロードだけでプライベートな時間の殆どを消費してしまいました。悲しい。
 

謝辞

 これは前からあったアイディアで、プログラムを作るの結構めんどくさかったので、半ば放置していたのでした。そんな折、My name is HAPPY HARDCORE.という音楽に出会いまして、最後までプログラムを書き上げるために強制的にテンションを上げていただき、ありがとうございます。この音楽がなかったら、この発想は私の中で永久に検証する機会がなかったと思います。

f:id:catindog:20170129214029p:plain

GANによるノイズ・モザイク等の除去

GANによるノイズ・モザイク等の除去

近況

 眠い。
 実は今月、三回も停電が起きてそのたびに機械学習のモデルが飛んでいます。原因は電子レンジとケトルを両方利用したとか、そういった当たり前のことなのですが...(ブレーカを飛ばしているの私でないです)。

モチベーション

 pix2pixなどのニューラルネットでの画像変換は、通常のフィルタと違って、情報量を増加させることができるような振る舞いをすることがある。
 画像は大学の学部で習ったレベルの知識しかないが、平滑化フィルタなどの画像を変換する系のやつは大抵が行列で表現されるようなやつで、平均値だの分散などを取るので、情報量が下がるものがほとんどだった(というかそれしか知らない)。
 GANでモザイク除去や、なんやらができるとは先行研究でわかっていたし、理論は単純だし、この前のpix2pix with textに比べて簡単だと思った。

先行研究

理論

  • GANなので、生成DNNと判別DNNがお互いを騙そうと、競争し合う。
  • 十分に学習した生成DNNが生成タスクとして利用可能
  • 一番良い理解はソースコードを見ることだと思う

f:id:catindog:20170124190828p:plain

図1. 生成タスクの例
f:id:catindog:20170124191025p:plain
図2. 判別タスクの例

実験環境

  • この前のpix2pix with textを更に変更したモデルを利用
  • textの領域にランダムなデータを入れることで、もとのDCGANのような、ランダムに近いZシードの位置づけを作成した(直感的な理解であるが、いらなくてもなんとかなるのでは)
  • GTX 1060, GTX 1070で4日ほど回した
  • 途中、chainerのバグを踏む、serializerがメモリバカ食いという点はあったものの、色々細工することで乗り切った. (バグは今は直っている。大容量なswapをNVMeに作成するなど)
  • 学習データとは別のデータセットを用意して、各モデルの学習の進み具合を確認してepochを進めていった. leakは防げていると考えている。
  • epoch: 350
  • 画像ドメイン: 艦これの7500枚の一人だけ表示されている絵、ただし縦横比が2:1, 1:2までのカラー画像のみ
  • その他パラメータは原則、Facadeのものに従っている
モザイク生成
  • opencvを利用
  • 一度1/10まで縮小して単純に10倍に拡大することで、モザイクを発生させる[1]
  • モザイク状態のデータと、正解データを対応させて学習する
ランダム情報欠落
  • opencvを利用
  • 全体の画像の面積の半分を白いブロック領域でランダムにデータを欠落させる[1]
  • 情報が欠落した状態のデータと、正解データを対応させて学習する
評価
  • 評価には、別途用意した500枚の画像を利用する

結果

  • 概ね良好な結果が得られた。
    • inputとはgeneratorの入力値である
    • predictとはgeneratorの出力値である
    • ground truthとは未加工のもとデータである

f:id:catindog:20170124191437p:plain

図3. ブロックノイズ除去の例

f:id:catindog:20170124191513p:plain

図4. モザイク除去の例

考察

  • ランダム情報欠落は、復元しやすいのかかなり強力に動作しているように見える
  • GANの特徴として、判別機を騙せるようにGeneratorは学習していくので、ニューラルネットという人間に近い判別の仕方、判別能を持っているので、人間をうまい感じに騙せような補完をしてくれる(別にground truthに近くなるわけでない)
  • 停電でpix2pix with textのデータが飛んでしまったので、しかたなくやった感があったが、思ったより簡単に結果が出たので、学部の論文とかにはいいかもしれない.ただし、通用するのは今年までな気がする
  • 比較こそしていないが、少しの汚れや情報欠落ぐらいでは、うまくドメインが合致していれば、もとの絵とイメージは違うけど、十分見れるものを出力できている.色々応用は広そうである

Future Work

  • StackGANを参考にUltra High-resolution GANを組んでみたいが、4Kの画像のデータセットとかあるのかな。実装の案はあるのだけど
  • 画像だけでなく、ベクトル表示できるものならなんでも行ける、多分
  • 自然言語の応用を考えてみる

ベイズ最適化と、しりとり

モチベーション

機械学習ばかりやらずに、久々にプログラミングをしたくなったというか、下手の横好きというか、プログラムを書いてみたくなりました。自分で思った通りにロジックを組めるのは楽しいものです。

 YouTubeを見ることを趣味の一つにしているのですが、たまに見かけるトリビアの泉の番組が結構面白い。知識欲とは人間が本来持つ本能的な欲求なんですかね。

 トリビアの泉で、広辞苑の辞書の単語をつなげていったら、どれくらいつながるかという問題設定で、東大協力のもと、15万語ぐらいを可能な限りつなげていったら、75775語繋がったという話。[1]
f:id:catindog:20170119210429p:plain

図1. 動画は、違法アップロードの可能性があり消されるかも知れない

 動画中では何の疑問点もなく、最長のしりとりネットワークを作成したといっていたが、数万を超える単語の問題をソルバー等で解くのは容易ではないのではないかという疑問が結構強く残った。

 自分でも再現してみたくなったけど、広辞苑の日本語をワープロソフトで手入力していくのはホント闇というかやりたくないなぁと思ってコメント書いたら突っ込まれた。これもネットの宿命。

単語を集める

 有償でも、広辞苑の辞書から単語が引っ張れるのなら電子版を買おうかと思ったが、パースできるかどうか保証がないし、一般的な語にしか対応しておらず、最新の単語データとくらべてしまうとどうも見劣りする。
 NEologdという形態素解析エンジンがある。頻繁にアップデートされており、この前Fate/Grand Orderという単語も追加された。

@HOPPOU:~/mecab-ipadic-neologd$ echo "Fate/Grand Order" | mecab
Fate/Grand Order        名詞,固有名詞,一般,*,*,*,Fate/Grand Order
フェイトグランドオーダー,フェイトグランドオーダー 

 NEologdのgithubでcloneしてインストールするために様々なファイルをダウンロードすると、ディレクトリの中に、名詞が含まれるcsvが含まれている。

$ ls | egrep "(n|N)oun" 
Noun.adjv.csv
Noun.adverbal.csv
Noun.csv 
Noun.demonst.csv 
Noun.nai.csv
Noun.name.csv
Noun.number.csv  
Noun.org.csv
Noun.others.csv
Noun.place.csv
Noun.proper.csv
Noun.verbal.csv
neologd-common-noun-ortho-variant-dict-seed.20161017.csv  
neologd-noun-sahen-conn-ortho-variant-dict-seed.20160323.csv 
neologd-proper-noun-ortho-variant-dict-seed.20161110.csv  

$ ls | egrep "(n|N)oun" | xargs wc -l 
 546969 合計

語尾と語頭を普通につなげていってもうまくいかない

最初は広辞苑より収録数が多いし、適当につなげていってもうまくいくだろうという思惑があったが、うまくいかない。問題点として、語尾で終わる単語の分布と、語頭が特定の単語で始まる分布の違いが明らかになった。

68326個 都ジマ ミヤコジマ
68327個 まわりはな マワリハナ
68328個 鍋もの ナベモノ
68329個 野面 ノツラ
最後の文字は、 野面 ノツラ <- ラで始まる単語を発見できなかった☆

f:id:catindog:20170119211327p:plain

図2. 語頭の分布
f:id:catindog:20170119211410p:plain
図3. 語尾の分布

提案

 うまくいかない原因として特定の語尾で終わる単語を頻出させすぎると、語頭でその語で始まる語が消費され尽くしてしまい、上手くいかないのではという仮定がある。
 そこで、確率的に採択するように、語尾をキーにして採択確率を変えるという手法を提案する。
 さて、単語の採択率を調整するはいいが、どのように決めようかとなる。何らかの最適化アルゴリズムを使うのが妥当だと思われるが、以前なら探査空間を限定したlbfgs[3]を使うことが多かったのだが、iteration何回か指定できない、数値に対して厳密に動作するので確率的に決定する系では難しいなどの理由で、少々使いづらいと考えていた。
 最近良く聞く、ベイズ最適化を適応できる問題(機械学習を考えたくなかったけど、近いアルゴリズムを採用せざる得なかっためう)ということに気づいて実装を行った。

ベイズ最適化とは

 詳しく説明すると、より詳しい人に刺されるので、表面的な知識だけ。
f:id:catindog:20170119211620g:plain

図4. アクションごとのベイズ最適化

 手法にもよるかも知れないが、基本的には背景の分布を説明するのに最も適したガウス過程の事後分布を作っていくものである。観測する回数が大きくなれば、その分、真の事後分布に近づいて行くものと思われる。
 
 あまり賢くない最適化手法では、グリッドサーチで探査空間を量で押し切ったり、極小解に陥ってしまいそうであるが、gifアニメを見てみると、赤の分布が3つほどあるが一番大きな赤を集中して探索しているため、賢いという印象。

実装

 実装の詳細はgithubに転載するので、確認する必要があれば参考にしてほしい[4]
 基本的には、最初に単語のプールを作って、ランダムにそのプールから取り出していくのであるが、この取り出しのランダム性に細工をして、特定の語尾の単語を引き当てにくくするというアプローチである。
 泥臭い実装になってしまったが、まあ私はこんなものです。
 nが単語のデータオブジェクトで、n.tailが語尾です。randomで採択関数をスキップしています。

            if 'ラ' == n.tail and random.random() < ps[7]: continue
            if 'ウ' == n.tail and random.random() < ps[6]: continue
            if 'ゲ' == n.tail and random.random() < ps[5]: continue
            if 'ズ' == n.tail and random.random() < ps[4]: continue
            if 'マ' == n.tail and random.random() < ps[3]: continue
            if 'リ' == n.tail and random.random() < ps[2]: continue
            if 'ケ' == n.tail and random.random() < ps[1]: continue
            if 'エ' == n.tail and random.random() < ps[0]: continue

psがベイズ最適化で決定されるパラメータ郡で、最適な不採択率を決定する。

また、今回のベイズ最適化では、Gaussian Processを利用した。
f:id:catindog:20170119212031p:plain

図5. 特定の末尾の文字を持つ単語の採択率をベイズ最適化が決めた定数で下げる

# 目的の分布がこの関数で発生させる。
# 目的関数って言っちゃうとだめというのは知ってる。
# os.systemしてるの、ゴミと言うツッコミは勘弁して
def target(x1, x2, x3, x4, x5, x6, x7, x8):
    xs = map(str, [x1, x2, x3, x4, x5, x6, x7, x8])
    command = ["pypy3", "siritori.py"]
    command.extend(xs)
    os.system(' '.join(command) + " | tee buff " )
    # 結果を取得
    fret = float( open('buff').read().split('\n')[-3].split(' ')[0] )
    return fret

# boオブジェクトと探索範囲の決定
bo = BayesianOptimization(target,
        {'x1': (0, 1), 'x2': (0, 1), 'x3': (0, 1), 'x4':(0, 1), 'x5':(0, 1), 'x6':(0,1), 'x7':(0,1), 'x8':(0,1)})
bo.explore({'x1': [0, 1], 'x2': [0, 1], 'x3':[0, 1], 'x4':[0, 1], 'x5':[0, 1], 'x6':[0,1], 'x7':[0,1], 'x8':(0,1) })

# maximizeの実行, iter 30
bo.maximize(init_points=5, n_iter=30, kappa=2)

# 最大化するときのx1~x8のパラメータの表示
print(bo.res['max'])

結果

139,813語 + 1(ンで終わる単語)で、しりとりチェーンを構築することができたので、まぁ、こんなものなのかなという感じ。詰めればもっと行きそうだけど、しりとりチェーンコンテストとかあっても良いかもしれない。もっとiteration回せば、もっと行くようにも思える。

考察

 1. ベイズ最適化はパラメータの探索に非常に効果があると思われる。従来の探査手法よりも、探査が少なく、なおかつ、確率的な系(予測する分布)に対しても有効そうである。(lbfgsbはすぐおかしくなる)
 2. 機械学習では結構重い学習も度々行う必要があり、コンペティションなどになると、探査を効率よくできたものが時間的にも精度的にも有利なので積極的に採用していきたい技術である。
 3. よくわかんないけど、アドホックな手法を使わずに演繹的にしりとりをこれだけの量解けなくない?Youtubeにサブグループ化してソルバーで解くとの案があったけど、どうなのかな。

結論

 早速手持ちの案件に導入してみました。
 パラメータサーチテクとして、優秀です。積極的に使っていきましょう。