实验背景
-
实验数据: 时间序列
-
以VGG16_bn 骨架的 自监督生成式学习
-
结果为 二分类
实验bug
- 在预训练阶段,loss 在一直下降
- 因为在预训练阶段,是没有标签的特征学习,没办法去验证该预训练网络是否已经过拟合或是欠拟合,只有loss 确实一直在下降,暂且认为预训练网络是没问题的。
#Todo 这部分还有待改善,找出一个办法来确定预训练网络的效果,不局限于loss效果
- 因为在预训练阶段,是没有标签的特征学习,没办法去验证该预训练网络是否已经过拟合或是欠拟合,只有loss 确实一直在下降,暂且认为预训练网络是没问题的。
- 在微调阶段,loss依旧在下降,但是ACC持续为0
bug解决思路
数据归一化
-
输入数据归一化,从一开始没有归一化,导致预训练的Loss 值巨大,然后训练直接崩溃,loss直接为
nan
。归一化能 -
第一次归一化采用了
preprocessing.MinMaxScaler
,确实归一化好了,参考至:时间序列标准化中的一些问题(更新) 的第二点,使用standarscaler整体的量纲差异较小,不过仍旧是存在一定的差距,而使用minmaxscaler则没有消除量纲的差异。scaler = preprocessing.MinMaxScaler() for i in range(3): traindata[:, i, :] = scaler.fit_transform(traindata[:, i, :]) for i in range(3): valdata[:, i, :] = scaler.fit_transform(valdata[:, i, :]) for i in range(3): testdata[:, i, :] = scaler.fit_transform(testdata[:, i, :]) #### 换成了 scaler = preprocessing.StandardScaler()
数据shuffle处理
-
训练数据需要打乱,要检查每此batch是否都是一个类别。 以下是自己进行的数据打乱的方式
index = [i for i in range(traindata.shape[0])] np.random.shuffle(index) traindata = traindata[index] trainlabel = trainlabel[index]
调整预训练和微调阶段的学习率
-
学习率从大到小,都试一遍。0.1 --> 0.00001
试过1的学习率,确实不行,loss 都先降低 然后又递增了。
-
现在预训练确定的学习率是0.01 ,然后每50个epoch,下降一个量级,这个50个epoch也是经过大量观察反复实验的。但是这样子做还是比较机械化
# Todo 这部分可以再研究一下怎么更好,epoch和学习率之间更合理
def adjust_learning_rate(optimizer, epoch, args): """Decay the learning rate based on schedule""" lr = args['lr'] * (0.1 ** (epoch // 50)) for param_group in optimizer.param_groups: param_group['lr'] = lr return lr
修改Loss函数
-
预训练从原来的
nn.MSELoss()
改到了后来的nn.L1Loss
。之前预训练的结果一开始就很低,从0.0023开始下降,可能是
MSELoss
这个loss函数是差取平方的缘故,所以导致预训练loss 一开始就很低。改成nn.L1Loss
后改善的效果很明显,训练一开始的loss 值从0.0023 -> 0.4534 两个量级的改善。实验的Loss 不一定说越低就越好,但更不会是越高越好。所以要调整Loss函数,让实验Loss在一个合理的范围内 。Todo 但我也没办法说出,Loss在什么范围是一个合理的范围,只是不断的去尝试,实验效果好了,就是合理的范围,不好就再找,确实有待提高
修改微调模型 [也是本次效果改善最好的地方]
-
最开始微调模型是五层
nn.Linear()
和nn.Relu()
,层数过深再加上relu激活函数,会导致某一卷积层的输出全为0。原因可参考至Relu神经网络输出预测全为0或1,对所有输入样本的预测概率也相同 一层一层找原因,发现某一卷积层的输出值全为0。经过分析,该层使用的是Relu激活函数,而且该层训练后的权值W和偏置b都是负数,这样,输入在这一层的卷积运算结果全为负值,再经过Relu激活函数后,这一层的输出值就全为0。因此,不管输入样本是什么,经过该层后的输出都为0,从而导致网络最终输出的预测概率和输入样本完全没有关系,此时输出概率取决于这一层后面层的偏置参数b。后来干脆直接将五层的五层
nn.Linear()
和nn.Relu()
改为两成,效果一下子就出来了。#Todo 后续还是应该再找一下解决方法,再提高层数的情况下,是否可以防止以上问题出现。
self.classifer = torch.nn.Sequential( torch.nn.Linear(16 * 512, 256), torch.nn.ReLU(), torch.nn.Dropout(0.8), torch.nn.Linear(256, classes), # torch.nn.ReLU(), # torch.nn.Dropout(0.8), # torch.nn.Linear(1024, 512), # torch.nn.ReLU(), # torch.nn.Linear(512, classes), )