机器学习算法竞赛实战-学习总结

本文为 《机器学习算法竞赛实战》by 王贺、刘鹏、钱乾一书的学习手记。
仅以此书来入门Kaggle等机器学习竞赛,学习Kaggle竞赛题该如何做,具体问题该如何用机器学习的方法来解决。

背景

  • 机器学习在大多数时候只是数学统计,数据相关的特征工程直接决定了模型的上限,而算法只是不断地逼近这个上限而已。

竞赛的介绍

竞赛平台

Kaggle

  • Kaggle是全世界最受欢迎的数据科学竞赛网站
  • 主要包含 Competitions(竞赛)、Datasets(数据)、Code(代码笔记)、Discussion(社区论坛)、Learn(在线课程)几个部分。
  • 当然最主要的竞赛部分,每一个竞赛主要包含 Overview、Data、Code、Discussion、Leaderboard、Rules几个部分。
    • Overview主要介绍竞赛的概况,包含基本的描述,评价标准、奖项和时间线
    • Data 数据通常是CSV格式的宽表数据,包含数据的来源,以及各个字段的含义
    • Code 这正是竞赛的开源社区精神所在,在这里可以看到各种数据探索、特征工程、建模方法的实现方式,也可以将各种建模方法进行融合,博采众长。
    • Discussion 讨论区和代码笔记略有不同,这里很少有代码,是参赛者真正交流的地方,有很多各种QA和对赛事的理解、发现。在这里可以见到各种Master和Grandmaster的身影。
    • LeaderBoard 用于展示排行榜,所有成功提交过的文件,都可以在这里找到位置,榜单实时刷新。通常分为Public Leaderboard 和 Private Leaderboard. 通常只有公开榜可以反复验证,最后只有两次机会选择用于计算B榜的结果文件,最终排名以B榜为准。这里也体现了机器学习重要的一点,就是注重模型的泛化性,只有健壮性强的模型才能在未来预测中始终保持良好的效果。
    • Rules, 竞赛的规则,是对overview部分更加详细的补充,通常需要注意几个时间点,比如Ab榜开放时间,B榜切换时间,队伍人数,提交次数的限制等等。
      机器学习算法竞赛实战-学习总结_第1张图片

天池

  • 打造国际高端算法竞赛,让选手用算法解决社会或业务问题,一般实战性和应用性较强。

其他算法竞赛

  • DF (DataFunction) CCF指定的专业大数据及人工智能竞赛平台
  • DC (DataCastle) 数据城堡,与Kaggle、天池比较类似
  • Kesci 和鲸社区 侧重高校计算机大赛
  • JDATA 京东智汇平台,主要涉及一些电商和物流
  • 企业网站的竞赛 比如腾讯、华为等

竞赛流程

要参加一次数据科学的竞赛,或者要用数据科学解决一个问题,通常有如下几步:

问题建模 --> 数据探索 --> 特征工程 --> 问题建模 --> 模型训练 --> 模型融合

问题建模

问题建模,就是要审题并理解题目。机器学习的问题建模中,并不是所有数据都是特征加标签这种可以直接加入模型训练的形式,很多时候需要分析数据,进而抽象出建模目标和方案。

数据探索

  • 数据探索是机器学习最重要的概念之一, 也被称为EDA(Exploratory Data Analysis)探索性数据分析,在知道问题的建模方式之后,需要结合赛题背景业务看看数据长什么样子、数据是否和描述相符、数据包含哪些信息、数据的质量等。首先要对数据有一个清晰的认知,比如表中每个字段的含义、范围和数据结构等,然后更深层次要结合标签分析特征的分布、训练集和测试集的同分布情况。特征之间的业务关联以及隐含信息表征等。
  • 数据探索承上启下,能够更好的理解问题建模,也能为接下来特征工作做准备

特征工程

  • 特征工程(Feature Engineering)也是机器学习重要概念,机器学习大多数是在进行特征工程,特征决定了机器学习预测效果的上限,而算法只是不断去逼近这个上限而已。

模型训练

  • 根据问题建好模型,根据业务理解进行了相关的数据探索,继而逐步完善特征工程,就可以得到标准的训练集和测试集结构。机器学习训练,一般使用GDBT类的树模型,常见的树模型主要有XGBoost、LightGBD,而且都有scikit-learn接口,比较方便使用。有时也会用到LR、SVM、RF等算法,有时候会用到DNN、CNN、RNN等深度学习模型等

