数据的规范化和归一化处理——Pandas实现

数据标准化(归一化)处理是数据挖掘的一项基础工作,不同评价指标往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要进行数据标准化处理,以解决数据指标之间的可比性。 原始数据经过数据标准化处理后,各指标处于同一数量级,适合进行综合对比评价。数据的规范化(Normalization)和归一化(Normalization)是数据预处理中非常重要的步骤,对于数据分析、机器学习和深度学习等任务都具有重要的作用。首先,数据的规范化和归一化可以消除数据特征之间的量纲差异。在实际应用中,不同特征往往具有不同的量纲和单位,例如身高可能以厘米为单位,体重可能以千克为单位。如果不对数据进行规范化或归一化处理,那么不同特征之间的数值范围差异会导致模型训练过程中出现偏向性,从而影响模型的性能和泛化能力。其次,规范化和归一化可以加速模型的收敛速度。在训练过程中,如果特征之间存在很大的数值差异,那么模型需要更多的迭代次数才能找到合适的参数值。通过对数据进行规范化或归一化处理,可以使得模型在更少的迭代次数内达到收敛,提高了模型训练的效率。此外,规范化和归一化还可以提高模型的稳定性和鲁棒性。当数据经过处理后,模型对噪声和异常值的敏感度降低,更容易适应各种数据分布和情况,从而提高了模型的泛化能力,减少了过拟合的风险。

一、数据规范化方法

1.1 离散化(Discretization)

为解决特定的分类问题或为简化分类模型的复杂度,有时需要采用特定标记将特征原始取值进行离散化处理。离散化常常用在诸多管理实践问题,如在成绩预测中,将小于60分成绩标记为C,将60至80之间的成绩标记为B,将80至100之间的成绩标记为A。

scores = [20, 70, 60, 100, 80, 66, 88, 92]
grades = []

for score in scores:
    if score < 60 and score >= 0:
        grades.append('C')
    elif score >= 60 and score < 80:
        grades.append('B')
    elif score >= 80 and score <= 100:
        grades.append('A')

print("原始分数:", scores)
print("离散化后的等级:", grades)

这种离散化的方法可以帮助我们更好地理解和处理数据,尤其是在需要将连续型数据转换为离散型数据进行分类或分析的场景中。

1.2 最小-最大缩放(Min-Max Scaling)

# 方法一:使用 apply 函数
df_normalized = df.apply(lambda x: (x - x.min()) / (x.max() - x.min()))

# 方法二:使用 MinMaxScaler 类
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
df_normalized = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)

1.3 标准化(Standardization)

# 方法一:使用 apply 函数
df_standardized = df.apply(lambda x: (x - x.mean()) / x.std())

# 方法二:使用 StandardScaler 类
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df_standardized = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)

二、数据规范化示例

2.1 离散化

import pandas as pd

# 创建一个包含年龄数据的DataFrame
data = {
    'ID': [1, 2, 3, 4, 5],
    'Age': [25, 35, 45, 55, 65]
}
df = pd.DataFrame(data)

# 定义离散化的区间和对应的标签
bins = [0, 10, 20, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
labels = ['<10', '10-20', '20-30', '30-35', '35-40', '40-45', '45-50', '50-55', '55-60', '60-65', '65-70', '70-75', '75-80', '80-85', '85-90', '90-95', '95-100']

# 使用cut函数进行离散化处理
df['Age_Group'] = pd.cut(df['Age'], bins=bins, labels=labels)

# 打印输出结果
print("原始数据:")
print(df[['ID', 'Age']])
print("\n离散化后的年龄分组:")
print(df[['ID', 'Age_Group']])

2.2 归一化

import pandas as pd
data = {'A': [10, 20, 30, 40, 50],
        'B': [100, 200, 300, 400, 500]}
df = pd.DataFrame(data)

# 方法一:使用 apply 函数
df_normalized = df.apply(lambda x: (x - x.min()) / (x.max() - x.min()))
print("Normalized DataFrame (Method 1):")
print(df_normalized)
# 方法二:使用 MinMaxScaler 类
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
df_normalized = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)
print("\nNormalized DataFrame (Method 2):")
print(df_normalized)

2.3 标准化

