切り絵が趣味の僕がプログラムや創作物について書き溜めるブログ

絵やモデリングやプログラミングなど僕が作った物について。アニメの感想や心動かされたきっかけなどを書き溜めるブログです。Boothで3Dアバターの販売もしていますhttps://paw.booth.pm/

ゼロから作るディープラーニング 第七章のプログラムをcifar10で実装してみた

今回は、ゼロから作るDeep Learningのサンプルプログラムを用いて

cifar10(データファイル)をcnn(畳み込みニューラルネット)で学習していきたいです!!

 

僕の環境

python 3.6.5

chainer v4.2.0

windows 7(研究室のよさげなパソコンを借りてる)

 

1.まずはサンプルプログラムの入手

GitHub - oreilly-japan/deep-learning-from-scratch: 『ゼロから作る Deep Learning』のリポジトリ

このサイトから入手できます。

緑色Clone or downloadって書いてあるボタンを押すと

全部ダウンロードできるはずです

 

欲しいのは

・ch07

・ch08(なくていい)

・common

の三つです。

 

2.cifar10のデータセット

 

入手

CIFAR-10 and CIFAR-100 datasets

このサイトのCIFAR-10 python versionをダウンロードしてください。

 

解凍すると

cifar-10-batches-pyというフォルダがあるので

deep-learning-from-scratch-masterの中のch7のフォルダに新規にDataというフォルダを作ってそこにぶち込んでください。

 

3.プログラムを書き換える

書き換える必要のあるファイルは

フォルダch7にあるtrain_convnet.py

 

上から11行目の

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)

from datetime import datetime
import time
import _pickle as cPickle
import numpy as np
import os

def unpickle(file):
    fo = open(file, 'rb')
    dict = cPickle.load(fo,encoding='bytes')
    fo.close()
    return dict

def conv_data2image(data):
    return np.rollaxis(data.reshape((3,32,32)),0,3)

def get_cifar10(folder):
    tr_data = np.empty((0,32*32*3))
    tr_labels = np.empty(1)
    '''
    32x32x3
    '''
    for i in range(1,6):
        fname = os.path.join(folder, "%s%d" % ("data_batch_", i))
        data_dict = unpickle(fname)
        if i == 1:
            tr_data = data_dict[b'data']
            tr_labels = data_dict[b'labels']
        else:
            tr_data = np.vstack((tr_data, data_dict[b'data']))
            tr_labels = np.hstack((tr_labels, data_dict[b'labels']))

    data_dict = unpickle(os.path.join(folder, 'test_batch'))
    te_data = data_dict[b'data']
    te_labels = np.array(data_dict[b'labels'])

    bm = unpickle(os.path.join(folder, 'batches.meta'))
    label_names = bm[b'label_names']

    tr_data = tr_data.reshape(tr_data.shape[0], 3, 32, 32)
    te_data = te_data.reshape(te_data.shape[0], 3, 32, 32)

    return tr_data, tr_labels, te_data, te_labels, label_names

    

if __name__ == '__main__':
    datapath = "./data/cifar-10-batches-py"

    tr_data10, tr_labels10, te_data10, te_labels10, label_names10 = get_cifar10(datapath)
    
x_train = tr_data10/255.0
t_train = tr_labels10.astype(np.int32)
x_test = te_data10/255.0
t_test = te_labels10.astype(np.int32)

x_train = x_train.astype(np.float32)
x_test =x_test.astype(np.float32)

 に書き換える。(最後に全部書き換えたやつをのせます)

 

あとはministのデータは(1.28.28)の大きさで

cifar10は(3.32.32)なので

1.28.28を3.32.32と書き直して終了。

 

commonフォルダのtrainer.pyの

49行目の if self.verbose: print("train loss:" + str(loss))

の前に#をつけてコメント文に変えることをおすすめします。

 

これで6割りぐらい正答します。

ch8のほうが計算量が多いのでそちらでも同じように実装すると

7割ぐらいは正答するようになります。

train_convnet.py

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import numpy as np
import matplotlib.pyplot as plt
from simple_convnet import SimpleConvNet
from common.trainer import Trainer

# データの読み込み
import _pickle as cPickle
import numpy as np
import os

def unpickle(file):
    fo = open(file, 'rb')
    dict = cPickle.load(fo,encoding='bytes')
    fo.close()
    return dict

def conv_data2image(data):
    return np.rollaxis(data.reshape((3,32,32)),0,3)

def get_cifar10(folder):
    tr_data = np.empty((0,32*32*3))
    tr_labels = np.empty(1)
    '''
    32x32x3
    '''
    for i in range(1,6):
        fname = os.path.join(folder, "%s%d" % ("data_batch_", i))
        data_dict = unpickle(fname)
        if i == 1:
            tr_data = data_dict[b'data']
            tr_labels = data_dict[b'labels']
        else:
            tr_data = np.vstack((tr_data, data_dict[b'data']))
            tr_labels = np.hstack((tr_labels, data_dict[b'labels']))

    data_dict = unpickle(os.path.join(folder, 'test_batch'))
    te_data = data_dict[b'data']
    te_labels = np.array(data_dict[b'labels'])

    bm = unpickle(os.path.join(folder, 'batches.meta'))
    label_names = bm[b'label_names']

    tr_data = tr_data.reshape(tr_data.shape[0], 3, 32, 32)
    te_data = te_data.reshape(te_data.shape[0], 3, 32, 32)

    return tr_data, tr_labels, te_data, te_labels, label_names

    

