pix2pix(GAN)を使ってモノクロのおそ松くんをカラー画像にしてみた

前半に着色結果
後半にpix2pixの導入方法、学習方法
という構成になっている。手っ取り早く導入したいならば、「作業内容」からみるのがオススメ。

概要

清水さんのブログにてpix2pixが紹介されていて面白そうだったので試してみた。
GANのパラメータを自動で修正させることで、汎用的に画像→画像変換ができるようになったものらしい。(まだ論文読んでないから正しくないかも・・・・)
shi3zの長文日記

githubに公開されているpix2pixを使えば、簡単に自分のデータセットを学習させられそうだったので、今回は、おそ松さん(2015年放送)のカラー画像を学習して、おそ松くん(1965年放送)の白黒画像を着色してみる。
もう時代遅れ(?)なのかもしれないけれど。同じような絵柄でカラー、白黒が存在するから、学習しやすそうかなぁと。

結果

まず最初に結果から。
完璧というわけではないけれど、結構自然に着色できた。

とりあえず、平均的なものを評価してみる。

人はある程度自然に着色されている。
着色度合いがなんとなく古臭い。何故w
よく見ると木目が緑だったり、腕に緑が入っていたりして、破綻している部分も。
f:id:t_nkb:20161126113044p:plainf:id:t_nkb:20161126112731p:plain
f:id:t_nkb:20161126113253p:plainf:id:t_nkb:20161126112636p:plain
f:id:t_nkb:20161126113240p:plainf:id:t_nkb:20161126112839p:plain
f:id:t_nkb:20161126114011p:plainf:id:t_nkb:20161126113931p:plain

人工物

建物や室内もそれっぽい。
まぁ何色塗ってもそれっぽくなる気もするが・・・。
f:id:t_nkb:20161126113057p:plainf:id:t_nkb:20161126112803p:plain
f:id:t_nkb:20161126113051p:plainf:id:t_nkb:20161126112749p:plain

その他

この着色とか、おそ松くんっぽいビビットな色合いが出てる。
本当は全体にわたってこんな色合いになって欲しかった・・・。
f:id:t_nkb:20161126113108p:plainf:id:t_nkb:20161126112853p:plain

(追記)漫画のカラー化もしてみた

これなら漫画の着色もできるのでは?ということで、ソーマの白黒ーカラー画像でも同様に学習させてみた。
150枚の白黒ーカラー画像を学習させて、別のソーマ画像に着色。ちょっとパラメータいじって、学習の解像度は2倍にしてある。
かなり自然な色付けに見える・・・。
f:id:t_nkb:20161203165222j:plainf:id:t_nkb:20161203165230j:plain

作業内容

ということで、この結果に至るまでの作業内容を記載する。
作業環境は、GTX1070,ubuntu16.04となる。

torchのインストール

基本以下に書いてるとおりに実行するだけ
Torch | Getting started with Torch

gitから取ってきて
$ git clone https://github.com/torch/distro.git ~/torch --recursive

インストール(結構時間がかかる)
$ cd ~/torch; bash install-deps;
$ ./install.sh

最後にパスを追加するか?と聞かれるので、yesと入力

$ source ~/.bashrc

thコマンドを打っていかが表示されるようならインストール成功。

$ th

______             __   |  Torch7 
/_  __/__  ________/ /   |  Scientific computing for Lua. 
/ / / _ \/ __/ __/ _ \  |  Type ? for help 
/_/  \___/_/  \__/_//_/  |  https://github.com/torch 
                        |  http://torch.ch 

pix2pixを導入

基本は以下参照
GitHub - phillipi/pix2pix: Image-to-image translation using conditional adversarial nets


言われるがままに、nngraphとdisplayを入れる

$ luarocks install nngraph
$ luarocks install https://raw.githubusercontent.com/szym/display/master/display-scm-0.rockspec

pix2pixをclone

