特征工程与数据预处理全解析:基础技术和代码示例

在机器学习和数据科学的世界里,数据的质量是建模成功与否的关键所在。这就是特征工程和数据预处理发挥作用的地方。本文总结的这些关键步骤可以显著提高模型的性能,获得更准确的预测,我们将深入研究处理异常值、缺失值、编码、特征缩放和特征提取的各种技术。

异常值

异常值是数据集中与其他观测值显著不同的数据点。它们可能是由测量误差、罕见事件或仅仅是数据自然变化的一部分引起的。识别和处理异常值是至关重要的,因为它们会扭曲统计分析并对模型性能产生负面影响。

有几种方法可以检测异常值:

1、视觉方法:箱形图、散点图、直方图

2、统计方法:

Z-score: Z-score > 3或< -3的点通常被认为是异常值。

四分位间距(IQR):低于Q1-1.5 * IQR或高于Q3 + 1.5 *IQR的数据点通常被视为异常值。

3、机器学习方法:孤立森林、单类SVM、局部离群因子(LOF)

而最常用的方法之一是使用四分位间距(IQR)方法

 defoutlier_thresholds(dataframe, col_name, q1=0.25, q3=0.75):quartile1=dataframe[col_name].quantile(q1)quartile3=dataframe[col_name].quantile(q3)interquantile_range=quartile3-quartile1up_limit=quartile3+1.5*interquantile_rangelow_limit=quartile1-1.5*interquantile_rangereturnlow_limit, up_limitdefcheck_outlier(dataframe, col_name):low_limit, up_limit=outlier_thresholds(dataframe, col_name)ifdataframe[(dataframe[col_name] >up_limit) | (dataframe[col_name] <low_limit)].any(axis=None):returnTrueelse:returnFalse

该函数计算IQR并将异常值定义为低于Q1-1.5 * IQR或高于Q3 + 1.5 * IQR的数据点。这个方法简单快速,效果也很好。

异常值处理

1、删除离群值

删除异常值是一种直截了当的方法,但应该谨慎行事。只有在以下情况下才考虑删除:

  • 确定异常值是由于数据错误造成的。
  • 数据集足够大,删除几个点不会显著影响你的分析。
  • 异常值不能代表正在研究的人群。

删除方法也很简单:

 def remove_outlier(dataframe, col_name):low_limit, up_limit = outlier_thresholds(dataframe, col_name)df_without_outliers = dataframe[~((dataframe[col_name] < low_limit) | (dataframe[col_name] > up_limit))]return df_without_outliers

2、带阈值的重新分配

可以将这些值限制在某个阈值,而不是删除。这种方法也被称为winsorization。

以下是使用threshold重新赋值的代码示例:

 def replace_with_thresholds(dataframe, variable):low_limit, up_limit = outlier_thresholds(dataframe, variable)dataframe.loc[(dataframe[variable] < low_limit), variable] = low_limitdataframe.loc[(dataframe[variable] > up_limit), variable] = up_limit

多元离群分析:局部离群因子

LOF算法:图像中的A点比其邻近点的密度更稀疏,距离更远。在这种情况下,可以说点A是一个异常值。

LOF是一种通过测量数据点相对于其邻居的局部偏差来识别异常值的算法。LOF将一个点的局部密度与其相邻点的局部密度进行比较,从而识别出密度明显低于相邻点的样本。

以下是多元离群分析的代码示例:

 from sklearn.neighbors import LocalOutlierFactordef detect_outliers_lof(data, n_neighbors=20):lof = LocalOutlierFactor(n_neighbors=n_neighbors, contamination='auto')outlier_labels = lof.fit_predict(data)return outlier_labels == -1  # True for outliers, False for inliers

缺失值

缺失值是现实世界数据集中常见的问题,处理丢失数据时要考虑的一个重要问题是丢失数据的随机性。

