Standford Dogs Dataset
数据集属性
为啥是预训练的模型,到底怎么用的这个预训练模型,多大程度取决于原来的预训练模型,那既然已经是预训练了,那如果现在效果好的话,是不是和之前预训练有关,而不是仅仅和狗数据集有关,那是不是会因为这个,而让结果比实际偏好。因为这个教程也说了 pretty good accuracy,说明这个的效果还不错
怎么选的训练集,又选的哪部分作为测试集。
为什么转换TF Records还要进Inception model而且还要从Inception model出来,然后才是图像和annotation标注在一起。
1.使用的是来自ImageNet的图像和注释
2.为的是细粒度(fine-grained)图像分类任务而构建
Numer of categories:120
Numer of images:20580
~150 images per class(如果120类每类有150张图像的话就是18000,但现在有20580,要不咋说每类大约有150张呢)
As you might have noticed, having only ~20K images of 120 different breeds (~200 images per breed) is not enough to train a deep neural network.你可能注意到了,只有120类的2W张图像去训练DNN是不够的。It would not be able to learn generic enough patterns off this dataset to classify different dog breeds.它不能从这个数据集中学习足够通用的模型来分类不同的犬种。Most likely(最有可能的是): 他仅仅适合于这个少量的训练样例,因此在测试集上的准确性会降低。
因此,有两种可能的方法来缓解训练实例缺乏的问题
(mitigate the lack of training examples) 参考自:.
https://towardsdatascience.com/dog-breed-classification-hands-on-approach-b5e4f88c333e
将狗数据集与另一个更大的数据集的图像合并(i.e ImageNet),并在这些合并的示例上训练CNN。 但是存在两大缺点:1.要分析更大量的数据 2.此外,如果只是把数据集合并,然后再在大数据集上重新训练的话耗时耗资源太多了。
采用一个在一个较大的数据集上已经预先训练好的深度神经网络,切入它,并附加一个额外的“分类头/分类头就是后文所指的Head”,即几个额外的完全连接的层(这些完全连接的层上面/上面可能不准确,而应该是FC基础上都有softmax层,都有softmax层),其上有Softmax层。Take an already pre-trained deep neural network on a larger dataset, cut into it, and attach an additional “classification head” i.e. several additional fully connected layers with the Softmax layer on top of them. 所以到底是softmax在FC上,还是作为单独的层和FC分开?
那是不是说,我跑这个Demo就是这么干的啊?第二种方法似乎很有前途:训练必须在原始数据集上执行,并且训练只有几个完全连接层的“分类头”不需要大量时间和资源。
将有“分类头”的预先训练的模型附加到较小的数据集上的方法称为迁移学习。
将有“分类头”附加的预训练模型放在更小数据集上的方法叫做迁移学习。
为啥会有迁移学习,为啥能这么干并且能does work,要去看理论How CNNs work
简而言之,在大数据集上训练的深层神经网络的底层捕获图像的低级基元(例如轮廓和简单形状),以便这些知识对于所有图像是通用的并且可以“迁移”到任何图像识别问题
Annotations:Class labels(类别标签),Bounding boxes(边界框)
readme信息
images:以单独文件夹形式放置不同类别图像
annotations:图像的边界框标注
file_list.mat:数据集中所有文件的列表
train_list.mat:数据集中所有训练图像的列表和标签(应该是列表对应着标签)
test_list.mat: 数据集中所有测试图像的列表和标签(应该是列表对应着标签)
Train splits:为了以每类少于100张图像进行测试,在train_list.mat中为每个类使用了前n个索引,此处n表示每类训练图像的数量。
Features(train_data.mat,test_data.mat)
train_data/test_data
–包含直方图交叉核(histogram intersection kernel)应用后的特征矩阵
train_fg_data/test_fa_data
–包含直方图交叉核(histogram intersection kernel)应用前的特征矩阵
train_info/test_info
–包含在特征矩阵中对相应图像的labels和ids
Baseline Results
两个任务的Baseline Results
Mean Accuracy(平均准确度)
每个类中训练图像的数目由1到100变化。
Comparison of Accuracy per Class
(每类准确性的比较,是在这种狗上的识别精度可能比另外一种狗的识别精度高这个意思么)
The accuracy of each class is compared for 15 and 100 training images per class.
(每类可以比较15个和100个训练图像对每类的精确性进行比较)
实验设置
所有的实验只使用边界框内的图像区域进行训练和测试
剩下的参数设置为如下的值:
Type of SIFT descriptors: Grayscale SIFT描述子类型
SIFT patch sizes: 8, 10, 14, 18, 22, 26, 30
SIFT grid spacing(SIFT网格间距):4 pixels
Spatial pyramid:1*1+2*2+4*4(3 levels)
Dictionary Size:256
Kernel: Histogram intersection kernel(直方图交叉核)
牛逼之处
参考链接:https://github.com/stormy-ua/dog-breeds-classification/blob/master/README.md
通过pip install -r requirements.txt
打包安装dependencies(把你要装的依赖库的名字存到一个txt里),像下面这样。
神经网络模型
在谷歌深度神经网络(即初始模型)的预训练模型上建立犬种分类dense神经网络模型。on top of 在…基础上
架构:Inception model 其实就是GoogleNet
Inception模型的输出经过几个完全连接(FC)层,最后softmax输出图像属于每个类的概率(probabilities)。Only FC layers representing “Classification head” have to be trained. 只有FC层代表“分类头”必须接受训练。Inception model remains frozen with already predefined model parameters.Inception模型在已经预定义的模型参数下保持冻结,就是继承在Imagnet上以后的模型参数,即使再次开始训练,incept module的参数也不变。
什么意思?只有加了FC层才证明”分类头”已经参加了训练?另外,冻结参数,freeze frozen到底又在干啥?【变量都被常量替换, frozen TensorFlow model来自ImageNet 2012挑战赛 链接在这】
https://github.com/tensorflow/models/blob/master/tutorials/image/imagenet/classify_image.py#L51
紧接着又说了只是用Google Inception model来pre-trained dogs dataset, 这简化了training, 因为我们无需在训练中为每个example计算Inception output. 但反而,But instead 它(inception)已经预先计算好了,而且准备被使用。
这意义重大啊,通过.sh
的脚本实现数据自动下载,解压,还能自动放到工作路径,也就是从程序上实现了路径可行性的约束。
setup.sh中的sh ./setup/inception_download.sh
下载和提取以a frozen TensorFlow graph(一张冻结的Tensorflow图)表示的Google Inception model.冻结意味着所有的变量都被常量替换并嵌入到图形本身中
因此不需要将checkpoint 文件与图一起执行,以便将模型加载到TensorFlow会话中并开始使用它。
Frozen means all variables are replaced with constants and embedded into
the graph itself so that there is no need to carry checkpoint files
together with the graph in order to load the model into a TensorFlow
session and start using it.
训练 顺序:2048 1024 120
HEAD_MODEL_LAYERS = [INCEPTION_CLASSES_COUNT(好像是Inception模型的最后一层),1024,CLASSES_COUNT]
首先,要给模型一个唯一的名称,其次,应配置多少全连接层以及那些全连接层中包括多少单元(units)
这个配置可以在src/common/consts.py
里配置。我暂时先不做任何修改,保持和Github原版一致。
默认地,设置2个全连接层,含1024和120个units(一层是1024,一层是120,120,1024谁靠前靠后)。
输入层(Inception model的第一层和最后一层都是2048个units对么)有2048个units,它等于Inception model最后一层中的units数。Inception model最后一层不是1024,而是2048个units.
src/training/train.py 执行训练 以下面的超参数 hyper parameters
learning rate:设置为0.0001
number of epochs:设置为5000 epoch数会影响训练时间,另外模型深度也会影响训练时间 :
mini-bath size (批尺寸不是批个数,每批里有多少example)可在src/training/train.py
进行配置。设置为:64 那得迭代总样本数除以64,那得迭代多少次啊!!!!!!!!!!!
有三种可用的度量标准,cost(代价), error on the test set(测试集误差), error on the training set(训练集误差). 默认情况下,误差率是对应来自训练集的3000样本而计算的,而且对于整个测试集也是有3000样本。默认情况下,对于来自训练集的3000个示例(这部分训练误差,训练集中选取3000样本)以及也包含3000个示例的整个测试集(测试集中样本共3000)计算错误率。
那么对于我这个到底多少图片用来训练多少图像用来测试呢。应该是3000。
Freeze Model
这将把Inception模型与前一步“分类头”模型的训练结合(Blind)起来,并将其序列化为一个Tensorflow图,该Tensorflow图的特点,其变量表示为常量。这个Frozen模型将被准备用于分类任务。
可以看到框框里显示的:把4个变量节点转化为常量节点。并把Frozen model保存到frozen/stanford_5_64_0001.pb,经过检查也确实保存进来了。Frozen的模型将被用于分类任务。
一旦模型得到训练,其优化参数将存储在./checkpoints目录中的检查点文件中。 为了有效地重复使用该模型进行推理【这块这个推理到底指什么】,将它作为一个冻结的TensorFlow图并将参数嵌入到图本身中是非常好的。[把优化很好的参数嵌入到冻结的TF图中,用于以后推理,这是极好的。] 这可以使用src / freeze / freezy.py来完成:
python -m src.freezing.freeze
该脚本按以下顺序执行几项操作:
1.将Inception模型和“分类头”模型加载到同一个TensorFlow会话中,并将它们组合到一个计算图中,以使来自Inception模型的输出直接输入到“分类头”模型的输入中。 绑定完成后,脚本会将文件系统中图形中的复合模型序列化。 此时,由于在训练过程中计算的模型参数仍然位于检查点文件中,因此图表尚未冻结。
2.使用TensorFlow freeze_graph函数冻结上一步中生成的图形。 它实际上从检查点文件中取出模型参数并将它们注入到图形变量中。 图形变量轮流转换为常量。 生成的文件将转到带有模型名称的./frozen目录。
代码调试部分
代码调试细节(step by step)
1.cd
to this repo root directory
2.Execute setup script: sh ./setup/setup.sh
先通过sh文件创建了所有需要的路径,然后通过sh文件下载了Google Inception model,最后通过sh文件下载了Standford Dogs Dataset
每个图片fed进这个GoogleNet模型,输出的时候,它就是图像和其他标注(其他标注都包含什么)在一起的状态了。
关于训练结果的分析
Both errors are pretty(相当地 颇低!) low on both test and training set. And there are no symptoms(症状) of a major overfit(严重过度) to the training set since the error on the training set is about the same as error on the test set.
在测试和训练集中,这两个错误都很低。 由于训练集的错误与测试集的错误大致相同,因此训练集没有主要过度训练(也就是没有过拟合)的症状。
说明在训练集上没有明显的overfit症状或现象。
Analyze
产生具有预测和实际品种的CSV文件,这可以用来分析训练数据的精度,例如(plot)绘制一个混淆矩阵(confusion matrix),生成的CSV文件前往:metrics/training_confusion.csv
Inference
一旦准备好冷冻模型,就可以对任意图像进行分类了。 src / inference / classify.py
脚本能够对存储在文件系统上的狗图像进行分类,或者可用作HTTP资源。 在幕后,它加载冻结的图并将图像输入到该图中。 这里有两个例子说明如何推理Airedale Terrier和Shih-Tzu:
容器
看看为啥机器学习模型分错类
仔细研究机器学习模型未能正确分类的例子总是一个好主意。 脚本src / analysis / training_perf_analysis.py会为所有训练示例生成具有预测和实际品种的CSV文件(它将转到metrics / training_confusion.csv)。
通过从training_confusion.csv加载数据,可以绘制混淆矩阵:
结论
正如我们所看到的,即使您没有足够的训练图像和/或计算资源,如果您可以访问预训练的深度神经网络和TensorFlow等现代机器学习库,也可以训练出鲁棒的图像分类器。