1. Для производства: меньшее количество переменных означает меньшие требования к входным данным клиента (например, клиенты заполняют форму на веб-сайте или в мобильном приложении) и, следовательно, меньше кода для обработки ошибок. Это снижает вероятность ошибок.
  2. Для производительности модели: меньшее количество переменных означает более простые, интерпретируемые и менее подогнанные модели.

В этой части мы выберем функцию с помощью различных методов, которые

1. Выбор признаков с корреляцией

2. Одномерный выбор признаков (хи-квадрат)

3. Рекурсивное устранение признаков (RFE) со случайным лесом

4. Рекурсивное устранение признаков с перекрестной проверкой (RFECV) со случайным лесом

5. Выбор признаков на основе дерева со случайной классификацией леса

6. Выбор функций на основе L1 (LinearSVC)

7. Выбор объектов на основе дерева (ExtraTrees)

8. Выбор функции на основе голосования

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

Импорт библиотек

# importing the libraries
from functools import reduce
# linear algebra
import numpy as np 
# data processing, CSV file I/O
import pandas as pd 
# data visualization library
import seaborn as sns  
import matplotlib.pyplot as plt
from pandas import DataFrame
import time
from statsmodels.stats.outliers_influence import variance_inflation_factor
from sklearn.svm import LinearSVC
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.metrics import f1_score,confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.feature_selection import SelectFromModel
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
from sklearn.feature_selection import RFE
from sklearn.feature_selection import RFECV
dataset = pd.read_csv("../data/data.csv")

Удаление ненужных столбцов в наборе данных

def get_xy(data:pd.DataFrame,list_drp:list):
        """
        set the x and y column
        
        args:
            data(pd.DataFrame): the dataFrame which we are extracting the x and y
        
        returns:
            y and X in form of pandas series
        
        """
        y = data.diagnosis # M or B 
        X = data.drop(list_drp,axis = 1 )
        return y,X
d_list = ['Unnamed: 32','id','diagnosis']
y,x = get_xy(dataset,d_list)
x.head()

1) Выбор признаков с корреляцией

Как видно на карте, тепловые показатели radius_mean, perimeter_mean и area_mean коррелируют друг с другом, поэтому мы будем использовать только area_mean. Если вы спросите, как я выбираю area_mean в качестве функции для использования, на самом деле правильного ответа нет, я просто смотрю на графики роя, и area_mean выглядит для меня ясно, но мы не можем провести точное разделение между другими коррелированными функциями, не пытаясь. Итак, давайте найдем другие коррелированные функции и посмотрим на точность с помощью классификатора случайного леса.

Compactness_mean, concavity_mean и concave points_mean коррелируют друг с другом. Поэтому я выбираю только concavity_mean. Помимо этого, радиус_se, периметр_se и area_se коррелированы, и я использую только area_se. radius_worst, perimeter_worst и area_worst коррелируют, поэтому я использую area_worst. Compactness_worst, вогнутость_worst и вогнутость points_worst, поэтому я использую concavity_worst. Compactness_se, concavity_se и concave points_se, поэтому я использую concavity_se. texture_mean и texture_worst коррелируют, и я использую texture_mean. area_worst и area_mean коррелируют, я использую area_mean.

Удаление высококоррелированных столбцов в наборе данных

def by_correlation(x,drop_list_cor):
    """
    selects the features by correlation
    
    args:
        x (pd.DataFrame):a dataframe of the independent variables
        drop_list_cor (list): a list of the columns believed to have high correlation
        
    returns:
        a dataframe demonstrating correlation among
    """
    x_1 = x.drop(drop_list_cor,axis = 1 )        # do not modify x, we will use it later 
    x_1.head()
    selected_feature_corr=x_1.columns
    fs_corr = np.ones(len(x_1.columns)).astype(int)
    fs_corr = DataFrame(fs_corr, columns = ["Corr"], index=x_1.columns)
    f,ax = plt.subplots(figsize=(14, 14))
    sns.heatmap(x_1.corr(), annot=True, linewidths=.5, fmt= '.1f',ax=ax)
    return x_1,fs_corr
drop_list_cor = ['perimeter_mean','radius_mean','compactness_mean','concave points_mean','radius_se','perimeter_se','radius_worst','perimeter_worst','compactness_worst','concave points_worst','compactness_se','concave points_se','texture_worst','area_worst']
x_1,fs_corr = by_correlation(x,drop_list_cor)
fs_corr = fs_corr.reset_index();fs_corr

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

