conta's diary

思ったこと、やったことを書いてます。 twitter: @conta_

3分で分かるDeep Learningの “Dark Knowledge"

最近Deep Learning界隈で話題のDark Knowledgeについて。

Deep Learningの教祖、Hinton先生がとあるところで”Dark Knowledge”というタイトルで発表されていました。 最初タイトルを見た時に、やばい、黒魔術的な何かか?!中二病的な何かか!と思いました笑
“Don’t be evil”なんてなかったんや。。。 というわけではなく、翻訳するとおそらく”隠れた知識”や”影の知識”になるのではないかと思います。(多分狙ってると思いますが)
面白そうだったので3分で理解できる範囲でざっとまとめてみます。

コンセプト

Deep Learningでクラス分類の学習をする際、一般的にアウトプットとしてSoftmax関数が利用されます。 学習器のアウトプットおける、Softmaxの最大値が指し示すものが推定されたクラスになります。 このSoftmax関数によるアウトプットには分類をする以外の能力(Softmaxのアウトプットに現れる何らかの相関関係)があり、 その性質をうまく利用することで、学習するネットワークをより小さく(より少ないパラメータで)、 少ない学習データセットでも高い性能を発揮できる、とのことです。

f:id:contaconta:20141204013458p:plain

例えば、(いぬ、ねこ、...、くるま)のクラスを持った画像の識別器を作ったとします。 その識別器の "ねこ" の出力は、"くるま” の出力よりも見た目の近い ”いぬ” の出力に何らかの相関が現れそうだなーという気がしますよね。
”くるま” と ”ねこ” よりも ”いぬ” と “ねこ" の方が似ている、といった なんらかの半教師的な情報の有効活用しよう、というのが今回のコンセプトだと思います。 (こういった本来のタスクでない隠れた知識のことを”Dark Knowledge”と読んでいるのでしょうか)

どうやるの?

Soft targets(?)という考え方を導入します。

通常のSoftmax関数を利用したロス関数{ \displaystyle Loss^{hard} }は下記のようになります。

{ \displaystyle
p_i =   \frac{exp \left( x_i  \right)} { \sum_{k=1}^{N} exp \left( x_k  \right)}
}

{ \displaystyle
Loss^{hard} = -\sum_{k} y_k \log{  \left(p_i  \right) }
}

*ここで { \displaystyle y_k} は 正解なら1, 不正解なら0 をとる。

一旦上記を学習した後、ここで得た出力から各クラスにおけるSoftmax出力の アンサンブル平均をとって、

{ \displaystyle
p_i(T) =   \frac{exp \left( \frac {z_i} {T}  \right)} { \sum_{k=1}^{N} exp \left( \frac{z_k} {T}  \right)}
}

を計算し、ラベルデータと見立てることで下記のロスを計算します。

{ \displaystyle
Loss^{soft} = -\sum_{k} p_k(T) \log{  \left(p_i   \right) }
}

*ここでTは“temperature”と呼ばれるパラメータ。クロスエントロピーの調整に使う。

これによって先ほどの理論を実現します(たぶん)。

実際どうなの?

MINST(数字認識)のデータセットでの実験では Dark knowkedge を使うとDropoutを使わなくても同等の性能を出すことができたそうです。 (しかも、ネットワークのパラメータの数も少なくできている) また、”3”のデータを抜きでネットワークの学習をした後、バイアスを調整しただけで98.6%の性能を出せたそうです。 (つまり、"3"というデータを一度も見ることなく"3"を認識できたということ?)

まとめ

Soft targets area a VERY good regularizer

だそうです。(嘘書いてたらごめんなさい)

いろいろ応用が効きそうなアイディアですね。 でも実際にやるとなると色々と大変そう。
(Deep Learningのパラメータ職人による”Dark Knowledge”が必要な気がします)