模型融合

  • 经过前期繁琐艰辛的尝试之后,终于到了模型融合(寻找队友)的阶段了,每种算法都有其自身的优势和局限性,综合各个算法的优势可以使得模型效果更好。
  • 模型融合有许多办法,诸如Stacking、加权投票等。

问题建模

数据理解

数据基础层

  • 数据基础层:重点关注每个字段的来源、生产过程、取数逻辑、计算逻辑等。
  • 由于原始数据的质量良萎不齐、数据的类型存储形式多种多样,需要正确的理解、选取并使用每个字段,从而加工计算出所需要的更多衍生的字段,最终以数据表格呈现。

数据描述层

  • 数据描述层主要是在处理好的数据基础层上进行统计分析和概况描述,重点关注一些简单的统计量,(均值、方差、最值、分布、增幅、趋势等)
  • 通过统计指标,概况数据的情况

评价指标

分类指标

  • 错误率 & 精度

    • 错误率:分类结果错误的样本,占样本总数的比例
    • 精度: 分类结果正确的样本,占样本总数的比例
  • 准确率 & 召回率

    • 准确率:Precision = TP / (TP + FP) 被分类器判定为正样本中真正正样本所占的比重 (即分类器判定的正样本,有多少是真正的正样本)
    • 召回率: Recall = TP / (TP + FN) 被分类器判定为正样本占总的正样本的比重 (即所有正类样本中有多少被分类器判定为正样本)
  • F1-score 准确率和召回率的调和平均 F1-score = 2 * (P * R) / (P + R) 最大值是1,最小值是0

  • ROC曲线: 用于绘制不同分类阈值时的TP率和FP率。 降低分类阈值会导致更多样本被归为正类样本。

  • AUC :表示ROC曲线下的面积,因为ROC曲线通常处于y = x上方,所有AUC取值范围在0.5~1.0之间。很多时候ROC曲线并不能清晰说明那个分类器效果更好,而AUC作为一个数值,其值越大,代表分类器效果越好。

  • 对数损失:对数损失通过惩罚错误的分类来实现对分类器准确度的量化,最小化对数损失等价于最大化分类器的准确度。 为了计算对数损失,分类器必须提供概率结果,即把输入样本喂入模型后,预测得到每个类别的概率,而不只是预测最可能的类别
    在这里插入图片描述
    在这里插入图片描述

机器学习算法竞赛实战-学习总结_第2张图片

回归指标

  • 平均绝对误差(MAE Mean Absoult Error) 也称为L1范数损失。平均绝对误差能够解决残差和的正负抵消问题,能较好的衡量回归模型的好坏,但是绝对值的存在导致函数不光滑,某些点上不能求导。
    机器学习算法竞赛实战-学习总结_第3张图片

  • 均方误差 (MSE Mean Squared Error) L2范数
    机器学习算法竞赛实战-学习总结_第4张图片

  • 均方根误差 (RMSE)由于均方值误差与数据标签的量纲不一致,通常需要对均方误差进行开方
    机器学习算法竞赛实战-学习总结_第5张图片

  • 平均绝对百分比误差 MAPE 不同于平均绝对误差,不仅考虑了预测值与真实值的误差,还考虑了误差与真实值之间的比例。
    机器学习算法竞赛实战-学习总结_第6张图片

平均绝对误差 & 均方误差有何区别:

  • 均方误差对误差取了平方,若误差大于1,则均方误差会进一步增大误差,因此相对于平均绝对误差计算损失,均方误差会赋予异常点更大的权重,即均方误差对异常值更加敏感。
  • 平方绝对误差,因为平衡误差的正负,取了绝对值,导致函数不光滑,不是二阶连续可微函数。所以需要使用可导的目标函数来逼近平均绝对误差,而MES又会随着损失函数的减小而减小,随损失函数的增大而增大。因此大家在训练时,通常选择Huber损失进行替换,它会由于梯度的减小而落在最小值附近。因此Huber损失函数结合了平均绝对误差和均方误差的优点。
  • 但是Huber损失函数需要不断调整超参数delta

样本处理

