零基础学习人工智能—Python—Pytorch学习(三)
前言
本文主要涉及两个方面的内容。首先是对上一篇关于requires_grad的相关内容进行补充说明,并对其中的一些关键点进行了扩展讨论;其次则是对线性回归的基本概念和应用方法进行简单介绍,并结合实际案例分析其在数据科学中的重要性。
关闭张量计算
关闭张量计算。这个相对简单,阅读下面代码即可。
print("============关闭require_grad==============")
x = torch.randn(3, requires_grad=True)
print(x)
x.requires_grad_(False) # 关闭x的张量计算
print("关闭x的张量计算后的x:", x) # 没有requires_grad属性了
x = torch.randn(3, requires_grad=True)
print("新的带张量计算的x:", x)
y = x.detach() # 去出x的张量附加属性,返回普通张量
print("y没有张量属性:", y)
print("x还有张量属性:", x)
print("============区域内去除x的张量附加属性==============")
with torch.no_grad():
y = x+2
print("y没有张量属性:", y)
print("x还有张量属性:", x)
一个有趣的例子
代码1如下,代码可以正常运行。
x = torch.tensor(1.0)
y = torch.tensor(2.0)
w = torch.tensor(1.0, requires_grad=True)
y_hat = w*x
loss = (y_hat-y)**2
print(loss)
loss.backward()
print(w.grad)
代码2如下,下面代码不能运行。
x = torch.tensor([1.0,2.0])
y = torch.tensor([1.0,2.0])
w = torch.tensor([1.0,2.0],requires_grad=True)
y_hat = w*x
loss =(y_hat-y)**2
print(loss)
loss.backward()
print(w.grad)
由于代码1的loss是一个数值,并且是一个标量变量的形式特征之一而导致其能够进行反向传播;相比之下,代码2的loss是一个向量形式的数据结构特征之一的原因导致其无法进行反向传播。
线性回归 linear regression
一些资料普遍认为:学习深度学习前需掌握线性回归的基础知识。然而事实并非如此:无需投入额外时间去学习这些课程即可快速上手;即便你浪费了这些时间也未必能真正理解其精髓所在。实际上掌握线性回归并不是难事——只需用简明扼要的语言就能解释清楚;这可能是由于教学方法的问题导致的:许多人可能觉得需要自行探索才能掌握这项技能。
线性回归快速理解
为了理解线性是什么的概念,请先静下心来仔细阅读下面内容。
已知A=2,B=4的情况下,通过观察数据可以看出,B确实是A的两倍大小,因此我们可以断定,A与B之间存在某种特定的关系,而这种关系就是我们今天要探讨的核心内容——线性关系。
在线性关系中,两个变量之间的变化具有严格的倍数规律,也就是说,一个变量随着另一个变量的变化而按固定比例改变。
现在我们已经明确了"线性"这一术语的具体含义,接下来我们将深入探讨如何利用这一概念来建立变量之间的数学模型。
在线性的定义中,"相关"意味着两个变量之间存在严格的比例关系,"关联"则强调它们之间的相互依存状态。
在线性模型中,"参数"指的是用来描述变量间相互关系的具体数值参数。
在线性的应用中,"预测"是指根据已知输入值对输出结果进行估算的能力。
在线性的核心思想中,"简单"体现在模型的设计上,即用最少的参数来描述尽可能多的现象特征。
在线性的基本假设中,"确定"意味着在特定条件下变量之间的关系不会发生变化,"稳定"则表明系统状态不会因外界干扰而发生显著变化。
在线性的实际意义中,"高效"体现在模型构建过程中的计算效率,"准确"则是指模型预测结果与真实值的高度吻合度。
在线性的局限性中,"复杂"意味着在面对高度非线性问题时,简单的线性模型可能无法达到预期效果。
综上所述,通过这一系列思考过程,我们可以清晰地认识到:学习并掌握基本统计方法对于数据分析能力提升具有重要意义。
代码
我们直接看代码,x是特征值,y是目标值。
例如我们有一个青蛙A的图片,他的矩阵就是y,然后找一个青蛙B的图片,x就是青蛙B的矩阵。
然后通过线性回归算出,青蛙B与青蛙A的线性关系(w和b)。
这里输入特征x我们写死,不用读取青蛙B的矩阵;y也不用读取青蛙A,也写死。
然后定义w是一个跟x同型矩阵,然后定义b是一个0张量。
然后利用前面的知识使用backward求梯度,然后得到w.grad和b.grad。
w.grad和b.grad和w,b是同型张量,现在我们用w.grad和b.grad去修正w和b,修正时我们使用learning_rate学习率,确保一次只修改一点点。
然后反复迭代多次,就得到了我们的关系(w和b)。
代码如下:
# 输入特征和目标值
x = torch.tensor([1.0, 2.0])
y = torch.tensor([115.0, 21.0])
# 权重初始化(包括偏差项)
w = torch.tensor([1.0, 2.0], requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)
# 学习率
learning_rate = 0.01
# 迭代多次进行优化
for epoch in range(100):
# 预测
y_hat = w * x + b
# 损失函数
loss = (y_hat - y).pow(2).mean()
# 反向传播
loss.backward()
# 更新权重和偏差
with torch.no_grad():
w -= learning_rate * w.grad
b -= learning_rate * b.grad
# 清零梯度
w.grad.zero_()
b.grad.zero_()
print(f'Epoch {epoch + 1}, Loss: {loss.item()}')
# 最终模型参数
print("Final weights:", w)
print("Final bias:", b)
运行如下图:

如图所示,在我的实验中进行了一定次数的迭代运算后发现损失值仍较大。具体而言,在本例中计算所得的损失值仍然偏高,在本例中损失函数越小则说明参数估计越接近真实情况
现在修改运行2000次,运行如下图:

将参数x、w和b代入方程y = wx + b后计算出预测值为62.4444 \times 1 + 52.5554 = 114.9998。观察到我们的目标变量y的第一个数据点为115.0。由此可见,预测结果与实际值之间的差异已经十分微小。
Optimizer
下面是optimizer的使用,具体内容下一篇再讲解。
import torch
import numpy as np
import torch.nn as nn
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)
w2 = torch.tensor(0.0, requires_grad=True)
def forward(_x):
return w2* _x
learning_rate = 0.01
n_iter = 100 # 循环次数
loss =nn.MSELoss()
optimizer =torch.optim.SGD([w2],lr=learning_rate)
for epoch in range(n_iter):
y_pred = forward(X)#
l = loss(Y, y_pred)
l.backward() #执行完反向传播后,w2里就已经有w2.grad了
optimizer.step() #optimizer初始化时就接收了w2,现在w2有了grad,就可以执行step进行优化了,优化时会使用w2的梯度grad属性和学习率learning_rate
optimizer.zero_grad() #梯度清零
if epoch % 1 == 0:
print(f'epoch {epoch+1}:w2= {w2:.3f} ,loss = {l:.8f}')
print(f'f(5)={forward(5):.3f}')
访问入口:零基础入门级Python Pytorch 学习(一)零基础入门级Python Pytorch 学习(二)零基础入门级Python Pytorch 学习(三) 这里就是开始的学习之旅
注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!

若您觉得这篇文章还不错,请点击下方的【推荐】,非常感谢!