$ git clone https://github.com/phillipi/pix2pix.git
#公式では以下だけど、このままではエラーになる。
#git clone git@github.com:phillipi/pix2pix.git

$cd pix2pix

まずはサンプルのデータセットをダウンロードして実行してみる。

$ bash ./datasets/download_dataset.sh facades
$ DATA_ROOT=./datasets/facades name=facades_generation which_direction=BtoA th train.lua

学習が進んでいるところがターミナルで見えたら、ctrl+cでストップしてOK。

オリジナルデータセットを学習させる

ダウンロードしてきた、サンプルのデータセットを見るとこんな感じ。
なるほど。256*256の画像をbefore,afterで並べりゃいいのね、お手軽。
f:id:t_nkb:20161126114750j:plain

ということで、
1.ネットからおそ松さん画像200枚を集めてきて
2.256*256にリサイズして
3.グレースケール化して
4.2つの画像を並べてひとつの画像にする
としたものがこれ。

f:id:t_nkb:20161126115028p:plain
f:id:t_nkb:20161126115053p:plain
f:id:t_nkb:20161126115127p:plain

この画像を、先ほどの./datasets/facades/trainの中身と入れ替えて(入れ替えなくても以下引数を変えればいいんだけど・・・。)学習させる。

(追記)
論文読むと、バッチサイズを増やせるなら増やしてもいい模様。
train.luaのbatchSize行を増やすとより早く計算が進む。
今回は論文の推奨通り、4に増やしてみた。これでエラーが出て学習が進まないようなら、1に戻すこと。

batchSize = 1,
↓ こう変更
batchSize = 4,

DATA_ROOT=./datasets/facades name=facades_generation which_direction=AtoB th train.lua

GTX1070で2時間程度まつと学習が完了する。

(追記)
学習中、別ウィンドウで以下を起動し、ブラウザから以下URLにアクセスすることで、実行過程を見ることができる。

th -ldisplay.start 8000 0.0.0.0

http://0.0.0.0:8000



テストデータを作って結果を見る

その間にテストデータを作る。
今回は結果を見たいだけなので、ソースコードはいじらない方針。
1.ネットからおそ松くん画像(白黒)を集めてきて
2.256*256にリサイズして
4.同じ画像を2つよこに並べる

出来たものはこんな感じ。
f:id:t_nkb:20161126115725p:plain
f:id:t_nkb:20161126115709p:plain

これを./datasets/facades/varの中身と入れ替えて、以下のコマンドを打つと、./resultsフォルダに結果が格納される。

$ DATA_ROOT=/path/to/data/ name=expt_name which_direction=AtoB phase=val th test.lua

感想

結果は上記の通り。
学習時間除けば、実作業1〜2時間でここまで出来てしまう。
いやぁ、時代の進歩って怖い・・・。
取り残されないように、ソースコードと論文でも読みますか。。。。

英語論文の文末を整形し、スムーズにGoogleに翻訳させる(javascript版)

概要

Google翻訳の精度は大幅に向上したが、論文をコピペして翻訳しようとすると文末、行末の"-"や改行のせいで、まともに翻訳できない

Google翻訳が理解できるよう、翻訳前に成形するスクリプト書いた!便利!

javascript
pythonだと、いちいちファイル開かなければいけないため面倒なので、せめてブラウザ上で完結させてみた。
初めてjavascript使ったけど、携帯からポチポチ打って試したら出来てしまった。簡単だし、結構便利かも。

以下の整形前英文入力欄に英文を入力すると、下に整形後の英文が出力される。
ここで出力された英文をGoogle翻訳に突っ込めば、まともな翻訳文をgetできる。

Google 翻訳

2017/09/10
翻訳がおかしな単語を最初に置換できるようにしてみた。


文末整形スクリプト

整形前英文入力

オリジナル置換語句(before)←→(after) (before)←→(after)




整形後文章




実装内容

