-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathselector.py
161 lines (130 loc) · 5.47 KB
/
selector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import warnings
import lightgbm as lgb
import numpy as np
import pandas as pd
import xgboost as xgb
from sklearn.metrics import make_scorer
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import cross_val_score
warnings.filterwarnings('ignore')
class Selector(object):
def __init__(self, ascending=False):
self.ascending = ascending
@staticmethod
def _get_xgb_model(**kwargs):
xgb_params = {
'booster': 'gbtree',
'learning_rate': 0.05,
'objective': 'reg:linear',
'n_estimators': 10000,
'silent': True,
'n_jobs': 4,
'random_state': 4590,
'verbose': -1
}
for k, v in kwargs.items():
xgb_params[k] = v
xgb_model = xgb.XGBRegressor(**xgb_params)
return xgb_model
@staticmethod
def _get_lgb_model(**kwargs):
lgb_params = {
'boosting_type': 'gbdt',
'objective': 'mae',
'n_estimators': 10000,
'metric': 'mae',
'learning_rate': 0.05,
'n_jobs': 4,
'verbose': -1,
'seed': 4590
}
for k, v in kwargs.items():
lgb_params[k] = v
lgb_model = lgb.LGBMRegressor(**lgb_params)
return lgb_model
@staticmethod
def _get_importance_features(model, columns, topn=300, ascending=False):
# ascending=False: 降序
# ascending=False: 升序
feature_importance = model.feature_importances_
importance_df = pd.DataFrame({'column': columns, 'score': feature_importance})
importance_df = importance_df.sort_values(by=['score'], ascending=ascending).reset_index()
importance_columns = importance_df['column'].loc[:topn].tolist()
return importance_columns
def _get_cv_error(self, x_train, y_train):
# model_list = [self._get_xgb_model(), self._get_lgb_model()]
model_list = [self._get_lgb_model()] # xgb速度过于慢,暂时只用lgb尝试
cv_error = 0.0
mae = make_scorer(mean_absolute_error)
for model in model_list:
mae_error = cross_val_score(model, x_train, y_train, scoring=mae, cv=5, n_jobs=5)
mae_error = np.mean(mae_error)
cv_error += mae_error
model_length = len(model_list)
cv_error = cv_error / model_length
return cv_error
def _get_increase_features(self, x_train, y_train):
# 获取有用特征
columns = x_train.columns
importance_columns_list = list()
for model in [self._get_xgb_model(), self._get_lgb_model()]:
meta_model = model.fit(x_train, y_train)
model_importance_columns = self._get_importance_features(meta_model, columns)
importance_columns_list.extend(model_importance_columns)
columns_num = 1
select_columns = list()
cv_error = 999.0
importance_columns_set = set()
for index, column in enumerate(importance_columns_list):
if column in importance_columns_set:
# set function will upset importance_columns_list order
continue
else:
importance_columns_set.add(column)
select_columns.append(column)
x_train_sample = x_train[select_columns]
tmp_cv_error = self._get_cv_error(x_train_sample, y_train)
if tmp_cv_error < cv_error:
cv_error = tmp_cv_error
print(f'columns_num:{columns_num}\tindex_num:{index}\tcv_error:{cv_error}\tcolumn:{column}')
columns_num += 1
else:
print(f'ignore column: {column}\tindex_num:{index}\tcv_error: {tmp_cv_error}')
select_columns.pop()
return select_columns
def _get_reduce_features(self, x_train, y_train):
# 删除无用特征
columns = x_train.columns
importance_columns_list = list()
for model in [self._get_xgb_model(), self._get_lgb_model()]:
meta_model = model.fit(x_train, y_train)
model_importance_columns = self._get_importance_features(meta_model, columns, ascending=True)
importance_columns_list.extend(model_importance_columns)
columns_num = x_train.shape[1]
select_columns = list(x_train.columns)
cv_error = 999.0
unimportance_columns_set = set()
for index, column in enumerate(importance_columns_list):
if column in unimportance_columns_set:
# set function will upset importance_columns_list order
continue
else:
unimportance_columns_set.add(column)
select_columns.remove(column)
x_train_sample = x_train[select_columns]
tmp_cv_error = self._get_cv_error(x_train_sample, y_train)
if tmp_cv_error < cv_error:
cv_error = tmp_cv_error
print(f'columns_num:{columns_num}\tindex_num:{index}\tcv_error:{cv_error}\tcolumn:{column}')
columns_num -= 1
else:
print(f'stay column: {column}\tindex_num:{index}\tcv_error: {tmp_cv_error}')
select_columns.append(column)
return select_columns
def get_select_features(self, x_train, y_train):
if self.ascending:
return self._get_reduce_features(x_train, y_train)
else:
return self._get_increase_features(x_train, y_train)