ディープラーニングについてディープにラーニング。

思いっきり、自分が学んだことのアウトプットしていきますが、何分初心者。もし何かアドバイス等頂けましたら幸いです!

CNNの実装

今日もアウトプットから。

f:id:kawam0t0:20191228184930p:plain

今回は、
このようなネットワークの構成でモデルを作成する。

重み、バイアスについては、
Conv層・Affine層(全結層)・Affine層(全結層)の3か所に当てはめる。

↓コード

import numpy as np

class SimpleConvNet:
    #input_dim -> 入力データ
    """
    5×5のフィルターが30個ある。パディングは0でストライドは1。
    更に隠れ層は100層あって、アウトプットは10個、最初の学習係数は0.01に設定
    引数にディクショナリーってあるんや笑
    """
    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"]
        #入力データのサイズ: 28
        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))
        
        #重みの初期化
        self.params = {}
        #まさかのこれでキーと値が追加できるってよ笑
        #np.random.randn -> ①重みの個数②チャネル数③行サイズ④列サイズ
        #5×5のフィルターサイズでチャネル数は1のフィルターが30個ある
        self.params["w1"] = weight_init_std * np.random.randn(filter_num,input_dim[0],filter_size,filter_size)
        #3次元のベクトルデータ
        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 , out_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_layers = SoftmaxWithLoss()
        
    """
    xは入力データでtは教師ラベルになる。
    """
    def predict(self,x):
        for layer in self.layers.values():
            x = layer.forward(x)
        return x
    
    def loss(self , x , t):
        y = self.predict(x)
        
        return self.lastLayer.forward(y,t)
        
    def gradient(self , x ,t):
        #forward
        self.loss(x,t)
        #backward→逆伝播を行う
        dout = 1
        dout = self.Lastlayer.backward(dout)
        
        layers = list(self.layers.values())
        layers.reverse()
        for layer in layers:
            dout = layer.backward(dout)
        grads = {}
        grads["w1"] = self.layers["conv1"].dw
        grads["b1"] = self.layers["conv1"].db
        grads["w2"] = self.layers["Affine1"].dw
        grads["b2"] = self.layers["Affine1"].db
        grads["w3"] = self.layers["Affine2"].dw
        grads["b3"] = self.layers["Affine2"].db
        
        return grads

第一層での重みはサイズが5×5のチャネル数が1の重みが30個あった。
この重みは学習回数を重ねていったり、
層が深くなるにつれて、抽象的な曲線に変化していく。
初めの層は横、縦、など、かなり線形のグラデーションだった。