李宏毅2020机器学习作业——Linear Regression

李宏毅2020机器学习作业——Linear Regression

一、问题描述

​ 1. 数据描述

​ 本次作业采用的数据是使用台湾某一座城市的观测记录,分别为train.csv,test.csv,其中train.csv

共有4320行, 27列,包含了该地点18种化合物一年12个月,每月钱20天,每天24小时的数值监控,test.csv则是从剩下资料当中取出的连续10小时为一组,前九个小时的观测值当做特征,第十小时的pm2.5当做answer,一共取出240组不重复的数据
2. 问题要求
​ 预测test.csv中240组测试集中的PM2.5

二、数据处理
  1. 导入必要的库
import pandas as pd
import numpy as np
import math
data = pd.read_csv('train.csv')

读取对应文件

  1. 数据处理的必要性

首先观测我们需要训练的feature与answer在表格中的关系
单一样本与标签
很容易发现1月1日的0-8小时18种化合物的所有数据都可以作为训练的数据,而第9小时的pm2.5的30数值作为这第一个训练数据的answer,从上表我们可以看出需要处理有两个部分,

  • 那个NR值需要处理为数值型,转化为0 2.
  • 数据的格式需要进行处理,每月每天每日的数据不连续,不易于后续处理
  1. 数据预处理
    #保留完全是数据的行列并导出为numpy
    data = data.iloc[:, 3:]
    data[data == 'NR'] = 0
    raw_data = data.to_numpy()
    print(raw_data)
    

    output

    [['14' '14' '14' ... '15' '15' '15']
     ['1.8' '1.8' '1.8' ... '1.8' '1.8' '1.8']
     ['0.51' '0.41' '0.39' ... '0.35' '0.36' '0.32']
     ...
     ['36' '55' '72' ... '118' '100' '105']
     ['1.9' '2.4' '1.9' ... '1.5' '2' '2']
     ['0.7' '0.8' '1.8' ... '1.6' '1.8' '2']]
    

    转化成numpy更有利于后期对test与train数据集进行一些转化的骚操作

    下面才是真正的骚操作

    将原始的数据按照月份重组,因为每个月只取了20天,20天又是连续的,那么每个月就会有(20×24)×18组数据集可供训练,每年就是12×(20*24)×18,而通过观测表格中的数据,你会发现每天24小时后数据在下一天的表格里,而16-24的数据明明可以以下一天的第0小时的pm2.5作为标签训练的!

    所以就要把原来train的4320×24的数据按照每月重组成12个18×480的数据,就是把一个月里,第二天的数据放到第一天的相邻的旁边,效果图如下

在这里插入图片描述

#对data进行调整,将4320*24重组为12*18*480
month_data = {}
for month in range(12):
    sample = np.empty([18,480])
    for day in range(20):
        sample[:,day * 24 : ( day + 1 ) * 24] = raw_data [ 18 * ( 20 * month + day ) : 18 * ( 20 * month + day + 1 ),: ]
    month_data[month] = sample

这一波操作秀吗?建立一个字典month_data存储每个月的数据,那么现在思考一下train_data与label的关系了,train_data就是九个小时的18种化合物的观测数据,如图1的绿色框框的内容,lable即红色框框的内容,而整个数据集中month_data[i]的列数即为每个月的小时数24×20,行数当然是18(化合物数量),那么其中的train_data组数即为480-9组,也就以为每个月有471个样本可以训练,其中每个样本的形状就是绿色框框显示的18×9,每年就有12×471个样本可以训练,将一整年的train_data放入一个数组x中,那么x的维度即为(12×471,18×9),那么将一整年的label放入y数组中,其维度为(12×471,1)

x = np.empty([12*471,18*9],dtype = float)
y = np.empty([12*471,1],dtype = float)
for month in range(12):
    for day in range(20):
        for hour in range(24):
            #一个月的最后一天的数据不能与下个月相连
            if day == 19 and hour>14:
                continue
            x[month * 471 + day * 24 + hour, :] = month_data[month][:,day * 24 + hour : day * 24 + hour + 9].reshape(1,-1)
            y[month * 471 + day * 24 + hour, 0] = month_data[month][9,day * 24 + hour + 9]
