にほんごのれんしゅう

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

pytorch-pix2pix

pytorch-pix2pix

一年ほどまえ、pix2pix系のネットワークを編集して色々おもしろいことができると言うことを示しました。当時はブログ等に何かポストする際に再現可能なコードを添付することを諸事情により十分にできなかったのですが、pytorchに元論文の実装に近いImage to Imageが登場し、かなり強力で表現力の高いネットワークであったので、いくつか再現性とデータセットを再び添付して公開したいと思います  

  1. 白黒画像に色をつける
  2. 不完全な欠損した画像を復元する
  3. フォントのスタイル変換

Image-to-Imageのネットワークと論文とその実装系のForkのForkになります。

素晴らしい編集力と、コードの一般化を行った方々に感謝を申し上げます

A fork of PyTorch implementation of Image-to-Image Translation Using Conditional Adversarial Networks.

Based on pix2pix by Isola et al.

Update

Image to Imageの初版は2016年12月時点の論文ですが、2017年12月にもarXivにversion2が投稿されています。  

学習が安定しているかつ、複雑なネットワークにも対応していて、U-netと論文中では言われていますが、コード中ではResisual Blockなどと表現されており、入力情報を忘れないように細工をする仕組みが十分に入っていることがあるようです(経験的にこのネットワークはコンピュータリソースが十分にあれば巨大なネットワークでも学習できます)  

 

目的関数の設計については古典的な普通の表現を古典的な距離とGANでの距離のハイブリッドになっていて、古典距離はブラー(画像のボケ)を防ぐ効果が期待できます

 

GANの距離と

 

古典的な距離を

 

くっつけます

  

End2Endでラベルを用いるような学習をかなり色々試行錯誤しましたが、もう限界に達しているとも思い、これからは、学習自体に何らか意味あるような学習が優位になっていく用に思います。

requirements

  • Python3 with numpy
  • cuda
  • pytorch
  • torchvision

Getting Started

git clone

$ git clone https://github.com/GINK03/pytorch-pix2pix
$ cd pix2pix-pytorch

train dataset

$ python3 train.py --dataset facades --nEpochs 100 --cuda

train dataset

$ python3 test.py --dataset facades --model checkpoint/facades/netG_model_epoch_200.pth --cuda

Examples

白黒写真に色を付ける

夏+花のデータセットを用いて、学習します Download

$ wget https://www.dropbox.com/s/yhstjhqmsy1cneb/grayscale.zip
$ mv grayscale.zip dataset
$ cd dataset 
$ unzip grayscale.zip

train dataset

$ python3 train.py --dataset grayscale --nEpochs 100 --cuda

predict dataset

$ python3 test.py --dataset grayscale --model checkpoint/grayscale/netG_model_epoch_100.pth --cuda

example output

ノイズや欠落情報を復元する

"自然"のデータセットに対して、ノイズを乗せて復元を試みます   Download

$ wget https://www.dropbox.com/s/1yvr560s24sliay/random_drop.zip
$ mv random_drop.zip dataset
$ cd dataset 
$ unzip random_drop.zip

train dataset

$ python3 train.py --dataset random_drop --nEpochs 50 --cuda

predict dataset

$ python3 test.py --dataset random_drop --model checkpoint/random_drop/netG_model_epoch_50.pth --cuda

example output

フォントのスタイルの変換を行う

人間が習字で書いたデータセットに対して、Takao Fontと対応させて、新規フォントを作るという発想です

Download

$ wget https://www.dropbox.com/s/owee6hxopnr4dpo/font.zip
$ mv font.zip dataset
$ cd dataset 
$ unzip font.zip

train dataset

$ python3 train.py --dataset font --nEpochs 150 --cuda

predict dataset

$ python3 test.py --dataset font --model checkpoint/font/netG_model_epoch_150.pth --cuda

example output

コード

ご自由にご利用ください

参考

RNNで関数近似

RNNで関数近似

DeepLearningの一種であるRNNで、任意の関数を学習させて、十分にある関数の挙動が観測できたとき、未知の任意の点で予想できることを示したいと思います。

始める前に諸々調査したこと

ディープラーニングで任意の連続する関数を再現可能です。