実装内容は以下リンク(python版)と同様
改行記号を消して、"-"を見つけて文頭と繋げているだけ。
officeのマクロでもできるけど、いちいちoffice使わなくても良い点がメリット。
英語論文の文末を整形し、スムーズにGoogleに翻訳させる(python版) - 技術メモ集




英語論文の文末を整形し、スムーズにGoogleに翻訳させる(python版)

概要

以下リンクの通り、Google翻訳の精度は大幅に向上したが、論文をコピペして翻訳しようとすると "-" や改行のせいで、まともに翻訳できない

Google翻訳が理解できるよう、翻訳前に成形するスクリプト書いた!便利!

やったことはしょぼしょぼだけど、翻訳がかなり使いやすくなる。

Google翻訳APIは有料なので、自分でコピペして翻訳させるしかない。
#本当はクリップボードの文章そのまま整形したいけど、マルチプラットフォーム対応が面倒・・・・。

t-nkb.hatenablog.com


(2016/11/22)
javascript版も作った。
こっちだとブラウザ内で完結するので、使うならばこちらがおすすめ。
t-nkb.hatenablog.com


うまく翻訳できない例

例えば、以下の論文を例にあげて、翻訳を確認してみる。
https://arxiv.org/pdf/1312.5602.pdf

上記のアブストをそのままコピペしてみると以下のような形になる。

【コピペ英文】
We present the first deep learning model to successfully learn control policies di-
rectly from high-dimensional sensory input using reinforcement learning. The
model is a convolutional neural network, trained with a variant of Q-learning,
whose input is raw pixels and whose output is a value function estimating future
rewards. We apply our method to seven Atari 2600 games from the Arcade Learn-
ing Environment, with no adjustment of the architecture or learning algorithm. We
find that it outperforms all previous approaches on six of the games and surpasses
a human expert on three of them.


これをそのまま翻訳させると・・・・


【コピペ翻訳文】
我々は、制御ポリシーを正しく学習するための最初の深い学習モデルを提示する。
強化学習を用いて高次元の感覚入力から直腸にザ
モデルは畳み込みニューラルネットワークであり、Q-learningの変種で訓練され、
その入力は生のピクセルであり、その出力は将来を予測する価値関数である
報酬。アーケード学習の7つのAtari 2600ゲームに本手法を適用し、
アーキテクチャーや学習アルゴリズムを調整する必要はありません。我々
6つのゲームとそれを上回るすべての先のアプローチよりも優れていることがわかります
そのうちの3人の人間の専門家。


うん、いまいち。「感覚入力から直腸にザ」ってなんだ。
ここでの問題点は2点。Google翻訳は、
・改行=文の区切りと判断する
・-で前後の行にわかれた単語を解釈しない
という仕様になっているため、改行周りでバグっていることが原因。
数行なら手でつなげればいいけど、長文になるとやってられん。

改善

ということで、ハイフンと改行を見つけて文章をつなげてみた。
以下スクリプトをtrans.py等として保存し、同じ場所に"before"というファイルを作り、その中に論文の内容をコピペ→スクリプトを起動することで、afterに整形された文章が出てくる。

#! /usr/bin/python
# -*- coding:utf-8 -*-

if __name__ == '__main__':
    f = open('before', 'r')
    fw = open('after', 'w')
    for row in f:
        row = row.replace('-\n','')
        row = row.replace('\n',' ')
        fw.write(row)
    f.close()
    fw.close()

整形された文章がこちら。
わかりやすいように自動改行させない形で表示してみた。
これを見るとちゃんと一文として繋がっていることがわかる。

【整形後英文】
We present the first deep learning model to successfully learn control policies directly  from  high-dimensional  sensory  input  using  reinforcement  learning.   The model  is  a  convolutional  neural  network,  trained  with  a  variant  of  Q-learning, whose input is raw pixels and whose output is a value function estimating future rewards. We apply our method to seven Atari 2600 games from the Arcade Learning Environment, with no adjustment of the architecture or learning algorithm. We find that it outperforms all previous approaches on six of the games and surpasses a human expert on three of them .

