Sci-kit 学习 PLS SVD 和交叉验证

Posted

技术标签:

【中文标题】Sci-kit 学习 PLS SVD 和交叉验证【英文标题】:Sci-kit Learn PLS SVD and cross validation 【发布时间】:2014-07-16 17:02:12 【问题描述】:

当响应变量的形状为(N,) 而不是(N,1)(其中N 是数据集中的样本数)时,Sci-kit learn 中的sklearn.cross_decomposition.PLSSVD 类似乎失败了。

但是,当响应变量的形状为 (N,1) 而不是 (N,) 时,sklearn.cross_validation.cross_val_score 会失败。我如何将它们一起使用?

一段代码:

from sklearn.pipeline import Pipeline
from sklearn.cross_decomposition import PLSSVD
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

# x -> (N, 60) numpy array
# y -> (N, ) numpy array

# These are the classifier 'pieces' I'm using
plssvd = PLSSVD(n_components=5, scale=False)
logistic = LogisticRegression(penalty='l2', C=0.5)
scaler = StandardScaler(with_mean=True, with_std=True)

# Here's the pipeline that's failing
plsclf = Pipeline([('scaler', scaler),
                   ('plssvd', plssvd), 
                   ('logistic', logistic)])

# Just to show how I'm using the pipeline for a working classifier
logclf = Pipeline([('scaler', scaler),
                   ('logistic', logistic)])

##################################################################

# This works fine
log_scores = cross_validation.cross_val_score(logclf, x, y, scoring='accuracy',
                                              verbose=True, cv=5, n_jobs=4)

# This fails!
pls_scores = cross_validation.cross_val_score(plsclf, x, y, scoring='accuracy',
                                              verbose=True, cv=5, n_jobs=4)

具体来说,它在cross_decomposition/pls_.pyccross_decomposition/pls_.pyc'IndexError: tuple index out of range' 函数中失败,在第103 行:y_std = np.ones(Y.shape[1]),因为形状元组​​只有一个元素。

如果我在 PLSSVD 构造函数中设置 scale=True,它会在第 99 行的同一函数中失败:y_std[y_std == 0.0] = 1.0,因为它试图在浮点数上执行布尔索引(y_std 是浮点数,因为它只有一维)。

似乎很容易解决,只需确保y 变量有两个维度(N,1)但是:

如果我从输出变量y 创建一个维度为(N,1) 的数组,它仍然会失败。为了改变数组,我在运行cross_val_score之前添加了这个:

y = np.transpose(np.array([y]))

然后,它在第 398 行的 sklearn/cross_validation.py 中失败:

File "my_secret_script.py", line 293, in model_create
    scores = cross_validation.cross_val_score(plsclf, x, y, scoring='accuracy', verbose=True, cv=5, n_jobs=4)
File "/Users/my.secret.name/anaconda/lib/python2.7/site-packages/sklearn/cross_validation.py", line 1129, in cross_val_score
    cv = _check_cv(cv, X, y, classifier=is_classifier(estimator))
File "/Users/my.secret.name/anaconda/lib/python2.7/site-packages/sklearn/cross_validation.py", line 1216, in _check_cv
    cv = StratifiedKFold(y, cv, indices=needs_indices)
File "/Users/my.secret.name/anaconda/lib/python2.7/site-packages/sklearn/cross_validation.py", line 398, in __init__
    label_test_folds = test_folds[y == label]
ValueError: boolean index array should have 1 dimension

我在 OSX 上运行它,NumPy 版本 1.8.0,Sci-kit Learn 版本 0.15-git

有什么方法可以将PLSSVDcross_val_score 一起使用?

【问题讨论】:

如果y 只有一列,我不确定偏最小二乘法是否有用。 PLSSVD 采用 X.T.dot(Y) 的 SVD,在您的情况下,它成为列向量。据我了解,偏最小二乘法的目的是找到潜在因素来投影XY,其中X的潜在因素用于解释Y的潜在因素。在这种情况下,由于Y 只有一个条目,看起来这会简化为普通的旧最小二乘法。在其上使用转换器会产生一个用于逻辑回归的一维向量,这似乎毫无意义。您也可以设置阈值。 【参考方案1】:

偏最小二乘法将您的数据X 和您的目标Y 投影到每个由n_components 向量跨越的线性子空间上。它们的投影方式使一个投影变量的回归分数最大化。

组件的数量,即潜在子空间的维度,受变量中特征数量的限制。您的变量Y 只有一个特征(一列),因此潜在子空间是一维的,有效地将您的构造简化为更类似于(但不完全相同)线性回归的东西。因此,在这种特定情况下使用偏最小二乘法可能没有用。

看看下面的

import numpy as np
rng = np.random.RandomState(42)
n_samples, n_features_x, n_features_y, n_components = 20, 10, 1, 1
X = rng.randn(n_samples, n_features_x)
y = rng.randn(n_samples, n_features_y)

from sklearn.cross_decomposition import PLSSVD
plssvd = PLSSVD(n_components=n_components)

X_transformed, Y_transformed = plssvd.fit_transform(X, y)

X_transformedY_transformedn_samples, n_components 形状的数组,它们是XY 的投影版本。

关于在cross_val_score 中的Pipeline 中使用PLSSVD 的问题的答案是,它不会开箱即用,因为Pipeline 对象调用@ 987654336@ 和 transform 尽可能使用两个变量 XY 作为参数,正如您在我编写的代码中看到的那样,它返回一个 tuple 包含投影的 XY 值。管道中的下一步将无法处理这个,因为它会认为这个元组是新的X

这种类型的失败是由于sklearn 才刚刚开始系统化多目标支持。您尝试使用的 PLSSVD 估算器本质上是多目标,即使您只在一个目标上使用它。

解决方案:不要在一维目标上使用偏最小二乘法,即使它与管道一起使用也没有任何好处。

【讨论】:

这很有意义。我知道 PLS 会产生输入的线性组合,但我没有直觉看到它不会对仅使用一个目标变量产生任何有益影响。谢谢! 我来晚了。我只评论指出,在我看来,上面的答案是错误的。关键是潜在向量由 X 和 Y 共享,因此断言“您的变量 Y 只有一个特征(一列),因此潜在子空间是一维的”是错误的。特别是,在一维因变量上运行 PLS 确实有意义。这些笔记vision.cse.psu.edu/seminars/talks/PLSpresentation.pdf 阐明了这个话题。如果我只是感到困惑,请告诉我。 嗯,所以我对 PLS 的理解类似于“找到 X 可以很好预测的 Y 投影”。也许这是错误的观念。但是,如果这是正确的概念,那么投影 1D Y 只是将这一列与一个(希望非零)数字相乘,该数字可以从 X 侧吸收到预测变量中,从而产生线性回归。我认为可能有很多不同的版本,整个动物学填补了 PLS 和 CCA 和回归之间的光谱,所以我们可能不是在谈论同一件事。

以上是关于Sci-kit 学习 PLS SVD 和交叉验证的主要内容,如果未能解决你的问题,请参考以下文章

pls R 的交叉验证中如何计算 R2 和 RMSE

交叉验证概述

如何在训练有素的 SVD 模型上验证测试集?

sci-kit 学习 PCA 和手动 PCA 的结果差异

机器学习交叉验证和网格搜索

机器学习交叉验证和网格搜索案例分析