现代卷积网络实战系列1:MNIST数据集处理、加载、网络初始化、测试函数

🌈🌈🌈现代卷积网络实战系列 总目录

本篇文章的代码运行界面均在Pycharm中进行
本篇文章配套的代码资源已经上传

1、MNIST数据集处理、加载、网络初始化、测试函数
2、训练函数、PyTorch构建LeNet网络
3、PyTorch从零构建AlexNet训练MNIST数据集
4、PyTorch从零构建VGGNet训练MNIST数据集
5、PyTorch从零构建GoogLeNet训练MNIST数据集
6、PyTorch从零构建ResNet训练MNIST数据集

任务概述:5万张训练集+1万张测试集的手写数字图片,经典的MNIST数据集,通过神经网络预测出结果

1、定义训练参数

训练参数我们只需要定义:训练设备、最大epoch、batch_size、学习率、优化器、学习率衰减率、分类数、权重衰减这几个参数就可以了
使用argparse包配置参数

parser = argparse.ArgumentParser()
parser.add_argument('--device', type=str, default='cuda:0', help='')
parser.add_argument('--max_epoch', type=int, default=10, help='Epoch to run [default: 250]')
parser.add_argument('--batch_size', type=int, default=8, help='Batch Size during training [default: 32]')
parser.add_argument('--learning_rate', type=float, default=0.0005, help='Initial learning rate [default: 0.001]')
parser.add_argument('--optimizer', default='adam', help='adam or momentum [default: adam]')
parser.add_argument('--decay', type=float, default=0.92, help='decay rate of learning rate [0.97/0.92]')

取出配置参数

FLAGS = parser.parse_args()
decay = FLAGS.decay
batch_size = FLAGS.batch_size
epochs = FLAGS.max_epoch
learning_rate = FLAGS.learning_rate
optimizer = FLAGS.optimizer
device = torch.device(FLAGS.device)
num_classes = 10
wdecay = 0.00
  1. batch_szie要根据自己的计算资源调整,越大越好,但是太大可能跑不起来
  2. epochs设置成10个就够了,收敛很快
  3. num_classes = 10,MNIST数据集是10分类任务
  4. wdecay = 0.00权重衰减为0

2、获取数据

2.1 加载数据

print("\nReading data...")
train_data = datasets.MNIST(
    root="./data/",
    train=True,
    transform=transforms.ToTensor(),
    download=True)

test_data = datasets.MNIST(
    root="./data/",
    train=False,
    transform=transforms.ToTensor(),
    download=True)
train_data_shape = tuple((train_data.data).shape)
train_label_shape = tuple((train_data.targets).shape)

test_data_shape = tuple((test_data.data).shape)
test_label_shape = tuple((test_data.targets).shape)
true_value = test_data.targets
print('train_data:',train_data_shape,'train_label',train_label_shape)
print('test_data:',test_data_shape,'test_label',test_label_shape)
  1. train_data = datasets.MNISTtest_data = datasets.MNIST是在下载MNIST数据集,所以第一次运行会下周一段时间
  2. train_data_shape = tuple((train_data.data).shape)是获取训练数据的维度数据,后面依次是训练标签、测试数据、测试标签
  3. true_value = test_data.targets用于计算准确率等分类指标需要用到的标签
  4. 打印出前面获取的shape值

运行结果:

Reading data…
train_data: (60000, 28, 28) train_label (60000,)
test_data: (10000, 28, 28) test_label (10000,)

训练数据6万张图片,测试数据1万张图片

2.2 制作dataloader

制作训练集和测试集的DataLoader

train_loader = torch.utils.data.DataLoader(
    dataset=train_data,
    batch_size=32,
    shuffle=True,
    drop_last=True)

test_loader = torch.utils.data.DataLoader(
    dataset=test_data,
    batch_size=32,
    shuffle=False,
    drop_last=False)

指定前面我们定义好的数据、batch_size
shuffle:是否需要洗牌的操作,训练集一万张图像设置为True,在不同epoch的加载顺序不同会让网络有更好的效果,但是在测试集设置为False,测试集需要得到预测结果,预测结果和真实的结果计算准确率的时候,需要保证原来的顺序,所以训练集不可以打乱

drop_last:用于控制在数据集中的样本数量不能整除批次大小时是否丢弃剩余的不足一个批次的样本。

  • drop_last=True 时, 将会丢弃剩余的不足一个批次的样本。
  • drop_last=False 时,DataLoader 将保留剩余的不足一个批次的样本

2.3 初始化网络

