FC2カウンター FPGAの部屋 2017年08月09日

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

映画『ジョジョの奇妙な冒険 ダイヤモンドは砕けない 第一章』を見てました

今日は8月11日に大学説明会で出勤するので、振替休日だった。なので、映画『ジョジョの奇妙な冒険 ダイヤモンドは砕けない 第一章』(音注意)を見てきた。
少し怖かったが(ジョジョの奇妙な冒険は漫画でも怖かったので、よく読んでいない)面白かった。
  1. 2017年08月09日 17:18 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作7(学習2)

白線追従走行用畳み込みニューラルネットワークの製作6(学習1)”の続き。

前回は、白線追従走行の直線走行用のトレーニング・データとテスト・データを用意し、それらのデータセットを使用するためのPython コードのstraight_dataset.py を用意した。今回は、浮動小数点数を使用して畳み込みニューラルネットワーク(CNN)をトレーニングするためにPython コードを修正する。
今回使用するフォルダは前回コピー&ペーストした ch07_straight フォルダだ。その内容を示す。
wlt_cnn_40_170808.png

このうちの、simple_convnet.py を変更した。このCNNを記述するPython コードはn x n の画像に対応しているコードだった。今回は 10 x 56 で行と列の数が違っているので、対応することができないのだ。そこで、input_size の代わりにinput_size_x とinput_size_y をconv_output_size の代わりにconv_output_size_x とconv_output_size_y を作った。

        input_size_y = input_dim[1]
        input_size_x = input_dim[2]
        conv_output_size_y = (input_size_y - filter_size + 2*filter_pad) / filter_stride + 1
        conv_output_size_x = (input_size_x - filter_size + 2*filter_pad) / filter_stride + 1
        pool_output_size = int(filter_num * (conv_output_size_y/2) * (conv_output_size_x/2))


simple_convnet.py の全文を貼っておく。

# simple_convnet.py
# 2017/08/08 白線追従走行用CNNに変更 by marsee
# 元になったコードは、https://github.com/oreilly-japan/deep-learning-from-scratch にあります。
# 改変したコードもMITライセンスとします。 2017/08/08 by marsee

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


