27、数据处理与特征工程实战

数据处理与特征工程实战

在数据处理和分析领域,我们常常会遇到数据缺失、特征不平衡等问题,同时也需要对数据进行特征工程以更好地进行建模和分析。下面将详细介绍相关的处理方法和实际操作。

1. 趋势插补评估练习

在这个练习中,我们要评估不同插补趋势的质量,并且思考如何处理在多个特征上可能存在不平衡的数据,而不仅仅是单个特征。

1.1 替代趋势插补

以氪石示例来说,我们使用二阶多项式拟合输入激光频率来插补每平方米坎德拉的缺失值。其实,使用局部插值、前向填充或后向填充会更简单,大多数数据框库都能直接实现这些局部插补。

以下是一个数据集示例:
| price_buy | price_maintain | doors | passengers | trunk | s | rating |
| — | — | — | — | — | — | — |
| 4304 | 1.0 | 0.158397 | 2.158397 | 6.0 | 2.0000 | Very Good |
| 337 | 3.0 | 0.000000 | 3.000000 | 4.0 | 0.0000 | Unacceptable |
| 2360 | 2.0 | 2.000000 | 3.247795 | 4.0 | 2.0000 | Acceptable |
| 3352 | 0.0 | 1.000000 | 2.123895 | 4.0 | 2.0000 | Good |
| 2064 | 0.0 | 3.000000 | 4.000000 | 6.0 | 1.8577 | Acceptable |
| 4058 | 1.0 | 0.000000 | 3.075283 | 6.0 | 2.0000 | Very Good |

该数据集可从 https://www.gnosis.cx/cleaning/excited-kryptonite.fwf 获取。

我们需要量化不同插补方法之间的差异,均方根偏差(RMSD)是一个很好的衡量样本差异的指标,在这个练习中我们就使用它。由于我们不知道缺失值的正确答案,所以只是评估各种方法之间的差异程度。具体需要测量和比较的差异如下:
- 所有点(原始点和插补点)与二阶多项式拟合函数本身之间的RMSD。
- 原始点与以下各项之间的RMSD:
- 对它们进行的线性回归。
- 二阶多项式拟合。
- 三阶多项式拟合。
- 其他你认为相关的回归(可能来自机器学习库)。
- 仅插补点在一阶、二阶和三阶多项式拟合以及仅基于相邻点的局部插值之间的RMSD。
- 仅插补点在不同阶数多项式拟合和简单前向填充之间的RMSD。

此外,还需要描述你认为击败讨厌的超人的最佳策略。

1.2 多特征平衡

人类身高/体重数据在身高数值上存在不平衡,体重也有类似的分布情况。带有一个奇特目标的该数据集版本可从 https://www.gnosis.cx/cleaning/height-weight-color.csv 获取。这个数据新增了一个名为 Favorite 的列,它大致是平衡的,是从 {red, green, blue} 集合中随机生成的。

以下是部分数据示例:

import pandas as pd
humcol = pd.read_csv('data/height-weight-color.csv') 
humcol.sample(6, random_state=1) 
Height Weight Favorite
21492 176.958650 72.604585 red
9488 169.000221 79.559843 blue
16933 171.104306 71.125528 red
12604 174.481084 79.496237 blue
8222 171.275578 77.094118 green
9110 164.631065 70.557834 green

我们的任务是探索根据身高和体重预测最喜欢颜色的模型。根据假设,身高和体重可能对最喜欢的颜色有预测作用,同时我们还假设身体质量指数(BMI)也可能有预测作用,其计算公式为:$BMI=\frac{体重(kg)}{身高(m)^2}$。

