解决问题:对类别特征使用catboost,观察其特征重要程度。
今天搜索catboost的实例应用的博客,该博客的样例、demo、以及特征重要度打印,这三个内容,都是我想使用的。可是,他收费了,碰见我这个身无分文的人,大抵是不能看了。我相信,想要的信息总是可以在互联网上找到,只是时间问题罢了。经过搜集整理, 汇总如下。(本篇先不说原理,先将demo跑起来,原理篇周末再更)
1.数据样例把数据放在当前目录下data文件夹下的test文本中,数据我简单做了一些加工,可能看着有点怪,不用懂他们的意思,只需要知道数据格式是这个 样子就好,格式如下,第一了是label,剩下的每一列是一维特征,用't'分割。
0 6663435 10055 资深运营视 设计 IT 17150989 1951408 IT 产品 产品经理 3487 0 6677198 13868 专员 人事 IT 7471671 17191119 IT 研发 研发 9634 0 6501035 9181 用户中心 研发 IT 30461 351185 IT 研发 Unity开发 11193 0 985633 15776 制片 制片 文化传媒业 3880313 337578 交通物流业 调度 办事员 4971140 0 9058494 8538 数据 数据分析 IT 173960855 34691004 IT 研发 大数据开发 48 1 98790 0 其他 IT 01358 3395398 学生 关注IT/ 实习生 10055 0 7499635 5839593 教务主管 校长/教务管理 教行业 34471341 3457416 教行业 公司职员 9535 0 169035759 938 云计算 研发 IT 879508 338347 IT 研发 前端开发实习生 687 0 836809 0 执行董事 企业高管 医疗业 1691 1006003 IT 企业高管 创始人 0 1 9160655 3747 材料科学 其他 学生 3543173 758109 IT 研发 软件开发 179563 1 9999806 1 负责人 运营 IT 58411 6455997 IT 测试 高级测试 11016 0 169034189 0 业务总监 销售 制造业 9399495 18514071 制造业 生产管理 常经理 0 0 8581430 0 其他 IT 01305 153915691 教行业 教育 02.demo
上面数据的类型如下,可以看到有object,这个类型下放置的特征可以是类别特征,比如数据中的“设计”。
0 int64 1 int64 2 object 3 object 4 object 5 int64 6 int64 7 object 8 object 9 object 10 int64 dtype: object
一个非常奇怪的现象,如果我直接用panda的 read_table读取训练数据,得到的数据类型同上,但是训练模型时,报错如下,说是类型错误,也没有查到到底是啥错误,如何解决。
catboost TypeError: Cannot convert 'b'xe8x81x8cxe8xa8x80xe8xb4x9fxe8xb4xa3xe4xbaxba'' to float
于是,这里我做了另外一个文本 打开方式,并对响应特征做对应的处理,逻辑如下:
from catboost import CatBoostClassifier, Pool
import pandas as pd
#
dx = [] # 训练数据
dy = [] # 训练label
# cat_feat表示原始数据的第几列为类别特征,当第n列为类别特征时,写到dx中的数据用str转换格式。
cat_feat = [3, 4, 5, 8, 9, 10]
with open('./data/test', 'r') as rf:
for line in rf:
line_split = line.strip().split('t')
dy.append(int(line_split[0]))
tmp = []
for i in range(1, len(line_split)):
if i not in cat_feat:
tmp.append(int(line_split[i]))
else:
tmp.append(line_split[i])
dx.append(tmp)
print(dx)
# cat_features训练数据中类别特征的index
cat_features = [2, 3, 4,7, 8, 9]
dxdf = pd.Dataframe(dx)
print(dxdf.dtypes)
model = CatBoostClassifier(iterations=20)
#
model.fit(dxdf, dy, cat_features)
predictions = model.predict(dxdf)
print(predictions)
3.特征重要度打印
接着上面的代码,特征重要度打印的 demo如下:
里面有一个feature_name.txt的文件,里面放了一些特征索引,跟序列数据的顺序对应,它的作用用来给特征重要度标注名字。
0 xid 1 au_cid 2 au_po 3 au_j 4 au_f 5 au_u 6 uid 7 p 8 m 9 poi 10 id
如果没有这个索引,打印的特征重要度如下:
上面的特征重要度图,看起来比较费劲,还是需要让人一眼就看明白什么 特征最重要。这里对上图多了一些优化:
1.将索引改为特征名字
2.将特征重要度从大到小排序
import matplotlib.pyplot as plt
import numpy as np
fea_ = model.feature_importances_
print(fea_)
print(type(fea_))
fea_name = model.feature_names_
print(fea_name)
idx_name = {}
with open('./data/feature_name.txt', 'r') as rf:
for line in rf:
ln = line.strip().split(' ')
idx_name[ln[0]] = ln[1]
print(idx_name)
# fea_arr = np.array(fea_)
idx = np.argsort(fea_)
print('---idx: ', idx)
print(idx.shape)
final_feat = []
final_name = []
for i in idx:
print('--{0} {1}'.format(i, fea_[i]))
final_feat.append(fea_[i])
final_name.append(idx_name[str(i)])
print(final_feat)
print(final_name)
fig, ax = plt.subplots(figsize=(11, 11))
# Horizontal Bar Plot
ax.barh(final_name, final_feat, height=0.5)
# Remove axes splines
for s in ['top', 'bottom', 'left', 'right']:
ax.spines[s].set_visible(False)
# Add x, y gridlines
ax.grid(b=True, color='grey',
linestyle='-.', linewidth=0.5,
alpha=0.2)
# Add annotation to bars
for i in ax.patches:
plt.text(i.get_width()+0.2, i.get_y()+0.2,
str(round((i.get_width()), 2)),
fontsize=9, fontweight='bold',
color='black')
ax.set_title('feature importance' )
plt.show()
结果:
演示完毕。
我的学习笔记,永不付费浏览,这是我的原则之一。今天也听到了浅墨离开的消息,难过,研究生期间,全靠他的blog续命,希望将来的某一天,本土文化游戏如你所愿,也希望净肃某些垃圾企业文化。
此致敬礼