class SimpleConvNet:
    """単純なConvNet

    conv - relu - pool - affine - relu - affine - softmax
    
    Parameters
    ----------
    input_size : 入力サイズ(MNISTの場合は784)
    hidden_size_list : 隠れ層のニューロンの数のリスト(e.g. [100, 100, 100])
    output_size : 出力サイズ(MNISTの場合は10)
    activation : 'relu' or 'sigmoid'
    weight_init_std : 重みの標準偏差を指定(e.g. 0.01)
        'relu'または'he'を指定した場合は「Heの初期値」を設定
        'sigmoid'または'xavier'を指定した場合は「Xavierの初期値」を設定
    """
    def __init__(self, input_dim=(1, 10, 56), 
                 conv_param={'filter_num':30, 'filter_size':5, 'pad':0, 'stride':1},
                 hidden_size=100, output_size=10, weight_init_std=0.01):
        filter_num = conv_param['filter_num']
        filter_size = conv_param['filter_size']
        filter_pad = conv_param['pad']
        filter_stride = conv_param['stride']
        input_size_y = input_dim[1]
        input_size_x = input_dim[2]
        conv_output_size_y = (input_size_y - filter_size + 2*filter_pad) / filter_stride + 1
        conv_output_size_x = (input_size_x - filter_size + 2*filter_pad) / filter_stride + 1
        pool_output_size = int(filter_num * (conv_output_size_y/2) * (conv_output_size_x/2))
        print("pool_output_size ={0}".format(pool_output_size))

        # 重みの初期化
        self.params = {}
        self.params['W1'] = weight_init_std * \
                            np.random.randn(filter_num, input_dim[0], filter_size, filter_size)
        self.params['b1'] = np.zeros(filter_num)
        self.params['W2'] = weight_init_std * \
                            np.random.randn(pool_output_size, hidden_size)
        self.params['b2'] = np.zeros(hidden_size)
        self.params['W3'] = weight_init_std * \
                            np.random.randn(hidden_size, output_size)
        self.params['b3'] = np.zeros(output_size)

        # レイヤの生成
        self.layers = OrderedDict()
        self.layers['Conv1'] = Convolution(self.params['W1'], self.params['b1'],
                                           conv_param['stride'], conv_param['pad'])
        self.layers['Relu1'] = Relu()
        self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2)
        self.layers['Affine1'] = Affine(self.params['W2'], self.params['b2'])
        self.layers['Relu2'] = Relu()
        self.layers['Affine2'] = Affine(self.params['W3'], self.params['b3'])

        self.last_layer = SoftmaxWithLoss()

    def predict(self, x):
        for layer in self.layers.values():
            x = layer.forward(x)

        return x

    def loss(self, x, t):
        """損失関数を求める
        引数のxは入力データ、tは教師ラベル
        """
        y = self.predict(x)
        return self.last_layer.forward(y, t)

    def accuracy(self, x, t, batch_size=100):
        if t.ndim != 1 : t = np.argmax(t, axis=1)
        
        acc = 0.0
        
        for i in range(int(x.shape[0] / batch_size)):
            tx = x[i*batch_size:(i+1)*batch_size]
            tt = t[i*batch_size:(i+1)*batch_size]
            y = self.predict(tx)
            y = np.argmax(y, axis=1)
            acc += np.sum(y == tt) 
        
        return acc / x.shape[0]

    def numerical_gradient(self, x, t):
        """勾配を求める(数値微分)

        Parameters
        ----------
        x : 入力データ
        t : 教師ラベル

        Returns
        -------
        各層の勾配を持ったディクショナリ変数
            grads['W1']、grads['W2']、...は各層の重み
            grads['b1']、grads['b2']、...は各層のバイアス
        """
        loss_w = lambda w: self.loss(x, t)

        grads = {}
        for idx in (1, 2, 3):
            grads['W' + str(idx)] = numerical_gradient(loss_w, self.params['W' + str(idx)])
            grads['b' + str(idx)] = numerical_gradient(loss_w, self.params['b' + str(idx)])

        return grads

    def gradient(self, x, t):
        """勾配を求める(誤差逆伝搬法)

        Parameters
        ----------
        x : 入力データ
        t : 教師ラベル

        Returns
        -------
        各層の勾配を持ったディクショナリ変数
            grads['W1']、grads['W2']、...は各層の重み
            grads['b1']、grads['b2']、...は各層のバイアス
        """
        # forward
        self.loss(x, t)

        # backward
        dout = 1
        dout = self.last_layer.backward(dout)

        layers = list(self.layers.values())
        layers.reverse()
        for layer in layers:
            dout = layer.backward(dout)

        # 設定
        grads = {}
        grads['W1'], grads['b1'] = self.layers['Conv1'].dW, self.layers['Conv1'].db
        grads['W2'], grads['b2'] = self.layers['Affine1'].dW, self.layers['Affine1'].db
        grads['W3'], grads['b3'] = self.layers['Affine2'].dW, self.layers['Affine2'].db

        return grads
        
    def save_params(self, file_name="params.pkl"):
        params = {}
        for key, val in self.params.items():
            params[key] = val
        with open(file_name, 'wb') as f:
            pickle.dump(params, f)

    def load_params(self, file_name="params.pkl"):
        with open(file_name, 'rb') as f:
            params = pickle.load(f)
        for key, val in params.items():
            self.params[key] = val

        for i, key in enumerate(['Conv1', 'Affine1', 'Affine2']):
            self.layers[key].W = self.params['W' + str(i+1)]
            self.layers[key].b = self.params['b' + str(i+1)]


次に、Jupyter Notebook を立ち上げて、DLFS_Chap7.ipynb を起動した。
wlt_cnn_41_170808.png

train_convnet.py のdataset_straight.straight_dataset を読むように変更し、また、input_dim=(1,10,56) に変更した。
wlt_cnn_42_170808.png