在Python中,你可以使用pandas轻松检测缺失值:

 def missing_values_table(dataframe, na_name=False):na_columns = [col for col in dataframe.columns if dataframe[col].isnull().sum() > 0]n_miss = dataframe[na_columns].isnull().sum().sort_values(ascending=False)ratio = (dataframe[na_columns].isnull().sum() / dataframe.shape[0] * 100).sort_values(ascending=False)missing_df = pd.concat([n_miss, np.round(ratio, 2)], axis=1, keys=['n_miss', 'ratio'])print(missing_df, end="\n")if na_name:return na_columns

缺失值处理

1、删除缺失值:如果缺失值的数量相对于数据集大小较小,则删除可能是一种有效的策略。

 def remove_missing(df, threshold=0.7):return df.dropna(thresh=int(threshold*len(df)), axis=1).dropna()

2、用简单的方法填充

简单的插值方法包括用均值、中位数或众数填充:

 def simple_impute(dataframe):cat_cols = [col for col in dataframe.columns if dataframe[col].dtypes == "O"]num_but_cat = [col for col in dataframe.columns if dataframe[col].nunique() < cat_th anddataframe[col].dtypes != "O"]cat_but_car = [col for col in dataframe.columns if dataframe[col].nunique() > car_th anddataframe[col].dtypes == "O"]cat_cols = cat_cols + num_but_catcat_cols = [col for col in cat_cols if col not in cat_but_car]num_cols = [col for col in dataframe.columns if dataframe[col].dtypes != "O"]num_cols = [col for col in num_cols if col not in num_but_cat]df[num_cols] = df[num_cols].fillna(df[num_cols].median())df[cat_cols] = df[cat_cols].fillna(df[cat_cols].mode().iloc[0])return df

3、分类变量分解中的值

对于数值变量,可以根据相关分类变量的平均值或中位数填充缺失值:

 def categorical_impute(df, col_1, col_2, method="mean"):df[col_1].fillna(df.groupby(col_2)[col_1].transform(method))return df

4、预测赋值填充

KNN Imputer (K-Nearest Neighbors Imputer)是一种处理数据集中缺失数据的方法:

它基于k近邻算法。对于每个缺失值的样本,它找到K个最相似的完整样本。然后使用这些邻居的值来估计和填充缺失的数据。输入值通常是相邻值的平均值或中值。当丢失的数据不是随机的并且依赖于其他特征时,它特别有用。

KNN Imputer比mean或median imputation等简单的imputation方法更准确,特别是对于特征之间的关系很重要的数据集。但是对于大型数据集来说,它的计算成本很高。

 from sklearn.impute import KNNImputerdef knn_impute(dataframe, n_neighbors=5):cat_cols = [col for col in dataframe.columns if dataframe[col].dtypes == "O"]num_but_cat = [col for col in dataframe.columns if dataframe[col].nunique() < cat_th anddataframe[col].dtypes != "O"]cat_but_car = [col for col in dataframe.columns if dataframe[col].nunique() > car_th anddataframe[col].dtypes == "O"]cat_cols = cat_cols + num_but_catcat_cols = [col for col in cat_cols if col not in cat_but_car]num_cols = [col for col in dataframe.columns if dataframe[col].dtypes != "O"]num_cols = [col for col in num_cols if col not in num_but_cat]df = pd.get_dummies(dataframe[cat_cols + num_cols], drop_first=True)# Standardization of Variablesscaler = MinMaxScaler()df = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)df.head()# Implementation of KNNimputer = KNNImputer(n_neighbors=n_neighbors)return pd.DataFrame(imputer.fit_transform(df), columns=df.columns)

编码

编码是将分类变量转换为可以提供给机器学习算法使用的格式的过程。一般包括

标签编码:为类别分配唯一的数字标签。

独热编码:将分类变量转换为二进制向量。

稀有编码:当一个分类变量有一些在数据集中很少出现的类别时,使用这种技术。

