Pytorch深度学习实践笔记7(b站刘二大人)

🎬个人简介:一个全栈工程师的升级之路!
📋个人专栏:pytorch深度学习
🎀CSDN主页 发狂的小花
🌄人生秘诀:学习的本质就是极致重复!

《PyTorch深度学习实践》完结合集_哔哩哔哩_bilibili​

目录

1 多维数据的输入

2 激活函数

3 问题解决

4 SGD 和Adam优化器的比较



1 多维数据的输入


注意bias使用矩阵的广播机制会复制多份,与输入维度相同

  • 问题引入:

一个人是否患有糖尿病有多个指标x1,x2,x3,x4,x5...,患有糖尿病的结果有患和不患(1 和0)两种,因此这是一个有着多维输入的二分类问题。
下图横轴一维代表一个样本sample,纵轴[X]一维代表一个指标,深度学习中可以叫一个特征feature,[Y]是二分类的结果。

 

  • 多维数据的引入说明:



 

  • 构造计算图:8维到1维,矩阵乘加实现


 



 

  • 激活层:

对于二分类问题,这里使用sigmod激活函数,一个sigmod本身是一个算子,对于sigmod等非线性算子优化的手段一般是线性拟合和查表,查表比较好。





 

  • nn.Linear 原码理解

pytorch系列 ----暂时就叫5的番外吧: nn.Modlue及nn.Linear 源码理解​

2 激活函数

 

机器学习中常用的几种函数--激活函数、损失函数_激活函数和损失函数的区别-CSDN博客​

  • 理解激活函数和损失函数:

        Relu等激活函数是为了解决在反向传播中梯度消失问题,而cross-entropy loss是为训练网络进行分类的,这两者之间并没有直接的关联!
        这里结合softmax可以很好的理解激活函数和损失函数,softmax一般在神经网络的最后一层,用于分类问题,虽然它可以作为激活函数,但是其不是为了改变输入值,因此一般不认为是激活函数。也就是说,损失函数的选择由它任务有关,即最后一层处理有关,与其整个网络中的激活函数无关,各自针对的问题不同,不可以混为一谈。

  • 输出层的激活函数损失函数由任务类型决定,见下表。它们与隐藏层的激活函数的选择是独立的。


 


3 问题解决

  • 数据集建立:

(1)训练集,去掉压缩包内最后10组数据
(2)测试集,将最后10组数据作为测试集

  • 建立Model和激活函数:

几个 Linera+sigmoid

  • 损失函数和优化器

BCELoss+SGD 或者 BCELoss+Adam

  • 训练:

主要是学习率的设置,SGD的训练速度和收敛与学习率有很大的关系;Adam需要设置初始的学习率,中间会自动调整学习率。

 

  • SGD 训练100万epoch,学习率设置0.1 结果如下:
import numpy as np
import torch
import matplotlib.pyplot as plt
 
# prepare dataset
xy = np.loadtxt('./dataset/diabetes_train.csv.gz', delimiter=',', dtype=np.float32)
x_data = torch.from_numpy(xy[:, :-1]) # 第一个‘:’是指读取所有行,第二个‘:’是指从第一列开始,最后一列不要
print("input data.shape", x_data.shape)
y_data = torch.from_numpy(xy[:, [-1]]) # [-1] 最后得到的是个矩阵
 

xy_test = np.loadtxt('./dataset/diabetes_test.csv.gz', delimiter=',', dtype=np.float32)
x_data_test = torch.from_numpy(xy_test[:, :-1]) # 第一个‘:’是指读取所有行,第二个‘:’是指从第一列开始,最后一列不要
print("input data.shape", x_data_test.shape)
y_data_test = torch.from_numpy(xy_test[:, [-1]]) # [-1] 最后得到的是个矩阵

# print(x_data.shape)
# design model using class
 
 
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = torch.nn.Linear(8, 6)
        self.linear2 = torch.nn.Linear(6, 4)
        self.linear3 = torch.nn.Linear(4, 2)
        self.linear4 = torch.nn.Linear(2, 1)
        self.active = torch.nn.Sigmoid()
 
    def forward(self, x):
        x = self.active(self.linear1(x))
        x = self.active(self.linear2(x))
        x = self.active(self.linear3(x)) # y hat
        x = self.active(self.linear4(x))  # y hat
        return x
 
 
model = Model()
 
epoch_list = []
loss_list = []
# construct loss and optimizer
# criterion = torch.nn.BCELoss(size_average = True)
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
 
 
# training cycle forward, backward, update
for epoch in range(1000000):
    y_pred = model(x_data)
    loss = criterion(y_pred, y_data)
    # print(epoch, loss.item())
    epoch_list.append(epoch)
    loss_list.append(loss.data.item())
 
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    y_pred_label = torch.where(y_pred>=0.5,torch.tensor([1.0]),torch.tensor([0.0]))
    acc = torch.eq(y_pred_label, y_data).sum().item()/y_data.size(0)

    print("epoch: ",epoch,"loss = ",loss.item(), "acc = ",acc)
    if (loss.item() < 1e-7):
        break
 

pred_test_y = model(x_data_test)
test_pred_label = torch.where(pred_test_y>=0.9,torch.tensor([1.0]),torch.tensor([0.0]))
acc1 = torch.eq(test_pred_label, y_data_test).sum().item()/y_data_test.size(0)

print("acc test= ",acc)
 
plt.plot(epoch_list, loss_list)
plt.ylabel('loss')
plt.xlabel('epoch')
# plt.show()
plt.savefig('./data/pytorch6.png')



 



 

  • Adam 训练1万epoch,初始学习率设置为0.01结果如下:
  • 代码