しかし、ディープラーニングは無限やかなり大きな値を扱うことは難しく、適切にフィットしない問題があります。無限大に発散しない(発散してもいいけど、目的とする値をなにか閉域に限定して変換する操作を行う)必要があります

もっと有機的で人間的な特徴を学習と予想を行う問題として、sketch-rnnというrnnで最初の一部だけを描き、学習した内容で残りを予想するという問題設定もあって面白くユニークです

図1. 関数近似もスケッチの特徴を学び学習するのも一緒な気がします

耳だけ描くと、残りの部分が自動的に機械学習の予想結果により描かれます

様々な関数をDeepLearingのRNNで近似する

RNNはn-1からn-mまでの情報を特徴量にnの系列でのデータを予想することができます。
この時、連続であることが望ましく、無限小、無限大を取らないような、一定の再帰性があると収束しやすいです。(発散する関数は予想が大きくなるに近づくにつれ、難しくなります)

 

図2. アステロイド(うまくいく)

 

図3. 二次関数(うまくいかない)

数式で表現する

ディープラーニングのRNNのEncoder-Decoderの一つの機能の粒度を関数として表現すると、このように表現することができると思います。

ディープラーニングで適切なF1, F2, F3を決定することで、次の系列のX,Yが予想可能になります

ネットワークで表現する

ディープラーニングのネットワークではこのように表せるように思います

図4. 作成したネットワーク(RNNのAutoEncoderモデルを参考に作成)

このネットワークは特に媒介変数がないと表現できないようなネットワークについて高い力を発揮しそうだと考えました。

実験

サイクロイド

サイクロイドはこのような図形になます

 

媒介変数をもちいた表現はこのようになります

 

学習

$ python3 20-train-cicloid.py --train

評価

trainで使用しなかったデータを使用して予想

$ python3 20-train-cicloid.py --predict

 

図6. 予想したサイクロイド

ステロイド

ステロイドはこのように表現され、一定の大きさよりは大きくなりません

 

図7. アステロイド

媒介変数をもちいた表現はこのようになります

 

学習

$ python3 20-train-asteroid.py --train

評価

trainで使用しなかったデータを使用して予想します

$ python3 20-train-asteroid.py --predict

 

図8. 予想したアステロイド(たまにyが0にドロップする)

対数らせん

対数らせんはこのように表現されます。無限に大きくなるので、媒介変数thetaを一定の大きさでストップします

 

図9. 対数らせん

媒介変数を用いた表現はこのようになります

 

対数らせんの図

図10. 予想すした対数らせん(微妙に歪んでいる)

コード説明

Githubからどなたでも確認することができます
10-prepare.py
上記の例で示した図を描くような数字の系列のデータセットを出力します
以下のファイルが生成されます

サイクロイド.pkl
アステロイド.pkl
カージオイド.pkl
対数らせん.pkl
リサージュ.pkl
インボリュート.pkl

20-train-asteroid.py
ステロイドを学習&予想します
20-train-kardio.py
カージオイドを学習&予想します
20-train-cicloid.py
サークロイドを学習&予想します
20-train-spiral.py
対数らせんを学習&予想します

まとめ

  • いろいろな媒介変数でないと表現が難しい関数をy = f(x)でない、系列予想の問題設定とすることで簡単に予想することができそうだとわかりました
  • とにかく時系列でもなんでも連続した数字として表現できるのであれば、(モデルが十分に大きければ)予想が可能そうです
  • 仮定や解析プロセスを挟まずに学習&予想することができるので、楽です

参考文献

Microsoft Bingのランキングエンジンをxgboostでシミュレート

Microsoft Bingのランキングエンジンをシミュレートし、ランキングを学習します

目的

inspector(検査官、監査人、検閲官、視学、警視正、警部補)

ランキングアルゴリズムは日々進化しています。Googleサーチエンジン200以上の特徴量を用いたり色々しています。

これらはGoogleでないと手に入らない特徴量も多数存在しており、容易に、ユーザが最適化できるものではなかったりします

わかりやすいものでは、ドメイン以内にコンテンツが十分に存在し、それがある程度参照されるものであれば、以前あったようにWelqさんのようにコンテンツの内容の是非によらず、ランクアップしてしまうような問題もございました。

