【科学计算与数学建模】线性回归预测PM2.5值之模型训练及测试

任务描述

本关任务:认识线性模型及梯度更新的一般知识,并实现PM2.5值的线性回归。

相关知识

为了完成本关任务,你需要掌握:1.线性回归的一般知识,2.实现线性回归预测PM2.5值。

线性回归的一般知识

回归分析是一种预测性的建模技术,它研究的是因变量(目标)和自变量(预测器)之间的关系。这种技术通常用于预测分析,时间序列模型以及发现变量之间的因果关系。通常使用曲线/线来拟合数据点,目标是使曲线到数据点的距离差异最小。

线性回归是回归问题中的一种,线性回归假设目标值与特征之间线性相关,即满足一个多元一次方程。通过构建损失函数,来求解损失函数最小时的参数w和b。通常我们可以表达成如下公式:

y^​=wx+b

y^为预测值,自变量x和因变量y是已知的,而我们想实现的是预测新增一个x,其对应的y是多少。因此,为了构建这个函数关系,目标是通过已知数据点,求解线性模型中w和b两个参数。

为了求解最佳参数,需要一个标准来对结果进行衡量,为此我们需要定量化一个目标函数式,使得计算机可以在求解过程中不断地优化。 针对任何樭型求解问题, 都是最终都是可以得到一組预则值 y^ ,对比已有的真实值y, 数据行数为 n,可以将损失函数定义如下:

L=n1​∑i=1n​(y^​i​−yi​)2

即预则值与真实值之间的平均的平方距离,统计中一般称其为 均方误差。 把之前的函数式代入损失函数,并且将需要求解的参数w和b看做是函数L的自变量,可得:

L(w,b)=n1​∑i=1n​(wxi​+b−yi​)2

现在的任务是求解最小化L时W和b的值,即核心目标优化式为

(w∗,b∗)=argmin(w,b)​∑i=1n​(wxi​+b−yi​)2

对于这个问题,我们可以使用梯度下降方法进行求解,梯度下降核心内容是对自变量进行不断的更新(针对w和b求偏导),使得目标函数不断逼近最小值的过程:

​w←w−α∂w∂L​b←b−α∂b∂L​​

这也是我们进行编程实现线性回归的基础。

上述一般的梯度下降算法的梯度更新规则可以改写为:

θt+1,i​=θt,i​−η⋅gt,i​

这里的更新规则中学习率是固定不变的,是开始给定的一个超参数。然而adagrad算法则是修改了学习率 ,使之成为一个可变参数,每一次学习率 的变化都是基于之前的梯度。即:

θt+1,i​=θt,i​−Gt,ii​+ε​η​⋅gt,i​

其中, 是一个对角矩阵,其中每一个对角元素i是梯度的平方,即从 直到 , 则是平滑项,通常取值为1e-8,避免除数为0。 向量化的Adagrad处理梯度更新规则如下:

θt+1​=θt​−Gt​+ε​η​⋅gt​ 其中,Gt​=θ12​+…+θt2​,adagrad的初始学习率也需要人为设置,通常设初值为0.01。

实现线性回归预测PM2.5值

基于上述线性回归和梯度更新的相关知识我们进行PM2.5数据的线性回归。
首先是初始化权重、学习率 和 迭代次数:

 
  1. w = np.zeros(len(x[0]))
  2. l_rate = 10
  3. repeat = 10

然后我们便可以进行模型的训练:

 
  1. x_t = x.transpose() #x的转置
  2. s_gra = np.zeros(len(x[0]))#记录之前梯度平方和
  3. for i in range(repeat):#每一次迭代
  4. hypo = np.dot(x,w)# w*x
  5. loss = hypo - y #误差
  6. # print(loss.shape)
  7. cost = np.sum(loss**2) / len(x) #平方差
  8. cost_a = math.sqrt(cost)#标准差
  9. gra = np.dot(x_t,loss)
  10. # print(gra.shape)
  11. s_gra += gra**2
  12. ada = np.sqrt(s_gra)
  13. w = w - l_rate * gra/ada
  14. # print ('iteration: %d | Cost: %f ' % ( i,cost_a))

模型训练完成后,我们便可以进行模型的存储,以便我们下次的使用:

 
  1. # save model 这里由于服务器不可写,仅仅展示相关代码
  2. # np.save('model.npy',w)
  3. # read model 对训练好的模型进行读取
  4. w = np.load('/data/shixunfiles/758ef4d7b2e0ac7ad1377ec761b6b05b_1636289441033.npy')

