画像処理とか機械学習とか

画像処理や機械学習関連の事について気まぐれで書いていきます。歩行者検出関係が多いと思います。ハリネズミもたまに出現します。

Windowsで超便利なディープラーニングのライブラリのchainerを使う方法

研究でも少しディープラーニングを扱っておきたかったので今回はディープラーニングを簡単に実装して動かすためのライブラリであるchainerを用いる方法を載せたいと思います。

公式ではWindowsに非対応ですが、mnistのサンプルとimagenetの学習まで独自のデータセットを用いてgpuで動かせたのでubuntuじゃなくても動かせます。(とりあえずは)

環境
f:id:hiro2o2:20160415160710p:plain:w300
日本の企業が提供しているDNN用のライブラリ
ドキュメントは英語のみの提供と日本人に厳しいS仕様
http://docs.chainer.org/en/stable/index.html

OS:Windows7
GPUNVIDIA TITAN X
Python2.7(64bitバージョン)
コンパイラMicrosoft Visual C++ Compiler for Python2.7

GPUを使う場合(cuDNNはダウンロードに会員登録が必要)
CUDA Toolkit, cuDNN

  • chainerをインストールするまで

Pythonコンパイラをインストール後、GPUを使う場合はCUDA Toolkitをインストールし、所定のディレクトリにcuDNNを配置した後にchainerをインストールします。cudaのディレクトリは標準ではC:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v6.5
の様な場所にあると思いますので、ダウンロードしたものをcudaのディレクトリにコピーします。

Pythonが正しくインストール出来たら、コマンドプロンプトを開いてpipコマンドが使えるはずです。まずはpip install -U pipとpip install -U setuptoolsをしましょう。その後pip install chainer で運が良ければインストールできます。エラーが出る場合は、エラーをよく読み、根気強く必要な物をインストールしたりする作業が必要です。アンインストールするときは pip uninstall chainerでアンインストールできます。

大体多いエラーは必要なものが無いというのが多かったのでpip install **** でインストールして再度チャレンジすれば良いと思います。コンパイラも忘れずにインストールしておかないとエラーが出ます。

  • 手書き文字認識mnistのサンプル

chainerのサンプルコードはgithubから入手できます。
https://github.com/pfnet/chainer

examplesの中のmnistというフォルダが手書き文字認識のサンプルプログラムです。
幾つか中身が入っていると思いますが、net.pyはネットワークが記述されたプログラム、train_mnist.pyが学習の流れが書かれたプログラムです。
使い方は簡単で、コマンドプロンプトをからpython train_mnist.py -g 0 で実行できます。
すると下の画像のようにずらずらと学習結果が出てくると思います。
f:id:hiro2o2:20160415163139p:plain

もし実行できない場合はpython train_mnist.py を試してみてください。
これが動けばchainerのインストールは成功してますがGPUのライブラリのインストールに失敗しています。
動かなければchainerが上手くインストールできてないです。

  • 画像分類のimagenetのサンプル

こちらのプログラムはサンプルそのままではmultiprocessing関係のエラーがでるのでWindowsで動きません。少しだけ修正が必要です。

以下train_imagenet.pyの一番下の部分

if __name__ == '__main__':
    # Invoke threads
    feeder = threading.Thread(target=feed_data)
    feeder.daemon = True
    feeder.start()
    logger = threading.Thread(target=log_result)
    logger.daemon = True
    logger.start()

    train_loop()
    feeder.join()
    logger.join()

    # Save final model
    serializers.save_npz(args.out, model)
    serializers.save_npz(args.outstate, optimizer)

if __name__ == '__main__': を追加してその下を全てインデントして下さい。
これだけでWindowsでも学習できるようになります。

独自のデータセットを使う際には、train.txt, test.txtが必要になり、それぞれ学習データ・テストデータへのパスとラベルが書かれたファイルです。
C:\Users\user\Desktop\stop256\test\neg0.png 0
C:\Users\user\Desktop\stop256\test\neg1.png 0
C:\Users\user\Desktop\stop256\test\neg2.png 0
C:\Users\user\Desktop\stop256\test\neg3.png 0
C:\Users\user\Desktop\stop256\test\neg4.png 1
C:\Users\user\Desktop\stop256\test\neg5.png 1
C:\Users\user\Desktop\stop256\test\neg6.png 1
C:\Users\user\Desktop\stop256\test\neg7.png 1
C:\Users\user\Desktop\stop256\test\neg8.png 2
C:\Users\user\Desktop\stop256\test\neg9.png 2
C:\Users\user\Desktop\stop256\test\neg10.png 2
C:\Users\user\Desktop\stop256\test\neg11.png 2
この様な感じでパス[半角スペース]ラベルとなっています。
画像は256×256の画像を用意して下さい。無理やりリサイズさせてもokです。

学習にはpython train_imagenet.py train.txt test.txt -g 0 で学習が始まります。
デフォルトではNetwork In NetworkというCNNで学習できます。
f:id:hiro2o2:20160415164946p:plain

学習が終わるとmodelというファイルができます。これが学習済みのネットワークで、このモデルを使って識別等を行うことが可能です。
識別のために、nin.pyを書き換えます。

import math

import chainer
import chainer.functions as F
import chainer.links as L


class NIN(chainer.Chain):

    """Network-in-Network example model."""

    insize = 227

    def __init__(self):
        w = math.sqrt(2)  # MSRA scaling
        super(NIN, self).__init__(
            mlpconv1=L.MLPConvolution2D(
                3, (96, 96, 96), 11, stride=4, wscale=w),
            mlpconv2=L.MLPConvolution2D(
                96, (256, 256, 256), 5, pad=2, wscale=w),
            mlpconv3=L.MLPConvolution2D(
                256, (384, 384, 384), 3, pad=1, wscale=w),
            mlpconv4=L.MLPConvolution2D(
                384, (1024, 1024, 1000), 3, pad=1, wscale=w),
        )
        self.train = True

    def clear(self):
        self.loss = None
        self.accuracy = None

    def __call__(self, x, t):
        self.clear()
        h = F.max_pooling_2d(F.relu(self.mlpconv1(x)), 3, stride=2)
        h = F.max_pooling_2d(F.relu(self.mlpconv2(h)), 3, stride=2)
        h = F.max_pooling_2d(F.relu(self.mlpconv3(h)), 3, stride=2)
        h = self.mlpconv4(F.dropout(h, train=self.train))
        h = F.reshape(F.average_pooling_2d(h, 6), (x.data.shape[0], 1000))

        self.loss = F.softmax_cross_entropy(h, t)
        self.accuracy = F.accuracy(h, t)
        return self.loss

    def predict(self, x_data):
        x = chainer.Variable(x_data, volatile=True)
        h = F.max_pooling_2d(F.relu(self.mlpconv1(x)), 3, stride=2)
        h = F.max_pooling_2d(F.relu(self.mlpconv2(h)), 3, stride=2)
        h = F.max_pooling_2d(F.relu(self.mlpconv3(h)), 3, stride=2)
        h = self.mlpconv4(F.dropout(h, train=self.train))
        h = F.reshape(F.average_pooling_2d(h, 6), (x.data.shape[0], 1000))
        
        return F.softmax(h)
        

predictという関数を追加しています。
この関数を使って評価を行うプログラムは他の開発者さんのものをお借りします。
https://github.com/shi3z/chainer_imagenet_tools/blob/master/inspection.py

これで画像識別までをWindows環境下でchainerを用いて動かすことができます。
まだサンプルを動かせただけですので、何か不具合が見つかるかもしれませんが、とりあえずはWindowsで動かして遊べる事を確認しました。