[机器学习100天][系列学习笔记]第1天:数据预处理(Data Preprocessing)

我深知尽管平时项目做得不少,但基本是面向GitHub、CSDN、StackOverflow编程,如果把我网一断,手撸快排都有些困难。
受人安利,得知机器学习100天系列教程,说是学习机器学习知识,在其前面还是有一些关于pandas与numpy的数据处理教程,可能我的数学功底吃透后续的机器学习原理还有些障碍,不过了解一些数据处理技巧对今后的学习也是大有裨益的嘛!
限于GitHub上的翻译内容有些分散,我在学习的过程中时常也会有些批注和代码注释,也没什么地方放就拿博客当笔记本好了。

今天第一天,我们要做的似乎是预测不同国家的人的购房意愿。
Day 1.jpg

第1天:数据预处理(Data Preprocessing)

第一步:导入需要的库

这两个是我们每次都需要导入的库。NumPy包含数学计算函数。Pandas用于导入和管理数据集。

import numpy as np
import pandas as pd

第二步:导入数据集

数据集通常是.csv格式。CSV文件以文本形式保存表格数据。文件的每一行是一条数据记录。我们使用Pandas的read_csv方法读取本地csv文件为一个数据帧。然后,从数据帧中制作自变量和因变量的矩阵和向量。

dataset = pd.read_csv('../datasets/Data.csv')
# 不包括最后一列的所有列
X = dataset.iloc[ : , :-1].values 
#取最后一列
Y = dataset.iloc[ : , 3].values
print("Step 2: Importing dataset")
print("X")
print(X)
print("Y")
print(Y)

结果如下:

X
[['France' 44.0 72000.0]
 ['Spain' 27.0 48000.0]
 ['Germany' 30.0 54000.0]
 ['Spain' 38.0 61000.0]
 ['Germany' 40.0 nan]
 ['France' 35.0 58000.0]
 ['Spain' nan 52000.0]
 ['France' 48.0 79000.0]
 ['Germany' 50.0 83000.0]
 ['France' 37.0 67000.0]]
Y
['No' 'Yes' 'No' 'No' 'Yes' 'Yes' 'No' 'Yes' 'No' 'Yes']

批注:第一时间看见[ : , :-1]和[ : , 3]还是有点慌的,尽管这是pandas中的方法,但Python中也有长得类似的切片索引,来回顾一下。(Python的基础知识不是很牢固)

Python切片索引

[x:y:z]是切片索引的意思,x是左端,y是右端,z是步长,在[x,y)区间从左到右每隔z取值,默认z为1可以省略z参数,省略x参数则是从头取,省略y则是取到尾。
步长的负号就是反向,从右到左取值。例如对

a=“python”
b=a[::-1]
print (b)
'nohtyp'

常见的用法有:对a = [0,1,2,3,4,5,6,7,8,9]
a[::-1]相当于倒序列表a;a[i:j]相当于将a中第i个元素取到j-1各元素形成一个新的列表;
还有一种类型是类似[:-1],代表从位置0到位置-1,-1是指从最后算起的第二个元素。

Pandas中loc和iloc函数

上面代码中其实并非切片索引,而是pandas中的iloc函数,用于提取行数据。pandas中还有loc函数,一并介绍。参考:Pandas中loc和iloc函数用法详解(源码+实例)

已知data为:
In[1]: data
Out[1]: 
    A   B   C   D
a   0   1   2   3
b   4   5   6   7
c   8   9  10  11
d  12  13  14  15

#取索引为'a'的行
In[2]: data.loc['a']
Out[2]:
A    0
B    1
C    2
D    3
 
#取第一行数据,索引为'a'的行就是第一行,所以结果相同
In[3]: data.iloc[0]
Out[3]:
A    0
B    1
C    2
D    3

In[4]:data.loc[:,['A']] #取'A'列所有行,多取几列格式为 data.loc[:,['A','B']]
Out[4]: 
    A
a   0
b   4
c   8
d  12
 
In[5]:data.iloc[:,[0]] #取第0列所有行,多取几列格式为 data.iloc[:,[0,1]]
Out[5]: 
    A
a   0
b   4
c   8
d  12


In[6]:data.loc[['a','b'],['A','B']] #提取index为'a','b',列名为'A','B'中的数据
Out[6]: 
   A  B
a  0  1
b  4  5
 
In[7]:data.iloc[[0,1],[0,1]] #提取第0、1行,第0、1列中的数据
Out[7]: 
   A  B
a  0  1
b  4  5

In[8]:data.loc[:,:] #取A,B,C,D列的所有行
Out[8]: 
    A   B   C   D
a   0   1   2   3
b   4   5   6   7
c   8   9  10  11
d  12  13  14  15
 
