ゼロから作るdeep learningのim2colとcol2im関数のみを用いて, かんたんな畳込みネットワークを作成しようとしているのですが, うまく学習が行えていません。
下のプログラムで決定的な誤りがある箇所はありますか?
学習率と活性化関数とバイアスは考えないでプログラムしています。
CNNの構成は、入力→畳み込み層→畳み込み層2→全結合層を想定しています。
全結合層から2乗誤差を逆伝搬して誤差逆伝搬を実装しています。
下のプログラムでは、簡略化のために、入力はnp.arrangeで実装しています。
入力はmnistを想定してのこの形となっています。
学習した結果、テストしたところ、出力の最大の要素が全て同じになってしまい、正しく学習がされていないようです。
col2imや逆伝搬の使い方に誤りがあるのでしょうか?
python
1 2import numpy as np 3 4def im2col(input_data, filter_h, filter_w, stride_h=1, stride_w=1, pad_h=0, pad_w=0): 5 6 N, C, H, W = input_data.shape 7 out_h = (H + 2*pad_h - filter_h)//stride_h + 1 8 out_w = (W + 2*pad_w - filter_w)//stride_w + 1 9 10 img = np.pad(input_data, [(0,0), (0,0), (pad_h, pad_h), (pad_w, pad_w)], 'constant') 11 col = np.zeros((N, C, filter_h, filter_w, out_h, out_w)) 12 13 for y in range(filter_h): 14 y_max = y + stride_h*out_h 15 for x in range(filter_w): 16 x_max = x + stride_w*out_w 17 col[:, :, y, x, :, :] = img[:, :, y:y_max:stride_h, x:x_max:stride_w] 18 19 col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1) 20 return col, out_h, out_w 21 22def col2im(col, input_shape, filter_h, filter_w, stride=1, pad=0): 23 N, C, H, W = input_shape 24 out_h = (H + 2*pad - filter_h)//stride + 1 25 out_w = (W + 2*pad - filter_w)//stride + 1 26 col = col.reshape(N, out_h, out_w, C, filter_h, filter_w).transpose(0, 3, 4, 5, 1, 2) 27 28 img = np.zeros((N, C, H + 2*pad + stride - 1, W + 2*pad + stride - 1)) 29 for y in range(filter_h): 30 y_max = y + stride*out_h 31 for x in range(filter_w): 32 x_max = x + stride*out_w 33 img[:, :, y:y_max:stride, x:x_max:stride] += col[:, :, y, x, :, :] 34 35 return img[:, :, pad:H + pad, pad:W + pad] 36 37def f(x): 38 y = 1 / (1 + np.exp(-0.01*x)) 39 return y 40 41#フィルタ 42#w = np.arange(5*1*9*9).reshape(5,1,9,9) 43w = np.random.rand(5,1,9,9)/100 44 45#2層目フィルタ 46#w2 = np.arange(5*5*9*9).reshape(5,5,9,9) 47w2 = np.random.rand(5,5,9,9)/100 48 49#全結合層重み 50w_affine = np.random.rand(6*6*5,10)/100 51 52for i in range(1000):#学習回数 53 #入力 54 x = np.arange(6*1*28*28).reshape(6,1,28,28) 55 x = 0.0001*x 56 57 #入力2次元化 58 col_x,out_h,out_w = im2col(x,9,9,1,1,0,0)#入力, フィルタサイズ9, ストライド1 59 60 #1層目フィルタ2次元化 61 col_w = w.reshape(5,-1).T 62 #1層目畳み込み計算 63 conv1_col = np.dot(col_x, col_w) 64 65 #1層目畳み込み層変換 66 conv1 = conv1_col.reshape(x.shape[0], out_h, out_w, -1).transpose(0, 3, 2, 1) 67 68 #2層目フィルタ2次元化 69 col_w2 = w2.reshape(5,-1).T 70 71 #2層目畳み込み計算(2次元) 72 input_col,out_h,out_w = im2col(conv1,9,9,2,2,0,0)#cov1, フィルタサイズ9,ストライド2 73 conv2_col = np.dot(input_col, col_w2) 74 conv2 = conv2_col.reshape(conv1.shape[0], out_h, out_w, -1).transpose(0, 3, 2, 1) 75 76 #全結合層出力 77 z = conv2.reshape(conv2.shape[0],-1) 78 y = f(np.dot(z,w_affine)) 79 80 t = np.zeros((6,10)) 81 #教師信号 82 for i in range(6): 83 t[i,i]=1 84 85 #全結合層誤差 86 Error2 = (t - y) * (1 - y) * y 87 88 a = 1e-5 89 #affine層更新 90 w_affine += a * np.dot(z.T, Error2) 91 92 #畳み込み層2誤差(1次元) 93 Error1 = np.dot(Error2, w_affine.T) 94 95 #畳み込み層誤差変換 96 dout2 = Error1.reshape(6,5,6,6) 97 dout2 = dout2.transpose(0,2,3,1).reshape(-1,5) 98 99 #w2更新 100 dw2 = np.dot(input_col.T,dout2) 101 dw2 = dw2.transpose(1,0).reshape(5,5,9,9) 102 w2 += a * dw2 103 104 #畳み込み層1誤差 105 dout1_col = np.dot(dout2,col_w2.T) 106 dout1 = col2im(dout1_col,conv1.shape,9,9,2,0) 107 dout1 = dout1.transpose(0,2,3,1).reshape(-1,5) 108 109 #w1更新 110 dw1 = np.dot(col_x.T,dout1) 111 dw1 = dw1.transpose(1,0).reshape(5,1,9,9) 112 w += a * dw1 113 114#学習結果をテスト 115#入力 116x = np.arange(6*1*28*28).reshape(6,1,28,28) 117x = 0.0001*x 118 119#フィルタ 120#w = np.arange(5*1*9*9).reshape(5,1,9,9) 121#w = 0.01*w 122 123#入力2次元化 124col_x,out_h,out_w = im2col(x,9,9,1,1,0,0)#入力, フィルタサイズ9, ストライド1 125 126#1層目フィルタ2次元化 127col_w = w.reshape(5,-1).T 128#1層目畳み込み計算 129conv1_col = np.dot(col_x, col_w) 130 131#1層目畳み込み層変換 132conv1 = conv1_col.reshape(x.shape[0], out_h, out_w, -1).transpose(0, 3, 2, 1) 133 134#2層目フィルタ 135#w2 = np.arange(5*5*9*9).reshape(5,5,9,9) 136#w2 = 0.01*w2 137 138#2層目フィルタ2次元化 139col_w2 = w2.reshape(5,-1).T 140 141#2層目畳み込み計算(2次元) 142input_col,out_h,out_w = im2col(conv1,9,9,2,2,0,0)#cov1, フィルタサイズ9,ストライド2 143conv2_col = np.dot(input_col, col_w2) 144conv2 = conv2_col.reshape(conv1.shape[0], out_h, out_w, -1).transpose(0, 3, 2, 1) 145 146#全結合層重み 147#w_affine = np.random.rand(6*6*5,10) 148 149#全結合層出力 150z = conv2.reshape(conv2.shape[0],-1) 151y = f(np.dot(z,w_affine)) 152y_max = np.argmax(y,axis=1) 153 154print(y) 155print(y_max) 156print(t)
回答2件
あなたの回答
tips
プレビュー