GANsやOpenCVをいじっている

ここのところ、画像処理関連をやってみています。 以前pix2pixをいじっていましたが、そこでも使われているGANs(Generative Adverarial Networks)という技術を、なにかしら自分の趣味の範囲で利用できないかなあと試してみています。 初期に提案されたDCGANは非常に衝撃的だったのですが、いかんせんハイパーパラメータのチューニングがシビアでした。学習がうまくいかないとmode collapseという現象を起こし、まったく意味不明な画像しか生成できなくなります。 この辺りの数理的理解が進んできて、mode collapseを起こしにくい新しい手法が提案されています。 chainer-gan-libという、Chainer開発元であるPreferred Networkが複数種類のGANsを実装、公開しています。主にこちらを使って画像生成を試してみています。 https://github.com/pfnet-research/chainer-gan-lib フレンズ画像を生成させてみたい-画像収集編+DCGAN フレンズ画像を生成させてみたい-画像収集編(2) wiki, twitter ただ、やはり少ない画像数でこれを行うことは難しいなあというのが実際やってみての感触です。 GANsでは生成器と識別器、2つのネットワークを交互に学習します。生成器はある分布に従う潜在変数の存在を仮定し、そこからサンプリングした乱数から画像を生成します。識別器は、生成器が生成した画像群を負例、訓練用に用意した画像を正例としてそれらを正しく分類するようなネットワークです。 生成器と識別器を交互に学習させることで、生成器は識別器の正例群が持つ画像の特徴を捉えた画像を生成できるようになる、というのがGANsの大まかな仕組みです。生成器と識別器はそれぞれ反対方向の目的関数に向かって最適化されるので、最終的にお互いの訓練誤差が均衡した状態が理想となります。 正例の画像があまりに少ないと、識別器の損失(誤差)がかなり小さな値にとどまってしまい、生成器は正例の画像をほぼそのまま覚えてしまうようです。つまるところ、「十分な数のデータがないと特徴を正しく捉えられない」というある種当たり前の結論に至りました。 人間だったら少ないサンプルからそれっぽいことが学習できるんですけどねえ…と思ったところでGANsの転移学習はできないのか、ということをこれを書きながら思いました。 何かしらの画像をうまく生成できるだけのモデルを予め学習させておき、それをベースにfine tuningすればもう少しマシな結果が出るのでは、という予想です。 これは一度試して見る価値はあるかもしれませんね…そのモデルを学習させるためのデータをどうやって用意するか、という課題はありますけど。

テキスト分類をDNNでやってみて思うところ

