def backward(self, dout): dout2 = np.zeros((dout.size, self.N)) dout2[np.arange(dout.size), self.arg_max] = dout.flatten() dout3 = np.zeros(self.u.shape) dout3[:, np.arange(self.u.shape[1])] = dout2[:, np.arange(self.u.shape[1])].T.reshape(dout2.shape+(1,1)) dout2 = dout3 # Conv backward FN, C, FH, FW = self.W.shape if self.activation == 'tanh': dout2 = dout2 * (1 - (np.tanh(self.u))**2) elif self.activation == 'Relu': dout2[self.mask] = 0 elif self.activation == 'None': pass FN, C, FH, FW = self.W.shape dout2 = dout2.transpose(0,2,3,1).reshape(-1, FN) if self.bias: self.db = np.sum(dout2, axis=0) self.dW = np.dot(self.x_col.T, dout2) self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH, FW) dconv = np.dot(dout2, self.W_col.T) dx = col2im(dconv, self.x.shape, FH, FW, self.T, 0) # update if self.optimizer == 'SGD': self.dW = np.sum(self.dW, axis=0) self.W = self.W - self.lr * self.dW if self.bias: self.b = self.b - self.lr * self.db if self.optimizer == 'Adam': if self.m is None: self.m = np.zeros_like(self.dW) self.v = np.zeros_like(self.dW) self.iter += 1 lr_t = self.lr * np.sqrt(1.0 - beta2**self.iter) / (1.0 - beta1**self.iter) self.m += (1 - beta1) * (self.dW - self.m) self.v += (1 - beta2) * (self.dW**2 - self.v) deltaW = np.sum(self.m / (np.sqrt(self.v) + 1e-7), axis=0) / self.m.shape[0] self.W = self.W - lr_t * deltaW self.W[self.W_mask] = 0 self.W_update(self.arg_max) if self.bias: if self.bm is None: self.bm = np.zeros_like(self.db) self.bv = np.zeros_like(self.db) self.bm += (1 - beta1) * (self.db - self.bm) self.bv += (1 - beta2) * (self.db**2 - self.bv) self.b = self.b - lr_t * self.bm / (np.sqrt(self.bv) + 1e-7) return dx
def update_x_by_inpainting(self, y, v, u, pixelMask): H, W = y.shape patchSize = int(np.sqrt(self.D)) rec_from_patches = col2im(v.T + u, patchSize, H, W) x = np.zeros((H, W)) x[~pixelMask] = y[~pixelMask] x[pixelMask] = rec_from_patches[pixelMask] return x
def backward(self, dout): dout = dout.transpose(0, 2, 3, 1) pool_size = self.fh * self.fw davg = dout / pool_size davg = np.repeat(davg, pool_size) davg = davg.reshape(dout.shape + (pool_size,)) dcol = davg.reshape(davg.shape[0] * davg.shape[1] * davg.shape[2], -1) return col2im(dcol, (self.batch_size, *self.input_shape), self.fh, self.fw, self.stride_h, self.stride_w, self.padding)
def backward(self, dout): oc, c, fh, fw = self.w.shape dout = dout.transpose(0,2,3,1).reshape(-1, oc) db = np.sum(dout, axis=0) dW = np.dot(self.col.T, dout).transpose(1, 0).reshape(oc, c, fh, fw) self.grads[0][...] = dW self.grads[1][...] = db dcol = np.dot(dout, self.col_w.T) return col2im(dcol, self.x.shape, fh, fw, self.stride_h, self.stride_w, self.padding)
def backward(self, dout): dout = dout.transpose(0, 2, 3, 1) pool_size = self.fh * self.fw dmax = np.zeros((dout.size, pool_size), skml_config.config.f_type) dmax[np.arange(self.arg_max.size), self.arg_max.flatten()] = dout.flatten() dmax = dmax.reshape(dout.shape + (pool_size,)) dcol = dmax.reshape(dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1) dx = col2im(dcol, (self.batch_size, *self.input_shape), self.fh, self.fw, self.stride_h, self.stride_w, self.padding) return dx
def backward(self, dout): N, C, oh, ow = dout.shape dtmp = dout.transpose(0, 2, 3, 1).reshape(-1) dy = np.zeros((dout.size, self.fw * self.fh)) dy[np.arange(self.mask.size), self.mask.flatten()] = dtmp dy = dy.reshape(N * oh * ow, C * self.fh * self.fw) img = col2im(self.din_shape, dy, self.fh, self.fw, self.stride, self.pad) return img
def piece_up_patches(): result = col2im(v.T + u, patchSize, H, W, normalize=False).ravel() for mask, idx in self.PgnPart.items(): maskLst = np.array(list(mask), dtype=bool) result += np.bincount( idx.ravel(), minlength=H * W, weights=(uPart[mask][:, np.newaxis] + vPart[mask][:, maskLst]).ravel()) result /= D return result.reshape(y.shape)
def backward(self, dout): FN, C, FH, FW = self.W.shape dout = dout.transpose(0, 2, 3, 1).reshape(-1, FN) self.db = np.sum(dout, axis=0) self.dW = np.dot(self.col.T, dout) self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH, FW) dcol = np.dot(dout, self.col_W.T) dx = col2im(dcol, self.x.shape, FH, FW, self.stride, self.pad) return dx
def backward(self, dout): dout = dout.transpose(0, 2, 3, 1) pool_size = self.pool_h * self.pool_w dmax = np.zeros((dout.size, pool_size)) dmax[np.arange(self.arg_max.size), self.arg_max.flatten()] = dout.flatten() dmax = dmax.reshape(dout.shape + (pool_size,)) dcol = dmax.reshape(dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1) dx = col2im(dcol, self.x.shape, self.pool_h, self.pool_w, self.stride, self.pad) return dx
def backward(self, dout): N, nf, oh, ow = dout.shape tmp_dout = dout.copy() tmp_dout = dout.transpose(0, 2, 3, 1).reshape(N * oh * ow, -1) self.dw = np.dot(self.din.transpose(), tmp_dout).reshape(self.fc, self.fh, self.fw, self.nf).transpose(3, 0, 1, 2) self.db = np.sum(tmp_dout, axis=0) #comput output dy col_w = self.w.reshape(self.nf, -1) col_dy = np.dot(tmp_dout, col_w) dy = col2im(self.din_shape, col_dy, self.fh, self.fw, self.stride, self.pad) return dy
def backward(self, dout): FN, C, FH, FW = self.W.shape dout = dout.transpose(0, 2, 3, 1).reshape(-1, FN) # (N, OH, OW, FN) -> (N * OH * OW, FN) self.db = np.sum(dout, axis=0) # (FN, 1, 1) ? self.dW = np.dot(self.col.T, dout) # self.dW = np.dot(self.x.T, dout) # (C * FH * FW, N * OH * OW) * (N * OH * OW, FN) # -> (C * FH * FW, FN) self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH, FW) dcol = np.dot(dout, self.col_W.T) # dx = np.dot(dout, self.W.T) # (N * OH * OW, FN) * (FN, C * FH * FW) # -> (N * OH * OW, C * FH * FW) dx = col2im(dcol, self.x.shape, FH, FW, self.stride, self.pad) # (N, C, H, W) return dx
def backward(self, dout): dout = dout.transpose(0, 2, 3, 1) # (N, OH, OW, C) pool_size = self.pool_h * self.pool_w dmax = np.zeros((dout.size, pool_size)) # (N * OH * OW * C, PH * PW) dmax[ np.arange(self.arg_max.size), self.arg_max.flatten() ] = dout.flatten() # np.arange(self.arg_max.size) : 0, 1, 2, ....., arg_max.size-1 # self.arg_max.flatten() : indices of the maximum values into arg_max, flattened to one dimension. # dout.flatten() : (N * OH * OW * C, 1) dmax = dmax.reshape(dout.shape + (pool_size,)) # (N, OH, OW, C, PH * PW) # can only concatenate tuple dcol = dmax.reshape(dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1) # (N * OH * OW, C * PH * PW) dx = col2im(dcol, self.x.shape, self.pool_h, self.pool_w, self.stride, self.pad) # (N, C, H, W) return dx
def backward(self, t): if self.pool_or_not: # Pooling層の逆伝搬 t = t.transpose(0, 2, 3, 1) pool_size = self.pool_h * self.pool_w if self.pool == 'max': dmax = 2 * np.ones((t.size, pool_size), dtype='complex64') dmax[np.arange(self.arg_max.size), self.arg_max.flatten()] = t.flatten() dmax = dmax.reshape(t.shape + (pool_size, )) t1_col = dmax.reshape( dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1) t1 = col2im(t1_col, self.conv_y.shape, self.pool_h, self.pool_w, self.pool_stride, self.pool_pad) t13 = t1 t1[t1 == 2] = self.conv_y[t1 == 2] # Convolutionの重みの教師信号 elif self.pool == 'avg': dmax = np.zeros((t.size, pool_size), dtype='complex64') for i in range(pool_size): dmax[np.arange(self.pool_x_col.shape[0]), i] = 1 / self.pool_x_col.shape[1] * t.flatten() dmax = dmax.reshape(t.shape + (pool_size, )) t1_col = dmax.reshape( dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1) t1 = col2im(t1_col, self.conv_y.shape, self.pool_h, self.pool_w, self.pool_stride, self.pool_pad) t13 = t1 #t1_col = t1.transpose(0,2,3,1) #t1_col = t1.reshape(t1_col.shape[0] * t1_col.shape[1] * t1_col.shape[2], -1) #t12 = col2im(t1_col, self.conv_y.shape, self.pool_h, self.pool_w, self.pool_stride, self.pool_pad) #t12[t12 == 0] = 0 t12 = t1 # Convolution層の逆伝搬 filternum, channel, filter_h, filter_w = self.W.shape if not self.pool_or_not: t1 = t t12 = t t1_col2 = t12.transpose(0, 2, 3, 1).reshape(-1, filternum) if self.batchnorm: t1_col2 = ( np.sqrt(self.sigma_sq + self.epsilon) * np.abs(t1_col2) + self.min - self.epsilon) * np.exp(1.j * np.angle(t1_col2)) if backpro == 0: if cbp == 0: t_tmp = np.dot(self.mag * self.W_col, np.conj(t1_col2.T)) if cbp == 1: dmax = g_repmat(t.flatten().reshape(-1, 1), 1, pool_size) dmax = dmax.reshape(t.shape + (pool_size, )) t1_col = dmax.reshape( dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1) t1 = col2im(t1_col, self.conv_y.shape, self.pool_h, self.pool_w, self.pool_stride, self.pool_pad) t1_col22 = t1.transpose(0, 2, 3, 1).reshape(-1, filternum) t_tmp = np.dot(self.W_col, np.conj(t1_col22.T)) if cbp == 2: t13_col = t13.transpose(0, 2, 3, 1).reshape(-1, filternum) t_tmp = np.dot(self.W_col, np.conj(t13_col.T)) t0_col = activation(np.conj(t_tmp.T)) t0 = col2im(t0_col, self.x.shape, filter_h, filter_w, self.conv_stride, self.conv_pad) # 前層の教師信号 # Wの更新 if not self.memory_save: lis = [] for i in range(self.x_col.shape[0]): lis.append([i] * self.W_col.shape[0]) lis = [flatten for inner in lis for flatten in inner] y_b = g_repmat(self.conv_y_col, self.W_col.shape[0], 1)[lis].reshape( (self.x_col.shape[0], self.W_col.shape[0], self.W_col.shape[1])) t_b = g_repmat(t1_col2, self.W_col.shape[0], 1)[lis].reshape( (self.x_col.shape[0], self.W_col.shape[0], self.W_col.shape[1])) u_b = g_repmat(self.u_col, self.W_col.shape[0], 1)[lis].reshape( (self.x_col.shape[0], self.W_col.shape[0], self.W_col.shape[1])) lis = [] for i in range(self.x_col.shape[0]): lis.append([i] * self.W_col.shape[1]) lis = [flatten for inner in lis for flatten in inner] x_b = g_repmat(self.x_col.T, 1, self.W_col.shape[1])[:, lis].T.reshape( (self.x_col.shape[0], self.W_col.shape[1], self.W_col.shape[0])).transpose(0, 2, 1) theta_b = np.angle(y_b) - np.angle(x_b) - np.angle(self.W_col) self.dWa = self.mag*((1 - np.abs(y_b)**2) * (np.abs(y_b) - np.abs(t_b)*np.cos(np.angle(y_b) - np.angle(t_b))) * np.abs(x_b) * np.cos(theta_b) \ - np.abs(y_b) * np.abs(t_b) * np.sin(np.angle(y_b) - np.angle(t_b)) * np.abs(x_b) / (np.abs(u_b)+1e-10) * np.sin(theta_b)) self.dWp = self.mag*((1 - np.abs(y_b)**2) * (np.abs(y_b) - np.abs(t_b)*np.cos(np.angle(y_b) - np.angle(t_b))) * np.abs(x_b) * np.sin(theta_b) \ + np.abs(y_b) * np.abs(t_b) * np.sin(np.angle(y_b) - np.angle(t_b)) * np.abs(x_b) / (np.abs(u_b)+1e-10) * np.cos(theta_b)) self.dWa = np.sum(self.dWa, axis=0) #/ np.sqrt(self.x_col.shape[0]) self.dWp = np.sum(self.dWp, axis=0) #/ np.sqrt(self.x_col.shape[0]) else: self.dWa = np.zeros(self.W_col.shape, dtype='float32') self.dWp = np.zeros(self.W_col.shape, dtype='float32') for b in range(self.x_col.shape[0]): y_b = g_repmat(self.conv_y_col[b], self.W_col.shape[0], 1) t_b = g_repmat(t1_col2[b], self.W_col.shape[0], 1) u_b = g_repmat(self.u_col[b], self.W_col.shape[0], 1) x_b = g_repmat(self.x_col[b].reshape((self.x_col.shape[1], 1)), 1, self.W_col.shape[1]) theta_b = np.angle(y_b) - np.angle(x_b) - np.angle(self.W_col) self.dWa += self.mag*((1 - np.abs(y_b)**2) * (np.abs(y_b) - np.abs(t_b)*np.cos(np.angle(y_b) - np.angle(t_b))) * np.abs(x_b) * np.cos(theta_b) \ - np.abs(y_b) * np.abs(t_b) * np.sin(np.angle(y_b) - np.angle(t_b)) * np.abs(x_b) / (np.abs(u_b)+1e-10) * np.sin(theta_b)) self.dWp += self.mag*((1 - np.abs(y_b)**2) * (np.abs(y_b) - np.abs(t_b)*np.cos(np.angle(y_b) - np.angle(t_b))) * np.abs(x_b) * np.sin(theta_b) \ + np.abs(y_b) * np.abs(t_b) * np.sin(np.angle(y_b) - np.angle(t_b)) * np.abs(x_b) / (np.abs(u_b)+1e-10) * np.cos(theta_b)) #self.dWa /= np.sqrt(self.x_col.shape[0]) #self.dWp /= np.sqrt(self.x_col.shape[0]) if self.bias: if not self.memory_save: y_b = self.conv_y_col.T t_b = t1_col2.T u_b = self.u_col.T x_b = np.ones((self.b.shape[0], y_b.shape[1]), dtype='complex64') b_b = self.b.reshape((self.b.shape[0], 1)) theta_b = np.angle(y_b) - np.angle(b_b) self.dba = self.mag*((1 - np.abs(y_b)**2) * (np.abs(y_b) - np.abs(t_b)*np.cos(np.angle(y_b) - np.angle(t_b))) * np.abs(x_b) * np.cos(theta_b) \ - np.abs(y_b) * np.abs(t_b) * np.sin(np.angle(y_b) - np.angle(t_b)) * np.abs(x_b) / (np.abs(u_b)+1e-7) * np.sin(theta_b)) self.dbp = self.mag*((1 - np.abs(y_b)**2) * (np.abs(y_b) - np.abs(t_b)*np.cos(np.angle(y_b) - np.angle(t_b))) * np.abs(x_b) * np.sin(theta_b) \ + np.abs(y_b) * np.abs(t_b) * np.sin(np.angle(y_b) - np.angle(t_b)) * np.abs(x_b) / (np.abs(u_b)+1e-7) * np.cos(theta_b)) self.dba = np.sum(self.dba, axis=1) # / np.sqrt(self.dba.shape[0]) self.dbp = np.sum(self.dbp, axis=1) # / np.sqrt(self.dba.shape[0]) else: self.dba = np.zeros((self.b.shape[0], 1), dtype='float32') self.dbp = np.zeros((self.b.shape[0], 1), dtype='float32') for b in range(self.conv_y_col.shape[0]): y_b = self.conv_y_col[b].reshape( self.conv_y_col[b].shape[0], 1) t_b = t1_col2[b].reshape(t1_col2[b].shape[0], 1) u_b = self.u_col[b].reshape(self.u_col[b].shape[0], 1) x_b = g_repmat(1. + 0.j, self.b.shape[0], 1) b_b = self.b.reshape((self.b.shape[0], 1)) theta_b = np.angle(y_b) - np.angle(b_b) self.dba += self.mag*((1 - np.abs(y_b)**2) * (np.abs(y_b) - np.abs(t_b)*np.cos(np.angle(y_b) - np.angle(t_b))) * np.abs(x_b) * np.cos(theta_b) \ - np.abs(y_b) * np.abs(t_b) * np.sin(np.angle(y_b) - np.angle(t_b)) * np.abs(x_b) / (np.abs(u_b)+1e-10) * np.sin(theta_b)) self.dbp += self.mag*((1 - np.abs(y_b)**2) * (np.abs(y_b) - np.abs(t_b)*np.cos(np.angle(y_b) - np.angle(t_b))) * np.abs(x_b) * np.sin(theta_b) \ + np.abs(y_b) * np.abs(t_b) * np.sin(np.angle(y_b) - np.angle(t_b)) * np.abs(x_b) / (np.abs(u_b)+1e-10) * np.cos(theta_b)) self.dba = self.dba.flatten() #/ np.sqrt(self.dba.shape[0]) self.dbp = self.dbp.flatten() # / np.sqrt(self.dba.shape[0]) if self.optimizer == 'Adam': if self.m is None: self.m, self.v = {}, {} self.m["dWa"] = np.zeros_like(self.dWa, dtype='float32') self.m["dWp"] = np.zeros_like(self.dWp, dtype='float32') self.v["dWa"] = np.zeros_like(self.dWa, dtype='float32') self.v["dWp"] = np.zeros_like(self.dWp, dtype='float32') self.iter += 1 lr_t_a = self.lr_a * np.sqrt(1.0 - beta2**self.iter) / ( 1.0 - beta1**self.iter) lr_t_p = self.lr_p * np.sqrt(1.0 - beta2**self.iter) / ( 1.0 - beta1**self.iter) self.m["dWa"] += (1 - beta1) * (self.dWa - self.m["dWa"]) self.m["dWp"] += (1 - beta1) * (self.dWp - self.m["dWp"]) self.v["dWa"] += (1 - beta2) * (self.dWa**2 - self.v["dWa"]) self.v["dWp"] += (1 - beta2) * (self.dWp**2 - self.v["dWp"]) newWabs = np.abs(self.W_col) - lr_t_a * self.m["dWa"] / ( np.sqrt(self.v["dWa"]) + 1e-7) newWphase = np.angle(self.W_col) - lr_t_p * self.m["dWp"] / ( np.sqrt(self.v["dWp"]) + 1e-7) if self.bias: if self.bm is None: self.bm, self.bv = {}, {} self.bm["dba"] = np.zeros_like(self.dba, dtype='float32') self.bm["dbp"] = np.zeros_like(self.dbp, dtype='float32') self.bv["dba"] = np.zeros_like(self.dba, dtype='float32') self.bv["dbp"] = np.zeros_like(self.dbp, dtype='float32') lr_t_a = self.lr_a * np.sqrt(1.0 - beta2**self.iter) / ( 1.0 - beta1**self.iter) lr_t_p = self.lr_p * np.sqrt(1.0 - beta2**self.iter) / ( 1.0 - beta1**self.iter) self.bm["dba"] += (1 - beta1) * (self.dba - self.bm["dba"]) self.bm["dbp"] += (1 - beta1) * (self.dbp - self.bm["dbp"]) self.bv["dba"] += (1 - beta2) * (self.dba**2 - self.bv["dba"]) self.bv["dbp"] += (1 - beta2) * (self.dbp**2 - self.bv["dbp"]) newbabs = np.abs( self.b) - (lr_t_a * self.bm["dba"] / (np.sqrt(self.bv["dba"]) + 1e-7)).flatten() newbphase = np.angle( self.b) - (lr_t_p * self.bm["dbp"] / (np.sqrt(self.bv["dbp"]) + 1e-7)).flatten() elif self.optimizer == 'SGD': newWabs = np.abs(self.W_col) - self.lr_a * self.dWa newWphase = np.angle(self.W_col) - self.lr_p * self.dWp if self.bias: newbabs = np.abs(self.b) - self.lr_a * self.dba newbphase = np.angle(self.b) - self.lr_p * self.dbp self.W_col = newWabs * np.exp(1.j * newWphase) self.W = self.W_col.transpose(1, 0).reshape(filternum, channel, filter_h, filter_w) if self.bias: self.b = newbabs * np.exp(1.j * newbphase) #print(str(np.abs(self.W[0,0,0,0])) + ' ' + str(np.angle(self.W[0,0,0,0]))) if backpro == 1: t_tmp = np.dot(self.W_col, np.conj(t1_col2.T)) t0_col = activation(np.conj(t_tmp.T)) t0 = col2im(t0_col, self.x.shape, filter_h, filter_w, self.conv_stride, self.conv_pad) return t0
def backward(self, dout): if self.gap_layer: dout = self.GAP.backward(dout) if self.dropout: dout = self.DO.backward(dout) if self.pool_or_not: # Pooling backward dout = dout.transpose(0, 2, 3, 1) pool_size = self.pool_h * self.pool_w if self.pool == 'max': dmax = np.zeros((dout.size, pool_size)) dmax[np.arange(self.arg_max.size), self.arg_max.flatten()] = dout.flatten() dmax = dmax.reshape(dout.shape + (pool_size, )) elif self.pool == 'avg': dmax = np.zeros((dout.size, pool_size)) for i in range(pool_size): dmax[np.arange(self.conv_y_col.shape[0]), i] = self.conv_y_col.shape[1] * dout.flatten() dmax = dmax.reshape(dout.shape + (pool_size, )) dcol = dmax.reshape(dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1) dx = col2im(dcol, self.conv_y.shape, self.pool_h, self.pool_w, self.pool_stride, self.pool_pad) else: dx = dout # Conv backward FN, C, FH, FW = self.W.shape if self.activation == 'tanh': dout2 = dx * (1 - (np.tanh(self.u))**2) elif self.activation == 'Relu': dout2 = dx dout2[self.mask] = 0 FN, C, FH, FW = self.W.shape dout2 = dout2.transpose(0, 2, 3, 1).reshape(-1, FN) if self.bias: self.db = np.sum(dout2, axis=0) self.dW = np.dot(self.x_col.T, dout2) self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH, FW) col_WT = self.W.reshape(FN, -1) dconv = np.dot(dout2, col_WT) dx = col2im(dconv, self.x.shape, FH, FW, self.conv_stride, self.conv_pad) # update if self.optimizer == 'SGD': self.W = self.W - self.lr * self.dW if self.bias: self.b = self.b - self.lr * self.db else: if self.m is None: self.m = np.zeros_like(self.dW) self.v = np.zeros_like(self.dW) self.iter += 1 lr_t = self.lr * np.sqrt(1.0 - beta2**self.iter) / ( 1.0 - beta1**self.iter) self.m += (1 - beta1) * (self.dW - self.m) self.v += (1 - beta2) * (self.dW**2 - self.v) self.W = self.W - lr_t * self.m / (np.sqrt(self.v) + 1e-7) if self.bias: if self.bm is None: self.bm = np.zeros_like(self.db) self.bv = np.zeros_like(self.db) self.bm += (1 - beta1) * (self.db - self.bm) self.bv += (1 - beta2) * (self.db**2 - self.bv) self.b = self.b - lr_t * self.bm / (np.sqrt(self.bv) + 1e-7) if self.batchnorm: dx = self.BN.backward(dx) return dx
self.col = col self.col_W = col_W return out def backward(self, dout): FN, C, FH, FW = self.W.shape dout = dout.transpose(0,2,3,1).reshape(-1, FN) self.db = np.sum(dout, axis=0) self.dW = np.dot(self.col.T, dout) self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH, FW) dcol = np.dot(dout, self.col_W.T) dx = col2im(dcol, self.x.shape, FH, FW, self.stride, self.pad) return dx # 전개 후, 행렬 최댓값 구하고, 적절한 형상으로 변형. class Pooling: def __init__(self, pool_h, pool_w, stride=1, pad=0): self.pool_h = pool_h self.pool_w = pool_w self.stride = stride self.pad = pad self.x = None self.arg_max = None def forward(self, x):