Kaggle 入门
2016 年 7 月 21 日, 数据科学家 Abhishek Thakur 在 Linkedin 发表了一篇文章 Approaching (Almost) Any Machine Learning Problem. 该篇文章介绍他建立的一个自动的机器学习框架, 几乎可以解决任何机器学习问题, 项目很快也会发布出来. 这篇文章迅速火遍 Kaggle,他参加过 100 多个数据科学相关的竞赛, 积累了很多宝贵的经验.
以下是对其文章的简要翻译, 并且加入了一些个人理解。
-------------------
在应用机器学习模型之前,必须将数据转换为表格形式。整个过程是最耗时且最困难的过程,如下图所示。
然后将机器学习模型应用于表格数据。表格数据是在机器学习或数据挖掘中表示数据的最常用方式。我们有一个数据表,包含不同数据样本的行或 $X$ 和标签 $y$。标签可以是单列或多列,具体取决于问题的类型。我们将用 $X$ 表示数据,用 $y$ 表示标签。
标签类型
标签定义问题,可以是不同类型,例如:
- 单列,binary values(分类问题,一个样本只属于一个类,只有两个类)
- 单列,实数值(回归问题,仅预测一个值)
- 多列,binary values(分类问题,一个样本属于一个类,但有两个以上的类)
- 多列,实数值(回归问题,多值预测)
- multilabel(分类问题,一个样本可以属于几个类)
Evaluation Metrics
For any kind of machine learning problem, we must know how we are going to evaluate our results, or what the evaluation metric or objective is.
对于任何类型的机器学习问题,我们必须知道我们将如何评估我们的结果,或评估指标或目标是什么。例如,在偏斜二元分类问题的情况下,我们通常选择接收器操作特性曲线下的面积(ROC AUC或简称AUC)。在多标签或多类别分类问题的情况下,我们通常选择分类交叉熵或多类日志损失和回归问题时的均方误差。
常用的库
- 查看和操作数据:pandas:http://pandas.pydata.org/
- 适用于各种机器学习模型:scikit-learn(http://scikit-learn.org/stable/
- 最好的梯度增强(gradient boosting) 库:xgboost:https://github.com/dmlc/xgboost
- 对于神经网络:keras:http://keras.io/
- 用于绘制数据:matplotlib:http://matplotlib.org/
- 监控进度 (progress:):tqdm:https://pypi.python.org/pypi/tqdm
机器学习框架
2015 年,Abhishek Thakur 提出了一个自动机器学习框架,该框架仍在开发中,并将很快发布。对于这篇文章,相同的框架将成为基础。框架如下图所示:
在上面显示的框架中,粉色线代表最常见的路径。在我们将数据提取并缩减为表格格式之后,我们可以继续构建机器学习模型。
第一步是确定问题。这可以通过查看标签来完成。必须知道问题是二元分类,多类别或多标签分类还是回归问题。在确定问题之后,我们将数据分成两个不同的部分,即训练集和验证集,如下图所示。
“必须” 根据标签将数据分成训练和验证集。如果出现任何类型的分类问题,请使用分层 (stratified) 划分。在 python 中,你可以很容易地使用 scikit-learn 来做到这一点。
from sklearn.model_selection import StratifiedKFold
eval_size = 0.1
kf = StratifiedKFold(y, round(1/eval_size))
train_indices, valid_indices = next(iter(kf))
X_train, y_train = X[train_indices], y[train_indices]
X_valid, y_valid = X[valid_indices], y[valid_indices]
在回归任务的情况下,简单的 K-fold 分割就足够了。然而,有一些复杂的方法倾向于保持标签的分布对于训练和验证集都是相同的。
from sklearn.model_selection import KFold
eval_size = 0.1
kf = KFold(len(y), round(1/eval_size))
train_indices, valid_indices = next(iter(kf))
X_train, y_train = X[train_indices], y[train_indices]
X_valid, y_valid = X[valid_indices], y[valid_indices]
在上面的示例中选择了 eval_size
或验证集的大小为完整数据的 $10\%$,但是可以根据它们拥有的数据大小选择此值。
完成数据拆分后,请保留此数据,不要试图改变它们。必须保存应用于训练集的任何操作,然后将其应用于验证集。无论如何,验证集不应与训练集相结合。验证集和训练严格分开,以防止过拟合情况的发生。
下一步是识别数据中的不同变量。我们通常会处理三种类型的变量。即,数值变量,分类变量和其中包含文本的变量。原文以流行的泰坦尼克号数据集为例。下面我以全球恐怖主义数据库 (GTD) 为例来说明。
import pandas as pd
import numpy as np
import zipfile
import sys, os
%pylab inline
Populating the interactive namespace from numpy and matplotlib
载入并查看数据
首先,在 Global Terrorism Database网页下载数据集,下面我们之间对其进行操作:
filename = '../data/globalterrorismdb_0718dist.csv_3.zip'
zf = zipfile.ZipFile(filename)
zf.extractall('./data/') # 解压数据
zf.close()
gtd_file = os.listdir('data/')
gtd_file
['globalterrorismdb_0718dist.csv']
该文件是 .csv
格式,需要解决各种编码问题,有点不是那么友好:
%%time
df = pd.read_csv('data/globalterrorismdb_0718dist.csv', encoding='ISO-8859-1', low_memory=False) # 载入数据
Wall time: 5.96 s
载入该文件花费时间小于 $10$ 秒.
df.get_dtype_counts() # 查看数据类型分布
float64 55
int64 22
object 58
dtype: int64
我们可以将其转换为 Excel (.xlsx
格式) :
df.to_excel('data/globalterrorismdb_0718dist.xlsx') # 保存为 excel 格式
%%time
df_ex = pd.read_excel('data/globalterrorismdb_0718dist.xlsx')
Wall time: 1min 37s
载入该 excel 文件花费 1min 45s
也不是我们想要的结果. 为了加快数据的存储和载入, 我们采用 HDF5 格式来保存文件:
df.to_hdf('data/globalterrorismdb_0718dist.h5', key='gtd_df')
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\generic.py:1996: PerformanceWarning:
your performance may suffer as PyTables will pickle object types that it cannot
map directly to c-types [inferred_type->mixed,key->block2_values] [items->['approxdate', 'resolution', 'country_txt', 'region_txt', 'provstate', 'city', 'location', 'summary', 'alternative_txt', 'attacktype1_txt', 'attacktype2_txt', 'attacktype3_txt', 'targtype1_txt', 'targsubtype1_txt', 'corp1', 'target1', 'natlty1_txt', 'targtype2_txt', 'targsubtype2_txt', 'corp2', 'target2', 'natlty2_txt', 'targtype3_txt', 'targsubtype3_txt', 'corp3', 'target3', 'natlty3_txt', 'gname', 'gsubname', 'gname2', 'gsubname2', 'gname3', 'gsubname3', 'motive', 'claimmode_txt', 'claimmode2_txt', 'claimmode3_txt', 'weaptype1_txt', 'weapsubtype1_txt', 'weaptype2_txt', 'weapsubtype2_txt', 'weaptype3_txt', 'weapsubtype3_txt', 'weaptype4_txt', 'weapsubtype4_txt', 'weapdetail', 'propextent_txt', 'propcomment', 'divert', 'kidhijcountry', 'ransomnote', 'hostkidoutcome_txt', 'addnotes', 'scite1', 'scite2', 'scite3', 'dbsource', 'related']]
return pytables.to_hdf(path_or_buf, key, self, **kwargs)
%%time
se = pd.read_hdf('data/globalterrorismdb_0718dist.h5')
Wall time: 2.62 s
载入 HDF5 文件仅仅需要 $2.42$ 秒。但是,有个性能预警,为此需要对其进行处理:
查看数据类型的分布情况
# Display a summary of the data frame
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 181691 entries, 0 to 181690
Columns: 135 entries, eventid to related
dtypes: float64(55), int64(22), object(58)
memory usage: 187.1+ MB
GTD 数据集有 $181\,691$ 个样本,且其特征数目为 $135$。为了解决 PerformanceWarning
问题, 下面我们仅仅需要处理 object
数据类型数据。
txt_columns = df.select_dtypes(['object']).columns
df.loc[:,txt_columns] = df.loc[:,txt_columns].replace(np.nan, 'Unknown')
%%time
df.to_hdf('data/globalterrorismdb_0718dist.h5', key='gtd_df')
Wall time: 3.5 s
此时,便没有在报错!
%%time
gtd_df = pd.read_hdf('data/globalterrorismdb_0718dist.h5') # 载入数据
Wall time: 1.78 s
总结:相比 Excel 和 CSV,HDF5 的载入和写入都很快速和方便!下面还需要对 GTD 数据进行一些必要的操作,详细内容见:GTD 数据预处理 和 附件。