Caffeの3D-CNNを使ったダミーデータの学習

  • 12
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに

一般的にCNN(Convolutional Neural Network、畳み込みニューラルネットワーク)は主に画像等の2次元配列データを入力とするが、これを3次元配列データにしたものが3D-CNN。
Caffeでは3D-CNNも使うことができるが、学習の方法についての資料が少なかったので、ダミーデータを使った学習方法をメモ。応用すれば一般のND-CNNにも適用できるとは思う。

環境

  • OS:SUSE Linux Enterprise Server 11 SP3
  • Python:2.7.10(Anaconda 2.3.0)
  • Caffe:0.13.0(本家)

ダミーデータ

今回は横2×縦3×奥行4の3次元配列データを3D-CNNの入力とし、チャネル数が5の4次元配列のデータを使う。
データの個数は学習用に6個、テスト用に6個、計12個とする。
今回は2クラス分類問題とする。どのデータも、全ての要素が1であるか、全ての要素が0であるかのどちらかとなるようにし、全ての要素が1であるデータは正例(ラベル1)、全ての要素が0であるデータは負例(ラベル0)、というごく単純なデータセットを構築する。
このページによれば、3D-CNNを使う際はデータセットの形式としてLEVELDBやLMDBは使えず、HDF5を用いる必要があるらしい(?)。HDF5形式の学習用データセットファイルの、"data"データセットにCNNへの入力を、"label"データセットにラベルを記録することにする。テスト用データセットファイルに対しても同様に記録を行うことにする。
以上のようなデータは以下のスクリプトで作れる。このスクリプトをmake_hdf5.pyとする。

# -*- coding: utf-8 -*-


import h5py
import numpy as np
import random
import sys

def save_hdf5(filename, inputs, labels):
    with h5py.File(filename, 'w') as f:
        f['data'] = inputs
        f['label'] = labels

def main():
    train_file  = sys.argv[1]
    test_file   = sys.argv[2]
    channels    = 5
    width       = 2
    height      = 3
    depth       = 4
    n_train     = 6
    n_test      = 6

    labels0 = np.zeros((n_train+n_test)/2)
    labels1 = np.zeros((n_train+n_test)/2) + 1
    labels = np.r_[labels0, labels1]

    neg = np.zeros(channels * width * height * depth) + 1
    neg = neg.reshape([channels, width, height, depth])
    pos = neg + 1
    negs = []
    poss = []
    for i in range((n_train+n_test)/2):
        negs.append(neg)
        poss.append(pos)
    negs = np.array(negs,dtype=np.float32)
    poss = np.array(poss,dtype=np.float32)
    inputs = np.r_[negs, poss]

    perm = np.random.permutation(len(inputs))
    train_inputs = inputs[perm[:n_train]]
    train_labels = labels[perm[:n_train]]
    save_hdf5(train_file, train_inputs, train_labels)

    test_inputs = inputs[perm[n_train:]]
    test_labels = labels[perm[n_train:]]
    save_hdf5(test_file, test_inputs, test_labels)


if __name__ == "__main__":
    main()

make_hdf5.pyの使い方は、まずh5pynumpyパッケージを以下のようにインストールしてから、

$ pip install h5py
$ pip install numpy

make_hdf5.pyを実行する。学習用データセットファイルをfoo_train.h5、テスト用データセットファイルをfoo_test.h5とすると、実行すべきコマンドは以下のようになる。

$ make_hdf5.py foo_train.h5 foo_test.h5

実行するとfoo_train.h5foo_test.h5が生成される。

学習の準備

foo_train_list.txtfoo_test_list.txtfoo_solver.prototxtfoo_train_test.prototxtという4つのファイルを作成する必要がある。
それぞれ、学習用データセットファイルへのパスのリスト、テスト用データセットファイルへのパスのリスト、Solverのパラメータの定義、学習・テストに用いるネットワークの定義を記述する。

foo_train_list.txtfoo_test_list.txtの作成

foo_train_list.txtにはfoo_train.h5へのパスを、foo_test_list.txtにはfoo_test.h5へのパスを書いておく。

foo_solver.prototxtの作成

foo_solver.prototxtを以下のように記述する。
このページに従って、「net:」の部分に学習用ネットのprototxtファイル名を記述する。また、「snapshot prefix:」の部分には、スナップショットファイル(後述) のプレフィックスを指定する。

# reduce the learning rate after 8 epochs (4000 iters) by a factor of 10

# The train/test net protocol buffer definition
net: "foo_train_test.prototxt"
# test_iter specifies how many forward passes the test should carry out.
# In the case of MNIST, we have test batch size 100 and 100 test iterations,
# covering the full 10,000 testing images.
test_iter: 100
# Carry out testing every 500 training iterations.
test_interval: 500
# The base learning rate, momentum and the weight decay of the network.
base_lr: 0.001
momentum: 0.9
weight_decay: 0.004
# The learning rate policy
lr_policy: "fixed"
# Display every 100 iterations
display: 100
# The maximum number of iterations
max_iter: 4000
# snapshot intermediate results
snapshot: 4000
snapshot_prefix: "foo"
# solver mode: CPU or GPU
solver_mode: GPU
#solver_mode: CPU

foo_train_test.prototxtの作成

foo_train_test.prototxtに以下のように記述する。
基本的なフォーマットの説明はCaffe公式のLayer Catalogueに譲るが、3D-CNNを用いる場合、40行目や66行目のように畳み込み層のパラメータ(「convolution_param」)の記述に「engine:CAFFE」の記述が必要。また、畳み込み層のカーネル(フィルタ)の大きさの指定には42-44行目、68-70行目のように「kernel_size」を3回書くことで指定できる。
また3D-CNNに限らないが、ソフトマックス層への入力となる層の出力フィルタ数(「num_output」)は判定するクラス数と同じにする必要があることに注意する。今回の場合は2クラス判定問題のため、114行目のようにソフトマックス層への入力となるip2層の出力フィルタ数を2とする。

name: "foo"
layer {
  name: "foo"
  type: "HDF5Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  hdf5_data_param {
    source: "foo_train_list.txt"
    batch_size: 2
  }
}
layer {
  name: "foo"
  type: "HDF5Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  hdf5_data_param {
    source: "foo_test_list.txt"
    batch_size: 2
  }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    engine: CAFFE
    num_output: 48
    kernel_size: 1
    kernel_size: 1
    kernel_size: 1
    stride: 2
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "conv1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    engine: CAFFE
    num_output: 160
    kernel_size: 1
    kernel_size: 1
    kernel_size: 1
    stride: 2
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "ip1"
  type: "InnerProduct"
  bottom: "conv2"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 64
    weight_filler {
      type: "gaussian"
      std: 0.1
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 2
    weight_filler {
      type: "gaussian"
      std: 0.1
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "ip2"
  bottom: "label"
  top: "accuracy"
  # include {
  #   phase: TEST
  # }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}

学習

以下のコマンドを入力して学習を行う。

$ caffe train --solver foo_solver.prototxt

学習が正常に終了するとfoo_iter_4000.caffemodelfoo_iter_4000.solverstateという名前の2つのファイルが生成される。

テスト

以下のコマンドを入力してテストを行う。

$ caffe test -weights=foo_iter_4000.caffemodel -model=foo_train_test.prototxt
  • この記事は以下の記事からリンクされています
  • Caffe で 3D-CNNからリンク