《机器学习算法竞赛实战》学习笔记(一)框架梳理

竞赛流程P9

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

竞赛类型P11

人工智能领域大致可以分为三个主要方向:

  1. 计算机视觉(CV)

  1. 自然语言处理(NLP)

  1. 数据挖掘(DM)

赛场P12:Kaggle ,天池,DF,DC,Kesci,JDATA等

第2 章 问题建模

2.1赛题理解

2.1.1业务背景

2.1.2数据理解:数据基础层、数据描述层

2.1.3评价指标

  1. 分类指标P16:包括错误率、精度、精确度(查准率precision)、召回率(查全率recall)、F1-score、ROC曲线(P17)、AUC和对数损失(logloss)

  1. 回归指标:平均绝对误差、圴方误差、圴方根误差、平均绝百分比误差

2.2样本选择

2.2.1提供的数据对最终预测结果造成很大的影响的因素有:

  1. 数据集过大

  1. 数据噪声

  1. 数据冗余

  1. 正负样本分布不平衡

2.2.2准确方法(解决方法)

对数据集过大:简单随机抽样、分层采样

对正负样本分布不平衡P24:评分加权处理、欠采样、过采样

欠采样:就是从数量较多 一类样本中随机选择一部分并剔除。常用方法有:随机欠采样和TomekLinks

过采样:主要是对样本较少的类别进行重新组合构造新样本。常用方法有:随机过采样和SMOTE算法

2.3线下评估策略 构建合适的线下验证集

2.3.1强时序性问题P25

2.3.2弱时序性问题

K折交叉验证(K-folf Cross Validation)

例 k=5

from sklearn.model_selection import KFold
NFOLDS=5
folds=KFold(n_splits=NFOLDS,shuffle=True,random_state=2021)
for trn_idx,val_idx in folds.split(X_train,y_train):
    train_df,train_label=X_train.iloc[trn_idx,:],y_train[trn_idx]
    valid_df,valid_label=X_train.iloc[val_idx,:],y_train[val_idx]

代码是从书上文字识别过来的,编辑时难免会有错误。

2.4实战案例

P28书上一例子 开始一些基本代码

#首先,导人基本的模块:
import numpy as np
import pandas as pd
from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import OneHotEncoder
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(al1_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

第3 章 数据探索

P30数据探索是一种总结、可视化和熟悉数据集中重要特征的方法。

数据探索分为三个部分:

  1. 初探(赛前):如缺失值、异常值、数据冗余

  1. 赛中数据探索:从单变量、多变量和变量分布进行分析

  1. 模型的分析:特征重要性分析、结果误差分析

3.1数据初探

3.1.2数据探索分析:单变量可视化分析、多变量可视化分析、降维分析

数据探索阶段必须要明确的7件事:

  1. 数据集基本情况:数据多大、每个字段类型

  1. 重复值、缺失值、异常值

  1. 特征之间是否冗余

  1. 是否存在时间信息 存在时相关性、趋势性、周期性的异常点的分析

  1. 标签分布 是否存在不均衡

  1. 训练集与测试集分布

  1. 单变量/多变量分布

了解数据的基本信息,下边操作为展现一些强大功能:通过一段代码展示nunique和缺失值情况。P32

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]

结果如下图

有些变量和缺失值很多,缺失比例到95%以上可以考虑将其删除。

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

3.2变量分析

3.2.1单变量分析 标签是重要的变量

train['SalePrice'].describe()

分布情况

plt.figure(figsize=(9,8))

sns.distplot(train['SalePrice'],color='g',bins=100,hist_kws={'alpha':0.4})

如有偏态,对'SalePrice'进行数据转换后

plt.figure(figsize=(9,8))

sns.distplot(np.log(train['SalePrice']),color='g',bins=100,hist_kws={'alpha':0.4})

下面为连续变量的分布可视化图的生成代码

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)

生成相似性矩阵图

corrmat=train.corr()
f,ax=plt.subplots(figsize=(20,9))
sns.haetmap(corrmat,vmax=0.8,square=True)

3.2.2多变量分析P38

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()

3.3模型分析

3.3.1学习曲线P40

学习曲线是机器学习中被广泛使用的效果评估工具。帮助我们快速了解模型的学习效果。可以通过学习曲线来观察模型是否过拟合。

欠拟合学习曲线

