提交 5245d3bb 编写于 作者: W wizardforcel

ch15

上级 aa919479
# 十五、分类
> 原文:[Classification](https://github.com/data-8/textbook/tree/gh-pages/chapters/15)
> 译者:[飞龙](https://github.com/wizardforcel)
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
> 自豪地采用[谷歌翻译](https://translate.google.cn/)
[David Wagner](https://en.wikipedia.org/wiki/David_A._Wagner) 是这一章的主要作者。
机器学习是一类技术,用于自动寻找数据中的规律,并使用它来推断或预测。你已经看到了线性回归,这是一种机器学习技术。本章介绍一个新的技术:分类。
......@@ -94,7 +103,7 @@ ckd = ckd.join('Class', color_table)
ckd.scatter('Hemoglobin', 'Glucose', colors='Color')
```
假设爱丽丝是不在数据集中的新患者。 如果我告诉你爱丽丝的血红蛋白水平和血糖水平,你可以预测她是否有 CKD 嘛? 确实看起来可以! 可以在这里看到非常清晰的规律:右下角的点代表没有 CKD 的人,其余的倾向于有 CKD 的人。 对于人来说,规律是显而易见的。 但是,我们如何为计算机编程来自动检测这种规律?
假设爱丽丝是不在数据集中的新患者。 如果我告诉你爱丽丝的血红蛋白水平和血糖水平,你可以预测她是否有 CKD 嘛? 确实看起来可以! 可以在这里看到非常清晰的规律:右下角的点代表没有 CKD 的人,其余的倾向于有 CKD 的人。 对于人来说,规律是显而易见的。 但是,我们如何为计算机编程来自动检测这种规律?
### 最近邻分类器
......@@ -150,7 +159,7 @@ show_closest(alice)
ckd.scatter('White Blood Cell Count', 'Glucose', colors='Color')
```
所见,非 CKD 个体都聚集在左下角。大多数 CKD 患者在该簇的上方或右侧,但不是全部。上图左下角有一些 CKD 患者(分散在金簇中的少数蓝点表示)。这意味着你不能从这两个检测结果确定,某些人是否拥有 CKD。
所见,非 CKD 个体都聚集在左下角。大多数 CKD 患者在该簇的上方或右侧,但不是全部。上图左下角有一些 CKD 患者(分散在金簇中的少数蓝点表示)。这意味着你不能从这两个检测结果确定,某些人是否拥有 CKD。
如果提供爱丽丝的血糖水平和白细胞计数,我们可以预测她是否患有慢性肾病嘛?是的,我们可以做一个预测,但是我们不应该期望它是 100% 准确的。直觉上,似乎存在预测的自然策略:绘制 Alice 在散点图中的位置;如果她在左下角,则预测她没有 CKD,否则预测她有 CKD。
......@@ -264,7 +273,7 @@ Row(Age=48, Blood Pressure=70, Specific Gravity=1.0049999999999999, Albumin=4, S
行通常不是数组,因为它们的元素可以是不同的类型。 例如,上面那行的一些元素是字符串(如`'abnormal'`),有些是数字。 所以行不能被转换成数组。
但是,行与数组有一些特征。 可以使用`item`来访问行中的特定元素。 例如,要访问患者 0 的白蛋白水平,我们可以查看上面那行的打印输出中的标签,发现它是第 3 项:
但是,行与数组有一些特征。 可以使用`item`来访问行中的特定元素。 例如,要访问患者 0 的白蛋白水平,我们可以查看上面那行的打印输出中的标签,发现它是第 3 项:
```py
ckd.row(0).item(3)
......@@ -556,7 +565,7 @@ banknotes = banknotes.join('Class', color_table)
banknotes.scatter('WaveletVar', 'WaveletCurt', colors='Color')
```
非常有趣! 这两个测量值看起来对于预测钞票是否伪造有帮助。 然而,在这个例子中,你现在可以看到蓝色的簇和金色的簇之间有一些重叠。 这表示基于这两个数字,很难判断钞票是否合法。 不过,可以使用 K 最近邻分类器来预测钞票的合法性。
非常有趣! 这两个测量值看起来对于预测钞票是否伪造有帮助。 然而,在这个例子中,你现在可以看到蓝色的簇和金色的簇之间有一些重叠。 这表示基于这两个数字,很难判断钞票是否合法。 不过,可以使用 K 最近邻分类器来预测钞票的合法性。
花点时间想一想:假设我们使用`k = 11`(是假如)。 图中的哪些部分会得到正确的结果,哪些部分会产生错误? 决定边界是什么样子?
......@@ -803,7 +812,7 @@ classify(wine, special_wine, 5)
为了看看我们的分类器做得如何,我们可以将 50% 的数据放入训练集,另外 50% 放入测试集。基本上,我们保留一些数据以便以后使用,所以我们可以用它来测量分类器的准确性。我们始终将这个称为测试集。有时候,人们会把你留下用于测试的数据叫做保留集,他们会把这个估计准确率的策略称为保留方法。
请注意,这种方法需要严格的纪律。在开始使用机器学习方法之前,必须先取出一些数据,然后放在一边用于测试。你必须避免使用测试集来开发你的分类器:你不应该用它来帮助训练你的分类器或者调整它的设置,或者用头脑风暴的方式来改进你的分类器。相反,在最后你已经完成分类器之后,当你想要它的准确率的无偏估计时,你应该仅仅使用它使用一次。
请注意,这种方法需要严格的纪律。在开始使用机器学习方法之前,必须先取出一些数据,然后放在一边用于测试。你必须避免使用测试集来开发你的分类器:你不应该用它来帮助训练你的分类器或者调整它的设置,或者用头脑风暴的方式来改进你的分类器。相反,在最后你已经完成分类器之后,当你想要它的准确率的无偏估计时,你应该仅仅使用它使用一次。
### 测量我们的葡萄酒分类器的准确率
......@@ -955,7 +964,7 @@ sales.sort('SalePrice')
(省略了 1992 行)
销售价格的直方图显示出大量的变化,分布显然不是正态。 右边的长尾包含几个价格非常高的房子。 左边的短尾不包含任何售价低于 35,000 美元的房子
销售价格的直方图显示出大量的变化,分布显然不是正态。 右边的长尾包含几个价格非常高的房屋。 左边的短尾不包含任何售价低于 35,000 美元的房屋
```py
sales.hist('SalePrice', bins=32, unit='$')
......@@ -1001,7 +1010,7 @@ correlation(sales.with_column('Both Floors', both_floors), 'SalePrice', 'Both Fl
## 多元线性回归
在多元线性回归中,通过将每个属性值乘以不同的斜率,从数值输入属性预测数值输出,然后对结果求和。 在这个例子中,第一层的斜率将代表房第一层面积的美元每平方英尺,它应该用于我们的预测。
在多元线性回归中,通过将每个属性值乘以不同的斜率,从数值输入属性预测数值输出,然后对结果求和。 在这个例子中,第一层的斜率将代表房第一层面积的美元每平方英尺,它应该用于我们的预测。
在开始预测之前,我们将数据随机分成一个相同大小的训练和测试集。
......@@ -1118,3 +1127,98 @@ plots.plot([0, 7e5], [0, 0]);
## 最近邻回归
另一种预测房屋销售价格的方法是使用类似房屋的价格。 这个最近邻的方法与我们的分类器非常相似。 为了加速计算,我们将只使用与原始分析中销售价格相关性最高的属性。
```py
train_nn = train.select(0, 1, 2, 3, 4, 8)
test_nn = test.select(0, 1, 2, 3, 4, 8)
train_nn.show(3)
```
| SalePrice | 1st Flr SF | 2nd Flr SF | Total Bsmt SF | Garage Area | Year Built |
| --- | --- | --- | --- | --- | --- |
| 240000 | 1710 | 0 | 1710 | 550 | 2004 |
| 229000 | 1302 | 735 | 672 | 472 | 1996 |
| 136500 | 864 | 0 | 864 | 336 | 1978 |
(省略了 998 行)
最近邻的计算与最近邻分类器相同。 在这种情况下,我们将从距离计算中排除`'SalePrice'`而不是`'Class'`列。 第一个测试行的五个最近邻如下所示。
```py
def distance(pt1, pt2):
"""The distance between two points, represented as arrays."""
return np.sqrt(sum((pt1 - pt2) ** 2))
def row_distance(row1, row2):
"""The distance between two rows of a table."""
return distance(np.array(row1), np.array(row2))
def distances(training, example, output):
"""Compute the distance from example for each row in training."""
dists = []
attributes = training.drop(output)
for row in attributes.rows:
dists.append(row_distance(row, example))
return training.with_column('Distance', dists)
def closest(training, example, k, output):
"""Return a table of the k closest neighbors to example."""
return distances(training, example, output).sort('Distance').take(np.arange(k))
example_nn_row = test_nn.drop(0).row(0)
closest(train_nn, example_nn_row, 5, 'SalePrice')
```
| SalePrice | 1st Flr SF | 2nd Flr SF | Total Bsmt SF | Garage Area | Year Built | Distance |
| --- | --- | --- | --- | --- | --- |
| 150000 | 1299 | 0 | 967 | 494 | 1954 | 51.9711 |
| 144000 | 1344 | 0 | 1024 | 484 | 1958 | 60.8358 |
| 183500 | 1299 | 0 | 1001 | 486 | 1979 | 68.6003 |
| 140000 | 1283 | 0 | 931 | 506 | 1962 | 76.5049 |
| 173000 | 1287 | 0 | 957 | 541 | 1977 | 77.2464 |
预测价格的一个简单方法是计算最近邻的价格均值。
```py
def predict_nn(example):
"""Return the majority class among the k nearest neighbors."""
return np.average(closest(train_nn, example, 5, 'SalePrice').column('SalePrice'))
predict_nn(example_nn_row)
158100.0
```
最后,我们可以使用一个测试样本,检查我们的预测是否接近真实销售价格。 看起来很合理!
```py
print('Actual sale price:', test_nn.column('SalePrice').item(0))
print('Predicted sale price using nearest neighbors:', predict_nn(example_nn_row))
Actual sale price: 146000
Predicted sale price using nearest neighbors: 158100.0
```
### 尾注
为了为整个测试集评估这个方法的性能,我们将`predict_nn`应用于每个测试示例,然后计算预测的均方根误差。 预测的计算可能需要几分钟的时间。
```py
nn_test_predictions = test_nn.drop('SalePrice').apply(predict_nn)
rmse_nn = np.mean((test_prices - nn_test_predictions) ** 2) ** 0.5
print('Test set RMSE for multiple linear regression: ', rmse_linear)
print('Test set RMSE for nearest neighbor regression:', rmse_nn)
Test set RMSE for multiple linear regression: 30232.0744208
Test set RMSE for nearest neighbor regression: 31210.6572877
```
对于这些数据,这两种技术的误差非常相似! 对于不同的数据集,一种技术可能会胜过另一种。 通过计算两种技术在同一数据上的均方根误差,我们可以公平比较这些方法。值得注意的是:表现的差异可能不完全由于技术;这可能由于随机变化,由于首先对训练和测试集进行抽样。
最后,我们可以为这些预测画出一个残差图。 我们仍然低估了最昂贵房屋的价格,但偏差似乎并不像系统性的。 然而,较低价格的残差非常接近零,这表明较低价格的预测准确性非常高。
```py
test.with_column('Residual', test_prices-nn_test_predictions).scatter(0, 'Residual')
plots.plot([0, 7e5], [0, 0]);
```
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册