1、MNIST数据集处理、加载、网络初始化、测试函数
2、训练函数、PyTorch构建LeNet网络
3、PyTorch从零构建AlexNet训练MNIST数据集
4、PyTorch从零构建VGGNet训练MNIST数据集
5、PyTorch从零构建GoogLeNet训练MNIST数据集
6、PyTorch从零构建ResNet训练MNIST数据集
任务概述:5万张训练集+1万张测试集的手写数字图片,经典的MNIST数据集,通过神经网络预测出结果
训练参数我们只需要定义:训练设备、最大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
num_classes = 10
,MNIST数据集是10分类任务wdecay = 0.00
权重衰减为0print("\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)
train_data = datasets.MNIST
和test_data = datasets.MNIST
是在下载MNIST数据集,所以第一次运行会下周一段时间train_data_shape = tuple((train_data.data).shape)
是获取训练数据的维度数据,后面依次是训练标签、测试数据、测试标签true_value = test_data.targets
用于计算准确率等分类指标需要用到的标签运行结果:
Reading data…
train_data: (60000, 28, 28) train_label (60000,)
test_data: (10000, 28, 28) test_label (10000,)
训练数据6万张图片,测试数据1万张图片
制作训练集和测试集的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
将保留剩余的不足一个批次的样本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)
逐行解释代码:
from model import VGGNet as model
,这里导入的是VGG测试函数主要是为了评估当前网络得到预测后的准确率,用来评价训练得到的网络效果如何
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,'%')
逐行解释代码:
net.eval()
: 这是一个模型状态切换的操作,它将模型切换到评估模式,模型通常会关闭一些训练时用到的特性,例如批量归一化层(Batch Normalization)的统计信息不再更新,Dropout层(如果有的话)会被禁用。这有助于确保评估过程的一致性和可重复性。一旦评估结束,与其对应的是net.train()
将模型切换回训练模式。torch.no_grad()
: 这是一个上下文管理器,它告诉PyTorch在该上下文中不计算梯度信息,以节省内存并加速评估过程。在评估过程中,通常不需要计算梯度,因为不会进行参数更新。这可以确保评估代码不会意外地修改模型参数。predicted_class.cpu()
:把数据从GPU放到CPU中,predicted_class.cpu().detach().numpy()
:得到一个不具有梯度历史的数据并且转换为numpy数据的格式,最后把分类结果加入到prediction 数组中。循环结果,即测试集迭代结束np.concatenate
将前面(32,1)的数据转换成1维的数组,此时prediction 中包含了测试集1万张图片的分类预测结果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的计算结果保留两位小数