もっと詳しく知りたい方は、Dark Knowledge を読んでみてください٩(๑❛ᴗ❛๑)۶ そして詳しいところご教授お願いします(´・ω・`)

Ubuntu 14.04 のinstall用USBメモリーをMacで作成する

公式ページからisoをDLする

convertする

hdiutil convert ubuntu-14.04.1-server-amd64.iso -format UDRW -o ubuntu-14.04.1-server-amd64.img

deviceの一覧からインストールしたいUSBメモリーを見つける

diskutil list

アンマウントする

自分の場合、/dev/disk2がUSBメモリーだった

diskutil unmountDisk /dev/disk2

書き込む

sudo dd if=ubuntu-14.04.1-server-amd64.img.dmg of=/dev/rdisk2 bs=4m

あとはマシンにUSBメモリーを挿してブートするだけ

Nvidia CUDA 6.0をUbuntu12.04にインストール

debを公式サイトからダウンロード

CUDA DownloadsからUbuntu12.04を選択してダウンロード

wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1204/x86_64/cuda-repo-ubuntu1204_6.0-37_amd64.deb

登録

sudo dpkg -i cuda-repo-ubuntu1204_6.0-37_amd64.deb 
sudo apt-get update

install cuda toolkit

sudo apt-get install cuda

PATHを通す

~/.zshrcや~/.bash_profile等に下記を追加

export CUDA_HOME=/usr/local/cuda-6.0
export LD_LIBRARY_PATH=${CUDA_HOME}/lib64
export PATH=${CUDA_HOME}/bin:${PATH}

再起動

これ大事。

sudo reboot

確認

サンプルコードをビルドして動かしてみる。

cuda-install-samples-6.0.sh  ./
cd NVIDIA_CUDA-6.0_Samples 
make -j

あとは適時生成されたバイナリを実行してみましょう。

これで快適CUDA生活(´・ω・`)b

Boost.Pythonで自作モジュールを呼び出すときにエラーが出る問題の解決

Boost.Pythonc++で書いたモジュールをPythonで使った時に発生した問題の解決策メモ

環境

  • Mac OSX 10.9
  • python 2.7.6 (brewでインストール)
  • boost 1.55.0

エラー内容

モジュールをインポートして、自作関数を呼ぶと、abortでPythonが落ちる

Fatal Python error: PyEval_SaveThread: NULL tstate

というエラー

エラーが起きるまで

ビルド設定

