其他分享
首页 > 其他分享> > 卷积层通道剪裁

卷积层通道剪裁

作者:互联网

卷积层通道剪裁

Pruner

classpaddleslim.prune.Pruner(criterion="l1_norm")

对卷积网络的通道进行一次剪裁。剪裁一个卷积层的通道,是指剪裁该卷积层输出的通道。卷积层的权重形状为 [output_channel, input_channel, kernel_size, kernel_size] ,通过剪裁该权重的第一纬度达到剪裁输出通道数的目的。

参数:

返回: 一个Pruner类的实例

示例代码:

from paddleslim.prune import Pruner

pruner = Pruner()

paddleslim.prune.Pruner.prune(programscopeparamsratiosplace=Nonelazy=Falseonly_graph=Falseparam_backup=Falseparam_shape_backup=False)

对目标网络的一组卷积层的权重进行裁剪。

参数:

for block in program.blocks:

    for param in block.all_parameters():

        print("param: {}; shape: {}".format(param.name, param.shape))

返回:

示例:

执行以下示例代码。

import paddle.fluid as fluid

from paddle.fluid.param_attr import ParamAttr

from paddleslim.prune import Pruner

 

def conv_bn_layer(input,

                  num_filters,

                  filter_size,

                  name,

                  stride=1,

                  groups=1,

                  act=None):

    conv = fluid.layers.conv2d(

        input=input,

        num_filters=num_filters,

        filter_size=filter_size,

        stride=stride,

        padding=(filter_size - 1) // 2,

        groups=groups,

        act=None,

        param_attr=ParamAttr(name=name + "_weights"),

        bias_attr=False,

        name=name + "_out")

    bn_name = name + "_bn"

    return fluid.layers.batch_norm(

        input=conv,

        act=act,

        name=bn_name + '_output',

        param_attr=ParamAttr(name=bn_name + '_scale'),

        bias_attr=ParamAttr(bn_name + '_offset'),

        moving_mean_name=bn_name + '_mean',

        moving_variance_name=bn_name + '_variance', )

 

main_program = fluid.Program()

startup_program = fluid.Program()

#   X       X              O       X              O

# conv1-->conv2-->sum1-->conv3-->conv4-->sum2-->conv5-->conv6

#     |            ^ |                    ^

#     |____________| |____________________|

#

# X: prune output channels

# O: prune input channels

with fluid.program_guard(main_program, startup_program):

    input = fluid.data(name="image", shape=[None, 3, 16, 16])

    conv1 = conv_bn_layer(input, 8, 3, "conv1")

    conv2 = conv_bn_layer(conv1, 8, 3, "conv2")

    sum1 = conv1 + conv2

    conv3 = conv_bn_layer(sum1, 8, 3, "conv3")

    conv4 = conv_bn_layer(conv3, 8, 3, "conv4")

    sum2 = conv4 + sum1

    conv5 = conv_bn_layer(sum2, 8, 3, "conv5")

    conv6 = conv_bn_layer(conv5, 8, 3, "conv6")

 

place = fluid.CPUPlace()

exe = fluid.Executor(place)

scope = fluid.Scope()

exe.run(startup_program, scope=scope)

pruner = Pruner()

main_program, _, _ = pruner.prune(

    main_program,

    scope,

    params=["conv4_weights"],

    ratios=[0.5],

    place=place,

    lazy=False,

    only_graph=False,

    param_backup=False,

    param_shape_backup=False)

 

for param in main_program.global_block().all_parameters():

    if "weights" in param.name:

        print("param name: {}; param shape: {}".format(param.name, param.shape))

sensitivity

paddleslim.prune.sensitivity(programplaceparam_nameseval_funcsensitivities_file=Nonepruned_ratios=None)

计算网络中每个卷积层的敏感度。每个卷积层的敏感度信息统计方法为:依次剪掉当前卷积层不同比例的输出通道数,在测试集上计算剪裁后的精度损失。得到敏感度信息后,可以通过观察或其它方式确定每层卷积的剪裁率。

参数:

返回:

{"weight_0":

   {0.1: 0.22,

    0.2: 0.33

   },

 "weight_1":

   {0.1: 0.21,

    0.2: 0.4

   }

}

其中, weight_0 是卷积层参数的名称, sensitivities['weight_0'] 的 value 为剪裁比例, value 为精度损失的比例。

示例:

点击 AIStudio 运行以下示例代码。

import paddle

import numpy as np

import paddle.fluid as fluid

from paddle.fluid.param_attr import ParamAttr

from paddleslim.prune import sensitivity

import paddle.dataset.mnist as reader

 

def conv_bn_layer(input,

                  num_filters,

                  filter_size,

                  name,

                  stride=1,

                  groups=1,

                  act=None):

    conv = fluid.layers.conv2d(

        input=input,

        num_filters=num_filters,

        filter_size=filter_size,

        stride=stride,

        padding=(filter_size - 1) // 2,

        groups=groups,

        act=None,

        param_attr=ParamAttr(name=name + "_weights"),

        bias_attr=False,

        name=name + "_out")

    bn_name = name + "_bn"

    return fluid.layers.batch_norm(

        input=conv,

        act=act,

        name=bn_name + '_output',

        param_attr=ParamAttr(name=bn_name + '_scale'),

        bias_attr=ParamAttr(bn_name + '_offset'),

        moving_mean_name=bn_name + '_mean',

        moving_variance_name=bn_name + '_variance', )

 