然后我们便可以利用训练好的模型进行测试数据的预测。数据的读取如上训练数据的读取。读取数据后,我们便可以进行预测:

 
  1. ans = []
  2. for i in range(len(test_x)):
  3. ans.append(["id_"+str(i)])
  4. a = np.dot(w,test_x[i])#使用训练好的权重来完成测试集的预测
  5. ans[i].append(a)
  6. # print("第%d个数据的预测结果为:"%i,a)

编程要求

完成右侧相关代码,实现线性回归预测PM2.5值。

测试说明


开始你的任务吧,祝你成功!

代码部分

import sys
import csv
import numpy as np
import pandas as pd
import math 
import random
data = []
# 每一个维度处理一种污染物
for i in range(18):
    data.append([])
# 训练数据的读取与处理
n_row = 0
text = open('/data/bigfiles/ab410c80-7695-4be3-9d57-b2c36fab9218',  'r',errors="ignore", encoding='big5')  #big5是针对于文档中存在繁体字的编码
row = csv.reader(text , delimiter = ",")
# 将数据存储到data变量中
for r in row:
    # 第0行沒有信息
    if n_row > 0: 
        # 每一行只有第3-27格有值(即一天中24小时)
        for i in range(3,27):
            if r[i] != "NR":#其中有一个污染物全部值为‘NR’
                data[(n_row-1)%18].append(float(r[i]))
            else:
                data[(n_row-1)%18].append(float(0))
    n_row = n_row+1
text.close()  
# 进行训练数据的处理和规整
x = []#特征
y = []#标签
# 共有12个月
for i in range(12):
    # 每个月共有480列数据,连取10小时的分组可有471组。
    for j in range(471):
        x.append([])
        # 共有18种污染物
        for t in range(18):#把18行合成同一行
            # 取前9小时为feature
            for s in range(9):
                x[471*i+j].append(data[t][480*i+j+s] )
        y.append(data[9][480*i+j+9])#取PM2.5的标签
x = np.array(x)
y = np.array(y)
#在第一列添加一列1
x = np.concatenate((np.ones((x.shape[0],1)),x), axis=1)

########Begin######
# 训练参数的设置
w = np.zeros(len(x[0]))
l_rate = 10
repeat = 10 

# 模型训练的过程
x_t = x.transpose() #x的转置
s_gra = np.zeros(len(x[0]))#记录之前梯度平方和
for i in range(repeat):#每一次迭代
    hypo = np.dot(x,w)# w*x
    loss = hypo - y #误差
#     print(loss.shape)
    cost = np.sum(loss**2) / len(x) #平方差
    cost_a  = math.sqrt(cost)#标准差
    gra = np.dot(x_t,loss)
#     print(gra.shape)
    s_gra += gra**2
    ada = np.sqrt(s_gra)
    w = w - l_rate * gra/ada
#    print ('iteration: %d | Cost: %f  ' % ( i,cost_a)) 

# 保存训练模型 这里由于服务器不可写,仅仅展示相关代码
# np.save('model.npy',w)
# 对训练好的模型进行读取,地址为:'/data/bigfiles/9bf99672-565e-4c8b-ad2a-c469f6cdc1bb'
w = np.load('/data/bigfiles/9bf99672-565e-4c8b-ad2a-c469f6cdc1bb')

# 读取测试数据,地址为:'/data/bigfiles/226ef946-237b-4946-8bde-c3ea9061c40d'
test_x = []
n_row = 0
text = open('/data/bigfiles/226ef946-237b-4946-8bde-c3ea9061c40d', 'r', encoding = 'big5')
row = csv.reader(text, delimiter = ',')
for r in row:
    if n_row %18 == 0:
        test_x.append([])#每个18加一行
        for i in range(2,11):
            test_x[n_row//18].append(float(r[i]))#整除18,得到每次id的预测
    else :
        for i in range(2,11):
            if r[i] !="NR":
                test_x[n_row//18].append(float(r[i]))
            else:
                test_x[n_row//18].append(0)
    n_row = n_row+1
text.close()
test_x = np.array(test_x)

# add square term
# test_x = np.concatenate((test_x,test_x**2), axis=1)

# add bias
test_x = np.concatenate((np.ones((test_x.shape[0],1)),test_x), axis=1)

# 进行预测
ans = []
for i in range(len(test_x)):
    ans.append(["id_"+str(i)])
    a = np.dot(w,test_x[i])#使用训练好的权重来完成测试集的预测
    ans[i].append(a)
#   print("第%d个数据的预测结果为:"%i,a) 


#######End#######
# 打印预测结果的信息
print("共有预测结果%d条"%(len(ans)))


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值