为什么缩放 SVD 运行 比随机森林模型中未缩放的 SVD 慢得多?
Why would a scaled SVD run so much slower than an unscaled SVD in a Random Forest model?
我正在 Python 通过重新创建常见的“预测垃圾邮件”项目来研究机器学习和 NLP。我完成了清理和预处理的所有初步步骤,直到我得到一个包含 2,000 个术语的 TF-IDF 文档术语矩阵。然后我执行 SVD 将其减少到 300 个项(或组件)并缩放结果,以便我可以 运行 一个快速的逻辑分类器来为以后的模型获得基准。
在项目的后期,在构建随机森林时,我意识到我忘记注释掉下面的缩放器并且正在使用缩放的 SVD 构建森林,这是完全没有必要的。然而,我没有意识到与未缩放的 SVD 相比,这会降低随机森林的速度,更糟糕的是,灵敏度也降低了大约 10%。
谁能帮我理解一下为什么会这样?
以下是具有最佳(最高灵敏度)未缩放 SVD 的网格搜索结果:
Elapsed: 1348 s
Best params: {'max_depth': 20, 'max_features': 250, 'min_samples_split': 10, 'n_estimators': 200}
Confusion matrix on validation set:
pred_neg pred_pos
neg 844 2
pos 5 124
Evaluation metrics:
accuracy: 0.9928
sensitivity: 0.9612
specificity: 0.9976
以下是具有最佳(最高灵敏度)缩放 SVD 的网格搜索结果:
Elapsed: 5297 s
Best params: {'max_depth': 5, 'max_features': 250, 'min_samples_split': 5, 'n_estimators': 200}
Confusion matrix on validation set:
pred_neg pred_pos
neg 838 8
pos 18 111
Evaluation metrics:
accuracy: 0.9733
sensitivity: 0.8605
specificity: 0.9905
罪魁祸首是:
from scipy.sparse.linalg import svds
from sklearn.utils.extmath import svd_flip
from sklearn.preprocessing import MaxAbsScaler
def perform_SVD(X, n_components=300):
# transpose to a term-document matrix
U, Sigma, VT = svds(X.asfptype().T,
k=n_components)
# reverse outputs
Sigma = Sigma[::-1]
U, VT = svd_flip(U[:, ::-1], VT[::-1])
# transpose to get V
V = VT.T
# scale for logistic classifier only
# can't take log of negative numbers
# ends up predicting ham base rate
# comment out for random forests!
scaler = MaxAbsScaler()
X_scaled = scaler.fit_transform(V)
return X_scaled
这并不奇怪。假设您对分类感兴趣,并且您有一个如下所示的数据集 -
如果你试图用决策树来拟合它,它很容易找到决策边界,因此你的分类精度会非常好。
现在想象一下,如果您首先尝试扩展它。新数据集将如下所示 -
如您所见,数据之间有更多的重叠,因此模型更难找到决策边界。
当您缩放数据时,您会使两个轴彼此靠近。这可能会使它们难以区分。
此时您可能想知道,如果是这种情况,我们为什么还要费心进行这种重新缩放。毕竟,无论您使用什么模型,都会看到这种效果。虽然这是真的,而且这样做可能会降低数据的可区分性,但在像神经网络这样的模型中,如果你不进行这种缩放操作,就会出现很多其他的缺点。就像一个特征的权重被人为膨胀,或者梯度流动不正常等等。在那种情况下,缩放的优点可能会超过缺点,您仍然可以得到一个好的模型。
关于你的问题为什么会有速度上的差异,同样的效果,随机森林可能要搜索更长的时间才能在参数相同的后一种情况下得到很好的拟合。这并不奇怪。
这是用于生成图的代码 -
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MaxAbsScaler
std = 7
X = np.random.multivariate_normal([2, 2], [[std, 0], [0, std]], size=100)
Y = np.random.multivariate_normal([10, 10], [[std, 0], [0, std]], size=100)
plt.scatter(X[:, 0], X[:, 1])
plt.scatter(Y[:, 0], Y[:, 1])
plt.show()
scaler = MaxAbsScaler()
X_scaled = scaler.fit_transform(X)
Y_scaled = scaler.fit_transform(Y)
plt.scatter(X_scaled[:, 0], X_scaled[:, 1])
plt.scatter(Y_scaled[:, 0], Y_scaled[:, 1])
plt.show()
我正在 Python 通过重新创建常见的“预测垃圾邮件”项目来研究机器学习和 NLP。我完成了清理和预处理的所有初步步骤,直到我得到一个包含 2,000 个术语的 TF-IDF 文档术语矩阵。然后我执行 SVD 将其减少到 300 个项(或组件)并缩放结果,以便我可以 运行 一个快速的逻辑分类器来为以后的模型获得基准。
在项目的后期,在构建随机森林时,我意识到我忘记注释掉下面的缩放器并且正在使用缩放的 SVD 构建森林,这是完全没有必要的。然而,我没有意识到与未缩放的 SVD 相比,这会降低随机森林的速度,更糟糕的是,灵敏度也降低了大约 10%。
谁能帮我理解一下为什么会这样?
以下是具有最佳(最高灵敏度)未缩放 SVD 的网格搜索结果:
Elapsed: 1348 s
Best params: {'max_depth': 20, 'max_features': 250, 'min_samples_split': 10, 'n_estimators': 200}
Confusion matrix on validation set:
pred_neg pred_pos
neg 844 2
pos 5 124
Evaluation metrics:
accuracy: 0.9928
sensitivity: 0.9612
specificity: 0.9976
以下是具有最佳(最高灵敏度)缩放 SVD 的网格搜索结果:
Elapsed: 5297 s
Best params: {'max_depth': 5, 'max_features': 250, 'min_samples_split': 5, 'n_estimators': 200}
Confusion matrix on validation set:
pred_neg pred_pos
neg 838 8
pos 18 111
Evaluation metrics:
accuracy: 0.9733
sensitivity: 0.8605
specificity: 0.9905
罪魁祸首是:
from scipy.sparse.linalg import svds
from sklearn.utils.extmath import svd_flip
from sklearn.preprocessing import MaxAbsScaler
def perform_SVD(X, n_components=300):
# transpose to a term-document matrix
U, Sigma, VT = svds(X.asfptype().T,
k=n_components)
# reverse outputs
Sigma = Sigma[::-1]
U, VT = svd_flip(U[:, ::-1], VT[::-1])
# transpose to get V
V = VT.T
# scale for logistic classifier only
# can't take log of negative numbers
# ends up predicting ham base rate
# comment out for random forests!
scaler = MaxAbsScaler()
X_scaled = scaler.fit_transform(V)
return X_scaled
这并不奇怪。假设您对分类感兴趣,并且您有一个如下所示的数据集 -
如果你试图用决策树来拟合它,它很容易找到决策边界,因此你的分类精度会非常好。
现在想象一下,如果您首先尝试扩展它。新数据集将如下所示 -
如您所见,数据之间有更多的重叠,因此模型更难找到决策边界。
当您缩放数据时,您会使两个轴彼此靠近。这可能会使它们难以区分。
此时您可能想知道,如果是这种情况,我们为什么还要费心进行这种重新缩放。毕竟,无论您使用什么模型,都会看到这种效果。虽然这是真的,而且这样做可能会降低数据的可区分性,但在像神经网络这样的模型中,如果你不进行这种缩放操作,就会出现很多其他的缺点。就像一个特征的权重被人为膨胀,或者梯度流动不正常等等。在那种情况下,缩放的优点可能会超过缺点,您仍然可以得到一个好的模型。
关于你的问题为什么会有速度上的差异,同样的效果,随机森林可能要搜索更长的时间才能在参数相同的后一种情况下得到很好的拟合。这并不奇怪。
这是用于生成图的代码 -
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MaxAbsScaler
std = 7
X = np.random.multivariate_normal([2, 2], [[std, 0], [0, std]], size=100)
Y = np.random.multivariate_normal([10, 10], [[std, 0], [0, std]], size=100)
plt.scatter(X[:, 0], X[:, 1])
plt.scatter(Y[:, 0], Y[:, 1])
plt.show()
scaler = MaxAbsScaler()
X_scaled = scaler.fit_transform(X)
Y_scaled = scaler.fit_transform(Y)
plt.scatter(X_scaled[:, 0], X_scaled[:, 1])
plt.scatter(Y_scaled[:, 0], Y_scaled[:, 1])
plt.show()