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

时间:2014-05-27 17:12:54

标签: numpy scikit-learn cross-validation multidimensional-array

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

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

一段代码:

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)

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

如果我在PLSSVD构造函数中设置了y_std[y_std == 0.0] = 1.0,它在第99行的同一个函数中失败:y_std,因为它试图在float上做一个布尔索引({ {1}}是一个浮点数,因为它只有一个维度。

似乎就像一个简单的解决方法一样,只需确保y变量有两个维度(N,1)。的然而

如果我从输出变量(N,1)中创建一个维度为y的数组,它仍会失败。为了更改数组,我在运行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学习版0.15-git上运行此功能。

如何将PLSSVDcross_val_score一起使用?

1 个答案:

答案 0 :(得分:4)

偏最小二乘法将您的数据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_transformed是形状n_samples, n_components的数组,它们是XY的预计版本。

关于在PLSSVD Pipeline内使用cross_val_score的问题的答案是,它不会开箱即用,因为Pipeline对象使用变量fittransform作为参数调用XY,如果可能的话,正如您在我编写的代码中看到的那样,返回包含预计XY值的元组。管道中的下一步将无法处理此问题,因为它会认为此元组是新的X

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

解决方案:不要在1D目标上使用偏最小二乘法,即使它与管道配合使用也不会有任何好处。