上篇文章对LeNet-5网络结构做了简单分析,并用pytorch搭建了该网络,同时实现了数据迭代器和一个简单的训练器对MNIST数据集做了简单训练,观察了训练过程中损失函数以及正确率的的变化情况,达到了预期效果。
本文将对上篇文章中的训练器稍作改进,希望在训练过程中可以观察损失函数值,以及模型在训练集和测试集上的正确率来判断神经网络的学习是否正常进行,模型是否出现过拟合。
1.改进前
def train(net,train_iter,test_iter,num_epochs,lr):
def init(n):
if type(n)==nn.Conv2d or type(n)==nn.Linear:
nn.init.normal(n.weight.data)
net.apply(init)
optimizer =torch.optim.SGD(net.parameters(),lr=lr)
loss=nn.CrossEntropyLoss()
train_loss_list=[]
train_acc_list=[]
for i in range(num_epochs):
for j,(X,y) in enumerate(train_iter):
optimizer.zero_grad()
Y=net(X)
l=loss(Y,y)
l.backward()
optimizer.step()
train_loss_list.append(l.data*X.shape[0]/X.shape[0])
train_acc_list.append(accuracy(Y,y)/X.shape[0])
该训练器将每一个batch的正确率和学习时的损失函数都保存了下来:
for j,(X,y) in enumerate(train_iter):
optimizer.zero_grad()
Y=net(X)
l=loss(Y,y)
l.backward()
optimizer.step()
train_loss_list.append(l.data*X.shape[0]/X.shape[0])
train_acc_list.append(accuracy(Y,y)/X.shape[0])
对MNIST数据集而言,训练集共有加60000张图片,假如一个batch为100张照片,那么一个epoch共有60000/100=600个batch,训练一个epoch打印600组数据,完全没有必要。
2.改进后
for i in range(num_epochs):
train_loss=0.0
train_acc=0.0
for j,(X,y) in enumerate(train_iter):
optimizer.zero_grad()
Y=net(X)
l=loss(Y,y)
l.backward()
optimizer.step()
train_loss+=l.item()
train_acc+=accuracy(Y,y)/X.shape[0]
if j%200==199:
a=train_loss/200.0
b=train_acc/200.0
train_loss_list.append(a)
train_acc_list.append(b)
train_loss=0.0
train_acc=0.0
with torch.no_grad():#在测试数据集上测试
for m,(X_test,y_test) in enumerate(train_iter):
output=net(X_test)
acc=accuracy(output,y_test)/X.shape[0]
test_acc_list.append(acc)
print(f'train_loss:{a:.3f},train_acc:{b:.3f},test_acc:{acc:.3f}')
改进后的训练器每训练200个batch才会计算这200个batch的损失函数和准确率的平均值:
train_loss+=l.item()
train_acc+=accuracy(Y,y)/X.shape[0]
if j%200==199:
a=train_loss/200.0
b=train_acc/200.0
train_loss_list.append(a)
train_acc_list.append(b)
同时还会计算在测试集上的准确率,用来判断模型是否过拟合(一般认为训练集上的准确率高而测试集上的准确率过低是模型过拟合):
with torch.no_grad():#在测试数据集上测试
for m,(X_test,y_test) in enumerate(train_iter):
output=net(X_test)
acc=accuracy(output,y_test)/X.shape[0]
test_acc_list.append(acc)
3.总结
本文对上篇文章中的训练器稍作改进,改进后的训练器每训练200个batch才会计算这200个batch的损失函数和准确率的平均值,当然也可以根据自己的需求调整batch个数,同时还计算在测试集上的准确率,用来判断模型是否过拟合。
最后将训练过程的损失函数值以及模型在测试集和训练集上的正确率都记录到了相应的列表里,用来画图,以便更加直观地观察数据随训练过程的变化。
(------纯属个人见解,欢迎交流不同意见------)