print(x)
print(y)

output

[[14.  14.  14.  ...  2.   2.   0.5]
 [14.  14.  13.  ...  2.   0.5  0.3]
 [14.  13.  12.  ...  0.5  0.3  0.8]
 ...
 [17.  18.  19.  ...  1.1  1.4  1.3]
 [18.  19.  18.  ...  1.4  1.3  1.6]
 [19.  18.  17.  ...  1.3  1.6  1.8]]
[[30.]
 [41.]
 [44.]
 ...
 [17.]
 [24.]
 [29.]]
4. 数据处理

​ 将数据标准化
x [ i ] [ j ] = x [ i ] [ j ] − m e a n x [ j ] s t d x [ j ] x[i][j] = \frac{x[i][j] - mean_x[j]} {std_x[j]} x[i][j]=stdx[j]x[i][j]meanx[j]
code

#标准化
mean_x = np.mean(x,axis = 0)
std_x = np.std(x,axis = 0)
for i in range(len(x)):
    for j in range(len(x[0])):
        if std_x[j] != 0:
            x[i][j] = (x[i][j] - mean_x[j]) / std_x[j]
#将训练集分成训练-验证集,用来最后检验我们的模型
x_train_set = x[: math.floor(len(x) * 0.8), :]
y_train_set = y[: math.floor(len(y) * 0.8), :]
x_validation = x[math.floor(len(x) * 0.8): , :]
y_validation = y[math.floor(len(y) * 0.8): , :]
print(x_train_set)
print(y_train_set)
print(x_validation)
print(y_validation)
print(len(x_train_set))
print(len(y_train_set))
print(len(x_validation))
print(len(y_validation))

output

[[-1.35825331 -1.35883937 -1.359222   ...  0.26650729  0.2656797
  -1.14082131]
 [-1.35825331 -1.35883937 -1.51819928 ...  0.26650729 -1.13963133
  -1.32832904]
 [-1.35825331 -1.51789368 -1.67717656 ... -1.13923451 -1.32700613
  -0.85955971]
 ...
 [ 0.86929969  0.70886668  0.38952809 ...  1.39110073  0.2656797
  -0.39079039]
 [ 0.71018876  0.39075806  0.07157353 ...  0.26650729 -0.39013211
  -0.39079039]
 [ 0.3919669   0.07264944  0.07157353 ... -0.38950555 -0.39013211
  -0.85955971]]
[[30.]
 [41.]
 [44.]
 ...
 [ 7.]
 [ 5.]
 [14.]]
[[ 0.07374504  0.07264944  0.07157353 ... -0.38950555 -0.85856912
  -0.57829812]
 [ 0.07374504  0.07264944  0.23055081 ... -0.85808615 -0.57750692
   0.54674825]
 [ 0.07374504  0.23170375  0.23055081 ... -0.57693779  0.54674191
  -0.1095288 ]
 ...
 [-0.88092053 -0.72262212 -0.56433559 ... -0.57693779 -0.29644471
  -0.39079039]
 [-0.7218096  -0.56356781 -0.72331287 ... -0.29578943 -0.39013211
  -0.1095288 ]
 [-0.56269867 -0.72262212 -0.88229015 ... -0.38950555 -0.10906991
   0.07797893]]
[[13.]
 [24.]
 [22.]
 ...
 [17.]
 [24.]
 [29.]]
4521
4521
1131
1131
三、数据处理(training)