样本数据的选择,会对预测结果造成很大的影响
比如常见的问题有:

  • 数据集过大,影响模型的性能 – >一般需要降采样 或者 分场景
  • 噪声和异常数据导致准确率不高 -->噪声具有双面性
    • 先考虑是否采集错误导致的,然后再去权衡模型的泛化性和模型的当前效果
    • 一方面噪声导致数据质量变低,影响模型效果
    • 另一方面通过在训练集中引入噪声使得模型更加健壮
  • 样本数据冗余或不相关数据没有给模型带来收益
    • 数据冗余侧重描述数据特征的冗余,一个典型的解决方案是进行特征选择
  • 正负样本不均衡导致数据存在倾斜

数据采样的方法

  • 数据采样就是模拟随机现象,根据给定的概率分布去模拟一个随机事件
  • 采样是用少量的样本去近似整体的分布,并刻画总体分布中的不确定性

如果拿到数据发现数据集过大以及样本不均衡该如何处理?
在数据量非常大的情况下,为了降低成本,如何提高模型训练速度:

  • 简单随机抽样, 通常分为有放回和无放回两种
  • 分层采样:先将数据集分成不同的子集(类别/层),然后对每个类别分别进行随机抽样

针对正负样本不均衡的场景,如何通过数据采样解决这类问题:

  • 评分加权处理:对于像欺诈交易识别、垃圾邮件识别等,其正负样本的数量分布差距极大
    • 考虑到正样本的重要性高于负样本,在模型训练以及评价时,可以设计相应的得分权重,使得模型能够学习到获得关注的部分。
    • 当然不同的应用场景可以选择不同的加权方式,比如Micro Fscore、Wighted Fscore指标等
  • 欠采样:(下采样)从数据较多的一类样本中随机选取一部分剔除,常用的方式又随机欠采样和Tomek Links
  • 过采样:(上采样)主要对于样本较少的类别进行重新组合,构造新样本。常用的方法有随机过采样和SMOTE算法。

数据的线下评估

通常对于竞赛的数据集不能都用于训练,这回导致没有数据对模型进行线下验证。通常会将数据集分成训练集和验证集。

  • 强时序问题:通常把数据集中最接近测试集的数据作为验证集
    机器学习算法竞赛实战-学习总结_第7张图片

  • 弱时序问题:最常用的方式是K折交叉验证,具体做法就是将数据集切分K分,用其中一个作为测试集,其他数据作为训练集,并重复K次,最后对得到的K个评价结果合并,比如求平均或者投票
    机器学习算法竞赛实战-学习总结_第8张图片

问题建模 小示例

House Prices - Advanced Regression Techniques
机器学习算法竞赛实战-学习总结_第9张图片

import numpy as np
import pandas as pd
from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_error #MSE
from sklearn.preprocessing import OneHotEncoder

# LightGBM(Light Gradient Boosting Machine)是一款基于决策树算法的分布式梯度提升框架
import lightgbm as lgb

# 导入数据集
train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')
train.describe()

# 对数据进行基本处理
all_data = pd.concat((train,test))
all_data = pd.get_dummies(all_data)
# 填充缺失值
all_data = all_data.fillna(all_data.mean())
# 数据切分
X_train = all_data[:train.shape[0]]
X_test = all_data[train.shape[0]:]
y = train.SalePrice

# KFold k折交叉验证
# n_splits k折交叉验证
# shuffle 是否每次生成数据集时进行洗牌
# random_state 仅当洗牌时有用,random_state数值相同时,生成的数据集一致
folds = KFold(n_splits=5, shuffle=True, random_state=2022)

# lightgbm 模型参数
params = {'num_leaves': 63,
          'min_child_samples': 50,
          'objective': 'regression',
          'learning_rate': 0.01,
          'boosting_type': 'gbdt',
          'metric': 'rmse',
          'verbose': -1,
         } 
for trn_idx, val_idx in folds.split(X_train, y):
    trn_df, trn_label = X_train.iloc[trn_idx, :], y[trn_idx]
    val_df, val_label = X_train.iloc[val_idx, :], y[val_idx]
    dtrn = lgb.Dataset(trn_df, label = trn_label)
    dval = lgb.Dataset(val_df, label = val_label) 
    
    bst = lgb.train(params,dtrn, 
                    num_boost_round=1000,
                    valid_sets=[dtrn, dval],
                    early_stopping_rounds=100, verbose_eval=100)

数据探索

数据初探

