数据准备技巧及其对机器学习的重要性

2020 年 9 月 03 日

数据准备技巧及其对机器学习的重要性

“数据只是数千个故事的整合,讲述其中一些故事可以为数据赋予意义。”——Chip & Dan Heath


本文最初发布于 Medium,经原作者授权由 InfoQ 中文站翻译并分享。



数据是什么?


数据是指在某领域中能够描述你所想解决问题的例子,而数据的选择则取决于你想满足的任务目标。下面是一些提供各种开源数据常用的网站,方便各位建立属于自己的机器学习应用,向成功更进一步。


Kaggle - 井井有条的平台,学习者的乐园,在其内核的帮助下,甚至可以不用下载直接在平台上处理数据。


UCI机器学习数据库- 包含大量种类繁多的数据集,为机器学习社区服务。


Data.gov- 提供各国的公开数据下载,从政府预算到学校成绩应有尽有。


CMU图书馆- 由卡内基梅隆大学(Carnegie Mellon University)提供的各个领域高质量数据集。


谷歌数据集搜索- 无论是出版者网站,数字图书馆,或者是数据集作者的网页,你都可以通过它搜索到。


数据收集的下一步是数据转换,让数据更符合不同机器学习算法的的要求。如何准备项目中最独特的建模数据,一直都是机器学习项目中的难点。


数据准备是指如何将原始数据转化为更适合建模形式的过程,而“数据的质量比复杂的算法更重要”。为了让原始数据所包含的信息更多也更明确,我们需要有一套可以解决任何建模问题的数据准备工作。


在本文中,作者将以汽车价格预测数据集为例,带你一步步走进数据准备。


数据准备的内容包括:


  • 数据清洗

  • 特征工程

  • 数据转换

  • 特征提取


数据清洗


这一步应该算是最难的一步,大多数真实生活中的数据都或多或少有因为观察时的误会而导致的错误,这时为了拿到干净的可靠数据,就需要利用专业知识来辨别数据属性中的异常值。数据清理过程不是件容易事,你需要花费大量时间来提升数据质量。不过值得庆幸的是,数据清理方法也有很多,例如:


  1. 检测空数值或缺失行

  2. 搜索重复行并将其移除

  3. 基于统计技术,利用专业知识发现离群点

  4. 确定列的分布情况,并剔除没有方差的列


以下是用于清洗“汽车价格预估”数据集的代码片段:


# 读取数据df_car = pd.read_csv('CarPrice_Assignment.csv')df_car.head(10)  # 显示前十行数据df_car.drop(['car_ID'], axis=1, inplace=True)  # 重复信息,丢弃car_ID列 # 检查列是否包含空数值df_car.isnull().sum()# 丢弃重复行df_car.drop_duplicates(inplace=True)# 根据其类型分配列名cat_variable = []num_variable = []for col in df_car.columns:    if df_car[col].dtype == 'object':        cat_variable.append(col)    elif df_car[col].dtype == 'float' or df_car[col].dtype == 'int64':        num_variable.append(col)        # CarName列中类别数量 df_car['CarName'].value_counts()# 检测数字变量中的离群点df_car[num_variable].describe()
复制代码


特征工程


特征工程指的是从现有数据中创建新的输入变量的过程。一般来说,数据清洗可以算是一个减法的过程,而特征工程则是一个加法的过程。


新功能的工程化是高度针对数据和数据类型的,因为其有助于隔离和突出关键信息,从而帮助算法“聚焦”于重要的东西,特征工程是数据科学家们为提高模型性能而做的最有价值的工作之一。


一些常用的特征工程技巧如下:


  1. 分箱(binning)

  2. 取对数(Log Transformation)

  3. 特征分割

  4. 组合稀疏类


特征工程与数据转换非常相似,但因为不同问题对相关领域知识的要求,特征工程被单独列为数据准备的技巧之一。


以“汽车价格预估”数据集为例,特征工程步骤如下:


# 分离汽车及其公司名称,从而进行特征分割# 检查Company_name列是否有重复数据 df_car['Company_name'] = df_car['CarName'].apply(lambda x:x.split(' ')[0])df_car['Company_name'].value_counts()df_car.drop(labels='CarName',axis=1,inplace=True)# 创建字典合并相似公司名称company_name_map_dict = {    'maxda' : 'mazda',    'vw' : 'volkswagen',    'toyouta' : 'toyota',    'Nissan' : 'nissan',    'vokswagen' : 'volkswagen',    'porcshce' : 'porsche'}df_car['Company_name'] = df_car['Company_name'].replace(company_name_map_dict)df_car['Company_name'].value_counts()# 绘图显示price与Company_name的关系plt.figure(figsize=(20, 8))sns.boxplot(x = 'Company_name', y = 'price', data = df_car)# 绘图显示数字列是否有线性相关plt.figure(figsize=(30, 25))for i, col in enumerate(num_variable):    plt.subplot(5,3,i+1)    sns.regplot(col, 'price', df_car, fit_reg=False)
复制代码


