提交 682dcba3 编写于 作者: W wizardforcel

ch15.

上级 35525fd0
......@@ -30,7 +30,7 @@
### 慢性肾病
我们来浏览一个例子。 我们将使用收集的数据集来帮助医生诊断慢性肾病(CKD)。 数据集中的每一行都代表单个患者,过去接受过治疗并且诊断已知。 对于每个患者,我们都有一组血液测试的测量结果。 我们希望找到哪些测量结果对诊断慢性肾病最有用,并根据他们的血液检查结果,开发一种方法,将未来的患者分类为“CKD”或“ CKD”。
我们来浏览一个例子。 我们将使用收集的数据集来帮助医生诊断慢性肾病(CKD)。 数据集中的每一行都代表单个患者,过去接受过治疗并且诊断已知。 对于每个患者,我们都有一组血液测试的测量结果。 我们希望找到哪些测量结果对诊断慢性肾病最有用,并根据他们的血液检查结果,开发一种方法,将未来的患者分类为“CKD”或“ CKD”。
```py
ckd = Table.read_table('ckd.csv').relabeled('Blood Glucose Random', 'Glucose')
......@@ -83,7 +83,7 @@ ckd
我们来看两列,(病人的血液中)血红蛋白水平和血糖水平(一天中的随机时间;没有专门为血液测试禁食)。
我们将绘制一个散点图来显示两个变量之间的关系。 蓝点是 CKD 患者; 金点是 CKD 的患者。 什么样的医学检验结果似乎表明了 CKD?
我们将绘制一个散点图来显示两个变量之间的关系。 蓝点是 CKD 患者; 金点是 CKD 的患者。 什么样的医学检验结果似乎表明了 CKD?
```py
color_table = Table().with_columns(
......@@ -113,13 +113,13 @@ show_closest(alice)
因此,我们的最近邻分类器是这样工作的:
+ 找到训练集中离新点最近的点。
+ 如果最近的点是“CKD”点,则将新点划分为“CKD”。如果最近的点是“无 CKD”点,则将新点划分为“无 CKD”。
+ 如果最近的点是“CKD”点,则将新点划分为“CKD”。如果最近的点是“非 CKD”点,则将新点划分为“非 CKD”。
散点图表明这个最近邻分类器应该相当准确。右下角的点倾向于接受“ CKD”的诊断,因为他们的最近邻是一个金点。其余的点倾向于接受“CKD”诊断,因为他们的最近邻是蓝点。所以这个例子中,最近邻策略似乎很好地捕捉了我们的直觉。
散点图表明这个最近邻分类器应该相当准确。右下角的点倾向于接受“ CKD”的诊断,因为他们的最近邻是一个金点。其余的点倾向于接受“CKD”诊断,因为他们的最近邻是蓝点。所以这个例子中,最近邻策略似乎很好地捕捉了我们的直觉。
## 决策边界
有时一种分类器可视化的实用方法是,绘制出分类器预测“CKD”的几种属性,以及预测“无 CKD”的几种。我们最终得到两者之间的边界,边界一侧的点将被划分为“CKD”,而另一侧的点将划分为“无 CKD”。这个边界称为决策边界。每个不同的分类器将有不同的决策边界;决策边界只是一种方法,用于可视化分类器实用什么标准来对点分类。
有时一种分类器可视化的实用方法是,绘制出分类器预测“CKD”的几种属性,以及预测“非 CKD”的几种。我们最终得到两者之间的边界,边界一侧的点将被划分为“CKD”,而另一侧的点将划分为“非 CKD”。这个边界称为决策边界。每个不同的分类器将有不同的决策边界;决策边界只是一种方法,用于可视化分类器实用什么标准来对点分类。
例如,假设爱丽丝的点坐标是`(0, 1.5)`。注意最近邻是蓝色的。现在尝试减少点的高度(`y`坐标)。你会看到,在`y = 0.95`左右,最近邻从蓝色变为金色。
......@@ -137,7 +137,7 @@ show_closest(alice)
对于每个红点,它必须找到训练集中最近的点;它必须将红点的颜色改变为最近邻的颜色。
结果图显示哪些点将划分为“CKD”(全部为蓝色),或者“ CKD”(全部为黄金)。
结果图显示哪些点将划分为“CKD”(全部为蓝色),或者“ CKD”(全部为黄金)。
决策边界是分类器从将红点转换为蓝色变成金色的地方。
......@@ -150,7 +150,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。
......@@ -158,7 +158,7 @@ ckd.scatter('White Blood Cell Count', 'Glucose', colors='Color')
我们可以在计算机上自动化吗?那么,最近邻分类器也是一个合理的选择。花点时间思考一下:它的预测与上述直觉策略的预测相比如何?他们什么时候会不同?
它的预测与我们的直觉策略非常相似,但偶尔会做出不同的预测。特别是,如果爱丽丝的血液检测结果恰好把她放在左下角的一个蓝点附近,那么这个直观的策略就可能预测“ CKD”,而最近邻的分类器会预测“CKD”。
它的预测与我们的直觉策略非常相似,但偶尔会做出不同的预测。特别是,如果爱丽丝的血液检测结果恰好把她放在左下角的一个蓝点附近,那么这个直观的策略就可能预测“ CKD”,而最近邻的分类器会预测“CKD”。
最近邻分类器有一个简单的推广,修正了这个异常。它被称为 K 最近邻分类器。为了预测爱丽丝的诊断,我们不仅仅查看靠近她的一个邻居,而是查看靠近她的三个点,并用这三个点中的每一个点的诊断来预测艾丽丝的诊断。特别是,我们将使用这 3 个诊断中的大部分值作为我们对 Alice 诊断的预测。当然,数字 3 没有什么特别之处:我们可以使用 4 或 5 或更多。 (选择一个奇数通常是很方便的,所以我们不需要处理相等)。一般来说,我们选择一个数字`k`,而我们对 Alice 的预测诊断是基于训练集中最接近爱丽丝的`k`个点。直观来说,这些是血液测试结果与爱丽丝最相似的`k`个患者,因此使用他们的诊断来预测爱丽丝的诊断似乎是合理的。
......@@ -237,3 +237,114 @@ plt.ylim(-2, 6);
把测试数据放在这个图上,你可以立刻看到分类器对于几乎所有的点都正确,但也有一些错误。 例如,测试集的一些蓝点落在分类器的金色区域。
尽管存在一些错误,但分类器看起来在测试集上表现得相当好。 假设原始样本是从底层总体中随机抽取的,我们希望分类器在整个总体上具有相似的准确性,因为测试集是从原始样本中随机选取的。
## 表的行
现在我们对最近邻分类有一个定性的了解,是时候实现我们的分类器了。
在本章之前,我们主要处理表格的单列。 但现在我们必须看看一个个体是否“接近”另一个个体。 个体数据包含在表格的行中。
那么让我们首先仔细看一下行。
这里是原始表格`ckd`,包含慢性肾病患者资料。
```py
ckd = Table.read_table('ckd.csv').relabeled('Blood Glucose Random', 'Glucose')
```
对应第一个患者的数据在表中第 0 行,与 Python 的索引系统一致。 `Table`的`row`方法将行索引作为其参数来访问行。
```py
ckd.row(0)
Row(Age=48, Blood Pressure=70, Specific Gravity=1.0049999999999999, Albumin=4, Sugar=0, Red Blood Cells='normal', Pus Cell='abnormal', Pus Cell clumps='present', Bacteria='notpresent', Glucose=117, Blood Urea=56, Serum Creatinine=3.7999999999999998, Sodium=111, Potassium=2.5, Hemoglobin=11.199999999999999, Packed Cell Volume=32, White Blood Cell Count=6700, Red Blood Cell Count=3.8999999999999999, Hypertension='yes', Diabetes Mellitus='no', Coronary Artery Disease='no', Appetite='poor', Pedal Edema='yes', Anemia='yes', Class=1)
```
行拥有自己的数据类型:它们是行对象。 注意屏幕不仅显示行中的值,还显示相应列的标签。
行通常不是数组,因为它们的元素可以是不同的类型。 例如,上面那行的一些元素是字符串(如`'abnormal'`),有些是数字。 所以行不能被转换成数组。
但是,行与数组有一些特征。 您可以使用`item`来访问行中的特定元素。 例如,要访问患者 0 的白蛋白水平,我们可以查看上面那行的打印输出中的标签,发现它是第 3 项:
```py
ckd.row(0).item(3)
4
```
### 将行转换为数组(可能的时候)
元素都是数字(或都是字符串)的行可以转换为数组。 将行转换为数组可以让我们访问算术运算和其他漂亮的 NumPy 函数,所以它通常很有用。
回想一下,在上一节中,我们试图根据血红蛋白和血糖两个属性将患者划分为“CKD”或“非 CKD”,这两个属性都是以标准单位测量的。
```py
ckd = Table().with_columns(
'Hemoglobin', standard_units(ckd.column('Hemoglobin')),
'Glucose', standard_units(ckd.column('Glucose')),
'Class', ckd.column('Class')
)
color_table = Table().with_columns(
'Class', make_array(1, 0),
'Color', make_array('darkblue', 'gold')
)
ckd = ckd.join('Class', color_table)
ckd
```
| Class | Hemoglobin | Glucose | Color |
| --- | --- | --- | --- |
| 0 | 0.456884 | 0.133751 | gold |
| 0 | 1.153 | -0.947597 | gold |
| 0 | 0.770138 | -0.762223 | gold |
| 0 | 0.596108 | -0.190654 | gold |
| 0 | -0.239236 | -0.49961 | gold |
| 0 | -0.0304002 | -0.159758 | gold |
| 0 | 0.282854 | -0.00527964 | gold |
| 0 | 0.108824 | -0.623193 | gold |
| 0 | 0.0740178 | -0.515058 | gold |
| 0 | 0.83975 | -0.422371 | gold |
(省略了 148 行)
下面是两个属性的散点图,以及新患者 Alice 对应的红点。 她的血红蛋白值是 0(即平均值)和血糖为 1.1(即比平均值高 1.1 个 SD)。
```py
alice = make_array(0, 1.1)
ckd.scatter('Hemoglobin', 'Glucose', colors='Color')
plots.scatter(alice.item(0), alice.item(1), color='red', s=30);
```
为了找到 Alice 点和其他点之间的距离,我们只需要属性的值:
```py
ckd_attributes = ckd.select('Hemoglobin', 'Glucose')
ckd_attributes
```
| Hemoglobin | Glucose |
| --- | --- |
| 0.456884 | 0.133751 |
| 1.153 | -0.947597 |
| 0.770138 | -0.762223 |
| 0.596108 | -0.190654 |
| -0.239236 | -0.49961 |
| -0.0304002 | -0.159758 |
| 0.282854 | -0.00527964 |
| 0.108824 | -0.623193 |
| 0.0740178 | -0.515058 |
| 0.83975 | -0.422371 |
(省略了 148 行)
每行由我们的训练样本中的一个点的坐标组成。 由于行现在只包含数值,因此可以将它们转换为数组。 为此,我们使用函数`np.array`,将任何类型的有序对象(如行)转换为数组。 (我们的老朋友`make_array`用于创建数组,而不是用于将其他类型的序列转换为数组。)
```py
ckd_attributes.row(3)
Row(Hemoglobin=0.59610766482326683, Glucose=-0.19065363034327712)
np.array(ckd_attributes.row(3))
array([ 0.59610766, -0.19065363])
```
这非常方便,因为我们现在可以在每行的数据上使用数组操作了。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册