当前位置:   article > 正文

PyTorch 实现 非线型回归_pytorch利用神经网络解决非线性回归问题

pytorch利用神经网络解决非线性回归问题

原文链接:https://xiets.blog.csdn.net/article/details/131711478

版权声明:原创文章禁止转载

专栏目录:PyTorch 专栏(总目录)

PyTorch 相关网站:

1. 人工神经网络

人工神经网络是模拟人脑神经网络行为,有多层人工神经元组成的网络结构。人工神经网络各层节点之间有着非常复杂的连接关系,可以通过机器学习训练优化调各节点之间连接的权重关系,从而拟合出复杂的非线性函数。

人工神经网络总体可分为三层:

  • 输入层:作为输入的神经元节点,即样本的 输入特征。
  • 隐含层:中间经过的多层神经元(包括与神经元组合的激活函数),不管中间有多少层,都称为隐含层。
  • 输出层:作为输出的神经元节点,输出为样本的 输出特征。

隐含层是神经网络大部分计算的区域,隐含层越复杂,所能拟合的非线性函数就越复杂。一般隐含层大于等于 2 的神经网络,可以称为 深度神经网络

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110

训练输出:

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

训练结果可视化:

nonlinear_regression.webp

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/123464
推荐阅读
相关标签
  

闽ICP备14008679号