任务:数据分析与可视化
数据探索性分析,是通过了解数据集,了解变量间的相互关系以及变量与预测值之间的关系,对已有数据在尽量少的先验假设下通过作图、制表、方程拟合、计算特征量等手段探索数据的结构和规律的一种数据分析方法,从而帮助我们后期更好地进行特征工程和建立模型,是机器学习中十分重要的一步。
示例给的匿名标签与target之间相关性的热力图
数据
热力图
x7与target的标签均值
似乎看起来就是x7标签下出现的标签与target出现的概率显示,这一部分和均值的关系并没有看出来,这一部分的均值会不会是x7数据出现概率的数学期望?这个问题还没解决。
以下是示例代码
# 导入库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 读取训练集和测试集文件
train_data = pd.read_csv('用户新增预测挑战赛公开数据/train.csv')
test_data = pd.read_csv('用户新增预测挑战赛公开数据/test.csv')
# 相关性热力图
sns.heatmap(train_data.corr().abs(), cmap='YlOrRd')
# x7分组下标签均值
sns.barplot(x='x7', y='target', data=train_data)
从common_ts中提取小时,绘制每小时下标签分布的变化。
做法和任务一中是类似的:
1.把common_ts中的时间戳改为以ms的数据,用pd.to_datatime完成
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")
2.把ms的数据用dt.hour这种属性设置提成小时
train_data["common_ts_h"] = train_data["common_ts"].dt.hour
test_data["common_ts_h"] = test_data["common_ts"].dt.hour
3.用countplot这种图会更适合做出标签变化感(看见还有人用groupby函数去分析了以小时分组的相对于target次数统计的图,CV过来用一用,太天才了,佩服大佬能想出来)
sns.countplot(x="common_ts_h",hue='target', data=train_data)# 条状图
update_graph = (train_data.groupby("common_ts_h")["target"]
.value_counts(normalize=True)# 百分比格式
.sort_index()
.unstack())
update_graph.plot.bar(stacked = True)# 百分比条状图
图
对udmap进行onehot,统计每个key对应的标签均值,绘制直方图。
前几步仍然和任务一类似
- 声明调用matplotlib.pyplot库和seabron库
import matplotlib.pyplot as plb import seaborn as sns
- 自定义一个独热算法函数
def one_hot(n): v = np.zeros(9) if n == "unknown": return v else: n = eval(n) for i in range(1,10): if "key"+str(i) in n: v[i-1] = n["key"+str(i)] return v
- 把字典格式存储的udmap转换成一个dataframe,改名字并且缝合到原本的train_data里面
train_data_df = pd.DataFrame(np.vstack(train_data['udmap'].apply(one_hot))) train_data_df.columns = ['key' + str(i) for i in range(1, 10)] train_data = pd.concat([train_data, train_data_df], axis=1)
- 建立一个单独的字典key_mean,然后从1~9算过去,把每个key相对于target的均值算出来存在字典里
key_means = {} for key in ["key"+str(i) for i in range(1,10)]: key_mean = train_data[train_data[key]!=0]["target"].mean() key_means[key] = key_mean key_means
- 用字典转换成dataframe并生成图
key_means_df = pd.DataFrame(key_means, index = [0]) print(key_means_df) plb.figure(figsize=(12, 6)) sns.barplot(data=key_means_df, palette="Set3") plb.xlabel('Keys') plb.ylabel('Mean Target') plb.title('Stacked Bar Plot of Mean Target by Keys') plb.legend(title='Keys', loc='upper right') plb.show()
图
画的柱状图,直方图一直画不出来,
x1~x7字段的分析
首先得要把x1~x7之间哪些是类型数据,哪些是数值数据分出来,这两者之间的分别大致在于数量以及连续与否上,像数量小、数据间连续性明显的大多都是类型数据,而数量大、缺少连续性的数据往往会是数值类型。因此在dataframe里面随机取一部分数据出来看看便可以知道类型是什么了
train_data[["x"+str(i)for i in range(1,9)]].head(10)
输出结果是这样的
x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | |
---|---|---|---|---|---|---|---|---|
0 | 4 | 0 | 41 | 107 | 206 | 1 | 0 | 1 |
1 | 4 | 0 | 41 | 24 | 283 | 4 | 8 | 1 |
2 | 4 | 0 | 41 | 71 | 288 | 4 | 7 | 1 |
3 | 1 | 3 | 41 | 17 | 366 | 1 | 6 | 1 |
4 | 0 | 3 | 41 | 92 | 383 | 4 | 8 | 1 |
5 | 0 | 3 | 41 | 104 | 250 | 4 | 8 | 1 |
6 | 1 | 3 | 41 | 150 | 27 | 1 | 6 | 1 |
7 | 0 | 3 | 41 | 143 | 347 | 4 | 7 | 1 |
8 | 4 | 0 | 41 | 24 | 338 | 1 | 2 | 0 |
9 | 4 | 3 | 41 | 75 | 59 | 1 | 7 | 1 |
由此可见x3、x4、x5是数值类型,而其余的是类别类型
然后就得对数值类型的数据进行箱线图刻画了。
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(10, 6))
for i,y in enumerate(['x3', 'x4', 'x5']):
sns.boxplot(x="target", y=y, data=train_data, width=0.5, showfliers=False,ax=axes[i])
图长这样
(分割的不是很好,标签重合了……)
总结
- matplotlib和seaborn用的不是很熟,画一张图要找半天教程
- pandas库的groupy函数真的好有玩法,可以干好多事情,分组、找关系用groupby真的好好用
- 关于某个数据和target的均值究竟是什么?是target出现1的概率的数学期望还是什么?关于这点我有些搞不清楚,还是希望有个大佬教一下我吧(@o@)
任务:交叉验证
旨在用上多个模型相互检验评估模型的性能和能力,要求尽可能的使用完数据集,并且有比较稳健的表现,这意味着这个模型预测的时候,它的f1-score必须要高,而准确性accura的就没有相对高的要求了。
以下是题解代码
# 导入库
import pandas as pd
import numpy as np
# 读取训练集和测试集文件
train_data = pd.read_csv('用户新增预测挑战赛公开数据/train.csv')
test_data = pd.read_csv('用户新增预测挑战赛公开数据/test.csv')
# 提取udmap特征,人工进行onehot
def udmap_onethot(d):
v = np.zeros(9)
if d == 'unknown':
return v
d = eval(d)
for i in range(1, 10):
if 'key' + str(i) in d:
v[i-1] = d['key' + str(i)]
return v
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['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
# 导入模型
from sklearn.linear_model import SGDClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import MultinomialNB
from sklearn.ensemble import RandomForestClassifier
# 导入交叉验证和评价指标
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import classification_report
# 训练并验证SGDClassifier
pred = cross_val_predict(
SGDClassifier(max_iter=10),
train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1),
train_data['target']
)
print(classification_report(train_data['target'], pred, digits=3))
# 训练并验证DecisionTreeClassifier
pred = cross_val_predict(
DecisionTreeClassifier(),
train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1),
train_data['target']
)
print(classification_report(train_data['target'], pred, digits=3))
# 训练并验证MultinomialNB
pred = cross_val_predict(
MultinomialNB(),
train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1),
train_data['target']
)
print(classification_report(train_data['target'], pred, digits=3))
# 训练并验证RandomForestClassifier
pred = cross_val_predict(
RandomForestClassifier(n_estimators=5),
train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1),
train_data['target']
)
print(classification_report(train_data['target'], pred, digits=3))
哪种模型的效果最好?原因?
DecisionTreeClassifier效果最好,它的f1-score是最高的
使用树模型训练,然后对特征重要性进行可视化
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
clf = DecisionTreeClassifier()
clf.fit(
train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1),
train_data['target']
)
# s树的特征重要性可视化
def plot_feature_importances(model):
n_features = train_data.shape[1]-4 # 列数-4
plt.barh(range(n_features),model.feature_importances_,align = 'center')# 横向柱状图以及参数
plt.yticks(np.arange(n_features),train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1).columns)#输数据
plt.xlabel("Feature importance")
plt.ylabel("Feature")
plot_feature_importances(clf)
再加入3个模型训练,对比模型精度
不清楚有什么可以用的模型,去网上搜了一下,额外决策树似乎是可以用来看看的
pred = cross_val_predict(
ExtraTreeClassifier(),
train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1),
train_data['target']
)
print(classification_report(train_data['target'], pred, digits=3))