0
点赞
收藏
分享

微信扫一扫

paddlepaddle 19 动态修改模型的最后一层

素锦时年_1b00 2022-03-24 阅读 64

 在进行迁移学习时,通常需要修改模型的最后一层,按照需求重新进行定义。但是,迁移学习需要在众多的模型中进行对比实验,而定义最后一个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所示

图1 修改模型的最后一层示例

 

举报

相关推荐

0 条评论