作者:互联网 时间: 2026-07-13 08:54:53
要进行机器学习,先得有数据。假定我们收集了一批关于西瓜的数据,例如:

每一对括号里是一条「记录」,「=」意思是「取值为」。
这组记录的集合,就称为一个数据集(data set)。其中:
把刚才的「色泽、根蒂、敲声」三个属性,分别当作三维空间里的三根坐标轴,它们就张成了一个用来描述西瓜的三维空间。每个西瓜都能在这个空间里找到自己的一个坐标位置。
例如「青绿、蜷缩、浊响」这个瓜,就对应空间里点 。
由于空间里的每个点都对应一个坐标向量,所以我们也把一个示例称为一个特征向量(feature vector)。
为了后面方便推导,我们用一套标准记号把数据集写出来。
一般地,令
表示包含 个示例的数据集。如果每个示例由 个属性描述(比如西瓜用了 3 个属性),那么每个示例都是一个 维向量:
其中:
直觉上: 是所有可能的「特征组合」构成的大空间,而我们的数据集 只是从这个大空间里采出来的一小批点。
从数据里学出模型的过程,叫做学习(learning)或训练(training),这个过程靠执行某个学习算法来完成。
学出来的模型,对应了关于数据某种潜在的规律,因此也称假设(hypothesis);而这种潜在规律本身,则称为真相 / 真实(ground-truth)。学习的目的,就是找出或逼近真相。
另外,我们有时把学出来的模型叫做学习器(learner)——可以把它理解为:学习算法在「给定数据 + 给定参数空间」上跑出来的一个具体实例。
如果我们想学一个能判断「没剖开的瓜是不是好瓜」的模型,光有前面的特征描述还不够——还得知道每个瓜到底是好是坏。
所以我们需要给训练样本补上「结果」信息,例如:
这里关于示例「结果」的信息(例如「好瓜」),称为标记(label);拥有了标记信息的示例,则称为样例(example)。
一般地,用
表示第 个样例,其中:
拿到标记之后,根据「我们要预测的东西是什么类型」,学习任务可以分成两大类:
一般地,预测任务的期望是:通过对训练集
进行学习,建立一个从输入空间到输出空间的映射
不同任务下输出空间 长这样:
模型学出来之后,当然要拿来用。使用模型进行预测的过程,叫做测试(testing);被拿去预测的样本,叫做测试样本(testing sample)(也叫「测试示例」或「测试例」)。
例如,学出了映射 之后,对某个测试例 ,我们就能得到它的预测标记:
一句话记忆:训练集用来「学」,测试样本用来「考」。
除了「预测某个具体结果」,我们还可以对数据做另一种处理——聚类(clustering):把训练集里的西瓜分成若干组,每组叫一个簇(cluster)。
这些自动形成的簇,可能对应一些潜在的概念划分,例如「浅色瓜 / 深色瓜」,甚至「本地瓜 / 外地瓜」。
根据训练数据有没有标记信息,学习任务可大致划分为两大类:
记忆窍门:有标记 = 有老师教 = 监督学习;没标记 = 自己摸索 = 无监督学习。
这是整个机器学习里最关键的一个词——泛化(generalization)。
机器学习的目标,是让学出的模型能很好地适用于「新样本」,而不是仅仅在训练样本上表现好。哪怕对聚类这种无监督任务,我们也希望学出的簇划分能适用于训练集里没出现过的样本。
这里藏着一个重要的前提假设:
为什么这个假设重要?
机器学习的「行话」看似多,其实围绕一条主线:用一批带(或不带)标记的样本,从数据空间里学出一个映射;评判它好坏的终极标准不是训练时多准,而是面对没见过的新样本时,泛化能力够不够强。
下面这段 Python 代码,把前面「西瓜」的例子落成可运行的数据结构,并演示了监督学习(带标记)与无监督学习(不带标记)两种视角,以及最基础的训练集 / 测试集划分。
"""演示:构造西瓜数据集,并展示1) 监督学习视角(带标记 -> 分类任务)2) 无监督学习视角(去标记 -> 聚类任务)3) 训练集 / 测试集划分"""import random# 每个样本: [色泽, 根蒂, 敲声, 标记]# 标记 1=好瓜, 0=坏瓜(监督学习视角才用)dataset = [["青绿", "蜷缩", "浊响", 1],["乌黑", "蜷缩", "浊响", 1],["青绿", "硬挺", "清脆", 0],["乌黑", "稍蜷", "沉闷", 0],["浅白", "蜷缩", "浊响", 1],["青绿", "稍蜷", "浊响", 1],["乌黑", "硬挺", "清脆", 0],["浅白", "硬挺", "沉闷", 0],]def split_train_test(data, test_ratio=0.25, seed=42):"""按比例随机划分训练集和测试集(保持可复现,设随机种子)"""random.seed(seed)idx = list(range(len(data)))random.shuffle(idx)n_test = int(len(data) * test_ratio)test_idx = idx[:n_test]train_idx = idx[n_test:]train = [data[i] for i in train_idx]test = [data[i] for i in test_idx]return train, testdef to_supervised(data):"""监督学习视角:特征 X + 标记 y"""X = [row[:3] for row in data]y = [row[3] for row in data]return X, ydef to_unsupervised(data):"""无监督学习视角:只保留特征,丢掉标记"""return [row[:3] for row in data]if __name__ == "__main__":train, test = split_train_test(dataset)print("训练集样本数:", len(train), " 测试集样本数:", len(test))X_train, y_train = to_supervised(train)print("n[监督学习视角] 训练集特征 X_train:")for x, yy in zip(X_train, y_train):print("特征", x, "-> 标记(好瓜?)", yy)X_unsup = to_unsupervised(train)print("n[无监督学习视角] 只看特征,没有标记(适合做聚类):")for x in X_unsup:print("特征", x)
把代码保存为 terms_demo.py,用 python terms_demo.py 运行,输出如下:
训练集样本数: 6测试集样本数: 2[监督学习视角] 训练集特征 X_train:特征 ['乌黑', '硬挺', '清脆'] -> 标记(好瓜?) 0特征 ['浅白', '硬挺', '沉闷'] -> 标记(好瓜?) 0特征 ['青绿', '硬挺', '清脆'] -> 标记(好瓜?) 0特征 ['青绿', '稍蜷', '浊响'] -> 标记(好瓜?) 1特征 ['青绿', '蜷缩', '浊响'] -> 标记(好瓜?) 1特征 ['乌黑', '蜷缩', '浊响'] -> 标记(好瓜?) 1[无监督学习视角] 只看特征,没有标记(适合做聚类):特征 ['乌黑', '硬挺', '清脆']特征 ['浅白', '硬挺', '沉闷']特征 ['青绿', '硬挺', '清脆']特征 ['青绿', '稍蜷', '浊响']特征 ['青绿', '蜷缩', '浊响']特征 ['乌黑', '蜷缩', '浊响']
这段代码直观展示了:同样一批西瓜数据,加上标记就是「分类」用的监督学习数据,去掉标记就是「聚类」用的无监督学习数据;而划出来的「测试集」正是用来检验模型泛化能力的那批新样本。