CNNの実装
今日もアウトプットから。
今回は、
このようなネットワークの構成でモデルを作成する。
重み、バイアスについては、
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個あった。
この重みは学習回数を重ねていったり、
層が深くなるにつれて、抽象的な曲線に変化していく。
初めの層は横、縦、など、かなり線形のグラデーションだった。