A simple machine learning project 一、 数据预处理 首先读取在BuaaDataLab上下载的train与test数据集。通过人工观察后决定先将数据集中的birth_date特征转换为可操作的年龄特征age,再将身高和体重这两项数据经过简单计算整理为BMI这个特征。由于所给数据集中包含了门将与非门将的数据,因此有一些特征存在空白现象,我对此做出的处理是将门将与非门将数据集分开,因而要先在原数据集中新增一项特征is_gk来判断该球员是否为门将。此外数据集中的work_rate_att, work_rate_def, preferred_foot这三个特征为分类变量,在此考虑将其进行独热编码。最后为了再次简化特征,我将球员在各个位置(包括守门员)的能力值这11个特征取其中的最大值从而合并为1个特征best_pos。
二、 特征选择
-
特征降维 考虑到原数据的大小,其原本的53个特征数量显然是有点多的,如果直接对原数据集进行训练的话极大概率会出现过拟合现象。因此,我决定调用sklearn库中的LightGBM模型来对特征值进行筛选。
-
LightGBM模型原理 GBDT(Gradient Boosting Decision Tree)是机器学习中一个长盛不衰的模型,其主要思想是利用弱分类器迭代训练以得到最优模型,该模型具有训练效果好、不易过拟合等优点。GBDT不仅在工业界应用广泛,通常被用于多分类、点击率预测、搜索排序等任务;在各种数据挖掘竞赛中也是致命武器,据统计Kaggle上的比赛有一半以上的冠军方案都是基于GBDT。而LightGBM是一个实现GBDT算法的框架,支持高效率的并行训练,并且具有更快的训练速度、更低的内存消耗、更好的准确率、支持分布式可以快速处理海量数据等优点。 LightGBM采用Leaf-wise的增长策略,该策略每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。Leaf-wise的优点是:在分裂次数相同的情况下可以降低更多的误差,得到更好的精度;Leaf-wise的缺点是:可能会长处比较深的决策树,产生过拟合。因此LightGBM会在Leaf-wise之上增加一个最大深度的限制,在保证高效率的同时防止过拟合。 Gradient-based One-Side Sampling 应该被翻译为单边梯度采样(GOSS)。GOSS算法从减少样本的角度出发,排除大部分小梯度的样本,仅用剩下的样本计算信息增益,它是一种在减少数据量和保证精度上的平衡的算法。 GOSS是一个样本的采样算法,目的是丢弃一些对计算信息增益没有帮助的样本留下有帮助的。根据计算信息增益的定义,梯度大的样本对信息增益有更大的影响。因此,GOSS在进行数据采样的时候只保留了梯度较大的数据,但是如果直接将所有梯度较小的数据都丢弃掉势必会影响数据的总体分布。所以,OSS首先将要进行分裂的特征的所有取值按照绝对值大小降序排序(XGBoost一样也进行了排序,但是LightGBM 不用保存排序后的结果),选取绝对值最大的 a ∗ 100 % a * 100%a∗100% 个数据。然后在剩下的较小梯度数据中随机选择 b ∗ 100 % b * 100%b∗100% 个数据。接着将这 b ∗ 100 % b * 100%b∗100% 个数据乘以一个常数 1 − a b \frac{1-a}{b}b1−a ,这样算法就会更关注训练不足的样本,而不会过多改变原数据集的分布。最后使用这( a + b ) ∗ 100 % (a+b) * 100%(a+b)∗100% 个数据来计算信息增益。
-
使用LightGBM模型训练 由于sklearn库中已经有完善的LightGBM模型,在此我考虑直接调用该模型。 该模型是需要有test测试集中有y的真实值的,但我们当前的test数据集中y值需要我们自己去预测,因而为了训练LightGBM模型我只能使用sklearn库中的train_test_split工具将train训练集按照7:3的比例分为新的训练集和测试集。 准备好测试集和训练集后就可以开始训练LightGBM了,具体代码如下。其中LightGBM的参数采用的是网上公认的比较好的特征提取参数,在此我就没有去调参。
三、训练
-
训练模型的选择 在将特征降到20个以后我们还是可以看出这些特征的数值大小各异,综合考虑到这两个特点后我选择了随机森林模型来训练。随机森林模型刚好适合特征比较多的数据,且不需要对数据进行归一化处理。
-
随机森林模型原理 集成学习(ensemble)思想是为了解决单个模型或者某一组参数的模型所固有的缺陷,从而整合起更多的模型,取长补短,避免局限性。随机森林就是集成学习思想下的产物,将许多棵决策树整合成森林,并合起来用来预测最终结果。
首先,介绍自助法(bootstrap),这个奇怪的名字来源于文学作品 The Adventures of Baron Munchausen(吹牛大王历险记),这个作品中的一个角色用提着自己鞋带的方法把自己从湖底下提了上来。因此采用意译的方式,叫做自助法。自助法顾名思义,是这样一种方法:即从样本自身中再生成很多可用的同等规模的新样本,从自己中产生和自己类似的,所以叫做自助,即不借助其他样本数据。自助法的具体含义如下: 如果我们有个大小为N的样本,我们希望从中得到m个大小为N的样本用来训练。那么我们可以这样做:首先,在N个样本里随机抽出一个样本x1,然后记下来,放回去,再抽出一个x2,… ,这样重复N次,即可得到N的新样本,这个新样本里可能有重复的。重复m次,就得到了m个这样的样本。实际上就是一个有放回的随机抽样问题。每一个样本在每一次抽的时候有同样的概率(1/N)被抽中。 这个方法在样本比较小的时候很有用,比如我们的样本很小,但是我们希望留出一部分用来做验证,那如果传统方法做train-validation的分割的话,样本就更小了,bias会更大,这是不希望的。而自助法不会降低训练样本的规模,又能留出验证集(因为训练集有重复的,但是这种重复又是随机的),因此有一定的优势。 至于自助法能留出多少验证,或者说,m个样本的每个新样本里比原来的样本少了多少?可以这样计算:每抽一次,任何一个样本没抽中的概率为 (1-1/N),一共抽了N次,所以任何一个样本没进入新样本的概率为(1-1/N)N。那么从统计意义上来说,就意味着大概有(1-1/N)N这么大比例的样本作为验证集。当N→inf时,这个值大概是1/e,36.8%。以这些为验证集的方式叫做包外估计(out of bag estimate) bagging的名称来源于 ( Bootstrap AGGregatING ),意思是自助抽样集成,这种方法将训练集分成m个新的训练集,然后在每个新训练集上构建一个模型,各自不相干,最后预测时我们将这个m个模型的结果进行整合,得到最终结果。整合方式就是:分类问题用majority voting,回归用均值。 决策树是用树的结构来构建分类模型,每个节点代表着一个属性,根据这个属性的划分,进入这个节点的儿子节点,直至叶子节点,每个叶子节点都表征着一定的类别,从而达到分类的目的。 常用的决策树有ID4,C4.5,CART等。在生成树的过程中,需要选择用那个特征进行剖分,一般来说,选取的原则是,分开后能尽可能地提升纯度,可以用信息增益,增益率,以及基尼系数等指标来衡量。如果是一棵树的话,为了避免过拟合,还要进行剪枝(prunning),取消那些可能会导致验证集误差上升的节点。 随机森林实际上是一种特殊的bagging方法,它将决策树用作bagging中的模型。首先,用bootstrap方法生成m个训练集,然后,对于每个训练集,构造一颗决策树,在节点找特征进行分裂的时候,并不是对所有特征找到能使得指标(如信息增益)最大的,而是在特征中随机抽取一部分特征,在抽到的特征中间找到最优解,应用于节点,进行分裂。随机森林的方法由于有了bagging,也就是集成的思想在,实际上相当于对于样本和特征都进行了采样(如果把训练数据看成矩阵,就像实际中常见的那样,那么就是一个行和列都进行采样的过程),所以可以避免过拟合。 prediction阶段的方法就是bagging的策略,分类投票,回归均值。
- 使用随机森林模型进行训练 由于非守门员与守门员间部分特征差异过大,为了提高正确率我决定将这两类数据分开训练分开测试。首先是对非守门员数据进行训练,见下图:
在该回归问题中,min_samples_split和min_samples_leaf参数选定为2,不需要再做改变。n_estimators只需选择一个较大的初始值450即可,因为在迭代过程中会自动收敛于0,不需要自行去选择一个大小合适的参数。所以,本模型中最需要调整的便是max_depth参数。 参考网络上许多开源模型,我决定从75开始调整,由于参数较小,并且需要调整的幅度不大,所以在此我选择的是手动调参。我选择了70、 75、 85、 95这几个参数,在BuaaDatalab上分别提交后得到的mae值分别为20.997,20.958, 20.926, 20.983,我选择将max_depth值选为85。 将非守门员数据训练好后再按照同样的方法训练守门员数据。
最终结果MAE值 20.9