只是普通的classifier,不是用triplet那种。Facenet用的是没有ResNet版本的inception网络
, david
指出:
These networks seems to be more difficult to train and does not converge very well when trained on the
CASIA/Facesccrub
datasets.
说白了就是,不带ResNet
的单纯Inception
网络在CASIA
上不好收敛。
为啥这么说,通过什么观察出来的?
在训练集上面loss相对地很大,此外,当no regularization
被使用的时候,同样表现出训练集上面loss很大
, 这就能暗示出模型不能去overfit the data
. 不是overfit
,而是压根fit
不好。
然后他们说那既然纯inception
不好,那这样的话,我就用Inception-ResNet-v1
,然后发现,就能很好收敛而且在LFW上表现也好。表现好在两个方面:
accuracy
validation rate
我没用david
库里面的人脸对齐的脚本了,而是用的ZhaoJ
的。 而且因为我在我现在的程序里,不像是之前的MTCNN
如果要给网络输入的是160*160
,那就因为random crop
给裁剪出182×182
。而是直接裁出来的就是112×112
。
5. Start classifer training
现在的问题是:
发现我可能少加了一个args
这就是要看是不是要对prelogits
做出normalization
. 我已经于2021.01.22
加上了这个args
.
但是,在关注这个之前,我们应该先关注:先关注david画的图,他画的图到底用的总loss(这里的总loss指的是包括上regularization loss)
还是只是cross_entropy_mean
. 先去验证这一点。 这得在TensorBoard
产生的数据里面看。
应该注意的是,可以通过用冒号分隔路径来使用多个数据集的并集。
数据是有了,标签咋弄的?
应该就是把标签转换成从0到类别总数
。但是如果数据集之间有类别上的overlap该怎么处理?
这里的reference
有没有特别的意思?
其实这个inference
就是给embedding产生一个输入prelogits
。给我的感觉prelogits
不是全连接层。这个暂时还不确定,得回头确定下
已经确定了,prelogits是来自net的结果,所以就是全连接层。
而在Inference
内部:
因为和下面inception_resnet_v2
的情形是一样的。
唯一不同就是:scope
的名字,但是,这个名字也无关紧要啊。
没错。实现了。确实一样,而且在多个测试时候,也是用的Zhaoj非图像格式
的测试数据集。所以这点不再担心。
这种当不变化时候,对学习率除以10
是惯用,和Marco说得一样。
下面讲到了我疑惑的参数--prelogits_norm_loss_factor 5e-4
, 这个可以让activation
更加稀疏,而且能让models
范化 a little bit
.
上面的weight decay
和dropout
都是为了防止过拟合,除了上面这两个,L1 norm loss
同样也能让模型更泛化一些。所以,不管咋样,还是得先带上。
regularization
我先不加这个参数,先跑一个。然后不行再加上。如果行的话,也可以下次再加上。 2021.1.22
后加上了。
6. Running TensorBoard(optional)
7. Plotting the learning curves
7.1 LFW accuracy
这个文件具体的内容如下:
这是在LFW
上测试的。然后,LFW test accuracy
而不是training accuracy
啥的。所以这个标题下面的那个图,意义不大。但是,david
画的这些图像都是带着pnlf
情况的结果得到的。另外的话,是不是这些图都是他提供的m文件画出来的? 是的
在这里可以看出,即使最后一次评估的准确度为0.9965,最近10次评估的平均准确度也较低(0.9950),这可能更接近再现结果时的预期。 例如,在比较不同的超参数设置时,平均值可能是更好的指标。
这个平均值是怎么获得的??? 应该是train_softmax.py
程序里的LFW验证部分的代码决定的。
这个先不细究。
7.2 Training /Validation cross entropy loss
看这个抬头的话,应该只是cross entropy loss
而不是加上regularization loss的总loss
.
确实的,可以在代码里看出来,每个部分都有自己专门画图的代码。
- 有专门画
cross_entropy
- 有专门画
regularization loss
- 有专门画
total loss
到底是啥,这下面给出了:
这明确了就是cross-entropy loss
, 但是得知道具体是哪个python的变量保存出来的。
我自己的话是27000~
多张图像。
`has been filtered with a sliding average filter over 500 steps(这个500在程序的哪里体现)
在m
文件里体现。
这块终于写了,终于写了到底是用的什么画的图???
写了这个cross_entropy during training but has filtered with a sliding average filter over 500 steps
所以,我也得用average过的
,
因为MATLAB的监控文档里提到经过平滑处理的训练准确度
贴个图,更加好观察。
那这明显就是cross_entropy_1
而不是cross_entropy__raw_
。
但是从0开始就有一个竖线这种的,不光cross_entropy
有,而且total_loss
也有。但是通过不止查看趋势,而是看下Y軸,就知道9左右开始,那说明应该就是cross_entropy
而不是总的。更何况的是,都说了每个都有自己画自己的那部分代码
而且这里是经过平滑处理的训练cross-entropy
. 而且指明了是经过滑动平均滤波器sliding average filter
, 在程序上的对应是:也是找cross_entropy_1
而不是cross_entropy_raw
.
这要看这个l
是什么,
这个l
无非就是在一个List里面遍历,大约是[loss1, loss2, loss3..., total loss]
这种. 也就是各个单独loss
和total loss
. 这么看的话,就是每个单独的loss
和total loss
都有raw
版本,然后,也都有平均过的版本。
而David画图用的是非raw版本,也就是平均过的版本,所以应该是下面这句代码
, 而且是单独loss里的cross_entropy_1(
_1就是区别于raw的平均后版本。)
tf.summary.scalar(l.op.name, loss_averages.average(l))
这个问题的最终解,还是得归到m
文件。去看m
文件怎么从state
里找到具体画滑动平均的那个变量名。
是这个xent_loss
.
有几个全连接层?
先把图例都放在这里,我们知道蓝色
代表的是全连接层(有时候在一些博客里也经常写成Dense layer, 没错,确实有时候也写成dense layer.).
on each of FC layer
因为有另外一篇博客,讨论VGG16的博客. 明确说了VGG16
有了三个DENSE
layer.
通过上图,确实是三个Dense layer
. 然后接下来关注的是每个全连接层有多少神经元。
第一个全连接层
4096
第二个全连接层
4096
第三个全连接层
1000
另一个链接10个CNN图示也能很好地说明确实是三个
,然后4096-4096-1000
因为讨论VGG16的博客这个有明确的文字描述,而且附带了具体对应程序的链接。
我们看到:
所以,我们知道,应该是看括号里面的第2位
,然后,我们知道:
如果看的是第二位,确实就能对应上,4096->4096->1000
.
从上面这个图,可以看出来,总共三个FC
,但是只有两个涉及Dropout
.
所以,难道是三个里有两个利用Dropout, 感觉就算用两个也没毛病,最后一个都是分类用的了,还Dropout什么啊?
有待验证:最后一个是不是都是softmax所在,然后单元数目是不是就是分类数目?
YES,是的,如下图所示:
能看到最后一个上面就是有个S
, 而且类别数1000
就是单元数目。
于是,我最先想到的是去看这个代码链接的系列里有没有inception_resnet_v1
的代码,然后从代码里看出来到底多少个Dense layer
以及每个dense layer
含有多少神经元
。
但是,却没有, 却没有inception_resnet_v1的
因此,我转而要去看inception的
,所以定下来去看inception.py
. 而且在这个py文件里,我们知道:里面有个def inception_v3和class Inception3
. 那还得分清楚到底是前面中的哪一者
真正定义了网络的结构。
从下图可以看出,涉及到真正的网络模型时,def inception_v3
还是class Inception 3
可以从代码中看出来的。
最终还是去找class Inception3
。因此,根据之前怎么看FC,就按照dropout
去找,应该就在Dropout
附近。
搜索后,有两个位置涉及dropout
.
一个位置是在class Inception3
的__init__
里:
另一个位置是在class Inception3
的__forward
里面:
所以, 我得去图示里看下inception_v3
的结构。
确实是有主和副的。
但是,能看出来无论是主还是副都是两个FC。 所以这么从图上看的话,就是确实能够确定出来FC。
主的是:2048--->1000
副的是: 768--->1000
综上,感觉不要再找dropout
而是应该找768或者FC这些字眼
。
找768
的结果能找到副的:
副的:看括号里面的第二个字,我们就知道是768
和1000
。
找2048
的结果能找到主的,在class Inception3()
的__init__里面
:
主的:看括号里面的第二个字,我们就知道是2048
和1000
。
其实就是要确定是不是多少FC是由self.fc
确定的。好像是的
。 为了节省篇幅,以副的
程序为例子:
在副的里确实有两个self.fc
, 一个跟768
有关,一个跟1000
有关。一个在副的滴__init__位置
,一个在forward
位置.
而在主的里也确实有两个self.fc
. 一个跟2048
有关,一个跟1000
有关。一个在__init__
位置,一个在_forward
位置.
该核对的是: 看看之前写的,如果之前写的没毛病,就是去和我自己的程序结合着看,从而确定我自己到底有多少FC
。
通过检查,确实就是找变量名fc
就能实现对哪个是全连接层的确定
。
InceptionV3
的FC
这个找完了,落回到我的Inception_ResNet_v1
. 在看自己的代码之前,因为10个CNN图示里面有提及Inception_ResNet_v2
, 所以,我去先看看Inception_ResNet_v2
。
其实吧,这个1536
是Inception-v4
的数值。
那么这个1536
到底算的是Dropout
的还是Average Pooling
的?
根据下面这个图,能看出来Global Average Pooling
被单独放出来。所以,是 dropout
那个层被当作FC
了。
副的不看。只看主的
。带有fully_connected
的有几个呢?
如果说有两个,那么另一个在哪?应该就是上图中的Dropout那行。
net =slim.dropout(net,
dropout_keep_prob,
is_training=is_training,
scope='Dropout')
如果net的维度是1792
或者1536
就能说明两个FC都找到了。可以去看我的程序了。
我把我程序里的哪个算上了? 算上的如下面一系列的图所示:
第一个
第二个
第三个
因为在前面别人的tutorial
里,数目为分类类别数的,都被算作FC
。 所以,我还缺那个,得把num_classes
那个也当作FC。
对于David之前的Softmax, 那么下面这个图就是第三个
:
对于我目前的Cosface, 下面这个图就是第三个
。好像还得和LIYule的Cosface版本再对照检查一次。
这个xw_norm的维度应该是10575
。
因为这个是缩放之前的logits
. 缩放通过下面代码实现:
看看那几个相关的数值都长成什么样子:
再看一眼David版本的,从而验证我自己的到底对不对。
感觉是对的啊! 都是(?,10575)
.
排故部分
应该先把不该删掉的带上然后训练一次,前提是:
应该确定到底怎么画得sliding average
.
此外, 原来的david有prelogits_norm
而且LiYuLe的CosFace也有fc_bn
。
两者分别如下:
Li的:
因此,基于两者都有的这一点,我觉得还是一定要加上这个prelogits_norm
的。
感觉调通这个程序有点费劲了,如果可能的话,还是直接在程序里找准变量,然后出来画。
本身画图的那个程序不行,如下所示,压根没有readlogs这个函数的定义
。
这可不只这一个函数啊,少太多函数了。fileread
这个函数也没有。
所以,转变策略,去自己做个滑动平均。
- 也就是:先不平滑,先把加上
norm
的,然后把index
同样变成1,然后把他们画到一个图里面。还没完成。
-
已经把
david
的softmax
和我之前的softmax
比较完了,但是还得将我前一步(基于david和我之前),再补上cosface
里新加上的。 已经加上了。完成 -
然后把最终的
softmax
和我目前的cosface
比较,再对cosface
补充,从而得到最终cosface
.2021.01.26
正在开展这个工作。 完成 -
还涉及到底要不要在最后的层里面给cosface的版本加上weight_decay
. 先不加,先训练一个。 -
该查查
summary writer
. 先重新查一下公共部分。再单独查不同的部分。完成 -
现在把两个版本都重新移动到PG,但是不覆盖。记住保留之前的。先弄
cosface
的,传上去训练着,然后再弄softmax
的。两个本地的都移动到PG
了,但是对应的训练脚本还没改,尤其是cosface
的。
現在一共有如下三種:
- 只是加了
prelogits_norm
- 不加
dropout
的只是降低到0.5 - 在
512後面
加dropout
的
然後我們就該:該畫曲線了。還是通過曲線才能判斷出來。
沒有必要,沒有必要申請72小時。申請48/足夠了,申請36也夠。
- 該先把这些结果整理出来发给Marco.
- 然后上传一个训练softmax的。
- 然后去调整新的loss了。
- 此外,感觉应该在200-275之间再设置个新的
learning rate
. - 那该怎么保证这套超参数对于所有的loss都好使呢。
Accuracy得到啥样才行?
- 在数值的绝对大小上,
training accuracy
得到0.95左右,然后validation accuracy
得到0.88左右。 - 在对比趋势上,在整体上
validation accuracy
肯定还是小于training accuracy
. - 在对比趋势相差多少数额上,有的区间段相差将近
0.2
, 有的区间相差0.05
左右, 这些数值都是我大约估计的数值。
Case 1
:
在高点,training accuracy
居然有0.91111
, 然后对应位置的validation accuracy
才 0.48
。 然后说明确实过拟合了。说明只是添加prelogits_norm
是不够的,还是会过拟合。
Case 2
: 不仅仅prelogits_norm
而且drop掉更多。
不太行啊。training accuracy
才达到0.8
。validation accuracy
也只是到0.47
。 而且后来val accuracy
还在下降。这种下降的也是难得的现象,是不是有什么预示???? 感觉改变drop_rate
反而让效果不好了。
Case3
: 最大特点在于加了dropout
.
我进行了三大类的对比,我发现只有加了dropout层的这个吧,training
和validation
相差得最少。而且在training accuracy
到0.75
时候, validation accuracy居然有0.55
之高。 这和david的规律很像啊。
此外,这个validation accuracy=0.55
是所有情形里目前最高的。
所以,根据这个图示得到启发,那就再降低一下学习率试试。自己又加了个除以10
的学习率试验了下。得到的图像如下:
case4
: 只是多添加个除以10
的学习率
可以看出在225epoch
时候有个小小的抬升。 那如果我把这个学习率调整到更小,那是不是意味着抬升更大。并不是的,因为下面marco建议的话给我们佐证的证据,太小也好,就不再发生任何变动。
case5
: 用Marco推荐的学习率
可以看出来,在100个epoch
的时候,因为学习率过小,validation accuracy
就不再有所提升了。其实在横轴120 epoch的时候
对validation accuracy的提升就很低了。在横轴140
的时候,就更是可以认为从那以后再也没提升过
。 所以,借用二分查找的思想,确定120就是这个模型能接受的最低学习率,对应的数值刚好是
。
所以,最低也就只能是0.0005
左右。 这么说得话,那我自己加的小数点后4个0
的0.00005
就不行。 行不行不是跑过了么。贴个图看看。从accuracy
上看,确实在225
以后有个小小的都基本看不出来的抬升。所以,最低界限就是0.0005
从loss上看,我们知道,225
以后一样是没啥降低和改善。所以,0.00005
这个数值确实没啥用。综上,0.0005
可能是对于CASIA上训cosface来说可以设定的最小的学习率下界
。所以,真正有意义的学习率范围应该是参考下图
来得到:
只是修改学习率
- 第一选择, 还是用
0.1
那套学习率。然后训练30
epoch。因为这是多数论文
里用的。
已经上传 是0.1initial_30那个
, 训练完毕了,从log
文本里看的话,训练30
epoch是不够的,总结的结论已经在ArcFace
博客中。画个图看看如下:
最奇怪的是:
这怎么还有那么长的一段,都是Validation Accuracy
大于training accuracy
?
我这里验证时候的数据
, 做不做和训练时候一样的那些数据增强操作?
- 第二选择,还是由
0.1
开始,训练90 epoch. 因为是小数据集,所以我更加偏向这个,而不是275epoch
。如果不行的话,就在中间除以2,来有更多steps.我画图去验证自己的这个想法是否可行
?
已经上传 是0.1initial_90那个
它的图如下:
确实是,确实是,每当validation accuracy不变动
的时候,就改变学习率,然后就能抬升,但是通过我的实验,我发现,改到太小以后就不好使了。就像上图80000 steps
时候的微弱抬升
。刚好对应的是0.001变到0.0001
所以,在这里的话,大体规律是: 把学习率设置成0.0001
以下是不行的,或者说顶多再除以2
, 也就是
0.0001
/
2
=
5
e
−
05
=
0.00005
0.0001/2=5e-05=0.00005
0.0001/2=5e−05=0.00005。这是接下来做实验我要进行尝试的点。
- 第三选择:不用
0.1
开始,而是按照david的0.05开始,训90个。
这个相当于是我加了dropout
以后的第一次训90。我画个图看看,因不因为加了dropout
可以在训练90
个就达到好效果。
可以知道的是:还是满足学习率变动validation accuracy
就增高的规律。
但是没试验过不加dropout
的记录指标无误版本的90
好像。
可以看出来一个优势,那就是
0.05 90epoch
这个版本的话,他们的training accuracy和validation accuracy
他们两者相差不那么多,要是能稳稳得再将training accuracy
提升一下,然后validation accuracy
稳稳地跟上来的话。就非常可以了。
通过对比之前的用vgg2
训练275 epoch
的有dropout
和无dropout
另外层的曲线,得出两个规律:
- 没有另外层的版本
training accuracy
可以达到0.9左右,但是validation accuracy
却只能达到0.5左右。而且200 epoch
后相距甚远。 - 有另外层的版本
training accuracy
只能达到0.75
多,但是吧,validation accuracy
却能够达到0.55
。
如果根据上面的描述,问题就在于如何把training accuracy提升到百分之90。我准备用混搭LR试试。
我再次看看单纯增加更多epochs,结论是:
不太行的。
- 把学习率调整到更小,不增加epoch
- 把学习率调整到更小,增加epoch
只是修改dropout
同时修改dropout和学习率
Loss得到啥样才行?