赛题网站传送门
题目描述
基于每月用户更换5G套餐数据,分析4G用户更换5G套餐的行为特征,从更换5G套餐的4G用户的基础信息、消费行为、超套信息、宽带信息、其他信息等维度,构建5G套餐潜客识别模型,识别出目前4G用户具有更换5G套餐的需求群体。
第一次参加数据分析,花了一个星期,A榜结果还行,B榜结果不怎么样,估计是过拟合,一些数据分析的东西也不太懂,这里记录下任务完成下来的细节。
1. pandas读取、处理csv文件
1.1 设置显式的最大行数pd.set_option('display.max_columns', _ )
pd.set_option(‘display.max_rows’, 10)pd.set_option(‘display.max_columns’, 10)显示的最大行数和列数,如果超额就显示省略号,这个指的是多少个dataFrame的列。如果比较多又不允许换行,就会显得很乱。
pd.set_option(‘expand_frame_repr’, False)显示的最大行数和列数,如果超额就显示省略号,这个指的是多少个dataFrame的列。如果比较多又不允许换行,就会显得很乱。
pd.set_option(‘precision’, 5)True就是可以换行显示。设置成False的时候不允许换行
显示小数点后的位数
pd.set_option还有其他一些参数可以设置,这里不展开。
1.2 读取csv文件pd.read_csv
train_label = pd.read_csv('./train_label.csv', encoding = 'utf-8')train_set = pd.read_csv('./train_set.csv',)
1.3 合并读取的csvpd.merge
train = pd.merge(train_set, train_label, left_on = 'user_id', right_on = 'user_id', how='left', sort = False)
pd.merge 相关参数说明
left:参与合并的左侧DataFrame对象
right:参与合并的右侧的DataFrame对象
how:表示连接方式,默认为 inner,该参数的取值有以下:
(1)left:使用左侧的DataFrame的键,类似于SQL的左外连接。 //左表全部显示,右表显示与重叠数据行索引值相同的数据
(2)right:使用右侧的DataFrame的键,类似于SQL的右外连接。 //右表全部显示,左表显示与重叠数据行索引值相同的数据
(3)outer:使用两个DataFrame所有的键,类似于SQL的全连接。
(4)inner:使用两个DataFrame的交键,类似于SQL的内连接。 //默认连接方式
on:用于连接的列名。 必须存在于左右两个DataFrame对象中。
left_on:以左侧的DataFrame作为连接键。
right_on:以右侧的DataFrame作为连接键
left_index:左侧的行索引的用作连接键。
right_index:右侧的行索引的用作连接键。
sort:是否排序,接收布尔值,默认为False。
suffixes:用于追加到重叠列名的末尾,默认为(_x,_y)
# 合并前>>> train_label.columnsIndex(['user_id', 'label'], dtype='object')>>> train_set.columnsIndex(['user_id', 'product_no', 'X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X7', 'X8','X9', 'X10', 'X11', 'X12', 'X13', 'X14', 'X15', 'X16', 'X17', 'X18','X19', 'X20', 'X21', 'X22', 'X23', 'X24', 'X25', 'X26', 'X27', 'X28','X29', 'X30', 'X31', 'X32', 'X33', 'X34', 'X35', 'X36', 'X37', 'X38','X39', 'X40', 'X41', 'X42', 'X43'],dtype='object')# 合并后,多了‘label'>>> train.columnsIndex(['user_id', 'product_no', 'X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X7', 'X8','X9', 'X10', 'X11', 'X12', 'X13', 'X14', 'X15', 'X16', 'X17', 'X18','X19', 'X20', 'X21', 'X22', 'X23', 'X24', 'X25', 'X26', 'X27', 'X28','X29', 'X30', 'X31', 'X32', 'X33', 'X34', 'X35', 'X36', 'X37', 'X38','X39', 'X40', 'X41', 'X42', 'X43', 'label'],dtype='object')
1.4 合并,pandas.concat()
合并数据统一对特征处理
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False)
参数说明
objs: series,dataframe或者是panel构成的序列 list
axis: 需要合并链接的轴,0是行,1是列
join:连接的方式 inner,或者outer
其他参数不常用,遇到了再补充
df = pd.concat([train, test], axis = 0)
1.5 索引设置,set_index() reset_index()
1.5.1set_index()
DataFrame.set_index(keys, drop=True, append=False, inplace=False, verify_integrity=False)
drop:默认为true,表示是否删除列作为新索引。
append:是否增加列到原来的索引上。
inplace:是否创建一个新的dataframe
DataFrame.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill='')
文档链接 /pandas-docs/stable/generated/pandas.DataFrame.reset_index.html
drop 为True,表示删除原来的索引
drop 为 False, 表示原来的索引作为一列保留,列名为 index
2. sklearn处理数据特征
在训练模型之前,我们通常都要对训练数据进行一定的处理。将类别编号就是一种常用的处理方法,比如把类别“男”,“女”编号为0和1。可以使用sklearn.preprocessing
中的LabelEncoder
处理这个问题。
我们的数据里是需要将 “先生”、“女士”分类。
下面是bash运行结果,分为了0, 1两类
LabelEncoder
对应的介绍见https://scikit-/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html?highlight=labelencoder
from sklearn import preprocessingencoder = preprocessing.LabelEncoder()df['X1'] = encoder.fit_transform(df['X1'])
>>> df['X1']0 女士1 先生2 女士3 先生4 女士..149995 女士149996 女士149997 先生149998 先生149999 女士>>> encoder.fit_transform(df['X1'])array([1, 0, 1, ..., 0, 0, 1])>>> encoder.classes_array(['先生', '女士'], dtype=object)
3. 根据原始数据提取特征
这里主要指根据提供的信息,对信息加一些处理,比如有当月使用流量,上个月的使用流量,上上月的,将上月减当月,上上月减上月
4. 特征处理feature_selector
特征选择(feature selection)是查找和选择数据集中最有用特征的过程,是机器学习流程中的一大关键步骤。不必要的特征会降低训练速度、降低模型可解释性,并且最重要的是还会降低其在测试集上的泛化表现。
feature_selector传送门
feature_select github
简单介绍,feature_selector主要对以下类型的特征进行选择:
具有高missing-values百分比的特征,identify_missing(*)
具有高相关性的特征,identify_collinear(*)
,对于每一对相关的特征,它都会标识出其中要移除的一个(因为我们只需要移除其中一个)对模型预测结果无贡献的特征(即zero importance),identify_zero_importance(*)
,只适用监督学习对模型预测结果只有很小贡献的特征(即low importance),identify_low_importance(*)
,只使用监督学习具有单个值的特征(即数据集中该特征取值的集合只有一个元素),identify_single_unique(*)
创建一个FeatureSelector实例,可以读取 FeatureSelector 的 ops 属性
fs = FeatureSelector(data=train_features, labels=train_labels)fs.identify_collinear(correlation_threshold=0.99)print(fs.ops['collinear'])
5. 分类器训练Catboost
使用了catboost作为分类器
相应的学习链接
xgboost, lightgbm, catboost, 谁才是预言之战的最终赢家?
机器学习算法之CatBoost
这次觉得比较重要的是分类特征的指定,catboost是可以转入这个参数的,不过传入前数据要先做好转换
第二个是使用one_hot编码
第三是模型过拟合问题:训练iteration大小,树的深度,还有正则化
6. 比赛具体模型设计、代码
树模型的训练代码都比较简单,这次用了catboost分类器模型。(目前看来lightgbm,xgboost用得比较多)。
初始化模型、fit、predict
此外还有网格搜索方式,但是这种类型的任务主要在数据,还有模型参数。
# 数据train_df = df.loc[df['orgin']=='train']test_df = df.loc[df['orgin']=='test']# train_features = train_df[cols1]train_labels = train_df['label']# 模型model = cat.CatBoostClassifier(loss_function='Logloss',eval_metric='AUC',learning_rate=0.01,iterations=4000,random_seed=42,od_type='Iter',depth=10,l2_leaf_reg=4,one_hot_max_size = 6,early_stopping_rounds=500)model.fit(train_df[feature],train_df['label'])y_pred_proba = model.predict_proba(test_df[feature])