系列目录:
Python数据挖掘与机器学习_通信信用风险评估实战(1)——读数据
Python数据挖掘与机器学习_通信信用风险评估实战(2)——数据预处理
有这么一句话在业界广为流传:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。
数据使用经数据预处理,合并后的宽表train_user_comm_basic
。
遍历DataFrame的特征,
for col in df.columns:
logger.info('%s,%s,%s,%s' % (
col, df[col].dtype, df[col].unique(), df[col].size))
logger.info('%s' % (df[col].value_counts()))
logger.info('%s' % (df[col].describe()))
logger.info('%s' % ('----------------------------------------'))
根据单特征的分析,进行特征处理。
缺失值处理,依据对通信的业务和数据理解,填充缺失值。AGE
列缺失数据6个,用中位数填充。ARPU
和SP_FEE
列缺失数据14个,用0填充。NUM_OF_COMM
缺失数据88个,用0填充。
train_user_comm_basic['AGE'] = train_user_comm_basic['AGE'].fillna(train_user_comm_basic['AGE'].median())
train_user_comm_basic = train_user_comm_basic.fillna({'ARPU': 0, 'SP_FEE': 0})
train_user_comm_basic = train_user_comm_basic.fillna({'NUM_OF_COMM': 0})
移除低方差的特征(Removing features with low variance),VarianceThreshold会移除所有方差不满足阈值的特征,默认设置下,它会移除所有方差为0的特征,即那些在所有样本中数值完全相同的特征。 OCCUPATION_ID
、CITY_ID
、date
列在所有样本中数值完全相同,可移除,其中CITY_ID
由于初赛是抽样数据,在决赛中可能不完全相同,可保留并进行重编码。
类别变量重编码,COUNTY_ID
、TELE_FAC
、SMART_SYSTEM
为分类变量,依据所用算法采取两种重编码方案,一是用cat.codes
(Label Encoding)重新编码为数字集合,二是如果类别变量列有k个不同取值,用get_dummies
(One Hot Encoding)派生出一个k列DataFrame(其值全为1和0)。因TELE_FAC
和SMART_SYSTEM
的种类很多,编码后的维度会极大增加,为避免维度灾难,保留TOP10分类取值,其余取值置为其他。
COUNTY_ID_ONE_HOT = pd.get_dummies(train_user_comm_basic['COUNTY_ID'], prefix='COUNTY_ID', drop_first=True)
train_user_comm_basic = pd.concat((train_user_comm_basic, COUNTY_ID_ONE_HOT), axis=1)
data_temp = train_user_comm_basic.groupby('TELE_FAC').size().sort_values()[:-20].index
train_user_comm_basic['TELE_FAC'] = train_user_comm_basic['TELE_FAC'].replace(list(data_temp), '其他')
TELE_FAC_ONE_HOT = pd.get_dummies(train_user_comm_basic['TELE_FAC'], prefix='TELE_FAC', drop_first=True)
train_user_comm_basic = pd.concat([train_user_comm_basic, TELE_FAC_ONE_HOT], axis=1)
train_user_comm_basic['SMART_SYSTEM'] = train_user_comm_basic['SMART_SYSTEM'].fillna('others')
data_temp = train_user_comm_basic.groupby('SMART_SYSTEM').size().sort_values()[:-10].index
train_user_comm_basic['SMART_SYSTEM'] = train_user_comm_basic['SMART_SYSTEM'].replace(list(data_temp), 'others')
SMART_SYSTEM_ONE_HOT = pd.get_dummies(train_user_comm_basic['SMART_SYSTEM'], prefix='SMART_SYSTEM', drop_first=True)
train_user_comm_basic = pd.concat([train_user_comm_basic, SMART_SYSTEM_ONE_HOT], axis=1)
衍生变量,FIST_USE_DATE
截断到月份取值太多,衍生变量FIST_USE_YEAR
,截断到年份。
train_user_comm_basic['FIST_USE_YEAR'] = train_user_comm_basic['FIST_USE_DATE'].str[:4]
data_temp = train_user_comm_basic.groupby('FIST_USE_YEAR').size().sort_values().index[-1]
train_user_comm_basic['FIST_USE_YEAR'][train_user_comm_basic['FIST_USE_YEAR']=='\\N'] = train_user_comm_basic['FIST_USE_YEAR'][train_user_comm_basic['FIST_USE_YEAR']=='\\N'].replace('\\N', data_temp)
train_user_comm_basic['FIST_USE_YEAR'] = train_user_comm_basic['FIST_USE_YEAR'].astype('int64')
交叉表分析,对数据处理前和处理后的每个特征与分类变量计算分组频率,验证数据处理过程是否正确,以及观察单特征与分类变量的关系。
# 特征与目标变量的交叉表输出
def df_crosstab(df):
logger = create_logger(df_crosstab)
for col in df.columns:
print col
if col == 'RISK_Flag':
continue
print pd.crosstab(df[col], df['RISK_Flag'], margins=True)
logger.info('%s' % (pd.crosstab(df[col],
df['RISK_Flag'],
margins=True)))
logger.info('%s' % ('----------------------------------------'))
经特征处理后,训练数据的维数为(7000, 80)。高维度数据集容易过拟合。
特征选择:基于树的属性子集选择,把数据输入RandomForestClassifier
训练,然后用SelectFromModel
提取训练的模型,最后使用transform
方法筛选出重要的特征。
训练集和交叉验证集的变量都需要筛选,且筛选原则是一致的,所以把筛选出来的特征的索引或列保存在fea_index
或fea_col
中。
# -------------feature selection------------------
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectFromModel
rf = RandomForestClassifier()
feature_set = rf.fit(x, y)
model = SelectFromModel(rf, prefit=True)
feature_set = model.transform(x)
fea_col = []
for A_col in x.columns:
for B_col in np.arange(feature_set.shape[1]):
if (x.loc[:, A_col] == feature_set[:, B_col]).all():
fea_col.append(A_col)
fea_index = []
for A_col in np.arange(x.shape[1]):
for B_col in np.arange(feature_set.shape[1]):
if (x.iloc[:, A_col] == feature_set[:, B_col]).all():
fea_index.append(A_col)
fea_impor = sorted(zip(map(lambda x: round(x, 4), rf.feature_importances_), x.columns), reverse=True)
附1:bug参考资料
索引、选取
e:\work\ml_py27\lib\site-packages\ipykernel_launcher.py:1: DeprecationWarning:
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing
See the documentation here:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated
"""Entry point for launching an IPython kernel.
Guide to Encoding Categorical Values in Python
http://pbpython.com/categorical-encoding.html