pytorch怎么使用定义好的模型的一部分
阅读原文时间:2023年07月12日阅读:3

Encoder代码为:

class Encoder(nn.Module): #输入图片的大小isize、噪声的维度nz=、输入图片的通道nc=、ndf=、
def __init__(self,isize,nz,nc,ndf,ngpu,n_exter_layers=,add_final_conv=True):
super(Encoder,self).__init__()
self.ngpu=ngpu
# 必须为16倍数
assert isize % ==,"isize has to be a multiple of 16"

    main=nn.Sequential()  
    # 图片的高宽缩小一倍  
    main.add\_module('initial-conv-{0}-{1}'.format(nc,ndf),nn.Conv2d(nc,ndf,,,,bias=False))  
    main.add\_module('initial-relu-{0}'.format(ndf),nn.LeakyReLU(0.2,inplace=True))  
    csize,cndf=isize/,ndf

    for t in range(n\_exter\_layers): #在这里面特征宽高不变,通道数也不变  
        main.add\_module('extra-layers-{0}-{1}-conv'.format(t,cndf),nn.Conv2d(cndf,cndf,,,,bias=False))  
        main.add\_module('extra-layers-{0}-{1}-batchnorm'.format(t,cndf),nn.BatchNorm2d(cndf))  
        main.add\_module('extra-layers-{0}-{1}-relu'.format(t,cndf),nn.LeakyReLU(0.2,inplace=True))

    # 在特征高宽仍大于4时,就添加缩小一倍高宽,通道增加一倍的卷积块  
    while csize>:  
        in\_feat = cndf

        out\_feat = cndf \* 

        main.add\_module('pyramid-{0}-{1}-conv'.format(in\_feat, out\_feat),nn.Conv2d(in\_feat, out\_feat, , , , bias=False))

        main.add\_module('pyramid-{0}-batchnorm'.format(out\_feat),nn.BatchNorm2d(out\_feat))

        main.add\_module('pyramid-{0}-relu'.format(out\_feat),nn.LeakyReLU(0.2, inplace=True))

        cndf = cndf \* 

        csize = csize / 

    # 最后一层卷积,将4\*4变为1\*,得到nz = 100的噪声  
    if add\_final\_conv:

        main.add\_module('final-{0}-{1}-conv'.format(cndf, ),nn.Conv2d(cndf, nz, , , , bias=False))  
        self.main=main

def forward(self,input):  
    if self.ngpu>:  
         output=nn.parallel.data\_parallel(self.main,input,range(self.ngpu)) #在多个gpu上运行模型,并行计算  
    else:  
        output=self.main(input)

    return output  #如果输入的大小是3××,最后的输出是100××.

判别器为:

#定义判别器D (编码器)
class NetD(nn.Module):
def __init__(self, opt):
super(NetD, self).__init__()

    # 第二个参数是1 因为判别器最后输出一个数  
    # 不过编码器在生成器里的时候  
    # 这个参数是100 因为它要把图片下采样成100××1的向量  
    model = Encoder(opt.isize, , opt.nc, opt.ndf, opt.ngpu, opt.extralayers)  

    layers = list(model.main.children())

    '''layers的输出如下:  
    \[  
    Conv2d(, , kernel\_size=(, ), stride=(, ), padding=(, ), bias=False),

    LeakyReLU(negative\_slope=0.2, inplace),

    Conv2d(, , kernel\_size=(, ), stride=(, ), padding=(, ), bias=False),

    BatchNorm2d(, eps=1e-, momentum=0.1, affine=True, track\_running\_stats=True),

    LeakyReLU(negative\_slope=0.2, inplace),

    Conv2d(, , kernel\_size=(, ), stride=(, ), padding=(, ), bias=False),

    BatchNorm2d(, eps=1e-, momentum=0.1, affine=True, track\_running\_stats=True),

    LeakyReLU(negative\_slope=0.2, inplace),

    Conv2d(, , kernel\_size=(, ), stride=(, ), bias=False)\] 因为132行定义的nz参数是1,所以经过这层之后输出的大小是1××  
    '''

    self.features = nn.Sequential(\*layers\[:-\])  
    # self.features的内容为除了最后一层的前8层  
    # nn.Sequential函数里面的参数一定是Module的子类,而list不是一个模块子类,所以不能当做参数  
    # 当然model.children()也一样不是一个模块子类,只有他们里面的值才是  
    # 这里的\*就起了作用,将list或者children的内容迭代地一个一个的传进去。

    #生成一个分类器模块  
    self.classifier = nn.Sequential(layers\[-\])  
    #self.classifier的内容为Conv2d(, , kernel\_size=(, ), stride=(, ), bias=False)最后一层  
    #并在后面添加子模块sigmoid  
    self.classifier.add\_module('Sigmoid', nn.Sigmoid())

def forward(self, x):

    features = self.features(x) #图片通过前8层之后的结果256××,前提是输入的图片的大小是32

    features = features

    classifier = self.classifier(features)#此时的结果是1××,值在\[,\],因为经过了sigmoid

    classifier = classifier.view(-, ).squeeze()  
    #a=torch.ones(\[,,\])  即a=tensor(\[\[\[ .\]\]\])   再a.view(-,) 变成tensor(\[\[ .\]\])  再加一个squeeze就是  
    # a.view(-,).squeeze() 结果是tensor(\[ .\]),squeeze里的值是0是1随意,只要去掉一个维度上的就可以

    # 因此返回得到一个判别值classifier 和一个大小为256××4的特征值  
    return classifier, features

重点在:

  • layers = list(model.main.children())
  • self.features = nn.Sequential(*layers[:-1]) :使用除了最后一层的前面所有层
  • self.classifier = nn.Sequential(layers[-1]):仅使用最后一层

这里可见同样的模型结构我们在Encoder.py中已经定义过一遍了,在判别其中实在不想再定义一遍,那我们就能够使用model.main.children()来获得模块中的子模块,然后将其转成列表形式,然后就能够根据想要的部分来进行处理了