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

DCGAN生成器自定义权重初始化报错:'ConvTr'无'weight'属性

PyTorch DCGAN生成器权重初始化报错解决

问题描述

在PyTorch中搭建DCGAN生成器时,封装了整合转置卷积、BatchNorm2d和ReLU的ConvTr模块,使用自定义weights_init函数初始化权重时,触发错误:

AttributeError: 'ConvTr' object has no attribute 'weight'

相关代码

官方教程生成器代码

# Generator Code

class Generator(nn.Module):
    def __init__(self, ngpu):
        super(Generator, self).__init__()
        self.ngpu = ngpu
        self.main = nn.Sequential(
            # input is Z, going into a convolution
            nn.ConvTranspose2d( nz, ngf * 8, 4, 1, 0, bias=False),
            nn.BatchNorm2d(ngf * 8),
            nn.ReLU(True),
            # state size. (ngf*8) x 4 x 4
            nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 4),
            nn.ReLU(True),
            # state size. (ngf*4) x 8 x 8
            nn.ConvTranspose2d( ngf * 4, ngf * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 2),
            nn.ReLU(True),
            # state size. (ngf*2) x 16 x 16
            nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf),
            nn.ReLU(True),
            # state size. (ngf) x 32 x 32
            nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False),
            nn.Tanh()
            # state size. (nc) x 64 x 64
        )

    def forward(self, input):
        return self.main(input)

自定义生成器代码

class ConvTr(nn.Module):
    def __init__(self, input_channels, output_channels, k_size, stride, pad, b = False):
        super().__init__()
        
        self.conv = nn.ConvTranspose2d(in_channels=input_channels,
                                       out_channels=output_channels,
                                       kernel_size=k_size,
                                       stride=stride,
                                       padding=pad,
                                       bias=b)
        
        self.batch_norm = nn.BatchNorm2d(input_channels)
        self.activation = nn.ReLU()
        
        
    def forward(self, x):
        x = self.conv(x)
        x = self.activation(x)
        x = self.batch_norm(x)
        return x



class Generator(nn.Module):
    
    def __init__(self, inputNoise=100):
        super().__init__()

        self.conv1 = ConvTr(input_channels = inputNoise, output_channels = 128, k_size = 4, stride = 2, pad = 0)
        self.conv2 = ConvTr(input_channels = 128, output_channels = 64, k_size = 3, stride = 2, pad = 1)
        self.conv3 = ConvTr(input_channels = 64, output_channels = 32, k_size = 4, stride = 2, pad = 1)
        self.conv4 = ConvTranspose2d(in_channels=32, out_channels=1, kernel_size=4, stride=2, padding=1)
        self.tanh = Tanh()
        

    def forward(self, x):
        
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = self.conv4(x)
        output = self.tanh(x)
        return output

权重初始化函数

def weights_init(model):
    # get the class name
    classname = model.__class__.__name__
    # check if the classname contains the word "conv"
    if classname.find("Conv") != -1:
        # intialize the weights from normal distribution
        nn.init.normal_(model.weight.data, 0.0, 0.02)
    # otherwise, check if the name contains the word "BatcnNorm"
    elif classname.find("BatcnNorm") != -1:
        # intialize the weights from normal distribution and set the
        # bias to 0
        nn.init.normal_(model.weight.data, 1.0, 0.02)
        nn.init.constant_(model.bias.data, 0)

错误信息

raise AttributeError("'{}' object has no attribute '{}'".format(
AttributeError: 'ConvTr' object has no attribute 'weight'

错误原因

  1. 初始化逻辑误判模块类型:weights_init通过类名含"Conv"就认为是卷积层,但ConvTr是你自定义的容器模块,本身没有weight属性,真正的卷积层是它内部的self.conv成员。调用generator.apply(weights_init)时,函数会递归遍历所有子模块,包括ConvTr,此时访问model.weight必然报错。
  2. BatchNorm参数错误:ConvTr中的BatchNorm2d传入了输入通道数,但转置卷积后的输出通道是output_channels,这里参数应该改为output_channels。
  3. 拼写错误:初始化函数里的BatcnNorm是笔误,正确应为BatchNorm。

解决方案

方案1:修改初始化函数,精准匹配目标模块

让初始化函数只对PyTorch原生的卷积层和BatchNorm层生效,跳过自定义的ConvTr容器:

def weights_init(model):
    # 遍历所有子模块
    for m in model.modules():
        classname = m.__class__.__name__
        # 只处理原生Conv层,跳过自定义ConvTr
        if classname.find('Conv') != -1 and not isinstance(m, ConvTr):
            nn.init.normal_(m.weight.data, 0.0, 0.02)
        elif classname.find('BatchNorm') != -1:
            nn.init.normal_(m.weight.data, 1.0, 0.02)
            nn.init.constant_(m.bias.data, 0)

使用时正常调用:

generator = Generator()
generator.apply(weights_init)

方案2:在ConvTr模块内部完成初始化

直接在ConvTr的初始化方法里完成内部卷积和BatchNorm的权重初始化,外部无需额外处理:

class ConvTr(nn.Module):
    def __init__(self, input_channels, output_channels, k_size, stride, pad, b = False):
        super().__init__()
        
        self.conv = nn.ConvTranspose2d(in_channels=input_channels,
                                       out_channels=output_channels,
                                       kernel_size=k_size,
                                       stride=stride,
                                       padding=pad,
                                       bias=b)
        # 修正BatchNorm的输入参数为输出通道数
        self.batch_norm = nn.BatchNorm2d(output_channels)
        self.activation = nn.ReLU()
        
        # 初始化当前模块内的卷积和BatchNorm
        nn.init.normal_(self.conv.weight.data, 0.0, 0.02)
        nn.init.normal_(self.batch_norm.weight.data, 1.0, 0.02)
        nn.init.constant_(self.batch_norm.bias.data, 0)
        
    def forward(self, x):
        x = self.conv(x)
        x = self.activation(x)
        x = self.batch_norm(x)
        return x

同时注意修正Generator中conv4和tanh的导入问题(需从torch.nn导入:from torch.nn import ConvTranspose2d, Tanh)。

内容的提问来源于stack exchange,提问作者Nafees

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:14:57