import pandas as pd
data = {'A': [10, 20, 30, 40, 50],
        'B': [100, 200, 300, 400, 500]}
df = pd.DataFrame(data)

# 方法一:使用 apply 函数
df_standardized = df.apply(lambda x: (x - x.mean()) / x.std())
print("Standardized DataFrame (Method 1):")
print(df_standardized)

# 方法二:使用 StandardScaler 类
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df_standardized = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)
print("\nStandardized DataFrame (Method 2):")
print(df_standardized)

三、综合应用

海伦女士一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的任选,但她并不是喜欢每一个人。经过一番总结,她发现自己交往过的人可以进行如下分类:不喜欢的人;魅力一般的人;极具魅力的人。海伦收集约会数据已经有了一段时间,她把这些数据存放在文件datingTestSet.csv中,每个样本数据占据一行,总共有1000行。

datingTestSet.csv数据下载,下载后解压缩

3.1 Min-Max标准化

Min-Max标准化是指对原始数据进行线性变换,将值映射到[0,1]之间,数据分布不变。
Min-Max标准化的计算公式为:

x=xmin(x)max(x)min(x)

公式中,x为原始数据中的一个数据,max(x)表示原始数据中的最大值,min(x)表示原始数据中的最小值。

# 借助Python的三方库pandas实现对数据集的读取与处理,numpy实现科学计算
# 代码主要通过jupyter notebook编写完成,复制时注意输出格式
import numpy as np
import pandas as pd

# 读取数据
df = pd.read_csv("datingTestSet.csv",header=None,names=['里程数','时间百分比','公升数','标签'])
labels = np.array(df['标签'])
df.drop('标签', axis=1, inplace=True)		# 删除标签值

print(df.head(10))   # 展示数据前十行

3.2 Z-Score标准化

Z-Score标准化是指基于原始数据的均值和标准差来进行数据的标准化,公式如下:

x=xμσ

公式中,x为原始数据中的一个数据,μ表示原始数据的均值,σ表示原始数据的标准差。

def Z_Score(data):    
    mean = np.mean(data)    # 均值
    std_dev = np.std(data)    # 标准差
    norm_data = (data - mean) / std_dev    
    return norm_data

norm_data = Z_Score(df)
print(norm_data.head(10))

3.3 数据解析与可视化

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.lines as mlines

# 数据预处理
def fileRead(fileName):
    # 打开文件
    fr = open(fileName)
    # 读取全部内容
    arraryOfLines = fr.readlines()
    # 求行数
    numberOfLines = len(arraryOfLines)
    # 生成 numberOfLines 行, 3 列的矩阵,方便后面存放数据
    returnMat = np.zeros((numberOfLines, 3))
    # 用于存放类别
    classLabelVector = []
    # 设置索引,用于循环
    index = 0
    # 开始循环读取
    for line in arraryOfLines:
        # 去除掉文件中的多余字符
        line = line.strip()
        # 用逗号对内容进行分割
        listFormLine = line.split(',')
        # 赋值
        returnMat[index, :] = list(map(float, listFormLine[0:3])) # Convert strings to float
        # 对类别数组进行赋值
        if listFormLine[-1] == 'didntLike':
            classLabelVector.append(1)
        if listFormLine[-1] == 'smallDoses':
            classLabelVector.append(2)
        if listFormLine[-1] == 'largeDoses':
            classLabelVector.append(3)
        index += 1
    return returnMat, classLabelVector


