在机器学习模型处理数据时,经常需要对数据进行预处理以确保模型能够更有效地工作。特征缩放就是这样一种预处理过程,它将数据转换为更易于模型处理的形式。特征缩放的目的是将数据集中的特征归一化到有限的范围内。本文将讨论特征缩放的必要性以及常用的特征缩放技术。
在现实世界的数据集中,许多特征的值范围很广。以房价预测数据集为例,它可能包含诸如卧室数量、房屋面积等特征。卧室数量可能在1到5之间变化,而房屋面积可能在500到2000之间变化,这两个特征的范围差异很大。许多使用欧几里得距离作为相似度度量标准的机器学习算法将无法合理地识别较小的特征,例如卧室数量,而在实际情况中,这可能是一个非常重要的指标。例如线性回归、逻辑回归、KNN等算法。
绝对最大值缩放是通过找到数据集中特征的绝对最大值,然后将该列中的所有值除以该最大值来实现的。如果对所有数值列都这样做,那么它们的值将介于-1和1之间。这种技术的主要缺点是对异常值敏感。例如,考虑房屋面积特征,如果99%的房屋面积小于1000平方英尺,即使只有1个房屋面积为20000平方英尺,那么其他房屋的值将被缩放到小于0.05。
接下来,将使用正弦和余弦函数来展示缩放技术如何影响它们的幅度。正弦函数的值将在-1和+1之间变化,而50倍的余弦函数的值将在-50和+50之间变化。
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0,20,0.4)
y1 = np.sin(x)
y2 = np.cos(x)*50
plt.plot(x,y1,'red')
plt.plot(x,y2,'blue')
plt.show()
如所见,如果不进行缩放,甚至无法看出红色线条是正弦曲线,它看起来就像一条与蓝色大曲线相比的直线。
y1_new = y1/max(y1)
y2_new = y2/max(y2)
从图中可以看出,缩放后两个数据集的范围都在-1到+1之间。这可能会变得非常小,如果有多个数据点低于0.01,即使只有一个大的异常值。
在最小-最大缩放中,会从数据集中的最小值中减去所有值,然后除以数据集的范围(最大值-最小值)。在这种情况下,数据集将在所有情况下都介于0和1之间,而在前一种情况下,它介于-1和+1之间。同样,这种技术也容易受到异常值的影响。
y1_new = (y1-min(y1))/(max(y1)-min(y1))
y2_new = (y2-min(y2))/(max(y2)-min(y2))
plt.plot(x,y1_new,'red')
plt.plot(x,y2_new,'blue')
与前一种情况不同,这里将使用平均值而不是最小值。在缩放中,正在改变数据的范围,而在归一化中,正在改变数据分布的形状。
y1_new = (y1-np.mean(y1))/(max(y1)-min(y1))
y2_new = (y2-np.mean(y2))/(max(y2)-min(y2))
plt.plot(x,y1_new,'red')
plt.plot(x,y2_new,'blue')
在标准化中,计算每个数据点的z值,并将这些值替换为这些值。这将确保所有特征都围绕均值中心,并且标准差值为1。如果特征是正态分布的,比如薪水或年龄,这是最好的选择。
y1_new = (y1-np.mean(y1))/np.std(y1)
y2_new = (y2-np.mean(y2))/np.std(y2)
plt.plot(x,y1_new,'red')
plt.plot(x,y2_new,'blue')
在这种方法中,需要从所有数据点中减去中位数值,然后除以四分位距(IQR)值。IQR是25%分位数点和50%分位数点之间的距离。这种方法将中位数值定位在零,并且对异常值具有鲁棒性。
from scipy import stats
IQR1 = stats.iqr(y1, interpolation = 'midpoint')
y1_new = (y1-np.median(y1))/IQR1
IQR2 = stats.iqr(y2, interpolation = 'midpoint')
y2_new = (y2-np.median(y2))/IQR2
plt.plot(x,y1_new,'red')
plt.plot(x,y2_new,'blue')
让来看一个大学录取数据集的例子,目标是根据给定的其他特征预测每个学生的录取机会。可以从下面的链接下载数据集。
import pandas as pd
df = pd.read_csv("Admission_Predict.csv")
df.head()
数据集包含各种特征,范围不同。第一列“序列号”并不重要,所以将删除它。然后将数据集分割为训练集和测试集。
df.drop("Serial No.",axis=1,inplace=True)
y = df['Chance of Admit']
df.drop("Chance of Admit",axis=1,inplace=True)
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(df,y,test_size=0.2)
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(x_train,y_train)
pred = lr.predict(x_test)
from sklearn import metrics
rmse = np.sqrt(metrics.mean_squared_error(y_test,pred))
rmse
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit(df)
df = sc.transform(df)
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(df,y,test_size=0.2)
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(x_train,y_train)
pred = lr.predict(x_test)
from sklearn import metrics
rmse = np.sqrt(metrics.mean_squared_error(y_test,pred))
rmse