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

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

1 问题

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


2 方法

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

控制其余变量:

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

测试代码如下

from torchvision import datasets
from torchvision.transforms import ToTensor
from torch import nn
import torch
from torch.utils.data import DataLoader
import torch.nn.functional as F
import matplotlib.pyplot as plt
from collections import defaultdict
# (5)定义三层全连接网络
# (5.1)创建一个新的类继承nn.Module
class 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_loss
def 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 结语

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

目录
相关文章
|
并行计算 Ubuntu Linux
Ubuntu学习笔记(五):18.04安装多版本CUDA
这篇博客文章介绍了在Ubuntu 18.04系统上如何安装和切换不同版本的CUDA,以及如何安装不同版本的cuDNN。
699 2
|
开发工具 git Windows
VSCode下载与安装使用教程【超详细讲解】
VSCode下载与安装使用教程【超详细讲解】
4882 0
VSCode下载与安装使用教程【超详细讲解】
|
4月前
|
数据库 Windows
D盘被删除了咋恢复丢失的文件?手把手教你找回宝贵资料
本文详解D盘误删后的文件恢复方法,涵盖三种实用方案:备份还原、专业工具扫描及联系数据恢复服务。强调操作前的关键注意事项,助你高效找回重要资料。
|
4月前
|
监控 安全 图形学
百度网盘下载速度很慢?电脑下载速度好快?玩游戏很慢?
OpenSpeedy是一款免费开源的Windows工具,可对百度网盘、游戏等软件进行加速,无需会员也能实现高速下载。
1417 0
|
数据可视化
Signac R|如何合并多个 Seurat 对象 (2)
Signac R|如何合并多个 Seurat 对象 (2)
482 11
Signac R|如何合并多个 Seurat 对象 (2)
|
计算机视觉 Python
Opencv学习笔记(七):如何根据opencv将BGR转换为HSV
使用OpenCV库在Python中将BGR图像转换为HSV颜色空间的两种方法:一种是直接使用cv2.cvtColor函数,另一种是手动实现RGB到HSV的转换。
514 0
Opencv学习笔记(七):如何根据opencv将BGR转换为HSV
|
Java 应用服务中间件 Maven
Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerExcepti
Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerExcepti
861 0
|
存储 安全 算法
Python如何在打印日志时隐藏明文密码?
Python如何在打印日志时隐藏明文密码?
397 0
|
安全 Unix Linux
Linux Clone函数
Linux Clone函数
286 3
|
机器学习/深度学习 人工智能 安全
未来智能手机操作系统的趋势与展望
随着智能手机技术的不断进步,操作系统作为其核心组成部分也在快速演变。本文探讨了未来智能手机操作系统的发展趋势,包括人工智能集成、安全性提升以及生态系统的开放性,以及这些趋势对用户体验和行业未来的影响。

热门文章

最新文章