【Python机器学习】零基础掌握Preprocessing and Normalization数据预处理方法

编程入门 行业动态 更新时间:2024-10-15 20:20:28

【Python<a href=https://www.elefans.com/category/jswz/34/1771242.html style=机器学习】零基础掌握Preprocessing and Normalization数据预处理方法"/>

【Python机器学习】零基础掌握Preprocessing and Normalization数据预处理方法

如何优化的数据?

在处理数据之前,为什么总是听说需要进行预处理和规范化?在这个信息爆炸的时代,数据无疑是宝贵的财富,但原始数据往往包含噪声、缺失值、格式不一致等问题。预处理就是在数据分析之前,通过一系列技术手段清洗和整理数据,以增强数据的质量和分析的准确性。规范化(Normalization)则是一种调整数值数据范围以便于比较的技术。

预处理和规范化在现实生活中的应用几乎无处不在。假设一家电商平台需要分析销售数据以优化库存管理。原始的销售数据可能包括各种不同的度量和尺度,预处理能帮助平台统一这些数据,以便进行有效比较;规范化则能确保不同规模的销售数额不会因为数值大小而影响分析结果,从而使决策更加合理。

文章目录

  • Add Dummy Feature
  • Binarize
  • Label Binarize
  • Maxabs Scale
  • Minmax Scale
  • Normalize
  • Quantile Transform
  • Robust Scale
  • Scale
  • Power Transform
  • 方法对比
  • 总结

Add Dummy Feature

在数据分析和机器学习中,add_dummy_feature这个算法就像是给菜肴加上基础的盐巴,它的作用是在数据集中添加一列,这一列的数值通常都是1。这个过程在统计学和机器学习模型中相当于添加一个截距项,也就是说,在建立模型时,它允许模型有一个非零的起点。

数学上,如果有一个数据集 X X X,使用 add_dummy_feature 可以表示为:

X new = [ 1 X ] X_{\text{new}} = [1 \quad X] Xnew​=[1X]

其中 X new X_{\text{new}} Xnew​ 是添加了虚拟特征后的新数据集,第一列是新添加的全为1的特征列,而 X X X 是原始数据。

将这个算法应用到一个案例上。假设在建设长城的过程中,工程师们需要记录不同地段长城的高度、宽度和长度。为了更好地模拟修建长城时各段的耗时,可能需要在数据集中添加一个截距项,代表了基础的建设时间,它是在实际测量的特征之外的。

from sklearn.preprocessing import add_dummy_feature
import numpy as np
import pandas as pd# 模拟的长城建设数据
data = {'Height': np.random.uniform(5, 10, 10),  # 高度,单位:米'Width': np.random.uniform(3, 5, 10),    # 宽度,单位:米'Length': np.random.uniform(50, 100, 10) # 长度,单位:米
}
df = pd.DataFrame(data)
df['Time'] = np.random.uniform(10, 20, 10)  # 耗时,单位:天# 添加虚拟特征
X = df.drop('Time', axis=1).values
X_new = add_dummy_feature(X)# 显示添加虚拟特征后的数据
df_new = pd.DataFrame(X_new, columns=['Intercept', 'Height', 'Width', 'Length'])
df_new['Time'] = df['Time']
df_newimport matplotlib.pyplot as plt
import seaborn as sns# 设置风格
sns.set(style="whitegrid")# 原始数据的散点图
plt.figure(figsize=(12, 6))
sns.scatterplot(data=df, x='Length', y='Time', hue='Height', size='Width', sizes=(50, 200))
plt.title('Original Long Wall Construction Data')
plt.xlabel('Length (meters)')
plt.ylabel('Time (days)')
plt.legend(title='Height (meters)', bbox_to_anchor=(1, 1))
plt.show()# 添加虚拟特征后的数据散点图
plt.figure(figsize=(12, 6))
sns.scatterplot(x=df_new['Length'], y=df_new['Time'], hue=df_new['Height'], size=df_new['Width'], sizes=(50, 200))
plt.title('Long Wall Construction Data with Dummy Feature')
plt.xlabel('Length (meters)')
plt.ylabel('Time (days)')
plt.legend(title='Height (meters)', bbox_to_anchor=(1, 1))
plt.show()

通过模拟长城建设的数据并添加了虚拟特征,可以看到,虽然数据的主要特征(高度、宽度、长度)没有变化,但是在数据集中多了一个常数特征。这在视觉上并不明显,因为它仅仅是数值上的变化,没有直接的视觉效果。但在实际建模过程中,这个额外的“盐巴”却能让模型更准确地捕捉到数据的基线水平,即使在没有任何其他信息的情况下,也能预测出一个基础的耗时。


