Train / Dev / Test sets

假设这是训练数据,我用一个长方形表示,我们通常会将这些数据划分成几部分

  • 训练集: 训练模型
  • 验证集(dev set):选定模型
  • 测试集:评估模型

在机器学习发展的小数据量时代,常见做法是将所有数据三七分,就是人们常说的 70%训练集,30%测试集。如果明确设置了验证集,也可以按照 60%训练集,20%验证集和 20%测试集来划分。这是前几年机器学习领域普遍认可的最好的实践方法。

如果只有 100 条,1000 条或者 1 万条数据,那么上述比例划分是非常合理的。

但是在大数据时代,我们现在的数据量可能是百万级别,那么验证集和测试集占数据总量的比例会趋向于变得更小。因为验证集的目的就是验证不同的算法,检验哪种算法更有效,因此,验证集只要足够大到能评估不同的算法,比如 2 个甚至 10 个不同算法,并迅速判断出哪种算法更有效。我们可能不需要拿出 20%的数据作为验证集。

比如我们有 100 万条数据,那么取 1 万条数据便足以进行评估,找出其中表现最好的 1-2 种算法。同样地,根据最终选择的分类器,测试集的主要目的是正确评估分类器的性能,所以,如果拥有百万数据,我们只需要 1000 条数据,便足以评估单个分类器,并且准确评估该分类器的性能。假设我们有 100 万条数据,其中 1 万条作为验证集,1 万条作为测试集,100 万里取 1 万,比例是 1%,即:训练集占 98%,验证集和测试集各占 1%。对于数据量过百万的应用,训练集可以占到 99.5%,验证和测试集各占 0.25%,或者验证集占 0.4%,测试集占 0.1%。

要确保验证集和测试集的数据来自同一分布,关于这个问题我也会多讲一些。因为你们要用验证集来评估不同的模型,尽可能地优化性能。如果验证集和测试集来自同一个分布就会很好。

最后一点,就算没有测试集也不要紧,测试集的目的是对最终所选定的神经网络系统做出无偏估计,如果不需要无偏估计,也可以不设置测试集。所以如果只有验证集,没有测试集,我们要做的就是,在训练集上训练,尝试不同的模型框架,在验证集上评估这些模型,然后迭代并选出适用的模型。因为验证集中已经涵盖测试集数据,其不再提供无偏性能评估。当然,如果你不需要无偏估计,那就再好不过了。


划分方法

留出法

直接将数据集划分为两个互斥集合,注意保持数据分布的一致性(比如比例相似)。保留类别比例的采样方式又叫分层采样(stratified sampling)。举个例子,原始数据集有 100 个样本,假设训练集占 70 个,验证集占 30 个。若训练集中正例反例各 35 个,也即比例为1:1,那么验证集中就应该正例反例个 15 个,同样保持1:1的比例。当然,这个比例最好还是遵循原始数据集中数据的分布规律。

单独一次留出法的结果往往不可靠,一般是进行多次随机划分,然后取各次评估的平均值作为评估结果。

留出法最大的缺点就是要进行划分,当训练集占的比例较大时,模型可以更准确地刻画原始数据集的特征,但是因为验证集较小,评估的结果往往不稳定也不准确;当训练集占的比例较小时,训练出的模型又不能充分学习到原始数据集的特征,评估结果可信度不高。这个问题没有完美的解决方案,一般取数据集2/3~4/5的样本作为训练集,余下的作为验证集。

交叉验证

又称为k 折交叉验证(k-fold cross validation),将数据集划分为 k 个互斥子集。每次使用 k-1 个子集的并集作为训练集,余下的一个子集作为验证集,这就构成了 k 组训练/验证集,从而可以进行 k 次训练和验证。最终取 k 次验证的均值作为评估结果。常用的 k 值包括 5,10,20。类似于留出法,因为存在多种划分 k 个子集的方式,为了减少因不同的样本划分而引入的差别,需要进行多次 k 折交叉验证。例如 10 次 10 折交叉验证,指的是进行了总计 100 次训练和 100 次评估。特别地,令 k=数据集样本数的交叉验证称为留一法(Leave-One-Out,简称 LOO),即有多少样本就进行多少次训练/验证,并且每次只留下一个样本做验证。这样做的好处是不需要担心随即样本划分带来的误差,因为这样的划分是唯一的。一般来说,留一法的评估结果被认为是比较准确的。但是!当数据集较大时,使用留一法需要训练的模型太多了!这种计算开销是难以忍受的!

image-20211127111739118

image-20220926200526880

自助法

在留出法和交叉验证法中,我们都需要对数据集进行划分,从而使得训练所用的数据集比源数据集小,引入了一些因规模不同而造成的偏差,有没有办法避免规模不同造成的影响呢?

