这几天,由于新型冠状病毒的爆发,每天的新确诊人数都让早上起床的我感到吃惊!大家为了给社会贡献一份力量,即使在春节期间,都可以待在家里少外出。各大IT企业纷纷捐钱捐物资,为抗战一线出力!而此时待在家里的我们能做些什么呢?
由于我是学计算机科学与技术的大三学生,想在待在家的时间,利用专业知识,预测一下下一天的确诊人数。因此,就简单地写了一个基础代码,跑了一下,得到了一个结果,准确率不敢保证,毕竟数据有限hhh~
Windows10
python3.7.4
pytorch1.2.0
matplotlib(忘了版本号)
在这里,因变量的我选的是每天的累计确诊人数,而自变量即特征其实有很多,但是我只能获取时间特征,因此只能简单地预测一下下一天的累计确诊人数。
通过观察每天的数据,我们可以很轻松地得出这是一个非线性回归问题,而对于处理非线性问题,用神经网络再合适不过了。因为神经网络每层都可以拥有非线性的激活函数,因此可以较好地拟合非线性数据。(数据量少我就不考虑过拟合问题了)
我选取了从1月20到27号的数据作为训练集,明天的结果自动的成为测试集。建立了一个输入层,两个隐藏层,一个输出层的全连接神经网络。数据集长度为BatchSize进行训练。
在激活函数上用来tanh和relu,tanh具有较好的非线性,relu具有较稳定的梯度。
tanh是双曲函数中的一个,tanh()为双曲正切。在数学中,双曲正切“tanh”是由双曲正弦和双曲余弦这两种基本双曲函数推导而来。
线性整流函数(Rectified Linear Unit, ReLU),又称修正线性单元,是一种人工神经网络中常用的激活函数(activation function),通常指代以斜坡函数及其变种为代表的非线性函数。
公式:
在这里,损失函数用的是L1loss,L1loss为目标值与预测值的差的绝对值的平均值,然后梯度下降反馈回去。如果不是对平均值的反馈,那效果就和batchsize==1一样,对每个x进行y的单独靠近而无法兼顾所有地x同时靠近所有的y,使得结果不稳定产生震荡而且无法有效地拟合。
下面是Adam优化器的伪代码:
关于adam优化器的详细介绍,可以参考链接:
简单认识Adam优化器
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import torch.nn.functional as F
learning_rate=0.006
class virus(nn.Module):
def __init__(self):
super(virus,self).__init__()
self.fc1 = nn.Sequential(nn.Linear(1,10),nn.Tanh())
self.fc2 = nn.Sequential(nn.Linear(10,20),nn.ReLU())
self.fc3 = nn.Sequential(nn.Linear(20,10),nn.ReLU())
self.fc4 = nn.Sequential(nn.Linear(10,1))
def forward(self,x):
out = self.fc1(x)
out = self.fc2(out)
out = self.fc3(out)
out = self.fc4(out)
return out
if __name__=='__main__':
plt.ion()
plt.show()
x=torch.tensor([[20],[21],[22],[23],[24],[25],[26],[27]]).float()
y=torch.tensor([[217],[291],[440],[571],[830],[1287],[1975],[2744]]).float()
model=virus()
loss=nn.MSELoss()
optimizer=torch.optim.Adam(model.parameters(),lr = learning_rate)
num_epoch=50000
for epoch in range(num_epoch):
model.train()
optimizer.zero_grad()
result=model.forward(x)
loss_value=loss(result,y)
loss_value.backward()
print(loss_value)
print(loss_value.item())
optimizer.step()
print("epoch:{} loss:{}".format(epoch,loss_value.item()))
if epoch % 10 == 0:
plt.cla()
plt.scatter(x.data.numpy(), y.data.numpy())
# r- 是红色 lw 是线宽
plt.plot(x.data.numpy(), result.data.numpy(), 'r-', lw=5)
plt.text(0.5, 0, 'Loss=%.4f'%loss_value.data.numpy(), fontdict={'size':20, 'color': 'red'})
# 间隔多久再次进行绘图
plt.pause(0.1)
torch.save(model.state_dict(),'epoch{}-loss{}weight.pth'.format(epoch,loss_value.item()))
r=model.forward(torch.tensor([[28]]).float())
print(r.item())
四舍五入后就是3447人。希望明天的确诊累积结果可以比这个值要低很多很多!