以前このような記事を書きました。 Recurrent Convolutional Neural Networks for Text Classificationを実装した  複数の単語から構成される文章を、Bag-of-Wordsと対応する単語分散ベクトルで表現し、特徴ベクトルの最大値のみを抽出する、という感じの手法です。 これの実装を書いた時はまだあんまり機械学習のことがよくわかっていなく(今もよくわかっていませんが)、それでも実験的、感覚的に「この手法は特に単語が増えると精度でないだろうな」と思っていました。 なので、その後畳み込みネットワークベースの手法を試しています。他の人が書いたChainer実装は既にあったので、自分はそれの最上層をSPP-Netに置き換えただけのものを試しています。 ichiroex/chainer-cnn: convolutional neural network for sentence classification by Chainer (オリジナル実装) https://github.com/knok/chainer-cnn (そのfork) 畳み込み(CNN)とSpatial Pyramid Pooling(SPP-net)を使ってテキスト分類 – Qiita (解説記事) 基本的に、こちらのほうが特徴量をより多く捉えているはず(層の数とか種類とかから類推)なので、きっと性能は高いと思います(未検証)。そこは同じテータセットを使ってちゃんと試したいところですが、GPUの空き時間ができたらということで… そんなわけでRecurrent CNN(RCNNはRegions with CNNと混同しやすい略称なのでこう記述します)は「自分も論文だけ見て実装することはできたので満足。だけど手法としてはいまいちっぽいよね」という気分でいました。 ふと先日この記事が目に飛び込んできました。 AIで2chに悪口書いてる人を特定してみた。 – ちょいちょいブログ ちょっと過大に扱われてしまったのではないかと思い、この記事を書いています。 分類結果の出力 自分の実装では評価時に最終出力として、全層結合層(Fully Connection layer)の値を生のまま出しています。実際にはこれにソフトマックス関数をかませて0〜1の確率値に整えるべきなのですが、そこをちょっとさぼっています。 ともかく、ソフトマックス関数で計算される分類タスクの出力は、全ラベルそれぞれの確率の合計が1になるよう調整されます。 Recurrent CNNでは分散表現の実数をそのまま加算するため、全体としては大きな値になりがちでです。その辺りの正規化が皆無なので、おそらく文章が長くなるほどあやしい挙動を示すでしょう。 分散表現獲得 また、分散表現の獲得もあまりよろしくない作りになっていると思います。乱数を初期値とし、逆誤差伝搬で各文字の分散表現を獲得しています。 十分なデータ量がないと、適切な分散表現は獲得できないと思います。代わりに、例えば一般的な表現が多数出現するデータ量の多いコーパス(Wikipediaの記事、新聞記事など)から、word2vec等で獲得した分散表現を初期値に設定してやる、といったことで性能が向上する可能性があります。 2017/8/30 追記: 今回のケースだとWikipediaよりも2chの各種書き込み、Twitterのツイートから分散表現を事前訓練したほうが良い気がしてきました。 「その他」というラベルの扱いの難しさ MNIST, ImageNet, CIFAR10等誰もが入手できるデータセットは非常に限られた分類のデータしかありません。それらを識別するモデルを用意したとして、まったく関係ないデータを与えると、識別器は無理やり何かしらの値を出力します。運が良ければ何かしらの要素が似ているものへの確率が高く出ますが、最悪まったく関係ないラベルだと推論してしまいます。 これを回避するために、たとえば雑多なデータをたくさん用意して「その他」ラベルを作るという解決方法がありますが、これも一筋縄ではいきません。… Continue reading テキスト分類をDNNでやってみて思うところ

猫の線画を着色させたい

ちょっと前に「猫の線画を書くと自動着色できる」というWeb上のデモが話題になりました。 Image-to-Image Demo – Affine Layer (web) [1611.07004] Image-to-Image Translation with Conditional Adversarial Networks (元論文) phillipi/pix2pix: Image-to-image translation with conditional adversarial nets (著者によるTorch実装) affinelayer/pix2pix-tensorflow: Tensorflow port of Image-to-Image Translation with Conditional Adversarial Nets  他複数のフレームワークによる実装あり ニュース記事 線画の猫をリアルにしてくれるWebツールが登場 夢に出てきそうな猫ちゃんが生み出される – ねとらぼ 手書きの「絵」から本物そっくりの「写真」を作るアプリがすごい―でも失敗すると… [インターネットコム] 他いろいろ 著者は、このデモに関するデータセットをいくつか公開してくれていますが、この妙に話題になった「猫画像の変換」に必要なデータセットのみ配布をしていません。 なんとか自分でも再現したいと思い、いろいろとトライしてようやく結果を出せそうなところまできました。 データ収集 まず猫画像の収集をやりました。最初はWikipediaからの取得を考えていたのですが、現在Wikipediaが用意しているダンプに画像ファイルは含まれておらず、そもそも画像に関してはWikipedia標準のライセンスであるとは限らないと公式に書かれていました。 しかたなく、Google画像検索でライセンスを「商用を含めた二次利用許可」に絞って探していたら、やたらPixabayというサイトの画像が出てくるのでよくよく調べてみると、なんとこのサイトはすべてCC0(public domain)ということなので、ここから画像を集めました。画像URLのリストをgithubで公開しています。 https://github.com/knok/pixabay-cat-images データ分類 Pixabayの検索結果には実際には猫ではない画像も割と混じっているので、ChainerCVの事前学習モデルを使ってある程度自動分類してから、手動でpix2pixに使えそうな画像を選別しました。 ChainerCVを用いて猫画像を分類する – Qiita 猫部分の抽出 集めた画像には背景が含まれています。これを除去する作業を最初はgimpやAndroidアプリを使って手動でやっていたのですが、なかなか大変なので自動で行うアプローチを模索し、セマンティックセグメンテーションを用いておおよそ望みの結果が得られました。 猫画像から猫部分のみを抽出する(matting/semantig segmentation) –… Continue reading 猫の線画を着色させたい