具体操作步骤如下:
1. 创建一个包含合成样本的新数据集,使身高、体重和BMI各自的观测值数量相对均衡。假设身高、体重和BMI各自分为五类,例如“非常矮”、“矮”、“中等”、“高”、“非常高”等。
2. 一种简单的方法是复制现有行以增加其量化类别的代表性,你可以先尝试这种方法。
3. 还可以使用如SMOTE、ADASYN或ROSE等技术生成代表其身高、体重或BMI类别的新颖合成样本。在生成这些合成样本时,需要分配适当的最喜欢的颜色(复制行时很直接,但根据不同平衡要求创建新颖合成行时会更微妙)。
4. 由于类别不平衡比例约为100:1,但每个特征仅在五类之间进行平衡,每个特征的平衡操作会使数据集大小增加约4倍。需要考虑是否需要链式相乘来生成约为原始大小64倍的数据集,实际上可以独立按特征进行平衡,将扩展限制为约原始大小的12倍。
5. 进行过采样,最多到300,000行数据通常是可行的。如果初始观测值超过25,000个,乘法扩展可能会有问题。假设初始过采样产生约300,000行数据,将这些大部分为合成样本的数据下采样到100,000行,同时保持大致的类别平衡(不要求精确平衡,目标是每类行数差异小于25%)。
6. 最后,如果有能力的话,尝试创建一个关于身高、体重、BMI和目标最喜欢颜色之间关系的实际模型。思考模型的预测效果如何、做出了什么预测、哪些人更喜欢哪种颜色以及偏好的强度如何,还有哪个特征的预测能力最强。

以下是体重的分布情况:

pd.cut(humcol.Weight, 5).value_counts().sort_index() 
区间 数量
(44.692, 55.402] 125
(55.402, 66.06] 3708
(66.06, 76.717] 14074
(76.717, 87.375] 6700
(87.375, 98.033] 393
2. 特征工程

特征工程主要关注基于原始数据集创建合成特征,与插补不同,它是关于改变数据的表示形式,且通常是确定性的和信息保留的(例如可逆)。以下是一些常见的特征工程方法:

2.1 数据类型转换
  • 对于日期时间,我们可以将其数字或字符串表示转换为原生表示,这样能使许多操作更方便。
  • 对于字符串,我们可以生成规范表示并将其视为类别(也称为因子),而且一个字符串通常包含多个有意义但独立的信息片段,将它们作为单独的变量处理会更有用。
  • 对于数值,有时将它们转换为不同的范围,进而转换为有序值,有助于揭示被过多精度掩盖的模式。不过,量化不是可逆转换,良好的实践仍然建议对数据进行版本控制并编写转换脚本以确保可重复性。
2.2 系统转换
  • 独热编码是一种简单的转换,它将单个分类特征转换为多个数字字段,这通常是特定统计或建模技术所需要的。
  • 多项式特征是合成特征,它以一种通常能揭示单变量特征中看不到的有意义交互的方式组合多个原始特征。
  • 分解是一种完全系统的转换,主成分分析(PCA)等技术以信息保留的方式转换整个参数空间。这种转换本身不会增加或减少任何信息,但通常会与降维相结合,这样可以从这些转换维度的子集中获取大部分信息。根据你的目的,这种转换可能会使模型更易于处理和/或质量更高。
3. 日期/时间字段处理

在处理日期/时间字段时,我们会遇到一些常见的问题,下面以温度读数数据为例进行说明。

3.1 数据读取与处理

温度数据由多个文件组成,每个文件包含一个不同自动温度计的测量值,通常每三分钟测量一次。以下是读取数据的代码:

temps = pd.read_csv('data/glarp/outside.gz',  
                    sep=' ', header=None,  
                    names=['year', 'month', 'day',  
                           'hour', 'minute', 'degrees']) 
temps.head(5) 
Year month day hour minute degrees
2003 7 25 16 4 27.5
2003 7 25 16 7 27.3
2003 7 25 16 10 27.3
2003 7 25 16 13 27.4
2003 7 25 16 16 27.8
3.2 创建日期时间索引

为了让数据更便于处理,我们将其转换为日期时间索引:

ts_fields = ['year', 'month', 'day', 'hour', 'minute'] 
temps.index = pd.to_datetime(temps[ts_fields]) 
temps.drop(columns=ts_fields, inplace=True) 
temps 
degrees
2003-07-25 16:04:00 27.5
2003-07-25 16:07:00 27.3
2003-07-25 16:10:00 27.3
2004-07-16 15:28:00 16.4