意図しない作用をもたらすから、狙ってはいけないなどということはなく、SEOはビジネスにおいて極めて重要な課題です。  

SEOでどの要素(サイト規模?テキスト数?キーワードの作り?コンテンツの内容?)などどれにどの程度注力すればいいのか判明したら大変なビジネスインパクトがあります。

ここでは、クリエイティブのキーワード(title, meta, body)で何がどの程度重要か、BingさんやGoogleさんなどを教師データとしたときに、機械学習アルゴリズムでサイトを、どの程度有益なのか定量化してみようと思います。  

お題

Rankingエンジンのランクの傾向を、検索クエリ結果から、ランキンされたサイトの自然言語的特徴から、獲得しようという意図です。

これを行うにあたって1つの制約があります。

1. ランキングエンジンのリバースエンジニアリングのような行為は認められるのか

  1. に関して述べると、この行為は、例えばGoogleやBingなどのサーチエンジンの競合を作るという意図がない、広域に解釈すれば、ビジネスでなければよいと言えそうである。例えば今回は、自己研究に基づくので問題がない。  

Microsft Bingのランキングエンジンのクエリ(neologdに内在している辞書を利用)することによって、膨大なダイバシティの検索結果が得られます。
検索結果のランキングを見ることにより、同等のランキングエンジンが作成可能であると期待できます

ランキングアルゴリズム一覧

読むべき論文

よく見る評価指標

目的関数

ranksvmフォーマット

資料が全くなく、調査して理解するまで結構かかりました。
ranksvmフォーマットはgroup fileというのが別途必要になっている

bingのデータクローン

  • neologdで一般単語をとりだす
  • bingでクエリを作成して、ひたすら大量に集める
  • 1位=4, 2位=3, 3位=2, 4位=1で、単一ページでないドメイントップのサイトをランキングする  
  • 言語処理的にtitle, meta, bodyの自然言語でランキングしてみる

(本当はこれ+DeepLearningでやってもいい)

オペレーション

Githubで公開しています(問題等があればtwitterにておしらせくださいませ)

Operation 1. ランククエリ生成

neologdなどからnoun(名詞)を取り出して、それを検索クエリ群にする

import glob
import pickle
import json 
nouns = []
for name in glob.glob('mecab-ipadic-neologd/build/*/*.csv'):
   f = open(name)
   for line in f:
     ents = line.strip().split(',')
     if '名詞' not in ents:
       continue
     term = ents[0]
     nouns.append(term)
open('nouns.json', 'w').write( json.dumps(nouns, indent=2, ensure_ascii=False) )

Operation 2. bingをスクレイピング

$ python3 scrape.py

Operation 3. フルドメインが入っているリンクをパース

$ python3 scan_pair.py

Operation 4. bingの結果からフルドメインスクレイピング

$ python3 pair_scrape.py

Operation 5. フルドメインのHTMLをパース

$ python3 10-parse-htmls.py

Operation 6. 分かち書きして特徴量化

$ python3 20-make-vector.py

Operation 7. 疎行列で表現してranksvm形式のファイルを出力

$ python3 30-index.py

学習

OP7を実行すると学習可能なファイル群が出力されます
(xgboostのバイナリがlibcなどの互換がなくて実行できない場合は、xgboostを再コンパイルしてください)

$ cd rank
$ ./xgb mq_train.conf 

map(mean average precision)の略で、平均精度です。pairwiseで評価すると、mapでの評価になります。他の関数のndcgなどはうまく動作しません。なぜ?

1000roundでの精度はこの程度です

[20:36:05] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 936 extra nodes, 1252 pruned nodes, max_depth=36                                                                                 
[20:36:05] [999]        test-map:0.721291        

学習が完了すると、rank.modelというファイルが出力されます

予想

rank.modelをもちいて未知のクエリに対してランキングすることができます

$ ./xgb mq_predict.conf 
[20:51:20] 144775x162216 matrix with 3899318 entries loaded from test.data
[20:51:20] start prediction...
[20:51:49] writing prediction to pred.txt

pred.txtの中にランキングされたファイルが記されています。