自作辞書のブートストラップを考える

かな漢字変換や形態素解析といった処理を行うにあたって、辞書は必要不可欠な存在です。これを一から自作することを考えています。 適切な単語のリストの作成 単語に対する読み、品詞の追加 単語に対するコスト値の算出 データソースはWikipediaを使う こんな感じでおそらくはできるでしょう。時間はかかると思うので、ゆっくり考えていくつもりです。 今はまず教師なし機械学習による単語分割を使って、単語リストを作ることを試みています。これについては階層Pitman-Yor過程に基づく可変長n-gram言語モデル(VPYLM)の実装が複数あり、それを使うことである程度下処理ができます。 latticelm C++/OpenFSTによる実装 vpylml-python C++/Pythonによる実装 (解説記事) Wikipediaの記事はhttps://dumps.wikimedia.org/jawiki/からダウンロードできます。本文のダンプはjawiki-latest-pages-articles.xml.bz2というファイル名です。これをWikipedia ExtractorというPythonスクリプトでプレーンテキストに変換できます。変換時に警告が出ますが、それはたいてい自己参照に関するものなので、放っておいても大丈夫そうです。 さしあたって、展開ディレクトリ/AA/wiki_00を対象にlatticelmをデフォルトパラメータで実施したところ、以下のような感じになりました。 ちょっと分割されすぎですね…ハイパーパラメータはいろいろとあるので、チューニングはいろいろと必要そうではあります。他に試された人の解説によると、初期状態がすべて分割されている点が大きいとのことです。 以前の記事で紹介した「続・わかりやすいパターン認識 教師なし学習入門」には通常のPitman-Yor過程までは解説されており、VPYMLに関してはなんとなくでしか理解出来ていません。もう少し自分の理解も深めたいところです。 単語分割自体は系列ラベル問題とみなしてRecurrent Neural Networkベースで処理することも出来るそうですが、教師あり学習なのできちんとしたデータセットを作る必要があります。そこにたどり着くまでのところを、教師なし学習との組み合わせでなんとか実現したいところです。

2016年9〜10月の活動

ここ2ヶ月ぐらいの活動を記録しておきます。 Debian関係 Namazuのbuild-arch/build-arch-indep対応 ChaSen symbolsの主要arch対応 qemu-debootstrapの利用 porterboxの利用 ChaSenに関しては前回の投稿とも関係があるのですが、とりあえずは主要(公式リリース)アーキテクチャのみ、一通りlibchasen2.symbolsの更新を行いました。 恥ずかしながら今回はじめてporterboxを使いました。これまでporterboxにログインしたことはあっても結局使い方がよくわからなくて諦めたりしていたのですが、たまたまログインしたホストのmotd(ログイン時に表示されるメッセージ)にschrootの使い方へのリンクhttps://dsa.debian.org/doc/schroot/が掲載されていて、それではじめて使い方を理解した次第です。 しかし、qemu-debootstrapでどうにかなる範囲についてはそちらで対応しました。 第12回 カーネル/VM探検隊参加 qemu-debootstrapについてそれなりに理解を深めたので、その紹介という形で発表をしてきました。   Qiitaへの投稿 MySQL 5.5でのCVE-2016-6662対応について 写経で使うツール symlinkを使わずにホームディレクトリの設定ファイル(dotfile)を管理する 写経に関する記事のストック数が多いのが以外です。 FSIJ月例会(予定) 今月10月の28日に、いつもの場所(東京体育館)、いつもの時間(18:30〜19:30)で勉強会が開催予定です。 10月の技術講座 テーマ: 特別じゃないGnuPG GnuPG 2.1のお話だそうで、期待できます。今の時点でのDebian stable(8.x/Jessie)ではまだ標準のGnuPGが1.4系なのですが、次のリリースには2.1が標準になる予定なので、大いに参考になることでしょう。

