用户新增预测挑战赛
背景
赛题介绍
赛事任务
基于提供的讯飞开放平台海量的应用数据的训练样本构建模型,预测用户的新增情况。
赛题数据集
赛题数据由约62万条训练集、20万条测试集数据组成,共包含13个字段。
数据记录 | 释义 |
---|---|
uuid | 样本唯一标识 |
eid | 访问行为ID |
udmap | 行为属性 |
common_ts | 应用访问记录发生时间(毫秒时间戳) |
x1 to x8 | 用户相关属性(匿名处理字段) |
target | 预测目标(是否为新增用户) |
注:udmap中的key1到key9表示不同的行为属性,如项目名、项目id等相关字段
评价指标
评价标准采用f1_score
f1_score
f1_score是一种用于评估二分类或多分类模型性能的指标之一,它结合了模型的精确度(precision)和召回率(recall)。f1_score可以作为一个综合指标,用于衡量模型在预测正例和负例时的准确性。
f1_score的计算公式如下:
f 1 _ s c o r e = 2 ∗ p r e c i s i o n ∗ r e c a l l p r e c i s i o n + r e c a l l f1\_score=2*\frac{precision*recall}{precision+recall} f1_score=2∗precision+recallprecision∗recall
其中,
- 精确度(precision) 表示模型预测为正例的样本中,实际上是真正例的比例。它衡量了模型预测为正例的准确性。
- 召回率(recall) 表示模型正确识别为正例的样本占所有实际正例样本的比例。它衡量了模型对正例样本的敏感程度。
f1_score的取值范围是0到1,其中1表示最佳性能,而0表示最差性能。当精确度和召回率都很高时,f1_score会接近1;当精确度和召回率存在较大差异时,f1_score会较低。
f1_score常用于不平衡类别数据集中,特别是在存在较多负例样本的情况下,因为它能够平衡考虑两个类别的性能表现。通过将精确度和召回率结合起来,f1_score提供了对模型综合性能的评估。
基本概念
baseline
在机器学习中,baseline通常指的是一个简单但有效的基准模型或方法,用于与新开发的模型进行比较和评估。这个基准模型可以作为一个参照点,帮助我们了解新模型的性能表现。
baseline的目的是提供一个相对简单且容易实现的模型来评估新的模型改进是否有效。如果新模型无法超过baseline的性能,那么需要重新考虑模型设计或者数据预处理等方面的改进。
csv文件
csv是一种常见的文件格式,其全称为"Comma-Separated Values"(逗号分隔值)。它是一种用于存储表格数据的简单文本文件格式。csv文件中的数据通常由逗号来进行分隔,每行代表表格中的一条记录,而每列代表各个字段(属性)的值。
特征工程
特征工程是指将原始数据转换为机器学习算法能够更好理解和利用的特征的过程。在机器学习领域中,特征是指用来描述数据的各种属性或特点的量化表示。
Python库
pandas库
pandas是一个流行的Python库,用于数据分析和数据处理。它提供了高性能、易于使用的数据结构和数据分析工具,使得处理和分析结构化数据变得更加简单。
pandas库提供了丰富的函数和方法,用于数据的加载、清洗、转换、分析和可视化。它还集成了许多其他常用的Python库(如NumPy和Matplotlib),使得在数据科学领域进行数据处理和分析更加便捷。
scikit-learn库
scikit-learn是一个用于机器学习的Python库,提供了许多用于数据预处理、模型选择、模型评估和模型部署的工具和算法。它构建在NumPy、SciPy和matplotlib等科学计算库的基础上,并且与其他常用的数据处理库(如pandas)兼容。
其中,
- sklearn.tree模块是scikit-learn库中的一个子模块,用于构建和训练决策树模型。决策树是一种基于树状结构的监督学习算法,可用于分类和回归任务。
- DecisionTreeClassifier类是scikit-learn库中sklearn.tree模块中的一个类,用于构建和训练基于决策树的分类模型。决策树是一种树状结构的机器学习算法,用于解决分类问题。
任务1:跑通Baseline
教程内容
实践步骤:
- 导入库:首先,代码导入了需要用到的库,包括 pandas(用于数据处理和分析)和 DecisionTreeClassifier(决策树分类器)等。
- 读取数据:代码通过使用 pd.read_csv 函数从文件中读取训练集和测试集数据,并将其存储在 train_data 和 test_data 两个数据框中。
- 特征工程:
- udmap_onethot 函数将原始的 udmap 特征进行了预处理,将其转换为一个长度为9的向量,表示每个key是否存在。
- 对 udmap 特征进行编码,生成 udmap_isunknown 特征,表示该特征是否为空。
- 将处理后的 udmap 特征与原始数据拼接起来,形成新的数据框。
- 提取 eid 特征的频次(出现次数)和均值,并添加为新的特征。
- 使用时间戳 common_ts 提取小时部分,生成 common_ts_hour 特征。
- 决策树模型训练和预测:
- 创建了一个 DecisionTreeClassifier 的实例,即决策树分类器。
- 使用 fit 函数对训练集中的特征和目标进行拟合,训练了决策树模型。
- 对测试集使用已训练的模型进行预测,得到预测结果。
- 将预测结果和相应的 uuid 组成一个DataFrame,并将其保存到 submit.csv 文件中。
教程实践代码:
# 1. 导入需要用到的相关库
# 导入 pandas 库,用于数据处理和分析
import pandas as pd
# 导入 numpy 库,用于科学计算和多维数组操作
import numpy as np
# 从 sklearn.tree 模块中导入 DecisionTreeClassifier 类
# DecisionTreeClassifier 用于构建决策树分类模型
from sklearn.tree import DecisionTreeClassifier
# 2. 读取训练集和测试集
# 使用 read_csv() 函数从文件中读取训练集数据,文件名为 'train.csv'
train_data = pd.read_csv('用户新增预测挑战赛公开数据/train.csv')
# 使用 read_csv() 函数从文件中读取测试集数据,文件名为 'test.csv'
test_data = pd.read_csv('用户新增预测挑战赛公开数据/test.csv')
# 3. 将 'udmap' 列进行 One-Hot 编码
# 数据样例:
# udmap key1 key2 key3 key4 key5 key6 key7 key8 key9
# 0 {'key1': 2} 2 0 0 0 0 0 0 0 0
# 1 {'key2': 1} 0 1 0 0 0 0 0 0 0
# 2 {'key1': 3, 'key2': 2} 3 2 0 0 0 0 0 0 0
# 在 python 中, 形如 {'key1': 3, 'key2': 2} 格式的为字典类型对象, 通过key-value键值对的方式存储
# 而在本数据集中, udmap实际是以字符的形式存储, 所以处理时需要先用eval 函数将'udmap' 解析为字典
# 具体实现代码:
# 定义函数 udmap_onethot,用于将 'udmap' 列进行 One-Hot 编码
def udmap_onethot(d):
v = np.zeros(9) # 创建一个长度为 9 的零数组
if d == 'unknown': # 如果 'udmap' 的值是 'unknown'
return v # 返回零数组
d = eval(d) # 将 'udmap' 的值解析为一个字典
for i in range(1, 10): # 遍历 'key1' 到 'key9', 注意, 这里不包括10本身
if 'key' + str(i) in d: # 如果当前键存在于字典中
v[i-1] = d['key' + str(i)] # 将字典中的值存储在对应的索引位置上
return v # 返回 One-Hot 编码后的数组
# 注: 对于不理解的步骤, 可以逐行 print 内容查看
# 使用 apply() 方法将 udmap_onethot 函数应用于每个样本的 'udmap' 列
# np.vstack() 用于将结果堆叠成一个数组
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)))
# 为新的特征 DataFrame 命名列名
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 = pd.concat([train_data, train_udmap_df], axis=1)
test_data = pd.concat([test_data, test_udmap_df], axis=1)
# 4. 编码 udmap 是否为空
# 使用比较运算符将每个样本的 'udmap' 列与字符串 'unknown' 进行比较,返回一个布尔值的 Series
# 使用 astype(int) 将布尔值转换为整数(0 或 1),以便进行后续的数值计算和分析
train_data['udmap_isunknown'] = (train_data['udmap'] == 'unknown').astype(int)
test_data['udmap_isunknown'] = (test_data['udmap'] == 'unknown').astype(int)
# 5. 提取 eid 的频次特征
# 使用 map() 方法将每个样本的 eid 映射到训练数据中 eid 的频次计数
# train_data['eid'].value_counts() 返回每个 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())
# 6. 提取 eid 的标签特征
# 使用 groupby() 方法按照 eid 进行分组,然后计算每个 eid 分组的目标值均值
# train_data.groupby('eid')['target'].mean() 返回每个 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())
# 7. 提取时间戳
# 使用 pd.to_datetime() 函数将时间戳列转换为 datetime 类型
# 样例:1678932546000->2023-03-15 15:14:16
# 注: 需要注意时间戳的长度, 如果是13位则unit 为 毫秒, 如果是10位则为 秒, 这是转时间戳时容易踩的坑
# 具体实现代码:
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')
# 使用 dt.hour 属性从 datetime 列中提取小时信息,并将提取的小时信息存储在新的列 'common_ts_hour'
train_data['common_ts_hour'] = train_data['common_ts'].dt.hour
test_data['common_ts_hour'] = test_data['common_ts'].dt.hour
# 8. 加载决策树模型进行训练(直接使用sklearn中导入的包进行模型建立)
clf = DecisionTreeClassifier()
# 使用 fit 方法训练模型
# train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1) 从训练数据集中移除列 'udmap', 'common_ts', 'uuid', 'target'
# 这些列可能是特征或标签,取决于数据集的设置
# train_data['target'] 是训练数据集中的标签列,它包含了每个样本的目标值
clf.fit(
train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1), # 特征数据:移除指定的列作为特征
train_data['target'] # 目标数据:将 'target' 列作为模型的目标进行训练
)
# 9. 对测试集进行预测,并保存结果到result_df中
# 创建一个DataFrame来存储预测结果,其中包括两列:'uuid' 和 'target'
# 'uuid' 列来自测试数据集中的 'uuid' 列,'target' 列将用来存储模型的预测结果
result_df = pd.DataFrame({
'uuid': test_data['uuid'], # 使用测试数据集中的 'uuid' 列作为 'uuid' 列的值
'target': clf.predict(test_data.drop(['udmap', 'common_ts', 'uuid'], axis=1)) # 使用模型 clf 对测试数据集进行预测,并将预测结果存储在 'target' 列中
})
# 10. 保存结果文件到本地
# 将结果DataFrame保存为一个CSV文件,文件名为 'submit.csv'
# 参数 index=None 表示不将DataFrame的索引写入文件中
result_df.to_csv('submit.csv', index=None)
实践经历
实操并回答下面问题:
- 如果将submit.csv提交到讯飞比赛页面,会有多少的分数?
f1_score = 0.6268分。
- 代码中如何对udmap进行了人工的onehot?
创建相应的零数组来对udmap进行One-Hot编码,再将其编入原数据中。
任务2
任务2.1:数据分析与可视化
教程内容
实践步骤:
- 导入必要的库,特别是画图库。
- 计算特征与标签之间的相关性,展示热力图。
- 展示特征与标签分组统计图。
教程实践代码:
# 导入库
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)
实践经历
第一阶段:实践操作
在具体的实践中我遇到了许多问题。首先,将上述教程实践代码直接复制到pycharm中会发现程序无法运行。报告错误如下:
Traceback (most recent call last):
File "E:\OneDrive - zju.edu.cn\桌面\match\draft.py", line 12, in <module>
sns.heatmap(train_data.corr().abs(), cmap='YlOrRd')
File "C:\Users\Bob\AppData\Roaming\Python\Python310\site-packages\pandas\core\frame.py", line 10054, in corr
mat = data.to_numpy(dtype=float, na_value=np.nan, copy=False)
File "C:\Users\Bob\AppData\Roaming\Python\Python310\site-packages\pandas\core\frame.py", line 1838, in to_numpy
result = self._mgr.as_array(dtype=dtype, copy=copy, na_value=na_value)
File "C:\Users\Bob\AppData\Roaming\Python\Python310\site-packages\pandas\core\internals\managers.py", line 1732, in as_array
arr = self._interleave(dtype=dtype, na_value=na_value)
File "C:\Users\Bob\AppData\Roaming\Python\Python310\site-packages\pandas\core\internals\managers.py", line 1794, in _interleave
result[rl.indexer] = arr
ValueError: could not convert string to float: '{"key3":"67804","key2":"650"}'
通过错误报告,我发现数据中存在非数值内容导致热力图绘制出错,即udmap部分,同时还发现代码并没有图像展示的部分。于是对代码改进如下:
# 导入库
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')
# 将udmap值设为NaN
train_data['udmap'] = np.nan
# 相关性热力图
sns.heatmap(train_data.corr().abs(), cmap='YlOrRd')
plt.show()
# x7分组下标签均值
sns.barplot(x='x7', y='target', data=train_data)
plt.show()
图像结果为
可以发现,相关性热力图存在空白列,不符合预期要求,而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')
# 创建一个新的DataFrame,包含相关性数据,但不包含 "udmap" 列
correlation_data = train_data.drop(columns=['udmap']).corr().abs()
# 相关性热力图
sns.heatmap(correlation_data, cmap='YlOrRd')
plt.show()
# x7分组下标签均值
sns.barplot(x='x7', y='target', data=train_data)
plt.show()
相关性热力图绘制结果:
至此,第一阶段任务已完成。
第二阶段:编写代码回答下面的问题:
- 字段x1至x8为用户相关的属性,为匿名处理字段。添加代码对这些数据字段的取值分析,那些字段为数值类型?那些字段为类别类型?
x3, x4, x5为数值类型;x1, x2, x6, x7, x8为类别类型。
在类型分类上,我通过对8个字段的唯一值进行分析,得出上述结论,分析代码如下:
import pandas as pd
import matplotlib.pyplot as plt
train_data = pd.read_csv('用户新增预测挑战赛公开数据/train.csv')
# 输出x1至x8的唯一值个数
heights = []
categories = []
for i in range(1, 9):
field = 'x' + str(i)
categories.append(field)
heights.append(train_data[field].nunique())
plt.bar(categories, heights, color='blue', edgecolor='black')
for i in range(len(heights)):
plt.text(i, heights[i] + 2, str(heights[i]), ha='center')
plt.show()
绘图结果如图所示,
由绘图结果,显然可以得到上述结论。
- 对于数值类型的字段,考虑绘制在标签分组下的箱线图。
代码:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
train_data = pd.read_csv('用户新增预测挑战赛公开数据/train.csv')
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])
plt.show()
箱线图:
- 从common_ts中提取小时,绘制每小时下标签分布的变化。
代码:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
train_data = pd.read_csv('用户新增预测挑战赛公开数据/train.csv')
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(15, 6),dpi=80)
train_data['common_ts'] = pd.to_datetime(train_data['common_ts'], unit='ms')
# 使用 dt.hour 属性从 datetime 列中提取小时信息,并将提取的小时信息存储在新的列 'common_ts_hour'
train_data['common_ts_hour'] = train_data['common_ts'].dt.hour
sns.countplot(x="common_ts_hour",hue='target', data=train_data, ax = axes[0])
new_df = (train_data.groupby('common_ts_hour')['target']
.value_counts(normalize=True)
.sort_index()
.unstack()
)
new_df.plot.bar(stacked=True, ax = axes[1])
plt.show()
图像结果:
- 对udmap进行onehot,统计每个key对应的标签均值,绘制直方图。
代码:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
train_data = pd.read_csv('用户新增预测挑战赛公开数据/train.csv')
def udmap_onethot(d):
v = np.zeros(9) # 创建一个长度为 9 的零数组
if d == 'unknown': # 如果 'udmap' 的值是 'unknown'
return v # 返回零数组
d = eval(d) # 将 'udmap' 的值解析为一个字典
for i in range(1, 10): # 遍历 'key1' 到 'key9', 注意, 这里不包括10本身
if 'key' + str(i) in d: # 如果当前键存在于字典中
v[i - 1] = d['key' + str(i)] # 将字典中的值存储在对应的索引位置上
return v # 返回 One-Hot 编码后的数组
# 注: 对于不理解的步骤, 可以逐行 print 内容查看
# 使用 apply() 方法将 udmap_onethot 函数应用于每个样本的 'udmap' 列
# np.vstack() 用于将结果堆叠成一个数组
train_udmap_df = pd.DataFrame(np.vstack(train_data['udmap'].apply(udmap_onethot)))
# 为新的特征 DataFrame 命名列名
train_udmap_df.columns = ['key' + str(i) for i in range(1, 10)]
# 将编码后的 udmap 特征与原始数据进行拼接,沿着列方向拼接
train_data = pd.concat([train_data, train_udmap_df], axis=1)
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_df = pd.DataFrame(key_means, index = [0])
plt.figure(figsize=(12, 6))
sns.barplot(data=key_means_df, palette="Set3")
plt.xlabel('Keys')
plt.ylabel('Mean Target')
plt.title('Stacked Bar Plot of Mean Target by Keys')
plt.show()
图像结果:
任务2.2:模型交叉验证
教程内容
实操步骤:
- 加载数据集,并对数据进行编码
- 导入多个模型进行交叉验证
- 比较模型的F1精度
教程实践代码:
# 导入库
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))
实践经历
第一阶段:实践操作
运行上述代码,pycharm返回信息如下:
C:\Users\Bob\AppData\Roaming\Python\Python310\site-packages\sklearn\linear_model\_stochastic_gradient.py:713: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
warnings.warn(
C:\Users\Bob\AppData\Roaming\Python\Python310\site-packages\sklearn\linear_model\_stochastic_gradient.py:713: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
warnings.warn(
C:\Users\Bob\AppData\Roaming\Python\Python310\site-packages\sklearn\linear_model\_stochastic_gradient.py:713: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
warnings.warn(
C:\Users\Bob\AppData\Roaming\Python\Python310\site-packages\sklearn\linear_model\_stochastic_gradient.py:713: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
warnings.warn(
C:\Users\Bob\AppData\Roaming\Python\Python310\site-packages\sklearn\linear_model\_stochastic_gradient.py:713: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
warnings.warn(
precision recall f1-score support
0 0.864 0.775 0.817 533155
1 0.157 0.257 0.195 87201
accuracy 0.702 620356
macro avg 0.511 0.516 0.506 620356
weighted avg 0.765 0.702 0.730 620356
precision recall f1-score support
0 0.934 0.940 0.937 533155
1 0.618 0.592 0.605 87201
accuracy 0.891 620356
macro avg 0.776 0.766 0.771 620356
weighted avg 0.889 0.891 0.890 620356
precision recall f1-score support
0 0.893 0.736 0.807 533155
1 0.221 0.458 0.298 87201
accuracy 0.697 620356
macro avg 0.557 0.597 0.552 620356
weighted avg 0.798 0.697 0.735 620356
precision recall f1-score support
0 0.921 0.955 0.938 533155
1 0.644 0.502 0.564 87201
accuracy 0.891 620356
macro avg 0.783 0.728 0.751 620356
weighted avg 0.882 0.891 0.885 620356
第二阶段:编写代码回答下面的问题:
-
在上面模型中哪一个模型的macro F1效果最好,为什么这个模型效果最好?
由代码的返回结果经分析可得图表如下:
显然,DecisionTreeClassifier(即决策树模型)的效果最好。这有三个方面的原因:其一,在非平衡数据集处理上,由于其基于特征分割数据的特点,该模型能够更好地适应不均衡的类别分布;其二,在特征组合上,由于该模型能够自动进行特征组合和选择,从而能够捕捉到不同特征之间的复杂关系;其三,在非线性关系上,该模型是一种非参数模型,不对数据分布做过多假设,因此能够捕捉到数据中的非线性关系。 -
使用树模型训练,然后对特征重要性进行可视化;
代码:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier
train_data = pd.read_csv('用户新增预测挑战赛公开数据/train.csv')
clf = DecisionTreeClassifier()
# 使用 fit 方法训练模型
# train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1) 从训练数据集中移除列 'udmap', 'common_ts', 'uuid', 'target'
# 这些列可能是特征或标签,取决于数据集的设置
# train_data['target'] 是训练数据集中的标签列,它包含了每个样本的目标值
clf.fit(
train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1), # 特征数据:移除指定的列作为特征
train_data['target'] # 目标数据:将 'target' 列作为模型的目标进行训练
)
# s树的特征重要性可视化
def plot_feature_importances_cancer(model):
n_features = train_data.shape[1] - 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_cancer(clf)
plt.show()
图像结果:
- 再加入3个模型训练,对比模型精度;
这里分别采用默认参数的岭回归分类器、极度随机树和梯度提升树进行训练得到结果。
代码:
import pandas as pd
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import classification_report
from sklearn.model_selection import cross_val_predict
from sklearn.tree import ExtraTreeClassifier
from sklearn.ensemble import GradientBoostingClassifier, BaggingClassifier
train_data = pd.read_csv('用户新增预测挑战赛公开数据/train.csv')
# 岭回归分类器
pred = cross_val_predict(
RidgeClassifier(),
train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1),
train_data['target']
)
print(classification_report(train_data['target'], pred, digits=3))
# 极度随机树
pred = cross_val_predict(
ExtraTreeClassifier(),
train_data.drop(['udmap', 'common_ts', 'uuid', 'target'], axis=1),
train_data['target'