8.2. 真实世界数据集#

scikit-learn 提供了加载大型数据集的工具,如有必要,会自动下载。

可以使用以下函数加载它们

fetch_olivetti_faces(*[, data_home, ...])

从 AT&T 加载 Olivetti 人脸数据集(分类)。

fetch_20newsgroups(*[, data_home, subset, ...])

从 20 个新闻组数据集加载文件名和数据(分类)。

fetch_20newsgroups_vectorized(*[, subset, ...])

加载并向量化 20 个新闻组数据集(分类)。

fetch_lfw_people(*[, data_home, funneled, ...])

加载野外标记人脸 (LFW) 数据集(分类)。

fetch_lfw_pairs(*[, subset, data_home, ...])

加载野外标记人脸 (LFW) 对数据集(分类)。

fetch_covtype(*[, data_home, ...])

加载森林覆盖类型数据集(分类)。

fetch_rcv1(*[, data_home, subset, ...])

加载 RCV1 多标签数据集(分类)。

fetch_kddcup99(*[, subset, data_home, ...])

加载 kddcup99 数据集(分类)。

fetch_california_housing(*[, data_home, ...])

加载加州住房数据集(回归)。

fetch_species_distributions(*[, data_home, ...])

加载来自 Phillips 等人的物种分布数据集。

8.2.1. Olivetti 人脸数据集#

此数据集包含 1992 年 4 月至 1994 年 4 月在 AT&T 剑桥实验室拍摄的一组人脸图像。`sklearn.datasets.fetch_olivetti_faces` 函数是一个数据获取/缓存函数,用于从 AT&T 下载数据存档。

如原始网站所述

每个 40 个不同主题都有十张不同的图像。对于某些主题,图像是在不同时间拍摄的,光照、面部表情(睁眼/闭眼、微笑/不微笑)和面部细节(戴眼镜/不戴眼镜)各不相同。所有图像均在黑暗均匀的背景下拍摄,主题人物处于直立、正面位置(允许一些侧向移动)。

数据集特性

类别

40

样本总数

400

维度

4096

特征

实数,介于 0 和 1 之间

图像被量化为 256 个灰度级并存储为无符号 8 位整数;加载器会将其转换为 [0, 1] 区间内的浮点值,这对于许多算法来说更容易处理。

此数据库的“目标”是一个介于 0 到 39 之间的整数,表示图中人物的身份;然而,由于每个类别只有 10 个示例,这个相对较小的数据集从无监督或半监督的角度来看更有趣。

原始数据集由 92 x 112 图像组成,而此处提供的版本由 64x64 图像组成。

使用这些图像时,请注明来源:AT&T 剑桥实验室。

8.2.2. 20 个新闻组文本数据集#

20 个新闻组数据集包含约 18000 篇关于 20 个主题的新闻组帖子,分为两个子集:一个用于训练(或开发),另一个用于测试(或性能评估)。训练集和测试集之间的划分是基于特定日期之前和之后发布的帖子。

此模块包含两个加载器。第一个是 sklearn.datasets.fetch_20newsgroups,它返回原始文本列表,这些文本可以作为输入传递给文本特征提取器(例如 CountVectorizer),并使用自定义参数来提取特征向量。第二个是 sklearn.datasets.fetch_20newsgroups_vectorized,它返回可直接使用的特征,即不需要使用特征提取器。

数据集特性

类别

20

样本总数

18846

维度

1

特征

文本

用法#

sklearn.datasets.fetch_20newsgroups 函数是一个数据获取/缓存函数,它从原始的 20 个新闻组网站下载数据存档,将存档内容解压到 ~/scikit_learn_data/20news_home 文件夹,并对训练集或测试集文件夹(或两者)调用 sklearn.datasets.load_files

>>> from sklearn.datasets import fetch_20newsgroups
>>> newsgroups_train = fetch_20newsgroups(subset='train')

>>> from pprint import pprint
>>> pprint(list(newsgroups_train.target_names))
['alt.atheism',
 'comp.graphics',
 'comp.os.ms-windows.misc',
 'comp.sys.ibm.pc.hardware',
 'comp.sys.mac.hardware',
 'comp.windows.x',
 'misc.forsale',
 'rec.autos',
 'rec.motorcycles',
 'rec.sport.baseball',
 'rec.sport.hockey',
 'sci.crypt',
 'sci.electronics',
 'sci.med',
 'sci.space',
 'soc.religion.christian',
 'talk.politics.guns',
 'talk.politics.mideast',
 'talk.politics.misc',
 'talk.religion.misc']

