【学习笔记】深度学习 demo2 二次函数回归

在本demo中,我们使用的二次函数为

f(x)=(x4)(x8)+rand=x212x+32+rand

其中rand表示一个满足标准正态分布N(0,1)的随机数(平均值为0,方差为1)

基于Parameter手动构建

我们可以尝试用类似的方式,从参数(Parameter)开始构建一个二次函数。

一个二次函数的基本结构如下

g(x)=ax2+bx+c

其中包含三个参数:abc

代码如下:

import matplotlib.pyplot as plt
import torch
from torch import nn
from torch.autograd import Variable


class SquareRegression(nn.Module):
    def __init__(self):
        nn.Module.__init__(self)
        self.a = nn.Parameter(torch.randn(1, 1), requires_grad=True)  # 1 x 1
        self.b = nn.Parameter(torch.randn(1, 1), requires_grad=True)  # 1 x 1
        self.c = nn.Parameter(torch.randn(1, 1), requires_grad=True)  # 1 x 1

    def forward(self, x_):
        p_ = (x_ ** 2).mm(self.a)  # n x 1
        q_ = x_.mm(self.b)         # n x 1
        t_ = self.c                # 1 x 1
        return p_ + q_ + t_.expand_as(p_)  # n x 1


if __name__ == "__main__":
    n = 100
    x = torch.linspace(-2, 12, n).resize_((n, 1))  # n x 1 tensor
    y = (x - 4) * (x - 8) + torch.randn(x.size())  # n x 1 tensor

    model = SquareRegression()

    criterion = nn.MSELoss()
    optimizer = torch.optim.SGD(model.parameters(), lr=2e-5)

    num_epochs = 500000
    for epoch in range(num_epochs):
        inputs, targets = Variable(x), Variable(y)

        out = model(inputs)
        loss = criterion(out, targets)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if (epoch + 1) % 100 == 0:
            print('Epoch[{}/{}], loss:{:.6f}'.format(epoch + 1, num_epochs, loss.item()))

    for name, param in model.named_parameters():
        print(name, param.data)

    predict = model(x)

    plt.plot(x.numpy(), y.numpy(), 'ro', label='Original Data')
    plt.plot(x.numpy(), predict.data.numpy(), label='Fitting Line')
    plt.show()

输出结果如下:

Epoch[100/500000], loss:386.833191
Epoch[200/500000], loss:385.401001
Epoch[300/500000], loss:383.982391
Epoch[400/500000], loss:382.576904
Epoch[500/500000], loss:381.184418
Epoch[600/500000], loss:379.804657
Epoch[700/500000], loss:378.437256
Epoch[800/500000], loss:377.082153
Epoch[900/500000], loss:375.738983
Epoch[1000/500000], loss:374.407532
Epoch[1100/500000], loss:373.087585
Epoch[1200/500000], loss:371.778870
Epoch[1300/500000], loss:370.481293
Epoch[1400/500000], loss:369.194580
Epoch[1500/500000], loss:367.918549

... ... ... ...

Epoch[499400/500000], loss:0.985296
Epoch[499500/500000], loss:0.985296
Epoch[499600/500000], loss:0.985296
Epoch[499700/500000], loss:0.985296
Epoch[499800/500000], loss:0.985296
Epoch[499900/500000], loss:0.985296
Epoch[500000/500000], loss:0.985296
a tensor([[1.0048]])
b tensor([[-12.0305]])
c tensor([[31.8826]])

生成图像如下:

可以发现,我们生成的拟合解如下