数据初探指前期的数据探索,主要是分析思路、分析方法和明确目标,加深对于数据的理解。要将数据探索的目的具象化。

  1. 了解数据集的基本情况:数据集有多大,各个字段是什么类型
  2. 重复值、缺省值、异常值:去除重复值、缺省值是否有特殊含义,如何发现异常值
  3. 特征之间是否冗余:通过特征之间的相似性来找出冗余特征
  4. 是否存在时间信息:当存在时间信息,需要进行相关性、趋势性、周期性和异常点的分析
  5. 标签分布:对于分类问题,是否存在类别分布不均衡;对于回归问题,是否存在异常值,整体分布如何,是否需要目标转换
  6. 训练集与测试集的分布:是否存在很多测试集中的特征字段在训练集中没有
  7. 单变量 / 多变量分布:熟悉特征分布情况,以及特征和标签的关系
# 统计每一列特征的唯一值和缺省值
stats = []
for col in train.columns:
    stats.append((col, train[col].nunique(), train[col].isnull().sum() * 100 / train.shape[0], train[col].value_counts(normalize=True, dropna=False).values[0] * 100, train[col].dtype))
stats_df = pd.DataFrame(stats, columns=['Feature', 'Unique_values', 'Percentage of missing values', 'Percentage of values in the biggest category', 'type'])
stats_df.sort_values('Percentage of missing values', ascending=False)[:10]

missing = train.isnull().sum()
missing = missing[missing > 0]
missing.sort_values(inplace=True)
missing.plot.bar()
plt.show()

机器学习算法竞赛实战-学习总结_第10张图片
机器学习算法竞赛实战-学习总结_第11张图片

变量分析

单变量分析

- 对于回归问题,标签值是最重要的变量,首先应该观察标签的分布情况

train['SalePrice'].describe() #查看标签数据基本统计分布

import seaborn as sns
plt.figure(figsize=(9, 8))
sns.distplot(train['SalePrice'], color='g', bins=100, hist_kws={'alpha': 0.4})
sns.distplot(np.log(train['SalePrice']), color='b', bins=100, hist_kws={'alpha': 0.4})
plt.show()

这里SalePrice为标签值,从图中可以看出呈偏离的正态分布,右倾斜类型,有些异常值在500 000 以上,需要最终去掉这些异常值。通过对数转换后,进行数据展示
机器学习算法竞赛实战-学习总结_第12张图片
机器学习算法竞赛实战-学习总结_第13张图片
- 单变量的特征变量的频率分布

df_num = train.select_dtypes(include = ['float64', 'int64'])
# df_num = df_num[df_num.columns.tolist()[1:5]]
df_num.hist(figsize=(16, 20), bins=50, xlabelsize=8, ylabelsize=8)
plt.show()

机器学习算法竞赛实战-学习总结_第14张图片

  • 相似性矩阵:分析特征变量的相关性
  • 正相关:一个变量增加导致另一个变量增加, 值为1则表示完全正相关,那么可以去掉一个多于的
  • 负相关:一个变量增加导致另一个变量减少, 值为-1则表示完全负相关

图中可以看出,OverllQual(总评)、GarageCars车库、TotalBsmtSF地下室面积、GrLivArea生活面积与房价呈正相关
机器学习算法竞赛实战-学习总结_第15张图片

  • 类别型: 对于非数值类型,可以可视化每个属性的频次
import seaborn as sns
df_not_num = train.select_dtypes(include = ['O'])
fig, axes = plt.subplots(round(len(df_not_num.columns) / 3), 3, figsize=(12, 30))

for i, ax in enumerate(fig.axes):
    if i < len(df_not_num.columns):
        ax.set_xticklabels(ax.xaxis.get_majorticklabels(), rotation=45)
        sns.countplot(x=df_not_num.columns[i], alpha=0.7, data=df_not_num, ax=ax)

fig.tight_layout()
plt.show()

机器学习算法竞赛实战-学习总结_第16张图片

多变量分析

  • 多变量分析:分析特征变量与特征变量之间的关系,有助于构建更好的特征,同时降低构建冗余特征的概率。
# 不同房屋位置的评价分布条状图
plt.style.use('seaborn-white')
type_cluster = train.groupby(['Neighborhood','OverallQual']).size()
type_cluster.unstack().plot(kind='bar',stacked=True, colormap= 'PuBu', figsize=(13,11),  grid=False)
plt.xlabel('OverallQual', fontsize=16)
# plt.show()

