デースマートフォン用の表示で見るデーこの広告は、90日以上更新していないブログに表示しています。2015-06-13waifu2xの更新(1)学習済みモデルファイルを更新しています。今後の準備のためにソースコードを更新するついでに手元のモデルを更新しただけなので、そのうちまた更新されます。デモサーバーには反映しているので少し変換結果が変わっています。サードパーティのローカルソフトウェアを使っている方は、modelsフォルダにあるjsonファイルを上書きすれば使えるのではないかと思いますが、ソフトによっては動かないかもしれません。何が変わっているかは画像によりますが、自分の意図としては、ノイズ除去でできるだけ細部が消えないようにする(ほとんど変わっていないけど、頬の///は消えにくくなった)拡大時に線画の線が太くなり過ぎないようにする(画像によってはかなり変わっている)漫画のことは諦めた(スクリーントーンは前のバージョンよりひどくなっている場合が多い)学習データとその生成方法から間接的に調節しているので、変更は分かりにくいです。検証用ベンチマークの数値的にはほとんど変わっていません。cuDNNの対応をやめて、Torch標準のCUDA実装を使うようにしたので、cuDNNは不要になりました。理由としては、速度的にそれほど変わらないのと、配布時にライセンスの問題があるためです。ボヤけたり、ギザギザになったりしませんでしたか?waifu2xをお試しください。(ブラウザの処理に影響されないようクリックで拡大おねがいします)waifu2xは、二次元画像を2倍に拡大するソフトウェアです。多くの二次元画像についてスゴイ級のクオリティで拡大できます。使って開発されました。waifu2xの人工知能は、次の問に答えます。いまから与える画像はある画像を半分に縮小したものである。縮小される前の画像を求めよ。画像を拡大するのではなく、縮小される前の状態に戻します。縮小されてないオリジナル画像を与えた場合も、やはり縮小される前の画像を答えます。その画像は本来存在しないものですが、waifu2xはそれを想像で創ります。Google画像検索を使ってもノイズのある画像しか見つかりませんでしたか?waifu2xをお試しください。(ブラウザの処理に影響されないようクリックで拡大おねがいします)waifu2xは、二次元画像のJPEGノイズを取り除くソフトウェアです。多くの二次元画像についてスゴイ級のクオリティでノイズを除去できます。使って開発されました。waifu2xの人工知能は、次の問に答えます。いまから与える画像はある画像を任意の圧縮率でJPEG圧縮したものである。JPEG圧縮される前の画像を求めよ。ノイズを取り除くのではなく、画像をJPEG圧縮される前の状態に戻します。JPEG圧縮される前の画像がインターネット上に存在しない場合も、やはりJPEG圧縮される前の画像を答えます。JPEGは非可逆圧縮と呼ばれる一度圧縮してしまうと元の状態には戻せない形式ですが、waifu2xは二次元画像の知識を使って逆変換を行います。waifu2xはなんだかスゴそうです。完璧ですか?waifu2xは実際スゴイですが、完璧ではありません。(ブラウザの処理に影響されないようクリックで拡大おねがいします)画像を見て、髪飾りに注目してください。waifu2xの出力では、髪飾りに数珠めいた模様が刻まれています。他の資料で確認したところ、初音ミクの髪飾りにそのような模様はありません。waifu2xは、縮小される前の画像には髪飾りに数珠めいた模様があったと解釈して、その模様を復元しましたが、それは間違いだったということです。waifu2xは、多くのケースでよい改変を行いますが、勘違いで余計なことをしてしまうことがあります。悪い例としてマンガのスクリーントーンがあります。waifu2xは、マンガのスクリーントーンを謎めいた模様に変換することがあります。その謎めいた模様を半分に縮小すると、不思議なことに元のスクリーントーンに戻ります。(ブラウザの処理に影響されないようクリックで拡大おねがいします)waifu2xは、我々人間の感覚からすると間違っているように見える変換を行うことがありますが、検証してみると間違ってはいません。「縮小される前の画像」をどのように想像するか、waifu2xと我々人間の間で感覚の相違があるようです。この溝は今のところ埋められていません。いったリスクがあることもあり、waifu2xは特に画像の色合いを変えないように制限されています。代償としてヤバイ級のJPEG劣化で虹色に変化してしまった部分は修復できません。参考waifu2xは、SRCNN[1]にインスパイアされて開発されました。細かい違いはたくさんありますが、大まかな枠組みはSRCNNです。BY-NCで公開されているものを使用しています。マンガのテクスチャはスクリーントーン風にワンダラー&SAI用テクスチャー素材[3]から引用しています。http://www.twodolls.net/archives/2011/09/sai-1.phpアクセスwaifu2xは以下のURLから利用できます。waifu2x.udp.jp現在サーバーが1台しかなく、なかなか重い処理(1件あたり1〜5秒程度)なので、多くの方が同時に試すとレスポンスが返ってこなくなるかもしれません。レスポンスが返ってこない場合は、少し時間をあけて試してください。ソースコードはgithubで公開されています。github.comwaifu2xのコードはLuaJIT/Torch7を使って開発されました。AMIEC2用の環境構築済みのイメージを公開しています。AMI追記Firefoxだと"画像を保存"で変換後の画像が保存できていないようです。イルとルカの不思議なふしぎな鍵があったのでやりました。ドラクエ好きでもモンスターズシリーズはやっていない人が多い気がしますが、イルルカは前作のテリーと違って普通の広めのマップでドラクエっぽいストーリーを進めるようになっているのでお勧めできます。難易度は、特に攻略サイトとか見なくてもストーリー上で引っかかるところはなかったし、あまり全滅もしなかったので、難しくはないと思いますが、前作はボス前に必ず回復ポイントがあったのが今作ではなくなっているので、MP回復アイテムを買うか雑魚用とボス用のパーティを分けて育てるようにしないとつらくなる気もします。最近のドラクエでは、クリア後の世界というのがありますが、僕はこれあまりやる意欲が沸かないなのですが、イルルカではクリア後というか前半・後半だろコレ!というくらいスタッフロール後も普通のストーリーが続いていてよかったです。前半が難しいとすぐ投げるライト層向けで、後半がレベル上げとか育成とか地道な作業をやらないとクリアできないゲーマー向け仕様じゃないかと思います。裏ボスを倒すとさすがに対戦しかやることがないですが、毎週マスターズGP(なんでもあり)、チャレンジャーズGP(モンスターのサイズや強さなどに制限あり)というAI戦(手動入力なし)が開催されていて、今でも2000人くらいは参加しているので、AI同士の対戦とか好きな人は楽しめると思います。対人戦は、wifiで段位戦とフリー対戦というのがあって、いまでも夕方くらいにやればできます。wifiで対戦するとすれ違いができて、すれ違った人から鍵(ボーナスマップようなもの)やモンスターが貰えるので、表クリア後くらいからやるのがいいと思います。表クリア後がいい理由として、2回ダイヤモンドスライムを倒すとレベルがカンストとするような鍵が出回っているので、これを前半でやってしまうと簡単すぎてつまらなくなるのではと思うからです(ただダイヤモンドスライム自体が結構強いので倒せないかもしれない)。後半は、レベルがカンストしててもパーティの構成などがんばらないと裏ボスは倒せないと思うので、対戦をやりながらクリアするのがいいのではないかと思います。300位/1300くらいでした。よくないですけど、発売して1年以上たってて、ずっとやり続けているガチ勢が多いのではと思います。wifi戦は、GP用パーティーのテストとして段位ベテランマスターまではやったのですが、手動入力なので「おまえそれはねーだろ」みたいな手を使ってくる人が多くて、AIだけだとつらいし、手動入力を考えると、GP用とは違うスキル構成のほうが強いと思うので――とか考えると、GPだけやるのがいいかなと思って、あまりやっていません。ウルトラガードSPみたいなスキルはたくさん欲しいので、たまにやっているいう感じです。いうことで、発売してかなりたちますがまだ楽しめるのでオススメです。Kaggle結果はタイトル通り10位(1049チーム中)でした。賞金2000万円が1円も貰えなかったショックで毎日15時間くらい寝ています。Networks職人コンテストという感じでした。前半は、2〜5位くらいにいる状態だったので、これは賞金はオレのものだなHAHAHAなどと思っていたのですが、終盤は15位くらいまで押し出されるようになり、こいつらマジかよ、強すぎだろ、と思って、最後方向転換をしてどうにか10位で終われました。CNNを熟知していて必要な処理を漏れなくやった上で相当チューニングしているという印象なのですが、これが最終的に50人以上いました。そんなにいるとは思わなくて、世界をなめていたと思います。自分でやりながら0.6くらいが限界だと思っていたのですが、上位3チームは飛び抜けて良いスコアを出していて、そこを超えているので、本当にすごかったと思います。入賞がちょうど3チームなので、まぁ...あそこにはどうやっても入れなかったな、と諦めがつくくらいです。いうことで、賞金は貰えず、ぎりぎり10位*1という微妙な結果だったので、10位だったことくらいは自慢させてください。ひとつのCNNのアーキテクチャをとにかくチューニングして、それを8個学習して平均するという、シンプルな手法を採用していました。96x96)を8ずつ計24個のCNNを20台のGPUマシンで4日くらいかけて学習して各予測値を線形モデルでアンサンブルするという、激重な手法に切り替えました。これは"色々混ぜればスゴイ"という適当な考えではなくて、データセットの画像サイズがバラバラ(幅32px〜400pxくらいがある)なので、予測時の適切な解像度は画像ごとに異り、異なる入力サイズのアーキテクチャをアンサンブルすればスコアは改善できるだろうという推測が初期の頃からありました(ただダサいのであまりやりたくなかった)。結果うまくいって、ぎりぎり10位で終われました。結局やるのなら初めからやっておけばもう少し良く出来たかもしれません。前処理このデータセットは、画像ごとにサイズが異なり、また正方形でもありません。一般的なCNNでは固定サイズで正方形の画像を入力とするので、以下の方法で変換しました。中央寄せして、パディングで正方形にして、画素値を反転させます。画素値を反転するのはその後の画像処理で背景が0となっていたほうが扱いやすいからで、精度等とは関係ありません。中央寄せの効果については、検証していません。augmentationと合わせて最悪なことになりそうなので中央寄せしたほうがいいだろうと思ってやっているのですが、最初のプログラミング時点からやっていたので、これに意味があるか、または逆に悪くなっていないか等は分かりません。上位には入れているのでそんなに悪くはないと思います。augmentation(学習データの人工的な拡大)でスコアが改善すると思ったので行いました。augmentationが特に効果的でした。augmentationには次の変形を使いました。(affine変換またはhomography変換による変形)コントラスト変更これらの変形メソッドとその変形パラメーターをランダムに組み合わせることで1枚の画像から以下のような改変バージョンをムゲンに生成して学習データとします。変形が分かりやすいようグリッドで表すと次のようになります。augmentationでは、(オンライン)学習器にデータを与える際にこのランダムな変形を通してから渡すようにします。変形のパターンが十分あれば、学習中に同じデータは1度しか与えられないので、オーバーフィッティングしにくくなります。augmentationのあり/なしを変えた時のスコアは以下のようになっています。augmentationで増加させた後で各パターンについて予測を行い、予測結果を平均しています。augmentationは非常に効果がありました。これをやるかやらないかまたその内容によって大まかな順位が決まったと思います。コンペ前半に、TheanoやTorchなどプログラミングを前提としているフレームワークを使っている勢が強かったのは、この処理を早くから採用していたからだと思います(僕は最初の投稿時からやっていました)。augmentationが効くという話が出始めた後で本体を改造し始めた人が多かったのではと思います。Normalization(GCN)を使いました。これは、画像ごとに画像内の平均画素値を引いて画素値の標準偏差で割るという正規化です。augmentationのハイパーパラメーターによって変わるので扱いづらく、画像単位で処理できるGCNが扱いやすかったのと、収束やスコア的にも問題なかったので選択しました。augmentationの後に行っています。学習器の更新が学習のメインループになります。アーキテクチャ終了1週間前まで96x96を入力サイズとするシングルアーキテクチャ(cnn_96x96)をずっと調節していました。最適化するようにした学習率のスケジューリングを調節くらいです。シングルモデルで0.7→0.65くらいの改善で、頑張っていた割にあまり改善できていませんが、0.7〜0.63くらいの密度が高かったのでコンペ的には効果があったと思います。cnn_96x96の最終盤は次のようになっています。create_model最初の頃はこんな深いネットワークは学習できませんでしたが、初期化処理を改善するのとLeakyReLUを使うのとで学習が可能になりました。悲しいことに、最後の1週間において勘で追加した入力を72x72とするアーキテクチャのほうが良いスコアを出しています。これは、入力画像サイズをチューニングしたのが最初の頃で、その後の様々な変更で適切なサイズが変わっていたのに気づかず、ずっと96x96の上で調節していたということだと思います。色々な所のハイパラーパラメーターが依存関係にあるのでもはや人類にはチューニング不可能だと思いました。アンサンブル上記のcnn_96x96の他に、cnn_72x72とcnn_48x48を追加してアーキテクチャごとに8個バギングした予測結果をさらに重みづけてアンサンブルしました。アンサンブルの重みは、validationの結果から解析的に求められますが、実装が面倒だったので乱数の総当りで決めました。最終的に各モデルの結果は次のようになりました。0.6160ソースコードは以下のURLで公開しています。Kaggle-NDSBまとめ自分で書いてて、きわめて普通だなーと思いました。上位3人の手法にはそれぞれ奇抜なものが含まれているようなので興味のある方はフォーラムを監視するのがよいと思います。Predictionが終わりました。言っても、僕は始めて1週間目くらいにプランクトン分類が始まったため、そっちばかりでほとんどやっていなかったのですが、ついに終わりました。結果は72th/1604。一応、上位5%には入っているけど、僕は絶対値を気にするので、72というのはあまり良くないな、と思う。ソリューション以下自分の投稿内容です。fast_solution_v3.pyです。統計量を特徴量に使ったGBDTモデルまずデータを2つに分割します。(出現したうちクリックされたレコード数)を統計量計算用データから計算します。...という感じのデータ。これらを使って、モデル学習用データの各変数を置換します。これでたくさんあるダミー変数の次元が全て2に次元削減されます。今回の場合、22変数だったので、44次元のデータになります。この特徴量をxgboostを使って学習しました。単体のLBスコアは、0.3933798でした。今回とにかく、GBDTを使ってみたいという思いが初めにあったのですが、変数が多すぎてうまく学習できないように思えたのでとにかく減らしてみました。データの分割方法はいろんなパターンが考えられて、たとえば、統計量計算に使うデータを1日ずつズラしながら7モデル学習して平均するようなこともできるのですが、やってみたところ特に良くなりませんでした。全体をランダムに分割するというのも試しましたが、これは統計量の情報が正確すぎるせいか、めちゃくちゃオーバーフィッティングしました。古いデータから統計量を計算すると、新しく出て来た変数の情報が無くて変換できない変数がテストデータに増えるため、一番新しいデータである30日を統計量計算用に使うのがよさそうでした。交互作用項を追加したfast_solution_v3.pyfast_solution_v3.pyはフォーラムで共有されているコードです。algorithmとかいうのを使った線形分類器です。変数の削除は、L1正則化に期待することにして、あとはいい感じのinteractionを追加できれば精度が良くなるだろうと思ったので、変数を追加する方向で改造しました。方法としては、ただのブルートフォースアタックです。効果があった変数順にソート効果がありそうな変数を上から5個単位で追加していってスコアが悪くなったところで追加を辞めるというコードを書いて、一晩ほど計算した結果を少し手で調節して、以下のパラメーターで学習するとよい、ということになりました。)interactionは元のコードでは全て入れるか全て入れないかの2値ですが、指定した変数の組み合わせだけ使うように改造しています。交互作用項を追加したfast_solution_v3.pyです。重みは適当に試して決めました。各モデル単体のスコアに比べてかなり良くなっています。decayが効いただの書いてあって、何でオレはそんなことも試していなんだ...と思う内容が多かったです。データが大きくてあまり手の込んだことはできないという思いが強くて、試すパターンを制限しすぎてしまっていた気もします。18:13Avazuが終わったTweet広告を非表示にするもっと読むコメントを書く2015-01-30Torch7の分かりにくい話Facebookがtorchの拡張を公開したこともあり、torchを使ってみている方も出始めたようなので、自分がtorchで使う上で分かりにくかったことやハマったことなどを上げていきます。ある程度使っている方を前提としています。ひどいことをたくさん書きますが、torchが嫌いなわけではありません。torchはサイコーです。リリースやバージョンについてezinstallはgitのリポジトリをcloneしてインストールします。torchは今のところリリースの管理などしていなくて、日々更新される開発リポジトリがあるだけなので、インストールした日によって異なるバージョンがインストールされます。以下のようなコマンドを実行して更新したほうがいいです。これは主にDropoutの動作に影響します。module:training()(デフォルトの状態)のままforward()で予測すると、Dropoutモジュールが含まれている場合にランダムに接続を切ってしまいます。モードを切り替えてからforward()を行います。バッチモードとはなにかnnのほとんどのモジュール(全てではない..)はバッチモードを持っています。これはminibatch更新などで一度に複数のデータをforward/backwardするためのモードです。このモードを使いたい場合は、入力として想定されているTensorよりひとつ軸の多いTensorを入力します。Tensorを渡した場合はバッチ処理になります。Tensorを渡した時はバッチ処理になります。CUDAバッグエンドのいくつかはバッチモードにしか対応していません。CUDAを使う場合はバッチモードで使うことを想定しているようです。CriterionCriterionは目的関数の定義です。SoftMaxなどの出力関数がCriterionと切り離されているため、分かりにくくなっていると思います。Tensorになります(バッチモードの場合、2DTensor)。nn.ClassNLLCriterion()を使います。変換する必要があります。計算効率の問題でこうなっているのだと思いますがかなり分かりにくいと思います。nn.TrueNLLCriterion()を使うようにしています。Lossで直接最小化するというごく普通の動きをしてくれます。このモジュールは、facebookのfbnnの一部ですが、単体で動くのでこのファイルだけコピってきて使うのがオススメです。入力データを(:cuda()メソッドで)CudaTensorにして実行します。forwardの返り値はCudaTensorになるのでその後使う場合はfloat()でFloatTensorに変換してから使ったほうがいいです。Successful!")endtorch.setdefaulttensortype('torch.FloatTensor')cuda_test()DropoutDropoutは第2引数にtrueを入れると学習時にランダムに接続を切って、予測時は(1-接続を切る確率)倍にするという一般的なDropoutになります。デフォルトでは、学習時にランダムに接続を切って1/(1-接続を切る確率)倍にして、予測時は出力そのままを使う実装になっています。デフォルトのほうが計算効率はいいと思うのですが、出力のスケールが変わるので他の実装を参考にした場合などは注意が必要です。デーを使うと便利です。moduleいろいろSpatialConvolution/SpatialMaxPooling/SpatialAveragePoolingには沢山の種類があります。微妙に動作が異なるものがあるので使う際には注意が必要です。nn.SpatialAveragePoolingtorch標準のものです。他の実装に比べて遅いです(と言ってもすごく遅いわけではありません)。CPU,GPU,逐次,バッチと広く対応しています。nn.SpatialAveragePoolingは平均ではなく合計を出力します。(平均を出力するものもあり、実装を切り替えただけつもりが出力が変わることがあります)またこれらのモジュールは、出力サイズの計算にfloor(切り捨て)を使います。(ceil(切り上げ)の実装がいくつかあるため、実装切り替えただけつもりが出力のサイズが変わることがあります)nn.SpatialConvolution昔からあるものでサンプルなどで使われていることがありますが、最近はnn.SpatialConvolutionMMを使うようになっているので、使わないほうがいいです。nn.SpatialMaxPoolingCUDA謎の実装です。実験的な実装のまま放置されているものなので使わないほうがいいです。cuDNNを使う実装です。cudnnでインストールできます。cuDNNが必要です。cuDNNは最近公開されたRC2-v2以外は全てバグっているので必ず新しいバージョンを使うようにします。モデル保存時に100行くらいの警告が標準出力に出てきて、とてもうざいです。GitHubcuda-convnet2のカーネルを使う実装です。ccn2でインストールできます。cuda-convnet2のコードは含まれているため別途インストールする必要はありません。(fbcunnは除く..)これらのカーネルは、torch標準とはTensorのフォーマットが違います。nn.Transpose()で軸を入れ替えてから使います。CUDA&バッチモードにしか対応していません。フィルタの数は16の倍数、バッチの数は32の倍数、などの制限があります。自分は主にこれを使っています。nn.SpatialConvolutionCuFFTfacebookが公開した実装です。fbcunnに入っています。カーネルが大きい場合は、とても速いらしいですが、小さなカーネル(流行りの3x3など)の場合はcudnnやcuda-convnet2のほうが速いです。BlackやK40などメモリが多いデバイスでないと大きなモデルが学習できないことがあるようです。他にもありますが、上のやつだけ把握していればいいように思います。GitHubに各実装のベンチマークがあります。画像関係image.loadで読み込んだ画像の各画素は0.0-1.0にスケールされています。0-255ではありません。image.display()image.display()で画像が表示できると書いてありますが、thコマンドではできません。qluaコマンドを使うとqtが使えるようになっていて、image.display()などが使えます。qluaはluajitと異なるバナーが表示され、luaの実装が違う?ようなので学習など重要な処理には使わないほうがいいと思います。image.display()は明るさを勝手に調節するため、画像処理結果の確認はimage.save()で保存してから見たほうがいいです。image.croptorch.Tensorの添字は1オリジンですが、どうもimageモジュールの一部は0オリジンで処理されているところがあるようです。image.cropもx/yは0から始まっているように見えます。image.rotatethetaの符号が逆?領域外は黒(0)で塗られます。augmentationなどで使う場合は、可能なら背景を0にするか、不可能なら広めに取った領域を回転させたあと領域外を含まない範囲でcropするのがいいと思います。width)のTensorで定義して画像を変換する関数です。大概の変換処理はこの関数でできますが、変換用のデータを自分で計算する必要があります。いまのところbicubicに対応しているのはこの関数だけなので、rotateやscaleを使わずこの関数を使っている方が多いようです。使い方は、https://github.com/torch/image/blob/master/test/test_warp.luaこれも0オリジンだと思います。使って画像の表示等を行うと書いてありますが、現在メンテされておらずバグっていて動かないという話なので無視しましょう。開発側としてはiTorchに移行したいようです。optimconfigoptim.sgd()にlearningRateなどの設定を渡しますが、このテーブルはただ設定を受け取るだけはなく、次の更新時に使うパラメーター等が書き込まれます。0.9})のようにリテラルや一時変数で渡してしまうと、momentumやlearningRateDecayの計算ができなくなってしまいます。学習中生存している変数を介して渡すようにします。momentumになると書いてありますが、一般的な実装とは違うようです。この問題が上がったあとoptim.nagが追加されたのでNAGを使いたい場合はこちらを使ったほうがいいようです。torch.setdefaulttensortype一部のチュートリアルでは、CUDAを使う場合はデフォルトをCudaTensorにすると書いてありますが、それをやるといろいろなところがバグるためしてはいけません。CudaTensorはまだFloatTensorと完全な互換性がありません。努力はしているようです。GitHubデフォルトはDoubleTensorですが、Floatで十分なので(どうせCUDAはFloatしか使わない)、FloatTensorにするのがオススメです。必要なメモリが半分になり処理も速くなります。torch.manualSeedCUDAを使っているときは、cutorch.manualSeedも設定します。便利情報torchサイアクだという印象を残して終わらたないために、最後に便利情報を載せます。Caffe関連Caffeうらやましい!と思うところはだいたい取り込まれています。modelをtorchのモジュールに変換して読み込めます。GitHubはcaffeをtorchのモジュールとして使います(caffeのインストールが必要です)。Challengeの成果が非常に参考になります。model[4]の実装例があります。OverFeatの実装例があります。Workshopにあります。あとオレのCIFAR-10のコードも参考になります。22:11Torch7の分かりにくい話Tweet広告を非表示にするもっと読むコメントを書く2015-01-06Torch7で最近傍探索のベンチマーク最近、Torch7で最近傍探索を繰り返し行いたかったけど、すごく遅いのでは??という不安があったのでk-NN(k=1)でベンチマークしてみた。初めは難しいことは考えず、パッと思いついた方法を試してみる。95.11s95.11秒だった。正解率は97.23%。世の中にはMNISTをk-NNしてみたら数時間かかったとか言っている人も散見されるので、そう考えると速い気もする。行列の積)で計算すればもっと速くなるだろうと思ったので変更してみた。12.41s12.41秒だった。