可以看到,数据虽然表面上看起来是按时间序列排列的,但实际上可能并非如此。我们可以检查索引是否单调递增:

temps.index.is_monotonic_increasing 

结果为 False ,说明索引不是单调的。我们可以查看连续行之间的时间差:

increments = temps.index.to_series().diff() 
increments[increments < pd.Timedelta(minutes=0)] 

发现有一个向后跳跃,这可能与夏令时调整有关。在进一步处理之前,我们需要对数据按日期时间索引进行排序:

temps.sort_index(inplace=True) 
temps.index.is_monotonic_increasing 

排序后,索引变为单调递增,结果为 True

3.3 施加规律性

我们知道,数据中可能存在缺失的时间戳,我们需要验证这些间隙是否存在,并进行修复以产生更规则的时间序列。

increments = temps.index.to_series().diff() 
gaps = increments[increments > pd.Timedelta(minutes=3)] 
gaps 

结果显示存在一些间隙,大多数间隙是丢失了一次测量(即六分钟而不是预期的三分钟),但也有一些较大的间隙,最长的超过一天。

我们还可以查看测量间隔过短的情况:

small_steps = increments[increments < pd.Timedelta(minutes=3)]
small_steps.sort_values(ascending=False) 

发现时间戳中的小间隙数量只有22个,其中除了一个是两分钟的间隙外,其余都是零时间差,即重复的日期时间值。我们可以根据领域判断,决定一分钟的差异对数据分析或建模是否重要。

3.4 重复时间戳处理

在时间序列数据中,重复时间戳是一个常见的问题。在这个数据集中,只有41行存在重复时间戳问题。以下是查看重复行的代码:

temps[temps.index.duplicated(keep=False)] 

大多数重复行的值差异较小,但在 2003-12-24 15:10:00 出现了一个特殊情况,有三个不同的值记录,其中一个明显是异常值,根据我们对科罗拉多州12月室外温度的领域知识和数据模式,我们可能会丢弃这个异常值。我们可以使用Pandas的 .drop_duplicates() 方法来处理重复行,但需要根据具体情况选择保留第一行、最后一行或丢弃所有有歧义的行。

综上所述,在数据处理和分析过程中,我们需要综合运用趋势插补、特征工程和日期/时间字段处理等方法,以解决数据缺失、特征不平衡和时间序列不规则等问题,从而为后续的建模和分析提供高质量的数据。

下面是一个简单的流程图,展示了日期/时间字段处理的主要步骤:

graph TD;
    A[读取数据] --> B[创建日期时间索引];
    B --> C[检查索引单调性];
    C -->|非单调| D[排序数据];
    C -->|单调| E[检查时间间隙];
    D --> E;
    E --> F[处理间隙和重复时间戳];

通过以上的操作和分析,我们可以更好地处理和利用数据,为数据科学和数据分析工作打下坚实的基础。

数据处理与特征工程实战

4. 处理重复时间戳的进一步探讨

在处理重复时间戳时,除了使用 .drop_duplicates() 方法,我们还可以根据具体业务需求采用其他策略。例如,如果我们认为重复时间戳的多个测量值都有参考价值,可以对这些值进行聚合操作,如求平均值、中位数等。以下是求重复时间戳对应温度平均值的代码示例:

duplicated_temps = temps[temps.index.duplicated(keep=False)]
grouped = duplicated_temps.groupby(duplicated_temps.index)
avg_duplicated_temps = grouped.mean()
avg_duplicated_temps

这样,我们就得到了重复时间戳对应的平均温度值,在某些情况下,这可以更全面地反映数据的特征。

5. 特征工程的实际应用

在前面我们介绍了特征工程的一些常见方法,下面我们通过一个具体的例子来展示如何应用这些方法。假设我们有一个包含客户信息的数据集,其中有年龄、收入、职业等特征,我们希望通过特征工程来提高对客户购买意愿的预测准确性。

5.1 独热编码的应用

如果职业是一个分类特征,我们可以使用独热编码将其转换为多个数值字段。以下是使用 pandas 进行独热编码的代码:

