随便记点今天学的
决策树特征重要性可视化
# 导入必要的库
from sklearn.tree import DecisionTreeClassifier
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt # 绘图库
# 忽略警告
import warnings
warnings.filterwarnings('ignore')
# 解决画图中文字体显示的问题
plt.rcParams['font.sans-serif'] = ['SimSun', 'Times New Roman'] # 汉字字体集
plt.rcParams['font.size'] = 10 # 字体大小
plt.rcParams['axes.unicode_minus'] = False
# 读取训练集和测试集文件
train_data = pd.read_csv('E:/编程/用户新增预测大赛/train.csv')
test_data = pd.read_csv('E:/编程/用户新增预测大赛/test.csv')
# 提取udmap特征,人工进行onehot
def udmap_onethot(d):
w = np.zeros(9)
if d == 'unknown':
return w
d = eval(d)
for i in range(1, 10):
if 'key' + str(i) in d:
w[i - 1] = d['key' + str(i)]
return w
train_udmap_df = pd.DataFrame(np.vstack(train_data['udmap'].apply(udmap_onethot)))
test_udmap_df = pd.DataFrame(np.vstack(test_data['udmap'].apply(udmap_onethot)))
train_udmap_df.columns = ['key' + str(i) for i in range(1, 10)]
test_udmap_df.columns = ['key' + str(i) for i in range(1, 10)]
# 编码udmap是否为空
train_data['udmap_isunknown'] = (train_data['udmap'] == 'unknown').astype(int)
test_data['udmap_isunknown'] = (test_data['udmap'] == 'unknown').astype(int)
# udmap特征和原始数据拼接
train_data = pd.concat([train_data, train_udmap_df], axis=1)
test_data = pd.concat([test_data, test_udmap_df], axis=1)
# 提取eid的频次特征
train_data['eid_freq'] = train_data['eid'].map(train_data['eid'].value_counts())
test_data['eid_freq'] = test_data['eid'].map(train_data['eid'].value_counts())
# 提取eid的标签特征
train_data['eid_mean'] = train_data['eid'].map(train_data.groupby('eid')['target'].mean())
test_data['eid_mean'] = test_data['eid'].map(train_data.groupby('eid')['target'].mean())
train_data['eid_std'] = train_data['eid'].map(train_data.groupby('eid')['target'].std()).astype(np.float32)
test_data['eid_std'] = test_data['eid'].map(train_data.groupby('eid')['target'].std()).astype(np.float32)
# 提取时间戳
train_data['common_ts'] = pd.to_datetime(train_data['common_ts'], unit='ms')
test_data['common_ts'] = pd.to_datetime(test_data['common_ts'], unit='ms')
train_data['common_ts_hour'] = train_data['common_ts'].dt.hour
test_data['common_ts_hour'] = test_data['common_ts'].dt.hour
进行数据载入/检测与特征分析工作。
# 训练模型:自己按需选取特征
x = train_data.drop(['udmap', 'common_ts', 'uuid', 'target', 'common_ts_hour', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7',
'x8', 'eid', 'eid_std', 'eid_mean', 'eid_freq', 'key1', 'key2', 'key3', 'key4', 'key5', 'key6',
'key7', 'key8', 'key9'], axis=1)
y = train_data['target']
clf = DecisionTreeClassifier()
clf.fit(x, y)
实在不知道怎么突破数据量限制,绘制完整特征重要性图像,只能分组绘制了。
# 获取特征重要性得分
feature_importances = clf.feature_importances_
# 创建特征名列表
feature_names = list(x.columns)
# 创建一个DataFrame,包含特征名和其重要性得分
feature_importances_df = pd.DataFrame({'feature': feature_names, 'importance': feature_importances})
# 对特征重要性得分进行排序
feature_importances_df = feature_importances_df.sort_values('importance', ascending=False)
# 颜色映射
colors = plt.cm.viridis(np.linspace(0, 1, len(feature_names)))
# 可视化特征重要性
fig, ax = plt.subplots(figsize=(10, 6))
ax.barh(feature_importances_df['feature'], feature_importances_df['importance'], color=colors)
ax.invert_yaxis() # 翻转y轴,使得最大的特征在最上面
ax.set_xlabel('特征重要性', fontsize=12) # 图形的x标签
ax.set_title('决策树特征重要性可视化', fontsize=16)
for i, v in enumerate(feature_importances_df['importance']):
ax.text(v + 0.01, i, str(round(v, 3)), va='center', fontname='Times New Roman', fontsize=10)
# 保存图形
plt.savefig('./特征重要性.jpg', dpi=400, bbox_inches='tight')
plt.show()
过拟合
定义:学习器把训练样本自身的一些特点当作了所有潜在样本都会具有的一般性质,导致泛化性能下降。具体表现就是最终模型在训练集上效果好;在测试集上效果差。模型泛化能力弱。
原因:
- 训练数据中噪音干扰过大,使得学习器认为部分噪音是特征从而扰乱学习规则
- 建模样本选取有误,例如训练数据太少,抽样方法错误,样本label错误等,导致样本不能代表整体
- 模型不合理,或假设成立的条件与实际不符
- 特征维度/参数太多,导致模型复杂度太高
解决办法(过拟合无法彻底避免,只能缓解):
- 保留验证集,获取额外数据进行交叉验证
- 降低模型复杂度,对于决策树可以限制树深,剪枝,限制叶节点数量
- 正则化,将权值的大小作为惩罚项加入到损失函数里,限制权值weight-decay
- 增加噪声
欠拟合
定义:对训练样本的一般性质尚未学好。在训练集及测试集上的表现都不好。
原因:
- 模型复杂度过低,表达能力较差
- 特征量过少,或现有特征与样本标签的相关性不强
解决办法:
- 增加特征数
- 增加模型复杂度
- 减小正则化系数
数据读取效率优化
# 尝试对比csv文件与parquet文件的读取效率
import pandas as pd
import time
start = time.time() # 计时起点
train_data = pd.read_csv('E:/编程/用户新增预测大赛/train.csv')
test_data = pd.read_csv('E:/编程/用户新增预测大赛/test.csv')
end = time.time() # 计时终点
print(end - start) # 输出读取csv文件耗时
train_data.to_parquet('train.parquet', compression=None)
test_data.to_parquet('test.parquet', compression=None)
start = time.time()
train_data = pd.read_parquet('train.parquet', engine='fastparquet')
test_data = pd.read_parquet('test.parquet', engine='fastparquet')
end = time.time()
print(end - start) # 输出读取parquet文件耗时
显然,pandas库的read_csv函数的读写效率不如read_parquet函数。