实际数据位于 filenamestarget 属性中。`target` 属性是类别的整数索引。

>>> newsgroups_train.filenames.shape
(11314,)
>>> newsgroups_train.target.shape
(11314,)
>>> newsgroups_train.target[:10]
array([ 7,  4,  4,  1, 14, 16, 13,  3,  2,  4])

可以通过将要加载的类别列表传递给 sklearn.datasets.fetch_20newsgroups 函数来仅加载类别的一个子集。

>>> cats = ['alt.atheism', 'sci.space']
>>> newsgroups_train = fetch_20newsgroups(subset='train', categories=cats)

>>> list(newsgroups_train.target_names)
['alt.atheism', 'sci.space']
>>> newsgroups_train.filenames.shape
(1073,)
>>> newsgroups_train.target.shape
(1073,)
>>> newsgroups_train.target[:10]
array([0, 1, 1, 1, 0, 1, 1, 0, 0, 0])
将文本转换为向量#

为了将文本数据输入到预测或聚类模型中,首先需要将文本转换为适合统计分析的数值向量。这可以通过 sklearn.feature_extraction.text 中的工具实现,如下面的示例所示,该示例从 20news 的一个子集中提取一元词符的 TF-IDF 向量。

>>> from sklearn.feature_extraction.text import TfidfVectorizer
>>> categories = ['alt.atheism', 'talk.religion.misc',
...               'comp.graphics', 'sci.space']
>>> newsgroups_train = fetch_20newsgroups(subset='train',
...                                       categories=categories)
>>> vectorizer = TfidfVectorizer()
>>> vectors = vectorizer.fit_transform(newsgroups_train.data)
>>> vectors.shape
(2034, 34118)

提取的 TF-IDF 向量非常稀疏,在超过 30000 维的空间中,每个样本平均只有 159 个非零分量(非零特征少于 0.5%)。

>>> vectors.nnz / float(vectors.shape[0])
159.01327...

sklearn.datasets.fetch_20newsgroups_vectorized 是一个函数,它返回可直接使用的词符计数特征,而不是文件名。

过滤文本以进行更真实的训练#

分类器很容易对 20 个新闻组数据中出现的特定内容(如新闻组标题)过拟合。许多分类器都能达到非常高的 F 分数,但它们的结果不会推广到不属于此时间段的其他文档。

例如,我们来看看多项式朴素贝叶斯分类器的结果,它训练速度快且 F 分数可观。

>>> from sklearn.naive_bayes import MultinomialNB
>>> from sklearn import metrics
>>> newsgroups_test = fetch_20newsgroups(subset='test',
...                                      categories=categories)
>>> vectors_test = vectorizer.transform(newsgroups_test.data)
>>> clf = MultinomialNB(alpha=.01)
>>> clf.fit(vectors, newsgroups_train.target)
MultinomialNB(alpha=0.01, class_prior=None, fit_prior=True)

>>> pred = clf.predict(vectors_test)
>>> metrics.f1_score(newsgroups_test.target, pred, average='macro')
0.88213...

(示例使用稀疏特征对文本文档进行分类将训练和测试数据打乱,而不是按时间分割,在这种情况下,多项式朴素贝叶斯获得了更高的 F 分数 0.88。你是否怀疑这个分类器内部发生了什么?)

让我们看看最有信息量的特征是什么

>>> import numpy as np
>>> def show_top10(classifier, vectorizer, categories):
...     feature_names = vectorizer.get_feature_names_out()
...     for i, category in enumerate(categories):
...         top10 = np.argsort(classifier.coef_[i])[-10:]
...         print("%s: %s" % (category, " ".join(feature_names[top10])))
...
>>> show_top10(clf, vectorizer, newsgroups_train.target_names)
alt.atheism: edu it and in you that is of to the
comp.graphics: edu in graphics it is for and of to the
sci.space: edu it that is in and space to of the
talk.religion.misc: not it you in is that and to of the

你现在可以看到这些特征过拟合的许多内容

  • 几乎每个组都通过标题(如 NNTP-Posting-Host:Distribution:)出现的频率高低来区分。

  • 另一个重要特征是发送者是否隶属于大学,这由其标题或签名显示。

  • “article”这个词是一个重要特征,基于人们引用以前帖子的频率,例如:“在文章 [文章 ID] 中,[姓名] <[电子邮件地址]> 写道:”

  • 其他特征与当时发帖的特定人员的姓名和电子邮件地址匹配。