# 数据展示
def showData(datingDataMat, datingLabels):

    fig, axs = plt.subplots(nrows=1, ncols=3, sharex=False, sharey=False, figsize=(18, 6))

    LabelsColors = []
    for i in datingLabels:
        if i == 1:
            LabelsColors.append('black')
        if i == 2:
            LabelsColors.append('orange')
        if i == 3:
            LabelsColors.append('red')
    axs[0].scatter(x=np.round(datingDataMat[:, 0], 2), y=np.round(datingDataMat[:, 1], 2), color=LabelsColors, s=15, alpha=.5)
    axs0_title_text = axs[0].set_title('flight_play')
    axs0_xlabel_text = axs[0].set_xlabel('flight_time')
    axs0_ylabel_text = axs[0].set_ylabel('play_time')
    plt.setp(axs0_title_text, size=9, weight='bold', color='red')
    plt.setp(axs0_xlabel_text, size=7, weight='bold', color='black')
    plt.setp(axs0_ylabel_text, size=7, weight='bold', color='black')
    axs[1].scatter(x=np.round(datingDataMat[:, 0], 2), y=np.round(datingDataMat[:, 2], 2), color=LabelsColors, s=15, alpha=.5)
    # 设置标题,x轴label,y轴label
    axs1_title_text = axs[1].set_title('flight_eat')
    axs1_xlabel_text = axs[1].set_xlabel('flight')
    axs1_ylabel_text = axs[1].set_ylabel('eat')
    plt.setp(axs1_title_text, size=9, weight='bold', color='red')
    plt.setp(axs1_xlabel_text, size=7, weight='bold', color='black')
    plt.setp(axs1_ylabel_text, size=7, weight='bold', color='black')

    # 画出散点图,以datingDataMat矩阵的第二(玩游戏)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5
    axs[2].scatter(x=np.round(datingDataMat[:, 1], 2), y=np.round(datingDataMat[:, 2], 2), color=LabelsColors, s=15, alpha=.5)
    # 设置标题,x轴label,y轴label
    axs2_title_text = axs[2].set_title('play_eat')
    axs2_xlabel_text = axs[2].set_xlabel('play_time')
    axs2_ylabel_text = axs[2].set_ylabel('eat_weight')
    plt.setp(axs2_title_text, size=9, weight='bold', color='red')
    plt.setp(axs2_xlabel_text, size=7, weight='bold', color='black')
    plt.setp(axs2_ylabel_text, size=7, weight='bold', color='black')
    # 设置图例
    didntLike = mlines.Line2D([], [], color='black', marker='.',
                              markersize=6, label='didntLike')
    smallDoses = mlines.Line2D([], [], color='orange', marker='.',
                               markersize=6, label='smallDoses')
    largeDoses = mlines.Line2D([], [], color='red', marker='.',
                               markersize=6, label='largeDoses')
    # 添加图例
    axs[0].legend(handles=[didntLike, smallDoses, largeDoses])
    axs[1].legend(handles=[didntLike, smallDoses, largeDoses])
    axs[2].legend(handles=[didntLike, smallDoses, largeDoses])
    # 显示图片
    plt.show()

fileName = 'datingTestSet.csv'
datingDataMat, datingLabels = fileRead(fileName)
print("datingLabels is", datingLabels)
print("datingDataMat is", np.round(datingDataMat, 2))  # Round the data to 2 decimal places
showData(datingDataMat, datingLabels)

通过上面的图片我们不难发现一个问题,飞行里程数的数据一般都是成百上千,但是吃冰淇淋的总量也就几升而已,这显然会影响欧式距离公式的计算结果,就如我们小时候画直角坐标系的时候,如果x轴y轴数值差距过大,我们往往会为x,y轴设立不同的比例,以此来让数据更加规整,那是显示层面的,同理为了让欧式距离公式计算更加精准,我们常用的方法一般为数值归一化,将取值范围取到0到1或者-1到1之间。

总结

数据的规范化和归一化是数据预处理中不可或缺的重要步骤,它能够消除数据特征之间的量纲差异,加速模型的收敛速度,提高模型的稳定性和鲁棒性,从而有效地改善了数据分析和机器学习任务的结果。在实际应用中,选择合适的规范化或归一化方法,并结合数据的特点和任务的要求,可以更好地发挥数据预处理的作用,提升模型的性能和效果。数据规范化可以提高模型精度:规范化可以让不同维度之间的特征在数值上有一定比较性,可以大大提高分类器的准确性;提升收敛速度:数据规范化后,最优解的寻优过程明显会变得平缓,更容易正确的收敛到最优解。

参考文献

  1. 分清规范化(标准化、归一化)、离散化、正则化
  2. 使用python做数据合规化
  3. K近邻算法经典案例实现之海伦约会
posted @   郝hai  阅读(999)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
历史上的今天:
2023-04-07 存储论——经济订货批量EOQ的R图解
点击右上角即可分享
微信分享提示