-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathSpeech.txt
74 lines (49 loc) · 13.6 KB
/
Speech.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
这些日常记录包括学生的行为信息, 比如每位同学一卡通的消费记录, 学生的成绩, 学生的图书的借阅几率, 图书馆和门禁的进出记录.通过这些记录信息, 我们能观测出一个学生的消费习惯, 学习状态和个人爱好. 这些信息反映了一个学生的紧急情况.例如, 一位贫困生就不会再日常生活中的其他方面花费的很多.
样本被分为四类{0, 1000, 1500, 2000}, 这意味着这是一个多分类问题.
如图所示, 没有获得助学金的同学所占的比重远远大于获得助学金, 因此, 我们把这个问题看做一个典型不均衡的多分类问题.
模型的评估标准: 需要注意的是, 为了评判每一个模型的性能好坏, 赛事举办方使用 Macro F1 score 得分来评判
公式:
这里的F1(i) 计算的是每一个类别i 在{0, 1000, 1500, 2000}中的准确率和召回率, N表示整个数据样本中学生的个数 Ni表示在i类别中的学生数量.
我们处理了冗余值与缺失值, 并且从每一个表中提取特征, 然后进行特征联合, 标准化 得到了模型的输入文件.
整体架构的说明: 我们首先描述了数据集和特征的提取. 这里我们将会说明特征工程的重要性. 在下一个部分中, .... 最后我们将会对整个项目做一个总结.
数据集: 数据描述
数据集包括了6个表, 分别是 图书借阅数据, 学生一卡通消费数据, 门禁进出数据, 图书馆门禁数据, 学生成绩数据. 我上面展示了所有训练集表中的字段 测试集和训练集相同的格式, 但是并没有标明助学金的类别
数据清洗:
因为所有的数据都是真实数据, 因此会有很多的脏数据存在 同时 也会有很多冗余数据和缺失数据的存在, 换句话说, 数据并不是规格的, 标准的.例如: 我们发现在门禁进出数据文件中, 一个学生的进入记录也许缺失进入记录, 也就是说存在不匹配的问题, 相同情况的数据在图书馆门禁中也出现过. 在图书借阅数据中, 有许多条目不包括图书的ISBN, 学生的消费记录中 花费额甚至出现负数. 因此 首要的目的就是进行数据清洗.
移除冗余数据相对比较简单. 对于缺失值的处理, 我们决定根据各种属性值来填补它们. 例如: 在成绩排名中用中位数来填补缺失值, 但是对那些没有借阅过图书的同学来说, 我们可以认为他没有借阅历史
特征工程:
1.特征工程的重要性: 为什么会很重要? 我们要知道所有的模型输入都是从特征提取开始的, 换句话说就是: 特征决定模型性能的好坏因素.
一位曾经是Kaggle比赛冠军的参赛者说过: 对每一位参赛者而言, 我们使用的算法已经是很标准很普遍的了, 反而在特征选取上花费了更多的时间, 同时,我们也非常谨慎地抛弃那些可能使我们面临过度拟合模型的特征. 实际上, 每一次的特征选取的如果更好的话, 对我们模型的提升效果也是很显著, 与此同时, 模型参数的选取也仅仅是在一个很小的范围内对模型有着细微的提升.
2.最大化模型输入:
我们的目标是尽可能的使用那些数据.例如: 我们之前忽视了消费数据中消费地点这一项属性,但是之后我发现这确实最有用的信息之一, 在项目中有许多那些令我们意外的好特种存在. 结果标明, 在多方面信息输入问题中, 最好的选择就是不要放弃原始数据表单中任何一个字段属性. 就假设所有的表中所有的字段都是有用的.
处理消费数据:
在所有数据集当中, 消费数据是最大的, 它包含了80%的特征数量. 不仅仅是因为它抱哈了更多的信息, 而且这也是观测一个学生紧急情况最有效的方面. 我们从学生消费文件中提取出了多维高质量的特征, 首先, 我们组合不同维度的特征使特征变得更具有合理性. 之后, 对每一个特征变量, 我们使用10个统计量来精确评测它们. 利用这个方法, 我们成功的从消费数据中提取了1000个特别有用的特征值. 在这些特征中, 我们展示了20个对模型贡献度最大的特征值出来. 令我们惊奇的是: "是否换卡" 成了最重要的特征. 这很难去解释为什么, 但是我们检查了原始数据, 发现这是确实存在的一个特征值, 剩下的都是一些组合特征, 反映了一个学生的生活习性, 看起来也是很合理很有意思的.
3.3特征构建和选择
在数据中发掘那些隐藏特征属性, 组合现有的特征去生成新的特征是很有效的一个方法. 通过基本算数将两个特征合并输出一个特征, 比如: 我们用消费总额除以消费天数(激活天数)-- 因为不同的学生他们的激活天数不一样; 再有: 用同学成绩的百分比, 来乘以他的消费百分比, 意味着更高排名同学的花费却很少, 他更可能会获得助学金. 其他一些例子包括:不同的消费类别除以消费总额得到消费类别的百分比. 但是不能简单地把这些组合特征值联合起来作为模型的输入文件, 因为这样做, 空间太大, 或许会使模型速度变慢, 甚至性能下降. 因此 最好的方式是了解预测问题的知识领域, 根据实际经验来构建新特征.
还有需要提及的问题就是特征选择, 这在学术界也是一个开放性的问题. 在我们的项目中, 我们剔除了一些导致过拟合的新特征, 使得我们得到了更好的结果.但是这样做也不是总是成功, 需要注意的就是要认真考虑并且对待每一个需要剔除的特征值, 因为每一个都是有价值的.
4.模型
4.1 模型输入准备
在进行完特征工程之后,我们需要对特征进行一些预处理,包括:填补缺失值,标准化特征以及处理不平衡问题。
在训练集中,很多特征都有缺失值。基于我们已经知道的数据,我们采用不同的策略去填补不同特征的缺失值。例如,对于“消费总金额”的特征而言,如果一个学生没有消费记录,那么我们认为在这个数据集中丢失了他的消费信息,因为一个学生一年之内不在学校里购买任何东西是不可能的,学生一定会有消费记录。因此,我们可以计算平均消费总金额去填补这个特征的缺失值。至于”在凌晨1点—凌晨2点学生的消费情况“,如果在这个时间段里没有这个学生的消费记录,那我们就可以把这个特征值填为0。显然,不是所有人都会熬夜去消费。
我们的这些不同的特征有不同的取值范围。一方面,我们获取消费总金额超过了10000美元的学生信息,另一方面我们将消费金额最多的排列顺序设定为是1。虽然这样像随机森林,梯度提升决策树和Adaboost这样的基于决策树的算法不会受到影响,但是这么做可能会导致模型整个的运行效率降低以及会影响像SVM和神经网络这样的算法模型结果的精度。在我们的项目中,我们标准化每个特征,使其看起来像标准的正态分布数据:利用高斯分布去计算零均值和单位权方差。
正如我们上一部分所提到的,我们面对不平衡的数据:大部分的样例都是那些没有补贴的学生。我们尝试使用三种方法去解决这个问题:密集采样,稀疏采样以及当计算损失函数时为样品附加权重。经过实验,我们发现稀疏采样是信息丢失和使样例选择困难的原因。对于密集采样,实际上相当于给样例设置权重:给训练集的样例设置两倍的权重也就意味着当发生错误时你需要承受两倍的惩罚。但是密集采样只支持整型权重,你不能重复样例1.5次。因此,我们选择第三种方法:允许给样例设置任意类型权重的方式。以下是带有样本权重的损失函数,如果第n个样例计算时出现误差,那么你需要付出Un倍的惩罚。我们给稀有的样本实例赋予高的权重以便于我们尽可能地预测出正确的样本实例。
(3)
4.2离线评估机制
因为我们每天只能在线上提交两次结果,所以我们需要建立有效的离线评估机制来调整模型参数。在我们的项目中我们使用5-折叠交叉验证。每当我们有了新的想法我们可以第一时间在交叉验证集中去验证它。我们只要一获得很好的离线结果就能立马将它提交到线上评估机制中去。
考虑数据不平衡的问题时,我们采取了分层抽样去建立交叉验证集。实验结果证明,分层抽样对在离线分和在线分之间保持一致性很有用。如果我们不使用分层抽样不同样本实例的比率在不同交叉验证集中是不一样的。这也是线下的分数高,线上的分数低的原因。图四展示了交叉验证集使用和不使用分层抽样。
图四:左边是没有使用分层抽样建立的交叉验证集。3个样本实例的比率在5个交叉验证集中不同。右边是使用了分层抽样建立的交叉验证集。
4.3模型建立
我们使用贪心坐标下降法和网格搜索法来调整模型参数。贪心坐标的意思是:我们根据每个参数对算法的影响去调整它们。
我们将使用GDBT作为一个例子来描述我们是如何使用这两种方法来调整参数的。表4是使用GDBT来展示一些重要的参数。使用网格搜索来穷举出这7个参数的所有的可能情况是不可能的。我们找到对算法的精度影响很大的样例权重。这样我们第一个调整这个参数。接着我们利用网格搜索同时调整max_depth和min_sample_leaf。因为他们会一起影响算法。然后我们调换min_sample_split,max_features。最终,我们通过网格搜索的学习速率和n_estimators来获取参数。事实上我们可以调换min_sample_split和min_sample_leaf的顺序,因为他们拥有相似的函数以避免过拟合。
另外通过经验来调整的参数不要一直坚持通过交叉验证集来选择做好的参数。图4是一个当我们在GDBT中调整参数n_estimators的真实的例子当n_estimators等于450时我们可以获得最好的线下值F1。但是当n_estimators超过450后F1会显著下降。因此,它事实上的一个边界点。因此我们不要很自信的说这个点是测试数据中最好的,或许当一切准备就绪开始测试数据阶段时这个点的值会下滑。在我们的项目的这个例子中我们首先会选择一个稳定的参数和像[200,450]这样高性能的间隔区间。我们将选择325为最佳参数的间隔区间的平均值。
图4:GDBT中真实参数变化样例
4.4模型集成
在模型集成阶段我们丢弃了SVM,NN和KNN模型因为这些模型的结果精度低,效率低。因此我们只保留了GDBT,XGB,RF,ET和Ada的这些有趣的基于树的集成算法。我们相信只使用5个学习模型集成绰绰有余,因此我们想到了一些方法来扩展一种算法到多个模型上去。
在许多基于树的算法中随机种子会影响模型的建立。例如,在RF中,随机种子会影响每个分裂的候选特征集和每棵重复采样的树的例子。因此选择不同的随机种子会得到不同模型结果。
图5:模型集成法则
我们也可以使用不同的特征来建立不同的模型GBDT可以实时输出一个用来分隔结点的重要的基础特征。我们通过重要的秩序来给予特征id。然后我们通过将特征对5求余的方式将特征划分为5个特征亚群。这10个特征亚群可以被用来建立10个模型
我们发现每中类型的标签的预测比率可以达到与F1高度相似的结果。对于GBDT,以下三个所有的预测比率都能达到很好的性能(2000奖金 : 1500:subsidy : 1000subsidy : 0) = (7635:2124:634:550), (7808:2117:677:359), (8239:1929:484:309).我们可以调节不同种类样例的权重来获取我们想要的预测比率。
通过扩展以上的三种方法,一个算法可以被扩展到不同的基础学习模型上去。图5展示了如何将这些学习模型融合。我们使用三层叠加的方法来集成。第0层,我们使用30种不同的种子和10个特征亚群通过一种算法来生成40个基础学习模型。第1层的分类器将第0层的输出作为输入使用少数服从多数投票算法进行预测。在学习模型中投票制度是平等的,因为他们是使用相同的算法建立的而且他们具有相似的精度。第二层,我们使用投票分类器来融合不同类型算法的预测从而生成最终的结果。在这种法则下,不同的投票算法是相应精度的基础。高精度模型获得高的票数。图6展示了不同的投票模型。比赛的最后几天,模型集成帮助我们逆天改命最终赢得了比赛。
5.总结
总的来说,我们介绍了本次比赛的整个流程:数据预处理,特征工程,模型建立以及模型集成。根据我们的经验,特征工程是最重要的一个步骤,特征直接决定最终的模型精度,如果特征质量很差,模型会变得越来越垃圾。模型集成就好似最后的冲刺。然而只有你的基础学习模型不同,你才可以通过模型集成来提高精度,事实上,我们也尝试过在第一层或者第二层使用Adaboost和GDBT来融合模型。但是这些强大的模型都会出现过拟合的问题因为我们的训练数据量没有那么大。因此我们在第一层和第二层选择了投票分类器。此外还有一个有趣的发现:在我们的项目中像GDBT,XGB,Ada,RF,ET这些基于树的集成模型超越了像SVM,NN,KNN这些没有集成的模型。因此,模型集成可以帮助我们在相同时间里减少误差和偏差就像我们在同一课堂中学习一样。
附录:数据集样例