由于有如此多的线索可以区分新闻组,分类器几乎不必从文本中识别主题,它们都达到了同样的高水平表现。

因此,加载 20 个新闻组数据的函数提供了一个名为 remove 的参数,用于指定要从每个文件中剥离的信息类型。**remove** 应该是一个元组,包含 ('headers', 'footers', 'quotes') 的任意子集,分别表示删除标题、签名块和引用块。

>>> newsgroups_test = fetch_20newsgroups(subset='test',
...                                      remove=('headers', 'footers', 'quotes'),
...                                      categories=categories)
>>> vectors_test = vectorizer.transform(newsgroups_test.data)
>>> pred = clf.predict(vectors_test)
>>> metrics.f1_score(pred, newsgroups_test.target, average='macro')
0.77310...

这个分类器损失了大量的 F 分数,仅仅因为我们删除了与主题分类关系不大的元数据。如果我们也从训练数据中剥离这些元数据,它会损失更多。

>>> newsgroups_train = fetch_20newsgroups(subset='train',
...                                       remove=('headers', 'footers', 'quotes'),
...                                       categories=categories)
>>> vectors = vectorizer.fit_transform(newsgroups_train.data)
>>> clf = MultinomialNB(alpha=.01)
>>> clf.fit(vectors, newsgroups_train.target)
MultinomialNB(alpha=0.01, class_prior=None, fit_prior=True)
>>> vectors_test = vectorizer.transform(newsgroups_test.data)
>>> pred = clf.predict(vectors_test)
>>> metrics.f1_score(newsgroups_test.target, pred, average='macro')
0.76995...

其他一些分类器更好地应对了这个更困难的任务版本。尝试文本特征提取和评估的样本管道示例,分别使用和不使用 remove 选项来比较结果。

数据考量

克利夫兰印第安人队是美国俄亥俄州克利夫兰市的一支大联盟棒球队。2020年12月有报道称,“在乔治·弗洛伊德去世引发了数月讨论以及全国对种族和殖民主义的反思之后,克利夫兰印第安人队已决定更改其队名。”球队老板保罗·多兰“明确表示,球队不会将其非正式昵称——‘部落’——作为新的队名。”多兰说,“这不会是与‘印第安人’队名半步之遥的改变,我们将不会使用与美洲原住民相关的主题名称。”

https://www.mlb.com/news/cleveland-indians-team-name-change

建议

  • 在评估 20 个新闻组数据上的文本分类器时,应剥离新闻组相关的元数据。在 scikit-learn 中,可以通过设置 remove=('headers', 'footers', 'quotes') 来实现。F 分数会降低,因为这样更真实。

  • 此文本数据集包含可能不适用于某些自然语言处理 (NLP) 应用的数据。例如,如上文“数据考量”部分所述。在 NLP 中使用当前文本数据集进行句子补全、聚类和其他应用面临的挑战是,具有文化偏见和煽动性的文本会传播偏见。在使用数据集、审查输出时应考虑这一点,并应记录偏见。

示例

8.2.3. 野外标记人脸 (LFW) 人脸识别数据集#

此数据集是在互联网上收集的名人 JPEG 图片集,详细信息可在 Kaggle 网站上找到

https://www.kaggle.com/datasets/jessicali9530/lfw-dataset

每张图片都以单个人脸为中心。典型的任务称为人脸验证:给定一对两张图片,二分类器必须预测这两张图片是否来自同一个人。

另一个任务是人脸识别或人脸辨识:给定一个未知人物的面部图片,通过参考一个已识别人物的先前见过图片库来识别该人物的姓名。

人脸验证和人脸识别都是通常在经过人脸检测训练的模型输出上执行的任务。最流行的人脸检测模型称为 Viola-Jones,并在 OpenCV 库中实现。LFW 人脸是从各种在线网站通过此人脸检测器提取的。

数据集特性

类别

5749

样本总数

13233

维度

5828

特征

实数,介于 0 和 255 之间

用法#

scikit-learn 提供了两个加载器,它们将自动下载、缓存、解析元数据文件、解码 JPEG 并将感兴趣的切片转换为内存映射的 NumPy 数组。此数据集大小超过 200 MB。首次加载通常需要几分钟以上才能将 JPEG 文件的相关部分完全解码为 NumPy 数组。如果数据集已加载一次,则后续加载时间将少于 200 毫秒,因为它使用 joblib 将内存映射版本缓存到磁盘上的 ~/scikit_learn_data/lfw_home/ 文件夹中。

第一个加载器用于人脸识别任务:一个多类别分类任务(因此是监督学习)

