乐趣区

实战-利用机器学习实现一个多分类任务

对于机器学习而言,如果你曾经大抵理解了相干算法的原理、实践推导,你也不是大家口中刚入门的小白了。接下来你须要将本人所学的常识利用起来,最好的形式应该就是独立实现几个我的项目实战,我的项目难度入门级即可,因为重点是帮忙你理解一个我的项目的流程,比方缺失值和异样值的解决、特色降维、变量转换等等。

Kaggle 毋庸置疑是一个很好的平台,外面的泰坦尼克号、屋宇价格预测、手写数字都是十分十分经典的入门实战我的项目,如果你独立实现这三个我的项目后感觉能够晋升一下难度,就能够持续在 Playground 中寻找适宜本人的我的项目。但如果你感觉还须要几个简略的我的项目坚固一下,这里给大家安利一下 SofaSofa 比赛平台。

业余水平尽管不迭 Kaggle,但练习赛中十个简略我的项目用来练手还是不错的,品种也是十分全的,包含分类、回归预测、自然语言解决、图像识别等等,本文在练习赛【8】——地震后修建修复倡议的根底上实现。

理解数据集

首先肯定要做的是理解数据集,因为大多数据集的特色名都是以英文或者以英文简写搭配命名,只有真正理解一个特色的意义,能力更好地剖析该特色与标签变量之前存在的关系。SofaSofa 在每个较量中都会有一个表格,给出所有变量对应的解释。

能够看到这个数据集的特色并不是很多,但训练集共有 65 万个样本,咱们都晓得数据多对于建模是有益处的,因为数据越多覆盖面就越广,会进步模型的准确率,当然这可能会就义一些内存和计算工夫。标签变量 y,共有四种可能取值,阐明这是一个多元分类问题。

没有缺失值是不错的音讯,除标签变量 y 之外,共有 9 个数值型比变量和 5 个类别型变量。

可视化剖析

可视化剖析一方面是帮忙咱们找出样本中的异样点和离群点,一方面也是帮忙剖析特色与标签变量之间的关系。但下面提及了这个训练集足足有 65 万条数据,如果同时利用所有样本绘制图像,图像可能会被样本点填满,很难从中得出有用的信息。

所以这里能够抉择随机抽样的形式,每次抽取 1000-2000 个样本绘制图像进行剖析,能够多抽取几次,避免数据的必然性。这里抉择用散点图可视化数值型特色,用 area 和 age 为例。

area 特色中有一些数值偏大,但不能说其是异样点,因为一些大型建筑物占地面积 3000 不是不可能的,但 2000 个样本,仅有不到 20 个样本的占地面积大于 1500,所以能够将其视为离群点,离群点在建模时是会影响拟合的,所以抉择舍去。

对于建筑物的年限 age 而言,可视化后会发现有很多样本在 age 这一特色的数值都为 999,两头却有很大的空缺,比方没有一个样本点的 age 位于 500-900 之间,所以这类样本被视为异样点,再联合离群点剖析,能够抉择一个阈值进行过滤。其余数值型特色能够做同样的操作,这里不再过多介绍。

这个数据集还有个奇怪的中央就是有很多样本地震后的楼层、高度都要高于地震产生之前,这显然是不可能产生的,可能是在数据填充时呈现了谬误,利用布尔索引过滤掉此类特色。

# 布尔索引
data1 = data1[data1['floors_before']>=data1['floors_after']]
data1 = data1[data1['height_before']>=data1['height_after']]
data1.reset_index(drop = True)# 重置索引 

而后利用相关矩阵对所有的数值型特色进行一下相关性剖析,通过观察相关性舍去一些没有必要的特色达到降维的目标。

这里 ”district_id” 和 ”area_id” 是齐全相干的,能够轻易留下一个,或者都删去,因为相关性的确小的可怜;能够看到这里减少了两个新的变量 ”floors_diff” 和 ”height_diff”,就是地震前后的建筑物层数和高度的差值,能够察看一下标签变量 ”y” 和这六个属性的相关性,与地震前的信息相关性极低,也就是说,标签变量很少关注一个建筑物震前的信息,而是着重关注通过地震之后建筑物发生变化的信息。

类别型变量转换

类别型变量不不便前期建模时传入数据,所以咱们须要提前将类别型变量转换为算法能辨认的数值型,变量转换形式有很多种,比方有序变量、哑变量、虚构变量。

对于 ”position” 这一特色,能够进行有序变量,因为仅有一个特色,所以没有调用 sklearn 中的 API,而是间接利用自定义函数联合 apply 函数进行转换。

def pos(e):
    if e == "Not attached":
        return 0
    elif e == "Attached-1 side":
        return 1
    elif e=="Attached-2 side":
        return 2
    else:
        return 3
data1['position'] = data1['position'].apply(pos)

而剩下的几个类别型变量皆为无序变量,能够将其转化为哑变量,再进一步转化为虚构变量。相比于 sklearn 中的 API,pandas 自带的办法看起来更加简洁。

