特征工程(三)特征选择

经过“数据清理”和“特征变换”后的数据集,已经满足了数据科学项目中算法对数值的基本要求。但是, 不呢止步于此,数据集的特征数量、质量会影响计算效率和最终模型的预测、分类效果。所以要对特征进行选择,即根据具体的项目选择适合的特征。

特征选择

3.1 特征选择简述

是不是维度越大的数据越好?是不是所有的维度都是必须的?

import pandas as pd
df_wine = pd.read_csv("datasets/wine_data.csv")
df_wine.head()
Class_label Alcohol Malic_acid Ash Alcalinity_of_ash Magnesium Total_phenols Flavanoids Nonflavanoid_phenols Proanthocyanins Color_intensity Hue OD280/OD315_of_diluted_wines Proline
0 1 14.23 1.71 2.43 15.6 127 2.80 3.06 0.28 2.29 5.64 1.04 3.92 1065
1 1 13.20 1.78 2.14 11.2 100 2.65 2.76 0.26 1.28 4.38 1.05 3.40 1050
2 1 13.16 2.36 2.67 18.6 101 2.80 3.24 0.30 2.81 5.68 1.03 3.17 1185
3 1 14.37 1.95 2.50 16.8 113 3.85 3.49 0.24 2.18 7.80 0.86 3.45 1480
4 1 13.24 2.59 2.87 21.0 118 2.80 2.69 0.39 1.82 4.32 1.04 2.93 735

依据机器学习的一般流程,把数据集划分为训练集和测试集,并且对测试集和训练集分别实现特征标准化。

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
X, y = df_wine.iloc[:, 1:], df_wine.iloc[:, 0].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0, stratify=y)

std = StandardScaler()
X_train_std = std.fit_transform(X_train)
X_test_std = std.fit_transform(X_test)

以Class_label为标签,建立对数回归模型,寻找另外13个特征与标签之间的关系。

from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(penalty='l1', C=1.0 , solver='liblinear') 
lr.fit(X_train_std, y_train)

LogisticRegression(penalty='l1', solver='liblinear')

在创建对数概率回归模型时候,使用了参数penalty='l1', C=1.0,这意味着在本模型中遵照此规则增加了惩罚项,其意图是避免训练得到的模型过拟合,也正是出于这个原因,模型舍弃了部分特性——表现出来就是系数为0

lr.coef_
array([[ 1.24568008,  0.18066268,  0.74500129, -1.16270324,  0.        ,
         0.        ,  1.16473536,  0.        ,  0.        ,  0.        ,
         0.        ,  0.55281296,  2.50976773],
       [-1.53710813, -0.38760504, -0.99525286,  0.36504305, -0.05948103,
         0.        ,  0.66797894,  0.        ,  0.        , -1.93413502,
         1.23360251,  0.        , -2.23189735],
       [ 0.13448113,  0.16969503,  0.35805173,  0.        ,  0.        ,
         0.        , -2.43221807,  0.        ,  0.        ,  1.56308975,
        -0.81943572, -0.49548102,  0.        ]])
lr.intercept_

array([-1.26347923, -1.21597948, -2.36926979])

在机器学习中,过拟合是比较常见的现象,通常采用如下避免方法:

  • 训练集和测试集五五开
  • 在模型中增加惩罚项,简化模型
  • 尽可能选用参数少的模型
  • 降低数据集的维度

特征选择,是指去除数据集中的冗余和无关的特征,从数据集中找出主要特征,最终得到得到的是原有特征的子集。因此,特征选择也称为“特征子集选择”

为实现特征选择,这里介绍三类方法:封装器法、过滤器法和嵌入法。

3.2 封装器法

封装器法的基本思路是:

  1. 选用一个特征子集训练模型,此处的模型通常是一种机器学习算法,也称为目标函数。
  2. 用验证数据集对模型进行评估。
  3. 依据某种搜索方式,对不同的特征子集进行上述操作,
  4. 依据评估结果,选出相对最佳的特征子集。