自助法(bootstrapping)正是我们需要的答案,以自助采样(bootstrap sampling)为基础,对包含 m 个样本的源数据集进行有放回的 m 次采样以获得同等规模的训练集。在这 m 次采样中都不被抽到的概率大约为 0.368,也即源数据集中有大约 1/3 的样本是训练集中没有的。因此,我们可以采用这部分样本作为验证集,所得的结果称为包外估计(out-of-bag estimate)

注意,自助法适用于数据集小,难以划分训练/验证集的情况。因为自助法能产生多个不同训练集,所以对集成学习也大有好处。但是!自助法改变了数据集的分布,也因此引入了一些额外的误差。因此,数据量足的时候还是留出法和交叉验证法用得多一些

MNIST

链接:https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-digits/

MNIST 是最流行的深度学习数据集之一。这是一个手写数字数据集,包含一个有着 60000 样本的训练集和一个有着 10000 样本的测试集。

大小:约 50 MB 数量:70000 张图像,共分为 10 个类别

MS-COCO

链接:http://cocodataset.org/#home

COCO 是一个大型数据集,用于目标检测、分割和标题生成。它有以下几个特征:

目标分割

在语境中识别

超像素物品分割

33 万张图像(其中超过 20 万张是标注图像)

150 万个目标实例

80 个目标类别

91 个物品分类

每张图像有 5 个标题

25 万张带有关键点的人像

大小:约 25 GB(压缩后) 数量:33 万张图像、80 个目标类别、每张图像 5 个标题、25 万张带有关键点的人像

ImageNet

链接:http://www.image-net.org/

ImageNet 是根据 WordNet 层次来组织的图像数据集。WordNet 包含大约 10 万个短语,而 ImageNet 为每个短语提供平均约 1000 张描述图像。

  • 大小:约 150 GB

  • 数量:图像的总数约为 1,500,000;

  • 每一张图像都具备多个边界框和各自的类别标签。

  • imagenet-1k是 ISLVRC2012 的数据集,训练集大约是 1281167 张+标签,验证集是 50000 张图片加标签,最终打分的测试集是 100000 张图片,一共 1000 个类别。

  • imagenet-21k是 WordNet 架构组织收集的所有图片,大约 1400 万张,2.1 万个类。多用于自监督预训练,比如 ViT。与 ImageNet-1k 相比,ImageNet-21k 具有更高的类别多样性,但它的标签质量可能较低,因为类别不是相互独立的,并且存在多个层级。此外,由于类别的不平衡性,处理起来会相对复杂一些。

官网下载

ImageNet

在官方网站注册账号,注册时最好使用教育邮箱(.edu )之后。按照流程申请,收到邮件之后可以就可以在 Download界面里下数据。

点进去之后,下载如下三个压缩包(图片分类任务用这三个足够了)

数据解压

下载完毕后把 Development kit 留着备用,我们会得到训练集与验证集的两个压缩包,分别是 ILSVRC2012_img_train.tarILSVRC2012_img_val.tar

首先创建两个用于放训练集和测试集的文件夹,然后解压:

1
2
3
4
mkdir train
mkdir val
tar xvf ILSVRC2012_img_train.tar -C ./train
tar xvf ILSVRC2012_img_val.tar -C ./val

对于train的压缩包,解压之后其实还是1000个tar压缩包(对应1000个类别),需要再次解压,解压脚本unzip.sh如下(PS:可能需要自己改一下目录 dir ):

1
2
3
4
5
6
7
dir=./train 
for x in `ls $dir/*tar` do
filename=`basename $x .tar`
mkdir $dir/$filename
tar -xvf $x -C $dir/$filename
done
rm *.tar

执行脚本之后,我们就获得了1000个文件夹和对应的图片数据啦~截至目前,我们已经把所有的 JPEG 图片搞了出来。

数据标签

对于训练集,不同类别的数据躺在不同的文件夹里,用起来很方便(同一文件夹的视为一类)。但是验证集没有对应的标签,需要额外处理。

验证集的标签在 Development kit (文件名为 ILSVRC2012_devkit_t12.tar.gz)中的ILSVRC2012_devkit_t12\data\ILSVRC2012_validation_ground_truth.txt 中:

但是新的问题又来了,那就是这个数字和文件夹的名字虽然是一一对应的,但还是需要额外的映射……好在映射关系储存在和txt文件同目录下的 meta.mat 文件中。我们希望验证集的文件结构长得和训练集一样,即 :

  • /val
    • /n01440764
      • images
  • /n01443537
    • images

因此,我们首先解压 devkit 压缩包,把我们需要的东西取出来:

1
tar -xzf ILSVRC2012_devkit_t12.tar.gz

之后,在imagenet目录(devkit和val的根目录下)创建并运行如下 python 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from scipy import io
import os
import shutil