ランクの値と、実際のランクはこのように表現され、やはり相関など何も考えなくても単純にランキングが上になりがちな構成という物がありそうです
(予想ランク@左、実測ランク@右)

1.05754 4
-0.578957 2
0.386893 0
0.511651 4
0.683687 2
-0.800342 0
0.642033 4
0.35129 2
0.74472 0
1.39248 4
0.454038 2
0.221512 0
...

単純なSVMなどを利用すると、簡単に配信システムで計算できますが、勾配ブーストのようなランキングはどうなんですかね。決定木なのでC++のファイルなどに変換させるのが良いと思います

xgboost, lightgbmランキング意外と便利

ランキング学習はレコメンドエンジンとも深く結びついた技術でマネタイズのコアをなしうる重要なテクノロジーです

AIで自動判別でなんかすごいのを作る前の前哨戦で、レコメンドはぜひとも検討に値するテクノロジーです  

おまけ

勾配ブーストによる特徴量選択の結果を見ることができます

強力に非線形化されているので、これ単独で見ることにあんまり意味はないのですが、どんな特徴量が選ばれやすいのかは視覚的に確認できます

例えばランキングに影響する単語群はtitleとkeywordの重要度が高いのはなるほどという感じなのですが、車なども強いことがわかります

title:インポートファッションアイテム 1989114     
title:Sledge 680939                              
title:バンキング 465049                          
title:西善 314689                                
title:メイプルストーリー 188914                  
keyword: ベローズ の 専門 メーカー  180548       
title:ラセン 153568                              
title:DV 86233                                   
keyword:建築 資材  68659                         
title:あぜ 68124                                 
body:none 60321                                  
keyword: クロス ロード  51767                    
title:Shade 46926                                
title:食通 44635                                 
body:, 43729                                     
keyword:競艇  38174                              
keyword: 常滑  32940                             
title:多摩丘陵 29434                             
title:cherry 25848                               
body:MAZDA 25152                                 
title:の 23459                                   
title:エビス 23234                               
title:本田技研工業 23085                         
body:Jewelry 22530                               
title:・ 21902     
...

brand-transition(ブランドの変遷)

brand-transition(ブランドの変遷)

SVMで極性評価した単語をもちいて、声優のポジティブネスをniconicoニュースコーパスを利用して、時系列的に表現します

時系列的な変遷を分析することで、バズの検知や、話題、炎上などをシステム的にキャッチアップしやすくなります

もともとの起草

これは、もともともブランドの毀損などを評価しうるものとして、prophetなどの系列予想システムと連結させることで、急激なブランド毀損(炎上)などを検知して、炎上に対して適切な対応をとることにより、ブランドイメージを守ろうとするものでした(これは個人研究でやっていたのですが、3ヶ月ほど前にいろいろなところに提案しましたが、どこにも引き取ってもらえてないので、いくつか再スクラッチして自分の所有しているデータセットに変換し、公開ナレッジ化します)  

Amazon, RakutenなどのレビューをコーパスSVMなどで大規模極性辞書を作成する

もともとブランドのネガティブさ、ポジティブさというのはどのように評価すればいいのかわかりません。

この時、SVMなどをレビュー情報(星の数)などを教師データに、極性を重んじた学習の分割が可能になります  

星の数を1,2,3個をネガティブとして、5個をポジティブとすると、非常にそれらしい結果が得ることができます。

学習した結果のウェイト

negative度が高いもの

売り手 -4.393270938125656
ガッカリ -3.947897992103171
がっかり -3.648103587594949
残念 -3.130127382290406
致命 -3.112032623756082
期待はずれ -3.083929660401355
返品 -2.948516584384151
灰皿 -2.87787780959521
3つ -2.783511547585251
駄作 -2.771137686778778
物足りなかっ -2.663694159049179
最悪 -2.655338531812268
うーん -2.499197140760456
二度と -2.480062770645911
意味不明 -2.420151065200296
いまいち -2.419859090879487
失せ -2.41635935742869
つまらない -2.404018144393537
単調 -2.368271765218191
堀江 -2.34675269334997
つまらなかっ -2.316511096716675
タートル -2.288030642964168
イマイチ -2.27754859957102
目新しい -2.269002906892812
まずい -2.23071763111786
欠ける -2.222289341852733
...