train_convnet.py を貼っておく。

# train_convnet.py
# 2017/08/08 白線追従走行用CNNに変更 by marsee
# 元になったコードは、https://github.com/oreilly-japan/deep-learning-from-scratch にあります。
# 改変したコードもMITライセンスとします。 2017/08/08 by marsee

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

# データの読み込み
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)

# 処理に時間のかかる場合はデータを削減 
#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=(1,10,56), 
                        conv_param = {'filter_num': 30, 'filter_size': 5, 'pad': 0, 'stride': 1},
                        hidden_size=100, output_size=3, 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=100)
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()


train_convnet.py を実行した結果を貼っておく。

pool_output_size =2340
train loss:1.09740103666
=== epoch:1, train acc:0.0, test acc:0.0 ===
train loss:1.09619339353
train loss:1.09805550027
train loss:1.09687513729
train loss:1.0943589982
train loss:1.09043641309
train loss:1.08765370932
train loss:1.08988835762
train loss:1.08589893222
train loss:1.08082757519
train loss:1.07091805021
train loss:1.06677488283
train loss:1.07590794106
train loss:1.07036316486
train loss:1.0564093902
train loss:1.04913884878
=== epoch:2, train acc:1.0, test acc:1.0 ===
train loss:1.05282141475
train loss:1.02463171511
train loss:1.03238803274
train loss:1.01808300652
train loss:1.00418097479
train loss:0.994927691467
train loss:0.971943720127
train loss:0.938959564805
train loss:0.959999566898
train loss:0.964902849483
train loss:0.930027599907
train loss:0.910958350671
train loss:0.912115741252
train loss:0.877372771453
train loss:0.881933637438
=== epoch:3, train acc:1.0, test acc:1.0 ===
train loss:0.82203361721
train loss:0.875176827014
train loss:0.799964071175
train loss:0.801881639351
train loss:0.815978625085
train loss:0.779677387859
train loss:0.808213315743
train loss:0.779122522377
train loss:0.67732259731
train loss:0.664630569144
train loss:0.696595385714
train loss:0.804241795734
train loss:0.665426441902
train loss:0.672940861823
train loss:0.65431805427
=== epoch:4, train acc:1.0, test acc:1.0 ===
train loss:0.733642727716
train loss:0.724044016753
train loss:0.728747015891
train loss:0.645574644162
train loss:0.563772565951
train loss:0.650969893624
train loss:0.71471792151
train loss:0.562708504548
train loss:0.603808048409
train loss:0.599713674484
train loss:0.627750549668
train loss:0.554349357064
train loss:0.615028866599
train loss:0.581826815111
train loss:0.614025507529
=== epoch:5, train acc:0.98, test acc:0.98 ===
train loss:0.536548177427
train loss:0.616438072707
train loss:0.545175491413
train loss:0.59173160996
train loss:0.593612159015
train loss:0.599846111758
train loss:0.602536956687
train loss:0.526653021569
train loss:0.493542164942
train loss:0.652987814042
train loss:0.593193099959
train loss:0.651098995425
train loss:0.583797795175
train loss:0.497425254547
train loss:0.50022478405
=== epoch:6, train acc:1.0, test acc:0.99 ===
train loss:0.546986740154
train loss:0.632857452048
train loss:0.596720193602
train loss:0.628242539831
train loss:0.516102642255
train loss:0.584049938495
train loss:0.643520590658
train loss:0.433788079879
train loss:0.464739965862
train loss:0.517770447956
train loss:0.565927389082
train loss:0.574423786278
train loss:0.487440270503
train loss:0.460763808238
train loss:0.50437176485
=== epoch:7, train acc:0.91, test acc:0.8 ===
train loss:0.539680492517
train loss:0.43184783555
train loss:0.463142994517
train loss:0.40834945717
train loss:0.502730258745
train loss:0.530335381027
train loss:0.483509730618
train loss:0.419754214749
train loss:0.542743643599
train loss:0.545018581985
train loss:0.527738479101
train loss:0.552609220918
train loss:0.511188282627
train loss:0.439410114208
train loss:0.547204230479
=== epoch:8, train acc:0.87, test acc:0.74 ===
train loss:0.42177291798
train loss:0.37878361722
train loss:0.553163684557
train loss:0.573063758222
train loss:0.39186244896
train loss:0.445078706415
train loss:0.462594294123
train loss:0.438555772242
train loss:0.385638041553
train loss:0.415701287503
train loss:0.391015150038
train loss:0.468615281475
train loss:0.504983134551
train loss:0.377033870421
train loss:0.39501268333
=== epoch:9, train acc:0.95, test acc:0.89 ===
train loss:0.387747127634
train loss:0.385348791912
train loss:0.482271444765
train loss:0.397431981912
train loss:0.38837660175
train loss:0.456368766821
train loss:0.381980621014
train loss:0.320979196606
train loss:0.374925172354
train loss:0.424100142739
train loss:0.339776275437
train loss:0.379021958425
train loss:0.415783734932
train loss:0.312515924983
train loss:0.493949450648
=== epoch:10, train acc:0.99, test acc:0.9 ===
train loss:0.443524574076
train loss:0.357979512064
train loss:0.415673465881
train loss:0.362790259715
train loss:0.25231192493
train loss:0.405671943517
train loss:0.35069212333
train loss:0.372544883284
train loss:0.409110864872
train loss:0.343560294381
train loss:0.31804787133
train loss:0.403356537286
train loss:0.268652788357
train loss:0.394903753068
=============== Final Test Accuracy ===============
test acc:0.714666666667
Saved Network Parameters!
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-d6e09c53f736> in <module>()
     36 markers = {'train': 'o', 'test': 's'}
     37 x = np.arange(max_epochs)