Ну, мы выбираем наши функции, но правильно ли мы выбрали? Давайте используем случайный лес и найдем точность в соответствии с выбранными функциями.

def test_rf(x,y):
    """
    find correlation tests by random forest
    
    args:
        x (pd.DataFrame): a dataframe of the independent variables
        y (pd.DataFrame): a dataframe of the dependent variable
    
    returns:
        a heatmap showing rf results
        
    """
    # split data train 70 % and test 30 %
    x_train, x_test, y_train, y_test = train_test_split(x_1, y, test_size=0.3, random_state=42)

    #random forest classifier with n_estimators=10 (default)
    clf_rf = RandomForestClassifier(random_state=43)      
    clr_rf = clf_rf.fit(x_train,y_train)

    ac = accuracy_score(y_test,clf_rf.predict(x_test))
    print('Accuracy is: ',ac)
    cm = confusion_matrix(y_test,clf_rf.predict(x_test))
    sns.heatmap(cm,annot=True,fmt="d")
    return x_train, x_test, y_train, y_test,clr_rf
x_train, x_test, y_train, y_test,clr_rf = test_rf(x_1,y)
Accuracy is:  0.9649122807017544

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

2. Одномерный выбор признаков (хи-квадрат)

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

В этом методе нам нужно выбрать, сколько функций мы будем использовать. Например, будет ли k (количество признаков) равным 5, 10 или 15? Ответ только пробуя или интуитивно. Я не пробую все комбинации, а выбираю только k = 10 и нахожу 10 лучших признаков.

def by_chi2(x_train,y_train):
    """
    selects features based on the chisquared method
    
    args:
        x_train (pd.DataFrame): dataframe of the training x dataset
        y_train (pd.DataFrame): dataframe of the training y dataset
    
    returns:
        result of the chi2 in a dataframe
    """
    # find best scored 10 features
    select_feature = SelectKBest(chi2, k=10).fit(x_train, y_train)
    np.set_printoptions(suppress=True)
    print('Score list:', select_feature.scores_)
    pd.options.display.float_format = '{:.2f}'.format
    fs_chi2 = pd.DataFrame(select_feature.scores_, columns = ["Chi_Square"], index=x_train.columns)
    fs_chi2 = fs_chi2.reset_index()
    fs_chi2 = fs_chi2.sort_values('Chi_Square',ascending=0)
    return select_feature,fs_chi2
select_feature,fs_chi2=by_chi2(x_train,y_train);fs_chi2
x_train_2 = select_feature.transform(x_train)
x_test_2 = select_feature.transform(x_test)
clf_rf_2 = RandomForestClassifier()      
clr_rf_2 = clf_rf_2.fit(x_train_2,y_train)
ac_2 = accuracy_score(y_test,clf_rf_2.predict(x_test_2))
print('Accuracy is: ',ac_2)
cm_2 = confusion_matrix(y_test,clf_rf_2.predict(x_test_2))
sns.heatmap(cm_2,annot=True,fmt="d")
Score list: [   60.69164331 36689.9556596      0.10001518    13.05476497
     0.19598285     0.00034258     0.0407131   6127.41067039
     0.0013247      0.69289672     0.00139558     0.00265927
     0.26322631    25.88581167     1.00635138     0.12308735]
Accuracy is:  0.9649122807017544





<AxesSubplot:>

3. Рекурсивное устранение признаков (RFE) со случайным лесом

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

Как и в предыдущем методе, мы будем использовать 10 функций. Однако какие 10 функций мы будем использовать? Мы выберем их методом RFE.

def by_rfe(x_train,y_train):
    """
    select by recursive feature elimination
    
    args:
        x_train (pd.DataFrame): a pandas dataframe for trarining x dataset
        y_train (pd.DataFrame): a pandas dataframe for training y dataset
        
    returns:
        a datafram of the extracted features
    """
    
    # Create the RFE object and rank each pixel
    clf_rf_3 = RandomForestClassifier()      
    rfe = RFE(estimator=clf_rf_3, n_features_to_select=10, step=1)
    rfe = rfe.fit(x_train, y_train)
    # let's print the number of total and selected features
    fs_rfe = DataFrame(rfe.support_, columns = ["RFE"], index=x_train.columns)
    fs_rfe = fs_rfe.reset_index()
    # this is how we can make a list of the selected features
    # let's print some stats
    print('total features: {}'.format((x_train.shape[1])))
    print('selected features: {}'.format(len(x_train.columns[rfe.support_])))
    print('Chosen best 10 feature by rfe:',x_train.columns[rfe.support_])
    return fs_rfe,rfe
