8.2. 真实世界数据集#

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

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

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

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

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

加载 20 newsgroups 数据集(分类)的文件名和数据。

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

加载和向量化 20 newsgroups 数据集(分类)。

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

加载 Labeled Faces in the Wild (LFW) 人物数据集(分类)。

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

加载 Labeled Faces in the Wild (LFW) 对数据集(分类)。

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

加载 covertype 数据集(分类)。

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 个不同对象,每个对象有 10 张不同的图像。对于某些对象,图像是在不同时间拍摄的,光照、面部表情(睁眼/闭眼,微笑/不微笑)和面部细节(戴眼镜/不戴眼镜)各不相同。所有图像均以深色均匀背景为背景拍摄,拍摄对象处于直立、正面位置(允许一些侧向移动)。

数据集特征

类别数

40

样本总数

400

维度

4096

特征值范围

实数,介于 0 和 1 之间

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

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

原始数据集的分辨率为 92x112,而这里提供的版本包含 64x64 图像。

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

8.2.2. 20 newsgroups 文本数据集#

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

此模块包含两个加载器。第一个加载器 sklearn.datasets.fetch_20newsgroups 返回原始文本列表,可以将其提供给文本特征提取器(例如 CountVectorizer)并使用自定义参数来提取特征向量。第二个加载器 sklearn.datasets.fetch_20newsgroups_vectorized 返回即用型特征,即无需使用特征提取器。

数据集特征

类别数

20

样本总数

18846

维度

1

特征值范围

text

用法#

sklearn.datasets.fetch_20newsgroups 函数是一个数据获取/缓存函数,它从原始 20 newsgroups 网站下载数据档案,将档案内容解压缩到 ~/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 Newsgroups 数据中出现的特定内容(例如新闻组标题)进行过拟合。许多分类器获得了非常高的 F-score,但它们的结果无法推广到来自其他时间段的文档。

例如,让我们看看多项式朴素贝叶斯分类器的结果,它训练速度快且 F-score 尚可:

>>> 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-score 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”这个词是一个重要特征,它是基于人们引用先前帖子的频率,例如:“In article [article ID], [name] <[e-mail address]> wrote:”

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

由于有如此多的线索来区分新闻组,分类器几乎不必从文本中识别主题,它们的性能都处于相同的高水平。

因此,加载 20 Newsgroups 数据的函数提供了一个名为 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-score,仅仅是因为我们删除了与主题分类关系不大的元数据。如果我们也从训练数据中剥离这些元数据,它会损失更多。

>>> 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 月,“在乔治·弗洛伊德逝世以及一场关于种族和殖民主义的全国性反思引发的数月讨论之后,克利夫兰印第安人队决定更改队名。”球队老板保罗·多兰“明确表示球队不会将其非正式昵称——Tribe(部落)——作为新的队名。”多兰说:“这不会是印第安人队名的一半退让。我们不会使用以美洲原住民为主题的队名。”

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

建议

  • 在评估 20 Newsgroups 数据上的文本分类器时,您应该剥离与新闻组相关的元数据。在 scikit-learn 中,您可以通过设置 remove=('headers', 'footers', 'quotes') 来实现。F-score 会降低,因为它更贴近现实情况。

  • 这个文本数据集包含的数据可能不适合某些 NLP 应用。上面的“数据注意事项”部分列举了一个例子。在 NLP 中使用当前文本数据集进行句子补全、聚类和其他应用时,挑战在于具有文化偏见和煽动性的文本会传播偏见。在使用数据集时应考虑这一点,审查输出,并记录偏见。

示例

8.2.3. “野外标记人脸 (Labeled Faces in the Wild)” 人脸识别数据集#

该数据集是从互联网上收集的名人 JPEG 图片集,详情可在 Kaggle 网站上找到:

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

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

另一种任务,人脸识别(Face Recognition)或人脸辨识(Face Identification)是:给定一张未知人物的面部图片,通过参考先前见过的已识别人物图片库来识别此人的姓名。

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

数据集特征

类别数

5749

样本总数

13233

维度

5828

特征值范围

实数,介于 0 和 255 之间

用法#

scikit-learn 提供了两个加载器,它们会自动下载、缓存、解析元数据文件、解码 jpeg 并将感兴趣的切片转换为内存映射的 numpy 数组。该数据集大小超过 200 MB。第一次加载通常需要几分钟以上才能将 jpeg 文件的相关部分完全解码为 numpy 数组。如果数据集已加载一次,则后续加载时间不到 200ms,因为它使用 joblib 将内存映射版本 memoized 到 ~/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 个子集:开发 train set、开发 test set 和用于使用 10 折交叉验证方案计算性能指标的评估 10_folds set。

References

示例

8.2.4. 森林覆盖类型数据集#

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

数据集特征

类别数

7

样本总数

581012

维度

54

特征值范围

整数

sklearn.datasets.fetch_covtype 将加载 covertype 数据集;它返回一个类似字典的“Bunch”对象,其中特征矩阵位于 data 成员中,目标值位于 target 中。如果可选参数 'as_frame' 设置为 'True',它将以 pandas DataFrame 的形式返回 datatarget,并且还会有一个额外的成员 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 识别,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。

References

8.2.6. Kddcup 99 数据集#

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

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

  • 在观测中占少数)的无监督异常检测。

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

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

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

  • http 和 smtp 是 SF 的两个子集,对应于第三个特征等于“http”(分别对应“smtp”)。

KDD 一般结构

样本总数

4898431

维度

41

特征值范围

离散(int)或连续(float)

目标值

字符串,“normal.” 或异常类型的名称

SA 结构

样本总数

976158

维度

41

特征值范围

离散(int)或连续(float)

目标值

字符串,“normal.” 或异常类型的名称

SF 结构

样本总数

699691

维度

4

特征值范围

离散(int)或连续(float)

目标值

字符串,“normal.” 或异常类型的名称

http 结构

样本总数

619052

维度

3

特征值范围

离散(int)或连续(float)

目标值

字符串,“normal.” 或异常类型的名称

smtp 结构

样本总数

95373

维度

3

特征值范围

离散(int)或连续(float)

目标值

字符串,“normal.” 或异常类型的名称

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

References

8.2.7. California Housing 数据集#

数据集特征

实例数:

20640

属性数:

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

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

  • HouseAge 街区组的房屋年龄中位数

  • AveRooms 每户的平均房间数

  • AveBedrms 每户的平均卧室数

  • Population 街区组的人口数

  • AveOccup 平均家庭成员数

  • Latitude 街区组的纬度

  • Longitude 街区组的经度

缺失属性值:

None

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

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

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

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

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

References

  • Pace, R. Kelley and Ronald Barry, Sparse Spatial Autoregressions, Statistics and Probability Letters, 33:291-297, 1997.

8.2.8. 物种分布数据集#

该数据集表示两个物种在中南美洲的地理分布。这两个物种是:

该数据集不是一个典型的数据集,因为它不返回包含属性 datatargetBunch。相反,我们有允许创建不同物种“密度”图的信息。

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

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

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

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

References

示例