数据、特征和标签 · 人工智能基础
程序怎么从例子里学习,而不是靠人写规则?
课程目录为什么需要它
有些问题很难写成规则:这封邮件是不是垃圾邮件?这套房子能卖多少钱?哪张照片里有猫?机器学习改为从例子里找规律。不过在任何模型之前,先要有数据。模型的大多数实际问题,一开始都是数据的问题:列选错了,数字的量级差得太远,或者测试偷偷看到了答案。
直觉理解
数据集就是一张表。每一行是一个例子;事先就知道的那些列是特征,你想预测的那一列是标签:
| 面积 (m²) | 房间数 | 价格 (千) |
|---|---|---|
| 50 | 2 | 150 |
| 80 | 3 | 230 |
| 120 | 4 | 330 |
(本课程里的数字都是为了练习编的。)
训练的意思是:找一个从特征到标签的函数,让它符合这些例子。但是符合旧例子很容易,一张查找表就能做到完美。真正重要的是模型在从没见过的行上表现如何。所以训练之前,你要先留出一部分行作为测试集,直到最后才去看它们。
特征的量级经常不一样:面积能到几百,房间数只有几个。很多方法会直接比较数字,大的那一列会把小的那一列淹没。最小-最大缩放把每个特征映射到 0…1:
缩放后 = (值 - 最小值) / (最大值 - 最小值)最小值和最大值只从训练集里取,再把同样的数用到测试集上。否则测试集的信息就漏进了训练。
定义
特征
An input column the model uses, such as size or number of rooms.模型使用的输入列,比如面积或房间数。
标签
The column the model learns to predict, such as the price.模型要学着预测的那一列,比如价格。
测试集
Rows kept aside during training and used only to check the finished model on new data.训练时留出来的行,只用来检查训练好的模型在新数据上的表现。
最小-最大缩放
Mapping a feature to the range 0…1 with (value − min) / (max − min).用 (值 − 最小值) / (最大值 − 最小值) 把特征映射到 0…1。
示例
特征和标签
动手试试从每一行里取出输入和答案。
houses = [
{"size": 50, "rooms": 2, "price": 150},
{"size": 80, "rooms": 3, "price": 230},
{"size": 120, "rooms": 4, "price": 330},
{"size": 65, "rooms": 2, "price": 190},
]
X = [[h["size"], h["rooms"]] for h in houses]
y = [h["price"] for h in houses]
print(X)
print(y)[[50, 2], [80, 3], [120, 4], [65, 2]] [150, 230, 330, 190]
- L7特征:每套房子一个输入列表。
- L8标签:每套房子的答案,顺序相同。
- L9X 的第 i 行和 y 的第 i 项是一对。
[[50, 2], [80, 3], [120, 4], [65, 2]]
留出测试集
动手试试把最后 20% 留出来。实际代码会先把行打乱。
rows = list(range(1, 11))
cut = int(len(rows) * 0.8)
train, test = rows[:cut], rows[cut:]
print(train)
print(test)[1, 2, 3, 4, 5, 6, 7, 8] [9, 10]
- L210 行的 80% 是 8。
8 - L3切片:前 8 行用于训练,剩下的用来最后检查。
最小-最大缩放
动手试试每个面积最后都落在 0 到 1 之间。
sizes = [50, 80, 120, 65]
lo, hi = min(sizes), max(sizes)
scaled = [(s - lo) / (hi - lo) for s in sizes]
print([round(v, 2) for v in scaled])[0.0, 0.43, 1.0, 0.21]
- L2lo = 50,hi = 120,范围是 70。
- L3最小的变成 0,最大的变成 1;80 是 (80 − 50) / 70 ≈ 0.43。
常见错误
用训练数据来测试
一个把训练数据背下来的模型,在这些数据上得分完美,却什么也说明不了。只能用它没见过的行来评判。
先缩放再划分
如果最小值和最大值来自全部数据,测试集就已经影响了训练。先划分,再只用训练集确定缩放。
泄露答案的特征
预测「这个订单会不会退货」时,像「已退款」这样的列只有事后才知道。模型测试时看起来很厉害,真用起来就不行。
小测验
1. 这段代码会输出什么?
rows = ["a", "b", "c", "d", "e"]
cut = int(len(rows) * 0.6)
print(rows[cut:])查看答案
答案:A
5 的 60% 是 3,所以 rows[3:] 是最后两个。
2. 为什么要留一份训练时模型看不到的测试集?
查看答案
答案:A
只有没见过的行,才能说明模型实际使用时的表现。
3. 你用整个数据集的最小值和最大值做缩放,然后才划分。问题在哪?
查看答案
答案:A
测试集参与了缩放的确定,最后的检查就不公平了。
动手练习
3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。
- 预测输出缩放三个分数
准确写出它打印的内容。
- 改需求全都一样
当所有值都相同时,
scale会崩溃:max - min是 0,Python 拒绝除以零。这种情况下给每个值都返回0.0。 - 从零写用训练集的数字缩放
写一个
scale_with(train, values),用 **train** 的最小值和最大值(而不是values的)来缩放values。测试数据可以超出 0…1,这没关系。如果train的最大值等于最小值,就给每个值返回0.0。scale_with([10, 20, 30], [15, 30, 40]) # [0.25, 1.0, 1.5]
本课术语
| 术语 | 中文 | 英文定义 |
|---|---|---|
| Feature | 特征 | An input column the model uses. |
| Label | 标签 | The value the model learns to predict. |
| Test set | 测试集 | Rows kept aside to check the model on unseen data. |
| Min-max scaling | 最小-最大缩放 | Mapping values to 0…1 with (v − min) / (max − min). |