【问题标题】:Why would a scaled SVD run so much slower than an unscaled SVD in a Random Forest model?为什么在随机森林模型中,缩放的 SVD 比未缩放的 SVD 运行得慢得多?
【发布时间】:2021-04-17 00:26:18
【问题描述】:

我正在通过重新创建常见的“预测垃圾邮件”项目来研究 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

【问题讨论】:

    标签: python machine-learning nlp scaling svd


    【解决方案1】:

    这并不奇怪。假设您对分类感兴趣,并且您有一个如下所示的数据集 -

    如果您尝试为此拟合决策树,它很容易找到决策边界,因此您的分类准确度会非常好。

    现在想象一下,如果您首先尝试对其进行扩展。新数据集将如下所示 -

    如您所见,数据之间存在更多重叠,因此模型更难找到决策边界。

    当您缩放数据时,您会使两个轴彼此靠近。这可能会使它们难以区分。

    此时您可能想知道,如果是这种情况,我们为什么还要费心进行重新缩放。毕竟,无论您使用什么型号,都会看到这种效果。虽然这是真的,而且这样做可能会降低数据的可区分性,但在像神经网络这样的模型中,如果你不进行这种缩放操作,还会出现许多其他缺点。就像一个特征的权重被人为地夸大了,或者梯度没有正确流动等等。在这种情况下,扩展的优势可能会超过劣势,您仍然可以得到一个好的模型。

    至于你的问题,为什么会有速度差异,同样的效果,随机森林可能需要搜索更长的时间才能在后一种情况下以相同的参数获得良好的拟合。这并不奇怪。

    这是用于生成绘图的代码 -

    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()  
    

    【讨论】:

    • 哇,感谢阿南达的所有帮助。我必须承认我仍然很困惑。我为此 here 创建了一个简短的笔记本。我可能需要按目标值分开。我也使用了错误的缩放器,但这不是重点。任何缩放器只是改变数字而不是数据“云”的关系或形状(在这种情况下为 300 维矩阵)。我认为我的 maxabs 缩放器使数据变得更稀疏(滚动到最后)......对不起,我太冗长了!
    • 真的不清楚你在问什么,可能是因为在评论部分的字数限制中很难解释。如果您有一个特定问题,需要比当前答案更多的解释,请单独打开一个新问题。在这里,我已经解释了这种减速问题在训练 DT 时表现出来的一种方式。还有其他可能发生这种情况的方式,您似乎正在探索这些方式,如果是这种情况,它可能应该是一个单独的问题,更清楚地解释 IMO 的问题。
    • 你是绝对正确的@Ananda。这是我在 StackOverflow 的第一个问题,我没有意识到很多事情,感谢您的帮助。我会照你说的做,然后问另一个更集中的问题。我认为您的示例如此清楚地显示缩放有多糟糕的原因是因为它是针对 X 和 Y 分别完成的,而在我的情况下,我一次缩放了整个 SVD。所以所有的关系都是完整的,只有比例发生了变化(数字表示)。我试图理解为什么这种新的表示在随机森林中会更糟。下次我会展示一些情节,受你的启发;-)
    • 不用担心,由于您是 SO 新手,我会告诉您,如果您发现它有帮助,请考虑将答案标记为已接受的解决方案(答案旁边的勾号)并标记此问题已解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    • 2020-03-16
    • 2013-05-29
    • 2018-03-03
    • 2012-04-21
    • 2020-02-25
    • 2018-09-26
    相关资源
    最近更新 更多