自定义CNN卷积函数时出现AttributeError:int对象无shape属性
卷积函数实现报错修复
我自己实现了一个CNN卷积函数,输入张量尺寸为2×3×32×32,调用时触发了AttributeError,以下是我的代码、报错信息以及问题解决方法:
实现代码
def conv(x, in_channels, out_channels, kernel_size, stride, padding, weight, bias): """ Args: x: torch tensor with size (N, C_in, H_in, W_in), in_channels: number of channels in the input image, it is C_in; out_channels: number of channels produced by the convolution; kernel_size: size of onvolving kernel, stride: stride of the convolution, padding: implicit zero padding to be added on both sides of each dimension, Return: y: torch tensor of size (N, C_out, H_out, W_out) """ y = None xKernShape = kernel_size yKernShape = kernel_size xImgShape = x.shape[2] yImgShape = x.shape[3] xOutput = int(((xImgShape - xKernShape + 2 * padding) / stride) + 1) yOutput = int(((yImgShape - yKernShape + 2 * padding) / stride) + 1) output = np.zeros((xOutput, yOutput)) if padding != 0: imagePadded = np.zeros((x.shape[2] + padding*2, x.shape[3] + padding*2)) imagePadded[int(padding):int(-1 * padding), int(padding):int(-1 * padding)] = x print(imagePadded) else: imagePadded = x for i in range(x.shape[3]): if i > x.shape[3] - yKernShape: break if i % stride == 0: for j in range(x.shape[2]): if j > x.shape[2] - xKernShape: break try: if j % stride == 0: output[j, i] = (kernel_size * imagePadded[j: j + xKernShape, i: i + yKernShape]).sum() y = np.array(np.hsplit(output, 1)).reshape((x.shape[0], out_channels, j, i)) except: break return y
调用方式与报错信息
调用代码:
conv(x,in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0,weight=torch_conv.weight,bias=torch_conv.bias)
报错信息:
AttributeError Traceback (most recent call last) <ipython-input-71-f4d6ee7b5fd8> in <module> 6 padding=0, 7 weight=torch_conv.weight, ----> 8 bias=torch_conv.bias) <ipython-input-70-1d0a9f0d9820> in my_conv(x, in_channels, out_channels, kernel_size, stride, padding, weight, bias) 33 if i % stride == 0: 34 for x in range(x.shape[2]): ---> 35 if x > x.shape[2] - xKernShape: 36 break 37 try: AttributeError: 'int' object has no attribute 'shape'
问题分析与修复
1. 核心报错原因
内层循环变量名误用了x,和函数参数的输入张量x重名。循环开始后,x被覆盖为循环的整数索引,导致后续访问x.shape时触发AttributeError。
修复: 将内层循环变量名改为非冲突名称,比如h_idx,同时替换循环内所有该变量的引用:
# 原错误代码 for x in range(x.shape[2]): if x > x.shape[2] - xKernShape: # 修改后 for h_idx in range(x.shape[2]): if h_idx > x.shape[2] - xKernShape:
2. 其他关键逻辑修复
除了变量名冲突,代码还有多处无法实现正确卷积的问题,一并修复如下:
- 未使用传入的weight和bias:原代码用
kernel_size替代卷积核计算,需改为用传入的weight做逐元素相乘求和,最后加上bias。 - 多通道/多batch处理缺失:输入是
(N,C,H,W)的4D张量,需遍历每个样本、每个输入/输出通道做卷积求和。 - padding维度不匹配:原代码直接将4D张量赋值给2D数组,需对每个样本的每个通道单独做padding。
- 输出维度错误:原代码用循环变量作为输出维度,需改为用预先计算好的
xOutput和yOutput。
修复后的可运行版本示例
import numpy as np import torch def conv(x, in_channels, out_channels, kernel_size, stride, padding, weight, bias): # 转numpy数组方便操作 x_np = x.numpy() weight_np = weight.numpy() bias_np = bias.numpy() N, _, H_in, W_in = x_np.shape H_out = int(((H_in - kernel_size + 2 * padding) / stride) + 1) W_out = int(((W_in - kernel_size + 2 * padding) / stride) + 1) # 初始化输出数组 output = np.zeros((N, out_channels, H_out, W_out)) # 遍历每个样本、输出通道、输入通道做卷积 for n in range(N): for out_c in range(out_channels): feat_map = np.zeros((H_out, W_out)) for in_c in range(in_channels): # 对单通道输入做padding img = x_np[n, in_c] if padding > 0: img_padded = np.pad(img, pad_width=padding, mode='constant', constant_values=0) else: img_padded = img # 滑动卷积核计算 for h in range(0, H_out * stride, stride): for w in range(0, W_out * stride, stride): window = img_padded[h:h+kernel_size, w:w+kernel_size] feat_map[h//stride, w//stride] += np.sum(window * weight_np[out_c, in_c]) # 添加偏置 feat_map += bias_np[out_c] output[n, out_c] = feat_map # 转回torch张量返回 return torch.from_numpy(output)
内容的提问来源于stack exchange,提问作者Steamer
相关产品推荐
相关产品推荐

