提交 b60f2a25 编写于 作者: W wizardforcel

ch15.

上级 682dcba3
...@@ -348,3 +348,171 @@ array([ 0.59610766, -0.19065363]) ...@@ -348,3 +348,171 @@ array([ 0.59610766, -0.19065363])
``` ```
这非常方便,因为我们现在可以在每行的数据上使用数组操作了。 这非常方便,因为我们现在可以在每行的数据上使用数组操作了。
### 只有两个属性时点的距离
我们需要做的主要计算是,找出 Alice 的点与其他点之间的距离。 为此,我们需要的第一件事就是计算任意一对点之间的距离。
我们如何实现呢? 在二维空间中,这非常简单。 如果我们在坐标`(x0, y0)`处有一个点,而在`(x1, y1)`处有另一个点,则它们之间的距离是:
![](http://latex.codecogs.com/gif.latex?D%20%3D%20%5Csqrt%7B%28x_0-x_1%29%5E2%20+%20%28y_0-y_1%29%5E2%7D)
(这是从哪里来的?它来自勾股定理:我们有一个直角三角形,边长为`x0 - x1`和`y0 - y1`,我们想要求出斜边的长度。)
在下一节中,我们将看到,当存在两个以上的属性时,这个公式有个直接的扩展。 现在,让我们使用公式和数组操作来求出 Alice 和第 3 行病人的距离。
```py
patient3 = np.array(ckd_attributes.row(3))
alice, patient3
(array([ 0. , 1.1]), array([ 0.59610766, -0.19065363]))
distance = np.sqrt(np.sum((alice - patient3)**2))
distance
1.4216649188818471
```
我们需要 Alice 和一堆点之间的距离,所以让我们写一个称为距离的函数来计算任意一对点之间的距离。 该函数将接受两个数组,每个数组包含一个点的`(x, y)`坐标。 (记住,那些实际上是患者的血红蛋白和血糖水平。)
```py
def distance(point1, point2):
"""Returns the Euclidean distance between point1 and point2.
Each argument is an array containing the coordinates of a point."""
return np.sqrt(np.sum((point1 - point2)**2))
distance(alice, patient3)
1.4216649188818471
```
我们已经开始建立我们的分类器:距离函数是第一个积木。 现在让我们来研究下一个片段。
### 在整个行上使用`apply`
回想一下,如果要将函数应用于表的列的每个元素,一种方法是调用`table_name.apply(function_name, column_label)`。 当我们在列的每个元素上调用该函数时,它求值为由函数返回值组成的数组。所以数组的每个条目都基于表的相应行。
如果使用`apply`而不指定列标签,则整行将传递给该函数。 让我们在一个非常小的表格上,看看它的工作原理,表格包含训练样本中前五个患者的信息。
```py
t = ckd_attributes.take(np.arange(5))
t
```
| Hemoglobin | Glucose |
| --- | --- |
| 0.456884 | 0.133751 |
| 1.153 | -0.947597 |
| 0.770138 | -0.762223 |
| 0.596108 | -0.190654 |
| -0.239236 | -0.49961 |
举个例子,假设对于每个病人,我们都想知道他们最不寻常的属性是多么的不寻常。 具体而言,如果患者的血红蛋白水平远高于其血糖水平,我们想知道它离平均值有多远。 如果她的血糖水平远远高于她的血红蛋白水平,那么我们想知道它离平均值有多远。
这与获取两个量的绝对值的最大值是一样的。 为了为特定的行执行此操作,我们可以将行转换为数组并使用数组操作。
```py
def max_abs(row):
return np.max(np.abs(np.array(row)))
max_abs(t.row(4))
0.49961028259186968
```
现在我们可以将`max_abs`应用于`t`表的每一行:
```py
t.apply(max_abs)
array([ 0.4568837 , 1.15300352, 0.77013762, 0.59610766, 0.49961028])
```
这种使用`apply`的方式帮助我们创建分类器的下一个积木。
### Alice 的 K 最近邻
如果我们想使用 K 最近邻分类器来划分 Alice,我们必须确定她的 K 个最近邻。 这个过程中的步骤是什么? 假设`k = 5`。 然后这些步骤是:
+ 步骤 1:的是 Alice 与训练样本中每个点之间的距离。
+ 步骤 2:按照距离的升序对数据表进行排序。
+ 步骤 3:取得有序表的前 5 行。
步骤 2 和步骤 3 似乎很简单,只要我们有了距离。 那么我们来关注步骤 1。
这是爱丽丝:
```py
alice
array([ 0. , 1.1])
```
我们需要一个函数,它可以求出 Alice 和另一个点之间的距离,它的坐标包含在一行中。 `distance`函数返回任意两点之间的距离,他们的坐标位于数组中。 我们可以使用它来定义`distance_from_alice`,它将一行作为参数,并返回该行与 Alice 之间的距离。
```py
def distance_from_alice(row):
"""Returns distance between Alice and a row of the attributes table"""
return distance(alice, np.array(row))
distance_from_alice(ckd_attributes.row(3))
1.4216649188818471
```
现在我们可以调用`apply`,将`distance_from_alice`函数应用于`ckd_attributes`的每一行,第一步完成了。
```py
distances = ckd_attributes.apply(distance_from_alice)
ckd_with_distances = ckd.with_column('Distance from Alice', distances)
ckd_with_distances
```
| Class | Hemoglobin | Glucose | Color | Distance from Alice |
| --- | --- | --- | --- | --- |
| 0 | 0.456884 | 0.133751 | gold | 1.06882 |
| 0 | 1.153 | -0.947597 | gold | 2.34991 |
| 0 | 0.770138 | -0.762223 | gold | 2.01519 |
| 0 | 0.596108 | -0.190654 | gold | 1.42166 |
| 0 | -0.239236 | -0.49961 | gold | 1.6174 |
| 0 | -0.0304002 | -0.159758 | gold | 1.26012 |
| 0 | 0.282854 | -0.00527964 | gold | 1.1409 |
| 0 | 0.108824 | -0.623193 | gold | 1.72663 |
| 0 | 0.0740178 | -0.515058 | gold | 1.61675 |
| 0 | 0.83975 | -0.422371 | gold | 1.73862 |
(省略了 148 行)
对于步骤 2,让我们以距离的升序对表排序:
```py
sorted_by_distance = ckd_with_distances.sort('Distance from Alice')
sorted_by_distance
```
| Class | Hemoglobin | Glucose | Color | Distance from Alice |
| --- | --- | --- | --- | --- |
| 1 | 0.83975 | 1.2151 | darkblue | 0.847601 |
| 1 | -0.970162 | 1.27689 | darkblue | 0.986156 |
| 0 | -0.0304002 | 0.0874074 | gold | 1.01305 |
| 0 | 0.14363 | 0.0874074 | gold | 1.02273 |
| 1 | -0.413266 | 2.04928 | darkblue | 1.03534 |
| 0 | 0.387272 | 0.118303 | gold | 1.05532 |
| 0 | 0.456884 | 0.133751 | gold | 1.06882 |
| 0 | 0.178436 | 0.0410639 | gold | 1.07386 |
| 0 | 0.00440582 | 0.025616 | gold | 1.07439 |
| 0 | -0.169624 | 0.025616 | gold | 1.08769 |
(省略了 148 行)
步骤 3:前五行对应 Alice 的五个最近邻;你可以将五替换为任意正整数。
```py
alice_5_nearest_neighbors = sorted_by_distance.take(np.arange(5))
alice_5_nearest_neighbors
```
| Class | Hemoglobin | Glucose | Color | Distance from Alice |
| --- | --- | --- | --- | --- |
| 1 | 0.83975 | 1.2151 | darkblue | 0.847601 |
| 1 | -0.970162 | 1.27689 | darkblue | 0.986156 |
| 0 | -0.0304002 | 0.0874074 | gold | 1.01305 |
| 0 | 0.14363 | 0.0874074 | gold | 1.02273 |
| 1 | -0.413266 | 2.04928 | darkblue | 1.03534 |
爱丽丝五个最近邻中有三个是蓝点,两个是金点。 所以 5 邻近的分类器会把爱丽丝划分为蓝色:它可能预测爱丽丝有慢性肾病。
下面的图片放大了爱丽丝和她五个最近邻。 这两个金点就在红点正下方的圆圈内。 分类器说,爱丽丝更像她身边的三个蓝点。
我们正在实现我们的 K 最近邻分类器。 在接下来的两节中,我们将把它放在一起并评估其准确性。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册