这些编码有助于将各种数据类型转换为数字格式,使机器学习模型能够提取模式并更准确地进行预测。

标签编码:

标签编码用于将分类数据转换为算法可以处理的数字格式。它的工作原理是为分类变量中的每个类别分配一个唯一的整数。此方法对于类别有自然顺序的有序数据特别有用,例如评级。但是标签编码可能会在不存在的类别之间引入人为的顺序关系,这对于某些算法来说可能是有问题的。

 from sklearn.preprocessing import LabelEncoderdef label_encoder(dataframe, binary_col):labelencoder = LabelEncoder()dataframe[binary_col] = labelencoder.fit_transform(dataframe[binary_col])return dataframebinary_cols = [col for col in df.columns if df[col].dtype not in [int, float]and df[col].nunique() == 2]for col in binary_cols:label_encoder(df, col)

独热编码:

独热编码是一种用于数字表示分类数据的技术,适用于需要数字输入的机器学习算法。在这种方法中,特征中的每个唯一类别成为一个新的二进制列。对于给定的类别,相应的列被设置为1(或“hot”),而所有其他列都被设置为0。这种方法允许在不暗示类别之间的任何顺序关系的情况下表示类别变量。它在处理标称数据时特别有用,因为类别没有固有的顺序或层次结构。但是如果分类数据中的类别较多会增加稀疏性。

 def one_hot_encoder(dataframe, categorical_cols, drop_first=True):dataframe = pd.get_dummies(dataframe, columns=categorical_cols, drop_first=drop_first)return dataframeohe_cols = [col for col in df.columns if 10 >= df[col].nunique() > 2]one_hot_encoder(df, ohe_cols).head()

稀有编码:

机器学习中的稀有编码通常是指用于处理分类变量中罕见或不常见类别的技术。

当一个分类变量有一些在数据集中很少出现的类别时,使用这种技术可以防止过拟合,降低这些罕见类别给模型带来的噪声。

  • 将不常见的类别分组:将不常见的类别合并到一个“其他”类别中。
  • 基于频率的编码:用数据集中的频率替换稀有类别。
  • 基于相似性的编码:根据与更常见的类别的相似性对罕见类别进行分组。

设置频率阈值(例如,少于1%的出现)来定义什么构成“罕见”类别。这样有助于降低模型的复杂性,改进泛化,并处理测试数据中未见过的类别。

 cat_cols = [col for col in dataframe.columns if dataframe[col].dtypes == "O"]num_but_cat = [col for col in dataframe.columns if dataframe[col].nunique() < cat_th anddataframe[col].dtypes != "O"]cat_but_car = [col for col in dataframe.columns if dataframe[col].nunique() > car_th anddataframe[col].dtypes == "O"]cat_cols = cat_cols + num_but_catcat_cols = [col for col in cat_cols if col not in cat_but_car]def rare_analyser(dataframe, target, cat_cols):for col in cat_cols:print(col, ":", len(dataframe[col].value_counts()))print(pd.DataFrame({"COUNT": dataframe[col].value_counts(),"RATIO": dataframe[col].value_counts() / len(dataframe),"TARGET_MEAN": dataframe.groupby(col)[target].mean()}), end="\n\n\n")rare_analyser(df, "TARGET", cat_cols)def rare_encoder(dataframe, rare_perc):temp_df = dataframe.copy()rare_columns = [col for col in temp_df.columns if temp_df[col].dtypes == 'O'and (temp_df[col].value_counts() / len(temp_df) < rare_perc).any(axis=None)]for var in rare_columns:tmp = temp_df[var].value_counts() / len(temp_df)rare_labels = tmp[tmp < rare_perc].indextemp_df[var] = np.where(temp_df[var].isin(rare_labels), 'Rare', temp_df[var])return temp_dfnew_df = rare_encoder(df, 0.01)

特征缩放