​ 因为本次作业只是简单的回归模型,所以对于已有的训练数据集x,满足公式 x ∗ w + b = y x*w+b=y xw+b=y即可求出预测值y,而w的参数就是我们需要求解的值,我们将x的列数扩展一个维度作为参数b,可以得知参数w的维度为(18×9+1,1),给w初始化后,如何优化参数,那就是老生常谈的内容——梯度下降,但本次作业对学习率的调节方式值得学习。

  1. 损失函数
    L = ∑ i = 1 n ( x w − y ) 2 n L=\sqrt{\frac{\sum_{i=1}^{n}(xw-y)^2}{n}} L=ni=1n(xwy)2

  2. w的梯度值
    d w = x ( x w − y ) n L dw = \frac{x(xw-y)}{nL} dw=nLx(xwy)

  3. adagrad

    adagrad的参数更新方式与传统的梯度下降方式的参数更新方式不同,如你所知,传统的参数更新方式为:
    w t + 1 : = w t − a ∗ d w t w^{t+1}:=w^t - a*dw^t wt+1:=wtadwt
    再观看了李宏毅老师的gradient decent_1的视频课后,发现对于含有多个参数的模型优化,这时如果所有参数还采用同一学习率乘以梯度作为参数移动的步长,这时参数可以移动的步长取决于参数的梯度,而在每个参数距离这个参数的最优解之间的距离并不取决于它的梯度,而是它的梯度除上它的二阶导,如下所示:
    w t + 1 : = w t − a ∑ i = 0 t ( d w i ) 2 d w t w^{t+1}:=w^{t}-\frac{a}{\sqrt{\sum_{i=0}^{t}(dw^i)^2}}dw^t wt+1:=wti=0t(dwi)2 adwt
    上式的a均为学习率,若是想深剖细节可去学习李宏毅机器学习的gradient decent_1的视频课,其中的上述式子的均方根的值可近似为L对w的二阶导的数值,将上述公式应用与本题,可得以下公式:
    w t + 1 : = w t − a ∑ i = 0 t ( d w i ) 2 + b d w t w^{t+1}:=w^{t}-\frac{a}{\sqrt{\sum_{i=0}^{t}(dw^i)^2+b}}dw^t wt+1:=wti=0t(dwi)2+b adwt
    其中b为调节参数

    #因为存在偏差bias,所以dim+1
    dim = 18 * 9 + 1
    # w维度为163*1
    w = np.zeros([dim,1])
    # x_train_set维度为 4521*163
    x_train_set= np.concatenate((np.ones([len(x_train_set),1]),x_train_set),axis = 1).astype(float)
    #设置学习率
    learning_rate = 10
    #设置迭代数
    iter_time = 30000
    #让dw值初始化
    adagrad = np.zeros([dim,1])
    eps = 0.0000000001
    for t in range(iter_time):
        loss = np.sqrt(np.sum(np.power(np.dot(x_train_set,w)-y_train_set,2))/len(x_train_set))
        if(t%100 == 0):
            print("迭代的次数:%i , 损失值:%f"%(t,loss))
            gradient = (np.dot(x_train_set.T,np.dot(x_train_set,w)-y_train_set))/(loss*len(x_train_set))
            adagrad += (gradient ** 2)
            w = w - learning_rate * gradient / np.sqrt(adagrad + eps)
    #保存参数w
    np.save('weight.npy',w)
    
    迭代的次数:0 , 损失值:27.239592
    迭代的次数:100 , 损失值:598.991742
    迭代的次数:200 , 损失值:96.973083
    迭代的次数:300 , 损失值:240.807182
    迭代的次数:400 , 损失值:71.607934
    迭代的次数:500 , 损失值:212.116933
    迭代的次数:600 , 损失值:117.461546
    ......
    迭代的次数:29400 , 损失值:19.663413
    迭代的次数:29500 , 损失值:19.694863
    迭代的次数:29600 , 损失值:19.729828
    迭代的次数:29700 , 损失值:19.764402
    迭代的次数:29800 , 损失值:19.794056
    迭代的次数:29900 , 损失值:19.814439
    

    到此为止,模型已经训练完成,接下来对测试集进行测试

    四、模型求解

    ​ 首先对test.csv进行数据预处理

    #读取数据
    testdata = pd.read_csv('test.csv',header = None)
    test_data = testdata.iloc[:,2:]
    test_data[test_data == 'NR'] = 0
    test_data = test_data.to_numpy()
    test_x = np.empty([240,18*9],dtype = float)
    #数据格式转化,转化为240*162
    for i in range(240):
        test_x[i,:] = test_data[18*i:18*(i+1),:].reshape(1,-1)
    #数据标准化
    for i in range(len(test_x)):
        for j in range(len(test_x[0])):
            if std_x[j] != 0:
                test_x[i][j] = (test_x[i][j] - mean_x[j]) / std_x[j]
    #扩展出bais
    test_x = np.concatenate((np.ones([240,1]),test_x),axis = 1).astype(float)
    print(test_x)
    

    output

    [[ 1.         -0.24447681 -0.24545919 ... -0.67065391 -1.04594393
       0.07797893]
     [ 1.         -1.35825331 -1.51789368 ...  0.17279117 -0.10906991
      -0.48454426]
     [ 1.          1.5057434   1.34508393 ... -1.32666675 -1.04594393
      -0.57829812]
     ...
     [ 1.          0.3919669   0.54981237 ...  0.26650729 -0.20275731
       1.20302531]
     [ 1.         -1.8355861  -1.8360023  ... -1.04551839 -1.13963133
      -1.14082131]
     [ 1.         -1.35825331 -1.35883937 ...  2.98427476  3.26367657
       1.76554849]]
    

    最终使用模型进行预测

    #在验证集上进行验证
    w = np.load('weight.npy')
    x_validation= np.concatenate((np.ones([len(x_validation),1]),x_validation),axis = 1).astype(float)
    Loss = np.sqrt(np.sum(np.power(np.dot(x_validation,w)-y_validation,2))/len(x_validation))
    print ("the Loss on val data is %f" % (Loss))
    #预测
    ans_y = np.dot(test_x, w)
    print('预测PM2.5值')
    print(ans_y)
    

    output

    the Loss on val data is 18.427185
    预测PM2.5值
    [[-15.78367116]
     [ -2.32261409]
     [ 59.74234153]
     [ -2.69635112]
     [ 39.23820506]
     [ 13.8801302 ]
    ......
     [ 54.58686368]
     [ 44.25725877]
     [ 24.03437216]
     [ 50.94458229]
     [ 95.33833139]
     [ 67.19160767]
     [ -9.79522482]
     [ 26.46710166]]
    

    可以看出模型预测的结果并不优秀,甚至出现了负值,毕竟我们只使用了最简单的回归模型,这也就是我们需要为什么学习更复杂的模型的原因

