初学python和机器学习,此文的写作目的仅仅是日常学习笔记。
code以及详细参考:https://blog.csdn.net/iteapoy/article/details/105431738
import numpy as np
import sys
import pandas as pd
#读入train.csv,繁体字以big5为编码, 用pandas库读取csv文件
data = pd.read_csv('./train.csv', encoding = 'big5')
#显示前20行
data.head(3)
第1列是日期,第2列是观测站所在地,第3列是观测指标,第4列-第27列是0-23共24小时。
data.shape
Out:
(4320, 27)
数据规格为:4320行(12个月每个月前20天18个观测指标),27列(日期+观测地点+观测指标+24个小时)
MAC同时打开多个终端快捷键:control+N
终端输入:pip list
查看pandas版本为:0.23.4
更新pandas版本:
第一步:卸载pandas旧版本
pip3 uninstall pandas
第二步:下载最新版本:https://pypi.org/project/pandas
说明:由于python默认源是国外的,所以下载可能会出现很慢的情况,这里我建议直接切换镜像源下载
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -U pandas
这个命令的意思是指定在https://pypi.tuna.tsinghua.edu.cn/simple网站 下载pandas的包
解释一下上面的-U 和-i
-U:安装升级
-i:指定源
第三步:更新成功后需关闭jupyter后重新打开即可
# 丢弃前两列,需要的是从第三列开始的数值
data = data.iloc[:, 3:]
# 把降雨的NR字符变成数值0
data[data == 'NR'] = 0
# 把dataframe转换成numpy的数组
raw_data = data.to_numpy()
raw_data
4320行中,每18行(18个观测指标)是一天的数据,将18行作为一天,4320/18=240天(一年12个月,每个月20天),根据每个月将4320行×24列的数据分成12 组18 行(features) × 480 列(hours) 的数据:
(18行为18个特征值,480列为连续的480个小时:20*24)
month_data = {}
for month in range(12):#12组
sample = np.empty([18, 480])
for day in range(20):#20天
sample[:, day * 24 : (day + 1) * 24] = raw_data[18 * (20 * month + day) : 18 * (20 * month + day + 1), :]
month_data[month] = sample
分成了12个月,每个月有18行×480列的数据。
对于每个月,每10个小时分成一组,由前9个小时的数据来预测第10个小时的PM2.5,把前9小时的数据放入x,把第10个小时的数据放入y。窗口的大小为10,从第1个小时开始向右滑动,每次滑动1小时。因此,每个月都有471组这样的数据。
把一组18×9的数据平铺成一行向量,然后放入x的一行中,每个月有471组,共有12×471组向量,因此x有12×471行,18×9列。
将预测值放入y中,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) #vector dim:18*9 (9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9)
y[month * 471 + day * 24 + hour, 0] = month_data[month][9, day * 24 + hour + 9] #value
print(x)
print(y)
out:
[[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.]]
x = ( x − μ ) / σ x = (x - μ)/σ x=(x−μ)/σ
μ是xx的均值,σσ是xx的标准差。通过标准化,可以:将有量纲的表达式,经过变换,化为无量纲的表达式,成为标量使得数据更加符合独立同分布条件
'''
mean() 函数定义:
numpy.mean(a, axis, dtype, out,keepdims )
mean()函数功能:求取均值
经常操作的参数为axis,以m * n矩阵举例:
axis 不设置值,对 m*n 个数求均值,返回一个实数
axis = 0:压缩成行,对各列求均值,返回 1* n 矩阵
axis =1 :压缩成列,对各行求均值,返回 m *1 矩阵
np.std()是用来计算标准差
'''
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]
x
这里每一列是一个观测指标,按列进行标准化。
把训练数据分成训练集train_set和验证集validation,其中train_set用于训练,而validation不会参与训练,仅用于验证。(在baseline中并没有用)
import math
#`Math.floor()` 返回小于或等于一个给定数字的最大整数。
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))
[[-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
Adagrad
和上图不同处: 下面Loss的代码用到的是 Root Mean Square Error
因为存在常数项b,所以维度(dim)需要多加一列;eps项是极小值,避免adagrad的分母为0.
每一个维度(dim)会对应到各自的gradient和权重w,通过一次次的迭代(iter_time)学习。最终,将训练得到的模型(权重w)存储为.npy格式的文件。
dim = 18 * 9 + 1
w = np.zeros([dim, 1])
'''
numpy提供了numpy.concatenate((a1,a2,...), axis=0)函数。能够一次完成多个数组的拼接。其中a1,a2,...是数组类型的参数
>>> a=np.array([[1,2,3],[4,5,6]])
>>> b=np.array([[11,21,31],[7,8,9]])
>>> np.concatenate((a,b),axis=0)
array([[ 1, 2, 3],
[ 4, 5, 6],
[11, 21, 31],
[ 7, 8, 9]])
>>> np.concatenate((a,b),axis=1) #axis=1表示对应行的数组进行拼接
array([[ 1, 2, 3, 11, 21, 31],
[ 4, 5, 6, 7, 8, 9]])
'''
x = np.concatenate((np.ones([12 * 471, 1]), x), axis = 1).astype(float)
learning_rate = 100
iter_time = 1000
'''
用法:zeros(shape, dtype=float, order='C')
返回:返回来一个给定形状和类型的用0填充的数组;
参数:shape:形状
dtype:数据类型,可选参数,默认numpy.float64
order:可选参数,c代表与c语言类似,行优先;F代表列优先
'''
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))
#Numpy中dot()函数主要功能有两个:**向量点积和矩阵乘法**。
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('weight.npy', w)
w
# 读入测试数据test.csv
testdata = pd.read_csv('./test.csv', header = None, encoding = 'big5')
# 丢弃前两列,需要的是从第3列开始的数据
test_data = testdata.iloc[:, 2:]
# 把降雨为NR字符变成数字0
test_data[test_data == 'NR'] = 0
# 将dataframe变成numpy数组
test_data = test_data.to_numpy()
# 将test数据也变成 240 个维度为 18 * 9 + 1 的数据。
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)
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
out:
array([[ 1. , -1.19914238, -1.35883937, ..., 0.73508789,
0.73411671, 0.54674825],
[ 1. , -1.67647517, -1.67694799, ..., 0.36022341,
0.82780412, -0.20328266],
[ 1. , -2.18563014, -1.67694799, ..., 0.82880401,
0.0783049 , -0.29703653],
...,
[ 1. , -1.67647517, -1.8360023 , ..., 0.07907505,
-0.10906991, -1.04706744],
[ 1. , -1.35825331, -1.51789368, ..., -0.10835719,
0.35936711, 0.07797893],
[ 1. , -1.8355861 , -1.8360023 , ..., -1.04551839,
-1.13963133, -1.14082131]])
载入模型即可对test数据进行预测,得到预测值ans_y。
w = np.load('weight.npy')
ans_y = np.dot(test_x, w)
ans_y
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)
以上,baseline已完成,需要在baseline的基础上优化模型。优化模型这一部分就不在这里赘述了,我会另开一篇博客,记录我优化模型的几个过程。