Python-sklearn机器学习的第一个样例(3)

接上一篇


Step 3:数据整理

让我们逐个解决以上的问题: 出现5个种类的问题,经过数据探索,发现是有部分类名忘记加上Iris-的前缀,另外有部分setossa是拼写错误。下面纠正这些错误:

In [6]:
iris_data.loc[iris_data['class'] == 'versicolor', 'class'] = 'Iris-versicolor'
iris_data.loc[iris_data['class'] == 'Iris-setossa', 'class'] = 'Iris-setosa'

iris_data['class'].unique()
Out[6]:
array(['Iris-setosa', 'Iris-versicolor', 'Iris-virginica'], dtype=object)

这样看起来好多了! 现在数据集中只有三种类型了。想象一下,如果我们创建的数据模型中,使用了错误的分类,那多尴尬。

下面解决第二个问题。

解决异常值需要一些技巧。通常我们很难弄清楚产生异常值的原因,到底是测量失误?用了错误的数据单位?确实发生了异常事件?我们通常不知道。因此,我们在处理异常的时候需要保持清醒。如果我们决定要排除任何数据,就应该有强有力的理由,并且在文档中注明。

对于一个异常Iris-setosa条目,经过咨询Iris-setosa领域研究人员知道,不可能有萼片宽度小于2.5厘米。显然这个条目是错误,我们很难知道造成错误的原因,最好的方法是删掉这条记录。

In [7]:
# This line drops any 'Iris-setosa' rows with a separal width less than 2.5 cm
iris_data = iris_data.loc[(iris_data['class'] != 'Iris-setosa') | (iris_data['sepal_width_cm'] >= 2.5)]
iris_data.loc[iris_data['class'] == 'Iris-setosa', 'sepal_width_cm'].hist()
Out[7]:

好了,现在所有的 Iris-setosa 花萼宽度都比2.5大。

下一个要解决“一些Iris-versicolor的花萼长度sepal_length_cm接近于零”的问题。让我们看看这些行:

In [8]:
iris_data.loc[(iris_data['class'] == 'Iris-versicolor') &
              (iris_data['sepal_length_cm'] < 1.0)]
Out[8]:
  sepal_length_cm sepal_width_cm petal_length_cm petal_width_cm class
77 0.067 3.0 5.0 1.7 Iris-versicolor
78 0.060 2.9 4.5 1.5 Iris-versicolor
79 0.057 2.6 3.5 1.0 Iris-versicolor
80 0.055 2.4 3.8 1.1 Iris-versicolor
81 0.055 2.4 3.7 1.0 Iris-versicolor

看起来,这些接近0的数值,好像都比正常值低100倍,也许是小数点点错了?经过咨询研究人员,果然是有些人忘记把长度单位从“米”改为“厘米”。这就好办了:

In [8]:
iris_data.loc[(iris_data['class'] == 'Iris-versicolor') &
              (iris_data['sepal_length_cm'] < 1.0),
              'sepal_length_cm'] *= 100.0

iris_data.loc[iris_data['class'] == 'Iris-versicolor', 'sepal_length_cm'].hist()
Out[8]:
Python-sklearn机器学习的第一个样例(3)_第1张图片

我们已经把异常值处理完毕!

下面解决第三个问题:有些行的数据有缺失。

In [10]:
iris_data.loc[(iris_data['sepal_length_cm'].isnull()) |
              (iris_data['sepal_width_cm'].isnull()) |
              (iris_data['petal_length_cm'].isnull()) |
              (iris_data['petal_width_cm'].isnull())]
Out[10]:
  sepal_length_cm sepal_width_cm petal_length_cm petal_width_cm class
7 5.0 3.4 1.5 NaN Iris-setosa
8 4.4 2.9 1.4 NaN Iris-setosa
9 4.9 3.1 1.5 NaN Iris-setosa
10 5.4 3.7 1.5 NaN Iris-setosa
11 4.8 3.4 1.6 NaN Iris-setosa

把这些数据全部丢弃,显然不是很理想,特别是它们都属于setosa类。丢弃这部分数据,容易对数据分析结果造成不利影响。