数据转换


收集到的数据很少可以直接用于预测。这些数据可能格式不对或者需要先进行转换才能继续使用,而数据转换可以改变数据变量的分布类型。


数据中的属性以数字或类别值的形式存储信息,但机器学习算法的局限性在于,它只能处理数字值,而无法处理任何字符或字符串。因此我们必须先通过创建虚拟变量(dummy variables)或执行独热编码(one-hot encoding)将类别变量编码为整数。


在将类别属性转换为数字表示后,我们需要确定所有特征的数字范围,并将其调整到一个统一的比例。这是因为计算机在 0-1 的范围内分辨率要远大于其他更广泛的数据类型范围。数据的缩放可以通过归一化(将特征缩放至 0-1 的范围内)或者标准化(将特征缩放至其对应的高斯分布)实现。


在“汽车”数据集上进行数据转换的步骤如下:


    # 将类别列转换为虚拟变量,方便后续ML模型处理  df_car['fueltype'] = df_car['fueltype'].map({'gas':0, 'diesel':1})  df_car['aspiration'] = df_car['aspiration'].map({'std':0, 'turbo':1})  df_car['doornumber'] = df_car['doornumber'].map({'four':0, 'two':1})  df_car['enginelocation'] = df_car['enginelocation'].map({'front':0, 'rear':1})    # 为拥有超过两种类别的列创建虚拟变量  for col in ['carbody', 'drivewheel', 'enginetype', 'cylindernumber', 'fuelsystem', 'Company_name']:      df_car = pd.get_dummies(df_car, columns=[col], drop_first=True)       # 显示将所有类型数据列转换为0-1后的新数据   df_car.head()    # 将数据集分为训练与测试两部分   df_train, df_test = train_test_split(df_car, test_size = 0.15, random_state=44)  # 将所有数字类别列转化为0或1   from sklearn.preprocessing import MinMaxScaler  scaler = MinMaxScaler()  df_train[list(df_train.columns)] = scaler.fit_transform(df_train)  # 取price列为因变量‘y’,其余数据为自变量‘x’   y_train = df_train.pop('price')  X_train = df_train
复制代码


注意在这里我们将数据分为两部分,一是用于算法训练,二是用于评估。在后续的分析中,我们会专注于训练数据。


特征提取


特征提取(Feature Extraction)是指从现有特征列表中选择子集,或通过各种降低维度算法来降低数据维度的过程。数据集维度则是该数据集的输入特征数量。


但是数据的维度越多(即输入的变量越多),数据集就越有可能代表该空间的某个非常稀疏且不具代表性的采样,这被称作是维度的诅咒


主要有两种方式:


* 特征选择:用于对数据集中现有特征的重要性进行排序,并剔除不重要的特征。* 特征提取:用于将数据投影到一个较低维度的空间,但依然保留原始数据最重要的特征
复制代码


特征提取/选取技巧的好处有:


  1. 降低欠拟合(underfitting)或过拟合(overfitting)

  2. 减少训练时间

  3. 提高准确率

  4. 改善数据可视化


特征提取示例:


def corr_heatmap(df, v):      correlations = df[v].corr()      # Create color map ranging between two colors      cmap = sns.diverging_palette(220, 10, as_cmap=True)      fig, ax = plt.subplots(figsize=(20,20))      sns.heatmap(correlations, cmap=cmap, vmax=1.0, center=0, fmt='.2f',                  square=True, linewidths=.5, annot=True, cbar_kws={"shrink": .75})      plt.show()        # 可视化相关矩阵以排除因变量   corr_heatmap(df_car, num_variable[:-1])    # 丢弃高度相关的属性  df_car = df_car.drop(['citympg', 'curbweight', 'wheelbase', 'enginesize', 'carwidth'], axis=1)  # Importing RFE and LinearRegression  from sklearn.feature_selection import RFE  from sklearn.linear_model import LinearRegression    # Running RFE with the output number of the variable equal to 10  lm = LinearRegression()  lm.fit(X_train, y_train)               # Model_1  rfe = RFE(lm, 10)                      # running RFE  rfe = rfe.fit(X_train, y_train)  # Displaying the list of column with there rfe rank  list(zip(X_train.columns,rfe.support_,rfe.ranking_))  # taking a subset of column, that rfe has suggested important  col = X_train.columns[rfe.support_]    # Creating X_test dataframe with RFE selected variables  X_rfe = X_train[col]  lm.fit(X_rfe, y_train)              # Model_2
复制代码


