You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义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]):
---&gt; 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:35:24