前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >激活函数Relu对精度和损失的影响研究

激活函数Relu对精度和损失的影响研究

作者头像
算法与编程之美
发布2023-08-22 14:15:05
1920
发布2023-08-22 14:15:05
举报
文章被收录于专栏:算法与编程之美

1 问题

在学习深度学习的过程中,欲探究激活函数Relu对精度和损失的影响。

2 方法

测试设置激活函数时和没有设置激活函数时网络的性能。

控制其余变量:

  • Beach_size=128
  • optimizer = torch.optim.SGD
  • 网络为三层全连接网络(784->512->10)
  • 训练周期=50

测试代码如下

from torchvision import datasetsfrom torchvision.transforms import ToTensorfrom torch import nnimport torchfrom torch.utils.data import DataLoaderimport torch.nn.functional as Fimport matplotlib.pyplot as pltfrom collections import defaultdict# (5)定义三层全连接网络# (5.1)创建一个新的类继承nn.Moduleclass MyNet(nn.Module): # (5.2) 定义网络有哪些层,这些层都作为成员变量 def __init__(self) -> None: super().__init__() # 第一层,第一个全连接层Full Connection(FC) # in_features表示该层的前面一层神经元个数 # out_features表示当前这的一层神经元个数 # 对应图里面layer2 self.fc1 = nn.Linear(in_features=784, out_features=512) # in_features就是这一层的输入是多少纬的向量, # 对应layer3 也是就输出层 self.fc2 = nn.Linear(in_features=512, out_features=10) # feature特征 # (5.3) 定义数据在网络中的流动 x就表示输入 # x - 28*28的图像 def forward(self, x): x=torch.flatten(x,1) x = self.fc1(x) # 输出:512,Layer 2 # x=F.relu(x) out = self.fc2(x) # 输出:10,Layer 3 return out#(7)训练网络#loss_list:记录每一个周期的平均loss数据def train(dataloader,net,loss_fn,optimizer): size = len((dataloader.dataset)) epoch_loss=0.0 batch_num=len(dataloader)#有多少个batch net.train() correct = 0 #准确率 #一个batch一个batch的训练网络 for batch_ind, (X,y) in enumerate(dataloader): X,y=X.to(device),y.to(device) #gpu上运行X,y pred = net(X) #衡量y与y_hat之前的loss #y:128 ,pred:128*10 CrossEntropyLoss处理的 loss=loss_fn(pred,y) #基于loss信息利用优化器从后向前更新网络的全部参数 optimizer.zero_grad() loss.backward() optimizer.step() # print(f"batch index: {ind},loss:{loss.item()}")#item()方法将单个tensor转化成一个数字 epoch_loss+=loss.item() #每一个batch产生一个loss correct+=(pred.argmax(1)==y).type(torch.float).sum().item() #f-str if batch_ind % 100==0: print(f'[{batch_ind+1 :>5d} / {batch_num :>5d}], loss:{loss.item()}') #统计一个周期的平均loss avg_loss=epoch_loss/batch_num avg_accurcy = correct / size return avg_accurcy,avg_lossdef test(dataloder,net,loss): size=len(dataloder.dataset) batch_num = len(dataloder) net.eval() losses=0 correct = 0 with torch.no_grad(): for X,y in dataloder: X,y = X.to(device),y.to(device) pred = net(X) loss = loss_fn(pred,y) losses+=loss.item() #一个batch产生一个loss correct+=(pred.argmax(1) ==y).type(torch.int).sum().item() accuracy = correct / size avg_loss = losses /batch_num print(f'accuracy is {accuracy*100}%') return accuracy,avg_loss#数据的获取class getData: def __init__(self): self.train_ds = datasets.MNIST( root='data', download=True, train=True, transform=ToTensor(), # 将原始的数据格式(PIL)转换为Tensor格式 ) # 测试集:评估模型的性能/效果 self.text_ds = datasets.MNIST( root='data', download=True, train=False, transform=ToTensor(), ) # print(train_ds[0]) # print(text_ds[0]) # (3) self.train_loader = DataLoader( dataset=self.train_ds, batch_size=128, # 将60000个数据分成每一段的大小是128 shuffle=True, # 每一次我去拿那个128的数据都是打乱的,不是有序的。1-60000 打乱数据的次序,一般用于训练集,不需要在测试集 ) # (4) # 训练集共有469个batch 469*128 # print("训练集的batch{}".format(len(train_loader))) self.test_loader = DataLoader( dataset=self.text_ds, batch_size=128, )if __name__=='__main__': #(0)测试机器是否支持GPU batch_size=128 device='cuda' if torch.cuda.is_available() else 'cpu' # print(device) train_ds = datasets.MNIST( root='data', download=True, train=True, transform=ToTensor(), # 将原始的数据格式(PIL)转换为Tensor格式 ) # 测试集:评估模型的性能/效果 text_ds = datasets.MNIST( root='data', download=True, train=False, transform=ToTensor(), ) #(1.1)将训练集划分为训练集+验证集 train_ds,val_ds= torch.utils.data.random_split(train_ds,[50000,10000]) # (3) train_loader = DataLoader( dataset=train_ds, batch_size=batch_size, # 将60000个数据分成每一段的大小是128 shuffle=True, # 每一次我去拿那个128的数据都是打乱的,不是有序的。1-60000 打乱数据的次序,一般用于训练集,不需要在测试集 ) val_loder = DataLoader( dataset=val_ds, batch_size=batch_size, ) # (4) # 训练集共有469个batch 469*128 # print("训练集的batch{}".format(len(train_loader))) test_loader = DataLoader( dataset=text_ds, batch_size=batch_size, ) #(6)网络的输入、输出以及测试网络的性能(不经过任何训练的网络) net=MyNet().to(device)#to()GPU上运行该网络 #网络训练模型 #X, 真实的标签y, 网络预测的标签y_hat #目标: y_hat越来越接近y #算法:mini-bacth 梯度下降 #优化器 #具体实现梯度下降算法的传播 #SGD随机梯度下降学习度 #y=ax+b optimizer=torch.optim.SGD(net.parameters(),lr=0.15) #损失函数 #衡量yy与y_hat之前的差异 loss_fn=nn.CrossEntropyLoss() #训练一下 # train(train_loader,net,loss_fn,optimizer) #一个周期表示一个完整的训练集 #训练100个周期epoch train_loss=[] #记录所有周期的平均loss train_acc_list,train_loss_list,val_acc_list,val_loss_list=[],[],[],[] #找出周期内最好的模型 #评价标准:验证集的精度 best_acc=0 for epoch in range(50): print('-'*50) print(f'eopch:{epoch+1}') train_accuracy,train_loss=train(train_loader,net,loss_fn,optimizer) val_accuracy,val_loss =test(train_loader,net,loss_fn) print(f'train acc:{train_accuracy},train_val:{train_loss}') train_acc_list.append(train_accuracy) train_loss_list.append(train_loss) val_acc_list.append(val_accuracy) val_loss_list.append(val_loss) if val_accuracy > best_acc: best_acc = val_accuracy #保存当前模型 torch.save(net.state_dict(),'model_best.pth') #(7)评估模型` #加载最好的模型 net.load_state_dict(torch.load('model_best.pth')) print('the best val_acc is:') test(test_loader,net,loss_fn) plt.figure() ax1=plt.subplot(121) plt.plot([i for i in range(len(train_acc_list))],train_acc_list,ls='-',c='b') plt.title('accuracy') plt.xlabel('epoch') plt.ylabel('number') ax = plt.subplot(122) plt.plot([i for i in range(len(train_loss_list))], train_loss_list, ls='-', c='b') plt.title('loss') plt.xlabel('epoch') plt.ylabel('number') plt.show()

最后无激活函数时结果如图所示:

有激活函数时结果如图所示:

3 结语

通过实验发现,在未使用激活函数时,通过不断地训练模型,模型的准确率和损失率都时比较稳定地上升和下降,但是在上升和下降地过程中会出现抖动地情况,但是使用激活函数之后,模型的准确率和损失率就会上升和下降的非常平滑,更有利于实验的进行,以及对模型行为的预测。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-05-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 算法与编程之美 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云服务器利旧
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档