特征缩放是一种用于机器学习的预处理技术,用于标准化数据的自变量或特征的范围。因为特征在相同条件下可以减少算法的训练时间。当变量被标准化时,减少由缩放特征产生的误差的努力会更容易。因为在同一条件下可以确保所有特征对模型的性能贡献相同,防止较大的特征主导学习过程。

这对输入特征的尺度敏感的算法尤其重要,例如基于梯度下降的算法和基于距离的算法。当特征处于相似规模时,许多机器学习算法表现更好或收敛更快。但是应分别应用于训练集和测试集,以避免数据泄漏。

Standard Scaling

标准化对特征进行缩放,使它们的均值为0,方差为1。

 from sklearn.preprocessing import StandardScalerdef standard_scale(df, columns):scaler = StandardScaler()df[columns] = scaler.fit_transform(df[columns])return df

Robust Scaling

Robust Scaling使用对异常值具有鲁棒性的统计信息。

 from sklearn.preprocessing import RobustScalerdef robust_scale(df, columns):scaler = RobustScaler()df[columns] = scaler.fit_transform(df[columns])return df

Min-Max Scaling

MinMax Scaling将特征缩放到一个固定的范围,通常在0到1之间。

 from sklearn.preprocessing import MinMaxScalerdef minmax_scale(df, columns):scaler = MinMaxScaler()df[columns] = scaler.fit_transform(df[columns])return df

分箱

分箱是通过创建一组区间将连续变量转换为分类变量的过程。

 import numpy as npdef binning(df, column, bins, labels=None):df[f'{column}_binned'] = pd.qcut(df[column], bins=bins, labels=labels)return df

特征提取

特征提取是机器学习和数据分析中的一项重要技术。它包括选择原始数据并将其转换为一组更有用的特征,这些特征可用于进一步处理或分析。特征提取的目的是,降低数据的维数,这样可以简化模型,提高性能。

文本统计特征

创建二进制特征可以突出显示数据中的重要特征。

 def create_binary_feature(df, column, condition):df[f'{column}_flag'] = np.where(condition(df[column]), 1, 0)return df

例如对于下面的文本

文本数据通常包含有价值的信息,这些信息可以提取为数字特征。

 # Letter Countdf["NEW_NAME_COUNT"] = df["Name"].str.len()# Word Countdf["NEW_NAME_WORD_COUNT"] = df["Name"].apply(lambda x: len(str(x).split(" ")))# Capturing Special Structuresdf["NEW_NAME_DR"] = df["Name"].apply(lambda x: len([x for x in x.split() if x.startswith("Dr")]))df.groupby("NEW_NAME_DR").agg({"Survived": ["mean","count"]})# Deriving Variables with Regexdf['NEW_TITLE'] = df.Name.str.extract(' ([A-Za-z]+)\.', expand=False)df[["NEW_TITLE", "Survived", "AGE"]].groupby(["NEW_TITLE"]).agg({"Survived": "mean", "AGE": ["count", "mean"]})

时间序列变量

对于时间序列可以将日期变量分解为与分析相关的各种子组件。

 def date_features(df, date_column):df[f'{date_column}_year'] = df[date_column].dt.yeardf[f'{date_column}_month'] = df[date_column].dt.monthdf[f'{date_column}_day'] = df[date_column].dt.daydf[f'{date_column}_dayofweek'] = df[date_column].dt.dayofweekreturn df

这样就可以针对不同的时间进行处理。

总结

特征工程和数据预处理是任何机器学习中的关键步骤。它们可以通过确保数据干净、结构良好和信息丰富来显著提高模型的性能。本文介绍了如何处理异常值和缺失值、编码分类变量、缩放数值特征和创建新特征——为准备机器学习任务的数据奠定了坚实的基础。

我们这里也只是介绍一些简单常见的技术,使用更复杂和更具体技术将取决于数据集和试图解决的问题。

https://avoid.overfit.cn/post/3c783d3a115e44889d7f741aa158c533

作者:Kursat Dinc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/34058.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何阅读一篇学术论文

