“千克”和“毫升”(毫升与克)

毫升与克(“千克”和“毫升”)

图源:unsplash

你一定曾遇到过这样一个数据集,它具有多个特征,涵盖了不同程度的数量级、范围和单位。这会是一个巨大的阻碍,很少的机器学习算法对这些特征高度敏感。

其实类似的问题并不少见。例如,一个特征的单位是千克,另一个的单位是克,还有一个的单位是升。当它们所呈现的内容差异如此之大时,该如何使用这些特征呢?

该是特征缩放上场的时候了。这是数据预处理阶段的关键部分,但很多初学者忽视了这一点,这会损害他们的机器学习模型。

特性缩放可以显著提高某些机器学习算法的性能,而对其他算法则完全不起作用。这种怪事背后的原因可能是什么?

另外,归一化和标准化的区别是什么?这是机器学习中最常用的两种特征缩放技术,但它们不易理解。什么时候应该使用哪种技术?

本文将解答你关于特征缩放的疑问,将在Python中实现特性缩放,让你对它如何适用于不同的机器学习算法有一个实践上的理解。

为什么要使用特征缩放?

需要解决的第一个问题是,为什么需要缩放数据集中的变量。一些机器学习算法对特征缩放敏感,而另一些则几乎不变。

基于距离的算法

距离算法(例如KNN、K-means和SVM)受特征范围的影响最大。这是因为在后台,算法使用数据点之间的距离来确定它们的相似性。

例如,假如有一些数据,其中包含高中学生的CGPA分数(从0到5)和他们的未来收入(以千卢比为单位):

由于这两个特征具有不同的缩放程度,所以有可能给更高量级的特征更高的权重。这将影响机器学习算法的性能,显然,我们不希望算法偏向于一个特征。

因此,我们在使用基于距离的算法之前对数据进行缩放,这样所有的特征对结果的影响都是相等的。

当比较学生A和B的数据点之间的欧氏距离、B和C的数据点之间的欧氏距离,缩放前后的效果是明显的,如下所示:

· 缩放前AB距离 =>

· 缩放前BC距离 =>

· 缩放后AB距离 =>

· 缩放后BC距离 =>

缩放将所有特征都带入计算,并且现在的距离比缩放之前更具有可比性。

基于梯度下降的算法

使用梯度下降作为优化技术的机器学习算法(例如线性回归、逻辑回归、神经网络等)要求对数据进行缩放。请看下面的梯度下降公式:

公式中特征值X的存在将影响梯度下降的步长。特征范围的差异将导致每个特征的步长不同。为确保梯度下降平稳地向最小值移动,并确保所有特征的梯度下降步骤均以相同的速率更新,我们在将数据输入模型之前先对数据进行缩放。

具有相似缩放程度的特征可以帮助梯度下降更快地收敛到最小值。

基于树的算法

另一方面,基于树的算法对特征缩放非常不敏感。考虑一下,决策树仅基于单个特征拆分节点。决策树在特征上分割节点,从而增加了节点的同质性。特征上的拆分不受其他特征影响。

图源:unsplash

因此,其余特征对拆分几乎没有影响。这就是特征缩放不改变算法性能的原因!

什么是归一化?

归一化是一种缩放技术,对值进行移位和重新缩放,以使它们最终在0到1之间变化。这也称为“最小-最大”缩放。

这是归一化的公式:

其中,Xmax和Xmin分别为特征的最大值和最小值。

· 当X的值是列中的最小值时,分子为0,因此X '为0

· 相反,当X的值是列中的最大值时,分子等于分母,因此X '的值是1

· 如果X的值在最小值和最大值之间,那么X '的值在0和1之间

什么是标准化?

标准化是另一种缩放技术,其中值以具有单位标准偏差的平均值为中心。这意味着特征的均值变为零,结果分布具有单位标准差。

这是标准化的公式:

μ为特征值的均值,σ为特征值的标准差。注意,在这种情况下,值并不局限于特定的范围。

图源:unsplash

现在,你脑海中最大的问题一定是什么时候应该使用归一化,什么时候应该使用标准化?下面就来看看!

