首先说一下为什么要做特征工程?总的来说机器学习算法就是用输入的数据来推算输出的数据。输入的数据包含以下特征,这些特征是以行列矩阵的列来表示,算法需要具有特定形式的特征作为输入才能更好地发挥作用,模型的表现才能达到最佳,所以我们要对输入的特征进行一些列的操作,这个过程就是特征工程。在这篇文章里我利用Python把主要的特征工程技术通过全代码的形式,给大家做一个分享。
首先是缺失值的处理
1、删除缺失值
缺失值是机器学习对真实世界数据进行处理时最常见问题之一。人为错误、数据流中断、隐私问题和其他因素可能是缺失值的原因。无论出于何种原因,缺失值都会影响机器学习模型的性能。一些机器学习平台在模型训练阶段会自动删除缺失值的行,这会因训练规模减少而降低模型性能。另一方面,大多数算法拒绝具有缺失值的数据集并返回错误。处理缺失值最直接的方法是删除行或整列。没有最优的丢弃标准,但可以以80%为例,将缺失值大于该比例的行和列丢弃。
threshold_value = 0.8
#将缺失值大于阈值的列删除
data = data[data.columns[data.isnull().mean() < threshold_value]]
#将缺失值大于阈值的行删除
data = data.loc[data.isnull().mean(axis=1) < threshold_value]
2、插补
在不影响数据体量的前提下处理缺失值就是插补。插补对于数字列来讲,常用的是数值插补和中位数插补,一般不推荐用平均值,因为平均值比较受离群值的影响。
#数值插补 data = data.fillna(0) # 中位值插补 data = data.fillna(data.median)
对于离散变量列,我们一般采用众数进行插补,如果该变量仅包含一个唯一值,那么建议使用“unkown”进行插补,这样最能体现随机性。
#众数插补
data['column_name'].fillna(data['column_name'].value_counts() .idxmax(), inplace=True)
这里我们还要重点说一下binning插补
使用binning的原因就是保证模型的鲁棒性和防止过拟合。但有得必有失,这种binning的方法是以模型表现的性能下降作为代价的。因为我们封装数据的过程对于模型而言就是一种信息的损失。
#数字列的binning data['bin'] = pd.cut(data['value'], bins=[0,30,70,100], labels=["Low", "Mid", "High"])
#离散变量列的binning
conditions = [ data['Country'].str.contains('Spain'), data['Country'].str.contains('Italy'), data['Country'].str.contains('Chile'), data['Country'].str.contains('Brazil')] choices = ['Europe', 'Europe', 'South America', 'South America'] data['Continent'] = np.select(conditions, choices, default='Other')
对于医学研究场景来讲我是推荐用上述插补方法的,别的插补方法还有很多,可能别的应用场景比较适用,这里就不讨论了。
离群值的处理
首先我想说明一下,离群值的检测最直接的方法是可视化,可以直观的发现离群值,这里我们采用了统计学的方法,是为了能迅速发现离群值。
1、标准差法发现离群值
这种方法是把标准差n倍以外的数据定义为离群值,这个n没有明确的规定,一般文献上都是选择2到4倍的标准差。
factor = 3 upper_limt = data['column'].mean () + data['column'].std () * factor lower_limt = data['column'].mean () - data['column'].std () * factor data = data[(data['column'].values < upper_limt) & (data['column'].values >lower_limt)]
也可以使用zscore,它标准化了数值到均值的距离
data[(np.abs(stats.zscore(data['column'])) < factor)]
2、百分位数法发现离群值
upper_lim = data['column'].quantile(.95) lower_lim = data['column'].quantile(.05) data = data[(data['column'].values < upper_limt) & (data['column'].values >lower_limt)]
log转换
log转换是特征工程中非常常用的转换,它具有以下优点
1)它有助于处理偏斜数据,变换后,分布变得更接近正态分布。
2)有利于数据的归一化。
3)减少异常值的影响,使得到的模型更加稳健。
log转换的技巧主要是对零和负值的处理,如果转换列含有零或者负值需要加上一个数才能进行log转换,不然会报错。一般我们采用加1或者归一化后加1的方法进行处理,下面是一个例子
data = pd.DataFrame({'value':[2,45, -23, 85, 28, 2, 35, -12]})
data['log'] = data['value'].transform(np.log)
data['log+1'] = (data['value']+1).transform(np.log)
data['log(x-min(x)+1)'] = (data['value']-data['value'].min()+1) .transform(np.log)
单热变量
单热变量的实质就是把分类变量的特征通过多列数值型数据的形式来表示出来,这样做的好处在于对于一些需要数值型变量作为输入的算法中可以尽量保留分类变量的信息不丢失。代码范式如下:
encoded = pd.get_dummies(data['column']) data = data.join(encoded).drop('column', axis=1)
数据缩放
数据缩放就是通过归一化和标准化来统一量纲,非常常用的一种特征工程的方法,目前很多算法已经不需要专门做数据缩放,但是一些涉及“距离”的算法比如:KNN,k-means,还是需要做的。
1、归一化
归一化是指把数据归一到0-1之间,归一化会加剧离群值的影响,一般建议做归一化前先处理离群值
data = pd.DataFrame({'feature':[2, 45, -23, 85, 28, 2, 35, -12]})
data['normalized'] = (data['feature'] - data['feature'].min()) / (data['feature'].max() - data['feature'].min())
2、标准化
标准化也叫zscore归一化,是比较常用的数据缩放方法,这里不多说了,计算方法如下
data = pd.DataFrame({'feature':[2,45, -23, 85, 28, 2, 35, -12]}) data['standardized'] = (data['feature'] - data['feature'].mean()) / data['feature'].std()
以上就是特征工程常用的处理技巧,大家在实战中可以选择性使用。