技術系メモ

雑多なメモです。ほんと自分用のwikiです。

chainer初心者が畳み込みニューラルネット試してみた

  • うさぎとミサイルを見分ける
  • うさぎ3枚、ミサイル2枚学習
  • とりあえず細かい動きだけ知りたかったのでやってみた
  • しっかりしたやつは後日
  • 画像は適当にとってきた

コード

import time
import six.moves.cPickle as pickle
import numpy as np
import chainer 
from chainer import cuda,  Variable,  FunctionSet,  optimizers
import chainer.functions as F
import cv2
from matplotlib  import pyplot as plt

# 独自のモデル
class MyModel(chainer.Chain):
    def __init__(self):
        super(MyNet, self).__init__(
            # 入力が3チャンネル(RGB)、出力の特徴マップが16チャンネル、フィルタが3x3、パディングサイズ1
            conv1 = F.Convolution2D(3, 16, 3, pad=1), 
            conv2 = F.Convolution2D(16, 16, 3, pad=1), 
            l3 = F.Linear(1024, 50),    # 全結合NN
            l4 = F.Linear(50, 2))

    def __call__(self, x_data, y_data=None, train=True):
        x = Variable(x_data)
        h = F.max_pooling_2d(F.relu(self.conv1(x)), 2)
        h = F.max_pooling_2d(F.relu(self.conv2(h)), 2)
        h = F.dropout(F.relu(self.l3(h)), train=train)
        y = self.l4(h)

        if train:
            t = Variable(y_data)
            return F.softmax_cross_entropy(y, t), F.accuracy(y, t)
        else:
            return F.softmax(y)


x_train = []
y_train = []

# 学習用データ
## 画像1枚目
img = cv2.imread("labit.jpg")
img = cv2.resize(img, ( 32, 32 ))
img = np.transpose(img, (2, 0, 1))/255.0  # openCvで読み込むと配列の形が異なるので、整える
x_train.append(img)
y_train.append(0) # ラベル0

## 画像2枚目
img = cv2.imread("labit2.jpg")
img = cv2.resize(img, ( 32, 32 ))
img = np.transpose(img, (2, 0, 1))/255.0
x_train.append(img)
y_train.append(0)

## 画像3枚目
img = cv2.imread("labit4.jpg")
img = cv2.resize(img, ( 32, 32 ))
img = np.transpose(img, (2, 0, 1))/255.0
x_train.append(img)
y_train.append(0)   

## 画像4枚目
img = cv2.imread("mis.jpg")
img = cv2.resize(img, ( 32, 32 ))
img = np.transpose(img, (2, 0, 1))/255.0
x_train.append(img)
y_train.append(1) 

## 画像4枚目
img = cv2.imread("mis.jpg")
img = cv2.resize(img, ( 32, 32 ))
img = np.transpose(img, (2, 0, 1))/255.0
x_train.append(img)
y_train.append(1) 

x_train = np.array(x_train ).astype(np.float32)
y_train = np.array(y_train ).astype(np.int32)
x_train = x_train.reshape(len(x_train),  3,  32, 32) / 255


# モデルの設定
model = MyModel()
optimizer = optimizers.Adam()
optimizer.setup(model)

# 学習
batchsize = 1
datasize = len(x_train)
epoch_n = 1000

train_loss = []
for epoch in range(1, epoch_n):
    optimizer.zero_grads() # 勾配の初期化
    loss = model(x_train, y_train, train=True)  # すべてのx_train、y_trainで伝搬
    train_loss.append(loss[0].data) 
    print(loss[0].data) 
    loss[0].backward()  # 誤差逆伝搬
    optimizer.update()  # 最適化手法によりアップデート


# テスト
x_test = []

# labit3.jpgがどのように判定されるかチェック
img = cv2.imread("labit3.jpg")
img = cv2.resize(img, ( 32, 32 ))
img = np.transpose(img, (2, 0, 1))/255.0
x_test.append(img)

x_test = np.array(x_test ).astype(np.float32)
x_test = x_test.reshape(len(x_test),  3,  32, 32) / 255.0

loss = model(x_test, train=False)

print("================================================")
print(loss.data.argmax())  # 一番高い値をだしているラベルを出力

plt.plot(train_loss, label = "train_loss")
plt.title("loss")
plt.savefig("loss.png")