fs_rfe,rfe=by_rfe(x_train,y_train)
total features: 16
selected features: 10
Chosen best 10 feature by rfe: Index(['texture_mean', 'area_mean', 'smoothness_mean', 'concavity_mean',
       'fractal_dimension_mean', 'area_se', 'concavity_se', 'smoothness_worst',
       'concavity_worst', 'symmetry_worst'],
      dtype='object')

Выбранные rfe 10 лучших признаков: texture_mean, area_mean, smoothness_mean, concavity_mean, area_se, concavity_se, fractal_dimension_se, concavity_worst, symmetry_worst, fractal_dimension_worst. Они аналогичны предыдущему методу (selectkBest). Поэтому нам не нужно снова вычислять точность. Вкратце можно сказать, что мы делаем хороший выбор признаков с помощью методов rfe и selectkBest. Однако, как вы можете видеть, есть проблема, хорошо, за исключением того, что мы находим лучшие 10 функций двумя разными методами, и эти функции почти одинаковы, но почему это 10. Возможно, если мы используем лучшие 5 или лучшие 12 функции, мы будем иметь лучшую точность. Поэтому давайте посмотрим, сколько функций нам нужно использовать с методом rfecv.

4. Рекурсивное устранение признаков с перекрестной проверкой (RFECV) со случайным лесом

Теперь мы не только найдем лучшие функции, но и найдем, сколько функций нам нужно для максимальной точности.

def by_rfecv(x_train,y_train):
    """
    select by recursive feature elimination
    
    args:
        x_train (pd.DataFrame): a pandas dataframe for trarining x dataset
        y_train (pd.DataFrame): a pandas dataframe for training y dataset
        
    returns:
        a datafram of the extracted features
    """
    # The "accuracy" scoring is proportional to the number of correct classifications
    clf_rf_4 = RandomForestClassifier() 
    rfecv = RFECV(estimator=clf_rf_4, step=1, cv=5,scoring='accuracy')   #5-fold cross-validation
    rfecv = rfecv.fit(x_train, y_train)
    # let's print the number of total and selected features
    fs_rfecv = DataFrame(rfecv.support_, columns = ["RFECV"], index=x_train.columns)
    fs_rfecv = fs_rfecv.reset_index()
    # this is how we can make a list of the selected features
    # let's print some stats
    print('total features: {}'.format((x_train.shape[1])))
    print('selected features: {}'.format(len(x_train.columns[rfecv.support_])))
    print('Optimal number of features :', rfecv.n_features_)
    print('Best features by rfecv:',x_train.columns[rfecv.support_])
    return rfecv,fs_rfecv
rfecv,fs_rfecv = by_rfecv(x_train,y_train)
plt.figure()
plt.xlabel("Number of features selected")
plt.ylabel("Cross validation score of number of selected features")
plt.plot(range(1, len(rfecv.grid_scores_) + 1), rfecv.grid_scores_)
plt.show()
total features: 16
selected features: 15
Optimal number of features : 15
Best features by rfecv: Index(['texture_mean', 'area_mean', 'smoothness_mean', 'concavity_mean',
       'symmetry_mean', 'fractal_dimension_mean', 'area_se', 'smoothness_se',
       'concavity_se', 'symmetry_se', 'fractal_dimension_se',
       'smoothness_worst', 'concavity_worst', 'symmetry_worst',
       'fractal_dimension_worst'],
      dtype='object')


/home/martin/miniconda3/envs/causality/lib/python3.10/site-packages/sklearn/utils/deprecation.py:103: FutureWarning: The `grid_scores_` attribute is deprecated in version 1.0 in favor of `cv_results_` and will be removed in version 1.2.
  warnings.warn(msg, category=FutureWarning)

Наконец, мы находим лучшие 15 признаков: 'texture_mean', 'area_mean', 'smoothness_mean', 'concavity_mean', 'symmetry_mean', 'fractal_dimension_mean', 'area_se', 'smoothness_se', 'concavity_se', 'symmetry_se', ' fractal_dimension_se', 'smoothness_worst', 'concavity_worst', 'symmetry_worst', 'fractal_dimension_worst' для лучшей классификации. Давайте посмотрим на лучшую точность с сюжетом.

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

5. Выбор признаков на основе дерева и классификация случайных лесов

