SimpleConvNet을 주피터에서 돌리기 - LOPES-HUFS/DeepLearningFromForR GitHub Wiki

아래 코드에서 필요한 클래스를 쥬피터에 미리 채워 넣고, simple_convnet_7.h5을 폴더에 넣은 다음 돌리면 아래와 같이 돌아간다.

import numpy as np 
import tensorflow as tf
from tensorflow import keras
import h5py
from keras.utils import np_utils
mnist = keras.datasets.mnist
(x_train, t_train), (x_test, t_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0], 1, 28, 28).astype('float64')
x_test = x_test.reshape(x_test.shape[0], 1, 28, 28).astype('float64')
x_train, x_test = x_train / 255.0, x_test / 255.0
x_train_100 = x_train[0:100,:,:,:]
#import numpy as np
nb_classes = 6
data = [2, 3, 4, 0](/LOPES-HUFS/DeepLearningFromForR/wiki/2,-3,-4,-0)

def indices_to_one_hot(data, nb_classes):
    """Convert an iterable of indices to one-hot encoded labels."""
    targets = np.array(data).reshape(-1)
    return np.eye(nb_classes)[targets]

t_train_100 = indices_to_one_hot(t_train[0:100], 10)
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, 28, 28), 
                 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 = input_dim[1]
        conv_output_size = (input_size - filter_size + 2*filter_pad) / filter_stride + 1
        pool_output_size = int(filter_num * (conv_output_size/2) * (conv_output_size/2))

        # 重みの初期化
        hf = h5py.File('simple_convnet_7.h5', 'r')
        hf.keys()
        params['W1'] = hf.get('W1')
        params['W1'] = np.array(params['W1'])
        params['W2'] = hf.get('W2')
        params['W2'] = np.array(params['W2'])
        params['W3'] = hf.get('W3')
        params['W3'] = np.array(params['W3'])
        hf.close()
        
        self.params = {}
        self.params['W1'] = params['W1']
        #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['W2'] = params['W2']
        self.params['b2'] = np.zeros(hidden_size)
        #self.params['W3'] = weight_init_std * \
        #                    np.random.randn(hidden_size, output_size)
        self.params['W3'] = params['W3']
        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
network = SimpleConvNet(input_dim=(1,28,28), 
                        conv_param = {'filter_num': 30, 'filter_size': 5, 'pad': 0, 'stride': 1},
                        hidden_size=100, output_size=10, weight_init_std=0.01)
temp_network = network.gradient(x_train_100, t_train_100)
temp_network['b2']
array([ 1.13699712e-04, -4.29507837e-04,  4.71714423e-04, -7.16677820e-05,
       -1.17173921e-05,  1.41251011e-04,  1.30049931e-03, -8.63587884e-05,
        5.17859257e-04,  8.84411753e-04,  7.65561502e-04,  8.94050291e-05,
        9.32573578e-05,  1.37477149e-03,  5.00705892e-04,  1.46325479e-04,
        3.02025904e-04, -9.62641534e-04, -1.76420979e-03, -7.87698304e-04,
        4.85357144e-05, -9.11073628e-04,  2.52054550e-04, -1.29024335e-03,
        1.39014763e-04,  7.19705325e-04, -2.86479329e-05, -3.36708993e-05,
       -1.40866207e-04, -8.35243862e-04, -5.86974021e-04,  7.69837622e-06,
        6.47731337e-04, -3.21919105e-05, -1.62805397e-04, -1.24341778e-03,
        5.65282352e-04, -6.14486575e-04, -6.67954021e-04, -4.99853321e-04,
        9.78107945e-04,  1.96397320e-04,  1.72905028e-05,  1.06492456e-03,
        3.81550800e-05, -2.29788199e-04, -3.39012663e-04,  1.62358373e-04,
        2.28840405e-04,  9.14060899e-04, -7.77821848e-04, -7.74494830e-04,
       -2.06424376e-04, -1.40858049e-04,  4.61756875e-04, -1.56278450e-03,
       -1.84003721e-03,  4.64306361e-04, -2.18224066e-04,  9.65499452e-04,
        8.92501212e-04, -6.29480291e-04, -2.22677129e-04,  1.17979308e-03,
        1.61359668e-04,  1.04861107e-04, -8.77427823e-04, -4.16142822e-04,
       -1.35221922e-03,  6.12461262e-04,  1.15719992e-04,  1.47491435e-04,
        3.83007761e-04, -2.64106906e-04, -1.33239547e-05,  3.77785677e-05,
       -2.39847186e-04,  0.00000000e+00,  5.92925946e-04,  6.40392804e-04,
        8.56004223e-04,  5.39916724e-04, -2.73564848e-04,  0.00000000e+00,
        9.71619074e-04,  3.09403995e-04,  3.90876323e-04, -1.58906367e-03,
        2.13654319e-03, -1.08551966e-03, -5.27603802e-04, -1.44884157e-03,
       -2.03661078e-03,  9.47791735e-04,  2.50277621e-04,  6.11453738e-05,
        1.06337897e-04, -2.01938759e-03, -2.14810419e-04, -4.68517236e-04])