7.2. 真实世界数据集#

scikit-learn 提供工具来加载更大的数据集,并在必要时下载它们。

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

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

从 AT&T 加载奥利维蒂人脸数据集(分类)。

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

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

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

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

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, ...])

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

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

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

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

加载 kddcup99 数据集(分类)。

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

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

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

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

7.2.1. 奥利维蒂人脸数据集#

该数据集包含一组人脸图像,这些图像是在 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 实验室剑桥分部的版权。

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

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

该模块包含两个加载器。第一个加载器,sklearn.datasets.fetch_20newsgroups,返回原始文本列表,这些文本可以馈送到文本特征提取器,例如 CountVectorizer,并使用自定义参数来提取特征向量。第二个加载器,sklearn.datasets.fetch_20newsgroups_vectorized,返回可直接使用的特征,即不需要使用特征提取器。

数据集特征

类别

20

样本总数

18846

维数

1

特征

文本

Usage#

The sklearn.datasets.fetch_20newsgroups function is a data fetching / caching functions that downloads the data archive from the original 20 newsgroups website, extracts the archive contents in the ~/scikit_learn_data/20news_home folder and calls the sklearn.datasets.load_files on either the training or testing set folder, or both of them:

>>> 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']

The real data lies in the filenames and target attributes. The target attribute is the integer index of the category:

>>> 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])

It is possible to load only a sub-selection of the categories by passing the list of the categories to load to the sklearn.datasets.fetch_20newsgroups function:

>>> 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])
Converting text to vectors#

In order to feed predictive or clustering models with the text data, one first need to turn the text into vectors of numerical values suitable for statistical analysis. This can be achieved with the utilities of the sklearn.feature_extraction.text as demonstrated in the following example that extract TF-IDF vectors of unigram tokens from a subset of 20news:

>>> 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)

The extracted TF-IDF vectors are very sparse, with an average of 159 non-zero components by sample in a more than 30000-dimensional space (less than .5% non-zero features):

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

sklearn.datasets.fetch_20newsgroups_vectorized is a function which returns ready-to-use token counts features instead of file names.

Filtering text for more realistic training#

It is easy for a classifier to overfit on particular things that appear in the 20 Newsgroups data, such as newsgroup headers. Many classifiers achieve very high F-scores, but their results would not generalize to other documents that aren’t from this window of time.

For example, let’s look at the results of a multinomial Naive Bayes classifier, which is fast to train and achieves a decent 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...

(The example Classification of text documents using sparse features shuffles the training and test data, instead of segmenting by time, and in that case multinomial Naive Bayes gets a much higher F-score of 0.88. Are you suspicious yet of what’s going on inside this classifier?)

Let’s take a look at what the most informative features are:

>>> 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

You can now see many things that these features have overfit to:

  • Almost every group is distinguished by whether headers such as NNTP-Posting-Host: and Distribution: appear more or less often.

  • Another significant feature involves whether the sender is affiliated with a university, as indicated either by their headers or their signature.

  • The word “article” is a significant feature, based on how often people quote previous posts like this: “In article [article ID], [name] <[e-mail address]> wrote:”

  • Other features match the names and e-mail addresses of particular people who were posting at the time.

With such an abundance of clues that distinguish newsgroups, the classifiers barely have to identify topics from text at all, and they all perform at the same high level.

For this reason, the functions that load 20 Newsgroups data provide a parameter called remove, telling it what kinds of information to strip out of each file. remove should be a tuple containing any subset of ('headers', 'footers', 'quotes'), telling it to remove headers, signature blocks, and quotation blocks respectively.

>>> 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...

This classifier lost over a lot of its F-score, just because we removed metadata that has little to do with topic classification. It loses even more if we also strip this metadata from the training data:

>>> 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...

Some other classifiers cope better with this harder version of the task. Try the Sample pipeline for text feature extraction and evaluation example with and without the remove option to compare the results.

示例

7.2.3. 野外标记人脸的人脸识别数据集#

该数据集是互联网上收集的名人 JPEG 图片的集合,所有详细信息都可以在官方网站上找到

http://vis-www.cs.umass.edu/lfw/

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

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

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

数据集特征

类别

5749

样本总数

13233

维数

5828

特征

实数,介于 0 和 255 之间

用法#

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

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

>>> 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 集、开发 test 集和评估 10_folds 集,用于使用 10 折交叉验证方案计算性能指标。

参考文献

示例

7.2.4. 森林覆盖类型#

该数据集中的样本对应于美国森林中 30×30 米的森林斑块,这些斑块是为预测每个斑块的覆盖类型(即树木的主要物种)而收集的。共有七种覆盖类型,这使得它成为一个多类分类问题。每个样本有 54 个特征,在 数据集主页 上进行了描述。一些特征是布尔指示器,而另一些特征是离散或连续测量值。

数据集特征

类别

7

样本总数

581012

维数

54

特征

整数

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

7.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。

参考文献

7.2.6. Kddcup 99 数据集#

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

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

  • 在观察结果中占少数。

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

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

  • SF 是根据 [3] 获得的,通过简单地选择属性 logged_in 为正的数据,从而专注于入侵攻击,这使得攻击比例达到 0.3%。

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

一般 KDD 结构

样本总数

4898431

维数

41

特征

离散(int)或连续(float)

目标

str,‘normal.’ 或异常类型的名称

SA 结构

样本总数

976158

维数

41

特征

离散(int)或连续(float)

目标

str,‘normal.’ 或异常类型的名称

SF 结构

样本总数

699691

维数

4

特征

离散(int)或连续(float)

目标

str,‘normal.’ 或异常类型的名称

http 结构

样本总数

619052

维数

3

特征

离散(int)或连续(float)

目标

str,‘normal.’ 或异常类型的名称

smtp 结构

样本总数

95373

维数

3

特征

离散(int)或连续(float)

目标

str,‘normal.’ 或异常类型的名称

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

参考文献

7.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 (1997) 291-297

7.2.8. 物种分布数据集#

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

  • “Microryzomys minutus”,也称为森林小鼠,是一种生活在秘鲁、哥伦比亚、厄瓜多尔、秘鲁和委内瑞拉的啮齿动物。

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

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

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

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

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

参考文献