五、反思

​ 通过这次作业的不断copy,我学习了机器学习模型从数据处理到预测结果这一系列的整个流程,其中在本次学习中我认为有两个难点,一是我对开始数据预处理的操作的不熟练,所以我称它为骚操作,说它骚,是因为它似乎额外生成了数据,把一个月的所有数据拼接在一起,有效利用了每天之间的数据,也因为它使用numpy进行处理的方式真的很骚,也看出我对numpy数据处理的不熟悉,日后需要进行复习,第二个难点是对含有矩阵或者向量的方程进行求导,并使用代码的方式把他们表示出来不熟悉,这一点希望在以后的练习中能完全掌握。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
李宏毅2020机器学习笔记中,有一个关于注意力机制(Attention)的部分。这部分内容主要介绍了生成模型(Generation)、注意力(Attention)、生成的技巧(Tips for Generation)以及指针网络(Pointer Network)。在生成模型中,主要讲述了如何生成一个有结构的对象。接下来介绍了注意力机制,包括一些有趣的技术,比如图片生成句子等。在生成的技巧部分,提到了一些新的技术以及可能遇到的问题和偏差,并给出了相应的解决方案。最后,稍微提到了强化学习。其中还提到了在输出"machine"这个单词时,只需要关注"机器"这个部分,而不必考虑输入中的"学习"这个部分。这样可以得到更好的结果。另外,还提到了关于产生"ei"的方法,其中有研究应用了连续动态模型自注意力(Self-attention)来学习位置编码的方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [2020李宏毅机器学习笔记-Condition Generation by RNN&Attention](https://blog.csdn.net/zn961018/article/details/117593813)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [李宏毅机器学习学习笔记:Self-attention](https://blog.csdn.net/weixin_44455827/article/details/128094176)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值