此次进行特征选择的数据还是上次用到的金融数据并预测贷款用户是否会逾期。此次数据为了排除缺失值对数据的影响,将所有缺失的样本数据进行删除,并删除了几个对数据分类无影响的变量,最后保留1534×86的数据量。
1.删除方差较小的特征,也就是所谓的不发散的特征,因为这些特征在所有的数据中变化量很小或者几乎没有变化,那么可以认为这个变量对分类的结果不会产生太大的影响。
import pandas as pd
from sklearn.feature_selection import VarianceThreshold
data = pd.read_csv('data.csv')
label = data['status']#get label
data.drop('status',axis = 1, inplace = True)
names = data.columns
2.IV值进行特征选择
对于数据集中的变量来说,其蕴含的信息越多,那么对于分类结果的贡献就越大,信息价值就越大,也就是说此变量的IV(Information Value)就越大。对于IV值的具体计算可以参考:https://blog.csdn.net/a786150017/article/details/84573202
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold
def CalcIV(X,Y):
N_0=np.sum(Y==0)
N_1=np.sum(Y==1)
N_0_group=np.zeros(np.unique(X).shape)
N_1_group=np.zeros(np.unique(X).shape)
for i in range(len(np.unique(X))):
N_0_group[i] = Y[(X==np.unique(X)[i])&(Y==0)].count()
N_1_group[i] = Y[(X==np.unique(X)[i])&(Y==1)].count()
iv = np.sum((N_0_group/N_0-N_1_group/N_1)*np.log((N_0_group/N_0)/(N_1_group/N_1)))
if iv>=1.0:## 处理极端值
iv=1
return iv
def caliv_batch(data,Y):
ivlist=[]
for col in data.columns:
iv=CalcIV(data[col],Y)
ivlist.append(iv)
names=list(data.columns)
iv_df=pd.DataFrame({'Var':names,'Iv':ivlist},columns=['Var','Iv'])
return iv_df,ivlist
im_iv, ivl = caliv_batch(data,label)
threshold = 0.02
threshold2 = 0.6
data_index=[]
for i in range(len(ivl)):
if (im_iv['Iv'][i]< threshold)|(im_iv['Iv'][i] > threshold2):
data_index.append(im_iv['Var'][i])
data.drop(data_index,axis=1,inplace=True)
skf = StratifiedKFold(n_splits=10)#10折交叉
ac = []
for train_index, test_index in skf.split(data,label):
x_train, x_test = data.iloc[train_index,:], data.iloc[test_index,:]
y_train, y_test = label.iloc[train_index],label.iloc[test_index]
forest = RandomForestClassifier(n_estimators=100, random_state=0, n_jobs=-1)
forest.fit(x_train, y_train) #training
pre_rf = forest.predict(x_test)
ac_train = forest.score(x_train,y_train)
ac.append(ac_train)
print('the accuracy RF is : {:.4}'.format(np.mean(ac)))
最后数据集中只剩下3个特征['top_trans_count_last_1_month', 'rank_trad_1_month', 'regional_mobility']
分类的正确率为:0.7877,比用所有特征得到的结果要好。
3.用随机森林的方法来对其进行特征选择,这里主要是根据特征的重要性来选择的特征,属于filter类的方法
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold
forest = RandomForestClassifier(n_estimators=100, random_state=0,n_jobs=1)
forest.fit(data, label)
importance = forest.feature_importances_
imp_result = np.argsort(importance)[::-1]
columns = []
for i in range(data.shape[1]):
print("%2d. %-*s %f"%(i+1, 30, names[i], importance[imp_result[i]]))
columns.append(names[i])
columns = columns[0:44]
data1 = data[columns]
def RF_classify(train_data, train_label, test_data, test_label):
forest = RandomForestClassifier(n_estimators=15, random_state=0, n_jobs=-1)
forest.fit(train_data, train_label) #training
# pre_rf = forest.predict(x_test)
ac_train = forest.score(test_data, test_label)
return ac_train
skf = StratifiedKFold(n_splits=10)#10折交叉
ac = []
for train_index, test_index in skf.split(data1,label):
x_train, x_test = data1.iloc[train_index,:], data1.iloc[test_index,:]
y_train, y_test = label.iloc[train_index],label.iloc[test_index]
acc = RF_classify(x_train, y_train, x_test, y_test)
# acc = lightgbm_classify(x_train, y_train, x_test, y_test)
ac.append(acc)
print('the accuracy RF is : {:.4}'.format(np.mean(ac)))
4.除了filter类的方法外,我们还可以用遗传算法对特征进程编码,然后经过选择、交叉、变异最后选择出特征
代码后续再补充
5.sklearn中还有用wrapper的方法来进行特征选择,如递归特征消除法等,这里可以设置要选择特征的个数以及用的分类算法
from sklearn.feature_selection import RFE
data_=RFE(estimator=RandomForestClassifier(), n_features_to_select=10).fit_transform(data,label)
用随机森林分类的准确率为0.7764
6、以上的选择方法都是在完整的数据集上进行特征选择,但有的时候我们担心缺失值的填补会对数据分布造成影响,此时可以用决策树的方法来进行特征选择。在计算基尼指数或者信息熵的时候按照比例进行计算,最后按照特征的重要性排序选择特征。代码后续补充。
由于对此数据不是很熟悉,不太确定要怎么进行特征衍生,所以这部分后续进行补充。