在进行迁移学习时,通常需要修改模型的最后一层,按照需求重新进行定义。但是,迁移学习需要在众多的模型中进行对比实验,而定义最后一个layer时,需要知道layer的name,和layer输入数据的shape,也就是需要对model的layer进行遍历。
1、遍历model
通过以下代码可以遍历model
import paddle
#print('飞桨框架内置模型:', paddle.vision.models.__all__)
model=paddle.vision.resnet18()
layer_list=[(name,atom_layer) for name,atom_layer in model.named_sublayers()]
#print(model)
feature_layer_name,feature_layer=layer_list[-1]
feature_layer_shape=feature_layer.weight.shape
feature_layer_type=feature_layer.__class__
print("feature layer:",feature_layer_name,feature_layer_shape,feature_layer_type)
代码执行输出如下所示:
feature layer: fc [512, 1000] <class 'paddle.nn.layer.common.Linear'>
2、动态修改模型的最后一层
动态修改模型的最后一层,支持语义分割模型和图像分类模型。但是需要注意的是,模型的最后一层必须是layer对象(如resnet系列,densenet系列,mobilenet系列等),如果是paddle.nn.Sequential对象(vgg系列网络),那么通过laery_list[-1]获取到的name则是错误的。
#根据参数返回新的语义分割头
def get_seg_head(feature_chanel,cls_nums=10,kernel_size=(1,1)):
return paddle.nn.Conv2D(in_channels=feature_chanel, out_channels=cls_nums, kernel_size=kernel_size)
#按照参数返回新的图像分类头
def get_fc_layer(feature_nums,cls_nums=10,drop_rate=None):
if drop_rate is None:
return paddle.nn.Linear(feature_nums, cls_nums)
else:
return paddle.nn.Sequential(
paddle.nn.Dropout(drop_rate),
paddle.nn.Linear(feature_nums, cls_nums)
)
#动态修改模型的最后一个layer
def reset_model_head(model,cls_nums=4):
# 获取模型的name和layer
layer_list=[(name,atom_layer) for name,atom_layer in model.named_sublayers()]
# 获取最后一个layer的基本信息
feature_layer_name,feature_layer=layer_list[-1]
feature_layer_shape=feature_layer.weight.shape
feature_layer_type=feature_layer.__class__
print("feature layer:",feature_layer_name,feature_layer_shape,feature_layer_type)
#获取新的分类头
if len(feature_layer_shape)==4: #如果是语义分割 shape:out_chanel,in_chanerl,kernel_size_w,kernel_size_h
new_head=get_seg_head(feature_layer_shape[1],cls_nums=4)
else:#如果是图像分类 shape:in_feature_nums,out_feature_nums
new_head=get_fc_layer(feature_layer_nums,cls_nums)
print("new layer:",new_head.weight.shape,new_head.__class__)
#根据参数动态设置模型的最后一个layer
strs="model.%s=new_head"%feature_layer_name
exec(strs)
return model
修改模型最后一层的示例
import paddle
model=paddle.vision.resnet18()
#paddle下除了vgg系列模型外,语义分割模型与图像分类模型都是通用的
model=reset_model_head(model,cls_nums=4)
layer_list=[(name,atom_layer) for name,atom_layer in model.named_sublayers()]
#print(model)
feature_layer_name,feature_layer=layer_list[-1]
feature_layer_shape=feature_layer.weight.shape
feature_layer_type=feature_layer.__class__
print("feature layer:",feature_layer_name,feature_layer_shape,feature_layer_type)
代码执行输出如图1所示
