先掌握pytorch,学好pytorch, 才能学好人工智能
Linear regression
线性回归是一种用于建模两个或多个变量之间关系的统计方法。在这种模型中,一个或多个自变量(也称为预测变量或特征)与一个因变量(也称为响应变量或目标)之间的关系被假定为线性的,即这些变量的关系可以用一条直线(在二维空间中)或一个超平面(在多维空间中)来近似表示。
基本概念
- 自变量(X):用于预测因变量的变量。
- 因变量(Y):需要被预测的变量。
- 线性关系:自变量和因变量之间的关系可以表示为一条直线(Y = aX + b),其中a是斜率,b是截距。
- 回归系数(或权重):在线性方程中,每个自变量前的系数,表示该自变量对因变量的影响程度。
- 截距:线性方程中当所有自变量都为0时的因变量值。
线性回归的步骤
- 数据收集:收集包含自变量和因变量的数据集。
- 数据预处理:处理缺失值、异常值,进行特征缩放等。
- 模型构建:建立线性回归模型,即确定线性方程的形式。
- 参数估计:使用最小二乘法或其他优化方法估计回归系数和截距。
- 模型评估:通过计算残差、决定系数(R²)、均方误差(MSE)等指标评估模型的拟合效果。
- 预测:使用训练好的模型对新的数据进行预测。
原始模型
import torch
import matplotlib.pyplot as plt
# 设置CPU生成随机数的种子,方便下次复现实验结果。
torch.manual_seed(9)
# 准备训练数据
x = torch.rand(30,1)*10
y = 3*x + 2 + torch.rand(30,1)
# print('output','\n', 'x :', x,x.shape)
# print('\n', 'y :', y,y.shape)
# 初始参数
# w = torch.rand(size=(30,1),requires_grad=True)
# b = torch.zeros(size=(30,1),requires_grad=True)
w = torch.randn(1,requires_grad=True)
#.grad属性:在PyTorch中,每个tensor都有一个.grad属性,用于存储该tensor的梯度。对于leaf tensor,如果在计算图中它们参与了梯度计算,那么.grad属性会在反向传播后被填充。
b = torch.ones(1,requires_grad=True)
print('\n', 'w :', w,w.shape)
print('\n', 'b :', b,b.shape)
# 设置学习率为0.1
lr = 0.1
#
for i in range(1000):
# 前向传播
# torch.mul作element-wise的矩阵点乘,维数不限,可以矩阵乘标量
# 当a, b维度不一致时,会自动填充到相同维度相点乘。
wx = torch.mul(w, x)
# 支持广播相加
y_pred = torch.add(wx, b)
# 计算MSE Loss
# 反向传播, ✖2分之一是为了方便求导
loss = (torch.sqrt(y - y_pred)*0.5).mean()
print('loss:',loss)
# 反向传播, 计算当前梯度
loss.backward()
# print('w.grad',w.grad)
# print('b.grad',b.grad)
# 更新参数
# w = w- LR*w.grad
# b = b- LR*w.grad
# w = torch.sub(w,lr*w.grad)
# b = torch.sub(b,lr*b.grad)
# 函数形式:torch.sub(input, other, *, alpha=1, out=None)
# 参数解读:
# input: 输入的被减数,格式为tensor格式
# other:输入的减数
# alpha:与上面other参数搭配使用,用来与other相乘,当使用torch.sub()函数时不指定alpha的值时,alpha默认为1
# out: 指定torch.sub()输出值被赋给的变量,可不指定。
# 然而
# torch.sub_()功能与torch.sub()相同,区别在与torch.sub_()是torch.sub()的in-place操作版本。
b.data.sub_(lr * b.grad)
w.data.sub_(lr * w.grad)
# 绘图
if i % 20 == 0 or loss.data.numpy() < 1:
plt.cla() # 防止社区版可视化时模型重叠2020-12-15
plt.scatter(x.data.numpy(), y.data.numpy())
plt.plot(x.data.numpy(), y_pred.data.numpy(), 'r-', lw=5)
plt.text(2, 20, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': 'red'})
plt.xlim(1.5, 10)
plt.ylim(8, 28)
plt.title("Iteration: {}\nw: {} b: {}".format(i, w.data.numpy(), b.data.numpy()))
plt.pause(0.5)
if loss.data.numpy() < 1:
break
plt.show()
这段代码是在一个训练循环中使用的,通常用于机器学习或深度学习中,特别是在训练一个模型时可视化损失函数和模型的预测情况。下面是对这段代码的逐行解释:
-
if i % 20 == 0 or loss.data.numpy() < 1:
:这行代码检查两个条件是否满足其中之一。第一个条件是当前的迭代次数i
是否是20的倍数(i % 20 == 0
),这通常用于每隔一定数量的迭代更新一次可视化,以避免可视化过于频繁。第二个条件是当前的损失值loss
是否小于1,这通常表示模型已经达到了一个较好的性能水平,可以提前结束训练。 -
plt.cla()
:这行代码清除当前的轴内容,确保在每次更新可视化时不会重叠。 -
plt.scatter(x.data.numpy(), y.data.numpy())
:使用散点图绘制真实的数据点,其中x
和y
分别是输入特征和目标输出的真实值。 -
plt.plot(x.data.numpy(), y_pred.data.numpy(), 'r-', lw=5)
:绘制模型的预测线,其中y_pred
是模型对x
的预测输出。这里使用红色('r-'
)和线宽(lw=5
)来突出显示预测线。 -
plt.text(2, 20, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': 'red'})
:在图上添加文本,显示当前的损失值。文本的位置是(2, 20),字体大小为20,颜色为红色。 -
plt.xlim(1.5, 10)
和plt.ylim(8, 28)
:分别设置x轴和y轴的显示范围。 -
plt.title("Iteration: {}\nw: {} b: {}".format(i, w.data.numpy(), b.data.numpy()))
:设置图表的标题,显示当前的迭代次数i
,以及模型的参数(假设模型是一个简单的线性模型,参数为权重w
和偏置b
)。 -
plt.pause(0.5)
:暂停0.5秒,以便用户可以看到更新的图表。这在实时可视化时非常有用。 -
if loss.data.numpy() < 1:
:再次检查损失值是否小于1,如果是,则跳出循环。 -
plt.show()
:在所有迭代完成后,显示最终的图表。
总的来说,这段代码的目的是在训练过程中实时可视化模型的性能和预测结果,特别是当模型性能达到一定标准(损失值小于1)或每隔一定数量的迭代时。
-
x
和y
是输入特征和目标输出,它们也应该是torch.Tensor
类型。
- 参数更新:
- 您正在使用
.data.sub_()
进行in-place更新,这是不推荐的做法,因为它绕过了PyTorch的梯度计算图。更好的做法是使用优化器(如torch.optim.SGD
)来更新参数。
- 您正在使用
- 梯度清零:
- 在每次迭代开始时,您需要清零梯度,否则梯度会累积。
- 学习率(
lr
):- 学习率需要事先定义。
- 可视化:
- 可视化代码看起来是正确的,但请确保
plt
(matplotlib.pyplot)已经导入。
- 可视化代码看起来是正确的,但请确保
- 代码结构:
- 代码应该放在一个函数或类中,以便更好地组织和管理。
下面是一个改进后的代码示例:
import torch
import matplotlib.pyplot as plt
# 假设x和y是已经准备好的数据
x = torch.rand(size=(50,1),requires_grad=False)*10
y = 2*x + torch.rand(size=(50,1),requires_grad=False)
# 这里需要您自己定义x和y
# 定义模型参数
w = torch.tensor(10., requires_grad=True) # 假设只有一个特征,因此w是一个标量
b = torch.tensor(0., requires_grad=True)
print('w',w)
print('b',b)
# 学习率
lr = 0.05
# 训练循环
for i in range(1000):
# 前向传播
wx = torch.mul(w, x) # 这里假设x是一个标量或一维张量,与w兼容
y_pred = torch.add(wx, b)
# print('ypred',y_pred)
# print('A',torch.sqrt (y - y_pred) )
# print('B',(y - y_pred)**2)
# 计算MSE Loss
loss = (0.5 * (y - y_pred)**2 ).mean()
print('loss',loss)
# 反向传播
loss.backward()
# 更新参数
with torch.no_grad(): # 在更新参数时不需要计算梯度
w -= lr * w.grad
b -= lr * b.grad
# 梯度清零
w.grad.zero_()
b.grad.zero_()
# 绘图
if i % 20 == 0 or loss.item() < 1:
plt.cla()
plt.scatter(x.numpy(), y.numpy())
plt.plot(x.numpy(), y_pred.detach().numpy(), 'r-', lw=5) # 使用detach()避免在绘图时计算梯度
plt.text(2, 20, 'Loss=%.4f' % loss.item(), fontdict={'size': 20, 'color': 'red'})
plt.xlim(0, 10)
plt.ylim(-5, 30)
plt.title(f"Iteration: {i}\nw: {w.item()} b: {b.item()}")
plt.pause(0.5)
if loss.item() < 1:
break
plt.show()
tensor中
.grad属性:在PyTorch中,每个tensor都有一个.grad
属性,用于存储该tensor的梯度。对于leaf tensor,如果在计算图中它们参与了梯度计算,那么.grad
属性会在反向传播后被填充。