网站建设小程序定制开发,唐山网站制作软件,网页版梦幻西游五行斗法,网站怎么做图片动态图片大全一、前言 本章会需要 微分、线性回归与矩阵的基本观念 这次我们要来做 PyTorch 的简单教学#xff0c;我们先从简单的计算与自动导数#xff08; auto grad / 微分 #xff09;开始#xff0c;使用优化器与误差计算#xff0c;然后使用 PyTorch 做线性回归#xff0c;还有… 一、前言 本章会需要 微分、线性回归与矩阵的基本观念 这次我们要来做 PyTorch 的简单教学我们先从简单的计算与自动导数 auto grad / 微分 开始使用优化器与误差计算然后使用 PyTorch 做线性回归还有 PyTorch 于 GPU 显示卡 CUDA 的使用范例。 本文的重点是学会 loss function 与 optimizer 使用 文本目录
为什么选择 PyTorch名词与概念介绍 导数partial derivative 优化器optimizer 损失函数 loss function 自动导数 /Auto grad 手工优化与损失函数的实作- 此节很无聊优化器 损失函数 矩阵与 partial derivative 示例线性回归与矩阵范例 —Model 概念GPU 显卡 CUDA 运算范例
本文不讲解如何安装 PyTorch 且假设读者已经拥有 Numpy 使用经验 如果手边没有环境可以使用 Google Colab Google 已经帮各位安装好许多常用的套件
二、选择 PyTorch的理由 Machine Learning / Deep Learning 有许多 Framework 可以使用其中 Keras Tensorflow 与 PyTorch 本人都有使用经验但如果想要研究与了解 Deep Learning 如何运作本人认为最好的方式是使用 PyTorch 一般使用 Keras Tensorflow 虽然可以快速的建立模型但是底层原理没有打好基础的人一定会是雾里看花 知其然知其所以然 PyTorch 使用上很接近 Numpy另外有强大的数学计算功能例如自动微分自动优化方便配置到显卡上运算 Nvidia CUDA而且就本人使用经验来说安装比 TensorFlow 容易 ... 如果知道 PyTorch 这些功能可以使用在各种数学应用而且对于 Machine Learning / Deep Learning 底层运作也会更加了如指掌
三、名词与概念介绍 导数partial derivative 优化器optimizer 损失函数 loss function
其实我们之前的章节就是在为这些铺路
3.1 损失函数 loss function 这个名词中文看来奇怪其实他是计算数值差距用的计算与答案的误差帮助我们找目标的公式例如我们有 18 元去买 3块钱的苹果我们只买了 5颗我们是不是还可以买更多 18–3*53我们剩下 3元 误差就是 3 在线性回归 中就是计算和答案的差距主要用来取得导数
3.2 导数 partial derivative
就是微分概念透过损失函数还可以找出我们要移动的方向和距离
3.3 优化器 optimizer 开始修正我们的数值使用也有人称优化器就是依靠导数去调整数值 导数部分其实不用特别关心他实务上隐藏在 loss function 与 optimizer 之间但是这三者的组合就是 Machine Learning 中常用的概念 流程就是
误差计算 - 寻找导数 - 优化 -误差计算 - 寻找导数 - 优化 -误差计算 - 寻找导数 - 优化 -误差计算 - 寻找导数 - 优化 -...
四、自动导数 / Auto grad 手工优化与损失函数的实现
先说此节很无聊 是介绍损失函数与优化器如何运作但是可以跳到下节没关系
本节承接 线性回归 概念一样依照 loss function 与 optimizer 架构
微分在 Machine Learning 中是非常重要的计算而这种计算已经有公式可循所以 PyTorch 会自动的帮我们计算也就是我们之前章节说过不会算没关系电脑可以帮我们算但是概念与原理要懂
这边的 grad 其实就是微积分中的 partial derivative 导数 / 斜率PyTorch 会帮我们追踪每个变量的 导数/斜率 即自动追踪变量的任何变化
现在我们来看最基础的 PyTorch 与 Auto grad 范例 假设今天在商场买苹果结账假设苹果 3 元我们手上有 18 元纸袋 不用钱这边为了方便范例先忽略 我们要去尽可能的买越多苹果越好 公式如下
结账总额Y 苹果数量a * 苹果单价X 纸袋单价b 换成数学公式是 Y aX b
Y 是我们手上有的钱这个我们不能改变X 是苹果单价这个我们不能改变a 是苹果数量这是我们要找出来的b 这边因为纸袋0元所以我们直接省略不看
x torch.tensor([3.0]) # 蘋果單價
y torch.tensor([18.0]) # 我們的預算
a torch.tensor([1.0], requires_gradTrue) # 追蹤導數
print(grad:, a.grad)
loss y - (a * x) # loss function ( 中文稱 損失函數 )
loss.backward()
print(grad:, a.grad)
解说
torch.tensor 就是建立一个 Tensor 类似于 np.array requires_gradTrue 我们有需要追踪的变量才要加上这个参数不用追踪的不用例如这个范例中我们只希望 a 改变不要去动其他数值所以只有 a 有 requires_gradTrue
4.1 损失函数 loss function
实务上是让他越接近 0 越好我们后面会套用 PyTorch 内建的 function 就不用每次的手工打造
上面代码中loss就是差价公式概念就是Y ax b但是我们的目标是要把钱花光光所以loss要越趋近于0越好 所以数学上就成了Y-ax b 0是我们的目标loss.backward 就是和 PyTorch 说开始反向追踪
这是 print 出来的结果
# grad: None
# grad: tensor([-3.])
可以看到我们 printgrad a.grad 在 loss.backward 之前是没有数值的 但是之后冒出一个 -3这个 -3 就是 partial derivative 会微积分的人可以算看看 然后我们可以靠这个数值去调整 a 的值如下
4.2 优化器
PyTorch 有内建好的优化器但是我们这边为了演示原理一样手工计算 下节我们会使用内建的 下面代码是我们开始进行线性回归优化 计算 100 次
for _ in range(100):a.grad.zero_()loss y - (a * x)loss.backward()with torch.no_grad():a - a.grad * 0.01 * loss
解说
每一次的 backward a 的 grad 都会相加所以我们要先做归零 就像是实验室仪器每次都要先归零校正 loss 与 loss.backward 上面已经解说过用来反向追踪导数with torch.no_grad 这部分概念很重要前面提过 PyTorch 会自动追踪 a 的任何计算所以我们手动调整 a 一定要和 PyTorch 说不要追踪我们的手动调整
我們看看跑 100 次迴歸的結果 損失函跑 100 次的變化
print(a:, a)
print(loss:, (y - (a * x)))
print(result:, (a * x))
# a: 5.999598503112793
# loss: 0.0012054443359375
# result: 17.998794555664062
可以看到 a 趋近于 6 误差 loss 趋近于 0 表示我们真的可以用 18 块钱去买 6 颗苹果 3元的苹果
五、优化器 损失函数 矩阵与 partial derivative 示例 这边我们要用 PyTorch 内建的 loss function 与 optimizer 来做计算会方便很多而且可以做更多复杂的问题 本文的重点是学会 loss function 与 optimizer 使用 直接看代码一样是苹果 3元范例
x torch.tensor([3.0])
y torch.tensor([18.0])
a torch.tensor([1.0], requires_gradTrue)
loss_func torch.nn.MSELoss()
optimizer torch.optim.SGD([a], lr0.01)
for _ in range(100):optimizer.zero_grad()loss loss_func(y, a * x)loss.backward()optimizer.step()
解说
loss_func 就是损失函数我们这边使用 torch.nn.MSELoss 他其实是计算 均方误差loss function 有很多种我们日后有机会再介绍但是这边要知道很多情况下的数值比较其实用 MSELoss 就很好用了细节https://pytorch.org/docs/stable/nn.html#loss-functionsoptimizer 就是优化器 torch.optim.SGD[a] lr0.01 这边是我们使用 SGD 一样优化器有很多种我们这边为了简单示范先用 SGD - [a] 是我们和优化器说照顾好我们的 a 变量 - lr 是学习率 数值都是小于 1实际看场合调整 我们这边 0.01 是为了快速示范 细节 torch.optim — PyTorch 2.0 documentationoptimizer.zero_grad 是为了归零调整因为每次 backward 都会增加 grad 的数值就像是实验室每次做实验都要归零调整不然上个用户的操作会干扰实验结果 loss.backward 做反向传导就是找出导数optimizer.step 告诉优化器做优化他会自动帮我们调整 a 的数值 我们测试一下矩阵概念的计算 假设一样是 18 元的预算三个种不同的苹果 售价分别是 3 元 5 元 6 元这样可以买几颗 我们只要修改一下数值
x torch.tensor([3.0, 5.0, 6.0,]) # 不同種蘋果售價
y torch.tensor([18.0, 18.0, 18.0]) # 我們的預算
a torch.tensor([1.0, 1.0, 1.0], requires_gradTrue) # 先假設都只能買一顆 然后我们跑计算 这里跑 1000 次让数值精准些
loss_func torch.nn.MSELoss()
optimizer torch.optim.SGD([a], lr0.01)
for _ in range(1000):optimizer.zero_grad()loss loss_func(y, a * x)loss.backward()optimizer.step()
print(a:, a)
# a: tensor([6.0000, 3.6000, 3.0000], requires_gradTrue) 看起来没错如果只有 18 元分别去买不同的苹果我们只能买 6 颗 3元 3 颗5元 3 颗6元
六、线性回归与矩阵范例 —Model 概念
有了上面的概念现在我们来做更进阶的范例 data - model - output
我们将输入数据到输出数据这个过程称为 “Model” 概念上就是可以当作是一个黑箱我们把数据丢进去 一般称为 X 就会产生出预测数据 称为 Y 例如
影像分类照片丢入 model 然后 model 告诉我们影像的类别资料预测过去几天的气象资料温度、湿度、气压.. . 丢入 model 然后得到几天后的预测语音识别用户说话的音频丢入 model 得到文字输出
6.1 准备资料 因为本文是在示范线性回归我们先不探讨复杂问题先做最简单的计算所以这次我们使用 sklearn 来产生假资料练习打好基础比较重要
from sklearn.datasets import make_regression
np_x, np_y make_regression(n_samples500, n_features10)
x torch.from_numpy(np_x).float()
y torch.from_numpy(np_y).float() np_x 是产生出来的测试线性回归数据有 10 个不同的属性500 笔数据可以使用 np_x.shape 看到 np_y 是产生出来的答案 因为 make_regression 产生出来的是 numpy他不是 PyTorch 的 Tensor所以我们要转换一下 torch.from_numpy... . float() )
6.2 建立我们的 Model
w torch.randn(10, requires_gradTrue)
b torch.randn(1, requires_gradTrue)
optimizer torch.optim.SGD([w, b], lr0.01)
def model(x):return x w b
解说
w就是乱数产生的“权重”我们会用矩阵计算将 x 的每个特征相乘记得我们上面产生的数据有 10 个特征吗 所以他是 torch.randn10而 requires_gradTrue 就是和 PyTorch 说我们要优化这个数值b源自于 yaX b 公式这次我们把 b 放进来了torch.optim.SGD[w b] lr0.01 就是优化器和他说明我们要追踪 w 和 b
再来 model function 就是我们这次的主角基本精神就是 yaX b 这边的 a 我们已经改用 w 替代
6.3 先预测
我们还没有训练我们的 model 先看直接丢入 数据 x 会生出什么
predict_y model(x)
然后我们可视化一下
plt.figure(figsize(20, 10))
plt.subplot(1, 2, 1)
plt.plot(y)
plt.plot(predict_y.detach().numpy())
plt.subplot(1, 2, 2)
plt.scatter(y.detach().numpy(), predict_y.detach().numpy()) 什么都不训练直接预测 说明一下左图是数据范围理想上两个颜色的线应该会看起来一致; 右图是数据预测与目标数据的分布图理想上应该要是一条直线左右到右上看我们之后训练过的 model 就可以知道差异
6.4 开始训练 直接看程序
loss_func torch.nn.MSELoss() # 之前提過的 loss function
history [] # 紀錄 loss誤差/損失的變化
for _ in range(300): # 訓練 300 次predict_y model(x)loss loss_func(predict_y, y)# 優化與 backward 動作之前介紹過optimizer.zero_grad()loss.backward()optimizer.step()history.append(loss.item())
plt.plot(history) loss history 可以看到 loss 随时间降低这表示我们的 model 确实有学到东西再来看看预测结果
predict_y model(x)
plt.figure(figsize(20, 10))
plt.subplot(1, 2, 1)
plt.plot(y, labeltarget)
plt.plot(predict_y.detach().numpy(), labelpredict)
plt.legend()
plt.subplot(1, 2, 2)
plt.scatter(y.detach().numpy(), predict_y.detach().numpy()) 预测结果 如上所言我们输入 x 到 model 可以得到很好的 y 预测与答案几乎相似
七、GPU 显卡 CUDA 运算范例 之前的其他文章提过 显示卡对于矩阵计算非常在行 而 PyTorch 对于使用显卡计算很容易如果读者是 Nvidia 显卡用户安装 CUDA 相关套件即可这部分就不在本文教学范围了而 AMD 用户听说有 AMD ROCm 可以使用不过本人没有使用过也不清楚本人手上都是老黄牌的显卡 我们要在 PyTorch 使用 cuda 先检测一下环境支不支持
torch.cuda.is_available() 看到结果是true表示应该可能 或许 大概 没有问题 因为实际上可能会有 CUDA 版本 / 驱动 各种奇怪状况 再来就是我们把 device 抓出来
device torch.device(cuda) # cuda 即 nvidia gpu 計算
# device torch.device(cpu) # 如果想回到 cpu 計算
再来为了我们要示范GPU和CPU的差异我们需要更多数据
from sklearn.datasets import make_regression
np_x, np_y make_regression(n_samples5000, n_features5000)
x torch.from_numpy(np_x).float().to(device)
y torch.from_numpy(np_y).float().to(device) 为了要让矩阵更大所以我们这次增加到5000个特征 然后注意上面的todevice这就是把 PyTorch 的 Tensor 搬移到设备上面我们已经指定成 cuda 所以这些资料已经被移动到 GPU 上 只有位在相同的设备的 Tensor 才能互相计算例如 gpu 只能算 gpucpu 只能算 cpu所以计算之前要 .todevice 到相同设备 现在我们建立 model 这个 model 我们要移动到 GPU 上
w torch.randn(5000).to(device)
b torch.randn(1).to(device)
w.requires_gradTrue
b.requires_gradTrue
optimizer torch.optim.SGD([w, b], lr0.01)
def model(x):x x w breturn x
一样的 todevice然后 requires_grad 是因为移动到 GPU 上已经不同于 CPU所以我们要另外设置要求追踪导数 优化器这些就一样的代码
再来跑训练
loss_func torch.nn.MSELoss()
history []
ts time.time()
for _ in range(1000): # 訓練 1000 次predict_y model(x)loss loss_func(predict_y, y)# 優化與 backward 動作optimizer.zero_grad()loss.backward()optimizer.step()history.append(loss.item())
print(frun_time: {time.time()-ts:.5f})
plt.plot(history)
我們另外加了 time.time 來看執行時間 以下是本人的一些紀錄
AMD 3900X (CPU): 2.8 secNvidia 3090(GPU) : 0.327 secJetson Nano 4GB (CPU): 52.7 secJetson Nano 4GB (GPU):16.47 sec 如果是影像處理(CNN)或是隨 model 複雜度增加時間差距會更大另外也看到 GPU 的 RAM 被佔用 gpu ram 被使用 这也是为什么 Deep Learning 会需要大内存显卡的原因当你越多的数据搬移到 GPU 就会需要更多空间
八、结语 本文的重点是学会 loss function 与 optimizer 使用 其实掌握正确的 loss function 与 optimizer在 model 的设计上就会顺利很多这个我们日后有机会介绍会看到另外本文其实很多观念与细节碍于篇幅与时间没有很详细的交代 如果有兴趣的读者可以自行输入代码与试验不同的数值去发现其中的细节变化熟悉这些操作与概念对于 Machine Learning / Deep Learning 会很有帮助Seachaos