これを翻訳させてみると・・・。

【整形後翻訳文】
我々は、強化学習を用いて高次元の感覚入力から制御ポリシーを直接学習するための最初の深い学習モデルを提示する。モデルは畳み込みニューラルネットワークであり、その入力は生のピクセルであり、その出力は将来の報酬を推定する価値関数である、Q学習の変形で訓練されている。アーケード学習環境の7つのAtari 2600ゲームにこの方法を適用し、アーキテクチャや学習アルゴリズムは調整しません。 6つのゲームでこれまでのすべてのアプローチよりも優れていることがわかり、3つのゲームでは人間の熟練者を上回ります。


わかる、わかるぞっ!!
ということで、便利になりましたよと。

CNN学習時のDropoutの比率(DropoutRatio)についての知見

背景

つくばチャレンジにて、CNN、SlidingWindowを応用して、看板検出を行った。
今回は、学習時のDropout率をどう変えたらいいかについての知見をまとめる。
この辺りの小細工は当たり前に思いつくことだが、あまりまとめられていないように思う。

t-nkb.hatenablog.com

Dropoutの比率による正答率の変化

Dropoutの比率は大きければ大きいほど、モデルのロバスト性が上がると一般的には言われている。
当初は、その言葉を信じて各層に70%Dropoutさせて学習を進めていたが、全く正答率が上がらず困惑していた。
そこで、諦めてDropoutの比率を30%としたところ、急激に学習が進んだ。

Dropout70%、30%の学習結果を以下に示す。
2値分類の学習結果なので、Dropoutを70%とすると正答率は50%前後を推移しており全く学習が進んでいない、それに対し、Dropoutを30%とすると急速に学習が進んでいるのが見て取れる。

f:id:t_nkb:20161113120236p:plain

学習済みモデルに対し、Dropoutを増やして再学習させる

上記実験で、Dropout比率を下げることで学習が一気に進む場合があることがわかった。
しかし、”Dropoutの比率は大きければ大きいほど、モデルのロバスト性があがる”のならば、Dropoutの比率をさらに増やしたいと思うのが親心。
そこで、Dropout 30%で学習済みのモデルを使って、Dropout 70%で再学習してみた。
この再学習の学習結果を以下に示す。ここでは、上記実験でのDropout30% エポック20のモデルを使って再学習をさせている。

この結果を見ると、最初からDropout70%で学習させると全く学習しなかったものが、再学習ではしっかりと学習し、正答率100%近くまで上がっていることがみて取れる。
考察するに、Dropout比率を下げて学習させることで、autoencoderと同様の効果が得られているのだろう。

また、Dropout30%のものと、Dropout70%で再学習させたものを動画で比較すると、70%のものの方が、誤検知率が低く、優秀なモデルとなっていることが確認できた。

f:id:t_nkb:20161113120240p:plain

まとめ

Dropoutは最初は少なめで学習させる方が効率が良い。学習が進まないのならば、まずはDropoutを消して試してみる。
Dropoutを増やしたいのならば、ある程度学習させた後で増やすこと。収束に時間はかかるが、Dropoutを増やすと確かにロバスト性は上がる。

google翻訳が進化しすぎていてやばい

GOOGLE翻訳がDeepLearningで大幅に精度向上したと聞いて、試してみた。
結果としてはかなり使える!!!
英語の苦手な僕にとって、これまで英語論文の購読がストレスのもとだったけれど、これで大分緩和されそう。

nlab.itmedia.co.jp

SPP-NETの原文を翻訳させてみる

原文はここから引用しています。内容自体もなかなか面白いけれど、今回の論点はそこではない。
https://arxiv.org/pdf/1406.4729v4.pdf

例えば上記論文のアブストを訳してみると・・・