import pandas as pd

# 假设 data 是包含客户信息的 DataFrame
data = pd.DataFrame({
    'age': [25, 30, 35],
    'income': [50000, 60000, 70000],
    'occupation': ['Engineer', 'Doctor', 'Teacher']
})

encoded_data = pd.get_dummies(data, columns=['occupation'])
encoded_data

通过独热编码,我们将职业特征转换为了多个二进制特征,这样可以更好地用于机器学习模型的训练。

5.2 多项式特征的应用

我们可以使用 sklearn 库来创建多项式特征。假设我们希望考虑年龄和收入之间的交互作用,以下是创建多项式特征的代码:

from sklearn.preprocessing import PolynomialFeatures
import numpy as np

# 提取需要创建多项式特征的列
X = data[['age', 'income']].values

# 创建多项式特征对象,指定阶数为 2
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)

# 将多项式特征添加到原始数据中
poly_columns = poly.get_feature_names_out(['age', 'income'])
poly_data = pd.DataFrame(X_poly, columns=poly_columns)
final_data = pd.concat([data, poly_data], axis=1)
final_data

通过创建多项式特征,我们可以捕捉到特征之间的交互作用,从而提高模型的预测能力。

6. 趋势插补与多特征平衡的综合应用

在实际应用中,我们可能需要同时进行趋势插补和多特征平衡。以下是一个简单的示例,假设我们有一个包含销售数据的时间序列,其中存在缺失值,并且不同产品的销售数据存在不平衡的情况。

6.1 趋势插补

我们可以使用二阶多项式拟合来插补销售数据中的缺失值。以下是插补的代码:

import numpy as np
import pandas as pd
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression

# 假设 sales_data 是包含销售数据的 DataFrame,其中有缺失值
sales_data = pd.DataFrame({
    'date': pd.date_range(start='2023-01-01', periods=10),
    'sales': [10, np.nan, 12, 15, np.nan, 18, 20, np.nan, 22, 25]
})

# 提取非缺失值的索引和对应的销售数据
non_missing_index = sales_data['sales'].dropna().index
non_missing_sales = sales_data.loc[non_missing_index, 'sales']
non_missing_dates = sales_data.loc[non_missing_index, 'date'].map(pd.Timestamp.timestamp)

# 创建多项式特征对象,指定阶数为 2
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(non_missing_dates.values.reshape(-1, 1))

# 训练线性回归模型
model = LinearRegression()
model.fit(X_poly, non_missing_sales)

# 提取缺失值的索引和对应的日期
missing_index = sales_data['sales'].isna()
missing_dates = sales_data.loc[missing_index, 'date'].map(pd.Timestamp.timestamp)
X_missing_poly = poly.transform(missing_dates.values.reshape(-1, 1))

# 预测缺失值
imputed_sales = model.predict(X_missing_poly)

# 将预测值填充到原始数据中
sales_data.loc[missing_index, 'sales'] = imputed_sales
sales_data

通过二阶多项式拟合,我们成功地插补了销售数据中的缺失值。

6.2 多特征平衡

假设销售数据中不同产品的销售数量存在不平衡的情况,我们可以使用 SMOTE 技术来进行平衡。以下是使用 imblearn 库进行 SMOTE 过采样的代码:

from imblearn.over_sampling import SMOTE
from sklearn.datasets import make_classification
import pandas as pd

