Вопрос или проблема
Я хотел бы извлечь 20 самых информативных признаков из очень большого набора признаков $X$, который поступает из набора данных, содержащего клинические данные, с помощью функции RFE из библиотеки scikit-learn в Python.
$X$ представляет собой матрицу 68 x 1140, где
- Каждая строка представляет собой записанную сессию.
- Для каждого субъекта есть 4 записанные сессии.
- Таким образом, в наборе данных 17 субъектов.
Моя идея заключается в том, чтобы использовать 70% набора данных (т.е. 70% x 1140 случайных признаков из каждой записи) и извлечь 50 признаков из всего набора данных.
$Y$ представляет рейтинг от 0 до 2.
Другими словами, мои данные выглядят так:
А моя реализация в коде выглядит следующим образом:
## X = признаки
## Y = метки
p = 0.7
n_perc = round(X.shape[1]*X.shape[0]*p) #70% данных -> количество элементов (высота x ширина x 70%)
rand_idx = np.random.randint(X.shape[1]*X.shape[0], size=n_perc) #случайные индексы (70% данных)
X_rnd = X.flatten()[rand_idx] #выбор этих 70% в X
Y_rnd = np.repeat(Y,round(X.shape[1]*p)) #мы сопоставляем размеры для X_rnd - Y_rnd
selector = RFE(estimator=LogisticRegression(C=1),n_features_to_select=20) #запуск RFE
selector.fit(X_rnd.reshape,Y_rnd) #выбор лучших признаков
Идея заключается в том, что я выравниваю все значения из X и получаю только 70% случайных элементов из $X$, т.е. $X_{rnd}$ (и также адаптирую $Y$ соответственно, т.е. $Y_{rnd}$).
ValueError: Ожидался 2D массив, вместо этого получен 1D массив:
array=[-0.25367578 0.8069118 -0.63161352 ... 0.5500815 -0.37418711
0.2580666 ]. Измените форму ваших данных, используя array.reshape(-1, 1), если ваши данные содержат одну особенность, или array.reshape(1, -1), если в них содержится один пример.
Но по какой-то причине я получаю эту ошибку, которую не понимаю. Говорится, что я должен изменить форму массива, если у меня есть либо одна особенность, либо один образец, но это не мой случай.
Кто-нибудь знает, что мне делать? Это тот подход, который я должен использовать для решения проблемы? Должен ли я изменить форму $X$ другим способом?
Спасибо.
selector.fit(X_rnd.reshape,Y_rnd) #выбор лучших признаков
X_rnd должен быть 2D матрицей.
Я думаю, что эта ошибка возникла, когда метод “fit” был выполнен с X_rnd, но ваш код показывает X_rnd.reshape. В этом случае ошибка должна быть –
ValueError: Ожидался 2D массив, вместо этого получен скалярный массив:
array=<встроенный метод reshape объекта numpy.ndarray на 0x000000000C28EAD0>.
Измените форму ваших данных, используя array.reshape(-1, 1), если ваши данные содержат одну особенность, или array.reshape(1, -1), если в них содержится один пример.
Ответ или решение
Ошибка, с которой вы столкнулись — ValueError: Expected 2D array, got 1D array instead
, возникает, потому что метод fit
требует, чтобы входные данные имели двумерный формат. Давайте рассмотрим вашу реализацию и исправим её шаг за шагом.
Разбор проблемы:
Вы пытаетесь извлечь 70% случайных признаков из одномерного массива X_rnd
, который вы получаете, используя X.flatten()
и случайные индексы. Тем не менее, для метода fit
требуется двумерный массив, где строки представляют собой образцы, а столбцы — признаки.
Также вы вызываете X_rnd.reshape
без скобок, что не приводит к вызову метода и оставляет X_rnd
в одномерной форме.
Исправление кода:
Вот как можно исправить ваш код:
- Случайный отбор: Вместо того чтобы использовать
flatten
, удерживайте данные в их исходной двумерной форме. - Форматирование
X_rnd
иY_rnd
: Убедитесь, чтоX_rnd
остается двумерным. - Корректный вызов метода
reshape
: Определите правильный размер дляX_rnd
, чтобы он стал двумерным.
Вот исправленный код:
import numpy as np
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
# Предположим, что X и Y уже загружены
p = 0.7
n_samples = X.shape[0] # количество сессий
n_features = X.shape[1] # количество признаков
n_selected_features = 50 # число выбираемых признаков
# Генерируем случайные индексы для 70% сессий
rand_idx = np.random.choice(n_samples, size=int(n_samples * p), replace=False)
# Получаем подмассив X_rnd, который содержит только 70% сессий
X_rnd = X[rand_idx] # X_rnd будет 2D массивом размером (число выбранных сессий, число признаков)
# Теперь нам нужно адаптировать Y_rnd, таким образом, чтобы он соответствовал выбранным сессиям
Y_rnd = Y[rand_idx] # Предполагая, что Y имеет ту же базу индексов, что и X
# Теперь применяем RFE - нам нужно обращать внимание на то, что X_rnd имеет две размерности
selector = RFE(estimator=LogisticRegression(C=1), n_features_to_select=20)
selector.fit(X_rnd, Y_rnd) # Заходим в RFE с уже правильно оформленными массивами
# Получение выбранных признаков
selected_features = selector.support_
Объяснение изменений:
- Выбор сессий: Вместо выбора случайных значений из
X
, мы выбираем случайные индексы записей (сессий) и формируем новый массивX_rnd
, который остается 2D, сохраняя структуру данных. - Корректное формирование
Y_rnd
: При генерацииY_rnd
мы также выбираем только те метки, которые соответствуют отобранным сессиям. - Использование
fit
: Теперь, когдаX_rnd
иY_rnd
имеют соответствующие размеры и формат, методfit
будет работать без ошибок.
Рекомендации:
- Убедитесь, что ваши данные
Y
подходят для данной процедуры, так как еслиY
имеет значения, которые не могут быть обработаны моделью (например, не целые числа или NaN), это также может привести к ошибкам. - Проверьте, чтобы ваши функции и предобрабатывающие шаги были правильно выполнены, чтобы гарантировать качество ваших данных.
Следуя этим шагам, вы сможете успешно избежать ошибки и правильно извлечь информативные признаки из вашего массива данных.