1.基本概念:
迁移学习是在已经训练好的模型下,恢复这些训练好的模型参数到我们的新模型中,新模型使用的数据集一般比较少时,我们可以根据新数据集与原数据集的相似程度,数据规模大小等冻结网络的某几个卷积层,只训练最后的全连接层或者平均池化层,加快了训练速度,同时提升模型的泛化能力。
2.主要思路:
(1)准备基模型
首先需要一个提前训练好的模型文件。这里是我的文件目录。我们称为“基模型”。
(2)查询变量
查询变量的作用域并保存这个基模型的所有参数。方便后期迁移学习后对比模型的参数是否发生变化,是否按照我们冻结的层次进行的训练。主要代码如下:
import os
from tensorflow.python import pywrap_tensorflow
model_dir = os.getcwd() # 获取当前文件工作路径
checkpoint_path = r'D:\桌面\model\TrainInceptionV3-87000' #基模型的文件路径
#print(checkpoint_path)
reader = pywrap_tensorflow.NewCheckpointReader(checkpoint_path)
var_to_shape_map = reader.get_variable_to_shape_map()
Tag = False
var = []
for key in var_to_shape_map:
if key.startswith("Variable") and Tag: # Tag ==True 只显示不是网络权重的变量
var.append(key)
elif not Tag: # 显示所有变量及对应的值
if "weight" in key:
print('tensor_name', key)
with open('old_weights.txt','a+',newline='',encoding='utf-8') as w:
w.write(key+'\n')
w.write(str(reader.get_tensor(key))+'\n')
var.sort()
for v in var:
print('tensor_name', v) # ,": ",len(reader.get_tensor(v)))
3.查看权重
权重保存到txt文件完成后,我们可以查看这个文件:
这是我们的一部分权重参数。
(4)定义优化参数
在训练的代码中添加需要参与优化的参数,也就是需要冻结哪些参数,只训练哪些参数。因此,我们在进行损失函数的定义前,增加如下代码:
update_vars_list=[] #这里是需要更新的参数项
tvars=tf.trainable_variables()
for tvar in tvars:
if "Logits" in tvar.op.name:
update_vars_list.append(tvar)#只训练InceptionV3模型的辅助分类器和最终的分类器那一段(即包含了Logits这个作用域的变量)
else:
pass
这样我们就把需要训练的参数和层放在了一个列表里面,如果还需要修改冻结的层数,只需要通过第二步去查看变量的名称,然后根据需要放入这个update_vars_list列表里面,没有放进去的默认都不会变了。都会保持迁移学习前的参数值。下面只需要在优化器优化损失函数的时候,添加这个列表的变量即可。
(5)参与迭代和训练
在第4步的基础上,我们将update_vars_list这个列表里的参数参与优化器的迭代即可。即:
train_op=optimizer.minimize(loss,var_list=update_vars_list)
`
(6)训练几轮,查看保存的模型,并使用第2步的方法查看训练和的模型参数,并保存下来,进行对比。
第一张是保存的模型的部分参数,第二张是原来的。
我们发现冻结的这一层的参数未发生变化。我们继续看我们要求参与训练的“Logits”下的参数变化情况。
我们看到权重的值的确发生了变化,表示迁移学习成功了。