首页/文章/ 详情

非线性回归

精品
作者优秀平台推荐
详细信息
文章亮点
作者优秀
优秀教师/意见领袖/博士学历/特邀专家
平台推荐
主编推荐
3年前浏览1812

寒假撸了几把深度学习,感觉颇有意思。

在数据科学中,回归是最基础的计算。通俗来讲,回归就是找出一堆数据之间的函数关系。线性回归是最简单的回归,很容易利用最小二乘法解决。非线性回归也可以使用最小二乘法去处理,然而如果数据之间看不到明显的函数关系,最小二乘法利用起来就比较麻烦,比如下面的数据点就很难找到一个合适的数学函数进行拟合。

image.png

利用神经网络可以对上面的数据点进行拟合,下面是一个最简单的利用Pytorch进行非线性回归的代码。

import torch
from torch import nn,optim
import matplotlib.pyplot as plt
import pandas as pd

data  = pd.read_csv('temp.csv')
x = torch.from_numpy(data['time'].values.reshape(-1,1)).type(torch.float32)
y = torch.from_numpy(data['deltaT'].values.reshape(-1,1)).type(torch.float32)

class NonLinearNet(nn.Module):
   def __init__(self):
       super(NonLinearNet,self).__init__()
       self.linear = nn.Sequential(
           nn.Linear(1,20),
           nn.ReLU(),
           nn.Linear(20,12),
           nn.ReLU(),
           nn.Linear(12,1)
       )
       
   def forward(self,x):
       out = self.linear(x)
       return out

model = NonLinearNet()
loss_fn = nn.MSELoss()
optimizer = optim.Adam(model.parameters(),lr = 0.005)

for epoch in range(10000):
   output = model(x)
   loss = loss_fn(output,y)
   optimizer.zero_grad()
   loss.backward()
   optimizer.step()

   if epoch % 500 == 499:
       print('epoch:%d,loss=%.3f'%(epoch 1,loss.item()))
       plt.cla()
       plt.scatter(x, y, s=3, color='blue')
       y_pred = model(x)
       plt.plot(x, y_pred.detach().numpy(), lw=2, color='red')
       plt.grid()
       plt.title('epoch:%d,loss=%.3f'%(epoch 1,loss.item()))
       plt.pause(0.05)
       
plt.show()

这里数据规模很小,没有使用GPU计算。拟合过程如下图所示。

图片

训练完毕后可以将模型保存下来,可以利用下面的代码:

torch.save(model.state_dict(),'NonLinearNet.pkl')

后面就可以直接加载模型对输入的X数据进行Y值预测了,如下面的示例代码计算x=700时的Y值。

model  = NonLinearNet()
state_dict = torch.load('NonLinearNet.pkl')
model.load_state_dict(state_dict)
test_x = torch.tensor([[700.0]],dtype=torch.float32)
print(model(test_x))

程序输出结果为:

tensor([[52.3139]], grad_fn=<AddmmBackward>)

预测Y=52.3139。

当然这里只是随便举了个例子。神经网络也有一大堆莫名其妙的麻烦问题有待解决,比如复现性很差,比如过拟合等等,一不留神就变成了神经病网络,这个有兴趣的道友可以自己尝试。

利用神经网络处理拟合问题一个最大的好处是,每次只需要提供不同的数据而无需修改代码。下面看看拟合100个点的正弦数据。代码很简单,如下所示。

import torch
from torch import nn,optim
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 准备数据
x = np.linspace(0,2*np.pi,num=100).reshape(-1,1)
ysin = np.sin(x).reshape(-1,1)


class NonLinearNet(nn.Module):
   def __init__(self):
       super(NonLinearNet,self).__init__()
       self.linear = nn.Sequential(
           nn.Linear(1,20),
           nn.ReLU(),
           nn.Linear(20,12),
           nn.ReLU(),
           nn.Linear(12,4),
           nn.ReLU(),
           nn.Linear(4,1)
       )

   def forward(self,x):
       out = self.linear(x)
       return out


model = NonLinearNet()
loss_fn = nn.MSELoss()
optimizer = optim.Adam(model.parameters(),lr = 0.002)

for epoch in range(10000):
   x = torch.Tensor(x)
   y = torch.Tensor(ysin)
   output = model(x)
   loss = loss_fn(output,y)
   optimizer.zero_grad()
   loss.backward()
   optimizer.step()

   if epoch % 1000 == 999:
       print('epoch:%d,loss=%.3f'%(epoch 1,loss.item()))
       plt.cla()
       plt.scatter(x, y, s=3, color='blue')
       y_pred = model(x)
       plt.plot(x, y_pred.detach().numpy(), lw=2, color='red')
       plt.grid()
       plt.title('epoch:%d,loss=%.5f'%(epoch 1,loss.item()))
       plt.pause(0.05)

plt.show()

训练过程如下图所示。

图片

来预测一个sin(3*pi)的值。

下一次要训练余弦数据,此时只需要替换源数据即可。代码如下所示。

import torch
from torch import nn,optim
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 准备数据
x = np.linspace(0,2*np.pi,num=100).reshape(-1,1)
# ysin = np.sin(x).reshape(-1,1)
ycos = np.cos(x).reshape(-1,1)

class NonLinearNet(nn.Module):
   def __init__(self):
       super(NonLinearNet,self).__init__()
       self.linear = nn.Sequential(
           nn.Linear(1,20),
           nn.ReLU(),
           nn.Linear(20,12),
           nn.ReLU(),
           nn.Linear(12,4),
           nn.ReLU(),
           nn.Linear(4,1)
       )

   def forward(self,x):
       out = self.linear(x)
       return out


model = NonLinearNet()
loss_fn = nn.MSELoss()
optimizer = optim.Adam(model.parameters(),lr = 0.002)

for epoch in range(10000):
   x = torch.Tensor(x)
   y = torch.Tensor(ycos)
   output = model(x)
   loss = loss_fn(output,y)
   optimizer.zero_grad()
   loss.backward()
   optimizer.step()

   if epoch % 1000 == 999:
       print('epoch:%d,loss=%.3f'%(epoch 1,loss.item()))
       plt.cla()
       plt.scatter(x, y, s=3, color='blue')
       y_pred = model(x)
       plt.plot(x, y_pred.detach().numpy(), lw=2, color='red')
       plt.grid()
       plt.title('epoch:%d,loss=%.5f'%(epoch 1,loss.item()))
       plt.pause(0.05)

plt.show()

余弦数据训练过程如下图所示。

图片

声明:原创文章,欢迎留言与我讨论,如需转载留言

科普代码&命令网格处理其他软件
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2021-03-01
最近编辑:3年前
CFD之道
博士 | 教师 探讨CFD职场生活,闲谈CFD里外
获赞 2575粉丝 11348文章 739课程 27
点赞
收藏
作者推荐
未登录
1条评论
仿真秀0508001113
签名征集中
2年前
学到了
回复
课程
培训
服务
行家
VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