chainer-骨干网络backbone-LeNet5代码重构【附源码】

文章介绍了如何使用Chainer库分别以简单类形式和列表形式构建经典的LeNet5卷积神经网络模型,详细展示了网络结构的定义,包括卷积层、激活函数和最大池化层的设置。两种方法在功能上是等效的,可用于图像分类任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

本文以标准的chainer模型构建的方式构建lenet结构,代码阅读性强。


一、LeNet5简单版实现

class LeNet5_Simple(chainer.Chain):
    def __init__(self,num_classes=10, channels=1,image_size=28,initialW=chainer.initializers.Normal(0.01)):
        super(LeNet5_Simple, self).__init__()
        with self.init_scope():
            # (28-5+2*0)/1+1=24 12   (224-5+2*0)/1+1=220 maxpooling:110
            self.conv1 = L.Convolution2D(in_channels=channels, out_channels=6, ksize=5, stride=1,initialW=initialW)
            out_size = math.ceil(((image_size-5+2*0)//1+1)/2)
            # (12-5+2*0)/1+1=8  4    (110-5+2*0)/1+1=106 maxpooling:53
            self.conv2 = L.Convolution2D(in_channels=6, out_channels=16, ksize=5, stride=1,initialW=initialW)
            out_size = math.ceil(((out_size-5+2*0)//1+1)/2)
            # (4-4+2*0)/1+1=1        (53-4+2*0)/1+1=50
            self.conv3 = L.Convolution2D(in_channels=16, out_channels=120, ksize=4, stride=1,initialW=initialW)
            out_size = ((out_size-4+2*0)//1+1)
            self.fc4 = L.Linear(120*out_size*out_size, 84,initialW=initialW)
            self.fc5 = L.Linear(84, num_classes,initialW=initialW)

    def __call__(self, x):
        h = F.sigmoid(self.conv1(x))
        h = F.max_pooling_2d(h, 2, 2)
        h = F.sigmoid(self.conv2(h))
        h = F.max_pooling_2d(h, 2, 2)
        h = F.sigmoid(self.conv3(h))
        h = F.sigmoid(self.fc4(h))
        
        if chainer.config.train:
            return self.fc5(h)
        return F.softmax(self.fc5(h))

二、利用列表形式进行构建网络

class LeNet5_Complex(chainer.Chain):
    def __init__(self,num_classes=10, channels=1,image_size=28,initialW=chainer.initializers.Normal(0.01)):
        super(LeNet5_Complex, self).__init__()
        # (28-5+2*0)/1+1=24 12   (224-5+2*0)/1+1=220 maxpooling:110
        net = [('conv1', L.Convolution2D(in_channels=channels, out_channels=6, ksize=5, stride=1,initialW=initialW))]
        net += [('_sigm1', Sigmoid())]
        net += [('_mpool1', MaxPooling2D(2, 2))]
        out_size = math.ceil(((image_size-5+2*0)//1+1)/2)
        # (12-5+2*0)/1+1=8  4    (110-5+2*0)/1+1=106 maxpooling:53
        net += [('conv2', L.Convolution2D(in_channels=6, out_channels=16, ksize=5, stride=1,initialW=initialW))]
        net += [('_sigm2', Sigmoid())]
        net += [('_mpool2', MaxPooling2D(2, 2))]
        out_size = math.ceil(((out_size-5+2*0)//1+1)/2)
        # (4-4+2*0)/1+1=1        (53-4+2*0)/1+1=50
        net += [('conv3', L.Convolution2D(in_channels=16, out_channels=120, ksize=4, stride=1,initialW=initialW))]
        out_size = ((out_size-4+2*0)//1+1)
        net += [('_sigm3', Sigmoid())]
        # net += [('_mpool3', MaxPooling2D(2, 2))]
        net += [('fc4', L.Linear(120*out_size*out_size, 84))]
        net += [('_sigm4', Sigmoid())]
        net += [('fc5', L.Linear(84, num_classes))]
        net += [('_sigm5', Sigmoid())]
        with self.init_scope():
            for n in net:
                if not n[0].startswith('_'):
                    setattr(self, n[0], n[1])
        self.forward = net

    def __call__(self, x):
        for n, f in self.forward:
            origin_size = x.shape
            if not n.startswith('_'):
                x = getattr(self, n)(x)
            else:
                x = f.apply((x,))[0]
            print(n,origin_size,x.shape)
        if chainer.config.train:
            return x
        return F.softmax(x)

以上两种方式效果一致


总结

调用方式

if __name__ == '__main__':
    batch_size = 4
    n_channels = 1
    image_size = 28
    num_classes = 10
    
    model_simple = LeNet5_Simple(num_classes=num_classes, channels=n_channels,image_size=image_size)
    model_complex = LeNet5_Complex(num_classes=num_classes, channels=n_channels,image_size=image_size)
    print(model_simple.count_params())
    print(model_complex.count_params())
    x = np.random.rand(batch_size, n_channels, image_size, image_size).astype(np.float32)
    t = np.random.randint(0, num_classes, size=(batch_size,)).astype(np.int32)
    with chainer.using_config('train', True):
        y1 = model_simple(x)
        y2 = model_complex(x)
    loss1 = F.softmax_cross_entropy(y1, t)
    loss2 = F.softmax_cross_entropy(y2, t)
    print(loss1.data,loss2.data)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习的广东仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值