2020李宏毅深度学习hw1

2020李宏毅深度学习hw1

1、导入包

import sys
import pandas as pd
import numpy as np

2、加载数据

data = pd.read_csv('train.csv', encoding = 'big5')

两个参数分别是“文件路径”和“文件编码格式”,

‘big5’指的是繁体中文编码,因为给的数据是TW那边的,所以必须是用big5来进行解码。

3、无用数据去除

data = data.iloc[:, 3:] #iloc(行,列)

data.iloc[:, 3:]:
iloc(行号,列号),这个函数的功能是根据行号和列号提取内容。

行号传递的参数是“:”说明data的行内容全部取出,

列号传递的参数“3:”表明数据从3这个标号开始的列才拿出来,前面的0-3的列就全部去掉。

总结:取data中所有行的从第三列之后的所有列数

data[data == 'NR'] = 0

data[data == ‘NR’] = 0:
将数据中值为“NR”的数据全部赋值为0,去除特殊值。

raw_data = data.to_numpy()

raw_data = data.to_numpy():
将处理好的DataFrame的数据变成一个numpy矩阵。

事实证明raw_data = data.values这句话的效果和上面的这一句是一样的效果。

4、提取特征

month_data = {}
for month in range(12):  # month 从0-11 共12个月
    sample = np.empty([18, 480]) 
 # 返回一个18行480列的数组,用来保存一个月的数据(一个月只有20天,一天24个小时)
    for day in range(20):  # day从0-19 共20天
        sample[:, day * 24: (day + 1) * 24] = raw_data[18 * (20 * month + day): 18 * (20 * month + day + 1),:]
  		# 	raw的行每次取18行,列取全部列。
  		#	sample中(sample是18行480列)行给全部行,
  		#	列只给24列,然后列往后增加
    month_data[month] = sample

使用字典month_data来存储数据,先创建一个空字典

使用empty()来创建一个空的数组sample,用来存放最后的数据。

sample = np.empty([18,480])的参数是[18,480]就是要创建一个18行480列的数组来存放数据。

18行的意思是每天的一个小时的数据有18个特征数据,

480的意思是一天有24个小时,我们取得是每个月得前面20天,所以列数就是24*20==480。

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…这样取得。

5、特征提取

x = np.empty([12 * 471, 18 * 9],dtype=float)  
            # 一共480个小时,每9个小时一个数据(480列最后一列不可以计入,因为如果取到最后一行,
            # 那么最后一个数据便没有了结果{需要9个小时的输入和第10个小时的第10行作为结果}),
            # 480-1-9+1=471。471*12个数据集按行排列,每一行一个数据;
            # 数据是一个小时有18个特征,而每个数据9个小时,一共18*9列
y = np.empty([12 * 471, 1], dtype=float) 
	 		# 结果是471*12个数据,每个数据对应一个结果,即第10小时的PM2.5浓度
for month in range(12):  # month 0-11
    for day in range(20):  # day 0-19
        for hour in range(24):  # hour 0-23
            if day == 19 and hour > 14:  
   			  # 取到raw_data中的最后一块行为18,列为9的块之后,就不可以再取了,再取就会超过界限了
   			  #hour >14 表示每次取前9个小时,按滑动窗口方式依次向后滑动,当hour >14时,后面的列数就不够9列,所以不能>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)
            # 取对应month:行都要取,列取9个,依次进行,最后将整个数据reshape成一行数据
            #(列数无所谓)。然后赋给x,x内的坐标只是为了保证其从0-471*12

            y[month * 471 + day * 24 + hour, 0] = month_data[month][
                9, day * 24 + hour + 9] 
            # value,结果对应的行数一直是第9列(即第10行PM2.5)然后列数随着取得数据依次往后进行

这一步的工作内容为获取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) 
		 # 18 * 9 求均值,axis = 0表示对各列求均值,返回 1* 列数 的矩阵
std_x = np.std(x, axis=0)
		 # 18 * 9 求标准差,axis = 0表示对各列求均值,返回 1* 列数 的矩阵
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]  # 标准差归一化

mean_x = np.mean(x, axis=0)代码解释:
对x数据集中的每一列求平均值。

axis 不设置值,对 m*n 个数求均值,返回一个实数

axis = 0 : 压缩行,对各列求均值,返回 1*n矩阵

axis = 1 : 压缩列,对各行求均值,返回 m*1矩阵

https://www.cnblogs.com/LBSer/p/4440590.html 解释了上面的一段代码采用的是标准差归一化。

7、拆分训练集和验证集

​ 接下来是将训练数据按8:2拆成训练数据和验证数据。这样的好处是因为最终只给我们test data的输入而没有给我们输出,所以我们无法定量我们模型的好坏,而使用验证数据可以简单验证我们模型的好坏,让我们自己心里有数。

# 将训练数据拆成训练数据:验证数据=8:2,这样用来验证
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):, :]

