LoginSignup
11
14

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-03-03

はじめに

一般的に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
11
14
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
14