最大的问题——归一化还是标准化?

归一化与标准化是机器学习初学者的一个永恒的问题。

· 如果数据分布不遵循高斯分布,归一化是很有用的。这在不假设数据分布的算法(如k近邻和神经网络)中很有用。

· 相反,如果数据服从高斯分布,标准化是有用的。然而,这并不一定对。另外,与归一化不同,标准化没有边界范围。因此,即使数据中有异常值,也不会受到标准化的影响。

然而,最终使用归一化还是标准化将取决于问题和正在使用的机器学习算法。没有硬性的规则来确定何时将数据归一化或标准化。可以从将模型拟合为原始的、归一化的和标准化的数据开始,并比较性能以获得最佳结果。

好的做法是将缩放器与训练数据进行拟合,然后利用缩放器对测试数据进行转换。这将避免模型测试过程中的任何数据泄漏。此外,通常不需要调整目标值。

在Python中实现特征缩放

现在是有趣的部分,将学到的东西付诸实践。采用DataHack平台的BigMart数据集,可将特征缩放应用于一些机器学习算法。

图源:unsplash

跳过预处理步骤,因为它们超出了本教程的范围。但是可以在这篇文章中找到预处理的详细解释。这些步骤将使你能够在黑客马拉松排行榜上排名前20位,因此值得一试!

因此,首先将数据分为训练和测试集:

       # spliting training and testing data
    from sklearn.model_selection import train_test_split
         X= df
    y= target
         X_train, X_test, y_train, y_test =train_test_split(X,y,test_size=0.2,random_state=27)

在转到特征缩放部分之前,使用pd.describe()方法浏览有关数据的详细信息:

可以看到,特征的值范围存在巨大差异:Item_Visibility,Item_Weight,Item_MRP和Outlet_ Establishmentment_Year。尝试使用特征缩放来解决该问题!

注意:特征Item_Visibility中有负值,这是因为已采用对数转换来处理特征中的偏斜度。

使用sklearn进行归一化

为了归一化数据,需要从sklearn库导入MinMaxScalar并将其应用于数据集。所以,下面就开始吧!

         # data normalization with sklearn
     from sklearn.preprocessing importMinMaxScaler            # fitscaler on training data
     norm=MinMaxScaler().fit(X_train)            #transform training data
     X_train_norm= norm.transform(X_train)            #transform testing dataabs
     X_test_norm= norm.transform(X_test)

请看归一化如何影响数据集:

现在,所有特征的最小值均为0,最大值为1。完美!

接下来,尝试对数据进行标准化。

使用sklearn进行标准化

为了对数据进行标准化,需要从sklearn库中导入StandardScalar并将其应用于数据集。方法如下:

         # data standardization with sklearn
     from sklearn.preprocessing importStandardScaler
            #numerical features
     num_cols= ['Item_Weight','Item_Visibility','Item_MRP','Outlet_Establishment_Year']
            # applystandardization on numerical features     for i in num_cols:
         # fit on trainingdata
         scale =StandardScaler().fit(X_train[[i]])
         # transform thetraining data
         X_train_stand[i] = scale.transform(X_train_stand[[i]])
         # transform thetesting data
         X_test_stand[i] = scale.transform(X_test_stand[[i]])

可以发现,只对数字列应用了标准化,而没有对其他的单一热编码(One-HotEncoded)特征应用标准化。标准化单一热编码特征意味着将类别特征重新分布。你不会想这么做的!

但是为什么在对数据进行归一化时没有做同样的事情呢?因为单一热编码的特征已经在0到1之间了。所以,标准化不会影响它们的值。

好的,来看看标准化是如何改变数据的:

现在,特征的值以平均值为中心,具有单位标准偏差分布。太棒了!

比较未缩放、归一化和标准化的数据

可视化数据以了解当前分布总是很不错的。可以使用箱线图来比较未缩放数据和已缩放数据。

你会注意到,特征缩放考虑到了方方面面。这些特征现在更具可比性,并且会对学习模型产生类似的影响。