---> 38 plt.plot(x, trainer.train_acc_list, marker='o', label='train', markevery=2)
     39 plt.plot(x, trainer.test_acc_list, marker='s', label='test', markevery=2)
     40 plt.xlabel("epochs")

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\pyplot.py in plot(*args, **kwargs)
   3316                       mplDeprecation)
   3317     try:
-> 3318         ret = ax.plot(*args, **kwargs)
   3319     finally:
   3320         ax._hold = washold

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\__init__.py in inner(ax, *args, **kwargs)
   1889                     warnings.warn(msg % (label_namer, func.__name__),
   1890                                   RuntimeWarning, stacklevel=2)
-> 1891             return func(ax, *args, **kwargs)
   1892         pre_doc = inner.__doc__
   1893         if pre_doc is None:

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py in plot(self, *args, **kwargs)
   1404         kwargs = cbook.normalize_kwargs(kwargs, _alias_map)
   1405 
-> 1406         for line in self._get_lines(*args, **kwargs):
   1407             self.add_line(line)
   1408             lines.append(line)

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _grab_next_args(self, *args, **kwargs)
    405                 return
    406             if len(remaining) <= 3:
--> 407                 for seg in self._plot_args(remaining, kwargs):
    408                     yield seg
    409                 return

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _plot_args(self, tup, kwargs)
    383             x, y = index_of(tup[-1])
    384 
--> 385         x, y = self._xy_from_xy(x, y)
    386 
    387         if self.command == 'plot':

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _xy_from_xy(self, x, y)
    242         if x.shape[0] != y.shape[0]:
    243             raise ValueError("x and y must have same first dimension, but "
--> 244                              "have shapes {} and {}".format(x.shape, y.shape))
    245         if x.ndim > 2 or y.ndim > 2:
    246             raise ValueError("x and y can be no greater than 2-D, but have "

ValueError: x and y must have same first dimension, but have shapes (20,) and (10,)

In [21]:

print(network.params['W1'].shape)


plot がなぜか?エラーになってしまう。

テストデータの正解率が 71 % になってしまうのは低すぎないだろうか?
もう一度、トレーニング・データを取り直してみようか?
  1. 2017年08月09日 03:34 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0