李宏毅 机器学习 作业1 Hungyi.Li Machine Learning HW1 PM2.5 Prediction

HomeWork1 PM2.5 Prediction

课程资料:

https://ntumlta.github.io/2017fall-ml-hw1/

从印象笔记移过来修改的,懒得编辑太细了,CSDN又不让直接插图,CSDN的编辑器老出出现各种错误,太麻烦,反正代码能跑。

做题思路:

数据处理

id_x是时间点,每一个具体的x,是一个时间点。

怎么抽取训练集?1-9训练,第十个验证,2-10训练,第11个验证?这样每单次训练都要验证一次?

不对,这个方法是抽训练集,训练集包括input和output,前9个id_x是输入,第10个id_x是output。10个数据加起来,才是一个训练数据,而不是单条观测记录。

第一个简陋版本(有理解偏差):

for循环,从时刻0到时刻n-9迭代:

    抽0-8作为input,抽9为output

    把抽到的数据想好一个格式存起来。

PS:9比1的输入输出,也是自己可选的,不是固定的,考虑到给的test集是9:1预测,所以按9:1来设计。

难点:除了天数,还有每天的小时,不是按天预测的,有点复杂了,按小时能不能跨天?可能模型不要这么复杂?(错了,要跨)

跨天和不跨天的差距:

模型偏科,就是说从来不预测1点、2点、到9点的数据,只预测10点到24点的数据,这就会产生——用不针对1-9点的模型来预测1-9点,肯定有问题

不跨天的另一个问题就是大幅缩减了数据量——数据集是12个月,每个月20天,每天24小时,不跨天的话12*20*(24-9)==3600,而跨天是12*(20*24-9)==5652

另外,降雨的数据中有“NR”,这个要自己处理转换一下,用bool?不行,非NR是浮点数,NR是不降雨,NR标0就行了!!!

第二版本:

k=9,k是打算用来预测的前边的input,因为test集提供了9个,所以为了最大化自己的预测,肯定不会去用5个预测!k以test的最大数为准!!

大循环:

    按日期的不同,来做分割

    中循环:

        把所有不同的指标都读一遍,分别加标记以区分

        小for循环,i从时刻0到时刻n-9迭代(停止指标,i+9没数据了):

            抽i到i+(k-1)作为input,抽i+k为output

            把抽到的数据想好一个格式存起来。

第三版本,参考了作业补充ppt

需要跨天的,他也没演示跨月怎么处理,我估计每个月都算一个独立的数据集???可能他简化了,不用?用!!,比如你可以用随机森林什么的,把多个月拼接起来

跨天的话还面临另一个建模问题,时段问题(其实不跨天也有这问题,所以这不是问题)

特征抽取伪代码:

最外层循环-月份i迭代:

    每个月i内,每天之间要拼接起来。形成小时序列

    第二层循环,按小时i迭代抽取特征:

        从j到j+8取出来,作为input存储(train_x.append)这8个组合起来才是1个input,不是8个input,每一个都是向量,所以intpu是矩阵?

        j+9作为output,存储(train_y.append)

        直到j+10没数据停止

    直到月份取光结束

整个train_x,每笔加个bias

实操:参考代码片段,有分月份,只不过分到第二步去做了!!!

模型建立

建模

0.真正做预测,我肯定考虑要跨天了,但是操作也挺麻烦的,而且他的数据是断的,每个月只有20天(剩下10天可能当测试集了),每个月至少还要做个截断,操作繁琐。

1.特征选择,我肯定先用纯PM2.5了

2.然后可以考虑PM2.5+PM10.

3.然后我会考虑风,因为北京就和风有关

4.可以考虑一下降雨因素

5.然后考虑所有的都用?要不要正则化?

6.每天的不同时段明显不一样,也就是说,半夜那部分的数据,肯定影响你对白天那部分的预测?

既然是机器学习,可能就都考虑进去了,数据足够多,模型足够大,应该所有部分都能正确预测?

PS:应该西风或者西北风好点?

这都不绝对,因为你不知道台湾的污染源分布?

也许受大陆影响,西北风会更脏?

东边的海风也许更干净?

也许因为中部有山,所以东风不好用?

所以这个建模,跟实际地形、外部环境,等等,都有关系。你不了解详细信息,不会建模建的很好。

训练

之前把数据都处理好了,现在是分N批(月份),每批一堆input和一堆output。开始写模型训练。

数据处理转存完,应该可以直接训练了。把建模部分想好的模型的公式列出来,然后用这个公式去训练,然后用训练集输入一遍,然后把test输入,输出,做准确率对比。

第一版:

只算所有PM2.5,

随意初始化weights(多少层?)

模型:y = bias+w1*x1+w2*x2+...+w9*x9(深层?一层?)

训练过程:梯度下降:

η=0.01(先随便吧)

epoch = 1000

for e in epoch:

    还是要算出Loss才能进行下边的update的(主要问题就是这个gradient在python怎么表达)

    

       #theta = gradientDescent(X, y, theta, alpha, iterations);#octave代码

        #theta = theta - alpha/m * X' *(X*theta - y)#这是octave的,X'好像是逆之类的,而且这里X可能是矩阵,所以应该是通过公式转换了

    批量update:

        wij=wij-η*gradient#每个wij应该单独有一个gradient吧?

        ......

第二版:参考答案

(Pseudo code)

1. 宣告weight vector、初始learning rate、# of iteration

2. for i_th iteration :

