2020年李宏毅老师的课程网址:http://speech.ee.ntu.edu.tw/~tlkagk/courses_ML20.html
李宏毅老师的2020课程内容,个人感觉非常的系统和全面,而且是从头开始,从最简单的开始,一步一步讲到最难的,所以也非常的推荐。
下面开始第一课作业的范例讲解:
题目是预测PM2.5的值
代码部分:
1、导入包
import sys
import pandas as pd
import numpy as np
导入pandas和numpy两个模块,这一部分比较直白就不多介绍了。
2、加载数据
data = pd.read_csv('./hw1/train.csv', encoding = 'big5')
两个参数分别是“文件路径”和“文件编码格式”,‘big5’指的是繁体中文编码,因为给的数据是TW那边的,所以必须是用big5来进行解码。(参数其实有很多,这里只用到这两个就够了,其他参数想学习可以去pandas的官网查看API手册)。
data是返回值,类型是DataFrame,这里将介绍这个数据类型的博客挂过来DataFrame基本知识介绍,有兴趣者自己查看。
3、无用数据去除
data = data.iloc[:, 3:] #iloc(行,列)
data[data == 'NR'] = 0
raw_data = data.to_numpy()
data.iloc[:, 3:]这一句的解释:
iloc(行号,列号),这个函数的功能是根据行号和列号提取内容。行号这里传递的参数是“:”说明data的行内容全部取出,列号传递的参数“3:”表明数据从3这个标号开始的列才拿出来,前面的0-3的列就全部去掉。
data[data == ‘NR’] = 0这一句的解释:
将数据中值为“NR”的数据全部赋值为0,去除特殊值。
raw_data = data.to_numpy()这一句的解释:
将处理好的DataFrame的数据变成一个numpy矩阵。事实证明raw_data = data.values这句话的效果和上面的这一句是一样的效果。
4、提取特征(1)
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来存储数据,先创建一个空字典,
外层循环针对的月份,效果是:{0:“数据”,1:“数据”,…,12:“数据”};
在开始内层循环之前,先使用empty()来创建一个空的数组sample,用来存放最后的数据。sample = np.empty([18,480])的参数是[18,480]就是要创建一个18行480列的数组来存放数据。18行的意思是每天的一个小时的数据有18个特征数据,480的意思是一天有24个小时,我们取得是每个月得前面20天,所以列数就是24*20==480。
内存循环的工作就是将个月的数据合成一个sample,sample[:, day * 24 :(day+1) * 24]中的“,”前面是":“表明行的内容全部都要,”,"后面的是列的内容,就是按照0-24-48-…这样将24小时的数据提取出来保存。
raw_data的数据是竖着排列的,所以raw_data[18 * (20 * month + day) : 18 * (20 * month + day+1), :]的“,”前面是0-18-36…这样取得。
一个月20天取完之后保存到month_data这个字典中。这样数据得取值就完成了。
5、特征提取(2)
预测得训练数据按照每9个小时为一组,
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:continuex[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]
这一步的工作内容为获取x和y这两个数据,就相当于得到训练的数据与目标的结果。
x的维数是[12471,189],最后的数据格式应该是行数代表的是按照9小时划分出来的这么多的训练数据,列的内容是每个小时的18项特征的的值。这便是训练集的输入参数。
y的维数是[12*471,1],代表和x对应的输入的PM2.5的数值,所以列数是1,就只是一个PM2.5的值。
整个循环其实就是遍历month_data字典将数据分割为9小时一组的训练数据。
这里的reshape(1,-1),就是将month_data[month][:,day * 24 + hour : day *24 + hour + 9]取出来的数据变换成1行的数据,列数的参数给-1,就是说列数让程序自己去算出来。
https://www.jianshu.com/p/fc2fe026f002这个是reshape()函数的介绍的博客,贴在这里。
y的值取0-9者10个小时中的最后一个小时的PM2.5的值。
6、Normalize 归一化
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])
mean_x = np.mean(x, axis=0)代码解释:
对x数据集中的每一列求平均值。
https://www.cnblogs.com/LBSer/p/4440590.html这个链接的内容解释了上面的一段代码上面一段采用的是标准差归一化。
7、train 训练
dim = 18 * 9 + 1 #维数
w = np.zeros([dim,1])
x = np.concatenate((np.ones([12 * 471, 1]), x), axis=1).astype(float)
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))if(t%100 == 0):print(str(t) + ":" + str(loss))gradient = 2 * np.dot(x.transpose(), np.dot(x,w) - y)adagrad += gradient ** 2w = w - learning_rate * gradient / np.sqrt(adagrad + eps)
np.save('weight.npy', w)
w
代码解释:
前面的比价容易理解,loss的计算方法应该是没有问题的,但是下面的梯度计算就优点看不懂,查了下资料,原来是使用的adagrad这个优化的方法,这个方法可以自动选择合适的学习速率这个参数。
计算的公式如这个链接https://blog.csdn.net/tsyccnh/article/details/76769232
接下来就是使用测试集来进行测试,
详解完毕!!!!
PS:后面的内容我在这里确实理解的不够彻底,如有疑问请留言!