# 哑变量编码
dummy_df = pd.get_dummies(data1.iloc[:,6:10])


如果你感觉这种形式简略,并没有懂哑变量编码的意思和过程,能够试着理解一下上面这个函数,同样是实现哑变量编码。

def dummy_code(var):
    #获取特色中所有变量
    var_unique = var.unique()
    #新建一个 DataFrame
    dummy = pd.DataFrame()
    #最初一个不设置虚构变量,可用之前所有变量示意
    for val in var_unique:
        #利用一个布尔型数组存储编码后的变量
        bo = (val==var)
        #命名, 并将 True 转为 1,False 转为 0
        dummy[var.name+"_"+str(val)] = bo.astype(int)
    return dummy

将哑变量进一步转化为虚构变量合并至数据集中,代码如下:

# 每个特色删去一个类别,失去虚构变量
dummy_df1 = dummy_df.drop(['land_condition_S','foundation_type_O','roof_type_H','ground_floor_type_T'],axis = 1)
#删去原特色,合并虚构变量
data1 = data1.drop(['land_condition','foundation_type','roof_type','ground_floor_type'],axis = 1)
data1 = pd.concat([data1,dummy_df1],axis = 1)

可能很多搭档不太理解为什么虚构变量能够这样转换,虚构变量与哑变量相比,缩小了特色的维度,实质是相似的,以 ”roof_type” 这一特色举例,通过哑变量转换造成三个新特色:[“roof_type_H”,”roof_type_L”,”roof_type_R”],如果在 ”roof_type” 为 ”R” 的样本,在哑变量的表达方式应该是 [0,0,1],然而如果从哑变量中删去 ”roof_type_R” 这一特色,表达方式就能够变成 [0,0],通过唯一性就能够利用前两个特色推出第三个特色的值,所以缩小了不必要的特色以实现降维。

当然这里还能够做一下方差过滤、相关性剖析等操作进一步实现特色降维,各位在实操的时候能够本人试一下。

建模工作

后面说过了这个是一个多元分类我的项目,所以在建模的时候能够有两种抉择,一是利用多元分类器,比方随机森林、奢侈贝叶斯,二就是利用二元分类器实现多元分类工作,比方逻辑回归、SVM。

前面文章会写一篇对于二元分类器实现多元分类的文章,本文就集中于多元分类器的实现,次要用到的两个分类器是随机森林和 LGBM。

个别建模的流程大抵是在训练集上切分训练集和测试集,有的数据须要标准化解决,而后训练模型,利用测试集进行预测,获取模型的准确率或其余掂量模型好坏的指标,上面以随机森林分类器模仿一下该流程。

首先进行数据切分,能够抉择管制训练集和测试集的比例:

from sklearn.model_selection import train_test_split
features = data2.iloc[:,0:-1].values
label = data2.iloc[:,-1].values
X_train,X_test,y_train,y_test = train_test_split(features,label,test_size = 0.3)

这里介绍一下能够缩小代码量的管道流,如果失常来说,咱们可能要别离实例化标准化和 PCA 的 API,而后再传入训练集和测试集,这些操作能够利用管道流封装到一起,让代码看起来更加简洁。

from sklearn.ensemble import RandomForestClassifier
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline,Pipeline
#管道流简化工作流
pipe_rf = make_pipeline(StandardScaler(),
                        PCA(n_components=10),
                        RandomForestClassifier())
pipe_rf.fit(X_train,y_train)
#失去每个类别的概率
pred_y_rf = pipe_rf.predict_prob(X_test)

利用 predict_prob 计算出标签变量失去每个类别的概率,而后利用索引排序能够失去概率最大的两个类别:

pred_df = pd.DataFrame(data=pred_y_rf.argsort()[:, -2:][:, ::-1], columns=['y1', 'y2'])
pred_df.to_csv("eq_submission.csv",index=False)

因为数据量比拟大,调参比拟费时,在没有调参的状况下,随机森林模型的概率大抵为 68%,LGBM 模型的准确率大抵为 70%,准确率并不是太好,除准确率外还能够通过查全率、查准率、F1-score 掂量一下模型的好坏,上文大体上提供了一个建模前及建模的思路而已,搭档们能够利用本人的思路,再加上调参应该会失去一个不错的模型。

这幅图是对于特色重要度的饼图,能够依据饼图再调节特色,其中 area 占比是比最大的,而后 ”distict_id” 占比也是不小的,然而上文关系矩阵中与标签变量的相关性又很小,所以剖析要互相联合、更加全面一些才好。

说在最初

下面的一系列操作都是为了最初的模型,但如果作为一个比赛,你须要提交一份文件,而这份文件从何来?比赛会给出一个不含标签变量的测试集!留神与测试集中宰割出的测试集不同。咱们同样须要对测试集做一些数据处理,操作和训练集相似,而后将训练出的模型利用在测试集上,会得出最初的后果保留成一个新的 csv 文件,这就是你最初须要提交的文件啦。

公众号【奶糖猫】后盾回复 ” 地震 ” 可获取源码供参考

退出移动版