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

news2024/11/19 7:49:07

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

异常值

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

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

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-quartile1
     up_limit=quartile3+1.5*interquantile_range
     low_limit=quartile1-1.5*interquantile_range
     returnlow_limit, up_limit
 
 defcheck_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):
         returnTrue
     else:
         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_limit
     dataframe.loc[(dataframe[variable] > up_limit), variable] = up_limit

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

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

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

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

 from sklearn.neighbors import LocalOutlierFactor
 
 def 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 and
                    dataframe[col].dtypes != "O"]
     cat_but_car = [col for col in dataframe.columns if dataframe[col].nunique() > car_th and
                    dataframe[col].dtypes == "O"]
     cat_cols = cat_cols + num_but_cat
     cat_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 KNNImputer
 
 def 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 and
                    dataframe[col].dtypes != "O"]
     cat_but_car = [col for col in dataframe.columns if dataframe[col].nunique() > car_th and
                    dataframe[col].dtypes == "O"]
     cat_cols = cat_cols + num_but_cat
     cat_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 Variables
     scaler = MinMaxScaler()
     df = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)
     df.head()
 
     # Implementation of KNN
 
     imputer = KNNImputer(n_neighbors=n_neighbors)
 
     return pd.DataFrame(imputer.fit_transform(df), columns=df.columns)

编码

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

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

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

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

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

标签编码:

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

 from sklearn.preprocessing import LabelEncoder
 
 def label_encoder(dataframe, binary_col):
     labelencoder = LabelEncoder()
     dataframe[binary_col] = labelencoder.fit_transform(dataframe[binary_col])
     return dataframe
 
 binary_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 dataframe
 
 ohe_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 and
                    dataframe[col].dtypes != "O"]
 cat_but_car = [col for col in dataframe.columns if dataframe[col].nunique() > car_th and
                    dataframe[col].dtypes == "O"]
 cat_cols = cat_cols + num_but_cat
 cat_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].index
         temp_df[var] = np.where(temp_df[var].isin(rare_labels), 'Rare', temp_df[var])
 
     return temp_df
 
 new_df = rare_encoder(df, 0.01)

特征缩放

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

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

Standard Scaling

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

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

Robust Scaling

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

 from sklearn.preprocessing import RobustScaler
 
 def 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 MinMaxScaler
 
 def minmax_scale(df, columns):
     scaler = MinMaxScaler()
     df[columns] = scaler.fit_transform(df[columns])
     return df