В методе классификации случайного леса есть атрибуты featureimportances, которые представляют собой важность признаков (чем выше, тем важнее признак). !!! Чтобы использовать метод feature_importance, в обучающих данных не должно быть коррелированных признаков. Случайный лес выбирается случайным образом на каждой итерации, поэтому последовательность списка важности признаков может меняться.

def by_rf(x_train,y_train):
    """
    select by recursive feature elimination
    
    args:
        x_train (pd.DataFrame): a pandas dataframe for trarining x dataset
        y_train (pd.DataFrame): a pandas dataframe for training y dataset
        
    returns:
        a datafram of the extracted features
    """
    clf_rf_5 = RandomForestClassifier()      
    clr_rf_5 = clf_rf_5.fit(x_train,y_train)
    importances = clr_rf_5.feature_importances_
    clf_rf = RandomForestClassifier(random_state=43)   
    clr_rf = clf_rf.fit(x_train,y_train)

    std = np.std([tree.feature_importances_ for tree in clf_rf.estimators_],
                 axis=0)
    indices = np.argsort(importances)[::-1]

    # Print the feature ranking
    print("Feature ranking:")

    for f in range(x_train.shape[1]):
        print("%d. feature %d (%f)" % (f + 1, indices[f], importances[indices[f]]))

    # Plot the feature importances of the forest

    plt.figure(1, figsize=(14, 13))
    plt.title("Feature importances")
    plt.bar(range(x_train.shape[1]), importances[indices],
           color="g", yerr=std[indices], align="center")
    plt.xticks(range(x_train.shape[1]), x_train.columns[indices],rotation=90)
    plt.xlim([-1, x_train.shape[1]])
    plt.show()
    print(importances[indices])
    # let's print the number of total and selected features
    # let's print some stats
    print('total features: {}'.format((x_train.shape[1])))
    #print('Chosen optimal features by rf:',selected_feature_rf[1:10])
    fs_rf = DataFrame(clr_rf_5.feature_importances_, columns = ["RF"], index=x_train.columns)
    fs_rf = fs_rf.reset_index()
    fs_rf = fs_rf.sort_values('RF',ascending=0)
    return fs_rf

Как вы можете видеть на графике выше, после 6 лучших функций важность функций уменьшается. Поэтому мы можем сосредоточиться на этих 6 функциях.

fs_rf = by_rf(x_train,y_train)
Feature ranking:
1. feature 3 (0.216730)
2. feature 1 (0.201160)
3. feature 7 (0.172581)
4. feature 13 (0.118771)
5. feature 0 (0.047073)
6. feature 14 (0.041871)
7. feature 12 (0.033239)
8. feature 9 (0.032605)
9. feature 2 (0.024652)
10. feature 11 (0.019521)
11. feature 5 (0.018338)
12. feature 15 (0.017972)
13. feature 8 (0.017810)
14. feature 4 (0.017172)
15. feature 10 (0.010596)
16. feature 6 (0.009908)

[0.21673047 0.20115968 0.17258109 0.11877079 0.04707305 0.04187128
 0.03323901 0.03260499 0.02465216 0.01952089 0.01833808 0.01797202
 0.01781018 0.01717216 0.01059649 0.00990766]
total features: 16

6. Выбор функций на основе L1 (LinearSVC)

def by_l1(x_train,y_train):
    """
    select by recursive feature elimination
    
    args:
        x_train (pd.DataFrame): a pandas dataframe for trarining x dataset
        y_train (pd.DataFrame): a pandas dataframe for training y dataset
        
    returns:
        a datafram of the extracted features
    """
    lsvc = LinearSVC(C=0.01, penalty="l1", dual=False,max_iter=2000).fit(x_train, y_train) 
    model = SelectFromModel(lsvc, prefit=True) 
    x_new = model.transform(x_train) 
    print(x_train.columns[model.get_support()]) 
    # let's print the number of total and selected features
    fs_l1 = DataFrame(model.get_support(), columns = ["L1"], index=x_train.columns)
    fs_l1 = fs_l1.reset_index()
    # this is how we can make a list of the selected fes
    selected_feature_lsvc = x_train.columns[model.get_support()]

    # let's print some stats
    print('total features: {}'.format((x_train.shape[1])))
    print('selected features: {}'.format(len(selected_feature_lsvc)))
    print('Best features by lsvc:',x_train.columns[model.get_support()])
    return fs_l1,selected_feature_lsvc,model
fs_l1,selected_feature_lsvc,model=by_l1(x_train,y_train)
Index(['texture_mean', 'area_mean', 'area_se'], dtype='object')
total features: 16
selected features: 3
Best features by lsvc: Index(['texture_mean', 'area_mean', 'area_se'], dtype='object')