通过数据可视化,展示了原始数据和添加虚拟特征后的数据之间的差异。虽然在图表上看不出变化,但添加的虚拟特征对于后续的建模分析来说是至关重要的,因为它为模型提供了一个起点。这就像在讲述历史故事时,始终会有一个开端,那就是虚拟特征在数据故事中的角色。

Binarize

Binarize算法像是一个过滤器,它将数据分为两个部分:一部分高于某个阈值,一部分低于或等于这个阈值。数学上,这个过程可以表示为一个简单的函数:

output = { 1 if input > threshold 0 otherwise \text{output} = \begin{cases} 1 & \text{if } \text{input} > \text{threshold} \\ 0 & \text{otherwise} \end{cases} output={10​if input>thresholdotherwise​

用日常语言来说,就像是通过一个“高矮棒”来判断人们是否可以进入一个游乐设施,高于棒子的可以进入(标记为1),没过棒子的则不能(标记为0)。

为了更好地展示这个过程,设想在宋代的著名画家张择端,他在创作《清明上河图》时,想要区分画作中的人物是否身穿节日盛装。为了简化问题,假设衣物的华丽程度可以用数值来表示,通过Binarize方法,可以快速标记出画中人物的着装是否华丽(假设阈值为50,以上为华丽)。

from sklearn import preprocessing
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns# 数据模拟
# 假设数据中有四个特征:衣物华丽度、身份等级、年龄和身高
# 其中衣物华丽度将用于Binarize处理
data = np.array([[48, 5, 30, 160],  # 华丽度小于50,不华丽[52, 3, 40, 165],  # 华丽度大于50,华丽# ... 其他数据
])# 添加更多的模拟数据,共10条
np.random.seed(0)
additional_data = np.random.randint(10, 100, size=(8, 4))
data = np.vstack([data, additional_data])# 应用Binarize方法
binarizer = preprocessing.Binarize(threshold=50)
binary_huahuadu = binarizer.transform(data[:, [0]])# 结果拼接,用于可视化
labeled_data = np.hstack((data, binary_huahuadu))# 数据可视化
# 用Seaborn库创建一个条形图来表示衣物华丽度和对应的二值化结果
sns.set_theme(style="whitegrid")
ax = sns.barplot(x=np.arange(1, labeled_data.shape[0]+1), y=labeled_data[:, 0], hue=labeled_data[:, -1])
ax.set(xlabel='人物编号', ylabel='衣物华丽度', title='《清明上河图》人物衣物华丽度二值化结果')
plt.show()

上述代码创建了一个模拟数据集,表示《清明上河图》中的不同人物特征。使用Binarize方法根据衣物华丽度特征进行二值化处理,并将结果与原始数据合并。用条形图可视化每个人物的衣物华丽度以及二值化的结果。

在宋代的背景下,通过Binarizer算法,能够快速区分出《清明上河图》中人物的着装是否华丽。这个过程非常直观,就像是给画中的人物打分,通过一个简单的标准来分类。在现代数据分析中,这个方法同样适用,特别是在处理需要分类的问题时,如垃圾邮件过滤、疾病诊断等。通过二值化处理,可以简化模型的复杂性,使得后续的机器学习算法更加高效。这种方法也有其局限性,主要是信息损失,因为它将所有的数值信息简化为了两个类别。因此,在使用时需要权衡信息简化带来的便利和可能的信息损失。

Label Binarize

在机器学习中,尤其是处理分类问题时,经常会遇到需要将标签(labels)转换成模型能够理解的形式。preprocessing.label_binarize 就是这样一种转换工具。它可以将分类结果转换成二进制(0和1)形式,让计算机能夜读懂“是”或者“不是”这种简单的逻辑。如果有一个分类任务涉及到“苹果”、“香蕉”和“樱桃”,这个函数就可以将它们分别转换成 [1, 0, 0][0, 1, 0][0, 0, 1]

在数学上,如果有 n n n 个类别和 m m m 个样本,那么通过label_binarize转换后的结果是一个 m × n m \times n m×n 的矩阵,其中只有一列为1表示所属的类别,其余都为0。

假设在古代丝绸之路的贸易中,商队需要分类和记录来自不同地域的货物,这些货物包括“丝绸”、“香料”、“陶瓷”和“宝石”。每一种货物到达后,都需要进行分类标记,以便于进一步的贸易操作。

from sklearn import preprocessing
import pandas as pd
import numpy as np# 模拟数据
data = {'货物名称': ['丝绸', '香料', '陶瓷', '宝石', '丝绸', '香料', '陶瓷', '宝石', '丝绸', '香料'],'重量': np.random.randint(1, 100, 10),'价值': np.random.randint(100, 1000, 10),'产地': ['中国', '印度', '中国', '南非', '中国', '印度', '中国', '南非', '中国', '印度']
}df = pd.DataFrame(data)# 转换标签
classes = ['丝绸', '香料', '陶瓷', '宝石']
y = preprocessing.label_binarize(df['货物名称'], classes=classes)# 将转换结果添加回原数据框
for i, cls in enumerate(classes):df[cls] = y[:, i]dfimport matplotlib.pyplot as plt
import seaborn as sns# 设置图表的大小
plt.figure(figsize=(10, 6))# 绘制重量与价值的关系,并根据货物类型着色
sns.scatterplot(data=df, x='重量', y='价值', hue='货物名称', style='产地', palette='viridis', s=100)# 添加图例和标题
plt.title('古丝绸之路货物重量与价值分布图')
plt.xlabel('重量(单位:斤)')
plt.ylabel('价值(单位:文)')
plt.legend(title='货物名称与产地')
plt.show()

代码创建了一个含有货物名称、重量、价值和产地的DataFrame。使用label_binarize方法将“货物名称”这一列转换成二进制格式,并将结果作为新列添加到DataFrame中。

这段代码使用了Seaborn库来创建一个散点图,它显示了货物重量与价值之间的关系,并通过不同的颜色和形状区分了货物类型和产地。

在古代丝绸之路贸易案例中,通过label_binarize将货物名称转换成二进制形式,不仅方便了对不同货物的计算处理,而且为后续的数据分析打下了基础。通过可视化技术,能够直观地展示各种货物的重量和价值分布,为商队提供了宝贵的贸易决策信息。这不仅提高了数据处理的效率,而且通过图形化展示,使得复杂的数据信息变得易于理解,有助于商队优化贸易策略,获得更大的经济利益。

Maxabs Scale

假设在绘制一幅画时,如果使用的颜料直接从瓶中倾倒到画布上,那么颜料的浓度将会影响整体的效果,颜色可能会过于强烈或者太淡。在数据分析中,maxabs_scale算法就像是一位细心的艺术家,它调整数据中的每种特征(颜料),确保它们在同一强度级别上,这样在绘制数据的画面时,每种特征都能以正确的方式呈现。

该算法将每个特征的数值范围缩放到 [ − 1 , 1 ] [-1, 1] [−1,1] 之间,方法是除以该特征绝对值的最大值。对于有正有负的数据来说,这是一种保持数据稀疏性的方法,因为它不会改变数据中的0值。

数学公式可表述为:

X scaled = X max ⁡ ( ∣ X ∣ ) X_{\text{scaled}} = \frac{X}{\max(\lvert X \rvert)} Xscaled​=max(∣X∣)X​

其中 X X X 是原始数据, max ⁡ ( ∣ X ∣ ) \max(\lvert X \rvert) max(∣X∣) 是数据绝对值的最大值。

设想在古代丝绸之路的贸易中,商队需要评估不同货物(如丝绸、香料、珠宝)的价值,以优化其贸易策略。为了在多个城市之间进行比较,他们需要一种方法来标准化货物的价值,就像现代数据分析中的maxabs_scale

from sklearn import preprocessing
import numpy as np
import pandas as pd# 模拟数据,代表不同城市的货物价值
data = {'Silk': [100, 200, 300, 400, 250, 350, 150, 450, 50, 320],'Spices': [20, 30, 10, 40, 35, 45, 15, 50, 25, 30],'Jewels': [500, 300, 400, 200, 450, 350, 250, 150, 550, 330],'Gold': [1000, 800, 1200, 600, 1100, 900, 700, 1300, 500, 1150]
}
df = pd.DataFrame(data)# 应用 maxabs_scale 方法
maxabs_scaled_data = preprocessing.maxabs_scale(df, axis=0)
df_scaled = pd.DataFrame(maxabs_scaled_data, columns=df.columns)df_scaledimport matplotlib.pyplot as plt
import seaborn as snssns.set(style="whitegrid")
df_scaled_melted = df_scaled.melt(var_name='Goods', value_name='Value')
plt.figure(figsize=(10, 6))
sns.barplot(x='Goods', y='Value', data=df_scaled_melted)
plt.title('Standardized Values of Goods Across Cities')
plt.show()

将处理后的数据进行可视化,可以使用柱状图来表示每个城市中货物价值的相对大小,这有助于商队直观地比较和决策。

通过应用maxabs_scale,每个特征(货物)的价值都被标准化,保证了不同货物间的比较是公平的,而不会因为自然价值的差异而造成误解。在数据可视化中,清晰的柱状图展示了标准化后货物的相对价值,这为决策提供了直观的支持,商队可以更容易地分析哪种货物在哪个城市更具价值,进而做出明智的贸易选择。

Minmax Scale

preprocessing.minmax_scale 算法,简单来说就像是一个比赛中的“体重称”,它可以将所有运动员(数据点)的体重(数值)调整到相同的尺度,确保没有人因为体重(数值大小)的不同而享有不公平的优势或劣势。在数学上,这个过程可以通过一个简单的公式来描述:

X scaled = X − X min X max − X min \text{X}_{\text{scaled}} = \frac{\text{X} - \text{X}_{\text{min}}}{\text{X}_{\text{max}} - \text{X}_{\text{min}}} Xscaled​=Xmax​−Xmin​X−Xmin​​

这个公式将每个数值减去最小值除以范围(最大值减去最小值),这样原始数据中的最小值就变成了0,最大值变成了1,其他所有值都分布在0和1之间。

假设如果要将不同时代的绘画作品的价值进行比较,而这些作品的价值跨越了几个世纪。如果直接比较,可能会因为通货膨胀和市场变化而产生误导。通过使用minmax_scale,可以将所有作品的价值按比例缩放到相同的区间,使得跨时代的比较变得公平。

import numpy as np
from sklearn import preprocessing
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns# 模拟数据
data = {'Ancient_Coins_Value': np.random.randint(100, 10000, size=10),'Medieval_Paintings_Value': np.random.randint(5000, 20000, size=10),'Renaissance_Sculptures_Value': np.random.randint(2000, 15000, size=10),'Modern_Artifacts_Value': np.random.randint(1000, 5000, size=10)
}df = pd.DataFrame(data)# 应用minmax_scale
df_scaled = preprocessing.minmax_scale(df)# 转换回DataFrame
df_scaled = pd.DataFrame(df_scaled, columns=df.columns)# 显示原始和缩放后的数据
df_combined = pd.concat([df, df_scaled.add_suffix('_Scaled')], axis=1)# 设置画布
plt.figure(figsize=(14, 7))# 绘制原始数据的分布
plt.subplot(1, 2, 1)
sns.violinplot(data=df)
plt.title('Original Data Distribution')# 绘制缩放后数据的分布
plt.subplot(1, 2, 2)
sns.violinplot(data=df_scaled)
plt.title('Scaled Data Distribution')# 显示图表
plt.show()

在使用 preprocessing.minmax_scale 方法后,可以清楚地看到,原始数据的分布范围各不相同,这在不同特征的比较中可能会导致偏差。缩放后的数据则被统一调整到了0到1之间的区间,使得特征之间可以公平地进行比较。这种缩放不仅增强了数据的一致性,而且也有助于提高机器学习模型训练的效率和效果。可视化图表清晰地展示了这种变化,使得缩放前后的数据对比一目了然。

通过这种方式即使是跨越了数个世纪的艺术品,也能够在同一尺度下评估其价值和重要性,为艺术品的评估和比较提供了一个客观的标准。这不仅适用于艺术品,还可以用于任何需要跨时段或跨范围比较的领域,比如历史通货膨胀的研究、跨国公司的财务报表分析等。通过这样的处理,不同的数据点就像是穿上了一件统一的制服,站在同一起跑线上,确保了分析结果的公正性和准确性。

Normalize

预处理中的normalize算法,简单来说就像是给数据做“减肥”。在不同的特征(比如说身高和体重)量度不一致时,它能够帮助将每个样本的特征值“缩放”,确保它们在同一量级上,让每个特征对结果的影响一视同仁。在数学上,这通常意味着将每个样本向量的长度(也就是向量的欧几里得范数)缩放到1。如果用公式表示,就是:

normalized x i = x i x i 2 + y i 2 + z i 2 + . . . \text{normalized} \, x_i = \frac{x_i}{\sqrt{x_i^2 + y_i^2 + z_i^2 + ...}} normalizedxi​=xi2​+yi2​+zi2​+... ​xi​​

这里的 x i , y i , x_i, y_i, xi​,yi​,和 z i z_i zi​代表一个样本中不同的特征值,而分母是这个样本所有特征值的平方和的平方根。

现实生活中的例子可以是对古董的评估。想象一个评估师在考察一系列古董,每件古董都有多个属性,比如年代、稀有度、保存状态和艺术价值。这些属性的量级相差巨大,直接比较没有意义。使用normalize处理后,评估师能够更公正地对古董进行评估,确保不会因为某一特征的量级过大而对整体评估造成偏差。

数据集将包含古董的年代、稀有度、保存状态和艺术价值四个特征。

from sklearn import preprocessing
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns# 模拟古董数据
data = {'年代': [100, 200, 300, 150, 210, 330, 400, 60, 250, 100],'稀有度': [7, 6.5, 9, 4, 8, 5, 7.5, 6, 8.5, 5.5],'保存状态': [5, 7, 6, 3, 4, 8, 7, 5, 6.5, 4.5],'艺术价值': [80, 90, 75, 65, 85, 70, 95, 60, 85, 80]
}df = pd.DataFrame(data)# 应用normalize方法
normalized_df = preprocessing.normalize(df, norm='l2', axis=0)# 将规范化后的数据转换为DataFrame
normalized_df = pd.DataFrame(normalized_df, columns=df.columns)# 显示规范化后的数据
normalized_df# 绘制规范化前后的数据对比散点图
plt.figure(figsize=(14, 7))# 原始数据散点图
plt.subplot(1, 2, 1)
sns.scatterplot(data=df, x='年代', y='艺术价值')
plt.title('原始数据')# 规范化后数据散点图
plt.subplot(1, 2, 2)
sns.scatterplot(data=normalized_df, x='年代', y='艺术价值')
plt.title('规范化后数据')plt.show()

在这个例子中,通过规范化处理,古董的不同属性被缩放到了同一量级,使得比较和后续分析变得更加合理。这种处理方式非常适合机器学习和数据挖掘等领域,在这些领域中,数据的比例和量级可能会严重影响模型的预测结果。规范化后的数据更加平衡,每个特征都得到了公平的考量,而不是被个别量级大的特征所主导。通过可视化,可以直观地看到规范化对数据分布的影响,从而更好地理解数据规范化的必要性和效果。

Quantile Transform

preprocessing.quantile_transform 是一种将数据转换为更均匀或正态分布的方法。假设如果一组数据像一条蜿蜒的河流,有的地方水流湍急(数据集中),有的地方则宽广平静(数据稀疏),这种转换就像是对河道进行疏浚,使得水流在河道中均匀流动。在数学上,这种转换确保了转换后的输出数据的累积分布函数是一个线性函数,即:

F ( X new ) = 常数 × X old F(X_{\text{new}}) = \text{常数} \times X_{\text{old}} F(Xnew​)=常数×Xold​

其中 F F F 是累积分布函数, X old X_{\text{old}} Xold​ 是原始数据, X new X_{\text{new}} Xnew​ 是转换后的数据。简单来说就是通过这种转换,数据的分布被“拉直”,更加接近均匀或者正态分布。

假设有一组关于古代埃及粮食产量的数据,这些数据反映了不同地区、不同季节的产量差异。由于自然条件的影响,数据的分布可能非常不均匀,这对于预测未来粮食供应和规划粮食分配造成了困难。使用quantile_transform可以帮助平滑这些数据,使得模型的预测更加稳定。

import numpy as np
import pandas as pd
from sklearn.preprocessing import quantile_transform
import matplotlib.pyplot as plt
import seaborn as sns# 模拟数据
np.random.seed(0)
# 假设有四个地区的粮食产量数据,每个地区有不同的季节性影响
data = {'Lower_Egypt': np.random.gamma(shape=2.0, scale=1.0, size=10),'Upper_Egypt': np.random.gamma(shape=2.0, scale=2.0, size=10),'Delta': np.random.gamma(shape=2.0, scale=3.0, size=10),'Oasis': np.random.gamma(shape=2.0, scale=1.5, size=10)
}
df = pd.DataFrame(data)# 应用quantile_transform
df_transformed = pd.DataFrame(quantile_transform(df, output_distribution='normal'),columns=df.columns
)# 展示原始和转换后的数据
df_transformed['Region'] = 'Transformed'
df['Region'] = 'Original'
combined_df = pd.concat([df, df_transformed], ignore_index=True)# 绘制原始和转换后的数据分布
plt.figure(figsize=(14, 6))
for i, column in enumerate(df.columns[:-1], 1):plt.subplot(2, 4, i)sns.histplot(combined_df[combined_df['Region'] == 'Original'][column], kde=True, color='blue', label='Original')sns.histplot(combined_df[combined_df['Region'] == 'Transformed'][column], kde=True, color='red', label='Transformed')plt.legend()plt.title(column)plt.tight_layout()
plt.show()

代码创建了一个模拟的数据集,代表不同地区的粮食产量。quantile_transform被应用到这些数据上,将它们转换为更接近正态分布的形式。使用直方图对比了转换前后的数据分布。

通过应用quantile_transform,可以看到原始数据中的偏斜被显著地减少了。这使得模型预测时,不会过分地受到极端值的影响,而是能够捕捉到更加本质的、普遍适用的趋势。在古代埃及粮食产量的案例中,这可能帮助统治者更准确地进行粮食分配和规划,避免饥荒或粮食过剩的情况发生。在数据可视化中,可以直观地看出转换的效果,为决策提供了直观的支持。在现代的数据分析中,这种转换同样有着广泛的应用,从风险管理到资源分配,都可以利用这种方法来提高预测的准确性和鲁棒性。

Robust Scale

robust_scale算法是一种数据预处理方法,用于缩放特征以使其更为稳健,即减少异常值的影响。与传统的平均值和标准差缩放不同,robust_scale使用中位数和四分位数范围(IQR)来确定缩放的参数。这种方法通过剔除极端值的干扰,使得数据的主体部分更加突出。

用日常生活的语言解释,如果将一组人的身高进行比较,而其中有极端的高个子或矮个子,传统的平均值方法会受这些极端个例影响,导致平均身高偏离大多数人的实际情况。robust_scale就像是在计算平均身高时忽略那些极端个例,以便得到一个更能代表大众的平均身高。

数学公式描述如下:

X scaled = X − Median ( X ) IQR ( X ) X_{\text{scaled}} = \frac{X - \text{Median}(X)}{\text{IQR}(X)} Xscaled​=IQR(X)X−Median(X)​

其中 Median ( X ) \text{Median}(X) Median(X) 是数据的中位数,而 IQR ( X ) \text{IQR}(X) IQR(X) 是数据的四分位范围,通常是第三四分位数(75%)和第一四分位数(25%)之间的差。

from sklearn import preprocessing
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns# 模拟数据
data = {'Age': [25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 120],  # 加入异常值120岁'Height': [165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 230],  # 加入异常值230cm'Income': [5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000, 50000],  # 加入异常值50000'Education_Years': [10, 12, 14, 16, 18, 20, 12, 14, 16, 18, 25]  # 加入异常值25年
}df = pd.DataFrame(data)# 应用robust_scale方法
scaled_data = preprocessing.robust_scale(df)# 将numpy数组转换回DataFrame以便于可视化
scaled_df = pd.DataFrame(scaled_data, columns=df.columns)# 输出处理后的数据
scaled_df# 设置画布
plt.figure(figsize=(12, 6))# 原始数据与处理后数据的对比可视化
plt.subplot(1, 2, 1)
sns.boxplot(data=df)
plt.title('Original Data')plt.subplot(1, 2, 2)
sns.boxplot(data=scaled_df)
plt.title('Robust Scaled Data')plt.tight_layout()
plt.show()

通过robust_scale方法处理数据后,可以明显看出异常值的影响被减弱,主体数据的分布变得更加紧凑和集中。这对于那些算法和模型非常有用,它们对异常值特别敏感,如线性回归分析。在历史故事的背景下,可以想象这种方法类似于古代统计官员在测量粮食产量时,忽略因灾害或特殊原因导致的异常高产或低产,以获得一个更加稳定和可靠的粮食平均产量,从而更准确地预测和规划国家的粮食储备。

Scale

在介绍preprocessing.scale之前,可以先想象一下历史上的货币兑换问题。假设在古丝绸之路上的商人需要交换不同国家的货币,由于每种货币的价值不同,他们需要一个公平的方式来确保每笔交易是公正的。这就是scale算法的作用:它将不同的货币(在的例子中是数值特征)转换为同一标准,确保它们在交易(或数据分析)中的价值是可比较的。

preprocessing.scale函数的作用是去除特征的均值,并将其缩放到单位方差。这种转换通常称为标准化或Z得分规范化。简单来说这个过程就像是将每个特征的分布中心放到0,确保所有特征的重要性是一样的,没有哪个特征会因为数值范围大而主导模型的训练。

数学上,标准化的计算公式如下:

z = ( x − μ ) σ z = \frac{(x - \mu)}{\sigma} z=σ(x−μ)​

其中 x x x 是原始数据值, μ \mu μ 是特征的均值, σ \sigma σ 是特征的标准差。公式的结果 z z z就是标准化后的数值。

# 导入所需的库
from sklearn import preprocessing
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns# 模拟数据
data = {'稻谷产量': [300, 450, 500, 600, 750, 800, 1200, 1300, 900, 1100],'棉花产量': [50, 60, 80, 70, 120, 100, 200, 220, 150, 180],'陶瓷出货': [200, 300, 250, 400, 300, 450, 500, 600, 700, 800],'茶叶销量': [100, 200, 150, 300, 400, 350, 450, 550, 500, 650]
}
df = pd.DataFrame(data)# 应用标准化
scaled_data = preprocessing.scale(df)# 将标准化后的数据转换回DataFrame以便于可视化
scaled_df = pd.DataFrame(scaled_data, columns=df.columns)# 数据可视化
plt.figure(figsize=(10, 8))
sns.kdeplot(data=scaled_df)
plt.title('标准化后的产量分布')
plt.xlabel('值')
plt.ylabel('密度')
plt.legend(df.columns)
plt.show()

代码创建了一个包含稻谷、棉花、陶瓷和茶叶四个特征的模拟数据集,每个特征都有10个数据点。使用preprocessing.scale函数将这些数据标准化利用Seaborn库的kdeplot函数将结果可视化。

通过可视化,可以清楚地看到,标准化后的数据集中每个特征都围绕0值对称分布,具有相似的数据范围和密度,确保了在后续的数据分析和建模中,每个特征都能被公平地对待,没有一个特征会因为其数值的绝对大小而主导分析结果。

这个过程对于历史上的丝绸之路商人来说是多么有用!如果他们能够使用类似的方法来标准化他们的货币价值,那么无论是来自东方的珍珠还是来自西方的香料,都能够以一种公正和一致的方式进行交换。在现代数据分析中,preprocessing.scale就是那个确保每个特征都能公平交易的标准化方法。

Power Transform

preprocessing.power_transform 是一种数据转换的方法,它的目的是帮助修正数据分布的形状,使其更接近正态分布。在日常生活中,可以将其比作对食材进行腌制,以确保烹饪出来的菜肴口感均衡,不会因为某些部分过于突出而影响整体的风味。

这个方法通常使用的数学公式为:

X new = sign ( X ) ⋅ ( ∣ X ∣ + ϵ λ ) 1 2 X_{\text{new}} = \text{sign}(X) \cdot \left(\frac{|X| + \epsilon}{\lambda}\right)^{\frac{1}{2}} Xnew​=sign(X)⋅(λ∣X∣+ϵ​)21​

其中 X new X_{\text{new}} Xnew​ 表示转换后的数据, ϵ \epsilon ϵ 是一个很小的数以避免除以零的情况,而 λ \lambda λ 是从数据中估计出的参数。简单来说这个公式将每个值的大小调整为更加符合标准的形状,而符号函数确保不会丢失数值的正负信息。

将通过Python代码来演示这个方法的应用。假设数据来源于古代的粮食产量记录,其中包含不同地区、不同粮食种类的产量数据,希望通过power_transform来优化这些数据,以便进行未来的产量预测分析。

from sklearn.preprocessing import power_transform
import pandas as pd
import numpy as np# 模拟古代粮食产量数据
data = {'Wheat': np.random.poisson(lam=50, size=10),'Rice': np.random.normal(loc=100, scale=15, size=10),'Corn': np.random.beta(a=2, b=5, size=10) * 100,'Barley': np.random.chisquare(df=2, size=10) * 10
}df = pd.DataFrame(data)
df['Region'] = ['Region ' + str(i) for i in range(1, 11)]# 应用 power_transform 方法
df_transformed = pd.DataFrame(power_transform(df.iloc[:, :-1], method='yeo-johnson'), columns=df.columns[:-1])
df_transformed['Region'] = df['Region']# 显示转换前后的数据
df_transformedimport seaborn as sns
import matplotlib.pyplot as plt# 绘制转换前后的数据对比
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(15, 5))# 原始数据的直方图
sns.histplot(data=df.iloc[:, :-1], ax=ax1, kde=True)
ax1.set_title('Original Data Distributions')# 转换后数据的直方图
sns.histplot(data=df_transformed.iloc[:, :-1], ax=ax2, kde=True)
ax2.set_title('Transformed Data Distributions')plt.show()

通过power_transform方法,不均匀分布的原始数据被优化为更接近正态分布的形态。这种转换对于模型的训练非常有帮助,因为许多机器学习算法都假定输入数据是正态分布的。通过直观的可视化对比,可以清晰地看到数据分布的改变。在古代粮食产量的案例中,这种转换可以帮助统计学家更准确地预测未来的粮食产量,为皇家仓库的管理提供科学依据。通过这种方式即使在数百年前没有现代计算工具的情况下,统计学的原理也能发挥作用,为王朝的繁荣稳定做出贡献。

方法对比

在数据预处理的世界里,每一种技术都有其特定的舞台。当数据集中存在分类变量时,add_dummy_feature就像是在舞台上搭建一扇通向线性模型世界的门。而binarizelabel_binarize则将复杂的数值和标签简化为最基本的形式,有如用二进制代码编织现实。maxabs_scaleminmax_scale则在保持数据结构的同时调整数据的尺寸,就像是为数据穿上合适的衣服。normalize则保证每个特征都能在比较中公平发声。

当数据受到异常值的影响时,robust_scale就像是一个稳健的守门员,保护模型不受这些极端值的扰乱。scale提供了一个标准化的场景,使所有特征都能在同一起跑线上竞赛。而power_transform则试图将歪曲的舞台拉回到中心,以便每个特征都能够更平等地展现其特色。这些技术,虽然方法各异,但共同目标是为数据分析提供一个清晰、公正的舞台,让真实的故事得以展现。

方法应用场景功能优点缺点
add_dummy_feature增加一个常数列,例如截距项添加一个所有值为1的特征列对于某些模型如线性回归非常有用,因为可以添加截距项可能会增加不必要的维度
binarize需要将数值特征二值化根据阈值将特征转换为二进制值(0或1)简化了模型的复杂性,有助于某些算法的决策过程丢失了数值之间的相对关系
label_binarize多类别数据的处理将标签二值化为一对多的格式对于多分类问题非常有用会增加数据维度,可能导致稀疏矩阵
maxabs_scale不破坏稀疏性的缩放缩放每个特征到[-1,1]范围内不改变其分布保留了数据的稀疏性对于没有明确范围的数据不太合适
minmax_scale将特征缩放到给定范围缩放每个特征到指定的最小和最大值之间调整数据到同一量级,有助于某些算法的性能对异常值非常敏感
normalize需要对行或列进行标准化将每个样本缩放到单位范数提高了模型的泛化能力忽略了不同特征之间的分布
quantile_transform分布不均匀的特征转换将特征的分布转换为均匀或正态分布降低了异常值的影响计算成本较高,需要较大的样本量
robust_scale存在异常值的数据使用中位数和四分位数范围来缩放特征对异常值有很好的鲁棒性不会将数据缩放到一个特定的范围
scale需要标准化特征标准化特征,使其具有0均值和单位方差有助于许多机器学习算法的性能不适合稀疏数据
power_transform改善特征的对称性和稳定性应用幂变换使特征更接近高斯分布可以改善模型的预测效果变换过程可能难以解释

总结

通过对数据进行预处理和规范化,能够显著提高数据分析的质量和效率。从简单的虚拟特征添加到复杂的量化转换,每种方法都旨在从原始数据中提取最有价值的信息,同时消除可能的偏差和异常值。这不仅仅是技术操作的堆砌,更是一种艺术,需要数据分析师以其专业知识将数据转化为可靠的决策支持。

通过实际的代码操作和可视化,这些技术变得生动且易于理解。它们像是数据分析师的画笔,可以在原始数据的画布上绘制出更加精确和有说服力的画面。无论是在历史还是现代的故事中,这些方法都能够帮助人们更好地理解过去,预测未来,并在现在做出更明智的选择。

更多推荐

【Python机器学习】零基础掌握Preprocessing and Normalization数据预处理方法

本文发布于:2024-02-13 00:50:21,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1690050.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:机器   基础   方法   数据   Python

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!