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




回答1件
あなたの回答
tips
プレビュー