{a=1.0048b=12.0305c=31.8826

所得到的函数为

g(x)=ax2+bx+c=1.0048x212.0305x+31.8826

和原公式f(x)=x212x+32已经十分接近,图像上的拟合结果也与期望结果基本一致。

基于Linear叠加构建

除此之外,我们还可以通过叠加Linear来构建一个二次函数。

本次使用的公式如下:

h(x)=(w1x+b1)(w2x+b2)=w1w2x+(w1b2+w2b1)x+b1b2

包含四个参数w1b1w2b2

代码如下:

import matplotlib.pyplot as plt
import torch
from torch import nn
from torch.autograd import Variable


class SquareRegression(nn.Module):
    def __init__(self):
        nn.Module.__init__(self)
        self.linear1 = nn.Linear(1, 1)
        self.linear2 = nn.Linear(1, 1)

    def forward(self, x_):
        return self.linear2(x_) * self.linear1(x_)  # n x 1


if __name__ == "__main__":
    n = 100
    x = torch.linspace(-2, 12, n).resize_((n, 1))  # n x 1 tensor
    y = (x - 4) * (x - 8) + torch.randn(x.size())  # n x 1 tensor

    model = SquareRegression()

    criterion = nn.MSELoss()
    optimizer = torch.optim.SGD(model.parameters(), lr=2e-5)

    num_epochs = 20000
    for epoch in range(num_epochs):
        inputs, targets = Variable(x), Variable(y)

        out = model(inputs)
        loss = criterion(out, targets)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if (epoch + 1) % 100 == 0:
            print('Epoch[{}/{}], loss:{:.6f}'.format(epoch + 1, num_epochs, loss.item()))

    for name, param in model.named_parameters():
        print(name, param.data)

    predict = model(x)

    plt.plot(x.numpy(), y.numpy(), 'ro', label='Original Data')
    plt.plot(x.numpy(), predict.data.numpy(), label='Fitting Line')
    plt.show()

输出结果如下:

Epoch[100/20000], loss:448.569519
Epoch[200/20000], loss:444.616638
Epoch[300/20000], loss:441.241089
Epoch[400/20000], loss:438.343903
Epoch[500/20000], loss:435.845673
Epoch[600/20000], loss:433.682007
Epoch[700/20000], loss:431.799835
Epoch[800/20000], loss:430.154999
Epoch[900/20000], loss:428.709595
Epoch[1000/20000], loss:427.431366
Epoch[1100/20000], loss:426.291718
Epoch[1200/20000], loss:425.265594
Epoch[1300/20000], loss:424.330353
Epoch[1400/20000], loss:423.465973
Epoch[1500/20000], loss:422.654541

... ... ... ...

Epoch[19400/20000], loss:1.044041
Epoch[19500/20000], loss:1.044041
Epoch[19600/20000], loss:1.044041
Epoch[19700/20000], loss:1.044041
Epoch[19800/20000], loss:1.044041
Epoch[19900/20000], loss:1.044041
Epoch[20000/20000], loss:1.044041
linear1.weight tensor([[0.7155]])
linear1.bias tensor([-5.7249])
linear2.weight tensor([[1.4002]])
linear2.bias tensor([-5.6002])

生成图像如下:

可以发现,我们生成的拟合解如下

{w1=0.7155b1=5.7249w2=1.4002b2=5.6002

所得到的函数为

h(x)=(w1x+b1)(w2x+b2)=(0.7155x5.7249)(1.4002x5.6002)=1.0018431x212.02294808x+32.06058498

和原公式f(x)=x212x+32已经十分接近,图像上的拟合结果也与期望结果基本一致。而且训练速度还得到了大幅度的提高(原本进行了500000次,这次在使用同样learning rate的情况下,只进行了20000次就达到了类似的效果。

其他

关于Linear

通过阅读源码可以发现,Linear内含两个最为关键的参数:weight和bias。一定程度上可以理解为所构建的线性函数公式为

f(x)=wx+b

以此类推并扩展,在2输入(in_features == 2)3输出(out_features == 3)的时候,公式为:

{f1(x)=w1,1x1+w1,2x2+b1f2(x)=w2,1x1+w2,2x2+b2f3(x)=w3,1x1+w3,2x2+b3

其中wb都将以Tensor的格式,作为weight和bias进行存储,前向传播的时候则会进行矩阵运算并生成计算图。

posted @   HansBug  阅读(1117)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
历史上的今天:
2015-04-16 1000: A+B Problem(NetWork Flow)
2015-04-16 1782: [Usaco2010 Feb]slowdown 慢慢游
点击右上角即可分享
微信分享提示