Python数据归一化:使用Scikit-learn提升机器学习模型性能
引言
在本文中,你将尝试使用scikit-learn(也被称为sklearn)在Python中进行数据归一化的一些不同方法。当你归一化数据时,你改变了数据的范围。数据通常被重新缩放到0和1之间,因为机器学习算法在特征较小的范围上表现得更好或收敛得更快。在对数据进行机器学习模型训练之前,通常会先对数据进行归一化,以获得更好、更快的结果。归一化还使得训练过程对特征的范围不敏感,训练后的系数也更优。
通过重新缩放以使特征更适合训练的过程称为特征缩放。
本教程使用Python版本3.9.13和scikit-learn版本1.0.2进行了测试。
使用scikit-learn的preprocessing.normalize()
函数对数据进行标准化
你可以使用scikit-learn的preprocessing.normalize()
函数来归一化类数组数据集。
normalize()
函数将向量单独缩放到单位范数,使得向量的长度为1。normalize()
函数的默认范数是L2范数,也称为欧几里得范数。L2范数的公式是每个值的平方和的平方根。尽管使用normalize()
函数会使值介于0和1之间,但这与简单地将值缩放到0和1之间是不同的。
使用normalize()
函数归一化数组
你可以使用normalize()
函数归一化一维NumPy数组。
导入sklearn.preprocessing
模块:
from sklearn import preprocessing
导入NumPy并创建一个数组:
import numpy as np
x_array = np.array([2,3,5,6,7,4,8,7,6])
对数组使用normalize()
函数,沿行归一化数据,此处为一维数组:
normalized_arr = preprocessing.normalize([x_array])
print(normalized_arr)
运行完整的示例代码,演示如何使用normalize()
函数归一化NumPy数组:
from sklearn import preprocessing
import numpy as np
x_array = np.array([2,3,5,6,7,4,8,7,6])
normalized_arr = preprocessing.normalize([x_array])
print(normalized_arr)
输出结果为:
[[0.11785113 0.1767767 0.29462783 0.35355339 0.41247896 0.23570226 0.47140452 0.41247896 0.35355339]]
输出结果显示所有值都在0到1的范围内。如果你将输出中的每个值平方然后相加,结果将是1,或者非常接近1。
使用normalize()
函数归一化DataFrame的列
这是文章《如何使用scikit-learn在Python中归一化数据》的第2部分(共6部分)。
在pandas DataFrame中,特征是列,样本是行。您可以将DataFrame列转换为NumPy数组,然后对数组中的数据进行归一化处理。
本节及后续章节的示例均使用加利福尼亚住房数据集(California Housing dataset)。
示例代码的第一部分导入模块、加载数据集、创建DataFrame并打印数据集描述:
import numpy as np
from sklearn import preprocessing
from sklearn.datasets import fetch_california_housing
# 创建DataFrame
california_housing = fetch_california_housing(as_frame=True)
# 打印数据集描述
print(california_housing.DESCR)
请注意,as_frame
参数设置为 True
以将 california_housing
对象创建为 pandas DataFrame。
输出包含数据集描述的以下摘录,您可以根据此摘录选择要归一化的特征:
.. _california_housing_dataset:
加利福尼亚住房数据集
--------------------------
**数据集特征:**
:实例数量: 20640
:属性数量: 8个数值型预测属性和目标属性
:属性信息:
- MedInc 街区组的收入中位数
- HouseAge 街区组的房屋年龄中位数
- AveRooms 每户平均房间数
- AveBedrms 每户平均卧室数
- Population 街区组人口
- AveOccup 每户平均成员数
- Latitude 街区组纬度
- Longitude 街区组经度
...
接下来,将一列(特征)转换为数组并打印。本例使用“HouseAge”列:
x_array = np.array(california_housing['HouseAge'])
print("HouseAge 数组: ",x_array)
最后,使用 normalize()
函数对数据进行归一化并打印结果数组:
normalized_arr = preprocessing.normalize([x_array])
print("归一化后的HouseAge数组: ",normalized_arr)
运行完整示例以演示如何使用 normalize()
函数归一化特征:
这是文章《如何使用scikit-learn在Python中归一化数据》的第3部分(共6部分)。
from sklearn import preprocessing
import numpy as np
from sklearn.datasets import fetch_california_housing
california_housing = fetch_california_housing(as_frame=True)
# print(california_housing.DESCR)
x_array = np.array(california_housing.data['HouseAge'])
print("房屋年龄数组: ",x_array)
normalized_arr = preprocessing.normalize([x_array])
print("归一化后的房屋年龄数组: ",normalized_arr)
输出结果如下:
房屋年龄数组: [41. 21. 52. ... 17. 18. 16.]
归一化后的房屋年龄数组: [[0.00912272 0.00467261 0.01157028 ... 0.00378259 0.0040051 0.00356009]]
输出结果显示,normalize()
函数改变了房屋中位年龄值的数组,使得这些值的平方和的平方根等于一。换句话说,这些值使用 L2 范数被缩放到了单位长度。
使用 normalize()
函数按行或按列归一化数据集
当您在不将特征或列转换为数组进行处理的情况下归一化数据集时,数据会按行进行归一化。normalize()
函数的默认轴是 1,这意味着每个样本(即每一行)都被归一化。
以下示例演示了使用默认轴归一化加州住房数据集:
from sklearn import preprocessing
import pandas as pd
from sklearn.datasets import fetch_california_housing
california_housing = fetch_california_housing(as_frame=True)
d = preprocessing.normalize(california_housing.data)
scaled_df = pd.DataFrame(d, columns=california_housing.data.columns)
print(scaled_df)
输出结果如下:
这是文章《如何使用scikit-learn在Python中归一化数据》的第4部分(共6部分)。
MedInc HouseAge AveRooms ... AveOccup Latitude Longitude
0 0.023848 0.117447 0.020007 ... 0.007321 0.108510 -0.350136
1 0.003452 0.008734 0.002594 ... 0.000877 0.015745 -0.050829
2 0.014092 0.100971 0.016093 ... 0.005441 0.073495 -0.237359
3 0.009816 0.090449 0.010119 ... 0.004432 0.065837 -0.212643
4 0.006612 0.089394 0.010799 ... 0.003750 0.065069 -0.210162
... ... ... ... ... ... ... ...
20635 0.001825 0.029242 0.005902 ... 0.002995 0.046179 -0.141637
20636 0.006753 0.047539 0.016147 ... 0.008247 0.104295 -0.320121
20637 0.001675 0.016746 0.005128 ... 0.002291 0.038840 -0.119405
20638 0.002483 0.023932 0.007086 ... 0.002823 0.052424 -0.161300
20639 0.001715 0.011486 0.003772 ... 0.001879 0.028264 -0.087038
[20640 rows x 8 columns]
输出显示,值是按行归一化的,这意味着每个样本都被归一化,而不是每个特征。
然而,您可以通过指定轴(axis)来按特征进行归一化。
以下示例演示了如何使用 axis=0
按特征归一化加利福尼亚住房数据集:
from sklearn import preprocessing
import pandas as pd
from sklearn.datasets import fetch_california_housing
california_housing = fetch_california_housing(as_frame=True)
d = preprocessing.normalize(california_housing.data, axis=0)
scaled_df = pd.DataFrame(d, columns=california_housing.data.columns)
print(scaled_df)
输出结果如下:
MedInc HouseAge AveRooms ... AveOccup Latitude Longitude
0 0.013440 0.009123 0.008148 ... 0.001642 0.007386 -0.007114
1 0.013401 0.004673 0.007278 ... 0.001356 0.007383 -0.007114
2 0.011716 0.011570 0.009670 ... 0.001801 0.007381 -0.007115
3 0.009110 0.011570 0.006787 ... 0.001638 0.007381 -0.007116
4 0.006209 0.011570 0.007329 ... 0.001402 0.007381 -0.007116
... ... ... ... ... ... ... ...
20635 0.002519 0.005563 0.005886 ... 0.001646 0.007698 -0.007048
20636 0.004128 0.004005 0.007133 ... 0.002007 0.007700 -0.007055
20637 0.002744 0.003783 0.006073 ... 0.001495 0.007689 -0.007056
20638 0.003014 0.004005 0.006218 ... 0.001365 0.007689 -0.007061
20639 0.003856 0.003560 0.006131 ... 0.001682 0.007677 -0.007057
[20640 rows x 8 columns]
当您检查输出时,会注意到“HouseAge”列的结果与您在前面的示例中将“HouseAge”列转换为数组并进行归一化时得到的结果一致。
使用scikit-learn的preprocessing.MinMaxScaler()
函数归一化数据
您可以使用scikit-learn的preprocessing.MinMaxScaler()
函数通过将数据缩放到一定范围来归一化每个特征。
MinMaxScaler()
函数会单独缩放每个特征,使值具有给定的最小值和最大值,默认分别为0和1。
将特征值缩放到0到1之间的公式是:

从每个数据项中减去最小值,然后将结果除以范围(其中范围是最大值和最小值之间的差)。
以下示例演示了如何使用MinMaxScaler()
函数归一化加利福尼亚住房数据集:
from sklearn import preprocessing
import pandas as pd
from sklearn.datasets import fetch_california_housing
california_housing = fetch_california_housing(as_frame=True)
scaler = preprocessing.MinMaxScaler()
d = scaler.fit_transform(california_housing.data)
scaled_df = pd.DataFrame(d, columns=california_housing.data.columns)
print(scaled_df)
输出结果为:
MedInc HouseAge AveRooms … AveOccup Latitude Longitude
0 0.539668 0.784314 0.043512 … 0.001499 0.567481 0.211155
1 0.538027 0.392157 0.038224 … 0.001141 0.565356 0.212151
2 0.466028 1.000000 0.052756 … 0.001698 0.564293 0.210159
3 0.354699 1.000000 0.035241 … 0.001493 0.564293 0.209163
4 0.230776 1.000000 0.038534 … 0.001198 0.564293 0.209163
… … … … … … … …
20635 0.073130 0.470588 0.029769 … 0.001503 0.737513 0.324701
20636 0.141853 0.333333 0.037344 … 0.001956 0.738576 0.312749
20637 0.082764 0.313725 0.030904 … 0.001314 0.732200 0.311753
20638 0.094295 0.333333 0.031783 … 0.001152 0.732200 0.301793
20639 0.130253 0.294118 0.031252 … 0.001549 0.725824 0.309761
[20640 行 x 8 列]
输出结果显示,数值已被缩放到默认的最小值为0,最大值为1。
您也可以为缩放指定不同的最小值和最大值。在以下示例中,最小值为0,最大值为2:
这是文章《如何使用scikit-learn在Python中归一化数据》的第6部分(共6部分)。
from sklearn import preprocessing
import pandas as pd
from sklearn.datasets import fetch_california_housing
california_housing = fetch_california_housing(as_frame=True)
scaler = preprocessing.MinMaxScaler(feature_range=(0, 2))
d = scaler.fit_transform(california_housing.data)
scaled_df = pd.DataFrame(d, columns=california_housing.data.columns)
print(scaled_df)
输出结果如下:
MedInc HouseAge AveRooms ... AveOccup Latitude Longitude
0 1.079337 1.568627 0.087025 ... 0.002999 1.134963 0.422311
1 1.076054 0.784314 0.076448 ... 0.002281 1.130712 0.424303
2 0.932056 2.000000 0.105513 ... 0.003396 1.128587 0.420319
3 0.709397 2.000000 0.070482 ... 0.002987 1.128587 0.418327
4 0.461552 2.000000 0.077068 ... 0.002397 1.128587 0.418327
...
20635 0.146260 0.941176 0.059538 ... 0.003007 1.475027 0.649402
20636 0.283706 0.666667 0.074688 ... 0.003912 1.477152 0.625498
20637 0.165529 0.627451 0.061808 ... 0.002629 1.464400 0.623506
20638 0.188591 0.666667 0.063565 ... 0.002303 1.464400 0.603586
20639 0.260507 0.588235 0.062505 ... 0.003098 1.451647 0.619522
[20640 rows x 8 columns]
输出结果显示,所有值都被缩放到最小值为0,最大值为2。
总结
在本文中,您学习了如何使用scikit-learn的两个函数,通过按样本(行)和按特征(列)两种不同方式来归一化数据。您可以继续学习其他机器学习主题。