In[9]:data.iloc[:,:] #取第0,1,2,3列的所有行
Out[9]: 
    A   B   C   D
a   0   1   2   3
b   4   5   6   7
c   8   9  10  11
d  12  13  14  15

In[10]: data.loc[data['A']==0] #提取data数据(筛选条件: A列中数字为0所在的行数据)
Out[10]: 
   A  B  C  D
a  0  1  2  3

总结:iloc是一种完全基于位置的索引,loc是基于label的索引,什么意思呢?loc只看标签,就是上述的abcd与ABCD,iloc只看索引号,就是上述的0~3。
对[x,y],x的形式类似a:b,对iloc来说a,b只能是数字,表示取从a到b行,缺省代表从头取到尾。对loc来说a,b只能是标签,尽管标签有时可能也是数字形式,如

df
Out[4]: 
    a   b   c   d
0   0   1   2   3
1   4   5   6   7
2   8   9  10  11
3  12  13  14  15

df.loc[0:3,'a':'c']
Out[9]: 
    a   b   c
  0   1   2
  4   5   6
  8   9  10
 12  13  14

上面的0:3实际上并不是数字,而是行的label。

第三步:处理丢失数据

我们得到的数据很少是完整的。数据可能因为各种原因丢失,为了不降低机器学习模型的性能,需要处理数据。我们可以用整列的平均值或中间值替换丢失的数据。我们用sklearn.preprocessing库中的Imputer类完成这项任务。
批注:Anaconda的默认环境带了许多科学计算包,所以这套实验最好在Anaconda环境下进行。

from sklearn.preprocessing import Imputer
# axis=0表示按列进行
imputer = Imputer(missing_values = "NaN", strategy = "mean", axis = 0)
imputer = imputer.fit(X[ : , 1:3])
X[ : , 1:3] = imputer.transform(X[ : , 1:3])
print("---------------------")
print("Step 3: Handling the missing data")
print("step2")
print("X")
print(X)

Imputer函数主要用来填补缺失值,参数为sklearn.preprocessing.Imputer(missing_values=’NaN’, strategy=’mean’, axis=0, verbose=0, copy=True)

主要参数说明:
missing_values:缺失值,可以为整数或NaN(缺失值numpy.nan用字符串‘NaN’表示),默认为NaN

strategy:替换策略,字符串,默认用均值‘mean’替换
①若为mean时,用特征列的均值替换
②若为median时,用特征列的中位数替换
③若为most_frequent时,用特征列的众数替换
axis:指定轴数,默认axis=0代表列,axis=1代表行
copy:设置为True代表不在原数据集上修改,设置为False时,就地修改,存在如下情况时,即使设置为False时,也不会就地修改
①X不是浮点值数组
②X是稀疏且missing_values=0
③axis=0且X为CRS矩阵
④axis=1且X为CSC矩阵
statistics_属性:axis设置为0时,每个特征的填充值数组,axis=1时,报没有该属性错误statistics_属性:axis设置为0时,每个特征的填充值数组,axis=1时,报没有该属性错误

结果:

---------------------
Step 3: Handling the missing data
step2
X
[['France' 44.0 72000.0]
 ['Spain' 27.0 48000.0]
 ['Germany' 30.0 54000.0]
 ['Spain' 38.0 61000.0]
 ['Germany' 40.0 63777.77777777778]
 ['France' 35.0 58000.0]
 ['Spain' 38.77777777777778 52000.0]
 ['France' 48.0 79000.0]
 ['Germany' 50.0 83000.0]
 ['France' 37.0 67000.0]]

第四步:解析分类数据

分类数据指的是含有标签值而不是数字值的变量。取值范围通常是固定的。例如"Yes"和"No"不能用于模型的数学计算,所以需要解析成数字。为实现这一功能,我们从sklearn.preprocessing库导入LabelEncoder类。

from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X = LabelEncoder()  #实例化
X[ : , 0] = labelencoder_X.fit_transform(X[ : , 0])
#Creating a dummy variable
onehotencoder = OneHotEncoder(categorical_features = [0])
X = onehotencoder.fit_transform(X).toarray()
labelencoder_Y = LabelEncoder()
Y =  labelencoder_Y.fit_transform(Y)
print("---------------------")
print("Step 4: Encoding categorical data")
print("X")
print(X)
print("Y")
print(Y)

结果:


