前引


还有三部分 还要继续搞
可以剩一点放在明天上午搞 先这样 我先去把GoogleNet 给复现一遍

这两天早点弄完 明天多花点时间陪一下npy


从零开始的推荐系统学习之路(十五)---- 动手学深度学习系列 卷积神经网络 CNN(GoogLeNet & BatchNorm & ResNet)


1、GoogLeNet


下面即是 GoogleNet Inception的架构图 还有详细的架构图

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


import torch.nn.functional as F


class Inception(nn.Module):
    def __init__(self, in_channels, c1, c2, c3, c4, **kwargs):
        super().__init__()
        self.c1_1 = nn.Conv2d(in_channels, c1, kernel_size=1)
        self.c2_1 = nn.Conv2d(in_channels, c2[0], kernel_size=1)
        self.c2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)
        self.c3_1 = nn.Conv2d(in_channels, c3[0], kernel_size=1)
        self.c3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)
        self.c4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)
        self.c4_2 = nn.Conv2d(in_channels, c4, kernel_size=1)

    def forward(self, x):
        c1 = F.relu(self.c1_1(x))
        c2 = F.relu(self.c2_2(F.relu(self.c2_1(x))))
        c3 = F.relu(self.c3_2(F.relu(self.c3_1(x))))
        c4 = F.relu(self.c4_2(self.c4_1(x)))
        # print(c1.shape, c2.shape, c3.shape, c4.shape, torch.cat([c1, c2, c3, c4], 1).shape)
        return torch.cat([c1, c2, c3, c4], 1)




b1b2 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
                   nn.ReLU(),
                   nn.MaxPool2d(3, stride=2, padding=1),
                   nn.Conv2d(64, 64, kernel_size=1),
                   nn.ReLU(),
                   nn.Conv2d(64, 192, kernel_size=3, padding=1),
                   nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
                   nn.ReLU(),
                   nn.MaxPool2d(3, stride=2, padding=1))

b2 = nn.Sequential(nn.Conv2d(64, 64, kernel_size=1),
                   nn.ReLU(),
                   nn.Conv2d(64, 192, kernel_size=3, padding=1),
                   nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

X = torch.zeros((1, 1, 224, 224))
for layer in b1b2:
    X = layer(X)
    print(layer.__class__.__name__, '\t', X.shape)


X = torch.zeros((1, 1, 224, 224))
b1b2net = nn.Sequential(b1, b2)
for layer in b1b2net:
    X = layer(X)
    print("b1b2net",  layer.__class__.__name__, '\t', X.shape)



b3 = nn.Sequential(Inception(192, 64, (96, 128), (16, 32), 32),
                   Inception(256, 128, (128, 192), (32, 96), 64),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

X = torch.zeros((1, 1, 224, 224))
b1b2b3net = nn.Sequential(b1, b2, b3)
for layer in b1b2b3net:
    X = layer(X)
    print(layer.__class__.__name__, '\t', X.shape)


b4 = nn.Sequential(Inception(480, 192, (96, 208), (16, 48), 64),
                   Inception(512, 160, (112, 224), (24, 64), 64),
                   Inception(512, 128, (128, 256), (24, 64), 64),
                   Inception(512, 112, (144, 288), (32, 64), 64),
                   Inception(528, 256, (160, 320), (32, 128), 128),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

X = torch.zeros((1, 1, 224, 224))
b1b2b3b4net = nn.Sequential(b1, b2, b3, b4)
for layer in b1b2b3b4net:
    X = layer(X)
    print(layer.__class__.__name__, '\t', X.shape)



b5 = nn.Sequential(Inception(832, 256, (160, 320), (32, 128), 128),
                   Inception(832, 384, (192, 384), (48, 128), 128),
                   nn.AdaptiveAvgPool2d((1,1)),
                   nn.Flatten())

X = torch.zeros((1, 1, 94, 94))
net = nn.Sequential(b1, b2, b3, b4, b5, nn.Dropout(p=0.5), nn.Linear(1024, 10))
for layer in net:
    X = layer(X)
    print(layer.__class__.__name__, '\t', X.shape)



lr, num_epochs, batch_size = 0.1, 10, 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size, resize=96)
train_ch6(net, train_iter, test_iter, num_epochs, lr, try_gpu_mps(), "relu")

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


2、BatchNorm(批量归一化)


原理 站在我的角度来说 可以使参数输出更稳定 作用于特征纬度 然后 可以学习到 新的方差 和 均值
也有说的是 数据 例如减去了新的误差 以及数据去变换了

一般不与dropout同时去用

在这里插入图片描述


def batch_norm(X, gamma, beta, moving_mean, moving_var, eps=1e-5, momentum=0.9):
    if not torch.is_grad_enabled():
        X_hat = (X - moving_mean) / torch.sqrt(moving_var + eps)
    else:
        assert len(X.shape) in (2, 4)
        mean, var, features = 0.0, 1.0, 0
        if len(X.shape) == 2:
            mean = X.mean(dim=0, keepdims=True)
            var = ((X - mean) ** 2).mean(dim=0, keepdims=True)
        else:
            mean = X.mean(dim=(0, 2, 3), keepdims=True)
            # print(mean.shape)
            var = ((X - mean) ** 2).mean(dim=(0, 2, 3), keepdims=True)

        X_hat = (X - mean) / torch.sqrt(var + eps)

        moving_mean = momentum * moving_mean + (1 - momentum) * mean
        moving_var = momentum * moving_var + (1 - momentum) * var

    Y = gamma * X_hat + beta
    return Y, moving_mean, moving_var

class BatchNorm(nn.Module):
    # num_features:完全连接层的输出数量或卷积层的输出通道数。
    # num_dims:2表示完全连接层,4表示卷积层
    def __init__(self, num_features, num_dims):
        super().__init__()
        assert num_dims in (2, 4)
        shape = ()
        if num_dims == 2:
            shape = (1, num_features)
        else:
            shape = (1, num_features, 1, 1)
        
        self.gamma = nn.Parameter(torch.ones(shape))
        self.beta = nn.Parameter(torch.zeros(shape))
        self.moving_mean = torch.zeros(shape)
        self.moving_var = torch.ones(shape)

    def forward(self, X):
        if self.moving_mean.device != X.device:
            self.moving_mean = self.moving_mean.to(X.device)
            self.moving_var = self.moving_var.to(X.device)
        
        Y, self.moving_mean, self.moving_var = batch_norm(
            X, self.gamma, self.beta, self.moving_mean,
            self.moving_var, eps=1e-5, momentum=0.9)
        return Y

net = BatchNorm(3, 4)
X = torch.zeros(1, 3, 224, 224)
X.shape, net(X).shape


net = nn.Sequential(
    nn.Conv2d(1, 6, kernel_size=5), BatchNorm(6, num_dims=4), nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2),
    nn.Conv2d(6, 16, kernel_size=5), BatchNorm(16, num_dims=4), nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2), nn.Flatten(),
    nn.Linear(16*4*4, 120), BatchNorm(120, num_dims=2), nn.Sigmoid(),
    nn.Linear(120, 84), BatchNorm(84, num_dims=2), nn.Sigmoid(),
    nn.Linear(84, 10))


