はじめに
Caffeは深層学習のためのオープンソースフレームワークです。画像認識や物体検出などのタスクに広く使われています。この記事では、PythonでCaffeを使う方法を段階的に解説していきます。
第1章: Caffeのインストール
まずはCaffeをインストールしましょう。Ubuntuを使用している場合、以下のコマンドでインストールできます。
sudo apt-get update
sudo apt-get install -y python-dev python-pip
sudo pip install numpy scipy
sudo apt-get install -y libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler
sudo apt-get install -y --no-install-recommends libboost-all-dev
sudo apt-get install -y libatlas-base-dev
sudo apt-get install -y libgflags-dev libgoogle-glog-dev liblmdb-dev
git clone https://github.com/BVLC/caffe
cd caffe
cp Makefile.config.example Makefile.config
make all
make test
make runtest
make pycaffe
第2章: Caffeの基本概念
Caffeでは、ニューラルネットワークを「レイヤー」の積み重ねとして定義します。主要な概念は以下の通りです:
- Blob: データを保持する4次元配列
- Layer: ネットワークの基本構成要素
- Net: レイヤーを組み合わせたネットワーク全体
- Solver: 学習のパラメータを管理
第3章: 最初のCaffeモデル
簡単な例として、MNISTデータセットを使った手書き数字認識モデルを作成しましょう。
import caffe
import numpy as np
# ネットワークの定義
net = caffe.Net('mnist_net.prototxt', caffe.TEST)
# データの準備
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))
transformer.set_raw_scale('data', 255)
# 画像の読み込みと前処理
image = caffe.io.load_image('test_image.jpg', color=False)
transformed_image = transformer.preprocess('data', image)
# 推論
net.blobs['data'].data[...] = transformed_image
output = net.forward()
# 結果の表示
print(output['prob'][0])
第4章: データの準備
Caffeで学習を行うには、データを適切な形式に変換する必要があります。LMDBやHDF5形式がよく使われます。
import caffe
import lmdb
import numpy as np
from caffe.proto import caffe_pb2
# LMDBデータベースの作成
lmdb_env = lmdb.open('mnist_train_lmdb', map_size=int(1e12))
with lmdb_env.begin(write=True) as lmdb_txn:
for i in range(len(X_train)):
datum = caffe_pb2.Datum()
datum.channels = X_train[i].shape[2]
datum.height = X_train[i].shape[0]
datum.width = X_train[i].shape[1]
datum.data = X_train[i].tobytes()
datum.label = int(y_train[i])
str_id = '{:08}'.format(i)
lmdb_txn.put(str_id.encode('ascii'), datum.SerializeToString())
第5章: ネットワークの定義
Caffeでは、ネットワークの構造をprototxtファイルで定義します。以下は簡単な畳み込みニューラルネットワークの例です。
name: "LeNet"
layer {
name: "data"
type: "Input"
top: "data"
input_param { shape: { dim: 64 dim: 1 dim: 28 dim: 28 } }
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
convolution_param {
num_output: 20
kernel_size: 5
stride: 1
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "ip1"
type: "InnerProduct"
bottom: "pool1"
top: "ip1"
inner_product_param {
num_output: 500
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
inner_product_param {
num_output: 10
}
}
layer {
name: "prob"
type: "Softmax"
bottom: "ip2"
top: "prob"
}
第6章: Solverの設定
Solverは学習のパラメータを管理します。以下はSolverの設定例です。
net: "train_val.prototxt"
test_iter: 100
test_interval: 500
base_lr: 0.01
momentum: 0.9
weight_decay: 0.0005
lr_policy: "step"
gamma: 0.1
stepsize: 5000
display: 100
max_iter: 10000
snapshot: 5000
snapshot_prefix: "lenet"
solver_mode: GPU
第7章: 学習の実行
Pythonを使ってCaffeモデルを学習させる方法を見ていきましょう。
import caffe
solver = caffe.get_solver('solver.prototxt')
solver.solve()
# または、既存のモデルから学習を再開する場合
solver.restore('snapshot.solverstate')
solver.solve()
第8章: ファインチューニング
既存のモデルを新しいタスクに適応させるファインチューニングも、Caffeで簡単に行えます。
import caffe
# 事前学習済みモデルの読み込み
net = caffe.Net('model.prototxt', 'model.caffemodel', caffe.TRAIN)
# 最後の層の重みをリセット
net.params['fc8'][0].data[...] = 0
net.params['fc8'][1].data[...] = 0
# ソルバーの設定
solver = caffe.SGDSolver('solver.prototxt')
solver.net.copy_from('model.caffemodel')
# ファインチューニングの実行
solver.solve()
第9章: データ拡張
学習データを増やすデータ拡張は、モデルの汎化性能を向上させる重要な技術です。
import caffe
import numpy as np
def augment_data(image):
# 回転
angle = np.random.uniform(-10, 10)
rotated = caffe.io.rotate_image(image, angle)
# フリップ
if np.random.random() > 0.5:
flipped = caffe.io.flip_image(rotated)
else:
flipped = rotated
# スケーリング
scale = np.random.uniform(0.9, 1.1)
scaled = caffe.io.resize_image(flipped, (int(image.shape[0]*scale), int(image.shape[1]*scale)))
return scaled
# データ拡張の適用
augmented_images = [augment_data(img) for img in original_images]
第10章: 特徴抽出
学習済みモデルを使って、画像から特徴を抽出する方法を見ていきましょう。
import caffe
import numpy as np
# モデルの読み込み
net = caffe.Net('deploy.prototxt', 'model.caffemodel', caffe.TEST)
# 画像の前処理
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))
transformer.set_mean('data', np.load('mean.npy').mean(1).mean(1))
transformer.set_raw_scale('data', 255)
transformer.set_channel_swap('data', (2,1,0))
# 画像の読み込みと変換
image = caffe.io.load_image('image.jpg')
transformed_image = transformer.preprocess('data', image)
# 特徴抽出
net.blobs['data'].data[...] = transformed_image
output = net.forward()
features = net.blobs['fc7'].data[0]
print(features)
第11章: 可視化
学習の進捗や結果を可視化することは、モデルの理解と改善に役立ちます。
import caffe
import numpy as np
import matplotlib.pyplot as plt
# 学習曲線の可視化
train_loss = np.load('train_loss.npy')
test_accuracy = np.load('test_accuracy.npy')
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.plot(train_loss)
plt.title('Training Loss')
plt.subplot(1, 2, 2)
plt.plot(test_accuracy)
plt.title('Test Accuracy')
plt.show()
# フィルタの可視化
net = caffe.Net('deploy.prototxt', 'model.caffemodel', caffe.TEST)
filters = net.params['conv1'][0].data
n_filters, n_channels, height, width = filters.shape
fig = plt.figure(figsize=(n_filters, n_channels))
for i in range(n_filters):
for j in range(n_channels):
ax = fig.add_subplot(n_channels, n_filters, i*n_channels + j + 1)
ax.imshow(filters[i, j], cmap='gray')
ax.axis('off')
plt.show()
第12章: モデルの評価
学習したモデルの性能を評価する方法を見ていきましょう。
import caffe
import numpy as np
from sklearn.metrics import accuracy_score, confusion_matrix
# モデルの読み込み
net = caffe.Net('deploy.prototxt', 'model.caffemodel', caffe.TEST)
# テストデータの準備
X_test, y_test = load_test_data() # テストデータを読み込む関数
# 予測
predictions = []
for image in X_test:
net.blobs['data'].data[...] = image
output = net.forward()
pred = output['prob'].argmax()
predictions.append(pred)
# 精度の計算
accuracy = accuracy_score(y_test, predictions)
print(f'Accuracy: {accuracy}')
# 混同行列の作成
cm = confusion_matrix(y_test, predictions)
print('Confusion Matrix:')
print(cm)
第13章: モデルの保存と読み込み
学習したモデルを保存し、後で再利用する方法を説明します。
import caffe
# モデルの保存
net = caffe.Net('train_val.prototxt', 'model.caffemodel', caffe.TRAIN)
net.save('new_model.caffemodel')
# モデルの読み込み
net = caffe.Net('deploy.prototxt', 'new_model.caffemodel', caffe.TEST)
第14章: GPUの利用
Caffeは、GPUを使用して計算を高速化できます。
import caffe
# GPUモードの設定
caffe.set_mode_gpu()
caffe.set_device(0) # GPUデバイス番号
# 以降、通常通りCaffeを使用
net = caffe.Net('deploy.prototxt', 'model.caffemodel', caffe.TEST)
第15章: デプロイメント
学習したモデルを実際のアプリケーションで使用する方法を見ていきます。
import caffe
import numpy as np
from flask import Flask, request, jsonify
app = Flask(__name__)
# モデルの読み込み
net = caffe.Net('deploy.prototxt', 'model.caffemodel', caffe.TEST)
@app.route('/predict', methods=['POST'])
def predict():
# 画像データの受け取り
image_data = request.files['image'].read()
image = caffe.io.load_image(image_data)
# 前処理
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))
transformer.set_raw_scale('data', 255)
transformed_image = transformer.preprocess('data', image)
# 推論
net.blobs['data'].data[...] = transformed_image
output = net.forward()
# 結果の返送
result = {'class': int(output['prob'].argmax()), 'probability': float(output['prob'].max())}
return jsonify(result)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
以上で、PythonでのCaffe使用方法について、15章にわたって詳しく解説しました。各章で基本的な概念から応用まで幅広くカバーしていますので、Caffeを使った深層学習の実践に役立つことでしょう。