"""
Existing deep convolutional neural networks (CNNs) require a fixed-size input image. This requirement is “artificial” and may reduce the recognition accuracy for the images or sub-images of an arbitrary size/scale.
In this work, we equip the networks with another pooling strategy, “spatial pyramid pooling”, to eliminate the above requirement. The new network structure, called SPP-net, can generate a fixed-length representation regardless of image size/scale.
Pyramid pooling is also robust to object deformations. With these advantages, SPP-net should in general improve all CNN-based image classification methods. On the ImageNet 2012 dataset, we demonstrate that SPP-net boosts the accuracy of a variety of CNN architectures despite their different designs. On the Pascal VOC 2007 and Caltech101 datasets, SPP-net achieves state-of-the-art classification results using a single full-image representation and no fine-tuning.
The power of SPP-net is also significant in object detection. Using SPP-net, we compute the feature maps from the entire image only once, and then pool features in arbitrary regions (sub-images) to generate fixed-length representations for training the detectors. This method avoids repeatedly computing the convolutional features. In processing test images, our method is 24-102 faster than the R-CNN method, while achieving better or comparable accuracy on Pascal VOC 2007.
In ImageNet Large Scale Visual Recognition Challenge (ILSVRC) 2014, our methods rank #2 in object detection and #3 in image classification among all 38 teams. This manuscript also introduces the improvement made for this competition.
"""

エキサイト翻訳の場合

この文章をエキサイト翻訳にかけるとこうなる。
申し訳ないけれど、これなら原文をそのまま読んだほうがいいレベル。

"""
既存の深い渦巻き状のニューラルネットワーク(CNNs)は固定サイズインプットイメージを必要とする。この要件は「人工的で」、任意のサイズ/スケールのイメージまたはサブイメージのための認識精度を減らすことができる。
この仕事において、私達は、上記の要件を取り除くために、別の水たまりを作っている戦略、「空間のピラミッド水たまりを作り」をネットワークに装備する。イメージサイズ/スケールを問わず、新しいネットワーク構造〈SPP-ネットと呼ぶ〉は、固定長表現を生成できる。
ピラミッドに水たまりを作ることは、また、反対する 変形 ために頑強である。これらの利点によって、SPP-ネットは、一般改善 すべてのCNNベースのイメージ分類方法 においてするべきである。ImageNet 2012データセットにおいて、私達は、それらの種々のデザインにもかかわらずSPP-ネットが各種のCNNアーキテクチャの精度を押し上げるのを証明する。パスカルVOC 2007とCaltech101データセットにおいて、SPP-ネットは、単一の完全イメージ表現と微調整を全然使わず最先端の分類結果を達成する。
SPP-ネットのパワーはまた、オブジェクト検出において重要である。SPP-ネットを使うことによって、私達は、全体のイメージから機能マップをほんの1回計算し、それから、検出器を訓練するための固定長表現を生成するために、任意の地域(サブイメージ)の機能に共同出資する。この方法は、繰り返し渦巻き状の機能を計算することを避ける。テストイメージを処理する時に、私達の方法は、パスカルVOC 2007のよりよいまたは同等の精度を達成する間、R-CNN方法より速く24-102である。
ImageNetの大きなスケールビジュアル認識挑戦(ILSVRC)2014において、私達の方法はすべての38のチームの間のイメージ分類でのオブジェクト検出と#3において#2をランク付けする。この原稿は、この競争のために作られた改良も導入する。
"""

GOOGLE翻訳の場合

この文章をGOOGLE翻訳に読ませるとこうなる。
自然すぎて感動する。論文でかっちりした文章だから相性がいいのだろうか?これなら、原文そのまま読むより、まずは翻訳させたものを読んで概要を掴めそう。
いやほんと、技術はどんどん進歩しているなぁ。GOOGLE翻訳にも手伝ってもらいながら、少しでもピックアップしなきゃ。

