寒假撸了几把深度学习,感觉颇有意思。
在数据科学中,回归是最基础的计算。通俗来讲,回归就是找出一堆数据之间的函数关系。线性回归是最简单的回归,很容易利用最小二乘法解决。非线性回归也可以使用最小二乘法去处理,然而如果数据之间看不到明显的函数关系,最小二乘法利用起来就比较麻烦,比如下面的数据点就很难找到一个合适的数学函数进行拟合。
利用神经网络可以对上面的数据点进行拟合,下面是一个最简单的利用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()
余弦数据训练过程如下图所示。
声明:原创文章,欢迎留言与我讨论,如需转载留言