「Pytorch」用二次多项式拟合三次多项式一百万次,看看最后能做到多好?

一、背景

在廖星宇《深度学习入门》的github项目中,留了一道思考题:

小练习:上面的例子是一个三次的多项式,尝试使用二次的多项式去拟合它,看看最后能做到多好
提示:参数 w = torch.randn(2, 1),同时重新构建 x 数据集

二、代码部分

在项目中没有给出代码,作者自己改写了一个,作了大概如下改动:

  • 改动了criterion,选用了自带的MSE
  • 使用了nn.Sequential并强其放到了cuda上,试图用GPU增加运算效率
  • 训练100000000次
  • 多画几个窗口,好对比一下
  • 代码部分没有精校,可能存在一些错误
  • 也许criterion是否有更好的选择
  • 代码在我本地没有问题啊!(手动狗头
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Mar 27 17:36:24 2020

@author: ftimes
"""
import torch
import numpy as np
import matplotlib.pyplot as plt
import torch.nn as nn

SEED=2020
torch.manual_seed(SEED)
DEVICE=torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 定义一个多变量函数
w_target = np.array([0.5, 3, 2.4]) # 定义参数
b_target = np.array([0.9]) # 定义参数

f_des = 'y = {:.2f} + {:.2f} * x + {:.2f} * x^2 + {:.2f} * x^3'.format(
    b_target[0], w_target[0], w_target[1], w_target[2]) # 打印出函数的式子
print(f_des)

x_sample = np.arange(-3, 3.1, 0.1)
y_sample = b_target[0] + w_target[0] * x_sample + w_target[1] * x_sample ** 2 + w_target[2] * x_sample ** 3

plt.plot(x_sample, y_sample ,label='real curve')
plt.legend(loc='best')

# 构建数据 x 和 y
# x 是一个如下矩阵 [x, x^2, x^3]
# y 是函数的结果 [y]

x_train = np.stack([x_sample ** i for i in range(1, 3)], axis=1)
x_train = torch.tensor(x_train).float().to(DEVICE) # 转换成 float tensor
y_train = torch.tensor(y_sample).float().unsqueeze(1).to(DEVICE) # 转化成 float tensor


seq_net = nn.Sequential(
    nn.Linear(2, 1), # PyTorch 中的线性层,wx + b
).to(DEVICE)



'''
w = nn.Parameter(torch.randn(2, 1)*0.01).to(DEVICE)
b = nn.Parameter(torch.zeros(1)).to(DEVICE)
'''


optimizer=torch.optim.SGD(seq_net.parameters(),0.000001)
criterion=nn.MSELoss().to(DEVICE)

y_pred = seq_net(x_train)

plt.figure(2)
#plt.plot(x_train.data.numpy()[:, 0], y_pred.data.numpy(), label='fitting curve', color='r')
plt.plot(x_train.data.cpu().numpy()[:, 0], y_pred.data.cpu().numpy(), label='fitting curve', color='r')
plt.plot(x_train.data.cpu().numpy()[:, 0], y_sample, label='real curve', color='b')
plt.legend()



EPOCH=1000000
for e in range(EPOCH):
    y_pred = seq_net(x_train)
    loss=criterion(y_pred,y_train)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if (e + 1) % 100000 == 0:
        print('epoch: {}, loss: {}'.format(e+1, loss.data))
        
y_pred =seq_net(x_train)

plt.figure(3)
#plt.xlim(1, 2)
#plt.ylim(0, 20)
plt.plot(x_train.data.cpu().numpy()[:, 0], y_pred.data.cpu().numpy(), label='fitting curve', color='r')
plt.plot(x_train.data.cpu().numpy()[:, 0], y_sample, label='real curve', color='b')
plt.legend()

print(seq_net[0].weight,seq_net[0].bias)
print(f_des)

三、测试结果

epoch: 100000, loss: 279.2529296875
epoch: 200000, loss: 155.79791259765625
epoch: 300000, loss: 120.1278305053711
epoch: 400000, loss: 109.79125213623047
epoch: 500000, loss: 106.81745910644531
epoch: 600000, loss: 105.95108795166016
epoch: 700000, loss: 105.70142364501953
epoch: 800000, loss: 105.61643981933594
epoch: 900000, loss: 105.60639953613281
epoch: 1000000, loss: 105.60639953613281
Parameter containing:
tensor([[13.8103,  3.0138]], device='cuda:0', requires_grad=True) Parameter containing:
tensor([0.8424], device='cuda:0', requires_grad=True)
y = 0.90 + 0.50 * x + 3.00 * x^2 + 2.40 * x^3

我们可以看到,在学习率非常小的情况下,这个loss始终维持在了105.58638763427734。
如果是设置成0.03,可以迅速收敛到这个数。
可能是我哪里弄错了?恳请您指正我这个初学者。
但我们可以肯定的是,用二次多项式无法很好的拟合的三次多项式。
下面上图。
  1. 原始图像
    在这里插入图片描述2. 初始图像
    在这里插入图片描述3. 1000000次模拟后的图像
    在这里插入图片描述

如果您有更好的代码,欢迎在评论区留言,感激不尽~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值