8、train 训练2020李宏毅深度学习hw1_第1张图片2020李宏毅深度学习hw1_第2张图片2020李宏毅深度学习hw1_第3张图片

np.zeros([m,n]):返回一个全0的mn数组。
  np.ones([m,n]):返回一个全1的m
n维数组。
  np.concatenate((a,b),axis=1):a和b做行拼接,结果为[a,b]。
  np.dot(x,w):x和w点乘。
  np.power(x,n):x中各元素的n次方。
  np.sqrt(x):x中各元素的平方根。
  np.sum(x):x中所有元素的和,返回一个值。
  x.transpose():将x转置。

dim = 18 * 9 + 1 #参数:18*9个权重 + 1个偏置bias
w = np.zeros([dim, 1]) #参数列向量初始化为0
		#x新增一列用来与偏置bias相乘,将模型y=wx+b转化成y=[b,w]转置·[1,x]
x = np.concatenate((np.ones([12 * 471, 1]), x), axis=1).astype(float)  
    		# np.ones来生成12*471行1列的全1数组,np.concatenate,axis=1
    		#表示按列将两个数组拼接起来,即在x最前面新加一列内容,
    		#之前x是12*471行18*9列的数组,新加一列之后变为12*471行18*9+1列的数组
learning_rate = 100  # 学习率
iter_time = 10000  # 迭代次数
adagrad = np.zeros([dim, 1])  
			# 生成dim行即163行1列的数组,用来使用adagrad算法更新学习率
eps = 0.0000000001  
			# 因为新的学习率是learning_rate/sqrt(sum_of_pre_grads**2),
			#而adagrad=sum_of_grads**2,所以处在分母上而迭代时adagrad可能为0,
			#所以加上一个极小数,使其不除0
for t in range(iter_time):
    loss = np.sqrt(np.sum(np.power(np.dot(x, w) - y,
                                   2)) / 471 / 12)  
            # rmse loss函数是从0-n的(X*W-Y)**2之和/(471*12)再开根号,
            #即使用均方根误差(root mean square error),
            #具体可百度其公式,/471/12即/N(次数)
    if (t % 100 == 0):  # 每一百次迭代就输出其损失
        print(str(t) + ":" + str(loss))
    gradient = 2 * np.dot(x.transpose(), np.dot(x,w) - y)  
    		# dim*1 x.transpose即x的转置,后面是X*W-Y,即2*(x的转置*(X*W-Y))是梯度,
    		#具体可由h(x)求偏微分获得.最后生成1行18*9+1列的数组。转置后的X,其每一行是一个参数,
    		#与h(x)-y的值相乘之后是参数W0的修正值,
    		#同理可得W0-Wn的修正值保存到1行18*9+1列的数组中,即gradient
    adagrad += gradient ** 2  
    		# adagrad用于保存前面使用到的所有gradient的平方,进而在更新时用于调整学习率
    w = w - learning_rate * gradient / np.sqrt(adagrad + eps)  # 更新权重
np.save('weight.npy', w)  # 将参数保存下来

9、载入验证集进行验证

w = np.load('weight.npy')
		# 使用x_validation和y_validation来计算模型的准确率,因为X已经normalize了,
		#所以不需要再来一遍,只需在x_validation上添加新的一列作为bias的乘数即可
x_validation = np.concatenate((np.ones([1131, 1]), x_validation),axis=1).astype(float)
ans_y = np.dot(x_validation, w)
loss = np.sqrt(np.sum(np.power(ans_y - y_validation, 2)) / 1131)

print(loss)

10、预测testdata得到预测结果

testdata = pd.read_csv('./dataset/test.csv', header=None, encoding='big5')
test_data = testdata.iloc[:, 2:]  # 取csv文件中的全行数即第3列到结束的列数所包含的数据
test_data[test_data == 'NR'] = 0  # 将testdata中的NR替换为0
test_data = test_data.to_numpy()  # 将其转换为数组
test_x = np.empty([240, 18 * 9], dtype=float)  # 创建一个240行18*9列的空数列用于保存textdata的输入
for i in range(240):  # 共240个测试输入数据
    test_x[i, :] = test_data[18 * i: 18 * (i + 1), :].reshape(1, -1)
		# 下面是Normalize,且必须跟training data是同一种方法进行Normalize
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)  
		# 在test_x前面拼接一列全1数组,构成240行,163列数据


# 进行预测 
w = np.load('weight.npy')
ans_y = np.dot(test_x, w)  # test data的预测值ans_y=test_x与W的积



# 将预测结果填入文件当中
import csv

with open('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)

参考来源:

李宏毅深度学习课程作业hw1详解

李宏毅机器学习-第一课作业

李宏毅机器学习2020春季作业一hw1

你可能感兴趣的:(李宏毅机器学习作业,r语言,深度学习,python)