第一遍 论文的格式实际上常常遵循着固定的结构&#xff0c;这种结构有助于作者整理思路&#xff0c;同时也帮助读者快速定位论文的要点和创新之处。 最常见的错误是拿到一篇论文后立刻开始从头到尾仔细阅读&#xff0c;然后进行详细笔记。这种方法可以全局了解论文的内容&…

我是如何从功能测试转成自动化测试的!

大家好&#xff0c;我是测试君。&#xff08;六哥也行&#xff09; 时间过得好快&#xff0c;不知不觉已经在这个行业摸爬滚打10年多了&#xff0c;也算是测试圈的一枚老兵了。 回想自己在自动化求知路上的种种&#xff0c;依然历历在目&#xff0c;看着自己一步步的走来&#…

剪画小程序:视频文案提取神器:制作爆款视频的第一步!

在这个信息爆炸的时代&#xff0c;视频成为了我们获取知识和娱乐的重要途径。 但有时候&#xff0c;我们想要的不仅仅是观看视频&#xff0c;而是能够将其中精彩的文案提取出来&#xff0c;为自己的创作添砖加瓦。 现在&#xff0c;有一款神奇的工具应运而生&#xff0c;为您…

工作随记-构造调用虚函数

工作随记-构造调用虚函数 代码编译警告原因解决方法示例代码重构示例总结 代码编译警告 Call to virtual method CoordinateConversionTool::Reset during construction bypasses virtual dispatch [clang-analyzer-optin.cplusplus.VirtualCall]这个警告信息来自 Clang 静态分…

Linux-笔记 高级I/O操作

前言 I/O&#xff08;Input/Output&#xff0c;输入/输出&#xff09;是计算机系统中的一个重要组成部分&#xff0c;它是指计算机与 外部世界之间的信息交流过程。I/O 操作是计算机系统中的一种基本操作&#xff0c;用于向外部设备&#xff08;如 硬盘、键盘、鼠标、网络等&am…

https基础概念

目录 1.什么是https 1.1.https概念 1.2.一些术语 2.https如何加密 2.1.使用对称加密 2.2.使用非对称加密 1.什么是https 首先&#xff0c;https不是http的复数形式 1.1.https概念 &#xff08;1&#xff09;产生背景 为什么会出现https&#xff0c;是因为http协议在传…

如何通过有效的跟进,吸引国外客户回复?

相信很多外贸业务员都知道&#xff0c;想要走到最终达成订单成交的那一步&#xff0c;首要前提就是客户愿意和你继续谈。第一次询价就买的这种客户属于刚需&#xff0c;可遇而不可求&#xff0c;大部分的客户都需要通过我们坚持不懈的跟进最后达成交易。 所以如何通过有效的跟…

小白学python(第二天)

哈喽&#xff0c;各位小伙伴们我们又见面了&#xff0c;昨天的文章吸收得如何&#xff1f;可有不懂否&#xff1f;如有不懂可以在品论区留言哦&#xff0c;废话不多说&#xff0c;开始今天的内容。 字符及字符串的续讲 字符&#xff1a;英文字母&#xff0c;阿拉伯数字&#x…

大数据面试题之Hive(2)

目录 Hive的join操作原理&#xff0c;leftjoin、right join、inner join、outer join的异同? Hive如何优化join操作 Hive的mapjoin Hive语句的运行机制&#xff0c;例如包含where、having、group by、orderby&#xff0c;整个的执行过程? Hive使用的时候会将数据同步到HD…

Laravel 响应对象深度解析:构建动态 HTTP 响应

在 Laravel 框架中&#xff0c;响应&#xff08;Response&#xff09;对象扮演着至关重要的角色&#xff0c;它负责将应用程序的输出发送给客户端。Laravel 的响应系统非常灵活&#xff0c;允许开发者以多种方式构建和自定义响应。本文将深入探讨 Laravel 中响应对象的工作机制…

