def main(): x1 = np.random.rand(1, 3, 7, 7) col1 = im2col(x1, 5, 5, stride=1, pad=0) print(col1.shape) x2 = np.random.rand(10, 3, 7, 7) col2 = im2col(x2, 5, 5, stride=1, pad=0) print(col2.shape)
def forward(self, x): N, C, H, W = x.shape # 输入数据的个数、通道数、高度、宽度 # 计算池化层输出的高度和宽度(向下取整) out_h = (H - self.pool_h) // self.stride + 1 out_w = (W - self.pool_w) // self.stride + 1 # 把输入数据x转换成二维矩阵,每一行代表一次池化要用到的元素列表 col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) # 由于池化是逐个通道进行的,因此需要将输入数据转换成具有池化层大小个列的 # 二维矩阵,然后每一行取最大值即可 col = col.reshape(-1, self.pool_h * self.pool_w) # 按行取最大值,argmax获取的是下标,用于反向传播 arg_max = np.argmax(col, axis=1) out = np.max(col, axis=1) # 按行取最大值 """ 转换成与输入一样的形状:N, C, H, W, N个三维矩阵,每个三维矩阵就是一个图像, 有C个通道,每个通道就是一个二维矩阵, 也就是说一个图像就是C个H*W的矩阵,然后有N个图像,就是N*C*H*W out = out.reshape(N, C, out_h, out_w) 虽然这样结果也是对的,但是为了保持统一,还是先转换成N,H,W,C再转置 """ out = out.reshape(N, out_h, out_w, C).transpose((0, 3, 1, 2)) # 保存中间结果 self.x = x self.arg_max = arg_max return out
def forward(self, x): """ 순방향 전파 메소드 x: (samples, channel, height, width) 모양의 4차원 배열 """ # 구현 # x를 펼친다 self.x = x n, c, h, w = self.x.shape # 샘플 개수, 채널, 높이, 너비 oh = (h - self.fh + 2 * self.pad) // self.stride + 1 ow = (w - self.fw + 2 * self.pad) // self.stride + 1 # 1) x --> im2col --> 2차원 변환 col = im2col(x, self.fh, self.fw, self.stride, self.pad) # 2) 채널 별 최댓값을 찾을 수 있는 모양으로 x를 reshape col = col.reshape(-1, self.fh * self.fw) # 3) 채널 별로 최댓값을 찾음. self.arg_max = np.argmax(col, axis=1) out = np.max(col, axis=1) # max: 최댓값을 찾아주는 함수 argmax: 최댓값의 위치를 저장해주는 함수 # 4) 최댓값(1차원 배열)을 reshape & transpose out = out.reshape(n, oh, ow, c).transpose(0, 3, 1, 2) # 5) pooling이 끝난 4차원 배열을 리턴 return out
def forward(self, x): N, C, H, W = x.shape self.x = x OH = int(1 + (H - self.pool_h) / self.stride) OW = int(1 + (W - self.pool_w) / self.stride) # 展開(1) col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) # col は (N x OH x OW, C x pool_h x pool_w) になっているので、チャンネル毎に縦に並べる # (N x OH x OW x C, pool_h x pool_w) となる col = col.reshape(-1, self.pool_h * self.pool_w) # 最大値(2) # 各プーリング領域に対して最大値を求める # (N x OH x OW x C, 1) のサイズになる arg_max = np.argmax(col, axis=1) out = np.max(col, axis=1) # 整形(3) out = out.reshape(N, OH, OW, C).transpose(0, 3, 1, 2) self.arg_max = arg_max self.x = x return out
def forward(self, x): # フィルタ(W)の # * FN: バッチ数 # * C: チャンネル数 # * FH: height # * FW: width FN, C, FH, FW = self.W.shape # 入力(x)の # * N: バッチ数 # * C: チャンネル数 # * H: height # * W: width N, C, H, W = x.shape out_h = int((H + 2 * self.pad - FH) / self.stride) + 1 out_w = int((W + 2 * self.pad - FW) / self.stride) + 1 col = im2col(x, FH, FW, self.stride, self.pad) col_W = self.W.reshape(FN, -1).T out = np.dot(col, col_W) + self.b # transpose()を使い(N, C, H, W)にする out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) self.x = x self.col = col self.col_W = col_W return out
def forward(self,x): # 入力信号 # フィルターと出力の形状のセットアップ FN, C, FH, FW = self.W.shape N, C, H, W = x.shape out_h = 1 + int((H + 2*self.pad - FH) / self.stride) out_w = 1 + int((W + 2*self.pad - FW) / self.stride) # フィルターのサイズに分割、1次元のベクトルに整形 col = im2col(x, FH, FW, self.stride, self.pad) col_W = self.W.reshape(FN, -1).T # ベクトルの積和演算 out = np.dot(col, col_W) out = out + self.b # 出力の転置(並べ替え) out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) # 元の形状を記憶 self.x = x self.col = col self.col_W = col_W return out
def forward(self, x): N, H, W, C = x.shape self.x_shape = np.array([N, H, W, C]) #weight init if self.w is None: self.w = self.w_init([self.filters, C, *self.kernel_size], np.prod(self.kernel_size) * C) # [filters, in, FH, FW] out_shape = np.ceil(np.array([H, W]) / self.strides).astype(np.int32) self.out_shape = out_shape pad = (out_shape * self.strides) - np.array( [H, W]) + self.kernel_size - self.strides pad[pad < 0] = 0 # max(0, pad) self.pad = pad FH, FW = self.kernel_size col = util.im2col(x, self.kernel_size, self.strides, pad, out_shape) # [N*out_H*out_W, FH*FW*C] self.col = col w = self.w.reshape(self.filters, FH * FW * C).T # [FH*FW*C, filters] out = np.dot(col, w) + self.b # [N*out_H*out_W, filters] out = out.reshape(N, *out_shape, self.filters) # [N, out_H, out_W, filters] return out
def forward(self, x): N, H, W, C = x.shape self.x_shape = np.array([N, H, W, C]) out_shape = np.ceil(np.array([H, W]) / self.strides).astype(np.int32) self.out_shape = out_shape pad = (out_shape * self.strides) - np.array( [H, W]) + self.kernel_size - self.strides pad[pad < 0] = 0 # max(0, pad) self.pad = pad FH, FW = self.kernel_size col = util.im2col(x, self.kernel_size, self.strides, pad, out_shape) # [N*out_H*out_W, FH*FW*C] col = col.reshape(N * np.prod(out_shape) * C, FH * FW) # [N*out_H*out_W*C, FH*FW] max_mask = np.argmax(col, axis=1) # [N*out_H*out_W*C] self.max_mask = np.eye(FH * FW)[max_mask] # [N*out_H*out_W*C, FH*FW] max_col = np.max(col, axis=1) # [N*out_H*out_W*C] max_col = max_col.reshape(N, *out_shape, C) # [N, out_H, out_W, C] return max_col
def forward(self, x): """ 順伝播計算 x : 入力(配列形状=(データ数, チャンネル数, 高さ, 幅)) """ FN, C, FH, FW = self.W.shape N, C, H, W = x.shape out_h = (H + 2 * self.pad - FH) // self.stride + 1 # 出力の高さ(端数は切り捨てる) out_w = (W + 2 * self.pad - FW) // self.stride + 1 # 出力の幅(端数は切り捨てる) # 畳み込み演算を効率的に行えるようにするため、入力xを行列colに変換する col = im2col(x, FH, FW, self.stride, self.pad) # 重みフィルターを2次元配列に変換する # col_Wの配列形状は、(C*FH*FW, フィルター枚数) col_W = self.W.reshape(FN, -1).T # 行列の積を計算し、バイアスを足す out = np.dot(col, col_W) + self.b # 画像形式に戻して、チャンネルの軸を2番目に移動させる out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) self.x = x self.col = col self.col_W = col_W return out
def forward(self, x): ''' :param x: (samples, channel, height, width) 모양의 4차원 배열 ''' # 구현 self.x = x n, c, h, w = x.shape # (샘플 개수, 채널, 높이, 너비) oh = (h - self.fh + 2 * self.pad) // self.stride + 1 ow = (w - self.fw + 2 * self.pad) // self.stride + 1 # 1) x --> im2col --> 2차원 변환 x_col = im2col(x, self.fh, self.fw, self.stride, self.pad) # 2) 채널별 최댓값을 찾을 수 있는 모양으로 x를 reshape x_col = x_col.reshape(-1, self.fh * self.fw) # 3) 채널 별로 최댓값을 찾음 self.arg_max = np.argmax(x_col, axis=1) out = np.max(x_col, axis=1) # 4) 최댓값(1차원 배열)을 reshape & transpose out = out.reshape(n, oh, ow, c).transpose(0, 3, 1, 2) # 5) pooling 이 끝난 4차원 배열을 리턴 return out
def _forward(self, x): ''' :param x: 4차원 이미지 (mini-batch) 데이터 ''' self.x = x n, c, h, w = x.shape fn, c, fh, fw = self.W.shape oh = (h - fh + 2 * self.pad) // self.stride + 1 ow = (w - fw + 2 * self.pad) // self.stride + 1 # 이미지 데이터 x 를 im2col 함수를 사용해서 x_col 로 변환 self.x_col = im2col(self.x, fh, fw, self.stride, self.pad) # 필터 w 를 x_col 과 dot 연산을 할 수 있도록 reshape & transpose self.W_col = self.W.reshape(fn, -1).T # W(fn, c, fh, fw) --> W_col(fn, c*fh*fw) --> W_col(c*fh*fw, fn) # x_col @ w_col + bias out = np.dot(self.x_col, self.W_col) + self.b # self.x_col.dot(self.W_col) # @ 연산의 결과를 reshape & transpose out = out.reshape(n, oh, ow, fn) out = out.transpose(0, 3, 1, 2) return out
def forward(self, x): # 读取卷积层滤波器的形状:滤波器个数、通道数、高度、宽度 FN, C, FH, FW = self.W.shape # 读取输入数据x的形状: # 样本个数(如果是一个batch,就是batch_size)、通道数、高度、宽度 N, C, H, W = x.shape # 计算卷积输出的高度和宽度(向下取整):(H + 2pad - FH) / stride + 1 out_h = (H + 2 * self.pad - FH) // self.stride + 1 out_w = (W + 2 * self.pad - FW) // self.stride + 1 # 用im2col将输入数据x转换成2维的矩阵 col = im2col(x, FH, FW, self.stride, self.pad) # 将滤波器调整为2维矩阵 # 注意先将滤波器调整为一行一个,然后转置,变成一列一个, # 如果直接reshape成(-1, FN)的话,一列并不是一个滤波器 col_W = self.W.reshape(FN, -1).T # 转换后的输入数据x和reshape后的滤波器可以直接用np.dot高速计算 # 计算完之后要加上偏置b # 结果为 二维矩阵,大小为(N * out_h * out_w, FN) out = np.dot(col, col_W) + self.b # 最后将计算结果调整回原来的形状: # 先reshape成 N * H * W * C, # 因为im2col中也是调整成一个输出的三个通道连续输出,要保持一致(H, W, C) # 然后转置成 N * C * H * W,因为输入是这样的顺序 # **在这里要领会到reshape和transpose顺序不能对调** out = out.reshape(N, out_h, out_w, -1).transpose((0, 3, 1, 2)) # 记录前向传播的中间结果,将在反向传播中使用 self.x = x self.col = col self.col_W = col_W return out
def forward(self, x): FN, C, FH, FW = self.W.shape N, C, H, W = x.shape # 출력 크키 out_h = 1 + int((H + 2 * self.pad - FH) / self.stride) out_w = 1 + int((W + 2 * self.pad - FW) / self.stride) # 입력 데이터에서 필터를 적용하는 영역별로 가로로 전개 col = util.im2col(x, FH, FW, self.stride, self.pad) # 필터를 2차원 배열로 변형(reshape)하고(FN개의 묶음으로 변경) + Transpose 해서 세로로 전개 <- 필터는 im2col 할 필요 없다. col_W = self.W.reshape(FN, -1).T # < FN, C, FH, FW = 1, 2, 3, 3 일때 > # (1) self.W.reshape(FN, -1) 결과 # [[-0.00558132 - 0.00473335 0.00669913 - 0.0099481 0.0183686 - 0.01924093 # - 0.00076841 0.00406638 0.00376849 - 0.00606364 0.00859418 - 0.01257911 # 0.00217284 0.0036043 0.02057647 0.00256673 0.00883204 - 0.01496615]] # (2) Transpose 결과 # [[-0.00558132] # [-0.00473335] # [0.00669913] # [-0.0099481] # [0.0183686] # [-0.01924093] # [-0.00076841] # [0.00406638] # [0.00376849] # [-0.00606364] # [0.00859418] # [-0.01257911] # [0.00217284] # [0.0036043] # [0.02057647] # [0.00256673] # [0.00883204] # [-0.01496615]] out = np.dot(col, col_W) + self.b # 원소 수가 변환 후에도 똑같이 유지되도록 묶어준다.(-1 사용) && 축 순서를 바꿔준다. out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) # reshape: [[[[2.10218838] # [2.11292464] # [2.1236609 ]] # # [[2.20955099] # [2.22028725] # [2.23102351]] # # [[2.31691359] # [2.32764985] # [2.33838611]]]] # out: [[[[2.10218838 2.11292464 2.1236609] # [2.20955099 2.22028725 2.23102351] # [2.31691359 2.32764985 2.33838611]]]] self.x = x self.col = col self.col_W = col_W return out
def forward(self, x): N, C, H, W = x.shape out_h = int(1 + (H - self.pool_h) / self.stride) out_w = int(1 + (W - self.pool_w) / self.stride) col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) col = col.reshape(-1, self.pool_h * self.pool_w) out = np.max(col, axis=1) out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2) return out
def forward(self,x): FN,C,FH,FW = self.W.shape N,C,H,W = x.shape out_h = int(1 + (H + 2 * self.pad - FH) / self.stride) out_w = int(1 + (W + 2 * self.pad - FW) / self.stride) col = im2col(x,FH,FW,self.stride,self.pad) col_w = self.W.reshape(FN, -1).T out = np.dot(col,col_w) + self.b out = out.reshape(N,out_h,out_w,-1).transpose(0,3,1,2) return out
def forward(self, x): self.x = x N, C, H, W = self.x.shape FN, C, FH, FW = self.W.shape h_out = int((H + 2 * self.pad - FH) / self.stride) + 1 w_out = int((W + 2 * self.pad - FW) / self.stride) + 1 self.x_col = im2col(x, FH, FW, self.stride, self.pad) self.w_col = self.W.reshape(FN, -1).T out = np.dot(self.x_col, self.w_col) + self.b # numpy broadcast out = out.reshape(N, h_out, w_out, -1).transpose(0, 3, 1, 2) return out
def forward(self, x): # conv forward # # im2col을 통해 np.dot 행렬곱 연산 수행 # FN, C, FH, FW = self.W.Shape # filter의 shape 기록 N, C, H, W = x.shape # input data의 shape out_h = int(1 + (H + 2*self.pad - FH) / self.stride) out_w = int(1 + (W + 2*self.pad - FW) / self.stride) # 공식 col = im2col(x, FH, FW, self.stride, self.pad) # 2차원 col_W = self.W.reshape(FN, -1).T # 행렬 연산을 위한 reshape --> 2차원 out = np.dot(col, col_W) + self.b # 연산 out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)
def forward(self, x): self.x = x N, C, H, W = self.x.shape h_out = int((H + 2 * self.pad - self.h_p) / self.stride) + 1 w_out = int((W + 2 * self.pad - self.w_p) / self.stride) + 1 x_col = im2col(x, self.h_p, self.w_p, self.stride, self.pad)\ .reshape(-1, self.h_p * self.w_p) x_pool = x_col.max(axis=1) out = x_pool.reshape(N, h_out, w_out, C).transpose(0, 3, 1, 2) self.arg_max = np.argmax(x_col, axis=1) return out
def forward(self, x): N, C, H, W = x.shape out_h = int(1 + (H + 2 * self.pad - FH) / self.stride) out_w = int(1 + (W + 2 * self.pad - FW) / self.stride) # reshape to 2-dimensional array col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) col = col.reshape(-1, self.pool_h * self.pool_w) out = np.max(col, axis=1) # reshape again out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2) return out
def forward(self, x): FN, C, FH, FW = self.W.shape #滤波器是(FN, C, FH, FW)的4维形状。 N, C, H, W = x.shape out_h = int(1 + (H + 2 * self.pad - FH) / self.stride) out_w = int(1 + (W + 2 * self.pad - FW) / self.stride) col = im2col(x, FH, FW, self.stride, self.pad) # 参数:数据,滤波器的高,滤波器的长,步幅,填充 col_W = self.W.reshape(FN, -1).T #滤波器的展开 out = np.dot(col, col_W) + self.b out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) #transpose会更改多维数组的轴的顺序。上面的是把(N,H,W,C)改为(N,C,H,W) return out
def forward(self, x): N, C, H, W = x.shape out_h = int(1 + (H - self.pool_h) / self.stride) out_w = int(1 + (W - self.pool_w) / self.stride) col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) col = col.reshape(-1, self.pool_h * self.pool_w) out = np.array(np.mean(col, axis=1), dtype=np.float32) out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2) self.x = x return out
def forward(self, x): FN, C, FH, FW = self.W.shape # FN、C、FH、FW 分别是FilterNumber(滤波器数量) # 、Channel、Filter Height、Filter Width 的缩写。 N, C, H, W = x.shape out_h = int(1 + (H + 2 * self.pad - FH) / self.stride) out_w = int(1 + (W + 2 * self.pad - FW) / self.stride) self.col = im2col(x, FH, FW, self.stride, self.pad) self.col_W = self.W.reshape(FN, -1).T # 滤波器的展开 .T方法为矩阵的转置操作 out = np.dot(self.col, self.col_W) + self.b out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) self.x = x return out
def forward(self, x): self.x = x fn, c, fh, fw = self.w.shape # filter n, c, h, w = self.x.shape out_h = 1 + (h + 2 * self.pad - fh) // self.stride out_w = 1 + (h + 2 * self.pad - fw) // self.stride self.col = im2col(self.x, fh, fw, self.stride, self.pad) self.col_w = self.w.reshape((fn, -1)).T out = np.dot(self.col, self.col_w) + self.b out = out.reshape(n, out_h, out_w, -1).transpose(0, 3, 1, 2) return out
def forward(self, x): n, c, h, w = x.shape out_h = 1 + (h - self.pool_h) // self.stride out_w = 1 + (h - self.pool_w) // self.stride col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) col = col.reshape((-1, self.pool_h * self.pool_w)) self.x = x self.arg_max = np.argmax(col, axis=1) out = np.max(col, axis=1) out = out.reshape(n, out_h, out_w, c).transpose(0, 3, 1, 2) return out
def forward(self, x): FN, C, FH, FW = self.W.shape N, C, H, W = x.shape OH = int((H + 2*self.pad - FH)/self.stride +1) OW = int((W + 2*self.pad - FW)/self.stride +1) col_x = im2col(x, FH, FW, self.stride, self.pad) col_W = self.W.reshape(FN, -1).T result_2d = np.dot(col_x, col_W) + self.b result = result_2d.reshape(N, OH, OW, FN).transpose(3, 0, 1, 2) return result
def forward(self, x): N, C, H, W = x.shape out_h = int(1 + (H - self.pool_h) / self.stride) out_w = int(1 + (W - self.pool_h) / self.stride) # 1) 우선 데이터 전개 col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) col = col.reshape(-1, self.pool_h * self.pool_w) # 2) 최댓값 구하기 out = np.max(col, axis=1) # 행방향 (가로) # 3) 성형(적절한 모양으로 변형) out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2) return out
def forward(self, x): FN, C, FH, FW = self.W.shape # 卷积核尺寸 N, C, H, W = x.shape # mini-batch的输入图像尺寸 # 计算卷积后图像尺寸 out_h = 1 + int((H + 2*self.pad - FH) / self.stride) out_w = 1 + int((W + 2*self.pad - FW) / self.stride) # 矩阵变换方便计算卷积 col = im2col(x, FH, FW, self.stride, self.pad) col_W = self.W.reshape(FN, -1).T out = np.dot(col, col_W) + self.b out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) # 保存中间结果 self.x = x self.col = col self.col_W = col_W return out
def forward(self, x): N, C, H, W = x.shape out_h = (H - self.pool_h)//self.stride + 1 out_w = (H - self.pool_w)//self.stride + 1 col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) col = col.reshape(-1, self.pool_h*self.pool_w) arg_max = np.argmax(col, axis=1) out = np.max(col, axis=1) out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2) self.x = x self.arg_max = arg_max return out
def forward(self, x, **kwargs): n, c, h, w = x.shape out_h = int(1 + (h - self.pool_h) / self.stride) out_w = int(1 + (w - self.pool_w) / self.stride) col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) col = col.reshape(-1, self.pool_h * self.pool_w) arg_max = np.argmax(col, axis=1) out = np.max(col, axis=1) out = out.reshape(n, out_h, out_w, c).transpose((0, 3, 1, 2)) self.x = x self.arg_max = arg_max return out
def forward(self, x): N, C, H, W = x.shape out_h = int(1 + (H - self.pool_h) / self.stride) out_w = int(1 + (W - self.pool_w) / self.stride) col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) col = col.reshape(-1, self.pool_h*self.pool_w) arg_max = np.argmax(col, axis=1) out = np.max(col, axis=1) out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2) self.x = x self.arg_max = arg_max return out
def forward(self, x): FN, C, FH, FW = self.W.shape N, C, H, W = x.shape out_h = int((H + 2 * self.pad - FH) / self.stride) + 1 out_w = int((W + 2 * self.pad - FW) / self.stride) + 1 col = im2col(x, FH, FW, self.stride, self.pad) col_W = self.W.reshape(FN, -1).T # 滤波器的展开 out = np.dot(col, col_W) + self.b out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) self.x = x self.col = col self.col_W = col_W return out
def forward(self, x): FN, C, FH, FW = self.W.shape N, C, H, W = x.shape out_h = 1 + int((H + 2*self.pad - FH) / self.stride) out_w = 1 + int((W + 2*self.pad - FW) / self.stride) col = im2col(x, FH, FW, self.stride, self.pad) col_W = self.W.reshape(FN, -1).T out = np.dot(col, col_W) + self.b out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) self.x = x self.col = col self.col_W = col_W return out