if __name__ == '__main__':
    datapath = "./data/cifar-10-batches-py"

    tr_data10, tr_labels10, te_data10, te_labels10, label_names10 = get_cifar10(datapath)
    
x_train = tr_data10/255.0
t_train = tr_labels10.astype(np.int32)
x_test = te_data10/255.0
t_test = te_labels10.astype(np.int32)

x_train = x_train.astype(np.float32)
x_test =x_test.astype(np.float32)

# 処理に時間のかかる場合はデータを削減 
#x_train, t_train = x_train[:5000], t_train[:5000]
#x_test, t_test = x_test[:1000], t_test[:1000]

max_epochs = 20

network = SimpleConvNet(input_dim=(3,32,32), 
                        conv_param = {'filter_num': 30, 'filter_size': 5, 'pad': 0, 'stride': 1},
                        hidden_size=100, output_size=10, weight_init_std=0.01)
                        
trainer = Trainer(network, x_train, t_train, x_test, t_test,
                  epochs=max_epochs, mini_batch_size=100,
                  optimizer='Adam', optimizer_param={'lr': 0.001},
                  evaluate_sample_num_per_epoch=1000)
trainer.train()

# パラメータの保存
network.save_params("params.pkl")
print("Saved Network Parameters!")

# グラフの描画
markers = {'train': 'o', 'test': 's'}
x = np.arange(max_epochs)
plt.plot(x, trainer.train_acc_list, marker='o', label='train', markevery=2)
plt.plot(x, trainer.test_acc_list, marker='s', label='test', markevery=2)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()

 

commonの

trainer.py

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import numpy as np
from common.optimizer import *

class Trainer:
    """ニューラルネットの訓練を行うクラス
    """
    def __init__(self, network, x_train, t_train, x_test, t_test,
                 epochs=20, mini_batch_size=100,
                 optimizer='SGD', optimizer_param={'lr':0.01}, 
                 evaluate_sample_num_per_epoch=None, verbose=True):
        self.network = network
        self.verbose = verbose
        self.x_train = x_train
        self.t_train = t_train
        self.x_test = x_test
        self.t_test = t_test
        self.epochs = epochs
        self.batch_size = mini_batch_size
        self.evaluate_sample_num_per_epoch = evaluate_sample_num_per_epoch

        # optimzer
        optimizer_class_dict = {'sgd':SGD, 'momentum':Momentum, 'nesterov':Nesterov,
                                'adagrad':AdaGrad, 'rmsprpo':RMSprop, 'adam':Adam}
        self.optimizer = optimizer_class_dict[optimizer.lower()](**optimizer_param)
        
        self.train_size = x_train.shape[0]
        self.iter_per_epoch = max(self.train_size / mini_batch_size, 1)
        self.max_iter = int(epochs * self.iter_per_epoch)
        self.current_iter = 0
        self.current_epoch = 0
        
        self.train_loss_list = []
        self.train_acc_list = []
        self.test_acc_list = []

    def train_step(self):
        batch_mask = np.random.choice(self.train_size, self.batch_size)
        x_batch = self.x_train[batch_mask]
        t_batch = self.t_train[batch_mask]
        
        grads = self.network.gradient(x_batch, t_batch)
        self.optimizer.update(self.network.params, grads)
        
        loss = self.network.loss(x_batch, t_batch)
        self.train_loss_list.append(loss)
        #if self.verbose: print("train loss:" + str(loss))
        
        if self.current_iter % self.iter_per_epoch == 0:
            self.current_epoch += 1
            
            x_train_sample, t_train_sample = self.x_train, self.t_train
            x_test_sample, t_test_sample = self.x_test, self.t_test
            if not self.evaluate_sample_num_per_epoch is None:
                t = self.evaluate_sample_num_per_epoch
                x_train_sample, t_train_sample = self.x_train[:t], self.t_train[:t]
                x_test_sample, t_test_sample = self.x_test[:t], self.t_test[:t]
                
            train_acc = self.network.accuracy(x_train_sample, t_train_sample)
            test_acc = self.network.accuracy(x_test_sample, t_test_sample)
            self.train_acc_list.append(train_acc)
            self.test_acc_list.append(test_acc)

            if self.verbose: print("=== epoch:" + str(self.current_epoch) + ", train acc:" + str(train_acc) + ", test acc:" + str(test_acc) + " ===")
        self.current_iter += 1

    def train(self):
        for i in range(self.max_iter):
            self.train_step()

        test_acc = self.network.accuracy(self.x_test, self.t_test)

        if self.verbose:
            print("=============== Final Test Accuracy ===============")
            print("test acc:" + str(test_acc)

 

ここのぶろぐも参考にしました

http://msyksphinz.hatenablog.com/entry/2018/03/11/092428

http://sssiii.seesaa.net/article/452359119.html