机器学习数据预处理该怎样做?(转载)

训练一个机器学习项目,对数据的预处理是非常重要的,所谓“磨刀不误砍柴工”,这决定了整个项目的效率,多花半个小时来对数据进行更优化的处理,也许在之后的训练运行过程中会节省一个小时甚至一天的时间。

接下来我们就来看看如何磨这把“刀”吧。

导入数据

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

先导入数据预处理所需要的库,在Python中,最流行的三个库也就是Numpy、Matplotlib 和 Pandas。对于数据预处理而言,Pandas 和 Numpy 基本是必需的,而Matplotlib.pyplot则是满足绘图所需要的库。

我们通常处理的数据集是csv文件,这时我们用下面这条语句

dataset = pd.read_csv('train_data.csv')

用Pandas(pd.read_csv)来读入数据集。之后输入dataset并回车可以看到我们读入的数据。(图中仅显示了一部分)
在这里插入图片描述
然而有的时候我们想要输入的数据已经压缩好了譬如是一文件夹的图片,那我们可以用另一种读取数据的方式,如下:

import glob
image = glob.glob('./*.jpg')

这样的操作会读入当前目录下的所有jpg格式的图片

数据处理的第一步应该是打乱输入的数据,以防数据集是以某种规律整合在一起的,这对于我们的训练是有利的

dataset= np.random.permutation(image)

在这之后我们需要将我们视作标签的一列与其他的分离开,形成两个矩阵(或者说一个矩阵一个向量),并将标签视作因变量,其余的作为自变量。

X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, 3].values

这两行语句分别将从第一列到倒数第二列与最后一列分开并存入两个变量中。“,”的前面表示取所有行,后面表示取对应的列。

如果数据有缺失怎么办?

事实上,我们总会遇到数据缺失。对此,我们可以将存在缺失的行直接删除,但这不是一个好办法,还很容易引发问题。因此需要一个更好的解决方案。最常用的方法是,用其所在列的均值来填充缺失。为此,你可以利用 scikit-learn 预处理模型中的 imputer 类来很轻松地实现。

from sklearn.preprocessing import Imputer
imputer = Imputer(missing_values = np.nan, strategy = ‘mean’, axis = 0)

均值填充是默认的填充策略,所以其实不需要指定,加在此处是为了方便了解可以包含什么信息。missing_values 的默认值是 nan。如果你的数据集中存在「NaN」形式的缺失值,那么你应该关注 np.nan,可以在此查看官方文档:
https://scikit-learn.org/stable/modules/generated/sklearn.impute.SimpleImputer.html

我们只希望在数据存在缺失的列上拟合 imputer。为了拟合这个 imputer,输入:

imputer = imputer.fit(X[:, 1:3])

现在,我们希望调用实际上可以替换填充缺失数据的方法。通过输入以下语句完成:

X[:, 1:3] = imputer.transform(X[:, 1:3])

By the way,也许在某些项目中,你会发现,使用缺失值所在列的中位数或众数来填充缺失值会更加合理。填充策略之类的决策看似细微,但其实意义重大。因为流行通用的方法并不一定就是正确的选择,对于模型而言,均值也不一定是最优的缺失填充选择。

如果包含属性数据,会怎么样呢?

这是一个好问题。没有办法明确地计算诸如猫、狗、麋鹿的均值。那么可以怎么做呢?可以将属性数据编码为数值!你可能希望使用 sklearn.preprocessing 所提供的 LabelEncoder 类。从你希望进行编码的某列数据入手,调用 label encoder 并拟合在你的数据上。

from sklearn.preprocessing import LabelEncoder
labelencoder_X = LabelEncoder()
X[:, 0] = labelencoder_X.fit_transform(X[:, 0])

这就是将第一列中的属性变量替换为数值所需的全部工作了。例如,麋鹿将用 0 表示,狗将用 2 表示,猫将用 3 表示。

你发现什么潜在问题了吗?

对了!所使用的数值层级关系可能会影响模型结果:在程序中,3 比 0 的数值大,会导致程序认为猫比麋鹿大(但这并不是可比较的),但猫并不一定比麋鹿大。

如何解决这个问题呢?输入 OneHotEncoder 吧!也就是所谓的独热编码。比如在mnist手写数据集中,我们会把0,1,2,3…9这十个数字用一个十位的二进制(至少看起来像二进制)表示,1000000000表示0,0100000000表示1,…。下面看程序

导入编码器,并制定对应列的索引:

from sklearn.preprocessing import OneHotEncoder
onehotencoder = OneHotEncoder(categorical_features = [0])

接着是一点拟合和转换:

X = onehotencoder.fit_transform(X).toarray()

现在,你的那一列数据已经被替换为了这种形式:数据组中的每一个属性数据对应一列,并以 1 和 0 取代属性变量。非常贴心,对吧?如果我们的 Y 列也是如「Y」和「N」的属性变量,那么我们也可以在其上使用这个编码器。

labelencoder_y = LabelEncoder()
y = labelencoder_y.fit_transform(y)

这会直接拟合并将 y 表示为编码变量:1 表示「Y」,0 表示「N」。

训练集与测试集的划分

如果你导入的数据并没有将训练集数据与测试集数据分开,你可以开始将数据集划分为训练集和测试集了。不过记得,一定要将你的数据分为训练集和测试集,永远不要用测试集来训练!

现在,我们有了需要学习的模型。模型需要在数据上训练,并在另外的数据上完成测试。对训练集的记忆并不等于学习。模型在训练集上学习得越好,就应该在测试集给出更好的预测结果。过拟合永远都不是你想要的结果,学习才是!

首先,导入:

from sklearn.model_selection import train_test_split

现在,可以创建 X_train、X_test、y_train 和 y_test 集合了。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)

一种常见的方法是将数据集按 80/20 进行划分,其中 80% 的数据用作训练,20% 的数据用作测试。这也是为何指定 test_size 为 0.2 的原因。你也可以根据自己的需求来任意划分,如果你的数据集特别大,譬如有一百万张图片,那完全可以只用五万张图片来作为测试集。你并不需要设置 random_state,这里设置的原因是为了可以完全复现结果。

特征缩放

什么是特征缩放?为什么需要特征缩放?

看看我们的数据。我们有一列动物年龄,范围是 4~17,还有一列动物价值,范围是$48,000-$83,000。价值一栏的数值不仅远大于年龄一栏,而且它还包含更加广阔的数据范围。这表明,欧式距离将完全由价值这一特征所主导,而忽视年龄数据的主导效果。如果欧式距离在特定机器学习模型中并没有具体作用会怎么样?缩放特征将仍能够加速模型,因此,你可以在数据预处理中,加入特征缩放这一步。

特征缩放的方法有很多。但它们都意味着我们将所有的特征放在同一量纲上,进而没有一个会被另一个所主导。

导入相关库开始:

from sklearn.preprocessing import StandardScaler

创建一个需要缩放对象并调用 Standard Scaler

sc_X = StandardScaler()

直接在数据集上进行拟合以及变换。获取对象并应用方法。

X_train = sc_X.fit_transform(X_train)
X_test = sc_X.transform(X_test)

不需要在测试集上进行拟合,只进行变换

sc_y = StandardScaler()
y_train = sc_y.fit_transform(y_train)

原文链接:https://towardsdatascience.com/the-complete-beginners-guide-to-data-cleaning-and-preprocessing-2070b7d4c6d

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章