"""
既存の深い畳み込みニューラルネットワーク(CNN)は、固定サイズの入力画像を必要とする。この要件は「人工的」であり、任意のサイズ/スケールの画像またはサブ画像の認識精度を低下させる可能性がある。
この作業では、上記の要件を排除するために、ネットワークに別のプーリング戦略「空間ピラミッドプーリング」を装備しています。 SPP-netと呼ばれる新しいネットワーク構造は、画像サイズ/スケールに関係なく固定長表現を生成することができます。
ピラミッドプーリングは、オブジェクトの変形に対しても堅牢です。これらの利点を利用して、SPP-netは一般にすべてのCNNベースの画像分類方法を改善すべきである。 ImageNet 2012のデータセットでは、SPP-netがさまざまな設計にもかかわらず、さまざまなCNNアーキテクチャの精度を向上させることを実証しています。 Pascal VOC 2007およびCaltech101データセットでは、SPP-netは単一のフルイメージ表現を使用し、微調整は行わず最先端の分類結果を達成します。
SPP-netの機能は、オブジェクト検出においても重要です。 SPP-netを使用して、画像全体から特徴マップを1回だけ計算し、特徴を任意の領域(サブ画像)にプールして、検出器を訓練するための固定長表現を生成する。この方法は、畳み込み特徴を繰り返し計算することを回避する。テスト画像の処理では、我々の手法はR-CNN法より24-102速く、Pascal VOC 2007ではより良い精度または同等の精度を達成しています。
ILSVRC(ImageNet Large Scale Visual Recognition Challenge)2014では、我々の方法は物体検出で2位、画像分類で3位、全38チームでランク付けされています。この原稿はまた、この競争のためになされた改善を紹介します。
"""

【つくばチャレンジ2016】DeepLearningを使ってリアルタイム看板検知をしてみた

つくばチャレンジとは

「つくばチャレンジ」は、つくば市内の遊歩道等の実環境を、移動ロボットに自律走行させる技術チャレンジであり、地域と研究者が協力して行う、人間とロボットが共存する社会の実現のための先端的技術への挑戦です。(下記HPから引用)

つくばチャレンジ

大雑把に言うと、遊歩道2kmをロボットに自律走行させるコンテスト。今回、土浦プロジェクトというチーム名でつくばチャレンジに参加し、DeepLearning(CNN)を用いたリアルタイム看板検知を実装したので、その概要を記す。

本ページでは今回開発したシステムの概要を記す。
その内、それぞれの詳細・まとめたソースコードもアップしたいところ・・・。

成果

動画中から特定の物体を検出するシステムを担当し、実装した。
DeepLearningのフレームワークはChainerを使用し、64*64ビットの画像から、対象物の有無・属性を判別するCNNモデルを作成した。画面内の対象物がありうる場所に検知窓をスライドさせ、逐次CNNをかけることで対象を検出している。モデルは試行錯誤しながら最適なモデルを自作した。
以下に検知動画を示す。

人(看板)検知

つくばチャレンジにて本番使用し、4人中2人の人発見に成功。
本番はTK1を使用したため検知速度に限界が有り、2人検知漏れしてしまったが、GTX9xx,GTX10xx等の高速で処理を行えるGPUを使用すれば、ロバストに検知が可能だと考えている。
(少なくとも、これまでのログデータを見る限りは、ほぼ完璧に検知できている)

動画は試験走行のもの(カメラはリコーTHETA)
youtu.be

信号検知

手元確認のみで本番は使用せず。
ある程度はロバスト性がありそうだが、未検証。