Keil汇编相关知识

一、汇编的组成 1.汇编指令&#xff1a;在内存中占用内存&#xff0c;执行一条汇编指令会让处理器进行相关运算 分类&#xff1a;数据处理指令&#xff0c;跳转指令&#xff0c;内存读写指令&#xff0c;状态寄存器传送指令&#xff0c;软中断产生指令&#xff0c;协助处理器…

AcWing算法基础课笔记——状态压缩DP:蒙德里安的梦想

状态压缩DP 状态是整数&#xff0c;但把它看成二进制数&#xff0c;二进制中每一位是0或1表示不同的情况。 蒙德里安的梦想 291. 蒙德里安的梦想 - AcWing题库 题目 求把 NM&#x1d441;&#x1d440; 的棋盘分割成若干个 1212 的长方形&#xff0c;有多少种方案。 例如…

electron-builder 打包过慢解决

报错内容如下 > 6-241.0.0 build > electron-builder • electron-builder version24.13.3 os10.0.22631 • loaded configuration filepackage.json ("build" field) • writing effective config filedist\builder-effective-config.yaml • pack…

地下管线管网三维建模系统MagicPipe3D

地下管网是保障城市运行的基础设施和“生命线”。随着实景三维中国建设的推进&#xff0c;构建地下管网三维模型与地上融合的数字孪生场景&#xff0c;对于提升智慧城市管理至关重要&#xff01;针对现有三维管线建模数据差异大、建模交互弱、模型效果差、缺乏语义信息等缺陷&a…

清科ZF引导基金数据(1990-2023年)

清科ZF引导基金数据&#xff0c;参考经济学家吴超鹏和严泽浩在《经济研究》2023年的研究&#xff0c;通过清科私募通数据库&#xff0c;获取ZF引导基金的管理机构信息。数据涵盖了ZF引导基金的关键信息&#xff0c;如基金名称、管理机构详情、所属层级、发展阶段、地域分布、初…

java学习 - Redis五大数据类型

redis通用命令 命令说明时间复杂度type key判断key的数据类型O(1)keys [pattern]获取数据库中所有符合pattern的keyO(n)dbsize获取数据库的key的数量O(1)exists key判断是否存在key;存在返回1&#xff0c;不存在返回0O(1)del key [key…]删除key;返回删除个数O(1)expire key s…

Batch学习:开启高效学习之旅

Batch学习&#xff1a;开启高效学习之旅 Batch学习是一种学习方法&#xff0c;它将学习内容划分为多个批次进行学习。这种方法有助于学生更好地掌握知识&#xff0c;提高学习效果。本文将详细介绍Batch学习的概念、方法和优势&#xff0c;并探讨如何有效地实施Batch学习。 一…

数据集MNIST手写体识别 pyqt5+Pytorch/TensorFlow

GitHub - LINHYYY/Real-time-handwritten-digit-recognition: VGG16和PyQt5的实时手写数字识别/Real-time handwritten digit recognition for VGG16 and PyQt5 pyqt5Pytorch内容已进行开源&#xff0c;链接如上&#xff0c;请遵守开源协议维护开源环境&#xff0c;如果觉得内…

redis集群简单介绍及其搭建过程

Redis集群 1、哨兵模式 哨兵可以有多个&#xff0c;从服务器也可以有多个&#xff0c;从服务器也可以有多个&#xff0c;在Redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态&#xff0c;如果master节点异常&#xff0c;则会实现主从切换&#x…

百度大模型安全荣获2024世界智能产业博览会“Find智能科技创新应用典型案例”

6月20日&#xff0c;2024世界智能产业博览会在天津开幕。会议聚焦人工智能、智能网联汽车、智能制造等年度热点议题&#xff0c;由世界智能产业博览会组委会指导&#xff0c;世界智能产业博览会组委会秘书处、中国新一代人工智能战略发展研究院、中国软件行业协会、中国网络空间…