过拟合学习曲线P41

3.3.2特征重要性分析

3.3.3误差分析

第4 章 特征工程(Feature Engineering)

“机器学习本质还是特征工程,数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已”。吴恩达老师说。P44

特征工程主要分为四个部分

  1. 数据预处理

  1. 特征变换

  1. 特征提取

  1. 特征选择

4.1数据预处理

4.1.1缺失值处理

面对数据缺失问题,除了XGBoost和LightGBM等算法在训练时可以直接处理缺失值以外,其他很多算法(如LR、DNN、CNN、RNN等)并不能对缺失值进行直接处理。

区分缺失值

处理方法:

数据缺失:

  1. 类别特征缺失:众数填充、通常填充一个新类别

  1. 数据特征缺失:均值填充、对异常值敏感的选中位数填充

对有序数据(比如时间序列):填充相邻值、next或previous

模型预测填充:

4.1.2异常值处理

寻找异常值:

  1. 可视化分析方法:散点图 四分位数间距箱图

  1. 简单的统计发现异常值:四分位数间距、极差、均差、标准差

处理异常值

  1. 删除含有异常值的记录

  1. 视为缺失值

  1. 平均值(中位数)修正

  1. 不处理

4.1.3优化内存

介绍了Python的内存回收机制P47

数值类型优化

内存回收机制:Python 中gc模块主要运用“引用计数”来跟踪和回收垃圾。

在我们删除一些变量时使用gc.collect() 来释放内存。

数值类型优化:如float类型有float16,float32和float64,数字部分表明了这种类型使用多少比特来表示数据。

我们可以用np.iinfo类来确认每一个int 型子类型的最小值和最大值,代码如下:

import numpy as np
np.iinfo(in.int8).min
np.iinfo(in.int8).max
#然后,我们可以通过选择某列特征的最小值和最大值来判断所属的子类型,代码如下:
c_min=df[col].min()
c_max=df[col].max()
if c_min>np.iinfo(np.int8).min and c_max<np.iinfo(np.int8).max:
    df[col]=df[col].astype(np.int8)

而对于数值型的变量,常常由于存在浮点数使得内存占用过多,可以考虑先将其最小值和最大值归一化,然后乘以100,1000等之后取整,这样不仅可以保留同一变量的大小关系,还极大地减少了内存占用。P48

4.2特征变换

4.2.1连续变量无量纲化

常见的无量纲化方法:

  1. 标准化:前提是特征值服从正态分布

  1. 区间缩放法:放缩到某个特定的范围例[0,1]

单特征转换是构建一些模型(如线性回归、KNN,神经网络)的关键,对决策树相关模型没有影响,这也是决策树及其所有衍生算法 随机森林、梯度提升) 日益流行的原因之一。还有一些纯粹的工程原因,即在进行回归预测时,对目标取对数处理,不仅可以缩小数据范围.而且压缩变量尺度使数据更平稳。这种转换方式仅是一个特殊情况,通常由使数据集适应算法要求的愿望驱动。然而,数据要求不仅是通过参数化方法施加的。如果特征没有被规范化,例如当一个特征的分布位于0附近且范围不超过(-1,1),而另一个特征的分布范围在数十万数量级时,会导致分布位于0附近的特征变得完全无用。

举一个简单的例子:假设任务是根据房间数量和到市中心的距离这两个变量来预测公寓的成本。公寓房间数量一般很少超过 5间,而到市中心的距离很容易达到几千米。此刻,使用线性回归或者KNN这类模型是不可以的,需要对这两个变量进行归一化处理。

4.2.2 连续变量数据变换

log 变换

进行 log 变换可以将倾斜数据变得接近正态分布,这是因为大多数机器学习模型不能很好地处理非正态分布的数据,比如右倾数据。可以应用log(x+l)变换来修正倾斜,其中加1的目的是防止数据等于0,同时保证x都是正的。取对数不会改变数据的性质和相关关系,但是压缩了变量的尺度,不仅数据更加平稳,还削弱了模型的共线性、异方差性等。

扩展学习:cbox-cox 变换一自动寻找最佳正态分布变换函数的方法。此方法在竞赛中并不常用,有兴趣的读者可以了解一下。

连续变量离散化P50

无监督的离散化:等频、等距

有监督的离散化

4.2.3类别特征转换