動画は試験走行のもの(カメラはwebカメラ
www.youtube.com

コアとなる知見

CNNにてモデルを構築する上で最も問題となるのが、学習データをどう集めるかということ。
基本的には多く集めれば集めるだけ良いが、真面目にやるには、撮影する時間もラベル付をする時間も必要になる。

そんな時間はないので、今回はコーンの全周囲から撮影した10画像を元に、学習データを自動生成するスクリプトを記載し、学習データの大幅な水増しを行った。今回のつくばチャレンジ用には、10枚の元画像から3万枚のコーンの画像を作成して学習をさせている。
このようにしてランダムの背景画像と組み合わせることで、学習データの作成時間削減の他、以下の利点があり、非常に有効だと考えている。

・背景に対する過学習を抑える
・モデルの位置、サイズ等の変化に対するロバスト性の向上
・誤検知した画像を背景に加え、再学習させていくことでモデルの誤検知率を調整可能
・一度スクリプトを組んでしまえば、別の検知対象のモデルが簡単に作れる

特に最後の利点はとても大きく、3時間で看板検知プログラム→信号検知プログラムへの変更が出来た。忙しい現代人にはピッタリ。

と、ここまで書いたが、元となるアイディアは技ラボさんの以下ページです。
認識のさせ方、合成したデータの扱いについてはオリジナルのつもり。
Deep Learningで用いるデータを「生成」してみた | 技ラボ

学習データの作成

看板のみを切り出した透過画像の作成

まずは看板のみを切り出した透過画像を作成する。
以下のサンプルの通り、そこまで真面目に切り出さなくともOK。

f:id:t_nkb:20161107183054p:plain:w100 f:id:t_nkb:20161107183055p:plain:w60f:id:t_nkb:20161107183056p:plain:w70f:id:t_nkb:20161107183114p:plain:w80

学習画像の作成

上記で切り出した透過画像のサイズ・縦横比をランダムに変更させ、ランダムな背景画像に追加する。
ここで大きさ、位置をバラけさせることで、動画内から対象を探す時に、検出窓を重ねなくても済むようになる(=計算コストが非常に下がる。重要!!)
f:id:t_nkb:20161107183222j:plain:w100f:id:t_nkb:20161107183227j:plain:w100f:id:t_nkb:20161107183238j:plain:w100f:id:t_nkb:20161107183210j:plain:w100
f:id:t_nkb:20161107213220j:plain:w100f:id:t_nkb:20161107213207j:plain:w100f:id:t_nkb:20161107212849j:plain:w100f:id:t_nkb:20161107212813j:plain:w100

データオーグメンテーション

作成した学習画像を元に、反転・ガンマ変換・コントラスト変換を行い、画像を水増しする。
また、上記画像を上下左右に数ピクセルずつランダムにずらす、ランダムにノイズを入れる等の小細工も行っている。

1.元画像
f:id:t_nkb:20161107183538j:plain:w300

2.左右反転
定番。
f:id:t_nkb:20161107183632p:plain:w300

3.ガンマ変換
明るさの調整。
明度を変化させたものを学習させることで、モデルのロバスト性を増すことができる。この画像を学習させることで、太陽光に対するロバスト性が大きく増加した。

f:id:t_nkb:20161107183717p:plain:w300f:id:t_nkb:20161107183727p:plain:w300f:id:t_nkb:20161107183732p:plain:w300f:id:t_nkb:20161107183739p:plain:w300

4.コントラスト変換
効果は実感できなかったが、有効だと言われているのでとりあえず入れてみた。
f:id:t_nkb:20161107183752p:plain:w300f:id:t_nkb:20161107183801p:plain:w300

学習

上記で作成した画像を元に、検知対象の有り・無しの2つのラベルの認識を行うモデルを学習させた。
以下にchainerのモデル部分のみを記載する。
大雑把に言うと、畳み込み4層、全結合層3層のCNNモデルとなる。
上記のモデルを元にGTX1070で学習を行うと、およそ1時間程度でtestデータの正答率98%、4時間ほどで99%以上の検知性能のモデルを作成することができた。

このモデルを使って、THETAの全方位画像のうち、看板の有りそうな高さの画像を20分割してそれぞれを64*64にリサイズし、看板が領域内にあるかどうかを識別することでどの方位に看板があるかを検出する。
冒頭の動画で、人の確率90%以上の部分を青枠で囲っているが、これを見ると、探索対象を3人共検知できていることがわかる。(対象に近づき過ぎると検知できなくなるが・・・)

モデル作成時のノウハウ等も公開したかったが、データをまとめるのが大変なのでおいおい・・・。

(少しまとめてみた)
t-nkb.hatenablog.com

if args.lname == "none":
    model = chainer.FunctionSet(conv1=F.Convolution2D(3, pic_size, 5, pad=1),
                                bn1 = F.BatchNormalization(pic_size),
                                conv2=F.Convolution2D(pic_size, pic_size_conv, 5, pad=1),
                                bn2 = F.BatchNormalization(pic_size_conv),
                                conv3=F.Convolution2D(pic_size_conv, pic_size_conv, 7, pad=1),
                                bn3 = F.BatchNormalization(pic_size_conv),
                                conv4=F.Convolution2D(pic_size_conv, pic_size_conv, 7, pad=1),
                                bn4 = F.BatchNormalization(pic_size_conv),
                                
                                l1=F.Linear(1344, 256),
                                l2=F.Linear(256, 64),
                                l4=F.Linear(64, dataset.get_n_types_target()))
else:
    model = pickle.load(open(args.lname,'rb'))


def forward(x_data, y_data, train):
    dropout_ratio = args.drop
    x, t = chainer.Variable(x_data), chainer.Variable(y_data)
    h = F.dropout(F.relu(model.bn1(model.conv1(x),test = not train)),ratio=dropout_ratio,train=train)
    h = F.dropout(F.max_pooling_2d(F.relu(model.bn2(model.conv2(h),test = not train)), 2),ratio=dropout_ratio,train=train)
    h = F.dropout(F.relu(model.bn3(model.conv3(h),test = not train)),ratio=dropout_ratio,train=train)
    h = F.dropout(F.max_pooling_2d(F.relu(model.bn4(model.conv4(h),test = not train)), 2),ratio=dropout_ratio,train=train)
    h = F.dropout(F.spatial_pyramid_pooling_2d(h, 3, F.MaxPooling2D),ratio=dropout_ratio,train=train)
F.dropout(F.relu(model.l1(h)),ratio=dropout_ratio,train=train)
    h = F.dropout(F.relu(model.l2(h)),ratio=dropout_ratio,train=train)
    y = model.l4(h)
    return F.softmax_cross_entropy(y, t), F.accuracy(y, t)

pickleをjoblibに変えて保存データサイズを圧縮!

経緯

以前のエントリで述べたとおり、Pickleで1.9GB以上のデータを保存しようとすると、エラーが出て保存できない問題があった。
この問題を、joblibを使うことでコードをほとんどいじらずに解決できることがわかったので、まとめておく。

t-nkb.hatenablog.com

joblibを使ったデータの圧縮保存方法

導入

いつもどおりpip

sudo pip install joblib

import

これまたいつも通りimport

import joblib

保存

dump部分は以下の通り書き換える。
pickleをjoblibに変更して、最後の引数をcompress=3に変更するだけでOK
compressは圧縮率を示し、0〜9まで指定できるようだが、とりあえずは3で充分。
pickleではエラーが出て保存できなかったデータが580MBまで圧縮されて保存できたことから、画像であれば1/4以下に圧縮できることがわかる。

(WAS)
pickle.dump((self.X_train,self.X_test,self.y_train,self.y_test,self.index2name), open(self.dump_name, 'wb'), -1)

(IS)
joblib.dump((self.X_train,self.X_test,self.y_train,self.y_test,self.index2name), open(self.dump_name, 'wb'), compress=3)

読み込み

読み込みもpickleをjoblibに書き換えるだけでOK。

(WAS)
self.X_train,self.X_test,self.y_train, self.y_test, self.index2name = pickle.load(open(self.dump_name, 'rb'))

(IS)
self.X_train,self.X_test,self.y_train, self.y_test, self.index2name = joblib.load(open(self.dump_name, 'rb'))