使用NumPy实现机器学习任务
使用最原始的的NumPy实现一个有关回归的机器学习任务,不使用PyTorch中的包或类。代码可能会多一点,但每一步都是透明的,有利于理解每一步的工作原理。
主要步骤如下:
1)首先,给出一个数组x,然后基于表达式 y = 3x^2 + 2,加上一些噪声数据到达另一组数据。
2)然后,构建一个机器学习模型,学习表达式 y = ax^2 + b 的两个参数a、b。利用数组x、y的数据训练模型。
3)最后,采用梯度下降法,通过多次迭代学习到a、b的值。
import numpy as np
import matplotlib.pyplot as plt
n = 10
# x:生成10个随机数,[0, 1)
x = np.random.rand(n)
print("*"*10 + " x " + "*"*10)
print(x)
# y:生成10个随机数,[0, 1)
y = np.random.rand(n)
print("*"*10 + " y " + "*"*10)
print(y)
# 画散点图
plt.scatter(x, y)
# plt.scatter(x, y, s=100, c='g', marker='*', alpha=0.5)
# x,y:散点的坐标
# s:散点的面积
# c:散点的颜色(默认值为蓝色,'b',其余颜色同plt.plot())
# marker:散点样式(默认值为实心圆,'o',其余样式同plt.plot())
# alpha:散点透明度([0, 1]之间的数,0:完全透明,1:完全不透明)
# linewidths:散点的边缘线宽
# edgecolors:散点的边缘颜色
plt.show()
运行结果:
import numpy as np
# 设置随机数种子
np.random.seed(10)
# 输入数据x:从[-1, 1]均匀切分成10份,形状为10×1
x = np.linspace(-1, 1, 10).reshape(10, 1)
print("*"*10 + " x " + "*"*10)
print(x)
# 输出x中的元素个数
print("*"*10 + " x.size " + "*"*10)
print(x.size)
# 输出x的形状
print("*"*10 + " x.shape " + "*"*10)
print(x.shape)
# 生成值在[0, 1)之间,元素个数为x的元素个数
print("*"*10 + " np.random.rand(x.size) " + "*"*10)
print(np.random.rand(x.size))
# 生成值在[0, 1)之间,元素个数为x的元素个数,形状为10×1
print("*"*10 + " np.random.rand(x.size).reshape(10, 1) " + "*"*10)
print(np.random.rand(x.size).reshape(10, 1))
运行结果:
# 编辑器:PyCharm 解释器:Python=3.9
# 使用NumPy实现机器学习任务
import numpy as np
from matplotlib import pyplot as plt
# 设置随机数种子,生成同一份数据,以便用多种方法比较
np.random.seed(100)
# 输入数据x:从[-1, 1]均匀切分成100份,形状为100×1
x = np.linspace(-1, 1, 100).reshape(100, 1)
print("*"*10 + " x " + "*"*10)
print(x)
# 目标数据y = 3x^2 + 2 + 噪声数据(生成值在[0, 1)之间,元素个数为x的元素个数,形状为100×1)
# y = 3*pow(x, 2) + 2 + 0.2*np.random.rand(x.size).reshape(10, 1)
# y = 3*pow(x, 2) + 2
# print("*"*10 + " y = 3*pow(x, 2) + 2 " + "*"*10)
# print(y)
# 画图:查看x,y的数据分布情况
# plt.scatter(x, y)
# plt.show()
y = 3*np.power(x, 2) + 2 + 0.2*np.random.rand(x.size).reshape(100, 1)
print("*"*10 + " y = 3*pow(x, 2) + 2 + 0.2*np.random.rand(x.size).reshape(10, 1) " + "*"*10)
print(y)
# 画图:查看x,y的数据分布情况
plt.scatter(x, y)
plt.show()
# 随机初始化参数a1
a1 = np.random.rand(1, 1)
print("*"*10 + " a1 " + "*"*10)
print(a1)
# 随机初始化参数b1
b1 = np.random.rand(1, 1)
print("*"*10 + " b1 " + "*"*10)
print(b1)
# 学习率
lr = 0.001
print("*"*10 + " lr " + "*"*10)
print(lr)
for i in range(800):
# 正向传播
y_pred = np.power(x, 2)*a1 + b1
print("*" * 10 + " y_pred = np.power(x, 2)*a1 + b1 " + "*" * 10)
print(y_pred)
# 定义损失函数
loss = 0.5*(y_pred-y) ** 2
print("*" * 10 + " loss " + "*" * 10)
print(loss)
loss = loss.sum()
print("*" * 10 + " loss.sum() " + "*" * 10)
print(loss)
# 计算梯度(求偏导):grad_a
grad_a = np.sum((y_pred - y)*np.power(x, 2))
print("*" * 10 + " grad_a " + "*" * 10)
print(grad_a)
# 计算梯度(求偏导):grad_b
grad_b = np.sum((y_pred-y))
print("*" * 10 + " grad_b " + "*" * 10)
print(grad_b)
# 使用梯度下降法学习参数,损失值最小
a1 -= grad_a*lr
print("*" * 10 + " a1 " + "*" * 10)
print(a1)
b1 -= grad_b*lr
print("*" * 10 + " b1 " + "*" * 10)
print(b1)
# 可视化结果:显示连线图
plt.plot(x, y_pred, 'r-', label='predict', linewidth=4)
# 可视化结果:显示散点图
plt.scatter(x, y, color='blue', marker='o', label='true')
# x的范围
plt.xlim(-1, 1)
# y的范围
plt.ylim(2, 6)
# 图例
plt.legend()
# 显示
plt.show()
# 打印输出预测值 a1,b1
print("*" * 10 + " a1, b1 " + "*" * 10)
print(a1, b1)
运行结果:
NumPy实现的源数据
可视化NumPy的学习结果:
predict:预测数据线(连线图) true:源数据(散点图)
结果部分截图:
使用Tensor及autograd实现机器学习任务
使用PyTorch自动求导的autograd包及对应的Tensor,以利用自动反向传播来求梯度。
# 编辑器:PyCharm 解释器:Python=3.9
# 使用 Tensor 及 autograd 实现机器学习任务
# 1)导入需要的库
import torch
from matplotlib import pyplot as plt
# 2)生成训练数据,并可视化数据分布情况
# 设置随机数种子,生成同一份数据,以便用多种方法进行比较
torch.manual_seed(100)
# 定义数据类型为浮点型
dtype = torch.float
# 生成x坐标数据,x为tensor,形状为100×1,dim=1:最后形成1列(2维),范围[-1, 1],均匀切分成100份。
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)
print("*" * 10 + " x " + "*" * 10)
print(x)
# 生成:y = 3x^2 + 2
# y = 3*x.pow(2) + 2
# print("*" * 10 + " y = 3x^2 + 2 " + "*" * 10)
# print(y)
# 打印输出x的形状
# print("*" * 10 + " x.size() " + "*" * 10)
# print(x.size())
# 打印输出x的形状
# print("*" * 10 + " x.shape " + "*" * 10)
# print(x.shape)
# 噪声:服从均匀分布的随机数,范围再[0,1),形状为x的形状,
# y = 0.2*torch.rand(x.size())
# print("*" * 10 + " y = 0.2*torch.rand(x.size()) " + "*" * 10)
# print(y)
# 生成y坐标数据,y为tensor,形状为100×1,另外加上一些噪声
y = 3*x.pow(2) + 2 + 0.2*torch.rand(x.size())
print("*" * 10 + " y = 3*x.pow(2) + 2 + 0.2*torch.rand(x.size()) " + "*" * 10)
print(y)
# 画图,把tensor数据转换为numpy数据,散点图
plt.scatter(x.numpy(), y.numpy())
plt.xlabel("x")
plt.ylabel("y")
plt.show()
# 3)初始化权重参数
# 随机初始化参数,参数a,b是需要学习的,故需设置为:requires_grad=True,自动求导
# a:服从标准正态分布,形状为1×1(二维),自动求导
a = torch.randn(1, 1, dtype=dtype, requires_grad=True)
print("*" * 10 + " a " + "*" * 10)
print(a)
# b:全0,形状为1×1(二维),自动求导
b = torch.zeros(1, 1, dtype=dtype, requires_grad=True)
print("*" * 10 + " b " + "*" * 10)
print(b)
# 4)训练模型
# 学习率
lr = 0.001
print("*" * 10 + " lr " + "*" * 10)
print(lr)
for i in range(800):
# forward:计算loss
# y_pred = x.pow(2).mm(a)
# print("*" * 10 + " y_pred = ax^2 " + "*" * 10)
# print(y_pred)
# y_pred = ax^2 + b pred:predict,预测
y_pred = x.pow(2).mm(a) + b
print("*" * 10 + " y_pred = x.pow(2).mm(a) + b " + "*" * 10)
print(y_pred)
# 定义损失函数:loss = 0.5*(y_pred-y)^2
loss = 0.5 * (y_pred - y)**2
print("*" * 10 + " loss = 0.5 * (y_pred - y)**2 " + "*" * 10)
print(loss)
loss = loss.sum()
print("*" * 10 + " loss.sum() " + "*" * 10)
print(loss)
# backward:自动计算梯度
loss.backward()
# backward计算loss对a的偏导数
print("*" * 10 + " a.grad " + "*" * 10)
print(a.grad)
# backward计算loss对b的偏导数
print("*" * 10 + " b.grad " + "*" * 10)
print(b.grad)
# 手动更新参数,需要使用torch.no_grad()更新参数
# 阻止 autograd 去跟踪那些标记为 requires_grad = True 的张量的历史记录 以及 不再自动计算张量的梯度值
with torch.no_grad():
# 梯度下降法更新参数 a = a - 学习率*偏导数
a -= lr * a.grad
print("*" * 10 + " a " + "*" * 10)
print(a)
# 梯度下降法更新参数 b = b - 学习率*偏导数
b -= lr * b.grad
print("*" * 10 + " b " + "*" * 10)
print(b)
# 因通过 autograd 计算的梯度会 自动累加 到grad中,故每次循环需要把梯度清零
# a梯度值清零
a.grad.zero_()
print("*" * 10 + " a.grad " + "*" * 10)
print(a.grad)
# b梯度值清零
b.grad.zero_()
print("*" * 10 + " b.grad " + "*" * 10)
print(b.grad)
print("*" * 10 + " x.requires_grad " + "*" * 10)
print(x.requires_grad)
print("*" * 10 + " y_pred.requires_grad " + "*" * 10)
print(y_pred.requires_grad)
# 5)查看可视化训练结果
# 绘制连线图:预测线
plt.plot(x.numpy(), y_pred.detach().numpy(), 'r-', label='predict', linewidth=4)
# plt.plot(x.numpy(), y_pred.numpy(), 'r-', label='predict', linewidth=4)
# 绘制散点图:目标函数
plt.scatter(x.numpy(), y.numpy(), color='blue', marker='o', label='true')
# 规定x的范围
plt.xlim(-1, 1)
plt.xlabel("x")
# 规定y的范围
plt.ylim(2, 6)
plt.ylabel("y")
# 是否显示 图表中的辅助信息(图例)
plt.legend()
# 是否显示图表
plt.show()
# 输出最终的预测值
print("*" * 10 + " a,b " + "*" * 10)
print(a, b)
运行结果:
可视化输入数据:目标函数+噪声数据 的 散点图
使用autograd的结果:
结果部分截图:
使用优化器及自动微分实现机器学习任务
使用PyTorch 内置的损失函数、优化器 和 自动微分机制 等可大大简化整个机器学习的过程。
梯度更新简化为optimizer.step()
梯度清零optimizer.zero_grad()
# 编辑器:PyCharm 解释器:Python=3.9
# 使用 优化器 及 自动微分 实现机器学习任务
# 1)导入需要的库
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
# 2)生成训练数据,并可视化数据分布情况
torch.manual_seed(100)
data_type = torch.float
# 生成x坐标数据,x为tensor,形状为100×1,二维数组,(把[-1, 1]均匀切分成100份,dim=1最后形成1列)
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)
print("*"*10 + " x " + "*"*10)
print(x)
# 生成y坐标数据,y为tensor,形状为100×1,二维数组,y = 3x^2 + 2 + 噪声数据
y = 3*x.pow(2) + 2 + 0.2*torch.rand(x.size())
# 画图,把 tensor 数据转换为 numpy 数据,scatter:散点图
plt.scatter(x.numpy(), y.numpy())
# x轴坐标名称
plt.xlabel("x")
# y轴坐标名称
plt.ylabel("y")
# 是否显示散点图
plt.show()
# 生成形状为1×1(二维矩阵),数据类型为:浮点数,需要自动求导,服从 标准正态分布 的随机数,N~(0, 1)
a = torch.randn(1, 1, dtype=data_type, requires_grad=True)
print("*"*10 + " a " + "*"*10)
print(a)
# 生成形状为1×1(二维矩阵),数据类型为:浮点数,需要自动求导,全0
b = torch.zeros(1, 1, dtype=data_type, requires_grad=True)
print("*"*10 + " b " + "*"*10)
print(b)
# 3) 定义 损失函数 及 优化器
loss_func = nn.MSELoss()
print("*"*10 + " loss_func " + "*"*10)
print(loss_func)
# 定义 优化器
optimizer = torch.optim.SGD([a, b], lr=0.001)
print("*"*10 + " optimizer " + "*"*10)
print(optimizer)
# 4) 训练模型
for i in range(10000):
# forward(正向传播),定义预测函数: y_pred = ax^2 + b
y_pred = x.pow(2).mm(a) + b
print("*" * 10 + " y_pred = x.pow(2).mm(a) + b " + "*" * 10)
print(y_pred)
# 计算损失函数( 相当于 NumPy 中的 定义损失函数 + 损失函数求和 )
loss = loss_func(y_pred, y)
print("*" * 10 + " loss " + "*" * 10)
print(loss)
# 自动计算梯度( 相当于 NumPy 中的 计算梯度,求 偏导值)
loss.backward()
# 输出 a.grad 的值
print("*" * 10 + " a.grad " + "*" * 10)
print(a.grad)
# 输出 b.grad 的值
print("*" * 10 + " b.grad " + "*" * 10)
print(b.grad)
# 更新参数( 相当于 NumPy 中的 使用梯度下降法,手动更新参数 )
optimizer.step()
# a = a - lr*a.grad
# b = b - lr*b.grad
# 输出更新参数a
print("*" * 10 + " a " + "*" * 10)
print(a)
# 输出更新参数b
print("*" * 10 + " b " + "*" * 10)
print(b)
# 通过 autograd 计算的梯度会 累加 到 grad 中, 故每次循环需要把梯度清零
optimizer.zero_grad()
# a.grad 清零: None
print("*" * 10 + " a.grad " + "*" * 10)
print(a.grad)
# b.grad 清零: None
print("*" * 10 + " b.grad " + "*" * 10)
print(b.grad)
# 查看可视化运行结果
# 绘制 预测函数:y_pred 的图像
plt.plot(x.numpy(), y_pred.detach().numpy(), 'r-', label='predict', linewidth=4)
# 绘制 目标函数 的散点图
plt.scatter(x.numpy(), y.numpy(), color='blue', marker='o', label='true')
# 定义x轴的范围,名称
plt.xlim(-1, 1)
plt.xlabel("x")
# 定义y轴的范围,名称
plt.ylim(2, 6)
plt.ylabel("y")
# plt.legend() 需要放到 plt.show() 前面
# 显示图例
plt.legend()
# 显示图表
plt.show()
# 输出最终的预测值
print("*" * 10 + " a, b " + "*" * 10)
print(a, b)
运行结果:
可视化输入数据:目标函数+噪声数据
使用优化器及自动微分(autograd)的结果:
结果部分截图:
把数据集转换为带批量处理功能的迭代器
把数据集转换为带批量处理功能的迭代器,这样训练时就可进行批量处理。如果数据量比较大,采用批量处理可提升训练模型的效率及性能。
# 编辑器:PyCharm 解释器:Python=3.9
# 把 数据集 转换为 带批量处理功能 的 迭代器
# 导入需要的库
import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
# 1)构建数据迭代器
# features:对应自变量x,labels:对应目标函数y,batch_size:对应每批需要处理的数据量
def data_iter(features, labels, batch_size=4):
# 定义自变量的个数
num_examples = len(features)
print("*" * 10 + " num_examples " + "*" * 10)
print(num_examples)
# 定义自变量的下标
indices = list(range(num_examples))
print("*" * 10 + " indices " + "*" * 10)
print(indices)
# 打乱自变量的下标,使样本的读取顺序是随机的
np.random.shuffle(indices)
print("*" * 10 + " shuffle-indices " + "*" * 10)
print(indices)
# 按照 batch_size 批量输出数据
for i in range(0, num_examples, batch_size):
# 定义批量输出数据的下标,min:当未取整时,最后输出的下标为num_examples
indexs = torch.LongTensor(indices[i: min(i + batch_size, num_examples)])
print("*" * 10 + " for-i, i + batch_size, num_examples " + "*" * 10)
print(i, i+batch_size, num_examples)
# 输出打乱顺序后的下标值
print("*" * 10 + " i, min(i + batch_size, num_examples " + "*" * 10)
print(indices[i: min(i + batch_size, num_examples)])
# 输出打乱顺序后的下标值
print("*" * 10 + " for-indexs " + "*" * 10)
print(indexs)
# 输出打乱顺序后的 x 值
print("*" * 10 + " x:features.index_select(0, indexs) " + "*" * 10)
print(features.index_select(0, indexs))
# 输出打乱顺序后的 y 值
print("*" * 10 + " y:labels.index_select(0, indexs) " + "*" * 10)
print(labels.index_select(0, indexs))
# features -> x labels -> y
# yield是一个类似于return的关键字,yield 返回的是一个 生成器。
# 这里 yield 返回的时 打乱下标顺序后的 x的值 和 y的值。
yield features.index_select(0, indexs), labels.index_select(0, indexs)
# 设置随机数种子,生成同一份数据,以便用多种方法进行比较
torch.manual_seed(100)
# 设置数据类型为浮点型
data_type = torch.float
# 生成x坐标数据,x为tensor,形状为100×1,二维数组,(把[-1, 1]均匀切分成100份,dim=1最后形成1列)
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)
print("*"*10 + " x " + "*"*10)
print(x)
# 生成y坐标数据,y为tensor,形状为100×1,二维数组,y = 3x^2 + 2 + 噪声数据
y = 3*x.pow(2) + 2 + 0.2*torch.rand(x.size())
print("*"*10 + " y = 3x^2 + 2 + 0.2*torch.rand(x.size()) " + "*"*10)
print(y)
# 画图,把 tensor 数据转换为 numpy 数据,scatter:散点图
plt.scatter(x.numpy(), y.numpy())
# x轴坐标名称
plt.xlabel("x")
# y轴坐标名称
plt.ylabel("y")
# 是否显示散点图
plt.show()
# 生成形状为1×1(二维矩阵),数据类型为:浮点数,需要自动求导,服从 标准正态分布 的随机数,N~(0, 1)
a = torch.randn(1, 1, dtype=data_type, requires_grad=True)
print("*"*10 + " a " + "*"*10)
print(a)
# 生成形状为1×1(二维矩阵),数据类型为:浮点数,需要自动求导,全0
b = torch.zeros(1, 1, dtype=data_type, requires_grad=True)
print("*"*10 + " b " + "*"*10)
print(b)
# 定义 损失函数 及 优化器
# 定义 损失函数
loss_func = nn.MSELoss()
print("*"*10 + " loss_func " + "*"*10)
print(loss_func)
# 定义 优化器
optimizer = torch.optim.SGD([a, b], lr=0.001)
print("*"*10 + " optimizer " + "*"*10)
print(optimizer)
# 2)训练模型
for i in range(1000):
# features:对应自变量x,labels:对应目标函数y,batch_size:对应每批需要处理的数据量,此处为10
for features, labels in data_iter(x, y, 10):
# forward(正向传播),定义预测函数:y_pred = ax^2 + b
y_pred = features.pow(2).mm(a) + b
print("*" * 10 + " y_pred = features.pow(2).mm(a) + b " + "x" * 10)
print(y_pred)
print("*" * 10 + " y_pred.size() " + "x" * 10)
print(y_pred.size())
print("*" * 10 + " x.size() " + "x" * 10)
print(x.size())
# 计算损失函数( 相当于NumPy中的 定义损失函数 + 损失函数求和 )
loss = loss_func(y_pred, labels)
print("*" * 10 + " loss " + "x" * 10)
print(loss)
# 自动计算梯度( 相当于 NumPy 中的 计算梯度,求 偏导值)
loss.backward()
# 输出 a.grad 的值
print("*" * 10 + " a.grad " + "*" * 10)
print(a.grad)
# 输出 b.grad 的值
print("*" * 10 + " b.grad " + "*" * 10)
print(b.grad)
# 更新参数( 相当于 NumPy 中的 使用梯度下降法,手动更新参数 )
optimizer.step()
# a = a - lr*a.grad
# b = b - lr*b.grad
# 输出更新参数a
print("*" * 10 + " a " + "*" * 10)
print(a)
# 输出更新参数b
print("*" * 10 + " b " + "*" * 10)
print(b)
# 通过 autograd 计算的梯度会 累加 到 grad 中, 故每次循环需要把梯度清零
optimizer.zero_grad()
# a.grad 清零: None
print("*" * 10 + " a.grad " + "*" * 10)
print(a.grad)
# b.grad 清零: None
print("*" * 10 + " b.grad " + "*" * 10)
print(b.grad)
# 3)查看可视化运行结果
# 绘制 预测函数:y_pred 的图像
# plt.plot(x.numpy(), y_pred.detach().numpy(), 'r-', label='predict', linewidth=4)
# 显示 y_predict.size() 形状
y_predict = x.pow(2).mm(a) + b
print("*" * 10 + " y_predict.size() " + "*" * 10)
print(y_predict.size())
# 使 y_p.size() 与 x.size() 的形状相同,以及 自动求导 的 参数分离
y_p = x.pow(2).mm(a).detach().numpy() + b.detach().numpy()
# 绘制 预测函数:y_pred 的图像
plt.plot(x.numpy(), y_p, 'r-', label='predict', linewidth=4)
# 绘制 目标函数 的散点图
plt.scatter(x.numpy(), y.numpy(), color='blue', marker='o', label='true')
# 定义x轴的范围,名称
plt.xlim(-1, 1)
plt.xlabel("x")
# 定义y轴的范围,名称
plt.ylim(2, 6)
plt.ylabel("y")
# plt.legend() 需要放到 plt.show() 前面
# 显示图例
plt.legend()
# 显示图表
plt.show()
# 输出最终的预测值
print("*" * 10 + " a, b " + "*" * 10)
print(a, b)
运行结果:
可视化输入数据:目标函数+噪声数据
使用数据迭代器、优化器和自动微分(autograd)的结果:
结果部分截图:
使用 TensorFlow2 实现机器学习任务
使用TensorFlow2实现这个任务
# 编辑器:PyCharm 解释器:python=3.8 框架:tensorflow2.13
# 1) 导入库
import numpy as np
import tensorflow as tf
from matplotlib import pyplot as plt
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '1'
# 设置log输出信息,程序运行时系统的打印的信息。
# 0:输出 INFO + WARNING + ERROR + FATAL
# 1:输出 WARNING + ERROR + FATAL
# 2:输出 ERROR + FATAL
# 3:输出 FATAL
# https://blog.csdn.net/qq_40549291/article/details/85274581
# 2) 生成 训练数据 并 初始化参数
# 生成训练数据
# 设置随机数种子,生成同一份数据,以便用多种方法进行比较
np.random.seed(100)
# 生成x坐标数据,把[-1, 1]均匀切分成100份,形状为100×1,二维数组
x = np.linspace(-1, 1, 100).reshape(100, 1)
print("*" * 10 + " x " + "*" * 10)
print(x)
# 生成噪声数据
y = 0.2 * np.random.rand(x.size).reshape(100, 1)
print("*" * 10 + " y = np.random.rand(x.size).reshape(10, 1) " + "*" * 10)
print(y)
# 生成y坐标数据,y = 3x^2 + 2 + 噪声数据, 形状为100×1,二维数组,
y = 3*np.power(x, 2) + 2 + 0.2 * np.random.rand(x.size).reshape(100, 1)
print("*" * 10 + " y = 3x^2 + 2 + 0.2 * np.random.rand(x.size).reshape(10, 1) " + "*" * 10)
print(y)
# 画散点图:scatter
plt.scatter(x, y)
# x轴坐标名称
plt.xlabel("x")
# y轴坐标名称
plt.ylabel("y")
# 是否显示散点图
plt.show()
# 创建权重变量a和b,并用随机值初始化
# 形状:[1],服从区间[0, 1.0) 上的均匀分布
a = tf.Variable(tf.random.uniform([1], 0, 1.0))
print("*" * 10 + " a " + "*" * 10)
print(a)
# 形状:[1],全0
b = tf.Variable(tf.zeros([1]))
print("*" * 10 + " b " + "*" * 10)
print(b)
# 3)构建模型
# 定义模型
class CustNet:
def __call__(self, x):
# 定义预测函数
y_pre = np.power(x, 2) * a + b
print("*" * 10 + " y_pre = np.power(x, 2)*a + b " + "*" * 10)
print(y_pre)
# 返回预测函数 y_pre = ax^2 + b
return np.power(x, 2)*a + b
# 定义损失函数:y_true:目标函数 y_pred:预测函数
def loss_func(self, y_true, y_pred):
# 降维 或者 计算平均值
return tf.reduce_mean((y_true - y_pred)**2/2)
# 定义模型变量
model = CustNet()
print("*" * 10 + " model " + "*" * 10)
print(model)
# 4) 训练模型
# 定义最大的训练次数
epochs = 24000
print("*" * 10 + " epochs " + "*" * 10)
print(epochs)
# for循环范围:[1, epochs)
for epoch in tf.range(1, epochs):
# tf.GradientTape():TensorFlow提供的自动微分接口,tape:磁带
with tf.GradientTape() as tape:
# 打印现在处于第几轮模型训练
print("*" * 10 + " epoch " + "*" * 10)
print(epoch)
# 定义 预测函数
predictions = model(x)
print("*" * 10 + " predictions " + "*" * 10)
print(predictions)
# 调用 损失函数,y:目标函数 predictions:预测函数
loss = model.loss_func(y, predictions)
print("*" * 10 + " loss " + "*" * 10)
print(loss)
# 反向传播求梯度,分别对a,b求偏导。
da, db = tape.gradient(loss, [a, b])
print("*" * 10 + " da " + "*" * 10)
print(da)
print("*" * 10 + " db " + "*" * 10)
print(db)
# 梯度下降法更新参数a
a.assign(a - 0.001*da)
print("*" * 10 + " a " + "*" * 10)
print(a)
# 梯度下降法更新参数b
b.assign(b - 0.001*db)
print("*" * 10 + " b " + "*" * 10)
print(b)
# tensorflow:梯度值不需要清零。
# 可视化结果
# 打印多张图片
# plt.figure()
# 画散点图:目标函数
plt.scatter(x, y, color='blue', marker='o', label='ture')
# 画连线图:预测函数
plt.plot(x, b+a*x**2, 'r-', label='predict', linewidth=4)
# 设置x坐标轴的范围
plt.xlim(-1, 1)
# 设置x坐标轴 标签
plt.xlabel("x")
# 设置y坐标轴的范围
plt.ylim(2, 6)
# 设置y坐标轴 标签
plt.ylabel("y")
# 显示图片
plt.show()
# 打印输出a,b的预测值
print("*" * 10 + " a, b " + "*" * 10)
print(a, b)
运行结果:
可视化输入数据:目标函数+噪声数据
使用 TensorFlow 的结果:
结果部分截图:
小结
PyTorch基础知识是后续章节的重要支撑,介绍了PyTorch的安装配置(GPU版),PyTorch的重要数据结构Tensor。Tensor是类似于NumPy的数据结构,但Tensor提供了GPU加速及自动求导等技术。分别用NumPy、Tensor、autograd、优化器和TensorFlow2等技术分别实现了同一个机器学习的任务。