Baum-Welchアルゴリズムの実装

機械学習についての理解を進めてゆこうとする過程で、ニューラルネットワーク以外の手法の重要性に改めて気づき、「続・わかりやすいパターン認識 教師なし学習入門」を読み進めています。 途中で困ったのが、Baum-Welchアルゴリズムの実装です。その手前のViterbiアルゴリズムは書籍の記述をそのままコード化すれば同じ結果が得られたのですが、Baum-Welchについては解説が少なく、思ったように動作しませんでした。 いろいろとネットを探しまわった結果、コロラド州立大学のCS教材のページがかなりナイーブな実装で参考になりました。ただし、完全にナイーブではなくスケーリングが施してあります。これがないと、条件によっては値が小さくなりすぎてNaNになってしまうような状況が発生します。 より複雑な実装としては、hmmlearnがありました。元はscikit-learnの一部だったようですが、独立したモジュールになったようです。その他、Wikipediaの記事、朱鷺の杜Wikiの記事が参考になりました。

Recurrent Convolutional Neural Networks for Text Classificationを実装した

RNN/LSTMでテキスト分類をしたいと思い、まず自分でネットワーク構造を考えてみました。word embeddingとLSTMを組み合わせて、単純な和を文章全体のベクトルとして扱うことを考えてみたのですが、これは思うように動きませんでした。さっぱり学習する気配がありません。 そこで既に提案されている手法を探してみると、word embeddingの配列をx軸固定の畳み込み演算するという手法がひとつありました(CNNによるテキスト分類)。TensorFlowでの実装もあったのですが、chainerでできないかと思いmax_poolingでstride=(0, 1)といった感じで指定してみたのですが、chainerではstrideの値が0より大きいことを想定しているため0除算が発生して動かせませんでした。 仕方がないので、もうひとつの手法「Recurrent Convolutional Neural Networks for Text Classification」を試してみました(参考: 研究開発:RNNで文書分類(Text Classification) )。 構造としては、いわゆる双方向RNNで単語の出現順、その逆順の2つの方向からRNN(実際にはLSTM)を使って、それらを結合し単語ごとに一つのベクトルを生成します。そして、すべての単語についてベクトル各要素の中の最大の値を取り出したベクトルを生成します。最大プーリングに相当する処理ですが、chainerのmax_pooling_2dは今回の用途には使えませんでした。代わりに、function.maximumが使えたのでそちらを使っています。 結果として、おおよそ望むような挙動を得られました。目視で分類したネガティブな文章とポシティブな文章とを分類することができました。 ソースコードは https://github.com/knok/rcnn-text-classification にあります。Qiitaにも解説記事を書きました(Recurrent Convolutional NNでテキスト分類)。  

Instagramの画像から食べ物の画像のデータセットを作成

過去の記事で予告した、「画像分類タスクのテストのために作ったデータセット」を公開しました。 https://github.com/knok/instagram-food-images 画像そのものではなく、InstagramのURLへのリンク集という形で公開しています。各自でダウンロードしてご利用ください。再配布可能な画像のみをチョイスするのがより良い方法だったのですが、今回はそこまで手が回りませんでした。 Qiitaにも「画像判別タスク向けの自前データセットを作ってみた」という記事を書いています。そちらにも書きましたが、実際に自分で用意したデータセットをChainerで処理する手順の詳細な記事「PFN発のディープラーニングフレームワークchainerで画像分類をするよ(chainerでニューラルネット1) 」があるので、実際の手順はそちらを参考にするとよいでしょう。 最近はseq2seqをやってみているのですが、これも対話文のデータ収集に苦労しています。togetterを起点に、そこから拾えるスレッドをデータ化するといった作業をしています。 これもある程度自動化できないかと試してみています。公開可能な形にできると良いのですが。