完成对训练数据集的特征选择之后,就可以开始训练模型了,本文例子中使用的是线性回归,因此不需要对算法进行任何预分析。我们使用矩阵对所得模型进行评估,回归问题的性能则是根据“均方误差”和“平均绝对误差”来计算的。


总结


以上都是解决机器学习问题的基本步骤,在搭建模型时,最重要并且最困难的通常都是清理预处理数据。而讽刺的是,应用算法和预测输出通常也就是几行代码而已,这部分可以说是模型构建中最简单的部分了。


如果喜欢这篇文章,欢迎在评论区留下你的见解或疑问,也可以关注原作者的领英Instagram


原文链接:


《Data Preparation Techniques and Its Importance in Machine Learning, by Data Science Whoopees》


2020 年 9 月 03 日 11:27633

评论

发布
暂无评论
发现更多内容

架構師訓練營第 1 期 - 第 07 周總結

Panda

架構師訓練營第 1 期

架构师训练营 - 第三周课后练习

joshuamai

区块链usdt承兑商支付系统开发,usdt跑分系统搭建

WX13823153201

Week 7 性能优化总结

黄立

力扣解题:第三题(个人思路整理)

人语驿边桥

力扣

屏读时代,我们患上了注意力缺失候群症

脑极体

从广西的新基建耕种,读懂一颗名为智能体的种子

脑极体

6年Java开发经验,蚂蚁金服面试3+2次,最终有惊无险通过!(已拿offer)

Java架构之路

Java 程序员 架构 面试 编程语言

【涂鸦物联网足迹】涂鸦云平台全景介绍

IoT云工坊

人工智能 云计算 大数据 物联网平台 物联网

【涂鸦物联网足迹】物联网主流通信方式

IoT云工坊

人工智能 云计算 大数据 物联网 云平台

第三周作业

丁乐洪

Week 7 作业一

黄立

架构师训练营第三周课后作业

天涯若海

极客大学 - 架构师训练营 第七周作业

9527

架构师训练营 - 第 7 周课后作业(1 期)

阿甘

8张图带你分析Redis与MySQL数据一致性问题

Java架构师迁哥

https 握手失败问题排查全记录

lockdown56

nginx https 网络 HTTP 抓包

WSL还是不错的

孙苏勇

WSL2 工具链 wsl

手把手教你如何在Windows安装Anaconda

计算机与AI

Python Anaconda

阿里P8大牛精心整理,GitHub上超火的《Java工程师成神之路》从基础,到高级、底层、架构、进阶、扩展,囊括了Java体系内的所有知识点。

Java架构之路

Java 程序员 架构 面试 编程语言

GitHub上超牛的Java进阶教程,汇总Java生态圈常用技术框架、开源中间件,系统架构、数据库、大公司架构案例、常用三方类库、项目管理、线上问题排查、个人成长、思考等知识

Java架构之路

Java 程序员 架构 面试 编程语言

一道比较运算符相关的面试题把我虐的体无完肤

新世界杂货铺

在Idea中使用JUnit单元测试

jiangling500

单元测试 IDEA JUnit

穿越时空的回响:华为欧洲创新日的蝴蝶振翅

脑极体

应用层软件开发教父教你如何重构,资深程序员必备专业技能

小Q

Java 学习 架构 面试 重构

解决大中型浏览器(Chrome)插件开发痛点:自定义热更新方案——1.原理分析及构建部署实现

梁龙先森

Java chrome 前端 浏览器 技术方案

1分钟带你解锁Angular

Leo

学习 前端 angular 前端进阶训练营

GrowingIO 响应式编程探索和实践

GrowingIO技术专栏

响应式编程

架构师训练营 第三周作业(手写单例模式)

springH₂O

架构训练营

一周信创舆情观察(10.26~11.1)

统小信uos

架构师训练营 - 第三周学习总结

joshuamai

数据准备技巧及其对机器学习的重要性-InfoQ