一、写好网络后如何测试网络的正确性?程序如下:
if __name__ == '__main__': # 通过以下代码测试模型的正确性 tudui = Tudui() input = torch.ones((64,3,32,32)) output = tudui(input) print(output.shape)
torch.ones((64,3,32,32))表示batch_size=64,channel=3,高H=32,宽W=32,cifar10的图片就是3通道,宽高就是32的
二、为了减少打印输出太多的冗余信息,通常每几百次训练打印一次损失,下面程序是每训练100次,打印一次损失值,具体程序如下:
if total_train_step % 100 ==0: print("训练次数 : {},Loss : {}".format(total_train_step,loss.item())) writer.add_scalar("train_loss",loss.item(),total_train_step)
为什幺loss要加一个item(),使其变成loss.item(),因为原本的loss是tensor类型,加了item后就变成了数值型,防止构建计算图,具体案例如下:
运行结果如下:
三、加入tensorboard,具体程序如下:
在terminal中输入tensorboard –logdir=logs –port=6007得到下图
四、模型的保存程序如下:
五、在分类问题当中,通常需要有正确率作为分类评判的标准。
argmax(1)时,是横向查找比较数据的大小索引,取出最大值所在的位置
也就是说,如果是为1,则返回每一 行 最大值的索引
argmax(0)时,是纵向查找比较数据的大小索引,取出最大值所在的位置
也就是说,如果是为0,则返回每一 列 最大值的索引
源程序计算准确率的代码如下:
六、model.train()的用法
model.train()的作用是 启用 Batch Normalization 和 Dropout。
如果模型中有BN层(Batch Normalization)和Dropout,需要在训练时添加model.train()。model.train()是保证BN层能够用到每一批数据的均值和方差。对于Dropout,model.train()是随机取一部分网络连接来训练更新参数。
七、model.eval()的用法
model.eval()的作用是 不启用 Batch Normalization 和 Dropout。
如果模型中有BN层(Batch Normalization)和Dropout,在测试时添加model.eval()。model.eval()是保证BN层能够用全部训练数据的均值和方差,即测试过程中要保证BN层的均值和方差不变。对于Dropout,model.eval()是利用到了所有网络连接,即不进行随机舍弃神经元。
训练完train样本后,生成的模型model要用来测试样本。在model(test)之前,需要加上model.eval(),否则的话,有输入数据,即使不训练,它也会改变权值。这是model中含有BN层和Dropout所带来的的性质。
在做one classification的时候,训练集和测试集的样本分布是不一样的,尤其需要注意这一点。
八、model.eval()和torch.no_grad()的区别
在PyTorch中进行validation/test时,会使用model.eval()切换到测试模式,在该模式下:
1. 主要用于通知dropout层和BN层在train和validation/test模式间切换:
在train模式下,dropout网络层会按照设定的参数p设置保留激活单元的概率(保留概率=p); BN层会继续计算数据的mean和var等参数并更新。
在eval模式下,dropout层会让所有的激活单元都通过,而BN层会停止计算和更新mean和var,直接使用在训练阶段已经学出的mean和var值。
2. 该模式不会影响各层的gradient计算行为,即gradient计算和存储与training模式一样,只是不进行反向传播(back probagation)。
而with torch.no_grad()则主要是用于停止autograd模块的工作,以起到加速和节省显存的作用。它的作用是将该with语句包裹起来的部分停止梯度的更新,从而节省了GPU算力和显存,但是并不会影响dropout和BN层的行为。
如果不在意显存大小和计算时间的话,仅仅使用model.eval()已足够得到正确的validation/test的结果;而with torch.no_grad()则是更进一步加速和节省gpu空间(因为不用计算和存储梯度),从而可以更快计算,也可以跑更大的batch来测试。
九、案例、实现下图的神经网络结构
完整程序如下:
model.py文件
import torch from torch import nn class Tudui(nn.Module): def __init__(self): super(Tudui, self).__init__() self.model1 = nn.Sequential( nn.Conv2d(3, 32, 5, padding=2, stride=1), nn.MaxPool2d(2), nn.Conv2d(32, 32, 5, padding=2, stride=1), nn.MaxPool2d(2), nn.Conv2d(32, 64, 5, padding=2, stride=1), nn.MaxPool2d(2), nn.Flatten(), nn.Linear(1024, 64), nn.Linear(64, 10) ) def forward(self, x): x = self.model1(x) return x if __name__ == '__main__': # 通过以下代码测试模型的正确性 tudui = Tudui() input = torch.ones((64,3,32,32)) output = tudui(input) print(output.shape)
train.py文件
import torchvision from torch import nn from torch.nn import Conv2d, MaxPool2d, Flatten from torch.utils.tensorboard import SummaryWriter from model import * from torch.utils.data import DataLoader train_data = torchvision.datasets.CIFAR10(root='./data_CIFAR10',train=True, transform=torchvision.transforms.ToTensor(),download=True) test_data = torchvision.datasets.CIFAR10(root='./data_CIFAR10',train=False, transform=torchvision.transforms.ToTensor(),download=True) train_data_size = len(train_data) test_data_size = len(test_data) print("训练数据集的长度为:{} " .format(train_data_size)) print("测试数据集的长度为:{} " .format(test_data_size)) train_dataloader = DataLoader(train_data,batch_size=64) test_dataloader = DataLoader(test_data,batch_size=64) #搭建神经网络 tudui = Tudui() #损失函数 loss_fn = nn.CrossEntropyLoss() #优化器 optimizer = torch.optim.SGD(tudui.parameters(),lr=0.01) #设置训练网络的一些参数 total_train_step = 0 total_test_step = 0 epoch = 10 writer = SummaryWriter('./logs_train') for i in range(epoch): print("------------第 {} 轮训练开始--------------".format(i+1)) tudui.eval() for data in train_dataloader: imgs,targets = data outputs = tudui(imgs) loss = loss_fn(outputs,targets) optimizer.zero_grad() loss.backward() optimizer.step() total_train_step +=1 if total_train_step % 100 ==0: print("训练次数 : {},Loss : {}".format(total_train_step,loss.item())) writer.add_scalar("train_loss",loss.item(),total_train_step) tudui.eval() total_test_loss = 0 total_accuracy = 0 with torch.no_grad(): for data in test_dataloader: imgs,targets = data outputs = tudui(imgs) loss = loss_fn(outputs,targets) total_test_loss += loss.item() accuracy = (outputs.argmax(1) == targets).sum() total_accuracy = total_accuracy +accuracy print("整体测试数据集的Loss:{}".format(total_test_loss)) print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size)) writer.add_scalar('test_loss',total_test_loss,total_test_step) writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step) total_test_step += 1 torch.save(tudui, 'tudui_{}.pth'.format(i)) print("模型已保存") writer.close()
运行结果如下:
Be First to Comment