常用的处理数据丢失的方法是:“均值归一”法,就是用所有测量值的平均值来填补缺失值。

In [11]:
iris_data.loc[iris_data['class'] == 'Iris-setosa', 'petal_width_cm'].hist()
Out[11]:
Python-sklearn机器学习的第一个样例(3)_第2张图片

看得出来,大部分setosa类的花瓣宽度都在0.2-0.3cm之间,这就更有理由用平均值来填补缺失值了。

In [12]:
average_petal_width = iris_data.loc[iris_data['class'] == 'Iris-setosa', 'petal_width_cm'].mean()

iris_data.loc[(iris_data['class'] == 'Iris-setosa') &
              (iris_data['petal_width_cm'].isnull()),
              'petal_width_cm'] = average_petal_width

iris_data.loc[(iris_data['class'] == 'Iris-setosa') &
              (iris_data['petal_width_cm'] == average_petal_width)]
Out[12]:
  sepal_length_cm sepal_width_cm petal_length_cm petal_width_cm class
7 5.0 3.4 1.5 0.25 Iris-setosa
8 4.4 2.9 1.4 0.25 Iris-setosa
9 4.9 3.1 1.5 0.25 Iris-setosa
10 5.4 3.7 1.5 0.25 Iris-setosa
11 4.8 3.4 1.6 0.25 Iris-setosa
In [13]:
iris_data.loc[(iris_data['sepal_length_cm'].isnull()) |
              (iris_data['sepal_width_cm'].isnull()) |
              (iris_data['petal_length_cm'].isnull()) |
              (iris_data['petal_width_cm'].isnull())]
Out[13]:

非常棒,已经没有缺失值了。当然如果你不喜欢对数据进行这样的计算处理,把所有缺失值都去除,也是一种方法。

注意: 如果你对这样修补数据感到不爽,也可以把包含所有缺失数据的行删除,调用 dropna() 方法:

iris_data.dropna(inplace=True)

接下来,把清理后的数据保持到文件里,这样下次就不用再处理一次了。

In [14]:
iris_data.to_csv('iris-data-clean.csv', index=False)

iris_data_clean = pd.read_csv('iris-data-clean.csv')

让我们再用散点图矩阵来看看经过清洗后的数据分布。

In [15]:
sb.pairplot(iris_data_clean, hue='class')
Out[15]:
Python-sklearn机器学习的第一个样例(3)_第3张图片

关于数据清洗的几个要点:

确保你的数据采用正确的方式编码

确保你的数值落在合理的区间,尽可能采用专业领域的知识,判断合理的数值区间范围

处理缺失数据的两个方法:替换或删除

不要手工整理数据,因为这很难重现

使用程序代码,这样可以比较好地记录数据处理的过程

尽可能画图展现所有数据,可视化地方式确认数据正确性

彩蛋:数据的完整性测试

使用assert语句,可以快速进行数据测试。如果测试结果是True,notebook不会显示任何信息并继续向下执行,否则终止运行,并显示错误提示。

In [16]:
assert 1 == 2
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
 in ()
----> 1 assert 1 == 2

AssertionError: 
In [17]:
# We know that we should only have three classes
assert len(iris_data_clean['class'].unique()) == 3
In [18]:
# We know that sepal lengths for 'Iris-versicolor' should never be below 2.5 cm
assert iris_data_clean.loc[iris_data_clean['class'] == 'Iris-versicolor', 'sepal_length_cm'].min() >= 2.5
In [19]:
# We know that our data set should have no missing measurements
assert len(iris_data_clean.loc[(iris_data_clean['sepal_length_cm'].isnull()) |
                               (iris_data_clean['sepal_width_cm'].isnull()) |
                               (iris_data_clean['petal_length_cm'].isnull()) |
                               (iris_data_clean['petal_width_cm'].isnull())]) == 0

就像这样的测试,如果不能通过测试,会终止程序并返回例外信息,我们必须回头继续对数据进行整理。

你可能感兴趣的:(机器学习,Python)