def move_valimg(val_dir='./val', devkit_dir='./ILSVRC2012_devkit_t12'):
"""
move valimg to correspongding folders.
val_id(start from 1) -> ILSVRC_ID(start from 1) -> WIND
organize like:
/val
/n01440764
images
/n01443537
images
.....
"""
# load synset, val ground truth and val images list
synset = io.loadmat(os.path.join(devkit_dir, 'data', 'meta.mat'))

ground_truth = open(os.path.join(devkit_dir, 'data', 'ILSVRC2012_validation_ground_truth.txt'))
lines = ground_truth.readlines()
labels = [int(line[:-1]) for line in lines]

root, _, filenames = next(os.walk(val_dir))
for filename in filenames:
# val image name -> ILSVRC ID -> WIND
val_id = int(filename.split('.')[0].split('_')[-1])
ILSVRC_ID = labels[val_id-1]
WIND = synset['synsets'][ILSVRC_ID-1][0][1][0]
print("val_id:%d, ILSVRC_ID:%d, WIND:%s" % (val_id, ILSVRC_ID, WIND))

# move val images
output_dir = os.path.join(root, WIND)
if os.path.isdir(output_dir):
pass
else:
os.mkdir(output_dir)
shutil.move(os.path.join(root, filename), os.path.join(output_dir, filename))

if __name__ == '__main__':
move_valimg()

用Pytorch加载

使用 torchvision.datasets.ImageFolder() 就可以直接加载处理好的数据集

1
2
3
4
5
6
7
8
9
10
11
12
13
import os
import torch
import torchvision.datasets as datasets

root = 'data/imagenet'
def get_imagenet(root, train = True, transform = None, target_transform = None):
if train:
root = os.path.join(root, 'train')
else:
root = os.path.join(root, 'val')
return datasets.ImageFolder(root = root,
transform = transform,
target_transform = target_transform)

ImageNet-R

ImageNet-R 全称 ImageNet-Rendition,是 ImageNet 数据集的拓展。 ImageNet-R 数据集包含对多个 ImageNet 类别(艺术、卡通、 DIYART 、涂鸦、刺绣、图形、折纸、绘画、图案、塑料制品、毛绒制品、雕塑、素描、纹身、玩具和视频游戏等)的演绎。

ImageNet-R 数据集涉及对 200 个 ImageNet 类别的演绎,产生了 30,000 张图像。

OpenImages 数据集

链接:https://github.com/openimages/dataset

Open Images 是一个包含近 900 万个图像 URL 的数据集。这些图像使用包含数千个类别的图像级标签边界框进行了标注。该数据集的训练集包含 9,011,219 张图像,验证集包含 41,260 张图像,测试集包含 125,436 张图像。

大小:500GB(压缩后) 数量:9,011,219 张图像,带有超过 5000 个标签

CIFAR-10

链接:http://www.cs.toronto.edu/~kriz/cifar.html

该数据集也用于图像分类。它由 10 个类别共计 60,000 张图像组成(每个类在上图中表示为一行)。该数据集共有 50,000 张训练集图像和 10,000 个测试集图像。数据集分为 6 个部分——5 个训练批和 1 个测试批。每批含有 10,000 张图像。

大小:170MB 数量:60,000 张图像,共 10 类

Untitled

CIFAR-10 是一个更接近普适物体的彩色图像数据集。CIFAR-10 是由 Hinton 的学生 Alex Krizhevsky 和 Ilya Sutskever 整理的一个用于识别普适物体的小型数据集。

一共包含 10 个类别的 RGB 彩色图片:飞机( airplane )、汽车( automobile )、鸟类( bird )、猫( cat )、鹿( deer )、狗( dog )、蛙类( frog )、马( horse )、船( ship )和卡车( truck )。

每个图片的尺寸为 32 × 32 ,每个类别有 6000 个图像,数据集中一共有 50000 张训练图片和 10000 张测试图片。

数据文件名及用途

在 CIFAR-10 数据集中,文件 databatch_1.bin、data_batch_2.bin 、··data_batch_5.bin 和 test batch.bin 中各有 10000 个样本。一个样本由 3073 个字节组成,第一个字节为标签 label ,剩下 3072 个字节为图像数据。样本和样本之间没高多余的字节分割, 因此这几个二进制文件的大小都是 30730000 字节。

CIL 数据集整理

Dataset Domain Similarity Classes Train Train/Class Validation Test
CropDiseases 0.386 35 34260 978 8566 10692
ChestX 0.39 6 7252 1208 2417 2417
ISIC 0.409 6 5940 990 1980 1980
RESISC45 0.432 45 18900 420 6300 6300
EuroSAT 0.444 10 16200 1620 5400 5400
Pets 0.47 35 2774 79 706 3469
CIFAR-100 0.491 100 40,000 400 10,000 10000
ImageNet-R 0.577 200 18000 90 6000 6000
DomainNet 0.6 345 96724 280 24182 52041
miniImageNet
CUB-200