>>> from sklearn.datasets import fetch_lfw_people
>>> lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)

>>> for name in lfw_people.target_names:
...     print(name)
...
Ariel Sharon
Colin Powell
Donald Rumsfeld
George W Bush
Gerhard Schroeder
Hugo Chavez
Tony Blair

默认切片是围绕人脸的矩形形状,去除了大部分背景。

>>> lfw_people.data.dtype
dtype('float32')

>>> lfw_people.data.shape
(1288, 1850)

>>> lfw_people.images.shape
(1288, 50, 37)

1140 张人脸中的每一张都被分配到 target 数组中的一个单一人员 ID。

>>> lfw_people.target.shape
(1288,)

>>> list(lfw_people.target[:10])
[5, 6, 3, 1, 0, 1, 3, 4, 3, 0]

第二个加载器通常用于人脸验证任务:每个样本是一对属于或不属于同一人的两张图片。

>>> from sklearn.datasets import fetch_lfw_pairs
>>> lfw_pairs_train = fetch_lfw_pairs(subset='train')

>>> list(lfw_pairs_train.target_names)
['Different persons', 'Same person']

>>> lfw_pairs_train.pairs.shape
(2200, 2, 62, 47)

>>> lfw_pairs_train.data.shape
(2200, 5828)

>>> lfw_pairs_train.target.shape
(2200,)

对于 sklearn.datasets.fetch_lfw_peoplesklearn.datasets.fetch_lfw_pairs 函数,都可以通过传递 color=True 来获取包含 RGB 颜色通道的额外维度,在这种情况下,形状将是 (2200, 2, 62, 47, 3)

sklearn.datasets.fetch_lfw_pairs 数据集分为 3 个子集:开发训练集、开发测试集以及一个用于使用 10 折交叉验证方案计算性能指标的评估 10_folds 集。

参考文献

示例

8.2.4. 森林覆盖类型#

此数据集中的样本对应于美国 30×30 米的森林斑块,收集目的是预测每个斑块的覆盖类型,即优势树种。共有七种覆盖类型,这使其成为一个多类别分类问题。每个样本有 54 个特征,在数据集主页上有所描述。其中一些特征是布尔指示符,而另一些是离散或连续测量值。

数据集特性

类别

7

样本总数

581012

维度

54

特征

整数

sklearn.datasets.fetch_covtype 将加载 covertype 数据集;它返回一个类似字典的“Bunch”对象,其中特征矩阵在 data 成员中,目标值在 target 中。如果可选参数“as_frame”设置为“True”,它将把 datatarget 返回为 pandas 数据帧,并且还会有一个额外的 frame 成员。如有必要,数据集将从网络下载。

8.2.5. RCV1 数据集#

路透社语料库第一卷 (RCV1) 是路透社有限公司为研究目的提供的超过 800,000 篇人工分类新闻报道的档案。该数据集在[1]中 有详细描述。

数据集特性

类别

103

样本总数

804414

维度

47236

特征

实数,介于 0 和 1 之间

sklearn.datasets.fetch_rcv1 将加载以下版本:RCV1-v2,向量,完整集,主题多标签。

>>> from sklearn.datasets import fetch_rcv1
>>> rcv1 = fetch_rcv1()

它返回一个类似字典的对象,具有以下属性

data: 特征矩阵是一个 scipy CSR 稀疏矩阵,包含 804414 个样本和 47236 个特征。非零值包含余弦归一化、对数 TF-IDF 向量。在[1]中提出了一个近似按时间顺序的划分:前 23149 个样本是训练集。后 781265 个样本是测试集。这遵循官方的 LYRL2004 时间顺序划分。该数组有 0.16% 的非零值。

>>> rcv1.data.shape
(804414, 47236)

target: 目标值存储在一个 scipy CSR 稀疏矩阵中,包含 804414 个样本和 103 个类别。每个样本在其所属类别中值为 1,在其他类别中值为 0。该数组有 3.15% 的非零值。

>>> rcv1.target.shape
(804414, 103)

sample_id: 每个样本可以通过其 ID 识别,范围(有间隔)从 2286 到 810596。

>>> rcv1.sample_id[:3]
array([2286, 2287, 2288], dtype=uint32)

target_names: 目标值是每个样本的主题。每个样本属于至少一个主题,最多可属于 17 个主题。共有 103 个主题,每个主题由一个字符串表示。它们在语料库中的频率跨越五个数量级,从 'GMIL' 的 5 次出现到 'CCAT' 的 381327 次。