感想「深層強化学習による東方AI」

能登さんが発行された技術系同人誌、「深層強化学習による東方AI」のダウンロード版を入手したので読みました。BoothとGumroadで販売されているおり、特に理由はありませんがGumroadで購入しました。   第13回 博麗神社例大祭で頒布した『深層強化学習による東方AI』のダウンロード版をBooth https://t.co/ZysBlu7LY4 およびGumroad https://t.co/HtgRa44sr6 にて販売しています. pic.twitter.com/7rDT2qG9uq — 何もわからん (@ntddk) 2016年5月8日 東方紺珠伝というシューティングゲームを、深層機械学習によってクリアさせようというものです。 この種の話でまず思い浮かぶのが、八重樫さんによるvArashiです。Linux Conference 2002にて発表された資料(PDF)もあります。今になって資料を見ていると、既に10年以上前の話となってしまって当時とはずいぶん状況が変わっているなあと思います。ビデオ入力はBT848でNTSC出力をキャプチャしていますし、捜査対象は初代Playstationなのでコントローラー操作は単純な電気信号です。 自分自身もこの領域については興味を持っていて、REVIVE USBを組み立てたのもその一環だったりします。今欲しいものはLinuxでも動く、できるだけ遅延の少ないHDMIキャプチャーです。USBカメラでOpenCVをちょこっと触ったりもしました。 しかしながら、近年のゲーミング環境をみると、このような仕組みがあまり歓迎されない状況になってきています。対人要素の強いソーシャルゲームやBOT、RMTといった要素があるので、ある程度は理解できるのですが… この著者のアプローチは画像を入力としている点ではvArashiと同じです。大きく異なるのは、深層強化学習を用いている点です。とはいえ、vArashiも通常のアルゴリズムで記述した部分を深層強化学習での実装にお聞かることは可能ではありそうです。 実際に深層強化学習でゲームをクリアさせるという試みはDeepMindが実現しています(Kotaku Japanの記事)。技術的にはその延長です。この書籍では基礎となるQ学習とニューラルネットワークの要素技術である逆誤差伝搬法、畳込みニューラルネットワーク、LSTMのざっくりとした解説がなされています。 また、東方Project作品をクリアする他の既存実装の紹介もされていまする。中にはDLLインジェクションを行い、ゲーム内の情報を直接参照しているものもあります。5種類紹介されていますが、そのうちの一つは深層学習を用いているそうです(東方ProjectをDeepLearningで攻略した…かった。)。ただ、残念ながら最高難度での1面クリアは達成できなかったとのことでした。 この書籍での手法は、難易度Normalの1面をクリアできたことがツイートで示されています。また、戦果の中で「弾幕ごっこのためだけに生みだされたというのに,並の人間に劣るとはいただけな い.」と書かれています。DeepMindが取り組んでいたもっとシンプルなゲーム郡(スペースインベーダーなど)と比較すれば、東方プロジェクトのゲームは敵弾の数が桁違いに多く、個人的にはそこまで行けることは十分な偉業だと思います。 今後の展望のなかに、人間のプレイヤーの行動を元に学習できないか、という提案があります。「視線追跡デバイスを併用してみるのもよさそうだ.」ともありますが、このアプローチについて大昔のログインで実際にシューティングプレイヤーへアイトラッキングデバイスを装着させた記事があったことを思い出します。 詳細は覚えていないのですが、「不慣れなプレイヤーは主に自機を中心に見ているが、上級プレイヤーは自機の少し先を見ている傾向がある」といった内容だった気がします。1980年台頃の話だったので、さすがにWebなどにその記録は残っていないようです。確か横スクロールのシューティングゲーム(グラディウス?)だったような… 当時は「そんなものか」としか思いませんでしたが、今となってはこの傾向は私個人の経験にはかなり適合しているように思います。特に攻撃を中心とした動きをする場合には視線は主に出現した(あるいはこれから出現する)敵の方向にあります。その場合、自機の位置は感覚的に覚えていて、敵弾については意識はするものの、その移動先が極端に自機に向かない場合を除いて無視します。この心の内部モデルにある自機と敵弾との位置関係にズレがあると、被弾するケースがよくあります。そして「あれ、なんで今死んだんだ?」という感想をいだきます。上手い人ほど、このズレがないのだろうと個人的に思っています。 しかし、比較的速度の遅い敵弾が大量に降ってくる状況、いわゆる弾幕を避けるという場面についてはこの限りではありません。この時は、視点が自機よりになります。ただし完全に自機を見るわけではなく、自機に向かってくる方向の敵弾郡を見ます。そして、一定時間後に敵弾が移動したあとを想像し、その時により広い空間になるであろう場所とそこへの経路を考えます。そして実際に移動しながら同じように次の場面ではどこの空間が広くなるか、ということを考え得るという繰り返しです。 これ以外のケースで行う避け方に、「ちょん避け」と呼ばれるものがあります。これは、高速かつ正確に自機を狙ってくる敵弾が出現する場合に用いる方法で、敵弾が発射されるタイミングにあわせてちょっとだけ移動する、という動きを繰り返すものです。近代のシューティングだと、正確な自機狙いの敵弾と正確な自機の隣を狙った敵弾を交互におり混ぜてくることがあり、両方を避けるためにこのような動きをします。また、完全に画面端まで追い詰められにくくする目的もあります。追い詰められてしまった場合、うまく敵弾を避けられるタイミングで入力を反転させる「切り返し」という操作が必要になります。 このように、 局面によって戦略を変えるという行為はシューティングに限らず、様々な競技で見られます。囲碁もおそらくそうでしょう。AlphaGoの仕組みの話を見聞きした限りでは、単純に現在の局面と、予想される読み手の局面評価を単純に有利・不利で区別しているように感じました。囲碁とシューティングゲームではゲームとしての前提がいろいろ違いますが、アプローチ自体はそう変わりないのかもしれません。 ところで怒首領蜂最大往生の陰蜂は、未だノーコンティニュークリアが出ていないようですね。その存在が明らかになってから、トップシューターレベルの人たちが「これは無理だ」と感じているようなので、7年超でクリア者の出た緋蜂とは違い、本当に人類には攻略不可能かもしれません。これを機械学習でクリア出来たらすごいでしょうね。 最後に、この本はビデオゲームを機械学習でクリアさせてみたい、という人には良い本だと思います。ただし、深層学習については別途専門書を購入する、あるいはAndrew Ng先生のオンラン講座を受ける(日本語字幕付き)のがよいでしょう。

Chainerでデータのwhitening(Qiita)

Qiitaに記事を書きました。Chainerのimagenetサンプルで、画像のwhiteningを含むデータ拡張を行うようにした、という内容です。 Chainerのimagenetサンプルで学習データの拡張/whitening いろいろあって、TensorFlowよりもChainerを当面使っていこうという気分になったので、TFでできていたことをChainerでやらせようという試みです。 TFのCIFAR-10デモをCPUとGPUで動かしてみると、思ったほど速度が出ないんですよね…TFが分散ありきのアーキテクチャで、それなりにCPU-GPU間のコピーが発生してるようで、それがボトルネックなのかなあという気がしています。 ちょうど昨日になってTensorFlow 0.7.0が出たようです。そこでパフォーマンスがどう変わったのかは確認したいところです。また、Distributed TensorFlowが出るという発表もあったようです。 今個人で使えるGPUつきマシンがMac miniしかなくて、GPUがATIなのでこのあたり全然使えないのが残念です。