网站首页 > 技术文章 正文
可以说,开发机器学习模型的两个最重要的步骤是特征工程和预处理。特征工程包括特征的创建,而预处理涉及清理数据。
折磨数据,它会坦白任何事情。 - 罗纳德科斯
我们经常花费大量时间将数据精炼成对于建模有用的东西。为了使这项工作更有效,我想分享四个技巧,可以帮助你进行特征工程和预处理。
要注意到,领域知识是特征工程时最重要的事情之一(陈词滥调)。更好地了解你使用的特征可以帮助防止陷入欠拟合和过拟合的情况
本链接是特征工程分析的笔记(https://github.com/MaartenGr/feature-engineering)。
1. 重新采样不平衡数据
实际上,我们经常会遇到不平衡的数据。如果目标数据只有轻微的不平衡,这并不一定是一个问题。可以通过对数据使用适当的验证措施来解决这个问题,比如平衡精度(Balanced Accuracy)、精确召回曲线(Precision-Recall Curves)或F1分数(F1-score)。
不幸的是,情况并非总是如此,目标变量可能非常不平衡(例如,10:1)。这种情况下,我们可以对该少数类(即样本数少的类别)进行过采样,以便使用一种称为SMOTE的技术来引入平衡。
SMOTE
SMOTE(https://jair.org/index.php/jair/article/view/10302)是合成少数类过采样技术 (Synthetic Minority Oversampling Technique)的缩写,是一种用于增加少数类样本的过采样技术。
它通过观察目标的特征空间和检测最近邻来生成新的样本。然后,在相邻样本的特征空间内,简单地选择相似的样本,每次随机地改变一列。
要实现SMOTE的模块可以在imbalanced-learn包(https://imbalanced-learn.readthedocs.io/en/stable/index.html)中找到。导入该包并使用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包(https://imbalanced-learn.readthedocs.io/en/stable/index.html)中找到。
附加提示2:确保在训练集与测试集分割之后进行过采样,并且只对训练数据进行过采样。因为通常不在合成数据上测试模型的性能。
2. 创建新的特征
为了提高模型的质量和预测能力,经常从现有变量中创建新特征。我们可以在每对变量之间创建一些交互(例如,乘法或除法),希望找到一个有趣的新特征。然而,这是一个漫长的过程,需要大量的编码。幸运的是,这可以使用深度特征综合(Deep Feature Synthesis)自动完成。
深度特征综合
深度特征综合(DFS)是一种能够快速创建具有不同深度的新变量的算法。例如,不仅可以对列进行相乘,你也可以选择先将列A与列B相乘,然后再添加列C。
首先,让我介绍将用于示例的数据。我选择使用人力资源分析数据(https://www.kaggle.com/lnvardanyan/hr-analytics)分析数据,因为这些特征很容易解释:
简单地根据我们的直觉,我们可以将 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最大的优点是它可以进行表之间的聚合中创建新的变量。有关示例,请参见此链接(https://docs.featuretools.com/loading_data/using_entitysets.html)。
附加技巧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:有一个扩展版的Isolation Forest(https://github.com/sahandha/eif)可用,它改进了一些缺点。然而,评论褒贬不一(https://towardsdatascience.com/outlier-detection-with-extended-isolation-forest-1e248a3fe97b)。
结论
希望本文中的技巧能够帮助你设计和预处理这些特征,Jupyter写的笔记在本链接(https://github.com/MaartenGr/feature-engineering/blob/master/Engineering%20Tips.ipynb)
猜你喜欢
- 2024-10-11 sklearn分类模型汇总 sklearn svm分类
- 2024-10-11 一款小众但实用的自动化特征选择工具:AutoFeatSelect
- 2024-10-11 基于决策树算法完成鸢尾花的分类并使用scikit-learn进行交叉验证
- 2024-10-11 「程序员」如何5分钟掌握,pandas数据累计与分组?
- 2024-10-11 Python 机器学习 特征降维 python tsne降维
- 2024-10-11 mooc机器学习第七天-分类支持向量机svm.svc
- 2024-10-11 模型选择之交叉验证(简单交叉验证、S折交叉验证和留一交叉验证)
- 2024-10-11 I2C七宗罪之第二罪 七宗罪二哥
- 2024-10-11 PCA 主成分分析 PCA主成分分析实现鸢尾花数据集分类-MATLAB代码
- 2024-10-11 Python实现机器学习算法——随机森林
你 发表评论:
欢迎- 最近发表
-
- 在 Spring Boot 项目中使用 activiti
- 开箱即用-activiti流程引擎(active 流程引擎)
- 在springBoot项目中整合使用activiti
- activiti中的网关是干什么的?(activiti包含网关)
- SpringBoot集成工作流Activiti(完整源码和配套文档)
- Activiti工作流介绍及使用(activiti工作流会签)
- SpringBoot集成工作流Activiti(实际项目演示)
- activiti工作流引擎(activiti工作流引擎怎么用)
- 工作流Activiti初体验及在数据库中生成的表
- Activiti工作流浅析(activiti6.0工作流引擎深度解析)
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)