/home/martin/miniconda3/envs/causality/lib/python3.10/site-packages/sklearn/base.py:443: UserWarning: X has feature names, but SelectFromModel was fitted without feature names
  warnings.warn(

7. Выбор объектов на основе дерева (ExtraTrees)

def by_trees(x_train,y_train,model):
    """
    select by recursive feature elimination
    
    args:
        x_train (pd.DataFrame): a pandas dataframe for trarining x dataset
        y_train (pd.DataFrame): a pandas dataframe for training y dataset
        
    returns:
        a datafram of the extracted features
    """
    # Build a forest and compute the impurity-based feature importances
    clf = ExtraTreesClassifier(n_estimators=32,random_state=0)
    clf.fit(x_train, y_train)
    clf.feature_importances_ 
    importances = clf.feature_importances_
    std = np.std([tree.feature_importances_ for tree in clf.estimators_],
                 axis=0)
    indices = np.argsort(importances)[::-1]

    # Print the feature ranking
    print("Feature ranking:")

    for f in range(x_train.shape[1]):
        print("%d. feature %d (%f)" % (f + 1, indices[f], importances[indices[f]]))

    # Plot the impurity-based feature importances of the forest
    plt.figure(1, figsize=(14, 13))
    plt.title("Feature importances")
    plt.bar(range(x_train.shape[1]), importances[indices],
            color="r", yerr=std[indices], align="center")
    plt.xticks(range(x_train.shape[1]), x_train.columns[indices],rotation=90)
    plt.xlim([-1, x_train.shape[1]])
    plt.show()        
    # let's print the number of total and selected features
    # this is how we can make a list of the selected features
    selected_feature_extraTrees = x_train.columns[model.get_support()]
    # let's print some stats
    print('total features: {}'.format((x_train.shape[1])))
    print('selected features: {}'.format(len(selected_feature_extraTrees)))
    print('Best features by ExtraTrees:',x_train.columns[model.get_support()])
    fs_extratrees=DataFrame(clf.feature_importances_, columns = ["Extratrees"], index=x_train.columns)
    fs_extratrees = fs_extratrees.reset_index()
    fs_extratrees = fs_extratrees.sort_values(['Extratrees'],ascending=0)
    return fs_extratrees
fs_extratrees = by_trees(x_train,y_train,model)
Feature ranking:
1. feature 3 (0.191527)
2. feature 1 (0.170634)
3. feature 13 (0.169116)
4. feature 7 (0.123651)
5. feature 0 (0.056858)
6. feature 14 (0.039312)
7. feature 12 (0.035452)
8. feature 15 (0.032071)
9. feature 9 (0.030526)
10. feature 5 (0.029508)
11. feature 4 (0.028988)
12. feature 2 (0.022375)
13. feature 11 (0.020679)
14. feature 10 (0.017656)
15. feature 6 (0.016700)
16. feature 8 (0.014947)

total features: 16
selected features: 3
Best features by ExtraTrees: Index(['texture_mean', 'area_mean', 'area_se'], dtype='object')

8. Выбор функции на основе голосования

Соединить все вместе

def combine_vote(dfs):
    """
    combine all features selected to make a vote
    
    args:
        dfs (list): a list of all features
    
    returns:
        score of features that occur in all
    """
    final_results = reduce(lambda left,right: pd.merge(left,right,on='index'), dfs)
    columns = ['Chi_Square', 'RF', 'Extratrees']
    score_table = pd.DataFrame({},[])
    score_table['index'] = final_results['index']
    for i in columns:
        score_table[i] = final_results['index'].isin(list(final_results.nlargest(10,i)['index'])).astype(int)

    #score_table['Corr'] = final_results['Corr'].astype(int)
    score_table['RFE'] = final_results['RFE'].astype(int)
    score_table['RFECV'] = final_results['RFECV'].astype(int)
    score_table['L1'] = final_results['L1'].astype(int)
    score_table['final_score'] = score_table.sum(axis=1)   
    scores = score_table.sort_values('final_score',ascending=0)
    return scores
dfs = [fs_corr, fs_chi2, fs_rfe, fs_rfecv, fs_rf, fs_l1, fs_extratrees]
scores = combine_vote(dfs);scores
/tmp/ipykernel_32410/3542194670.py:22: FutureWarning: Dropping of nuisance columns in DataFrame reductions (with 'numeric_only=None') is deprecated; in a future version this will raise TypeError.  Select only valid columns before calling the reduction.
  score_table['final_score'] = score_table.sum(axis=1)

# Voted features
list(score_table['index'][score_table['final_score']>=2])
['texture_mean',
 'area_mean',
 'smoothness_mean',
 'concavity_mean',
 'symmetry_mean',
 'fractal_dimension_mean',
 'area_se',
 'concavity_se',
 'fractal_dimension_se',
 'smoothness_worst',
 'concavity_worst',
 'symmetry_worst',
 'fractal_dimension_worst']
# RFE features
list(score_table['index'][score_table['RFE']==1])
['texture_mean',
 'area_mean',
 'concavity_mean',
 'fractal_dimension_mean',
 'area_se',
 'concavity_se',
 'fractal_dimension_se',
 'smoothness_worst',
 'concavity_worst',
 'symmetry_worst']
# RFECV features
list(score_table['index'][score_table['RFECV']==1])
['texture_mean',
 'area_mean',
 'smoothness_mean',
 'concavity_mean',
 'symmetry_mean',
 'fractal_dimension_mean',
 'area_se',
 'smoothness_se',
 'concavity_se',
 'fractal_dimension_se',
 'smoothness_worst',
 'concavity_worst',
 'symmetry_worst',
 'fractal_dimension_worst']
# Chi-Square features
list(score_table['index'][score_table['Chi_Square']==1])
['texture_mean',
 'area_mean',
 'concavity_mean',
 'symmetry_mean',
 'area_se',
 'concavity_se',
 'smoothness_worst',
 'concavity_worst',
 'symmetry_worst',
 'fractal_dimension_worst']
# RF features
list(score_table['index'][score_table['RF']==1])
['texture_mean',
 'area_mean',
 'smoothness_mean',
 'concavity_mean',
 'area_se',
 'concavity_se',
 'fractal_dimension_se',
 'smoothness_worst',
 'concavity_worst',
 'symmetry_worst']
# L1 features
list(score_table['index'][score_table['L1']==1])
['texture_mean', 'area_mean', 'area_se']
# ExtraTrees features
list(score_table['index'][score_table['Extratrees']==1])
['texture_mean',
 'area_mean',
 'concavity_mean',
 'fractal_dimension_mean',
 'area_se',
 'concavity_se',
 'smoothness_worst',
 'concavity_worst',
 'symmetry_worst',
 'fractal_dimension_worst']

Мультиколлинеарность — VIF (аддон)

def calculate_vif(features):
    """
    return variation inflation
    
    args:
        features (pd:DataFrame): a dataframe of the training dataset
    
    returns:
        variance inflation value
    """
    vif = pd.DataFrame()
    vif["Features"] = features.columns
    vif["VIF"] = [variance_inflation_factor(features.values, i) for i in range(features.shape[1])]
    return(vif)
def vif(x_train):
    """
    return variation inflation
    
    args:
        features (pd:DataFrame): a dataframe of the training dataset
    
    returns:
        variance inflation dataframe
    """
    vif = calculate_vif(x_train)
    while vif['VIF'][vif['VIF'] > 10].any():
        remove = vif.sort_values('VIF',ascending=0)['Features'][:1]
        x_train.drop(remove,axis=1,inplace=True)
        vif = calculate_vif(x_train)
    return vif
vif_ = vif(x_train);vif_

Извлечение признаков с использованием PCA

Мы будем использовать анализ основных компонентов (PCA) для извлечения признаков. Перед PCA нам нужно нормализовать данные для лучшей производительности PCA.

def by_pca(x,y):
    """
    return principal compenonent analysis of features
    
    args:
        x (pd:DataFrame): a dataframe of the x dataset
        y (pd:DataFrame): a dataframe of the y dataset
   
    returns:
        plot of the principal component analysis
    """
    # split data train 70 % and test 30 %
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42)
    #normalization
    x_train_N = (x_train-x_train.mean())/(x_train.max()-x_train.min())
    x_test_N = (x_test-x_test.mean())/(x_test.max()-x_test.min())

    pca = PCA()
    pca.fit(x_train_N)

    plt.figure(1, figsize=(14, 13))
    plt.clf()
    plt.axes([.2, .2, .7, .7])
    plt.plot(pca.explained_variance_ratio_, linewidth=2)
    plt.axis('tight')
    plt.xlabel('n_components')
    plt.ylabel('explained_variance_ratio_')
by_pca(x,y)

По соотношению дисперсии можно выбрать 3 компонента.