# 不同房屋位置,对应的房价箱型图
import seaborn as sns
var = 'Neighborhood'
data = pd.concat([train['SalePrice'], train[var]], axis=1)
f, ax = plt.subplots(figsize=(26, 12))
fig = sns.boxplot(x=var, y="SalePrice", data=data)
plt.show()

机器学习算法竞赛实战-学习总结_第17张图片
机器学习算法竞赛实战-学习总结_第18张图片

模型学习曲线分析

  • 学习曲线能够反映训练集和验证集在训练迭代中分数变化情况,帮助我们了解模型的学习效果,观测模型是否过拟合,通过判断拟合程度来确定如何改进模型。
  • 模型随着训练迭代,评估学习的指标可能最大化(分类准确率)或者最小化(回归误差),这也意味着指标分数的高低,表示学习到的信息多少。

欠拟合学习曲线

欠拟合曲线可能是一条平坦的线,或者相对较高的Loss,表明模型无法学习训练集

  • 左图表明模型的拟合能力不够
  • 右图表明需要进一步训练来降低Loss
    机器学习算法竞赛实战-学习总结_第19张图片

过拟合学习曲线

过拟合是指模型对训练集学习得很好,包括统计噪声或训练集中的随机波动。 导致模型对训练数据的专业化程度越高,对新数据的泛化能力就越差。
如果模型的容量超出了问题所需的容量,而灵活性又过多,则经常发生这种情况; 或者模型训练时间过长,也会发生这种情况。

  • 左图是过拟合曲线,验证集loss曲线减少到一个点时又开始增加,训练集的loss却在不停地减少。
  • 右图时一个正常的学习曲线,训练集和验证集都可以降低到稳定点,并且两个最终loss值差距很小,从而可以确定拟合程度良好。
    机器学习算法竞赛实战-学习总结_第20张图片

特征重要性分析

  • 通过模型训练可以得到特征重要性。
  • 对于树模型(LightGBM 和 XGBoost), 通过计算特征的信息增益或分裂次数,得到特征的重要性得分
  • 对于LR和SVM,则是使用特征系数作为特征的重要性得分。在LR中,每个特征对应一个特征系数w,w越大,那么该特征对模型预测结果的影响就越大。
  • 通过特征重要性分析也可以用于业务理解,有些奇怪的指标在模型中起着关键作用,可以帮助我们更好地理解业务。同时有些特征反常规,也可以看出是不是就是它们过拟合了。

机器学习算法竞赛实战-学习总结_第21张图片

误差分析

  • 误差分析是通过模型预测结果来发现问题,分析造成误差的可能因素,修正训练数据和模型
  • 在回归问题中,看预测结果的分布
  • 在分类问题中,开混淆矩阵等

特征工程

  • 特征工程介于数据和算法之间,是将原始数据转化为特征,进而能够从各种各样新的维度来对样本进行刻画
  • 特征可以更好的向预测模型描述潜在问题,从而提高模型对预测的准确性,高质量的特征有助于提升模型的泛化性能。
  • 在机器学习竞赛中,80%的时间和精力都用来搭建特征工程上。

特征工程通常可分为四个步骤:

  1. 数据预处理
  2. 特征变换
  3. 特征提取
  4. 特征选择

数据预处理

  • 如果原始数据质量不高,需要对数据进行预处理,从而得到标准的、干净的、连续的数据
  • 对于缺失值也需要处理,是填补均值还是中位数等

缺省值处理

  • 缺省值常常表现为 None NA NaN -1等
  • 对于类别特征:可以选择最常见的一类填充,即众数
  • 对于数值特征:可以根据情况填充平均数、中位数、
  • 对于有序数据:用前一帧或者后一帧填充
  • 模型预测填充:用模型预测结果填充缺省值

异常值处理

  • 通过散点图,发现明显偏离的异常值
  • 通过四分位数间距,极差、均差、标准差等发现异常值
  • 对异常值,直接删除、或者视为缺失值、或者用平均值修正、或者保留不处理

内存优化

因为加载数据,可能因为内存不足导致 memory error

  • python 内存回收机制
  • 数值类型优化

特征变换

特征提取

特征选择

你可能感兴趣的:(机器学习,机器学习,算法,学习)