3. y’ = train_x 和 weight vector 的 內積

4. L = y’ - train_y

5. gra = 2*np.dot( (train_x)’ , L )

6. weight vector -= learning rate * gra

模型公式示意和步骤示意(不过这里的y'没有+b了呢。。。grad+2*x乘以L)

测试

给了参考

# use close form to check whether ur gradient descent is good 
# however, this cannot be used in hw1.sh 
# w = np.matmul(np.matmul(inv(np.matmul(x.transpose(),x)),x.transpose()),y)

但是这个也不是分类问题,我应该怎么比结果?取整?不是一个整数就算不准?不是吧?!

但是要的是准确了就该是个比例,而不是其他的

看一下训练过程?那个Loss的计算方法应该可以。

下边是照着参考PPT和代码片段做的

import csv
import numpy as np
from numpy.linalg import inv
#import sys
import math
#import random


#############################################
#parse data
#initial
data = []
for i in range(18):
        data.append([])
n_row = 0
#print("data:",data)
#print("type(data):",type(data))

text = open('train.csv','r',encoding='big5')
row = csv.reader(text,delimiter=",")

print("type(text):",type(text))
print("type(row):",type(row))


for r in row:
        #0 cols
        if n_row != 0:
                for i in range(3,27):
                        if r[i] != "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()
print("data[0]:",data[0][:12])
print("data[1]:",data[1][:12])


#divide data
x = []
y = []
const_month = 12
src_data_in_month = int(len(data[0]) / const_month)     #480=12*20
data_per_month = src_data_in_month - 9          #471
#per month
for i in range(12):
        for j in range(data_per_month):
                x.append([])
                for t in range(18):
                        for s in range(9):
                                x[471*i+j].append(data[t][480*i+j+s])
                y.append(data[9][480*i+j+9])    #s=9
print("after append,x[0]:",x[0][:10])
print("len(x):",len(x))

x=np.array(x)
y=np.array(y)
print("len(x):",len(x))

x=np.concatenate((np.ones((x.shape[0],1)),x),axis=1)
print("len(x):",len(x))
w2 = np.matmul(np.matmul(inv(np.matmul(x.transpose(),x)),x.transpose()),y)

################################################
#train
w = np.zeros(len(x[0]))
print("len(x[0]):",len(x[0]))
l_rate=10
repeat=10000
#print("w[0]:",w[0][:10])
#print("w[1]:",w[1][:10])

x_t = x.transpose()
s_gra = np.zeros(len(x[0]))

for i in range(repeat):
        hypo = np.dot(x,w)
        loss = hypo - y
        cost = np.sum(loss**2)/len(x)
        cost_a = math.sqrt(cost)
        gra = np.dot(x_t,loss)
        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)

w2 = np.load('model.npy')


#######################################################
#test
test_x = []
n_row = 0
text = open('test.csv',"r")
row = csv.reader(text, delimiter=",")

for r in row:
        if n_row % 18 == 0:
                test_x.append([])
                for i in range(2,11):
                        test_x[n_row//18].append(float(r[i]))
        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)
test_x = np.concatenate((np.ones((test_x.shape[0],1)),test_x),axis=1)


#######################################################3
#test
ans = []
for i in range(len(test_x)):
        ans.append(["id_"+str(i)])
        a = np.dot(w,test_x[i])
        ans[i].append(a)
#############
'''
        a = np.dot(w,test_x[i])
        a2 = np.dot(w2,test_x[i])
        loss = a - a2
        cost = np.sum(loss**2)/len(test_x[i])
        cost_a = math.sqrt(cost)
        print("test Cost:%f"%(cost_a))
'''
########################
filename = "predict.csv"
text = open(filename,"w+")
s = csv.writer(text,delimiter=',',lineterminator='\n')
s.writerow(["id","value"])
for i in range(len(ans)):
        s.writerow(ans[i])
text.close()



顺便加入了自己写的和“标准答案”对比的代码,因为这是他们台大的作业,kaggle已经过期,没法直接拿去跑,只能用这个答案对比。为什么能比?这个模型他给的就是线性的,凸函数,可以用close form(翻译是直接公式法?)来找到答案。

import csv
import math

ans = []
n_row = 0
text = open('ans.csv',"r")
row = csv.reader(text,delimiter=",")
print(text)
print(row)
#print("len(row):",len(row))
for r in row:
        #print("r[0] is ",r[0])
        #print("r[1] is ",r[1])
        if r[1] != 'value':
                ans.append(round(float(r[1])))
print(ans)

predict = []
n_row = 0
text = open('predict.csv',"r")
row = csv.reader(text,delimiter=",")
for r in row:
        #print("r[0] is ",r[0])
        #print("r[1] is ",r[1])
        if r[1] != 'value':
                predict.append(round(float(r[1])))
print(predict)
print(type(predict))


sum = 0
for i in range(len(ans)):
        sum += abs(predict[i] - ans[i])
err = sum / len(ans)
#err = abs(predict - ans).sum()/len(ans)
print(err)

方法二:array操作,最后求和平均

#######################################
#implementation 2

predict_ndarray = np.array(predict)
ans_ndarray = np.array(ans)
err_ndarray = predict_ndarray - ans_ndarray
err_ndarray = np.abs(err_ndarray)
sum2 = np.ndarray.sum(err_ndarray)
print(sum2)
err2 = sum2 / len(ans)
print(err2)

猜你喜欢

转载自blog.csdn.net/huqinweI987/article/details/81431631