lr, num_epochs, batch_size = 1.0, 10, 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
train_ch6(net, train_iter, test_iter, num_epochs, lr, try_gpu_mps(), 'relu')



net = nn.Sequential(
    nn.Conv2d(1, 6, kernel_size=5), nn.BatchNorm2d(6), nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2),
    nn.Conv2d(6, 16, kernel_size=5), nn.BatchNorm2d(16), nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2), nn.Flatten(),
    nn.Linear(16*4*4, 120), nn.BatchNorm1d(120), nn.Sigmoid(),
    nn.Linear(120, 84), nn.BatchNorm1d(84), nn.Sigmoid(),
    nn.Linear(84, 10))


lr, num_epochs, batch_size = 1.0, 10, 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
train_ch6(net, train_iter, test_iter, num_epochs, lr, try_gpu_mps(), 'relu')

在这里插入图片描述
在这里插入图片描述


3、ResNet


**残参网络架构 我理解本质上有个类似的短路机制 或者说大网络包含着小网络 让网络更稳定一点 **

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


class Residual(nn.Module):  
    def __init__(self, input_channels, num_channels, use_1x1conv=False, strides=1):
        super().__init__()
        self.c1 = nn.Conv2d(input_channels, num_channels, kernel_size=3, stride=strides, padding=1)
        self.b1 = nn.BatchNorm2d(num_channels)

        self.c2 = nn.Conv2d(num_channels, num_channels, kernel_size=3, padding=1)
        self.b2 = nn.BatchNorm2d(num_channels)

        self.c3 = None
        if use_1x1conv == True:
            self.c3 = nn.Conv2d(input_channels, num_channels, kernel_size=1, stride=strides)

    def forward(self, X):
        tmp = nn.functional.relu(self.b1(self.c1(X)))
        o1 = self.b2(self.c2(tmp))

        o2 = torch.zeros_like(o1)
        if self.c3 != None:
            o2 = self.c3(X)

        Y = nn.functional.relu(o1 + o2)
        return Y
        
        

blk = Residual(3,3)
X = torch.rand(4, 3, 6, 6)
Y = blk(X)
Y.shape


# 下面即为copy

def resnet_block(input_channels, num_channels, num_residuals,
                 first_block=False):
    blk = []
    for i in range(num_residuals):
        if i == 0 and not first_block:
            blk.append(Residual(input_channels, num_channels,
                                use_1x1conv=True, strides=2))
        else:
            blk.append(Residual(num_channels, num_channels))
    return blk

b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
                   nn.BatchNorm2d(64), nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

b2 = nn.Sequential(*resnet_block(64, 64, 2, first_block=True))
b3 = nn.Sequential(*resnet_block(64, 128, 2))
b4 = nn.Sequential(*resnet_block(128, 256, 2))
b5 = nn.Sequential(*resnet_block(256, 512, 2))

net = nn.Sequential(b1, b2, b3, b4, b5,
                    nn.AdaptiveAvgPool2d((1,1)),
                    nn.Flatten(), nn.Linear(512, 10))


lr, num_epochs, batch_size = 0.1, 10, 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=96)
train_ch6(net, train_iter, test_iter, num_epochs, lr, try_gpu_mps(), 'relu')

显然过拟合了

在这里插入图片描述

更多推荐