机器学习-数据预处理
数据预处理是机器学习中很基本也是很重要的一步,数据处理是否得当对训练和预测结果影响非常大。
在工程实践中,我们得到的数据会存在有缺失值、重复值等,在使用之前需要进行数据预处理。数据预处理没有标准的流程,通常针对不同的任务和数据集属性的不同而不同。数据预处理的常用流程为:处理缺失值、属性编码、数据标准化正则化、特征选择、主成分分析。
首先,我们开始进行缺失值的处理,一般在读取数据某些特征时会有缺失值,如果缺失值过多基本上可以直接去除掉这一列,在缺失值不多的情况下我们可以用一些方法处理,比如插入0、平均值、中位数值等等,根据实际情况而定。
# 第一天数据预处理 from sklearn.preprocessing import Imputer,minmax_scale,LabelEncoder,OneHotEncoder
import pandas as pd # 数据读取 data = pd.read_csv('1day/dataSource/Data.csv', header=0) print(data) # 缺失值处理 #方法一 # imputer = Imputer(missing_values='NaN', strategy='mean', axis=0) # imputer = imputer.fit(data.iloc[:,1:3]) # data.iloc[:,1:3] = imputer.transform(data.iloc[:,1:3]) # print(data) #方法二 data['Age'].fillna(data['Age'].mean(), inplace=True) data['Salary'].fillna(data['Salary'].mean(), inplace=True) print(data)
Country Age Salary Purchased 0 France 44.0 72000.0 No 1 Spain 27.0 48000.0 Yes 2 Germany 30.0 54000.0 No 3 Spain 38.0 61000.0 No 4 Germany 40.0 NaN Yes 5 France 35.0 58000.0 Yes 6 Spain NaN 52000.0 No 7 France 48.0 79000.0 Yes 8 Germany 50.0 83000.0 No 9 France 37.0 67000.0 Yes Country Age Salary Purchased 0 France 44.000000 72000.000000 No 1 Spain 27.000000 48000.000000 Yes 2 Germany 30.000000 54000.000000 No 3 Spain 38.000000 61000.000000 No 4 Germany 40.000000 63777.777778 Yes 5 France 35.000000 58000.000000 Yes 6 Spain 38.777778 52000.000000 No 7 France 48.000000 79000.000000 Yes 8 Germany 50.000000 83000.000000 No 9 France 37.000000 67000.000000 Yes
这里列出了两种插入缺失值的方法,都是用的插入特征列的均值,还可以插入中位数、最大值、最小值等等都可以。
现在我们发现Country这列和Purchased不是数字类型不能直接用于训练计算,这里要进行处理成能够训练的格式,为实现这一功能,我们从sklearn.preprocessing库导入LabelEncoder类。
# 解析分类数据 labelEncoder = LabelEncoder() data['Purchased'] = labelEncoder.fit_transform(data['Purchased']) print(data)
Country Age Salary Purchased 0 France 44.000000 72000.000000 0 1 Spain 27.000000 48000.000000 1 2 Germany 30.000000 54000.000000 0 3 Spain 38.000000 61000.000000 0 4 Germany 40.000000 63777.777778 1 5 France 35.000000 58000.000000 1 6 Spain 38.777778 52000.000000 0 7 France 48.000000 79000.000000 1 8 Germany 50.000000 83000.000000 0 9 France 37.000000 67000.000000 1
现在Purchased已经ok了,接下来再把Country列的每个值当做一个特征列,用0,1表示是否是该值,我们用pandas中的get_dummies方法,该方法会把非数字的枚举列变成进行one-hot编码,结果如下
# 解析分类数据 labelEncoder = LabelEncoder() data['Purchased'] = labelEncoder.fit_transform(data['Purchased']) data = pd.get_dummies(data) print(data)
Age Salary Purchased Country_France Country_Germany Country_Spain 0 44.000000 72000.000000 0 1 0 0 1 27.000000 48000.000000 1 0 0 1 2 30.000000 54000.000000 0 0 1 0 3 38.000000 61000.000000 0 0 0 1 4 40.000000 63777.777778 1 0 1 0 5 35.000000 58000.000000 1 1 0 0 6 38.777778 52000.000000 0 0 0 1 7 48.000000 79000.000000 1 1 0 0 8 50.000000 83000.000000 0 0 1 0 9 37.000000 67000.000000 1 1 0 0
到这里就已经具备了训练数据的格式了,可以直接把数据和标签列放入训练模型里,但是在这里还要继续进行处理。
我们发现Age和Salary列的数字数量级差距很大,而且这两列的单位其实也是不一样的,对于数量级大的训练得到的参数权重会更大,这样会导致训练的结果仅仅与数量级越大的特征越密切,而且在训练过程中收敛的速度会比较慢,因为梯度下降可能会走不少弯路。
所以在这里我们要进行数据的归一化处理,让每个特征列的数据范围基本一致。
这里我们用到minmax_scale当然还有其它的归一化的方法,比如scale,standardscale,上代码
# 归一化处理 data_y = data['Purchased'] data_x = data.drop(['Purchased'], axis=1) data_x = minmax_scale(data_x) print(data_x)
[[0.73913043 0.68571429 1. 0. 0. ] [0. 0. 0. 0. 1. ] [0.13043478 0.17142857 0. 1. 0. ] [0.47826087 0.37142857 0. 0. 1. ] [0.56521739 0.45079365 0. 1. 0. ] [0.34782609 0.28571429 1. 0. 0. ] [0.51207729 0.11428571 0. 0. 1. ] [0.91304348 0.88571429 1. 0. 0. ] [1. 1. 0. 1. 0. ] [0.43478261 0.54285714 1. 0. 0. ]]
这个数据就比较标准了,最后在训练前的一步就是给数据拆分成训练集和测试集了,我们还是用sklearn里面的方法train_test_split
from sklearn.model_selection import train_test_split #... #中途省略上面有代码 #... # 拆分数据 train_x, test_x, train_y, test_y = train_test_split(data_x, data_y, test_size=0.3) print(train_x) print(train_y) print(test_x) print(test_y)
[[0.56521739 0.45079365 0. 1. 0. ] [0.73913043 0.68571429 1. 0. 0. ] [0.51207729 0.11428571 0. 0. 1. ] [1. 1. 0. 1. 0. ] [0.34782609 0.28571429 1. 0. 0. ] [0.43478261 0.54285714 1. 0. 0. ] [0.13043478 0.17142857 0. 1. 0. ]] 4 1 0 0 6 0 8 0 5 1 9 1 2 0 Name: Purchased, dtype: int64 [[0.91304348 0.88571429 1. 0. 0. ] [0.47826087 0.37142857 0. 0. 1. ] [0. 0. 0. 0. 1. ]] 7 1 3 0 1 1 Name: Purchased, dtype: int64