分箱

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

 import numpy as np
 
 def 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 Count
 
 df["NEW_NAME_COUNT"] = df["Name"].str.len()
 
 # Word Count
 
 df["NEW_NAME_WORD_COUNT"] = df["Name"].apply(lambda x: len(str(x).split(" ")))
 
 # Capturing Special Structures
 
 df["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 Regex
 
 df['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.year
     df[f'{date_column}_month'] = df[date_column].dt.month
     df[f'{date_column}_day'] = df[date_column].dt.day
     df[f'{date_column}_dayofweek'] = df[date_column].dt.dayofweek
     return df

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

总结

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

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

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

作者:Kursat Dinc

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

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

相关文章

Springboot拦截器使用及其底层源码剖析

博主最近看了一下公司刚刚开发的微服务&#xff0c;准备入手从基本的过滤器以及拦截器开始剖析&#xff0c;以及在帮同学们分析一下上次的jetty过滤器源码与本次Springboot中tomcat中过滤器的区别。正题开始&#xff0c;拦截器顾名思义是进行拦截请求的一系列操作。先给大家示例…

Java学习 - 网络TCP,UDP协议讲解

TCP协议 TCP协议特点 面向连接 应用程序在使用TCP协议之前&#xff0c;必须先建立TCP连接在数据传输完毕后&#xff0c;必须释放已经建立的TCP连接类似于打电话 点对点通信 TCP协议就像打电话&#xff0c;只能一对一&#xff0c;不能一对多或多对多 可靠传输 TCP协议能够保证…

分布式锁实现方案-基于Redis实现的分布式锁

目录 一、基于Lua看门狗实现 1.1 缓存实体 1.2 延迟队列存储实体 1.3 分布式锁RedisDistributedLockWithDog 1.4 看门狗线程续期 1.5 测试类 1.6 测试结果 1.7 总结 二、RedLock分布式锁 2.1 Redlock分布式锁简介 2.2 RedLock测试例子 2.3 RedLock 加锁核心源码分析…

OpenAI CTO谈GPT-5将达博士生智力水平;斯坦福评估排名前十两款来自中国

&#x1f989; AI新闻 &#x1f680; OpenAI CTO谈GPT-5将达博士生智力水平 摘要&#xff1a;美国达特茅斯工程学院采访了OpenAI首席技术官米拉・穆拉蒂&#xff0c;她表示GPT-4的智力相当于高中生&#xff0c;而GPT-5将在一年半后发布&#xff0c;预计达到博士生水平。穆拉蒂…

【Unity Shader】Alpha Blend(Alpha混合)的概念及其使用示例

在Unity和图形编程中&#xff0c;Alpha Blend&#xff08;也称为Alpha混合&#xff09;是一种用于处理像素透明度的技术。它允许像素与背景像素融合&#xff0c;从而实现透明或半透明的效果。Alpha Blend在渲染具有透明度的物体&#xff08;如窗户、玻璃、水、雾等&#xff09;…

闷热烦躁,精神倦怠?3个食疗方,5款好物,助您清凉度夏~

夏日&#xff0c;阳气旺盛&#xff0c;万物繁荣秀丽&#xff0c;但赤日炎炎似火烧&#xff0c;人们容易闷热、食欲不佳、四肢倦怠、萎靡不振等&#xff0c;再加上蚊虫多&#xff0c;更是让人烦躁不安&#xff01; 5款清凉好物 赶走蚊虫 天气炎热&#xff0c;蚊子、小虫都来了…

webpack【实用教程】

基础配置 配置的拆分和合并 通常 webpack 的配置文件会有3个 webpack.common.js 公共配置&#xff08;会被另外两个配置文件导入并合并&#xff09;webpack.dev.js 开发环境的配置webpack.prod.js 生产环境的配置 开发环境的本地服务 在 webpack.dev.js 中配置 devServer:…

springboot加载bean的方式

在SpringBoot的大环境下&#xff0c;基本上很少使用之前的xml配置Bean&#xff0c;主要是因为这种方式不好维护而且也不够方便。 springboto注入bean主要采用下图几种方式&#xff0c; 1、注解装配Bean 1、使用Component等派生注解 只要在类上加类上加 Component 注解即可,该…

Kotlin 运行代码片段多种方式

目录 场景描述 一、Scratch files and worksheets in the IDE 1、Scratch files(草稿文件) 特点&#xff1a; Scratch files文件创建步骤&#xff1a; 功能解释&#xff1a; Scratch Buffer笔记文件&#xff1a; 2、Worksheets(工单) 1&#xff09;、创建方式不同。 …

基于堆叠长短期记忆网络 Stacked LSTM 预测A股股票价格走势

前言 系列专栏:【深度学习&#xff1a;算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域&#xff0c;讨论了各种复杂的深度神经网络思想&#xff0c;如卷积神经网络、循环神经网络、生成对…

思看科技冲刺上市疑云:募资用途遭强烈质疑,IPO前突击分红

近日&#xff0c;思看科技&#xff08;杭州&#xff09;股份有限公司&#xff08;下称“思看科技”&#xff09;已更新提交2023年最新财务资料&#xff0c;重启科创板IPO进程。贝多财经了解到&#xff0c;思看科技的上市申请于2023年6月获上交所受理&#xff0c;目前已进入问询…

简鹿文件批量重命名:一款文件批量改名高手都在用的工具

作为 IT 行业的搬砖民工&#xff0c;互联网的数据量爆炸性增长&#xff0c;文件管理成为了一项日益重要的任务。"简鹿文件批量重命名"应运而生&#xff0c;旨在为用户提供一个高效、灵活的解决方案&#xff0c;以应对繁琐的文件命名、排序、创建及属性修改等挑战。 这…

足底筋膜炎吃什么药最管用

足底筋膜炎在使用药物后未见明显改善&#xff0c;但通过使用“古顺、敷堂、筋膜”贴后病情得到了缓解。按疗程使用自愈了&#xff0c;这款筋膜贴通过其药物成分渗透到组织中&#xff0c;从根本上消除炎症&#xff0c;从而快速缓解症状&#xff0c;足底筋膜炎得到了明显的改善。…

【思科】IPv6 过渡技术 - 6to4隧道

【思科】IPv6 过渡技术 - 6to4隧道 实验要求实现思路6 to 4 特点注意点IPv4 转 IPv6 格式小技巧 配置R1基础配置OSPFv3 局域网可达 R2基础配置局域网环境(OSPFv3)&#xff1a;IPv6 网络6 to 4 隧道 R3R4基础配置局域网环境(OSPFv3)&#xff1a;IPv6 网络6 to 4 隧道 R5基础配置…

Apifox 快速入门教程

访问示例项目​ 可访问Apifox官网&#xff0c;下载并打开 Apifox 后&#xff0c;你将会看到由系统自动创建的“示例团队”&#xff0c;其中内含一个“示例项目”。 项目中自动生成了与宠物商店有关的数条接口。 手动新建接口​ 新建接口是开发者们最常用的功能之一。Apifox 能…

Java研学-RBAC权限控制(八)

九 登录登出 1 登录作用 判断员工是否有权限访问&#xff0c;首先得知道现在操作的人是谁&#xff0c;所以必须先实现登录功能 2 登录流程 ① 提供登录页面&#xff0c;可输入用户名与密码信息&#xff0c;并添加执行登录的按钮。&#xff08;登录页面不能被拦截&#xff09;…

微服务、多租户、单点登录、国产化形成的开源Java框架!

一、项目简介 JVS是软开企服构建的一站式数字化的开源框架&#xff0c;支持对接多种账户体系&#xff0c;支持多租户、支持Auth2、统一登录、单点登录等&#xff0c;支持原生开发、低代码/零代码开发应用。 二、框架核心功能 控制台(首页)&#xff1a;采用配置化的方式 用户…

C语言从入门到进阶(15万字总结)

前言&#xff1a; 《C语言从入门到进阶》这本书可是作者呕心沥血之作&#xff0c;建议零售价1元&#xff0c;当然这里开个玩笑。 本篇博客可是作者之前写的所有C语言笔记博客的集结&#xff0c;本篇博客不止有知识点&#xff0c;还有一部分代码练习。 有人可能会问&#xff…

HarmonyOS Next 系列之可移动悬浮按钮实现(六)

系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现&#xff08;一&#xff09; HarmonyOS Next 系列之验证码输入组件实现&#xff08;二&#xff09; HarmonyOS Next 系列之底部标签栏TabBar实现&#xff08;三&#xff09; HarmonyOS Next 系列之HTTP请求封装和Token…

Huffman树——AcWing 148. 合并果子

目录 Huffman树 定义 运用情况 注意事项 解题思路 AcWing 148. 合并果子 题目描述 运行代码 代码思路 其它代码 代码思路 Huffman树 定义 它是一种最优二叉树。通过构建带权路径长度最小的二叉树&#xff0c;经常用于数据压缩等领域。 运用情况 在数据压缩中&a…