image-20220609191735736

这种方式属于贪心搜索算法,计算量较大。针对特征子集的组合搜索问题,封装法有下述三种常见的选择方式。

循序特征选择

包括 循环向前(SFS)和循环向后(SBS)

基础知识

以SFS为例:

(1)创建一个空的集合X,作为特征子集
(2)从原特征集合中“一次挑选一个”——这就是“循序”的含义,与特征子集X中的特征组合,并使得目标函数(选定的某个机器学习模型)结果最佳(模型预测的误差最小)
(3)将挑选出来的特征从原特征中移除,同时将其追加到X中。
(4)重复(2)、(3)步骤,直到集合X的特征数量达到规定的数量为止,中止上述循环。

显然,SFS不是把所有可能都实现一遍,而是找到一种可能最优解即中止寻找,这样就大大降低了计算量。
mlxtend的第三库提供了实现包含SFS的多种循环特征选择方法

pip install mlxtend

mlxtend中集成了几个数据集,这里使用关于葡萄酒的数据。X有13个特征178个样本,y是每个样本的标签,即每种葡萄酒的等级(共有3级,用0,1,2表示)。其中,X的13特征依次对应的名称是:

  1. Alcohol
  2. Malic acid
  3. Ash
  4. Alcalinity of ash
  5. Magnesium
  6. Total phenols
  7. Flavanoids
  8. Nonflavanoid phenols
  9. Proanthocyanins
  10. Color intensity
  11. Hue
  12. OD280/OD315 of diluted wines
  13. Proline

https://archive.ics.uci.edu/ml/datasets/Wine

from mlxtend.feature_selection import SequentialFeatureSelector as SFS
from sklearn.neighbors import KNeighborsClassifier
from mlxtend.data import wine_data
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

X, y = wine_data()
X.shape

(178, 13)

X_train, X_test, y_train, y_test= train_test_split(X, y, 
                                                   stratify=y,
                                                   test_size=0.3,
                                                   random_state=1)
std = StandardScaler() #标准化
X_train_std = std.fit_transform(X_train)

knn = KNeighborsClassifier(n_neighbors=3)    # knn作为SFS的目标函数
sfs = SFS(estimator=knn,     # SFS封装器
           k_features=4,     # 选择4个最佳特征
           forward=True, 
           floating=False, 
           verbose=2,         # 2输出训练过程的全部日志信息
           scoring='accuracy',#模型评估方法
           cv=0)              # 0 表示不进行交叉验证
