Pylearn2 で Maxout + CNN(Convolutional Neural Network) を使ったときにいくつかはまったのでメモ。
GPU必須です。
環境
- OS: Windows7 64bit
- Python2.7.8 |Anaconda 2.1.0 (64-bit)
Python DistributionのAnacondaを使っています。 - Theano
公式ページのManual installation に従ってインストールしました。 - Pylearn2
- Cuda6.5
- Visual Studio 2013
準備(Windows用)
以下はWindows環境で必要な設定・修正です。
LinuxやMacでは必要ないかもしれませんが、確認していません。
pthreadライブラリ をインストールする
pylearn2内部でpthreadを使っているのでインストールします。
pthreadなしだと学習時に以下のエラーメッセージを出力します。
pylearn2\sandbox\cuda_convnet\nvmatrix.cuh(39) fatal error C1083: include ファイルを開けません。'pthread.h':No such file or directory
今回は以下のサイトからライブラリをダウンロードしました。
https://sourceware.org/pthreads-win32/
pthreadライブラリへのパスを設定
pylearn2/sandbox/cuda_convnet/pthreads.py でpthreadライブラリへのパスを設定します。
以下に例を記載します。
from theano.configparser import AddConfigVar, StrParam
AddConfigVar('pthreads.inc_dir',
"location of pthread.h",
StrParam("C:\\lib\\pthreads-w32-2-9-1-release\\Pre-built.2\\include"))
AddConfigVar('pthreads.lib_dir',
"location of library implementing pthreads",
StrParam("C:\\lib\\pthreads-w32-2-9-1-release\\Pre-built.2\\lib\\x64"))
AddConfigVar('pthreads.lib',
'name of the library that implements pthreads (e.g. "pthreadVC2" if using pthreadVC2.dll/.lib from pthreads-win32)',
StrParam("pthreadVC2"))
pthreadVC2.dll を実行ディレクトリに置く
POSIX threadに含まれるpthreadVC2.dllを以下のディレクトリに置きます。
pylearn2/scripts/papers/maxout
pthreadVC2.dllの配置を行わないと以下のエラーが発生します。
これはpydファイルから参照しているdllが見つからないために発生しているエラーです。
DLL load failed:
同様のエラーが発生する場合には、以下のサイトにあるDependency Walkerを使ってpydの依存関係を調べるとよいと思います。
http://www.dependencywalker.com/
cuda_ndarrayライブラリへのパスを通す
Pylearn2による学習時にcuファイルのコンパイルを行うのですが、リンクエラーが発生します。
以下のファイルを修正して、cuda_ndarrayライブラリを読み込めるようにします。
compiler.compile_str('cuda_convnet',
code,
location = cuda_convnet_loc,
include_dirs = [this_dir, config.pthreads.inc_dir] if config.pthreads.inc_dir else [this_dir],
lib_dirs = nvcc_compiler.rpath_defaults + [cuda_convnet_loc] + ([config.pthreads.lib_dir] if config.pthreads.lib_dir else []),
- libs = ['cublas', config.pthreads.lib] if config.pthreads.lib else ['cublas'],
+ libs = ['cublas', 'cuda_ndarray', config.pthreads.lib] if config.pthreads.lib else ['cublas', 'cuda_ndarray'],
preargs = ['-O3'] + args,
py_module=False)
def c_libraries(self):
if config.pthreads.lib:
- return ['cuda_convnet', config.pthreads.lib]
+ return ['cuda_convnet', 'cuda_ndarray', config.pthreads.lib]
else:
- return ['cuda_convnet']
+ return ['cuda_convnet', 'cuda_ndarray']
学習
Pylearn2のpylearn2/scripts/papers/maxout にある mnist.yaml を使いました。
このファイルで使われている pylearn2.models.maxout.MaxoutConvC01B が Maxout + CNN のモデルクラスです。
MaxoutConvC01B を使うためにはGPUが必要です。
pylearn2/scripts/papers/maxout に移動した後、以下のコマンドで学習を行います。
python ..\..\train.py mnist.yaml
学習後のモデルは mnist_best.pkl に保存されます。
結果の確認
以下のファイルを作成し、
python mnist_result.py mnist_best.pkl
を実行するとテストデータに対する認識結果を確認することができます。
私の環境では 9940/10000 でした。
import numpy as np
import pickle
import sys
import theano
import pylearn2.datasets.mnist as mnist
from pylearn2.space import VectorSpace
def simulate(inputs, model):
space = VectorSpace(inputs.shape[1])
X = space.get_theano_batch()
Y = model.fprop(space.format_as(X, model.get_input_space()))
f = theano.function([X], Y)
result = []
for x in xrange(0, len(inputs), 100):
result.extend(f(inputs[x:x + 100]))
return result
def countCorrectResults(outputs, labels):
correct = 0;
for output, label in zip(outputs, labels):
if np.argmax(output) == label:
correct += 1
return correct
def score(dataset, model):
outputs = simulate(dataset.X, model)
correct = countCorrectResults(outputs, dataset.y)
return {
'correct': correct,
'total': len(dataset.X)
}
model = pickle.load(open(sys.argv[1]))
test_data = mnist.MNIST(which_set='test')
print '%(correct)d / %(total)d' % score(test_data, model)
さらに学習
mnist.yamlで学習した後、mnist_continued.yamlを使って学習を行うと、mnist_best.pklをさらに学習するようです。
学習後のモデルはmnist_continued.pklに保存されます。