赞
踩
原文链接:https://xiets.blog.csdn.net/article/details/131711478
版权声明:原创文章禁止转载
专栏目录:PyTorch 专栏(总目录)
PyTorch 相关网站:
人工神经网络是模拟人脑神经网络行为,有多层人工神经元组成的网络结构。人工神经网络各层节点之间有着非常复杂的连接关系,可以通过机器学习训练优化调各节点之间连接的权重关系,从而拟合出复杂的非线性函数。
人工神经网络总体可分为三层:
隐含层是神经网络大部分计算的区域,隐含层越复杂,所能拟合的非线性函数就越复杂。一般隐含层大于等于 2 的神经网络,可以称为 深度神经网络。
使用 线性模型 组合 激活函数 构建神经网络模型实现非线性回归。下面代码示例,先随机生成一组接近 y = x^3
的坐标点,然后构建非线性神经网络模型拟合所有坐标点,训练出拟合函数。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import torch
import torch.nn.functional as F
from torch import nn, optim
class Net(nn.Module):
"""
神经网络模型
"""
def __init__(self, *, in_features: int, hidden_features: int, out_features: int):
"""
:param in_features: 输入层 的神经元数量 (样本的输入特征数)
:param hidden_features: 隐含层 的神经元数量 (隐含层的输出特征数)
:param out_features: 输出层 的神经元数量 (样本的输出特征数)
"""
super().__init__()
# 使用线性模型创建 隐含层
self.hidden = nn.Linear(in_features, hidden_features)
# 使用线性模型创建 输出层
self.out = nn.Linear(hidden_features, out_features)
# 这里只有一层隐含层:
# 输入层 (每个样本提供的 in_features 个特征)
# =>
# 隐含层 (in_features 个特征输入 -> hidden_features 个特征输出)
# =>
# 输出层 (hidden_features 个特征输入 -> out_features 个特征输出)
def forward(self, inputs: torch.Tensor) -> torch.Tensor:
"""
前向传播 (预测输出)
"""
# 把 输入层的特征数据(inputs) 批量输入到 隐含层, 返回的张量形状为 (inputs.size()[0], hidden_features)
x = self.hidden(inputs)
# 把隐含层的输出应用激活函数 (用于拟合非线性模型), 返回经过激活函数处理后具有相同形状的张量
# 这里使用 ReLU (Rectified Linear Unit, 线性整流函数) 激活函数, 函数公式: relu(x) = max(0, x)
x = F.relu(x)
# 把激活函数处理后的张量批数据输入到输出层, 返回输出张量, 返回的张量形状为 (inputs.size()[0], out_features)
outputs = self.out(x)
return outputs
def main():
# 随机生成一组接近 pow(x, 3) 函数的坐标点数据集
x = torch.linspace(-10, 10, 20).reshape((-1, 1))
y = torch.pow(x, 3) + 100 * torch.rand(x.size())
print(f"Datasets Size: x.size = {x.size()}, y.size = {y.size()}")
# 输出: Datasets Size: x.size = torch.Size([20, 1]), y.size = torch.Size([20, 1])
plt.grid(True, linestyle="--")
# 把原始数据集坐标点绘制为散点图
# x.data 是一个始终不需要计算梯度的 Tenser (值与原 x 相等), 即 x.data.requires_grad == False, requires_grad 为 False 时才能调用 numpy()。
# 如果原张量是需要计算梯度的, 则必须以 x.data.numpy() 的形式转换为 ndarray。如果原张量不需要计算梯度则可以直接调用 numpy() 方法。
plt.scatter(x.data.numpy(), y.data.numpy())
# 数据集的 输入 和 真实输出 张量, 数据类型为 torch.Tensor
inputs = x
target = y
# inputs 和 target 是二维矩阵, 每一行表示一个样本数据
# 创建 网络模型 (1个输入特征, 10个隐含层特征, 1个输出特征)
model = Net(in_features=1, hidden_features=10, out_features=1)
# 创建 损失函数 (均分误差)
criterion = nn.MSELoss()
# 创建 优化器 (随机梯度下降, 学习率为 0.001)
optimizer = optim.SGD(model.parameters(), lr=0.0001)
# 总的迭代次数
epochs = 10000
# 训练模型
for epoch in range(epochs):
# 1. 前向传播 (预测输出)
outputs = model(inputs)
# 2. 计算损失值
loss = criterion(outputs, target)
# 3. 梯度清零 (清空 model 参数的梯度值, 即 grad 属性, 不清空会累积)
optimizer.zero_grad()
# 4.反向传播 (计算梯度, 计算 model 参数的梯度值)
loss.backward()
# 5. 更新模型参数 (根据 model 参数的梯度值 更新 参数值)
optimizer.step()
# 每隔 100 次 或 最后一次 输出相关参数
if (epoch % 1000 == 0) or (epoch == epochs - 1):
print(f"Epoch[{epoch:04d}/{epochs - 1}]: loss={loss.item()}")
# 使用训练好的模型预测输出, 并绘制为红色直线
outputs = model(inputs)
plt.plot(inputs.numpy(), outputs.detach().numpy(), "r-")
plt.show()
if __name__ == "__main__":
main()
训练输出:
Epoch[0000/9999]: loss=192367.546875
Epoch[1000/9999]: loss=3623.327392578125
Epoch[2000/9999]: loss=2979.42626953125
Epoch[3000/9999]: loss=2191.74365234375
Epoch[4000/9999]: loss=900.7564697265625
Epoch[5000/9999]: loss=1211.87158203125
Epoch[6000/9999]: loss=538.9493408203125
Epoch[7000/9999]: loss=651.341064453125
Epoch[8000/9999]: loss=592.1126098632812
Epoch[9000/9999]: loss=639.177734375
Epoch[9999/9999]: loss=524.032470703125
训练结果可视化:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。