net = model(num_classes)
net.to(device)  # to cuda
optimizer = optim.Adam(net.parameters(), lr=learning_rate, weight_decay=wdecay)
scheduler = optim.lr_scheduler.ExponentialLR(optimizer, decay)
print('\nInitialize neural network')
test(net, test_loader, device, true_value, epoch=0)

逐行解释代码:

  1. 指定网络,在前面导包的时候,会有这行代码from model import VGGNet as model,这里导入的是VGG
  2. 网络放入GPU
  3. 优化器,adam优化器,学习率,权重衰减
  4. 学习率衰减测量
  5. 打印初始化神经网络
  6. 调用测试函数(评估函数),计算网络预测结果的准确率

3、测试函数

3.1 测试函数

测试函数主要是为了评估当前网络得到预测后的准确率,用来评价训练得到的网络效果如何

def test(net, test_loader, device, true_value, epoch):
    net.eval()
    with torch.no_grad():
        all_test_loss = []
        prediction = []
        for batch_idx, (data, target) in enumerate(test_loader):
            data = data.to(device)
            target = target.to(device)
            output = net(data)
            cur_test_loss = F.cross_entropy(output, target)
            all_test_loss.append(cur_test_loss.item())
            _, predicted_class = torch.max(output, 1)
            prediction.append(predicted_class.cpu().detach().numpy())
        prediction = np.concatenate(prediction, 0)
        test_loss = np.round(np.mean(all_test_loss)*1000, 2)
        accuracy = np.round(accuracy_score(true_value, prediction) * 100, 2)
        print('test loss:', test_loss)
        print('test accuracy:', accuracy,'%')

逐行解释代码:

  1. 测试函数,当前GPU中的网络,测试数据集,训练设备,真实数据,当前训练的epoch
  2. net.eval(): 这是一个模型状态切换的操作,它将模型切换到评估模式,模型通常会关闭一些训练时用到的特性,例如批量归一化层(Batch Normalization)的统计信息不再更新,Dropout层(如果有的话)会被禁用。这有助于确保评估过程的一致性和可重复性。一旦评估结束,与其对应的是net.train() 将模型切换回训练模式。
  3. torch.no_grad(): 这是一个上下文管理器,它告诉PyTorch在该上下文中不计算梯度信息,以节省内存并加速评估过程。在评估过程中,通常不需要计算梯度,因为不会进行参数更新。这可以确保评估代码不会意外地修改模型参数。
  4. all_test_loss存放测试集一万张图片的损失
  5. prediction 存放一万字图片的分类预测结果
  6. 按照索引、(数据、标签)的方式迭代测试集
  7. 数据进入GPU
  8. 标签进入GPU
  9. 当前batch的所有数据进入网络后,计算得到的输出,维度为(batch_size=32,classes_score=10),假如batch_size是32的话(后面都以此举例),那这里就是32张图片的输出结果,一张图片包含10个分类的概率值,即(32,10)的输出维度
  10. 使用分类的交叉熵损失函数计算当前32张图片的损失,也就是一张图片对应一个值
  11. 把当前的32个损失都放入到all_test_loss 数组中
  12. 获取当前图片的10个分类分数最高的那一个,并且根据索引得到是那一个数字(这里索引刚好对应数字,0-9的索引,对应0-9数字),也就是当前batch得到32个预测结果的数字
  13. predicted_class.cpu():把数据从GPU放到CPU中,predicted_class.cpu().detach().numpy():得到一个不具有梯度历史的数据并且转换为numpy数据的格式,最后把分类结果加入到prediction 数组中。循环结果,即测试集迭代结束
  14. np.concatenate将前面(32,1)的数据转换成1维的数组,此时prediction 中包含了测试集1万张图片的分类预测结果
  15. 将所有的损失求平均,test_loss就是当前训练集的损失
  16. 使用accuracy 函数,将预测的结果和真实的数据作对比,得到准确率
  17. 打印出准确率和损失

3.2 准确率计算函数

np.set_printoptions(precision=2)
def accuracy_score(y_true, y_pred):
    correct = sum(1 for true, pred in zip(y_true, y_pred) if true == pred)
    total = len(y_true)
    return correct / total

现在有一个包含n个预测结果的数组y_pred,以及一个真实结果的标签数组y_pred,计算出预测正确的个数,比上所有样本,得到正确率
np.set_printoptions(precision=2)设置当前python文件中,所有numpy的计算结果保留两位小数

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

机器学习杨卓越

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

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

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

打赏作者

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

抵扣说明:

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

余额充值