# 假设 product_data 是包含不同产品销售数据的 DataFrame
product_data = pd.DataFrame({
    'product': ['A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'C'],
    'sales': [10, 12, 20, 22, 25, 30, 32, 35, 38]
})

# 将产品类别转换为数值编码
product_data['product_encoded'] = pd.factorize(product_data['product'])[0]

# 提取特征和标签
X = product_data[['sales']]
y = product_data['product_encoded']

# 创建 SMOTE 对象
smote = SMOTE()
X_resampled, y_resampled = smote.fit_resample(X, y)

# 将平衡后的数据转换为 DataFrame
resampled_data = pd.DataFrame(X_resampled, columns=['sales'])
resampled_data['product_encoded'] = y_resampled
resampled_data

通过 SMOTE 过采样,我们成功地平衡了不同产品的销售数量,使得数据更适合用于机器学习模型的训练。

7. 总结与展望

在数据处理和分析的过程中,趋势插补、特征工程和日期/时间字段处理等方法是非常重要的。通过趋势插补,我们可以处理数据中的缺失值;通过特征工程,我们可以创建更有意义的特征,提高模型的预测能力;通过日期/时间字段处理,我们可以解决时间序列数据中的不规则问题。

在未来的工作中,我们可以进一步探索这些方法的应用,例如结合深度学习模型进行更复杂的特征工程,或者使用更先进的插补算法来处理缺失值。同时,我们也需要不断关注数据的质量和特征的选择,以确保我们的模型能够准确地反映数据的本质特征。

下面是一个流程图,展示了数据处理和分析的整体流程:

graph TD;
    A[数据读取] --> B[趋势插补];
    B --> C[特征工程];
    C --> D[日期/时间字段处理];
    D --> E[数据平衡];
    E --> F[模型训练与评估];

通过综合运用这些方法,我们可以更好地处理和分析数据,为实际问题提供更有效的解决方案。希望本文能够对你在数据处理和分析方面有所帮助。

基于遗传算法的新的异构分布式系统任务调度算法研究(Matlab代码实现)内容概要:本文档围绕基于遗传算法的异构分布式系统任务调度算法展开研究,重点介绍了一种结合遗传算法的新颖优化方法,并通过Matlab代码实现验证其在复杂调度问题中的有效性。文中还涵盖了多种智能优化算法在生产调度、经济调度、车间调度、无人机路径规划、微电网优化等领域的应用案例,展示了从理论建模到仿真实现的完整流程。此外,文档系统梳理了智能优化、机器学习、路径规划、电力系统管理等多个科研方向的技术体系实际应用场景,强调“借力”工具创新思维在科研中的重要性。; 适合人群:具备一定Matlab编程基础,从事智能优化、自动化、电力系统、控制工程等相关领域研究的研究生及科研人员,尤其适合正在开展调度优化、路径规划或算法改进类课题的研究者; 使用场景及目标:①学习遗传算法及其他智能优化算法(如粒子群、蜣螂优化、NSGA等)在任务调度中的设计实现;②掌握Matlab/Simulink在科研仿真中的综合应用;③获取多领域(如微电网、无人机、车间调度)的算法复现创新思路; 阅读建议:建议按目录顺序系统浏览,重点关注算法原理代码实现的对应关系,结合提供的网盘资源下载完整代码进行调试复现,同时注重从已有案例中提炼可迁移的科研方法创新路径。
【微电网】【创新点】基于非支配排序的蜣螂优化算法NSDBO求解微电网多目标优化调度研究(Matlab代码实现)内容概要:本文提出了一种基于非支配排序的蜣螂优化算法(NSDBO),用于求解微电网多目标优化调度问题。该方法结合非支配排序机制,提升了传统蜣螂优化算法在处理多目标问题时的收敛性和分布性,有效解决了微电网调度中经济成本、碳排放、能源利用率等多个相互冲突目标的优化难题。研究构建了包含风、光、储能等多种分布式能源的微电网模型,并通过Matlab代码实现算法仿真,验证了NSDBO在寻找帕累托最优解集方面的优越性能,相较于其他多目标优化算法表现出更强的搜索能力和稳定性。; 适合人群:具备一定电力系统或优化算法基础,从事新能源、微电网、智能优化等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于微电网能量管理系统的多目标优化调度设计;②作为新型智能优化算法的研究改进基础,用于解决复杂的多目标工程优化问题;③帮助理解非支配排序机制在进化算法中的集成方法及其在实际系统中的仿真实现。; 阅读建议:建议读者结合Matlab代码深入理解算法实现细节,重点关注非支配排序、拥挤度计算和蜣螂行为模拟的结合方式,并可通过替换目标函数或系统参数进行扩展实验,以掌握算法的适应性调参技巧。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值