.
.
.
FIND_PACKAGE(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
message(STATUS " python includes dir: ${PYTHON_INCLUDE_DIRS}")
message(STATUS " python libs: ${PYTHON_LIBRARIES}")
.
.
.

Cmakeした時のログ。

--  python includes dir: /System/Library/Frameworks/Python.framework/Headers
--  python libs: /usr/lib/libpython2.7.dylib

あれ、おかしい。デフォルトのPython使ってる。

動かしてみる。

Fatal Python error: PyEval_SaveThread: NULL tstate
[1]    52771 abort      python

なんかHomebrewでインストールしたPythonだとfind_package(PythonLibs)がうまく働かないみたい。 cmake find_package(PythonLibs) broken with brewed python on 10.9 · Issue #25118 · Homebrew/homebrew · GitHub

このエラーは、実行環境と違うPythonライブラリ(Macに入ってるデフォルトのPythonとHomebrewでインストールしたPython)がはいってると起きるらしい。(ソースがどこかわからなくなった。。。

とりあえずの解決策

無理やりパスを通してあげましょう。

set(PYTHON_INCLUDE_DIRS "/usr/local/Cellar/python/2.7.6_1/Frameworks/Python.framework/Versions/Current/include/python2.7/")
set(PYTHON_LIBRARIES "/usr/local/Cellar/python/2.7.6_1/Frameworks/Python.framework/Versions/Current/lib/libpython2.7.dylib")
include_directories(${PYTHON_INCLUDE_DIRS})
message(STATUS " python includes dir: ${PYTHON_INCLUDE_DIRS}")
message(STATUS " python libs: ${PYTHON_LIBRARIES}”)

とりあえず動きました。 Homebrewで入れたPythonはなかなか使いにくい(´・ω・`)

MacにMongo c++ driver をインストール(brewで)

昔はインストールしたりリンクしたりするのが すごくめんどくさかったけど(sconとかインストーラのバグとか)、今はbrewで簡単にインストールできるみたいだ。 なんか2.5.xになってDocumentもかっこよくなってきてるしね。

環境

  • Mac OSX 10.9
  • mongo 2.5.5
  • libmongoclient 2.5.4
  • boost 1.55.0

インストール

install mongodb

brew install mongo

これで実はlibmongoclient.aができてる。 しかしながら自分でboost libraryをインストールしているのであれば、 リンクする際にエラー祭りが発生してビルドエラーになるので、libmongoclientを別で入れてあげる。(Mongoのソース中にBoostのコードが一部入ってる?らしい、それでコンフリクトが起きちゃってるのではないかと)
*ちなみにソースからインストールする場合は --external的なオプションでboostのパスを指定すればOKだった気がする。今回はbrewのみでインストールすることが目的なのでスルーします。

install c++ driver

brew install libmongoclient

途中で、下記のように怒られる。

Warning: Could not link libmongoclient. Unlinking...
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
You can try again using `brew link libmongoclient'

なので、こんな感じで上書きしましょう。

brew link libmongoclient --overwrite

これで、/usr/local/libの中にlibmongoclient.alibmongoclient.dylibができてる。

ls -la /usr/local/lib/ |grep libmongoclient
libmongoclient.a -> ../Cellar/libmongoclient/2.5.4/lib/libmongoclient.a
libmongoclient.dylib -> ../Cellar/libmongoclient/2.5.4/lib/libmongoclient.dylib

これで快適Mongo生活++

Pythonのmultiprocessing.PoolでExceptionを受け取る

Pythonで並列にいろいろ処理させたいなと思い、multiprocessing.Poolをつかってプログラムを作っていたらぶち当たった問題。

下記のコードを動かしていた、実はバグあり。

出力は

start main
end main

??おかしい。本当ならworkerのprint関数が実行される、はず。

実は

res = pool.apply_async(worker, (i))

じゃなくて

res = pool.apply_async(worker, (i,))

じゃないといけない。引数をタプルとして認識してくれないのが原因だ。

修正してみる。

出力は

start main
worker i: 0
worker i: 1
worker i: 2
worker i: 3
worker i: 4
worker i: 5
worker i: 6
worker i: 7
end worker
end worker
end worker
end worker
end worker
end worker
end worker
end worker
end main

おー、治った。 しかしながら、エラーがわからん!!

困った、Exception出して欲しいよ(´・ω・`)

ちょっとWorkerでException投げてテストしてみる。 i == 6の時に例外を投げる。

出力

start main
worker i: 0
worker i: 1
worker i: 2
worker i: 3
worker i: 4
worker i: 5
worker i: 6
worker i: 7
end worker: 1
end worker: 2
end worker: 3
end worker: 0
end worker: 4
end worker: 5
end worker: 7
end main

うん、正常に動いて、ないね。6番が抜けてるけど、Exceptionはスルー。 困った。 教えて、すたっくおーばーふろー先生。

python - Exception thrown in multiprocessing Pool not detected - Stack Overflow

16.6. multiprocessing — Process-based “threading” interface — Python v2.7.6 documentation

なるほど、AsyncResult.get()という関数を使うと例外が投げられるのね

get()を呼んでみる。

start main
worker i: 0
worker i: 1
worker i: 2
worker i: 3
worker i: 4
worker i: 5
worker i: 6
end worker: 1
end worker: 0
worker i: 7
end worker: 2
end worker: 5
end worker: 3
end worker: 4
end worker: 7
end main
Traceback (most recent call last):
  File "pool_test_4.py", line 30, in <module>
    main()
  File "pool_test_4.py", line 26, in main
    res.get()
  File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 554, in get
    raise self._value
Exception: help me! 6

おー、でたでた! res.get()、覚えておこう。 これで快適multiprocessing生活(・∀・)

FlaskとPILImageを使ってリサイズした画像をResponseする

Webの画像をサムネイルにして表示したい!
ファイルシステムからの画像の読み書きは情報いっぱいあるんだけど、
メモリ上にキャッシュして処理したかったのでやってみた。

やりたいこと

  • 画像をリサイズしてサムネイルをつくりたい
  • Webから撮ってきた画像をファイルに書き出すことなくレスポンスを作りたい(メモリ上にキャッシュしたい)
  • Flaskでレスポンスを返したい

方法

1. StringIOを使って画像のバイナリを受け取る

url = 'http://www.google.co.jp/intl/ja_jp/images/logo.gif'
buffer = urllib2.urlopen(url).read()
img = Image.open(StringIO(buffer))

2. 画像をリサイズしてStringIOに渡す

size = (120, 75)
img.thumbnail(size)
buf = StringIO()
img.save(buf, 'png')

3. レスポンスを作る

response = helpers.make_response(buf.getvalue())
response.headers["Content-type"] = "Image"
return response

コードはGithubに
contaconta/FlaskPILImageThumbnailExample · GitHub

*参考
Python Imaging Library Handbook