import numpy as np
import torch
import matplotlib.pyplot as plt
 
# prepare dataset
xy = np.loadtxt('./dataset/diabetes_train.csv.gz', delimiter=',', dtype=np.float32)
x_data = torch.from_numpy(xy[:, :-1]) # 第一个‘:’是指读取所有行,第二个‘:’是指从第一列开始,最后一列不要
print("input data.shape", x_data.shape)
y_data = torch.from_numpy(xy[:, [-1]]) # [-1] 最后得到的是个矩阵
 

xy_test = np.loadtxt('./dataset/diabetes_test.csv.gz', delimiter=',', dtype=np.float32)
x_data_test = torch.from_numpy(xy_test[:, :-1]) # 第一个‘:’是指读取所有行,第二个‘:’是指从第一列开始,最后一列不要
print("input data.shape", x_data_test.shape)
y_data_test = torch.from_numpy(xy_test[:, [-1]]) # [-1] 最后得到的是个矩阵

# print(x_data.shape)
# design model using class
 
 
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = torch.nn.Linear(8, 6)
        self.linear2 = torch.nn.Linear(6, 4)
        self.linear3 = torch.nn.Linear(4, 2)
        self.linear4 = torch.nn.Linear(2, 1)
        self.active = torch.nn.Sigmoid()
 
    def forward(self, x):
        x = self.active(self.linear1(x))
        x = self.active(self.linear2(x))
        x = self.active(self.linear3(x)) # y hat
        x = self.active(self.linear4(x))  # y hat
        return x
 
 
model = Model()
 
epoch_list = []
loss_list = []
# construct loss and optimizer
# criterion = torch.nn.BCELoss(size_average = True)
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
 
 
# training cycle forward, backward, update
for epoch in range(10000):
    y_pred = model(x_data)
    loss = criterion(y_pred, y_data)
    # print(epoch, loss.item())
    epoch_list.append(epoch)
    loss_list.append(loss.data.item())
 
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    y_pred_label = torch.where(y_pred>=0.5,torch.tensor([1.0]),torch.tensor([0.0]))
    acc = torch.eq(y_pred_label, y_data).sum().item()/y_data.size(0)

    print("epoch: ",epoch,"loss = ",loss.item(), "acc = ",acc)
    if (loss.item() < 1e-7):
        break
 

pred_test_y = model(x_data_test)
test_pred_label = torch.where(pred_test_y>=0.9,torch.tensor([1.0]),torch.tensor([0.0]))
acc1 = torch.eq(test_pred_label, y_data_test).sum().item()/y_data_test.size(0)

print("acc test= ",acc)
 
plt.plot(epoch_list, loss_list)
plt.ylabel('loss')
plt.xlabel('epoch')
# plt.show()
plt.savefig('./data/pytorch6.png')



 






4 SGD 和Adam优化器的比较

  • 前言:

上述实验,我使用Adam前期可以比较迅速的收敛,使得loss收敛迅速,并且没有过拟合,一般Adam由于其特性出现过拟合的概率比SGD高。我用SGD优化器训练,训练了100万次才勉强达到Adam的1万次结果,由此可以看出Adam的收敛速度比SGD快很多,但是由于SGD的噪声比较大,而且其每次计算一个梯度或者一小批量的梯度,使得泛化能力强,适应于大型数据的训练中。

  • 区别:
  • SGD(随机梯度下降)

基本思想: SGD在每一步更新中仅使用一个(或一小批)样本来计算梯度,而不是使用整个数据集。这种方法可以显著减少计算量,使得训练大规模数据集变得可行。
学习率: SGD通常需要手动调整学习率,并且可能会使用如学习率衰减这样的技巧来帮助模型收敛。学习率的选择对SGD的性能影响很大。
收敛速度: SGD的收敛速度通常比较慢,尤其是在接近最小值的平坦区域。
泛化能力: 研究表明,由于SGD的噪声更大,它可能有助于模型找到泛化性能更好的解。

  • Adam(自适应矩估计)

基本思想: Adam是一种自适应学习率的优化算法,它结合了动量(Momentum)和RMSprop的优点。Adam会为不同的参数计算不同的自适应学习率。
学习率: Adam自动调整学习率,通常不需要像SGD那样手动微调学习率,这使得Adam在很多情况下都能较快地收敛。
收敛速度: 由于自适应学习率的特性,Adam在初期训练阶段通常比SGD收敛得更快。
泛化能力: 尽管Adam在许多任务中都显示出了较快的收敛速度,但一些研究表明,对于某些问题,Adam可能导致过拟合,泛化能力不如SGD。
应用场景
Adam: 由于其易用性和快速收敛的特点,Adam非常适合在需要快速得到结果的场景中使用,特别是在计算资源有限或模型较复杂时。
SGD: 如果模型训练时出现过拟合,或者当你有足够的时间和资源来精细调整学习率时,SGD可能是更好的选择。对于大规模分布式训练,SGD的泛化能力可能更优。
总之,选择哪种优化算法取决于具体任务、模型的复杂性、可用的计算资源以及是否需要模型有更好的泛化能力。在实践中,可能需要尝试不同的优化算法,以找到最适合当前任务的选项。

🌈我的分享也就到此结束啦🌈
如果我的分享也能对你有帮助,那就太好了!
若有不足,还请大家多多指正,我们一起学习交流!
📢未来的富豪们:点赞👍→收藏⭐→关注🔍,如果能评论下就太惊喜了!
感谢大家的观看和支持!最后,☺祝愿大家每天有钱赚!!!欢迎关注、关注!

  • 36
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发狂的小花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值