質問編集履歴

2

該当コードを載せないと分かりにくいとのご指摘を受けたのでコードを載せました。

2022/02/11 13:36

投稿

ai_learner
ai_learner

スコア10

test CHANGED
File without changes
test CHANGED
@@ -1,4 +1,4 @@
1
- # 解決したい問題
1
+ ![# 解決したい問題
2
2
  3600個の画像データをミニバッチ処理するCNNを含んだニューラルネットワークの中の活性化関数の手前にBatch Normalizationを入れたいが、一個でも入れると ”ValueError: operands could not be broadcast together with shapes (50176,16) (12544,16) ”と エラーが出てしまい実行できない。
3
3
  該当する行列はmu(バッチ正規化する際の平均値)の行列
4
4
 
@@ -8,40 +8,197 @@
8
8
  なぜなら、上記の例では、データ数:3600、batch size:64でその商が56と1/4であり、12544は50176の1/4であるからだ。
9
9
  しかし、バッチサイズをデータ数を割り切れる数字(例:100)に設定したところ、再び、”ValueError: operands could not be broadcast together with shapes (78400,16) (2822400,16) ”とエラーが出てしまい、何が原因なのか、わからなくなってしまいました。
10
10
 
11
-
12
-
13
-
14
- エラー文全文
15
-
16
-
17
- `ValueError Traceback (most recent call last)
18
- <ipython-input-33-eaa9794c89e7> in <module>
19
- 43
20
- 44 # 訓練データおけloss
21
- ---> 45 train_loss.append(dcn.loss(X_train, y_train))
22
- 46
23
- 47 # テストデータにおけるloss
24
-
25
- <ipython-input-9-a33e61666ae3> in loss(self, x, t)
26
- 63
27
- 64 def loss(self, x, t):
28
- ---> 65 y = self.predict(x, train_flg=True)
29
- 66 return self.last_layer.forward(y, t)
30
- 67
31
-
32
- <ipython-input-9-a33e61666ae3> in predict(self, x, train_flg)
33
- 59 x = layer.forward(x, train_flg)
34
- 60 else:
35
- ---> 61 x = layer.forward(x)
36
- 62 return x
37
- 63
38
-
39
- ~/Downloads/*****/畳み込み/common/layers.py in forward(self, x, train_flg)
40
- 315 x = x.transpose(0, 2, 3, 1) # NHWCに入れ替え
41
- 316 x = x.reshape(N*H*W, C) # (N*H*W,C)の2次元配列に変換
42
- --> 317 out = self.__forward(x, train_flg)
43
- 318 out = out.reshape(N, H, W, C)# 4次元配列に変換
44
- 319 out = out.transpose(0, 3, 1, 2) # 軸をNCHWに入れ替え
11
+ ### 該当コード
12
+ ### テキスト畳み込みニューラルネットワーク(ゼロから作るディープラーニング1のドロップアウトをバッチノーマライゼーションに変更)は文字数制約のため添付写真に表示
13
+
14
+
15
+ #### バッチノーマライゼーションのコード
16
+
17
+ ```Python3
18
+ class BatchNormalization:
19
+ def __init__(self, gamma, beta, rho=0.9, moving_mean=None, moving_var=None):
20
+ self.gamma = gamma # 学習よって更新させ.
21
+ self.beta = beta # 学習によって更新させる
22
+ self.rho = rho
23
+
24
+ # 予測時に使用する平均と分散
25
+ self.moving_mean = moving_mean # muの移動平均
26
+ self.moving_var = moving_var # varの移動平均
27
+
28
+ # 計算中に算出される値を保持しておく変数群
29
+ self.batch_size = None
30
+ self.x_mu = None
31
+ self.x_std = None
32
+ self.std = None
33
+ self.dgamma = None
34
+ self.dbeta = None
35
+
36
+ def forward(self, x, train_flg=True):
37
+ """
38
+ 順伝播計算
39
+ x : CNNの場合は4次元、全結合層の場合は2次元
40
+ """
41
+ if x.ndim == 4:
42
+ """
43
+ 画像形式の場合
44
+ """
45
+ N, C, H, W = x.shape
46
+ x = x.transpose(0, 2, 3, 1) # NHWCに入れ替え
47
+ x = x.reshape(N*H*W, C) # (N*H*W,C)の2次元配列に変換
48
+ out = self.__forward(x, train_flg)
49
+ out = out.reshape(N, H, W, C)# 4次元配列に変換
50
+ out = out.transpose(0, 3, 1, 2) # 軸をNCHWに入れ替え
51
+ elif x.ndim == 2:
52
+ """
53
+ 画像形式以外の場合
54
+ """
55
+ out = self.__forward(x, train_flg)
56
+
57
+ return out
58
+
59
+ def __forward(self, x, train_flg, epsilon=1e-8):
60
+ """
61
+ x : 入力. N×Dの行列. Nはバッチサイズ. Dは手前の層のノード数
62
+ """
63
+ if (self.moving_mean is None) or (self.moving_var is None):
64
+ N, D = x.shape
65
+ self.moving_mean = np.zeros(D)
66
+ self.moving_var = np.zeros(D)
67
+
68
+ if train_flg:
69
+ """
70
+ 学習時
71
+ """
72
+ # 入力xについて、Nの方向に平均値を算出.
73
+ N, D = x.shape
74
+ mu = np.mean(x, axis=0) # 要素数D個のベクトル
75
+ mu = np.broadcast_to(mu, (N, D)) # Nの方向にブロードキャスト
76
+ print("mu.shape=", mu.shape)
77
+
78
+ # 入力xから平均値を引く
79
+ x_mu = x - mu # N×D行列
80
+ print("x_mu.shape=", x_mu.shape)
81
+
82
+ # 入力xの分散を求める
83
+ var = np.mean(x_mu**2, axis=0) # 要素数D個のベクトル
84
+ print("var.shape=", var.shape)
85
+
86
+ # 入力xの標準偏差を求める(epsilonを足してから標準偏差を求める)
87
+ std = np.sqrt(var + epsilon) # 要素数D個のベクトル
88
+ print("std.shape=", std.shape)
89
+
90
+ # 標準偏差の逆数を求める
91
+ std_inv = 1 / std
92
+ std_inv = np.broadcast_to(std_inv, (N, D)) # Nの方向にブロードキャスト
93
+ print("std_inv.shape=", std_inv.shape)
94
+
95
+ # 標準化
96
+ x_std = x_mu * std_inv #N*D行列
97
+ print("x_std.shape=", x_std.shape)
98
+
99
+ # 値を保持しておく
100
+ self.batch_size = x.shape[0]
101
+ self.x_mu = x_mu
102
+ self.x_std = x_std
103
+ self.std = std
104
+ self.moving_mean = self.rho * self.moving_mean + (1-self.rho) * mu
105
+ self.moving_var = self.rho * self.moving_var + (1-self.rho) * var
106
+ else:
107
+ """
108
+ 予測時
109
+ """
110
+ x_mu = x - self.moving_mean # N*D行列
111
+ x_std = x_mu / np.sqrt(self.moving_var + epsilon) # N*D行列
112
+
113
+ # gammaでスケールし、betaでシフトさせる
114
+ out = self.gamma * x_std + self.beta # N*D行列
115
+ return out
116
+
117
+ def backward(self, dout):
118
+ """
119
+ 逆伝播計算
120
+ dout : CNNの場合は4次元、全結合層の場合は2次元
121
+ """
122
+ if dout.ndim == 4:
123
+ """
124
+ 画像形式の場合
125
+ """
126
+ N, C, H, W = dout.shape
127
+ dout = dout.transpose(0, 2, 3, 1) # NHWCに入れ替え
128
+ dout = dout.reshape(N*H*W, C) # (N*H*W,C)の2次元配列に変換
129
+ dx = self.__backward(dout)
130
+ dx = dx.reshape(N, H, W, C)# 4次元配列に変換
131
+ dx = dx.transpose(0, 3, 1, 2) # 軸をNCHWに入れ替え
132
+ elif dout.ndim == 2:
133
+ """
134
+ 画像形式以外の場合
135
+ """
136
+ dx = self.__backward(dout)
137
+
138
+ return dx
139
+
140
+ def __backward(self, dout):
141
+ """
142
+ ここを完成させるには、計算グラフを理解する必要があり、実装にかなり時間がかかる.
143
+ """
144
+ N, D = self.x_.shape
145
+
146
+ # betaの勾配
147
+ dbeta = np.sum(dout, axis=0)
148
+
149
+ # gammaの勾配(Nの方向に合計)
150
+ dgamma = np.sum(self.x_std * dout, axis=0)
151
+
152
+ # Xstdの勾配
153
+ a1 = self.gamma * dout
154
+ print("a1.shape=", a1.shape)
155
+
156
+ # Xmuの勾配(1つ目)
157
+ a2 = a1 / self.std
158
+ print("a2.shape=", a2.shape)
159
+
160
+ # 標準偏差の逆数の勾配
161
+ a3 = a1 * self.x_mu
162
+ print("a3.shape=", a3.shape)
163
+ a3 = np.sum(a3, axis=0) # Nの方向に合計
164
+
165
+ # 標準偏差の勾配
166
+ a4 = -(a3) / (self.std * self.std)
167
+ print("a4.shape=", a4.shape)
168
+
169
+ # 分散の勾配
170
+ a5 = 0.5 * a4 / self.std
171
+ print("a5.shape=", a5.shape)
172
+
173
+ # Xmuの2乗の勾配
174
+ a6 = a5 / self.batch_size
175
+ a6 = np.broadcast_to(a6, (N, D)) # Nの方向にブロードキャスト
176
+ print("a6=",a6)
177
+ print("a6.shape=", a6.shape)
178
+
179
+ # Xmuの勾配(2つ目)
180
+ a7 = 2.0 * self.x_mu * a6
181
+ print("a7.shape=", a7.shape)
182
+
183
+ # muの勾配
184
+ a8 = -(a2+a7)
185
+ print("a8.shape=", a8.shape)
186
+ a8 = np.sum(a8, axis=0) # Nの方向に合計
187
+
188
+ # Xの勾配
189
+ a9 = a8 / self.batch_size
190
+ a9 = np.broadcast_to(a9, (N, D)) # Nの方向にブロードキャスト
191
+ dx = a2 + a7 + a9
192
+ print("a9.shape=", a9.shape)
193
+
194
+ self.dgamma = dgamma
195
+ self.dbeta = dbeta
196
+
197
+ return dx
198
+ ```
199
+
200
+
201
+ エラー文
45
202
 
46
203
  ~/Downloads/*****/畳み込み/common/layers.py in __forward(self, x, train_flg, epsilon)
47
204
  371 self.x_std = x_std
@@ -54,11 +211,11 @@
54
211
 
55
212
 
56
213
 
57
- ご回答いただけたら、幸いです。
214
+ ご回答いただけたら、幸いです。](https://ddjkaamml8q8x.cloudfront.net/questions/2022-02-11/a99998cf-725f-4dac-8169-3cab12cdf9b5.png)
58
-
59
-
60
-
61
-
62
-
63
-
64
-
215
+
216
+
217
+
218
+
219
+
220
+
221
+

1

ミニバッチ処理していることを明記していなかったので、明記いたしました。

2022/02/09 02:27

投稿

ai_learner
ai_learner

スコア10

test CHANGED
File without changes
test CHANGED
@@ -1,5 +1,5 @@
1
1
  # 解決したい問題
2
- 3600個の画像データを処理するCNNを含んだニューラルネットワークの中の活性化関数の手前にBatch Normalizationを入れたいが、一個でも入れると ”ValueError: operands could not be broadcast together with shapes (50176,16) (12544,16) ”と エラーが出てしまい実行できない。
2
+ 3600個の画像データをミニバッチ処理するCNNを含んだニューラルネットワークの中の活性化関数の手前にBatch Normalizationを入れたいが、一個でも入れると ”ValueError: operands could not be broadcast together with shapes (50176,16) (12544,16) ”と エラーが出てしまい実行できない。
3
3
  該当する行列はmu(バッチ正規化する際の平均値)の行列
4
4
 
5
5
  # 自分なりに考えたこと