将缩放应用于机器学习算法

是时候在数据上训练一些机器学习算法,以比较不同缩放技术对算法性能的影响。特别注意缩放对三种算法的影响:K-近邻、支持向量回归和决策树。

K-近邻(KNN)

如前所述,KNN是一种基于距离的算法,受特征范围的影响。来看看缩放前后数据对性能的影响:

         # training a KNN model
     from sklearn.neighbors importKNeighborsRegressor     # measuring RMSE score
     from sklearn.metrics import mean_squared_error            # knn
     knn=KNeighborsRegressor(n_neighbors=7)
            rmse= []            # raw,normalized and standardized training and testing data
     trainX= [X_train, X_train_norm, X_train_stand]
     testX= [X_test, X_test_norm, X_test_stand]            # modelfitting and measuring RMSE
     for i inrange(len(trainX)):         # fit
         knn.fit(trainX[i],y_train)         # predict
         pred = knn.predict(testX[i])         # RMSE
         rmse.append(np.sqrt(mean_squared_error(y_test,pred)))            #visualizing the result
     df_knn= pd.DataFrame({'RMSE':rmse},index=['Original','Normalized','Standardized'])
     df_knn

可以看到,特征缩放降低了KNN模型的RMSE分数。具体来说,归一化数据的性能比标准化数据稍好一些。

注意:之所以测量RMSE,因为这个比赛中评估RMSE。

图源:unsplash

支持向量回归(SVR)

SVR是另一种基于距离的算法。所以,来看看它是在归一还是或标准化的情况下工作得更好:

         # training an SVR model
     from  sklearn.svm importSVR     # measuring RMSE score
     from sklearn.metrics import mean_squared_error            # SVR
     svr=SVR(kernel='rbf',C=5)
            rmse= []            # raw,normalized and standardized training and testing data
     trainX= [X_train, X_train_norm, X_train_stand]
     testX= [X_test, X_test_norm, X_test_stand]            # modelfitting and measuring RMSE
     for i inrange(len(trainX)):         # fit
         svr.fit(trainX[i],y_train)         # predict
         pred = svr.predict(testX[i])         # RMSE
         rmse.append(np.sqrt(mean_squared_error(y_test,pred)))            #visualizing the result   
     df_svr= pd.DataFrame({'RMSE':rmse},index=['Original','Normalized','Standardized'])
     df_svr

可以看到特征缩放确实降低了RMSE的分数。标准化数据的表现优于归一化数据。为什么会这样呢?

sklearn文档表明,SVR使用RBF核,假设所有特征都以0为中心,方差相同。这是因为一个方差大于其他方差的特征会阻止评估器从这些特征中学习。

决策树

已知特征缩放对于决策树没有影响。此处展示一个实例,展示决策树是如何操作数据的:

# training a Decision Tree model
     from sklearn.tree importDecisionTreeRegressor     # measuring RMSE score
     from sklearn.metrics import mean_squared_error            #Decision tree
     dt=DecisionTreeRegressor(max_depth=10,random_state=27)
            rmse= []            # raw,normalized and standardized training and testing data
     trainX= [X_train,X_train_norm,X_train_stand]
     testX= [X_test,X_test_norm,X_test_stand]            # modelfitting and measuring RMSE
     for i inrange(len(trainX)):         # fit
         dt.fit(trainX[i],y_train)         # predict
         pred = dt.predict(testX[i])         # RMSE
         rmse.append(np.sqrt(mean_squared_error(y_test,pred)))            #visualizing the result   
     df_dt= pd.DataFrame({'RMSE':rmse},index=['Original','Normalized','Standardized'])
     df_dt

可以看到,RMSE分数在特征缩放时并一点也没变。因此,可以放心在数据上使用基于树的算法!

图源:unsplash

要记住的是,何时使用归一化还是标准化永远没有标准答案。这完全取决于数据和使用的算法。接下来轮到你了,试试用其他算法进行特征缩放吧。

(0)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 PTU@FOXMAIL.COM 举报,一经查实,立刻删除。