李宏毅机器学习笔记——新手感悟——PM2.5作业
python也不会,计算机也不会,啥都不会,只带了个脑子考了计算机研究生。研究生选了人工智能方向。看来注定是漫长的学习之旅。
PM2.5作业,我是一个字都看不懂。所以我采用了直接看答案的方案。把答案看懂也是一种本事。
把答案CV上来。
import sys
import pandas as pd
import numpy as np #环境,就不说了。ananconda真的难装。
#提取TEST数据集
data = pd.read_csv('work/hw1_data/train.csv', encoding = 'big5')#读取文件数据
print(data)
data = data.iloc[:, 3:] #iloc是对表格式数据使用的一个函数 loc用的是表格索引,iloc用的是表格行列号,
# 此处取的就是所有行和第三列之后的所有列。作用就是只留数据不留前面的杂项。
data[data == 'NR'] = 0 #将所有数据里的NR全部置换为0.NR肯定无法参与运算,换成0让他不起作用。
print(data)
raw_data = data.to_numpy()#表格转换为numpy矩阵
month_data = {} #创建存放每月数据的数组
for month in range(12):
sample = np.empty([18, 480]) #empty创建一个数组,但是元素不一定为0,可能为随机值。
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####等于创建了12个二维数组。每个数组是平起来的整个月份每天的数据
###提取特征值,这里作业要求用前九天的数据来预测第十天数据,因此将每九天的数据变为一行,作为特征值。
x = np.empty([12 * 471, 18 * 9], dtype = float) #471是如何来的?这里是每九个小时一个数据,但并不是用过的就不用了。而是第一个数据0到8,第二个数据1到9,这个样子。最后9天因为找不到第十天的数据所以舍去,就是20*24-9=471.
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) #vector dim:18*9 (9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9)
#reshape(1,-1)可以转换为一行.这里把9列(9个小时)的18维数据融为一行。
y[month * 471 + day * 24 + hour, 0] = month_data[month][9, day * 24 + hour + 9] #value 为啥是9小时后的PM2.5
#因为这里作业要求使用9个小时的PM2.5来预测第十个小时的PM2.5的值,因此数据集进行了这样的划分,Y即为target,记录了每九个小时后第十个小时的PM2.5值
·
print('x',x)
print(y)###
###归一化
mean_x = np.mean(x, axis = 0) #18 * 9
std_x = np.std(x, axis = 0) #18 * 9###计算总体标准偏差。
for i in range(len(x)): #12 * 471
for j in range(len(x[0])): #18 * 9
if std_x[j] != 0:
x[i][j] = (x[i][j] - mean_x[j]) / std_x[j]
##对于所有的数据,如果这一列的标准偏差不为0(实际上好像也不存在为0的,可能每一列都是NR的那个是0?),应该是为了严谨。对于每一个数据都要减去均值后除以标准差,完成归一化。
#这里是中心化和标准化处理,通过处理,得到了均值为0,标准差为1的服从正态分布的数据。可以使一些原来数据大小、量纲不同的数据,对结果的影响趋向一致。
x
import math
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))
#好像保留了20%的数据,自己做测试用。虽然说有test数据集,但是自己还是需要自己的test数据集。
##深度学习
dim = 18 * 9 + 1
w = np.zeros([dim, 1])
x = np.concatenate((np.ones([12 * 471, 1]), x), axis = 1).astype(float)###axis=1 表示对应行拼接。
learning_rate = 100
iter_time = 1000
adagrad = np.zeros([dim, 1])
eps = 0.0000000001
for t in range(iter_time):
loss = np.sqrt(np.sum(np.power(np.dot(x, w) - y, 2))/471/12)#rmse
if(t%100==0):
print(str(t) + ":" + str(loss))
gradient = 2 * np.dot(x.transpose(), np.dot(x, w) - y) #dim*1
adagrad += gradient ** 2
w = w - learning_rate * gradient / np.sqrt(adagrad + eps)
np.save('work/weight.npy', w)#保存文件
print(w)
#这一步真的很难。dim加了1,起到的作用是Y=wX+b中b的作用。
loss是最常见的均方根误差函数,除了一个478*12,应该是平均的。这个除不除感觉对结果影响不大的样子。
梯度下降用的是adagrad方法,就是要除以之前所有梯度的均方和。
eps是为了防止分母为0
这个学习速率和初始值如何设置,目前还不是很了解。可能还需要学习后面的课程。
#测试
testdata = pd.read_csv('work/hw1_data/test.csv', header = None, encoding = 'big5') #读文件。
test_data = testdata.iloc[:, 2:] #不要前两列的表项
test_data[test_data == 'NR'] = 0 #NR设为0
test_data = test_data.to_numpy()
test_x = np.empty([240, 18*9], dtype = float) #创建测试矩阵
for i in range(240):
test_x[i, :] = test_data[18 * i: 18* (i + 1), :].reshape(1, -1) #可以仿照训练集看变化
print('1',len(test_x))
print('2',len(test_x[0]))
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]
test_x = np.concatenate((np.ones([240, 1]), test_x), axis = 1).astype(float)#拼接与b相乘的常数项。
test_x
w = np.load('work/weight.npy')
ans_y = np.dot(test_x, w)
print('ans',ans_y)
import csv #将测试集结果写在excal表格中了。
with open('work/submit.csv', mode='w', newline='') as submit_file:
csv_writer = csv.writer(submit_file)
header = ['id', 'value']
print(header)
csv_writer.writerow(header)
for i in range(240):
row = ['id_' + str(i), ans_y[i][0]]
csv_writer.writerow(row)
print(row)
额 ,看懂答案对我来说已经很吃力了,但这确实是一种好的学习方法。碰到一个不认识的函数或者语法就去查,可能比去看PYTHON教学视频来的还要快。
这篇作业应该是最简单的,但是还是花了很久时间才看懂,甚至回去又看了一遍前几集视频。只能说,路还很长,再接再厉!