Научный комплект Изучите PLS SVD и перекрестную проверку

Класс sklearn.cross_decomposition.PLSSVD в Sci-kit Learn, по-видимому, дает сбой, когда переменная ответа имеет форму (N,) вместо (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' в строке 103: y_std = np.ones(Y.shape[1]), потому что кортеж формы имеет только один элемент.

Если я установлю scale=True в конструкторе PLSSVD, произойдет сбой в той же функции в строке 99: y_std[y_std == 0.0] = 1.0, потому что он попытается сделать логический индекс для числа с плавающей запятой (y_std — это число с плавающей запятой, поскольку оно имеет только одно измерение).

Кажется, это легко исправить, просто убедитесь, что переменная y имеет два измерения, (N,1). Однако:

Если я создам массив с размерами (N,1) из выходной переменной y, это все равно не удастся. Чтобы изменить массивы, я добавляю это перед запуском cross_val_score:

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

Затем он терпит неудачу в sklearn/cross_validation.py в строке 398:

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.

Есть ли способ использовать PLSSVD вместе с cross_val_score?


person Mike C    schedule 27.05.2014    source источник
comment
Я не уверен, что частичные наименьшие квадраты очень полезны, если y имеет только один столбец. PLSSVD принимает SVD X.T.dot(Y), который в вашем случае становится вектором-столбцом. Насколько я понимаю, точка частичного наименьшего квадрата состоит в том, чтобы найти скрытые факторы для проецирования как X, так и Y, где скрытые факторы X используются для объяснения факторов Y. В этом случае, поскольку Y имеет только одну запись, похоже, что это сводится к простому методу наименьших квадратов. Использование преобразователя дает одномерный вектор, входящий в вашу логистическую регрессию, что кажется довольно бессмысленным. С тем же успехом можно было порог.   -  person eickenberg    schedule 27.05.2014


Ответы (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_transformed и Y_transformed — это массивы формы n_samples, n_components, они являются спроецированными версиями X и Y.

Ответ на ваш вопрос об использовании PLSSVD внутри Pipeline в cross_val_score нет, это не будет работать из коробки, потому что объект Pipeline вызывает fit и transform, используя обе переменные X и Y в качестве аргументов, если возможно, который, как вы можете видеть в написанном мной коде, возвращает кортеж, содержащий спроецированные значения X и Y. Следующий шаг в конвейере не сможет это обработать, потому что будет думать, что этот кортеж — новый X.

Этот тип отказа связан с тем, что sklearn только начинает систематически поддерживать несколько целей. Оценщик PLSSVD, который вы пытаетесь использовать, по своей сути является многоцелевым, даже если вы используете его только для одной цели.

Решение. Не используйте частичный метод наименьших квадратов для одномерных целей, от этого не будет никакой пользы, даже если он будет работать с конвейером.

person eickenberg    schedule 27.05.2014
comment
Это имеет большой смысл. Я знал, что PLS производит линейные комбинации входных данных, но у меня не было интуиции, чтобы увидеть, что это не будет иметь никаких полезных эффектов только с одной целевой переменной. Спасибо! - person Mike C; 28.05.2014
comment
Я очень поздно приду на вечеринку. Я только комментирую, чтобы указать, что, на мой взгляд, ответ выше неверен. Дело в том, что скрытые векторы являются общими для X и Y, поэтому утверждение Ваша переменная Y имеет только один признак (один столбец), поэтому скрытое подпространство одномерно неверно. В частности, имеет смысл запустить PLS для одномерной зависимой переменной. Эти примечания vision.cse.psu.edu/seminars/talks/PLSpresentation.pdf пролить свет на тему. Пожалуйста, дайте мне знать, если я просто запутался. - person Giovanni De Gaetano; 26.09.2018
comment
Хм, так что мое понимание PLS похоже на поиск проекции Y, которая хорошо предсказуема X. Может быть, это неправильное представление. Но если это правильное представление, то проецирование 1D Y просто сводится к умножению этого одного столбца на (надеюсь, ненулевое) число, которое может быть поглощено предиктором со стороны X, что дает линейную регрессию. Я думаю, что может быть множество разных версий этого, целая зоология, заполняющая спектр между PLS и CCA и регрессией, так что мы можем говорить о разных вещах. - person eickenberg; 28.09.2018