在机器学习中,除了归一化和标准化之外,
还有许多其他重要的数据预处理方法。
这些方法旨在提高数据的质量,使其更适合机器学习模型的训练和应用。
以下是一些常见的数据预处理方法:
1. 数据清洗
数据清洗是数据预处理的第一步,主要目的是去除或纠正数据中的错误、不一致和异常值。具体方法包括:
缺失值处理:
对于缺失的数据,可以采用删除法(删除观测样本、删除变量)、
插补法(均值插补、回归插补、热平台插补、冷平台插补等)进行处理。
异常值处理:
异常值是指那些在数据集中存在的不合理的值,
可以通过简单统计分析、3σ原则、箱线图等方法进行识别和处理,
常见的处理方式包括删除异常值或进行平滑处理。
去重:
检测并删除数据集中的重复记录,以避免模型训练过程中的过拟合问题。
2. 数据集成
数据集成是将多个数据源中的数据合并到一个一致的数据存储中的过程。
在数据集成过程中,需要解决数据冗余和数据冲突等问题,确保数据的一致性和完整性。
3. 数据规约
数据规约是在保持数据原貌的前提下,最大限度地精简数据量,
以提高数据处理的效率和模型训练的速度。
数据规约的方法主要包括:
属性选择:
从原始数据集中选择出最具代表性的特征,以减少模型的复杂性并提高性能。
数据抽样:
通过随机抽样等方法,从原始数据集中抽取一部分数据作为训练集,以减小数据处理的规模。
数据压缩:
采用编码等方式对原始数据进行压缩,以减小数据存储空间并提高数据传输效率。
4. 数据变换
数据变换是将原始数据转换成适合机器学习模型处理的形式的过程。
常见的数据变换方法包括:
光滑:去除数据中的噪声,可以通过分箱、回归、聚类等方法实现。
属性构造:
由给定的属性构造出新属性并添加到数据集中,
例如通过“销售额”和“成本”构造出“利润”。
聚集:
对数据进行汇总或聚集,
例如通过日销售数据计算月和年的销售数据。
规范化/标准化:
将不同数值变化范围的分布映射到相同的固定范围,以消除量纲对数据比较的影响。
离散化:
将连续数据分段为一系列离散化区间,以提高特征在知识层面的表达能力。
5. 数据编码
对于分类数据,需要进行适当的编码以便机器学习模型能够处理。
常见的编码方法包括独热编码(One-Hot Encoding)、标签编码(Label Encoding)等。
6. 特征选择
特征选择是根据特征的重要性或相关性,
从原始特征集中选择出最具代表性的特征子集,以减少模型的复杂性并提高性能。
特征选择的方法包括过滤法、包裹法、嵌入法等。
7. 数据增强
数据增强是在训练模型之前,
通过对原始数据进行变换、扩充等操作来增加数据样本的多样性,
以提高模型的泛化能力。
常见的数据增强方法包括旋转、缩放、平移、添加噪声等。
综上所述,数据预处理是机器学习过程中不可或缺的一步,
通过合理的数据预处理方法,可以显著提高模型的训练效率和性能。
|
|
|
|
|
|
|
|
空值处理
- 缺失值
- NULL
- 空值
|
每个特征有其业务含义,应该有业务的边界
需要验证这些数据是否在其边界内
如果不合理,则进行修改,使数据更加合理
------------------------------------------------------------------
|
# 数字置为0
for col in cname_num_type:
data.loc[data[col].isna(),col]=0
#object转str,仅处理分类特征,身份认证类特征不参与训练
data[cname_str_classification] = data[cname_str_classification].astype(str)
data[cname_str_classification] = data[cname_str_classification].astype("string")
for col in cname_str_classification:
data.loc[data[col].isna(),col]="
nan被转为了字符串,但在pandas中仍然是个特殊存在,转为特定字符串,以防Pandas自动处理
# 创建一个替换映射字典
type_mapping = {
'nan': '<PAD>',
}
# 使用.replace()方法替换'列的类型'列中的值
data[cname_str_classification] = data[cname_str_classification].replace(type_mapping)
# 显示结果
data.head(3)
|
|
|
|
|
|
字符串转时间戳
import pandas as pd
# 示例数据
data = {'Timestamp': ['2023-10-01 12:00:00', '2023-10-02 13:00:00']}
df = pd.DataFrame(data)
# 转换为 pandas.Timestamp 类型
df['Timestamp'] = pd.to_datetime(df['Timestamp'])
Timestamp
0 2023-10-01 12:00:00
1 2023-10-02 13:00:00
年月日 # 提取年份 df['Year'] = df['Timestamp'].dt.year # 提取月份 df['Month'] = df['Timestamp'].dt.month # 提取日期 df['Day'] = df['Timestamp'].dt.day
# 提取小时
df['Hour'] = df['Timestamp'].dt.hour
# 提取分钟
df['Minute'] = df['Timestamp'].dt.minute
# 提取秒
df['Second'] = df['Timestamp'].dt.second
|
df['Unix_Timestamp'] = df['Timestamp'].astype('int64') // 10**9 # 转换为秒
df
10**9是10的9次方,就是1后面9个0
df['Timestamp_value'] = df['Timestamp'].apply(lambda x: x.value)
取两条数据之间的时差(秒)
import pandas as pd
# 假设 df 是你的 DataFrame
# 示例数据
data = {
'Account': ['A', 'A', 'A', 'B', 'B', 'C', 'C'],
'Unix_Timestamp': [1622544000, 1622544010, 1622544020, 1622544030, 1622544040, 1622544050, 1622544600],
'Other_Column': ['X', 'Y', 'Z', 'W', 'V', 'U', 'T']
}
df = pd.DataFrame(data)
# 按 Account 列分组,并计算每个分组内 Unix_Timestamp 的差值
df['Time_Diff'] = df.groupby('Account')['Unix_Timestamp'].diff()
# 查看结果
df.fillna(0,inplace=True)
df
|
import pandas as pd
# 示例数据
data = {'Timestamp': ['2022-06-04 08:49:01', '2023-07-15 14:23:45']}
df = pd.DataFrame(data)
# 将Timestamp列转换为datetime类型
df['Timestamp_datetime'] = pd.to_datetime(df['Timestamp'])
# 从Timestamp_datetime列生成tstm和dt_time列
df['tstm'] = df['Timestamp_datetime'].dt.strftime('%Y-%m-%d')
df['dt_time'] = df['Timestamp_datetime'].dt.strftime('%Y-%m-%d %H:%M:%S')
df
# 转换为 pandas.Timestamp 类型
df['Timestamp'] = pd.to_datetime(df['Timestamp'])
# 提取年份
df['Year'] = df['Timestamp'].dt.year
# 提取月份
df['Month'] = df['Timestamp'].dt.month
# 提取日期
df['Day'] = df['Timestamp'].dt.day
df['Week'] = df['Timestamp'].dt.weekday
# df['Unix_Timestamp'] = df['Timestamp'].astype('int64') // 10**9 # 转换为秒
df['Timestamp'] = (df['Timestamp']-df['Timestamp'].min())/(df['Timestamp'].max()-df['Timestamp'].min())
df
|
|
|
|
|
IForest(孤立森林)是一种用于异常检测的无监督学习算法,其基于树模型,
通过随机切分数据空间来检测异常数据点。
IForest的核心思想在于异常数据点通常具有较低的密度,
因此在随机切分过程中会更快地被孤立到叶节点。
以下是如何使用IForest检测异常数据的详细步骤及举例说明:
IForest检测异常数据的步骤
构建iTree(孤立树):
从原始数据集中随机抽取一部分样本作为训练数据。
随机选择一个特征,并在该特征的最大值和最小值之间随机选择一个值作为切分点。
将样本中小于切分点的数据划分到左子树,大于等于切分点的数据划分到右子树。
递归地在左右子树上重复上述过程,直到满足停止条件(如树达到最大深度或节点中只有一个样本)。
构建iForest:
重复上述过程多次,构建多棵iTree,形成iForest。
计算异常分数:
对于待检测的数据点,计算其在每棵iTree中的路径长度(即从根节点到叶节点的边的数量)。
计算数据点在所有iTree中路径长度的平均值。
使用路径长度的平均值和树中样本数量的函数来计算异常分数。异常分数越高,表示数据点越异常。
举例说明
假设我们有一组一维数据,包含多个正常点和少数异常点。异常点通常与大多数正常点有较大的差异。
构建iTree:
从数据集中随机抽取一部分样本。
假设选择了一个特征,并在其值域内随机选择了一个切分点。
根据切分点将数据分为左右两部分,并递归地在左右部分上构建子树。
重复此过程,直到满足停止条件。
构建iForest:
重复上述过程,构建多棵iTree,形成iForest。
检测异常:
对于待检测的数据点(如一个新的数据点),将其输入到iForest中。
计算该数据点在每棵iTree中的路径长度。
计算路径长度的平均值,并使用该平均值计算异常分数。
假设异常分数高于某个阈值(该阈值可以根据实际情况设定),则认为该数据点为异常点。
注意事项
IForest对全局异常点(Global Anomaly)敏感,但对局部异常点(Local Anomaly)可能不敏感。
IForest的性能受树的数量、采样大小、树的最大高度等参数的影响。
在处理高维数据时,IForest可能不够有效,因为每次切分只考虑一个特征,导致大量维度信息未被利用。
通过上述步骤和例子,我们可以看到IForest如何通过随机切分数据空间来检测异常数据点。这种方法简单且高效,特别适用于处理大规模数据集。
|
在机器学习中,3sigma异常值检测是一种基于统计原理的异常值识别方法,
它主要依赖于数据的正态分布特性。
以下是对3sigma异常值的详细解释:
定义与原理
定义:
3sigma异常值检测是指,在假定数据服从正态分布的前提下,
将那些与平均值的偏差超过三倍标准差(3σ)的数据点视为异常值。
原理:
正态分布(高斯分布)是一种连续概率分布,其形状由均值(μ)和标准差(σ)决定。
根据正态分布的性质,大约99.7%的数据点会落在均值加减三倍标准差(μ±3σ)的范围内。
因此,那些落在这一范围之外的数据点,
即与均值偏差超过三倍标准差的数据点,被认为是极不常见的,从而被识别为异常值。
应用场景
3sigma异常值检测在多个领域都有广泛的应用,包括但不限于:
数据预处理:
在数据分析或机器学习模型训练之前,去除数据集中的异常值,以提高数据的质量和模型的准确性。
故障预警:
在工程科学中,通过传感器采集的数据进行故障预警时,
可以利用3sigma原理来识别异常数据,从而及时发现潜在的问题。
金融风控:
在金融领域,通过监测交易数据中的异常值来识别潜在的欺诈行为或市场异常波动。
优点与局限性
优点:
简单直观:基于统计学的原理,易于理解和实现。
广泛适用性:适用于大多数服从或近似服从正态分布的数据集。
局限性:
假设性强:要求数据必须服从正态分布,这在实际应用中可能难以满足。
灵敏度与特异性平衡:虽然能够识别出大部分异常值,
但有时也可能将正常范围内的极端值误判为异常值,或者漏判一些真正的异常值。
个人认为在正样本较少的情况下,正样本有较大的可能被判定为异常,
此时,可以将3sigma做一个特征,然后将这个特征并入总特征,供算法参考
实现步骤
在Python中,实现3sigma异常值检测的基本步骤包括:
计算均值和标准差:使用数据集的平均值和标准差作为基准。
确定阈值:根据均值和标准差计算上下阈值(μ-3σ和μ+3σ)。
识别异常值:将数据集中的数据点与阈值进行比较,超出阈值的数据点被视为异常值。
代码示例
import pandas as pd
# 假设有一个包含数据的DataFrame
data = {"size": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 160,3000]}
def std3(data):
data_df = pd.DataFrame(data)
# 计算均值和标准差
mean = data_df['size'].mean()
std = data_df['size'].std()
# 确定阈值
lower_bound = mean - 3 * std
upper_bound = mean + 3 * std
# 识别异常值
outliers = data_df[(data_df['size'] <= lower_bound) | (data_df['size'] >= upper_bound)]
return outliers
# 输出异常值
std3(data)
3000
这里面有个问题,如果异常值非常大,就会拉大std,进行使得较小的异常值就检测不出来了 一个轮次可能只会检测出一个异常数据
data = {"size": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 160]}
std3(data)
160
data = {"size": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
std3(data)
|
|
|
|
|
|
|
连续变量离散化是指将连续变量的取值范围划分为若干个离散的区间,
并将每个连续值 映射 到对应的区间中。
这种方法有助于简化模型、提高模型的泛化能力,并可能使模型更容易解释。
以下是连续变量离散化的几种常用方法:
等宽离散化(Equal Width Discretization) 等宽离散化是将连续变量的取值范围划分为宽度相等的若干个区间。 这种方法实现简单,适用于数据分布相对均匀的情况。 然而,当数据分布不均匀时,可能会导致某些区间内的样本数量差异很大。 等频离散化(Equal Frequency Discretization) 等频离散化是将连续变量的取值范围划分为包含大致相等数量样本的若干个区间。 这种方法确保了每个区间内的样本数量大致相等,有助于后续的分析和建模工作。 但是,在某些极端情况下,可能会导致区间的宽度差异很大。 聚类离散化(Cluster-based Discretization)
聚类离散化使用聚类算法(如K-means、DBSCAN等)将数据聚类成若干个群组,
然后根据聚类结果将数据分成离散的区间。
这种方法可以更好地适应数据分布的特点,但可能会受到聚类算法的选择和参数设置的影响。
聚类离散化能够发现 数据中的潜在结构和模式,从而得到更有意义的区间划分。
自定义离散化(Custom Discretization)
自定义离散化是根据具体问题和领域知识,按照自定义的规则将数据划分为离散的区间。
这种方法可以根据具体需求进行灵活调整,但需要 根据问题和数据特点 进行合理的划分设计。
自定义离散化通常需要对数据有深入的理解和分析。
其他
卡方分箱、决策树分箱等
|
简单处理:
等宽:
数据分布均匀时,各个箱子的样本数量差不多;
便于解释,可简化问题;
等频:
不要求数据分布均匀,但需要额外处理一下极值与异常值;
如果箱子数少,数据可能会集中于某几个箱子;
有利于提高模型的预测能力
聚类分箱更有意义一些,但处理起来稍微麻烦...
选择依据 数据分布: 如果数据分布相对均匀,等宽分箱和等频分箱可能都能得到较好的结果。 但如果数据分布极不均匀,等频分箱可能更合适, 因为它能够确保每个区间内的样本数量大致相等。 特征选择目的: 如果特征选择的主要目的是提高模型的预测能力, 那么应该根据数据的实际分布情况选择分箱方法。 如果目的是简化模型或提高模型的可解释性,等宽分箱可能更直观易懂。 业务背景: 在某些业务场景中,可能需要根据特定的业务规则或需求来选择分箱方法。 例如,在金融风控领域,可能需要根据信用评分的历史分布或业务经验来选择分箱方法。 注意事项
分箱数量:
无论是等宽分箱还是等频分箱,都需要合理确定分箱的数量。
分箱数量过多可能导致过拟合,分箱数量过少则可能无法充分反映数据的分布情况。
边界处理:
在分箱过程中,需要注意边界值的处理。
例如,在等宽分箱时,需要确定区间的开闭情况;
在等频分箱时,需要处理可能存在的极端值或异常值。
WOE和IV值的计算:
在分箱完成后,需要根据分箱结果计算WOE和IV值。
这些值将用于评估特征的预测能力和信息贡献程度。
对于离散型变量,每个类型就是一个箱子 |
|
等频分箱示例
import pandas as pd
import numpy as np
# 构造数据集
np.random.seed(0) # 为了结果的可重复性
data = {
'年龄': np.random.randint(20, 70, size=15),
'收入': np.random.randint(20000, 100000, size=15),
'简化信用评分': np.random.randint(300, 850, size=15),
'是否违约': np.random.choice([0, 1], size=15, p=[0.8, 0.2]) # 假设大部分不违约
}
df = pd.DataFrame(data)
X = df["年龄"] qbins = pd.qcut(X, q=4, duplicates='drop') # 分为4个等频的箱子 qbins
# 创建包含分组和是否违约的DataFrame
y = df["是否违约"]
result = pd.DataFrame({
'feature': X,
'target': y
}).groupby(qbins,observed=True).agg(
Total=('target', 'size'),
Bads=('target', lambda x: (x == 1).sum()),
Goods=('target', lambda x: (x == 0).sum())
)
result
等宽分箱示例
import pandas as pd
import numpy as np
# 创建一个示例DataFrame
data = pd.DataFrame({
'scores': np.random.normal(75, 10, 100) # 生成100个服从正态分布(均值75,标准差10)的随机分数
})
# 等宽离散化
bins = pd.cut(data['scores'], bins=4, right=False) # 分为4个等宽的箱子
data['score_bins_equal_width'] = bins
# 等频离散化
qbins = pd.qcut(data['scores'], q=4, duplicates='drop') # 分为4个等频的箱子
data['score_bins_equal_freq'] = qbins
# 查看结果
data.head()
|
|
|
|
|
将非数字内容转化为数字,方便模型计算
|
|
|
|
|
|
|
|
在机器学习中,特征工程的二值化(Binarization)是一种数据预处理技术,
旨在将数值型特征转换为二进制特征,
即通常转换为0和1。
这一过程通过设置一个阈值来实现,
大于或等于该阈值的特征值被设置为1,
小于该阈值的特征值则被设置为0。
特征二值化对于某些类型的机器学习模型特别有用,
尤其是那些假设输入数据遵循多值伯努利分布(Bernoulli distribution)的概率型模型。
特征二值化的意义 简化概率估计: 在文本处理等领域,即使归一化计数(如术语频率)和TF-IDF值特征在实践中表现稍好一些, 但团队常常使用二值化特征值来简化概率估计。 适应特定模型需求: 某些模型,如使用贝叶斯设置中伯努利分布建模的模型,更适合处理布尔型随机变量, 因此特征二值化可以作为这些模型的预处理步骤。 处理极端值: 在数据分布极不均匀的情况下,特征二值化有助于减少极端值对模型的影响, 例如,将极高或极低的收入值简化为1或0,可能有助于模型更好地捕捉一般趋势。
|
|
阈值选择很关键
from sklearn.preprocessing import Binarizer
# 假设X是一个包含数值特征的二维数组
X = [[1., -1., 2.],
[2., 0., 0.],
[0., 1., -1.]]
# 创建一个Binarizer实例,并设置阈值
binarizer = Binarizer(threshold=0.0)
# 对X进行二值化处理
X_bin = binarizer.fit_transform(X)
# 输出结果
print(X_bin)
# 输出: [[1. 0. 1.]
# [1. 0. 0.]
# [0. 1. 0.]]
[[1. 0. 1.]
[1. 0. 0.]
[0. 1. 0.]]
|
|
|
|
|
|
|
sklearn数据集分割方法汇总