---------------------
Step 4: Encoding categorical data
X
[[1.00000000e+00 0.00000000e+00 0.00000000e+00 4.40000000e+01
  7.20000000e+04]
 [0.00000000e+00 0.00000000e+00 1.00000000e+00 2.70000000e+01
  4.80000000e+04]
 [0.00000000e+00 1.00000000e+00 0.00000000e+00 3.00000000e+01
  5.40000000e+04]
 [0.00000000e+00 0.00000000e+00 1.00000000e+00 3.80000000e+01
  6.10000000e+04]
 [0.00000000e+00 1.00000000e+00 0.00000000e+00 4.00000000e+01
  6.37777778e+04]
 [1.00000000e+00 0.00000000e+00 0.00000000e+00 3.50000000e+01
  5.80000000e+04]
 [0.00000000e+00 0.00000000e+00 1.00000000e+00 3.87777778e+01
  5.20000000e+04]
 [1.00000000e+00 0.00000000e+00 0.00000000e+00 4.80000000e+01
  7.90000000e+04]
 [0.00000000e+00 1.00000000e+00 0.00000000e+00 5.00000000e+01
  8.30000000e+04]
 [1.00000000e+00 0.00000000e+00 0.00000000e+00 3.70000000e+01
  6.70000000e+04]]
Y
[0 1 0 0 1 1 0 1 0 1]

这一步相当于起到数据规范化的作用,毕竟无意义的字符对计算没有用处。

第五步:拆分数据集为测试集合和训练集合

把数据集拆分成两个:一个是用来训练模型的训练集合,另一个是用来验证模型的测试集合。两者比例一般是80:20。我们导入sklearn.model_selection库中的train_test_split()方法。

from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split( X , Y , test_size = 0.2, random_state = 0)
print("---------------------")
print("Step 5: Splitting the datasets into training sets and Test sets")
print("X_train")
print(X_train)
print("X_test")
print(X_test)
print("Y_train")
print(Y_train)
print("Y_test")
print(Y_test)
---------------------
Step 5: Splitting the datasets into training sets and Test sets
X_train
[[  0.00000000e+00   1.00000000e+00   0.00000000e+00   4.00000000e+01
    6.37777778e+04]
 [  1.00000000e+00   0.00000000e+00   0.00000000e+00   3.70000000e+01
    6.70000000e+04]
 [  0.00000000e+00   0.00000000e+00   1.00000000e+00   2.70000000e+01
    4.80000000e+04]
 [  0.00000000e+00   0.00000000e+00   1.00000000e+00   3.87777778e+01
    5.20000000e+04]
 [  1.00000000e+00   0.00000000e+00   0.00000000e+00   4.80000000e+01
    7.90000000e+04]
 [  0.00000000e+00   0.00000000e+00   1.00000000e+00   3.80000000e+01
    6.10000000e+04]
 [  1.00000000e+00   0.00000000e+00   0.00000000e+00   4.40000000e+01
    7.20000000e+04]
 [  1.00000000e+00   0.00000000e+00   0.00000000e+00   3.50000000e+01
    5.80000000e+04]]
X_test
[[  0.00000000e+00   1.00000000e+00   0.00000000e+00   3.00000000e+01
    5.40000000e+04]
 [  0.00000000e+00   1.00000000e+00   0.00000000e+00   5.00000000e+01
    8.30000000e+04]]
Y_train
[1 1 1 0 1 0 0 1]
Y_test
[0 0]

第六步:特征量化

大部分模型算法使用两点间的欧氏距离表示,但此特征在幅度、单位和范围姿态问题上变化很大。在距离计算中,高幅度的特征比低幅度特征权重更大。可用特征标准化或Z值归一化解决。导入sklearn.preprocessing库的StandardScalar类。

from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
X_train = sc_X.fit_transform(X_train)
X_test = sc_X.transform(X_test)
print("---------------------")
print("Step 6: Feature Scaling")
print("X_train")
print(X_train)
print("X_test")
print(X_test)

---------------------
Step 6: Feature Scaling
X_train
[[-1.          2.64575131 -0.77459667  0.26306757  0.12381479]
 [ 1.         -0.37796447 -0.77459667 -0.25350148  0.46175632]
 [-1.         -0.37796447  1.29099445 -1.97539832 -1.53093341]
 [-1.         -0.37796447  1.29099445  0.05261351 -1.11141978]
 [ 1.         -0.37796447 -0.77459667  1.64058505  1.7202972 ]
 [-1.         -0.37796447  1.29099445 -0.0813118  -0.16751412]
 [ 1.         -0.37796447 -0.77459667  0.95182631  0.98614835]
 [ 1.         -0.37796447 -0.77459667 -0.59788085 -0.48214934]]
X_test
[[ 0.  0.  0. -1. -1.]
 [ 0.  0.  0.  1.  1.]]

数据预处理的作用是使得后续数据训练过程更快,梯度下降过程更加笔直,收敛更快性能因此也得到提升。因此,在下一步训练数据之前数据预处理是十分有必要的。

Last modification:January 26th, 2019 at 04:40 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment