前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >文末福利|特征工程与数据预处理的四个高级技巧

文末福利|特征工程与数据预处理的四个高级技巧

作者头像
磐创AI
修改2019-08-26 16:36:19
1.2K0
修改2019-08-26 16:36:19
举报

折磨数据,它会坦白任何事情。- 罗纳德科斯

用于创建新特征,检测异常值,处理不平衡数据和估算缺失值的技术可以说,开发机器学习模型的两个最重要的步骤是特征工程和预处理。特征工程包括特征的创建,而预处理涉及清理数据。

我们经常花费大量时间将数据精炼成对于建模有用的东西。为了使这项工作更有效,我想分享四个技巧,可以帮助你进行特征工程和预处理。用于创建新特征,检测异常值,处理不平衡数据和估算缺失值的技术可以说,开发机器学习模型的两个最重要的步骤是特征工程和预处理。特征工程包括特征的创建,而预处理涉及清理数据。

要注意到,领域知识是特征工程时最重要的事情之一(陈词滥调)。更好地了解你使用的特征可以帮助防止陷入欠拟合和过拟合的情况

本链接(https://github.com/MaartenGr/feature-engineering)是特征工程分析的笔记。

1. 重新采样不平衡数据

实际上,我们经常会遇到不平衡的数据。如果目标数据只有轻微的不平衡,这并不一定是一个问题。可以通过对数据使用适当的验证措施来解决这个问题,比如平衡精度(Balanced Accuracy)精确召回曲线(Precision-Recall Curves)F1分数(F1-score)

不幸的是,情况并非总是如此,目标变量可能非常不平衡(例如,10:1)。这种情况下,我们可以对该少数类(即样本数少的类别)进行过采样,以便使用一种称为SMOTE的技术来引入平衡。

SMOTE

SMOTE^SMOTE是合成少数类过采样技术 (Synthetic Minority Oversampling Technique)的缩写,是一种用于增加少数类样本的过采样技术。

它通过观察目标的特征空间和检测最近邻来生成新的样本。然后,在相邻样本的特征空间内,简单地选择相似的样本,每次随机地改变一列。

要实现SMOTE的模块可以在imbalanced-learn包^imbalanced-learn中找到。导入该包并使用fit_transform方法:

import pandas as pd
from imblearn.over_sampling import SMOTE

# 导入数据创建x和y
df = pd.read_csv('creditcard_small.csv')
X = df.iloc[:,:-1]
y = df.iloc[:,-1].map({1:'Fraud', 0:'No Fraud'})

# 重新采样数据
X_resampled, y_resampled = SMOTE(sampling_strategy={"Fraud":1000}).fit_resample(X, y)
X_resampled = pd.DataFrame(X_resampled, columns=X.columns)

正如你所看到的,模型成功地对目标变量进行了过采样。当使用SMOTE进行过采样时,可以采用以下几种策略:

  • “少数类(minority)”:仅重采样少数类;
  • “非少数类(not minority)”:重新采样除少数类以外的其他类;
  • “非多数类(not majority)”:重新采样除了多数类的其他类;
  • '所有(all)':重新采样所有类;
  • "词典(dict)":键为目标类,值对应于每个目标类所需的样本数量。

我选择使用字典来指定我想要在多大程度上过采样数据。

附加提示1:如果数据集中有分类变量,那么可能会为那些不能发生的变量创建值。例如,如果有一个名为isMale的变量,它只能是0或1,SMOTE可能会创建0.365作为值。

这种情况下,可以使用SMOTENC,它考虑到了分类变量的性质。这个版本也可以在imbalanced-learn^imbalanced-learn包中找到。

附加提示2:确保在训练集与测试集分割之后进行过采样,并且只对训练数据进行过采样。因为通常不在合成数据上测试模型的性能。

2. 创建新的特征

为了提高模型的质量和预测能力,经常从现有变量中创建新特征。我们可以在每对变量之间创建一些交互(例如,乘法或除法),希望找到一个有趣的新特征。然而,这是一个漫长的过程,需要大量的编码。幸运的是,这可以使用深度特征综合(Deep Feature Synthesis)自动完成。

深度特征综合

深度特征综合(DFS)是一种能够快速创建具有不同深度的新变量的算法。例如,不仅可以对列进行相乘,你也可以选择先将列A与列B相乘,然后再添加列C。

首先,让我介绍将用于示例的数据。我选择使用人力资源分析数据^人力资源分析数据,因为这些特征很容易解释:

简单地根据我们的直觉,我们可以将 average_monthly_hours 除以number_project的值添加为一个新变量。然而,如果我们只跟着直觉,我们可能会错过很多的关系。

如果你的数据如果是一个简单的表格,你可以简单地按照下面的代码:

import featuretools as ft
import pandas as pd

# 创建实体
turnover_df = pd.read_csv('turnover.csv')
es = ft.EntitySet(id = 'Turnover')
es.entity_from_dataframe(entity_id = 'hr', dataframe = turnover_df, index = 'index')

# 指定trans_primitives参数以执行深度特征综合
feature_matrix, feature_defs = ft.dfs(entityset = es, target_entity = 'hr',
                                      trans_primitives = ['add_numeric', 'multiply_numeric'], 
                                      verbose=True)

第一步是创建一个实体(entity),如果需要,可以从这个实体与其他表创建关系。接下来,我们可以简单地运行ft.dfs来创建新变量。我们指定参数trans_primitives来表示以什么方式创建变量。这里我们选择将数值变量相加或相乘。

正如你在上面的图中所看到的,我们仅使用几行代码就创建了另外668个特征。创建的一些特征示例:

  • last_evaluate乘以satisfaction_level
  • left乘以promotion_last_5years
  • average_monthly_hours乘以satisfaction_level加上time_spend_company

附加技巧1:注意这里的实现是比较简单基础的。DFS最大的优点是它可以进行表之间的聚合中创建新的变量。有关示例,请参见此链接^链接。

附加技巧2:运行ft.list_primitives(),以查看可以执行的聚合的完整列表。它甚至处理时间戳(timestamps)、空值(null values)和经纬度信息(long/lat information)。

3. 处理缺失值

像往常一样,没有一种处理缺失值的最佳方法。根据你的数据,只需用特定组的平均值或模式填充它们就足够了。然而,有一些高级技术使用数据的已知部分来估算(impute)缺失的值。 其中一种方法来自Scikit-Learn中的一个新包叫做Iterative Imputer,它是基于R语言(MICE包)来估算缺失的变量。

Iterative Imputer(迭代输入器)

虽然python是开发机器学习模型的一种很好的语言,但是仍然有很多方法在R中工作得更好。

Iterative Imputer是由Scikit-Learn开发的,它将每个缺失值的特征作为其他特征的函数来建模。它使用该函数的值作为估算。在每个步骤中,选择一个特征作为输出y,其他所有特征作为输入的X。然后在X和y上训练一个回归器,用来预测y的缺失值。

让我们看一个例子。我使用的数据是著名的titanic数据集。在这个数据集中,Age列缺少我们希望填充的值。代码总是很简单:

# 显示的导入enable_iterative_imputer后
# 再从sklearn.impute 导入IterativeImputer
from sklearn.experimental import enable_iterative_imputer  
from sklearn.impute import IterativeImputer

from sklearn.ensemble import RandomForestRegressor
import pandas as pd

# 载入数据
titanic = pd.read_csv("titanic.csv")
titanic = titanic.loc[:, ['Pclass', 'Age', 'SibSp', 'Parch', 'Fare']]

# 使用随机森林估计器
imp = IterativeImputer(RandomForestRegressor(), max_iter=10, random_state=0)
titanic = pd.DataFrame(imp.fit_transform(titanic), columns=titanic.columns)

这种方法的优点是它允许使用你所选择的估计器(estimator)。我使用随机森林作为估计器来模拟在R中经常使用的missForest。

附加提示1:如果你有足够的数据,那么简单地删除缺少数据的示例可能是一个有吸引力的选项。但是,请记住,它可能会在你的数据中产生误差,因为丢失的数据可能遵循了你错过的模式。

附加提示2:Iterative Imputer允许使用不同的估计器。经过一些测试,我发现甚至可以使用Catboost作为估计器!不幸的是,LightGBM和XGBoost不能工作,因为它们的随机状态名(random state name)不同。

4. 异常值检测

如果不能很好地理解数据,就很难检测出异常值。如果你很了解数据,那么你可以很容易地指定数据还具有意义的阈值。

有时这是不可能的,因为很难完全理解数据。这种情况下,你可以使用离群点检测算法,比如流行的Isolation Forest

Isolation Forest

在Isolation Forest算法中,关键字是Isolation(孤立)。从本质上说,该算法检查了样本是否容易被分离。这样样本就产生了一个孤立编号,这个孤立编号由随机决策树中孤立该样本所需的分割数来计算。这个孤立编号在所有生成的树上进行平均。

如果算法只需要做几次分割就能找到一个样本,那么该样本更有可能是一个异常样本。分割本身也是随机划分的,这样异常样本在树中往往很浅(节点到根节点的路径长度短)。因此,当孤立编号在所有树中都很小时,该样本很可能是异常的。

为了展示一个例子,我再次使用了我们之前使用的信用卡数据集:

from sklearn.ensemble import IsolationForest
import pandas as pd
import seaborn as sns

# 预测和可视化离群点
credit_card = pd.read_csv('creditcard_small.csv').drop("Class", 1)
clf = IsolationForest(contamination=0.01, behaviour='new')
outliers = clf.fit_predict(credit_card)
sns.scatterplot(credit_card.V4, credit_card.V2, outliers, palette='Set1', legend=False)

附加提示1:有一个扩展版的IsolationForest可用,它改进了一些缺点。然而,评论褒贬不一。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 磐创AI 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 重新采样不平衡数据
    • SMOTE
    • 2. 创建新的特征
      • 深度特征综合
      • 3. 处理缺失值
        • Iterative Imputer(迭代输入器)
        • 4. 异常值检测
          • Isolation Forest
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档