VGG-11的实现

本文是笔者在学习深度学习过程中的代码分享,主要是对实现代码的一些注释 

dl库中的函数

#计时器
class Timer:  
    """记录多次运行时间"""
    def __init__(self):
        self.times = []
        self.start()

    def start(self):
        """启动计时器"""
        self.tik = time.time()

    def stop(self):
        """停止计时器并将时间记录在列表中"""
        self.times.append(time.time() - self.tik)
        return self.times[-1]

    def avg(self):
        """返回平均时间"""
        return sum(self.times) / len(self.times)

    def sum(self):
        """返回时间总和"""
        return sum(self.times)

    def cumsum(self):
        """返回累计时间"""
        return np.array(self.times).cumsum().tolist()
#加载图片分类数据集
def load_data_fashion_mnist(batch_size, resize=None):
    """下载Fashion-MNIST数据集,然后将其加载到内存中"""
    trans = [transforms.ToTensor()]
    if resize:
        trans.insert(0, transforms.Resize(resize))
    trans = transforms.Compose(trans)
    mnist_train = torchvision.datasets.FashionMNIST(
        root="../data", train=True, transform=trans, download=True)
    mnist_test = torchvision.datasets.FashionMNIST(
        root="../data", train=False, transform=trans, download=True)
    return (data.DataLoader(mnist_train, batch_size, shuffle=True,num_workers=2,pin_memory=False),
            data.DataLoader(mnist_test, batch_size, shuffle=False,num_workers=2,pin_memory=False))
#使用gpu
def try_gpu(i=0):  
    """如果存在,则返回gpu(i),否则返回cpu()"""
    if torch.cuda.device_count() >= i + 1:
        return torch.device(f'cuda:{i}')
    return torch.device('cpu')
#计算精度
def evaluate_accuracy_gpu(net, data_iter, device=None): #@save
    """使用GPU计算模型在数据集上的精度"""
    if isinstance(net, nn.Module):
        net.eval()  # 设置为评估模式
        if not device:#设置为网络模型中的第一个参数的设备
            device = next(iter(net.parameters())).device#net.parameters() 返回迭代器包含神经网络模型中的所有参数
    # 正确预测的数量,总预测的数量
    metric = Accumulator(2)#累加两个变量的累加器
    with torch.no_grad():
        for X, y in data_iter:
            #将张量移动到指定设备上
            if isinstance(X, list):
                X = [x.to(device) for x in X]
            else:
                X = X.to(device)
            y = y.to(device)
            metric.add(accuracy(net(X), y), y.numel())
    return metric[0] / metric[1]
#训练模型
def train_cnn(net, train_iter, test_iter, num_epochs, lr, device):
    """用GPU训练模型"""
    def init_weights(m):#初始化权重参数
        if type(m) == nn.Linear or type(m) == nn.Conv2d:
            nn.init.xavier_uniform_(m.weight)
    net.apply(init_weights)
    print('training on', device)
    net.to(device)#将网络放到gpu
    optimizer = torch.optim.SGD(net.parameters(), lr=lr)#优化算法(梯度下降)
    loss = nn.CrossEntropyLoss()#损失函数(交叉熵损失)
    timer, num_batches = Timer(), len(train_iter)#计时器
    train_losses, train_accuracies, test_accuracies = [], [], []#三个存储列表
    for epoch in range(num_epochs):
        metric = Accumulator(3)  # 累加器:训练损失之和,训练准确率之和,样本数
        net.train()#训练模式
        for i, (X, y) in enumerate(train_iter):
            timer.start()#启动计时器
            optimizer.zero_grad()#清空梯度
            X, y = X.to(device), y.to(device)#将数据放到gpu
            y_hat = net(X)#计算输出
            l = loss(y_hat, y)#计算损失
            l.backward()#计算梯度
            optimizer.step()#更新参数
            with torch.no_grad():
                metric.add(l * X.shape[0], accuracy(y_hat, y), X.shape[0])
            timer.stop()#停止计时器
        train_l = metric[0] / metric[2]#平均损失
        train_acc = metric[1] / metric[2]#平均准确率
        #存储损失和准确率同来绘图
        train_losses.append(train_l)
        train_accuracies.append(train_acc)
        #测试数据集准确率
        test_acc = evaluate_accuracy_gpu(net, test_iter)
        test_accuracies.append(test_acc)

    # 绘制训练过程中的损失和准确率
    epochs = range(1, num_epochs + 1)
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.plot(epochs, train_losses, label='Train Loss')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend()

    plt.subplot(1, 2, 2)
    plt.plot(epochs, train_accuracies, label='Train Accuracy')
    plt.plot(epochs, test_accuracies, label='Test Accuracy')
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend()

    plt.show()
    print(f'loss {train_l:.3f}, train acc {train_acc:.3f}, '
          f'test acc {test_acc:.3f}')
    print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec '
          f'on {str(device)}')

 调用pytorch实现VGG

import torch
from torch import nn
from dl import torch as dl

#定义vgg块
def vgg_block(num_convs, in_channels, out_channels):
    layers = []#创建一个存储层的列表
    #根据参数添加卷积层
    for _ in range(num_convs):
        layers.append(nn.Conv2d(in_channels, out_channels,kernel_size=3, padding=1))#卷积层
        layers.append(nn.ReLU())#RuLu激活函数
        in_channels = out_channels#之后每个卷积层的输入输出通道相同
    layers.append(nn.MaxPool2d(kernel_size=2,stride=2))#加最大池化层
    return nn.Sequential(*layers)#将层列表放入容器当中
#构建VGG-11
def vgg(conv_arch):
    conv_blks = []#创建一个存储vgg块的列表
    in_channels = 1#初始输入通道
    # 卷积层部分
    for (num_convs, out_channels) in conv_arch:#取出每个块的参数
        conv_blks.append(vgg_block(num_convs, in_channels, out_channels))#构建vgg块
        in_channels = out_channels#更新进入下一个块的输入通道
    #将vgg块列表放入Sequential中,在展平后添加全连接层
    return nn.Sequential(
        *conv_blks, #vgg块叠加
        nn.Flatten(),#展平层
        # 全连接层部分
        nn.Linear(out_channels * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5),#RuLu激活函数,概率为0.5的丢弃法
        nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5),#RuLu激活函数,概率为0.5的丢弃法
        nn.Linear(4096, 10))#输出层
#构建模型
conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))#5个块的参数(卷积层数,输出通道数)
ratio = 4
small_conv_arch = [(pair[0], pair[1] // ratio) for pair in conv_arch]#构建通道数较小的网络
net = vgg(small_conv_arch)
#加载数据
batch_size =128
train_iter, test_iter = dl.load_data_fashion_mnist(batch_size, resize=224)
#训练模型
lr, num_epochs= 0.05, 10
if __name__ == "__main__":
    dl.train_cnn(net, train_iter, test_iter, num_epochs, lr, dl.try_gpu())

运行结果显示

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值