>>> rcv1.target_names[:3].tolist()  
['E11', 'ECAT', 'M11']

如有必要,数据集将从 rcv1 主页下载。压缩后的大小约为 656 MB。

参考文献

8.2.6. KDD Cup '99 数据集#

KDD Cup '99 数据集是通过处理 1998 年 DARPA 入侵检测系统 (IDS) 评估数据集(由麻省理工学院林肯实验室创建[2])的 tcpdump 部分而生成的。人工数据(在数据集主页上描述)是使用封闭网络和手动注入攻击生成的,以在正常活动背景下产生大量不同类型的攻击。由于最初目标是为监督学习算法生成一个大型训练集,其中包含大量(80.1%)的异常数据,这在现实世界中是不切实际的,并且不适用于旨在检测“异常”数据(即)的无监督异常检测,

  • 与正常数据在性质上不同

  • 在观测值中占少数。

因此,我们将 KDD 数据集转换为两个不同的数据集:SA 和 SF。

  • SA 是通过简单地选择所有正常数据和一小部分异常数据获得的,从而使异常比例达到 1%。

  • SF 则如[3]中 所述,通过简单地选择 logged_in 属性为正的数据获得,从而侧重于入侵攻击,攻击比例为 0.3%。

  • http 和 smtp 是 SF 的两个子集,分别对应第三个特征等于 ‘http’(或 ‘smtp’)的情况。

通用 KDD 结构

样本总数

4898431

维度

41

特征

离散(整数)或连续(浮点数)

目标

字符串,‘正常’ 或异常类型的名称

SA 结构

样本总数

976158

维度

41

特征

离散(整数)或连续(浮点数)

目标

字符串,‘正常’ 或异常类型的名称

SF 结构

样本总数

699691

维度

4

特征

离散(整数)或连续(浮点数)

目标

字符串,‘正常’ 或异常类型的名称

http 结构

样本总数

619052

维度

3

特征

离散(整数)或连续(浮点数)

目标

字符串,‘正常’ 或异常类型的名称

smtp 结构

样本总数

95373

维度

3

特征

离散(整数)或连续(浮点数)

目标

字符串,‘正常’ 或异常类型的名称

sklearn.datasets.fetch_kddcup99 将加载 kddcup99 数据集;它返回一个类似字典的对象,其中特征矩阵在 data 成员中,目标值在 target 中。“as_frame”可选参数将 data 转换为 pandas DataFrame,将 target 转换为 pandas Series。如有必要,数据集将从网络下载。

参考文献

8.2.7. 加州住房数据集#

数据集特性

实例数量:

20640

属性数量:

8 个数值型预测属性和目标

属性信息:
  • MedInc 街区组中位数收入

  • HouseAge 街区组中位数房龄

  • AveRooms 每户平均房间数

  • AveBedrms 每户平均卧室数

  • Population 街区组人口

  • AveOccup 每户平均成员数

  • Latitude 街区组纬度

  • Longitude 街区组经度

缺失属性值:

此数据集来自 StatLib 存储库。https://www.dcc.fc.up.pt/~ltorgo/Regression/cal_housing.html

目标变量是加州地区房屋价值的中位数,以数十万美元($100,000)表示。

此数据集源自 1990 年美国人口普查,每行代表一个普查街区组。街区组是美国人口普查局发布样本数据的最小地理单位(一个街区组通常有 600 到 3,000 人)。

一个家庭是指居住在同一房屋内的一群人。由于此数据集中的平均房间数和卧室数是按户提供的,因此对于家庭数量少但空置房屋多的街区组(例如度假村),这些列的值可能会出人意料地大。

可以使用 sklearn.datasets.fetch_california_housing 函数下载/加载它。

参考文献

  • Pace, R. Kelley 和 Ronald Barry, 《稀疏空间自回归》,统计与概率快报,33:291-297, 1997。

8.2.8. 物种分布数据集#

此数据集代表了中美洲和南美洲两种物种的地理分布。这两种物种是

此数据集并非典型数据集,因为它不返回包含 datatarget 属性的 Bunch 对象。相反,我们拥有的信息允许创建不同物种的“密度”图。

地图网格可以使用 x_left_lower_cornery_left_lower_cornerNxNygrid_size 属性构建,它们分别对应于网格左下角的 x 和 y 坐标、沿 x 轴和 y 轴的点数以及网格上的步长大小。

网格中每个位置的密度包含在 coverage 属性中。

最后,traintest 属性包含关于物种在特定位置的信息。

该数据集由 Phillips 等人提供 (2006)。

参考文献

示例