自然编码:一列有意义的类别特征(顺序关系)比如年龄段、学历等

下面将给出两种自然数编码的常用方式:

#调用 sklearn 中的函数:
from sklearn import preprocessing
for f in columns:
    le = preprocessing.LabelEncoder()
    le.fit(data[f])
#自定义实现 (速度快):
for f in columns:
    data[f] = data[fl.fillna(-999)
    data[f] = data[f].map(dict(zip(data[f].unique(), range(0, data[f].nunique())))

独热编码。当类别特征没有意义 (即没有顺序关系) 时,需要使用独热编码。例如,红色>蓝色>绿色不代表任何东西,进行独热编码后,每个特征的取值对应一维特征,最后得到的是一个样本数 x 类别数大小的 0~1 矩阵。可以直接调用 sklean 中的API。

4.3特征提取P52(看的不很懂)

4.3.1类别相关的统计特征

类别特征又可以称为离散特征,除了每个类别属性的特定含义外,还可以构造连续型的统计特征,以挖掘更多有价值的信息,比如构造目标编码、count、nunique 和 ratio 等特征另外,也可以通过类别特征间的交叉组合构造更加细粒度的特征。

目标编码:目标编码可以理解为用目标变量(标签)的统计量对类别特征进行编码,即根据目标变量进行有监督的特征构造。如果是分类问题,可以统计正样本个数、负样本个数或者正负样本的比例,如果是回归问题,则可以统计目标均值、中位数和最值。目标编码方式可以很好地替代类别特征,或者作为新特征。

目标编码方法对于基数较低的类别特征通常很有效,但对于基数较高的类别特征、可能会有过拟合的风险。因为会存在一些类别出现频次非常低,统计出来的结果不具有代表性。一危我们会加人平滑性来降低过拟合风险。在处置安当的情况下,无论是线性模剧,还是非线性模型,目标编码都是最佳的编码方式和特征构造方式,为了帮助大家更好地理解。下面给出五折交叉统计的代码实现:

folds  KFold(n_splits=5, shufflewTrue, random_state=2020)
for col in columns:
    colname  col+"_kfold"
    for fold_, (trn_idx, val_idx) in ermerate(folds,split(train, train)):
        tmp=train.iloc[trn_idx]
        order_label=tmp.growpby([col])["labe1"].mean()
        train[colname]=traln[col].map(order_label)
    order_label=train.groupby([col])["labe1"].mean()
    test[colname]=test[col].map(order_label)

类别特征之间交又组合

交叉组合能够描述更细粒度的内容。对类别特征进行交叉组合在竞赛中是一项非常重要工作,这样可以进行很好的非线性特征拟合。如图4.5 所示,用户年和用户性别可以组合成“年龄_性别”这样的新特征。一般我们可以对两个类别或三个类别特征进行组合,也称作二阶合或三阶组合。简单来说,就是对两个类别特征进行苗卡儿积的操作,产生新的类别特征,实际数据中,可能会有很多类别特征。

4.3.2数值相关特征统计P54

数值特征之间的交叉组合

类别特征和数值特征之间的交叉组合

按行统计相关特征

4.3.3时间特征

4.3.4多值特征(例调查问题中爱好,至少填3个,3个填的也是很多种)

在实际竞赛中,可能会遇到某一列特征中每行都包含多个属性的情况,这就是多值持征,例如2018 腾讯广告算法大赛中的兴 (inierest)类目,其中包含5个兴趣特征组,每个兴要特征组都包含若干个兴趣ID。对于多值特征,通过可以进行稀疏化或者向量化的处理,这种操作一般出现在自然语言处理中,比如文本分词后使用 TF-IDF,LDA、NMF 等方式进行处理,这里则可以将多值特征看作文本分词后的结果,然后做相同的处理。

如图4.6 所示,对多值特征最基本的处理办法是完全展开,即把这列特征所包含的n个属姓展开成n淮裕疏矩阵。使用sklcam 中的CountVectorizer 函数,可以方便地将多值特征展开只考虑每个属性在这个特征的出现频次。

还有一种情况,比如在2020 腾讯广告算法大赛中,需要根据用户的历史点击行为预测用户的属性标签。这时候用户的点击序列尤为重要,当我们构造好用户对应的历史点击序列后,除了使用上述的 TF-IDF 等方法外,还可以提取点击序列中商品或广告的人表示,比如用Word2Vec、DecpWalk 等方法获取embedding向量表示。因为要提取用户单个特征,所以可以对序列中的嵌人向量进行聚合统计,这种方法本质上是假设用户点击过的商品或广告同等重要,是一种比较粗糙的处理方式。我们可以引人时间衰减因素,或者使用序列模型,如RMN、LSTN、GRU,套用NLP的方法进行求解。

4.4特征选择P56

特征选择的方法主要有先验的特征关联分析以及后验的特征重要性分析

4.4.1特征关联性分析

特征关联性分析是使用统计量来为特征之间的相关性进行评分。特征按照分数进行排序要么保留,要么从数据集中删除。关联性分析方法通常是针对单变量的,并且独立考虑特征或者因变量。常见的特征关联性分析方法有皮尔逊相关系数、卡方检验、互信息法和信息增益等这些方法的速度非常快,用起来也比较方便,不过忽略了特征之间的关系,以及特征和模型之间的关系。

皮尔逊相关系数 (Pearson correlation coeficient)。这种方法不仅可以衡量变量之间的线性相关性,解决共线变量问题,还可以衡量特征与标签的相关性。共线变量是指变量之间存在高度相关关系,这会降低模型的学习可用性、可解释性以及测试集的泛化性能很明显,这三个特性都是我们想要增加的,所以删除共线变量是一个有价值的步骤。我们将为删除共线变量建立一个基本的阙值 (根据想要保留的特征数量来定),然后从高于该闯值的任何一对变量中删除一个。

下面的代码用于解决特征与标签不具有相关性的问题,根据皮尔逊相关系数的计算提取top300的相似特征:

def feature select pearson(train,features):
    featureSelect = features[:]
    # 进行皮尔逊相关性计算
    corr =[]
    for feat in featureSelect:
        corr.append(abs(train[[feat,'target']].fillna(0).corr().values[0][1]))


    se = pd.Series(corr,index=featureSelect).sort_values(ascending=False)
    feature_select = se[:300].index.tolist()
    # 返回特征选择后的训练集
    return train[feature_select]

P57

4.4.2特征重要分析

在实际竞赛中,经常用到的一种特征选择方法是基于树模型评估特征的重要性分数、特的重要性分数越高,说明特征在模型中被用来构建决策树的次数这多。这里我们以 XGBoost例来介树模型评估特狂重要性的三种计算方法 (weight。gain和cover)。(LightGBM也可以返回特征重要性。)

weight计算方式,该方法比较简单,计算特征在所有树中被选为分裂特征的次数,并将此作为评估特征重要性的依据,代码示例如下:

params ={'max_depth': 10,'subsanple':1,'verbose_eval": True,'seed': 12,'objective':"binany:logistic"}
xgtrain = xgb.DMatrix(x,label=y)
bst=xgb.train(params, xgtrain, num_boost_round=10)
importance=bst.get_score(fmap='',importance_typeu='weight')

gain计算方式。gain 表示平均增益。在进行特征重要性评估时,使用 gain 表示特征在所有树中作为分裂节点的信息增益之和再除以该特征出现的频次。代码示例如下:

importance=bst.get_score(fmap='',importance_typeu='gain')

cover计算方式。cover 较复杂些,其具体含义是特征对每棵树的夏篮率。即特征被分到该节点的样本的二阶导数之和,而特征度量的标准就是平均覆盖率值。代码示例如下:

importance=bst.get_score(fmap='',importance_typeu='cover')

使用技巧

虽然特征重要注可以帮助我们快速分析特狂在模型训练过程中的重要性,但不能将其当作绝对的参考依据。一般而言,只要持征不会导致过拟合,我们就可以选择重委性高的特征进行分析和扩展,对于重要注低的特征,可以考虑将之从特征集中移险,然后现察线下效果,再做进一步判断。

4.4.3封装方法

两种常用的封装方法:

启发式方法

递归消除特征法:逆归消除特征法使用一个基模型来进行多轮训练,每轮训练都会先消除若干权值系数的特征,再基于新特征集进行下一轮训练。可以使用 feature_selection 库的RFE 类来进行特征选择。代码示例如下:

from sklearn,feature_selection import RFE
from sklearn.linear_model import LogisticRegression
#递归消除特征法。返回特征选择后的数据
#参数estimator为基模型
#参数n_features_to_select 为选择的特征个数
RFE(estimator=Log1sticRegression(),n_features_to_select=2),fit_transform(data, target)

另外,还有一些不常见的特征选择方法,比如 Kaggle 上非常经典的 null importance特征选择方式

null imponance 的思想其实很简单,就是将构建好的特征和正确的标签限入树模型得到特征重要性分数,再将特征和打乱后的标签喂入树模型得到一个特征重要性分数,然后对比两个分数,如果前者没有超过后者,那么这个特征就是一个无用的特征。

4.5实战案例P60

4.5.1数据预处理

本阶段的主要工作是数据清洗,对缺失值和异常值进行及时处理。执行下面的代码进行筹本的数据读取,副除缺失值比例大于 50%的特征列,并对 object 型的缺失特征进行填充:

test=pd.read_csv("../input/test.csv”)
train=pd.resd_csv("../input/train.csv”)
ntrain=train.shape[0]
ntest=test.shape[0]

data=pd.concat([train,test],axis=0, sort=False)
#删除缺失值比例大于50%的特征列
missing_cols=[c for c in data if data[c].isna().mean()*100 > 50]
data=data.drop(missing_cols,axis=1)

#对object 型的缺失特征进行填充
object_df=data.select_dtypes(include=["object"])
numerical_df = data.select_dtypes(exclude=["object”])

object.df=object_df.fillna("unknow")

#接下来,对数值型特征用中位数进行填充:
missing_cols = [c foe c in numerical_df 1f numerical_df[c].isna().sum() > 0)]
for c in missing_cols:
    numerical_df[c]=numerical_df[c].fillna(numerical_df[c].median())

下面为特征删除代码:

object_df=object_df.drop(['Heating','RoofMatl','Cordition2','Street','Utilities'],axis=1)

4.5.2特征提取

基本持征构造

房屋建筑年龄也是影响房屋价格的一个因素,在构建这个特征时。发现存在销售日期(YrSold)小于建造日期(Yearbuilt)的数据,针对这种异常情况需要进行测整。具体地将异常数据的销售日期改为数据集中销售日期的最大年份 (2009)。下面是构建特征的具体代码:

numerical_df.loc[numerical_df['YrSold'] < numerical_df['YearBuilt'], 'yrSold'] = 2009
numerical_df['Age_House']. (numerical_df['YrSold']-numerical_df['Yearbuilt'])

接下来构造业务相关特征,比如对原始特征中的浴池(BsmtFullBath)和半池(BstHalfBath)进行求和,对全浴 (Fu11Bath) 和浴 (HalfBath)求和对一面积(1stFlrSF) 和二楼面积(2ndFlrSF) 以及地下室面积求和,来表示房壁的结构信息。代码如下:

numerical_df['TotalBsmtBath'] =numerical_df['BsmtFullBsth'] + numerical_df['BsmtHalfBath”]·0.5
numerical_df["TotalBath"] = numerical_df['FullBath'] + numerical_df['HalfBath']*0.5
numerical_df['TotalSA'] = numerical_df['TotalBsmtSF'] + numerical_df['1stFIrSF'] + numerical_df["2ndFlrSF"]

特征编码

4.5.3 特征选择

这部分将使用相关性评估的方式进行特征选择,这种方式是相关性分析的一种,可以过掉相似性大于一定网值的特征,减少特征冗余。下面创建了一个相关性评估的辅助函数:

def correlation(data,threshold):#threshold为传入的阈值
    col_corr=set()
    corr_matrix=data.corr()
    for i in range(len(corr matrix.coluens)):
        for j in range(i):
            if abs(corr_matrix,iloc[i,j])>threshold: # 相似性分数与阈值对比
                colname=corr_matrix.columns[i]#获取列名
                col_corr.add(colname)
return col_corr


all_cols = [c for c in data.columns if c not in ['SalePrice']]
corr_features = correlation(data[all_cols],0.9)

对于阙值的确定一般很难量化,可以从总特征量和整体相似分数这两个角度进行考虑,比如我们的机器不允许使用太多特征,就可以以此为依据确定特征保留量,这也是个相对灵活的值。可以保留不同阙值下的特征集进行训练,辅助提升模型融合结果。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值