Как правильно использовать PCA с последующей логистической регрессией?

В программе я сканирую несколько образцов мозга, взятых во временном ряду изображений 40 x 64 x 64 каждые 2,5 секунды. Таким образом, число "вокселей" (3D-пикселей) в каждом изображении составляет ~ 168 000 иш (40 * 64 * 64), каждый из которых является "особенностью" для образца изображения.

Я думал об использовании Принципиального компонентного анализа (PCA) из-за чрезмерно высокого n выполнить уменьшение размерности. Я знаю, что PCA на самом деле не уменьшает количество функций. Поправьте меня, если я ошибаюсь, но PCA создаст новый набор функций из оригинальных. Новые функции, однако, должны соответствовать определенным условиям.

Я определил метод, чтобы получить количество компонентов:

def get_optimal_number_of_components():
    cov = np.dot(X,X.transpose())/float(X.shape[0])
    U,s,v = svd(cov)

    S_nn = sum(s)

    for num_components in range(0,s.shape[0]):
        temp_s = s[0:num_components]
        S_ii = sum(temp_s)
        if (1 - S_ii/float(S_nn)) <= 0.01:
            return num_components

    return s.shape[0]

Эта функция возвращает количество компонентов, так что сохраняется 99% отклонения от исходных данных. Теперь мы можем создать эти компоненты:

#Scaling the values
X = scale(X)

n_comp = get_optimal_number_of_components()
print 'optimal number of components = ', n_comp

pca = PCA(n_components = n_comp)
X_new = pca.fit_transform(X)

Я получаю оптимальное количество компонентов = 1001 при запуске программы в этом наборе данных. Это число согласуется с сюжетом, который я получил при выполнении:

#Cumulative Variance explains
var1 = np.cumsum(np.round(pca.explained_variance_ratio_, decimals=4)*100)

plt.plot(var1)
plt.title('Principle Component Analysis for Feature Selection')
plt.ylabel('Percentage of variance')
plt.xlabel('Number of voxels considered')

plt.show()

После завершения этого этапа PCA я использовал недавно созданный "X_new" вместо X для следующего этапа: Логистическая регрессия

#After PCA
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_new, y, test_size=0.10, random_state=42)

classifier = LogisticRegression()
classifier.fit(X_train,y_train)

Когда я проверяю на точность, я получаю около 77,57%

Но это меньше, чем когда я только что проанализировал образцы среднего вокселя (например, 9K образцов в середине изображения мозга). Мне было интересно, правильно ли я передал PCA и логистическую регрессию.

Я даже попробовал это в другом методе, используя sklearn.pipeline:

pipe = Pipeline(steps=[('pca', pca), ('logistic', classifier)])

pipe.set_params(pca__n_components = n_comp).fit(X_train,y_train)

print 'score = ', pipe.score(X_test,y_test)

Но я получил точно такую ​​же точность 77,57%. Правильно ли я внедряю PCA + логистическая регрессия? Должно быть, что-то не так, я просто не могу понять, что это такое.

2 ответа

Решение

Хотя я не могу сразу найти какую-либо ошибку, вы должны попробовать и проверить, как ведет себя ошибка, если вы увеличите number of components, Может быть, отсутствует некоторая информация о низкой дисперсии, чтобы придать логистической регрессии необходимое ей преимущество?

99% в PCA больше ориентир, чем факт.

Другие вещи, которые вы можете попробовать: вместо PCA просто удалите каждую функцию с нулевой (или очень низкой) дисперсией. Данные DTI часто имеют характеристики, которые никогда не меняются, и поэтому совершенно не нужны для классификации.

Попробуйте найти функции, которые сильно коррелируют с вашим результатом, и попробуйте использовать их только для классификации.

Всегда будьте осторожны, чтобы не надевать!

Поправьте меня, если я ошибаюсь, но PCA создаст новый набор функций из оригинальных.

Я постараюсь описать это как можно более нетехническим

Да. PCA - это в основном необычное преобразование оси. Да, вы получаете новый набор функций, но они представляют собой линейные комбинации предыдущих функций упорядоченным образом, так что первая функция описывает как можно больше данных.

Идея состоит в том, что, если у вас есть гиперплоскость, PCA фактически спроецирует гиперплоскость на первые оси и оставит последние почти пустыми.

PCA - это линейное уменьшение размерности, поэтому, если истинное распределение данных не является линейным, это дает худшие результаты.

Также мой друг работал с данными мозга, похожими на ваши (множество функций, очень мало примеров), и PCA почти никогда не помогал. Возможно, что значительная часть информации не найдена, потому что вокруг слишком много "шума".

РЕДАКТИРОВАТЬ: опечатка

Я обнаружил, что использование MLPClassifer было более точным для набора cc по умолчанию. Я добавил PCA в свой конвейер, а затем получил к нему доступ, чтобы посмотреть, какие функции можно удалить.

Цель PCA 1. те же данные с меньшим количеством признаков 2. предполагается, что низкая дисперсия является шумом 3. указать, сколько признаков следует сохранить

          pipeline= Pipeline([
    ('scaler',StandardScaler()),
    ('pca', PCA()),
    #('clf2',LogisticRegression(max_iter=10000, tol=0.1)),
    ('clf',MLPClassifier(hidden_layer_sizes=(36,150,36),  max_iter=100, solver='adam', 
             activation='relu', 
             alpha=0.1, 
             learning_rate_init=0.001,
             verbose=False,
             momentum=0.9,
             random_state=42))
     ])
     pipeline.fit(X_train,y_train)
     y_pred = pipeline.predict(X_test)
     cm = confusion_matrix(y_test,y_pred)

     class_names=[1,2]
     fig, ax = plt.subplots()
     tick_marks = np.arange(len(class_names))
     plt.xticks(tick_marks, class_names)
     plt.yticks(tick_marks, class_names)
     sns.heatmap(pd.DataFrame(cm), annot=True, cmap="coolwarm" ,fmt='g')
     ax.xaxis.set_label_position("top")
     plt.tight_layout()
     plt.title('Confusion matrix', y=1.1)
     plt.ylabel('Actual label')
     plt.xlabel('Predicted label')

     print("Test Accuracy is %s",pipeline['clf'].score(X_test,y_test)*100)

     pred_train=pipeline.predict(X_train)
     print("Train Accuracy is %s",accuracy_score(y_train, pred_train))
     
     pca=pipeline['pca']
     pca_features=pca.components_
     

     fig,ax = plt.subplots(figsize=(16,8))
     # Assign 1st column of pca_features: ys
     xs = pca_features[:,0]
     ys = pca_features[:,1]
     sns.scatterplot(x=xs, y=ys)

     mean = pca.mean_
     first_pc = pca.components_[0,:]
     # Plot first_pc as an arrow, starting at mean
     plt.arrow(mean[0],mean[1], first_pc[0], first_pc[1],       color='red', width=0.01)

     plt.axis('equal')
     plt.show()

     fig,ax = plt.subplots(figsize=(16,8))
     features = range(pca.n_components_)
     ax.bar(features, pca.explained_variance_)
     plt.xticks(features)
     plt.ylabel('variance')
     plt.xlabel('pca features')
     plt.show()
Другие вопросы по тегам