positive度が高いもの

お買い得 1.987645060840108
最高傑作 1.990702627997584
別格 2.011164421643425
目からウロコ 2.014549379784212
これ程 2.019119980229243
杞憂 2.026934292869131
戻れ 2.052378639149482
オジさん 2.061753308187434
痛快 2.061960603545156
欠か 2.087942969787786
叩け 2.08933 2.130187229517098
pop 2.1307765382222862
病みつき 2.142924963400594
憎め 2.160722430925575
洋楽 2.169574554504112
強いて 2.224321728820268
バイブル 2.229368722596254
絶妙 2.245596441611436
従う 2.254309352677592
五つ 2.255604793487576
待ち遠しい 2.25806614954727
逸品 2.265821501069568
最高 2.289466171874273
傑作 2.293924930835376
サウンドトラック 2.295214513832636
是非 2.311342110589227
半信半疑 2.39707658523505
ガル2.661651342883942922
R&B 2.6851915989280470909009
一括 2.730196185564076
リッツ 2.766706018272894
大正解 2.874333983897774
手放せ 2.948887203551322
必読 3.012749694663035
セレクトショップ 3.050995942436786
5つ 3.081741024496506
秀逸 3.229761176207314
...

このようにそれらしい結果が得られます

データセットDropboxで公開していますので必要ならばご利用ください(商用利用は法的に望ましくないです)。

ある名詞(人名)が含まれているドキュメントが含まれているドキュメントのネガポジをその語の含まれている文脈の意味とする

仮説ベースで、ヒューリスティックにうまくいく方法ですが、このようにすることで、ドキュメントの極性と、ドキュメントに含まれる単語の紐付けを行うことができます  

 

図1.

時系列的にドキュメントを並べて、ある人名のポジティブ度をSVMで作成した重みを利用して時系列順に並べる

niconicoニュースのコーパスは、毎日、ある程度更新されており、ライセンスの関係かわかりませんか、結構昔に遡れます(新聞社は多くの場合、過去に遡ることができません)  

そのため、コーパスを日時の粒度でまとめて、並べ直して、その時のniconicoニュースのコーパスを利用すると、下記の図にすることができます。  

SVMでレビュー情報を学習した単語に付与される重み情報から、ドキュメントのスコアを算出します(強調的に状態が見えるようにいくつかヒューリスティックにしてあります)  

 

図2.

実験結果

100日以上、話題にされている声優でかつ、私がわかる声優さんが含まれるニュース記事の極性を判定して、sigmoidにかける前の重みで、重みのリストを手動でいくつか編集した物を用いて、日付順で極性のスコアの変遷を見ていきます。

声優を題材としたのは、単純に、niconicoニュースがオタクよりのコンテンツが強いからであって、それ以上の他意はございません  

図3. 早見沙織の時系列データ

図4. 水瀬いのりの時系列データ

図5. 日笠陽子の時系列データ

単純に日々のニュースでポジティブに紹介されたようなことがあると、グラフ的に跳ねる現象になり、なんらかの異常値検知システムにて自動化もできそうです

コードとオペレーション  

niconico newsなどのコーパスは各自でご用意ください

(スクレイパーもありますが、1secのsleepを入れていますが、そもそもどの程度許容されるものなのかよくわかっていません)

レビュー情報をパース  

$ python3 10-scan-reviews.py

liblinear(sigmoid)で学習したウェイトを分析して、単語の重み付きファイルを構築する  

$ python3 20-scan-weights.py 

niconico newsを時系列で処理する  

$ python3 30-news-time-series.py  

声優名が含まれるコーパスを重み付き単語ファイルで評価

$ python3 40-actor-time-series-polarity.py

各々の声優名のデータを取り出す

$ python3 50-data-pick.py 

結果

このように、時系列データして扱うと、ところどころ、ポジティブさみたいなものが跳ねるような事象を観測することができて、プラスの意味での炎上(ただの話題ですが)を観測したりアラートを流すことができたりしそうです。
声優統計みたいな感じになりましたが、他意はございません。niconicoニュースとオタク関連の記事の相性がよかったので題材をこのように定義しました。