main_program = fluid.Program()

startup_program = fluid.Program()

#   X       X              O       X              O

# conv1-->conv2-->sum1-->conv3-->conv4-->sum2-->conv5-->conv6

#     |            ^ |                    ^

#     |____________| |____________________|

#

# X: prune output channels

# O: prune input channels

image_shape = [1,28,28]

with fluid.program_guard(main_program, startup_program):

    image = fluid.data(name='image', shape=[None]+image_shape, dtype='float32')

    label = fluid.data(name='label', shape=[None, 1], dtype='int64')

    conv1 = conv_bn_layer(image, 8, 3, "conv1")

    conv2 = conv_bn_layer(conv1, 8, 3, "conv2")

    sum1 = conv1 + conv2

    conv3 = conv_bn_layer(sum1, 8, 3, "conv3")

    conv4 = conv_bn_layer(conv3, 8, 3, "conv4")

    sum2 = conv4 + sum1

    conv5 = conv_bn_layer(sum2, 8, 3, "conv5")

    conv6 = conv_bn_layer(conv5, 8, 3, "conv6")

    out = fluid.layers.fc(conv6, size=10, act="softmax")

#    cost = fluid.layers.cross_entropy(input=out, label=label)

#    avg_cost = fluid.layers.mean(x=cost)

    acc_top1 = fluid.layers.accuracy(input=out, label=label, k=1)

#    acc_top5 = fluid.layers.accuracy(input=out, label=label, k=5)

 

 

place = fluid.CPUPlace()

exe = fluid.Executor(place)

exe.run(startup_program)

 

val_reader = paddle.batch(reader.test(), batch_size=128)

val_feeder = feeder = fluid.DataFeeder(

        [image, label], place, program=main_program)

 

def eval_func(program):

 

    acc_top1_ns = []

    for data in val_reader():

        acc_top1_n = exe.run(program,

                             feed=val_feeder.feed(data),

                             fetch_list=[acc_top1.name])

        acc_top1_ns.append(np.mean(acc_top1_n))

    return np.mean(acc_top1_ns)

param_names = []

for param in main_program.global_block().all_parameters():

    if "weights" in param.name:

        param_names.append(param.name)

sensitivities = sensitivity(main_program,

                            place,

                            param_names,

                            eval_func,

                            sensitivities_file="./sensitive.data",

                            pruned_ratios=[0.1, 0.2, 0.3])

print(sensitivities)

merge_sensitive

paddleslim.prune.merge_sensitive(sensitivities)

合并多个敏感度信息。

参数:

返回:

{"weight_0":

   {0.1: 0.22,

    0.2: 0.33

   },

 "weight_1":

   {0.1: 0.21,

    0.2: 0.4

   }

}

其中, weight_0 是卷积层参数的名称, sensitivities['weight_0'] 的 value 为剪裁比例, value 为精度损失的比例。

示例:

from paddleslim.prune import merge_sensitive

sen0 = {"weight_0":

   {0.1: 0.22,

    0.2: 0.33

   },

 "weight_1":

   {0.1: 0.21,

    0.2: 0.4

   }

}

sen1 = {"weight_0":

   {0.3: 0.41,

   },

 "weight_2":

   {0.1: 0.10,

    0.2: 0.35

   }

}

sensitivities = merge_sensitive([sen0, sen1])

print(sensitivities)

load_sensitivities

paddleslim.prune.load_sensitivities(sensitivities_file)

从文件中加载敏感度信息。

参数:

返回:

示例:

import pickle

from paddleslim.prune import load_sensitivities

sen = {"weight_0":

   {0.1: 0.22,

    0.2: 0.33

   },

 "weight_1":

   {0.1: 0.21,

    0.2: 0.4

   }

}

sensitivities_file = "sensitive_api_demo.data"

with open(sensitivities_file, 'wb') as f:

    pickle.dump(sen, f)

sensitivities = load_sensitivities(sensitivities_file)

print(sensitivities)

get_ratios_by_loss

paddleslim.prune.get_ratios_by_loss(sensitivitiesloss)

根据敏感度和精度损失阈值计算出一组剪切率。对于参数 w , 其剪裁率为使精度损失低于 loss 的最大剪裁率。

参数:

返回:

示例:

from paddleslim.prune import get_ratios_by_loss

sen = {"weight_0":

   {0.1: 0.22,

    0.2: 0.33

   },

 "weight_1":

   {0.1: 0.21,

    0.2: 0.4

   }

}

 

ratios = get_ratios_by_loss(sen, 0.3)

print(ratios)

 

标签:name,卷积,bn,fluid,param,program,sensitivities,剪裁,通道
来源: https://www.cnblogs.com/wujianming-110117/p/14424081.html