sfs.fit(X_train_std, y_train)
[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done   1 out of   1 | elapsed:    0.0s remaining:    0.0s
[Parallel(n_jobs=1)]: Done  13 out of  13 | elapsed:    0.0s finished

[2022-06-09 19:28:12] Features: 1/4 -- score: 0.8548387096774194[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done   1 out of   1 | elapsed:    0.0s remaining:    0.0s
[Parallel(n_jobs=1)]: Done  12 out of  12 | elapsed:    0.0s finished

[2022-06-09 19:28:12] Features: 2/4 -- score: 0.9596774193548387[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done   1 out of   1 | elapsed:    0.0s remaining:    0.0s
[Parallel(n_jobs=1)]: Done  11 out of  11 | elapsed:    0.0s finished

[2022-06-09 19:28:12] Features: 3/4 -- score: 0.9919354838709677[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done   1 out of   1 | elapsed:    0.0s remaining:    0.0s
[Parallel(n_jobs=1)]: Done  10 out of  10 | elapsed:    0.0s finished

[2022-06-09 19:28:12] Features: 4/4 -- score: 0.9838709677419355

从输出的日志信息可以很明确地看出,当选择3个特征的时候,模型knn表现最好

sfs.subsets_
{1: {'feature_idx': (6,),
  'cv_scores': array([0.85483871]),
  'avg_score': 0.8548387096774194,
  'feature_names': ('6',)},
 2: {'feature_idx': (6, 9),
  'cv_scores': array([0.95967742]),
  'avg_score': 0.9596774193548387,
  'feature_names': ('6', '9')},
 3: {'feature_idx': (6, 9, 11),
  'cv_scores': array([0.99193548]),
  'avg_score': 0.9919354838709677,
  'feature_names': ('6', '9', '11')},
 4: {'feature_idx': (6, 8, 9, 11),
  'cv_scores': array([0.98387097]),
  'avg_score': 0.9838709677419355,
  'feature_names': ('6', '8', '9', '11')}}

利用SFS的属性subsets_得到了每次选择出来的特征及其相应的评估分数,feature_names表示特征名称。

项目案例

使用随机森林回归作为目标函数,从房价数据集中,选择出10佳特征

import pandas as pd
from sklearn.ensemble import RandomForestRegressor

df = pd.read_csv("datasets/housprice.csv")
cols = list(df.select_dtypes(include=['int64', 'float64']).columns)  
data = df[cols]

X_train,X_test,y_train,y_test= train_test_split(
            data.drop('SalePrice',axis=1),
            data['SalePrice'],
            test_size=.2,
            random_state=1#随机数生成器使用的种子
)

X_train.fillna(0, inplace=True)    # 用0填充缺失值

sfs3 = SFS(RandomForestRegressor(),    
           k_features=10,
           forward=True,
           verbose=0,
           cv=5,
           n_jobs=-1,
           scoring='r2')
sfs3.fit(X_train,y_train)
sfs3.k_feature_names_

('MSSubClass',
'OverallQual',
'OverallCond',
'YearRemodAdd',
'BsmtFinSF1',
'TotalBsmtSF',
'GrLivArea',
'Fireplaces',
'GarageCars',
'3SsnPorch')

穷举特征选择

指封装器中的搜索算法先将所有特征组合都实现一遍,然后通过比较各种特征组合后的模型表现,从中选择出最佳得到特征子集。
显然穷举特征选择必然浪费更大的计算量。

# 对上面SFS练习题中的10个特征的数据集,对它使用穷举法,从10佳中选出5强
mini_data = X_train[X_train.columns[list(sfs3.k_feature_idx_)]]    
mini_data.shape

(1168, 10)

import numpy as np
from mlxtend.feature_selection import ExhaustiveFeatureSelector as EFS
efs = EFS(RandomForestRegressor(),
          min_features=1,
          max_features=5,
          scoring='r2',
          n_jobs=-1)    
efs.fit(np.array(mini_data),y_train)
mini_data.columns[list(efs.best_idx_)]

Index(['MSSubClass', 'OverallQual', 'YearRemodAdd', 'BsmtFinSF1', 'GrLivArea'], dtype='object')

很显然,穷举特征选择也是构建了一个封装器,在封装器里使用了一种机器学习算法作为目标函数。

递归特征消除

递归特征消除RFE也是封装器法的一种具体实施,其主要思想是利用训练集数据生成模型,再根据模型的特征权重,对特征进行取舍,消除权重不同的特征,从而得到数据集的特征子集。然后,对这个特征子集重复上述过程,直到特征数量达到规定值为止。显然,这种寻找最优特征子集的方法依然是贪心搜索算法。

from sklearn.feature_selection import RFE
# 为避免大规模计算,还是从10佳中选择5强,
mini_data = X_train[X_train.columns[list(sfs3.k_feature_idx_)]]  

rfe = RFE(RandomForestRegressor(), #依旧使用随机森林回归
          n_features_to_select=5)     
rfe.fit(np.array(mini_data),y_train)
rfe.ranking_

array([4, 1, 3, 2, 1, 1, 1, 5, 1, 6])

对mini_data的各个特征的权重从高到低排序之后,表示顺序的序号,1表示相应索引的特征权重最靠前,也就是权重最高。

mini_data.columns[rfe.ranking_==1]

Index(['OverallQual', 'BsmtFinSF1', 'TotalBsmtSF', 'GrLivArea', 'GarageCars'], dtype='object')

对比发现,使用不同的方法选出的5强不完全一致,因此不同的特征方法会训练出不同效果的模型

3.3 过滤器法

过滤器法不评估子集的预测误差,而是使用某些统计指标,比如相关系数、互信息等——目标函数不同,根据这些统计指标,对各特征进行排序,以确定特征的取舍。

image-20220609194319468

下面用卡方检验(皮尔森卡方检验)作为统计指标选择特征

from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest    # 过滤器类
from sklearn.feature_selection import chi2    #引用一个统计指标函数
iris = load_iris()
X, y = iris.data, iris.target
skb = SelectKBest(chi2, k=2)    #k为2表示特征子集中的特征数量
result = skb.fit(X, y)    # 根据从大到小的排序取2个特征
print("X^2 is: ", result.scores_)
print("P-values is: ", result.pvalues_)
X^2 is:  [ 10.81782088   3.7107283  116.31261309  67.0483602 ]
P-values is:  [4.47651499e-03 1.56395980e-01 5.53397228e-26 2.75824965e-15]
  • 卡方检验是统计学上的假设检验方法。值越大,两个变量之间的偏差越大;反之,偏差越小。
  • P值是统计学中用于判断假设检验结果的参数。P值越小,原假设发生的概率就越小。

利用训练得到的模型对数据集X进行特征选择,得到含有两个特征的新数据集

X_new = skb.transform(X) 
X_new.shape

(150, 2)

显示数据对应的特征名称

import numpy as np
[iris.feature_names[np.where(X[0, :]==i)[0][0]] for i in X_new[0, :]]

['petal length (cm)', 'petal width (cm)']

过滤法中利用统计指标对特征排序,然后依据特征排序结果选择特征

iris.feature_names

['sepal length (cm)',
'sepal width (cm)',
'petal length (cm)',
'petal width (cm)']

过滤器的实现路径可以表示为:

过滤器法和封装器法对比:

  • 过滤器法通常不对数据集执行迭代计算,因此计算速度比封装器法要快
  • 封装器的目标函数是某个机器学习算法,过滤器的函数则是通用的统计函数,这样使得过滤器法所得到的特征更具有通用性,非专门针对某个算法有良好表现
  • 利用过滤器法进行特征选择时,用户需要武断地输入阈值,这可能会导致一定的选择成本。
  • 如果特征数量过少,过滤器可能无法找到最佳的特征子集,而封装器总能返回特征子集
  • 因为过滤器所得特征子集与某种算法无关,所以一般不会出现过拟合现象,而经由封装器法所得特征子集训练的模型,会出现过拟合现象。

在项目中,应依据具体数据和项目要求,确定特征选择的实施方法。

3.4 嵌入法

在3.1节中曾用对数概率回归模型研究了葡萄酒的等级与特征的关系。因为在模型中使用了L1惩罚项,从而得到了特征系数的稀疏解,某些特征的系数为0。如此,可以对系数排序——特征权重,然后依据某个阈值选择部分特征。

这种特性选择的实现方法显然不是封装法,也不是过滤器法,而是在训练模型的同时,得到了特征权重,并完成特征选择。像这样将特征选择过程与训练模型融为一体,在模型训练过程中自动进行特征选择,被称为嵌入法特征选择。

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression

df_wine = pd.read_csv("datasets/wine_data.csv")
X, y = df_wine.iloc[:, 1:], df_wine.iloc[:, 0].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0, stratify=y)

std = StandardScaler()
X_train_std = std.fit_transform(X_train)
X_test_std = std.fit_transform(X_test)
# 创建对数概率回归模型,采用L1惩罚项
lr = LogisticRegression(C=1.0, penalty='l1', solver='liblinear')  
# 规定选择特征的阈值--特征权重的中位数
# 能够用的机器学习模型还有随机森林模型、决策树模型、LASSO回归模型、岭回归模型等
model = SelectFromModel(lr, threshold='median')   
X_new = model.fit_transform(X_train_std, y_train)

X_new.shape

(124, 7)

X_train_std.shape

(124, 13)

3.5 综合练习

import pandas as pd
df = pd.read_csv("datasets/app_small.csv")
df.drop('Unnamed: 0', axis=1, inplace=True) # 删除第一列
df.shape

(30751, 122)

df.columns

Index(['SK_ID_CURR', 'TARGET', 'NAME_CONTRACT_TYPE', 'CODE_GENDER',
'FLAG_OWN_CAR', 'FLAG_OWN_REALTY', 'CNT_CHILDREN', 'AMT_INCOME_TOTAL',
'AMT_CREDIT', 'AMT_ANNUITY',
...
'FLAG_DOCUMENT_18', 'FLAG_DOCUMENT_19', 'FLAG_DOCUMENT_20',
'FLAG_DOCUMENT_21', 'AMT_REQ_CREDIT_BUREAU_HOUR',
'AMT_REQ_CREDIT_BUREAU_DAY', 'AMT_REQ_CREDIT_BUREAU_WEEK',
'AMT_REQ_CREDIT_BUREAU_MON', 'AMT_REQ_CREDIT_BUREAU_QRT',
'AMT_REQ_CREDIT_BUREAU_YEAR'],
dtype='object', length=122)

共有122个特征

数字类型的特征和非数字类型的特征分别保存到不同的列表中

categorical_list = []
numerical_list = []
for i in df.columns.tolist():
    if df[i].dtype=='object':
        categorical_list.append(i)
    else:
        numerical_list.append(i)
print('Number of categorical features:', str(len(categorical_list)))
print('Number of numerical features:', str(len(numerical_list)))

Number of categorical features: 16
Number of numerical features: 106

将数值类型和分类型分别查出来共有16个分类型,106个数值类型

df[numerical_list].isna().any()

SK_ID_CURR False
TARGET False
CNT_CHILDREN False
AMT_INCOME_TOTAL False
AMT_CREDIT False
...
AMT_REQ_CREDIT_BUREAU_DAY True
AMT_REQ_CREDIT_BUREAU_WEEK True
AMT_REQ_CREDIT_BUREAU_MON True
AMT_REQ_CREDIT_BUREAU_QRT True
AMT_REQ_CREDIT_BUREAU_YEAR True
Length: 106, dtype: bool

检查numerical_list中的特征是否有缺失值,如果有缺失值,则用中位数填补

from sklearn.impute  import SimpleImputer
df[numerical_list] = SimpleImputer(strategy='median').fit_transform(df[numerical_list])

categorical_list中的特征都是分类型特征,于是乎进行OneHot编码(创建虚拟变量)

df = pd.get_dummies(df, drop_first=True)
df.shape

(30751, 228)

df
SK_ID_CURR TARGET CNT_CHILDREN AMT_INCOME_TOTAL AMT_CREDIT AMT_ANNUITY AMT_GOODS_PRICE REGION_POPULATION_RELATIVE DAYS_BIRTH DAYS_EMPLOYED ... FONDKAPREMONT_MODE_reg oper spec account HOUSETYPE_MODE_specific housing HOUSETYPE_MODE_terraced house WALLSMATERIAL_MODE_Mixed WALLSMATERIAL_MODE_Monolithic WALLSMATERIAL_MODE_Others WALLSMATERIAL_MODE_Panel WALLSMATERIAL_MODE_Stone, brick WALLSMATERIAL_MODE_Wooden EMERGENCYSTATE_MODE_Yes
0 100003.0 0.0 0.0 270000.000 1293502.5 35698.5 1129500.0 0.003541 -16765.0 -1188.0 ... 0 0 0 0 0 0 0 0 0 0
1 100015.0 0.0 0.0 38419.155 148365.0 10678.5 135000.0 0.015221 -20417.0 365243.0 ... 0 0 0 0 0 0 0 0 0 0
2 100051.0 0.0 0.0 202500.000 661702.5 48280.5 598500.0 0.007114 -9827.0 -758.0 ... 0 0 0 0 0 0 0 0 0 0
3 100054.0 0.0 0.0 99000.000 260640.0 26838.0 225000.0 0.022625 -20121.0 -5332.0 ... 0 0 0 0 0 0 0 0 0 0
4 100069.0 0.0 1.0 360000.000 640458.0 27265.5 517500.0 0.007330 -14186.0 -1743.0 ... 0 0 0 0 0 0 0 0 0 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
30746 456195.0 0.0 0.0 94500.000 270000.0 15075.0 270000.0 0.028663 -20246.0 -5452.0 ... 0 0 0 0 0 0 0 1 0 0
30747 456212.0 0.0 1.0 135000.000 808650.0 23773.5 675000.0 0.009657 -18042.0 -186.0 ... 0 0 0 0 0 0 0 0 0 0
30748 456219.0 0.0 1.0 112500.000 521280.0 31630.5 450000.0 0.006207 -13346.0 -1972.0 ... 0 0 0 0 0 0 0 0 0 0
30749 456237.0 0.0 0.0 135000.000 946764.0 37678.5 765000.0 0.019689 -17533.0 -2306.0 ... 0 0 0 0 0 0 0 0 0 0
30750 456253.0 0.0 0.0 153000.000 677664.0 29979.0 585000.0 0.005002 -14966.0 -7921.0 ... 0 0 0 0 0 0 1 0 0 0

30751 rows × 228 columns

X = df.drop(['SK_ID_CURR', 'TARGET'], axis=1)
y = df['TARGET']
feature_name = X.columns.tolist()

先对X进行特征规范化操作,而后利用卡方检验选择50个特征

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
from sklearn.preprocessing import MinMaxScaler

X_norm = MinMaxScaler().fit_transform(X)    # MinMax区间化
chi_selector = SelectKBest(chi2, k=50)    # 过滤器法
chi_selector.fit(X_norm, y)

SelectKBest(k=50, score_func=<function chi2 at 0x000001C74C48F310>)

chi_support = chi_selector.get_support()
chi_feature = X.loc[:,chi_support].columns.tolist()  

使用封装器,选50个特征

from sklearn.feature_selection import RFE    
from sklearn.linear_model import LogisticRegression
rfe_selector = RFE(estimator=LogisticRegression(penalty="l1",solver='liblinear'), n_features_to_select=50, step=10, verbose=5)   
rfe_selector.fit(X_norm, y)    
rfe_support = rfe_selector.get_support()
rfe_feature = X.loc[:,rfe_support].columns.tolist()

用嵌入法选择特征

from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression    #使用logistic回归模型

embeded_lr_selector = SelectFromModel(LogisticRegression(penalty="l1",solver='liblinear'),threshold= '1.25*median')
embeded_lr_selector.fit(X_norm, y)

embeded_lr_support = embeded_lr_selector.get_support()
embeded_lr_feature = X.loc[:,embeded_lr_support].columns.tolist()
print(str(len(embeded_lr_feature)), 'selected features')

105 selected features

不用对数几率回归模型,改为随机森林分类

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier    #相对上面,模型换了

embeded_rf_selector = SelectFromModel(RandomForestClassifier(n_estimators=50), threshold='1.25*median')
embeded_rf_selector.fit(X, y)

embeded_rf_support = embeded_rf_selector.get_support()
embeded_rf_feature = X.loc[:,embeded_rf_support].columns.tolist()
print(str(len(embeded_rf_feature)), 'selected features')

98 selected features

# 下把特征按照被选择的次数从高到低列出来
feature_selection_df = pd.DataFrame({'Feature':feature_name, 
                                     'Chi-2':chi_support, 
                                     'RFE':rfe_support, 
                                     'Logistics':embeded_lr_support,
                                     'Random Forest':embeded_rf_support})
# 每个特征在不同方式中被选择的次数总和
feature_selection_df['Total'] = np.sum(feature_selection_df, axis=1)
# 按照次数大小,显示前50个
feature_selection_df = feature_selection_df.sort_values(['Total','Feature'] , ascending=False)
feature_selection_df.index = range(1, len(feature_selection_df)+1)
feature_selection_df.head(50)
Feature Chi-2 RFE Logistics Random Forest Total
1 REGION_RATING_CLIENT_W_CITY True True True True 4
2 ORGANIZATION_TYPE_Self-employed True True True True 4
3 ORGANIZATION_TYPE_Construction True True True True 4
4 ORGANIZATION_TYPE_Business Entity Type 3 True True True True 4
5 FLAG_OWN_CAR_Y True True True True 4
6 EXT_SOURCE_3 True True True True 4
7 EXT_SOURCE_2 True True True True 4
8 EXT_SOURCE_1 True True True True 4
9 DAYS_ID_PUBLISH True True True True 4
10 CODE_GENDER_M True True True True 4
11 WALLSMATERIAL_MODE_Monolithic True True True False 3
12 ORGANIZATION_TYPE_Transport: type 3 True True True False 3
13 ORGANIZATION_TYPE_Police True True True False 3
14 ORGANIZATION_TYPE_Military True True True False 3
15 ORGANIZATION_TYPE_Industry: type 9 True True True False 3
16 OCCUPATION_TYPE_Low-skill Laborers True True True False 3
17 OCCUPATION_TYPE_Laborers True False True True 3
18 OCCUPATION_TYPE_High skill tech staff True True True False 3
19 OCCUPATION_TYPE_Drivers True False True True 3
20 NONLIVINGAPARTMENTS_MODE False True True True 3
21 NAME_FAMILY_STATUS_Married True False True True 3
22 NAME_EDUCATION_TYPE_Higher education True False True True 3
23 LIVINGAREA_MEDI False True True True 3
24 FLOORSMIN_MEDI False True True True 3
25 FLOORSMAX_MODE False True True True 3
26 FLAG_WORK_PHONE True False True True 3
27 FLAG_DOCUMENT_3 True False True True 3
28 ENTRANCES_AVG False True True True 3
29 DEF_60_CNT_SOCIAL_CIRCLE False True True True 3
30 DEF_30_CNT_SOCIAL_CIRCLE False True True True 3
31 BASEMENTAREA_AVG False True True True 3
32 APARTMENTS_MEDI False True True True 3
33 AMT_REQ_CREDIT_BUREAU_MON False True True True 3
34 AMT_GOODS_PRICE False True True True 3
35 AMT_CREDIT False True True True 3
36 AMT_ANNUITY False True True True 3
37 YEARS_BEGINEXPLUATATION_MODE False False True True 2
38 YEARS_BEGINEXPLUATATION_MEDI False False True True 2
39 WEEKDAY_APPR_PROCESS_START_TUESDAY False False True True 2
40 WALLSMATERIAL_MODE_Wooden False True True False 2
41 REG_CITY_NOT_WORK_CITY True False False True 2
42 REG_CITY_NOT_LIVE_CITY True False False True 2
43 REGION_RATING_CLIENT True False False True 2
44 ORGANIZATION_TYPE_Transport: type 1 False True True False 2
45 ORGANIZATION_TYPE_Realtor False True True False 2
46 ORGANIZATION_TYPE_Other False False True True 2
47 ORGANIZATION_TYPE_Insurance False True True False 2
48 ORGANIZATION_TYPE_Industry: type 3 False True True False 2
49 ORGANIZATION_TYPE_Industry: type 2 False True True False 2
50 ORGANIZATION_TYPE_Industry: type 12 False True True False 2
posted @ 2022-06-09 20:20  王陸  阅读(786)  评论(0编辑  收藏  举报