Beispiel #1
0
    def wider_conv2d(self, model, layer_name, new_width, config):
        # modify graph
        new_graph = model.graph.copy()
        new_node = new_graph.get_nodes(layer_name)[0]
        assert new_node.type == 'Conv2D' or new_node.type == 'Conv2D_Pooling', 'must wide a conv'
        new_node.config['filters'] = new_width

        # logger.debug(new_graph.to_json())
        # construct model
        new_model = MyModel(config=config, graph=new_graph)
        self.copy_weight(model, new_model)
        # inherit weight
        w_conv1, b_conv1 = model.get_layers(layer_name)[0].get_weights()
        w_conv2, b_conv2 = model.get_layers(layer_name,
                                            next_layer=True,
                                            type=['Conv2D', 'Conv2D_Pooling'
                                                  ])[0].get_weights()

        new_w_conv1, new_b_conv1, new_w_conv2 = Net2Net._wider_conv2d_weight(
            w_conv1, b_conv1, w_conv2, new_width, "net2wider")

        new_model.get_layers(layer_name)[0].set_weights(
            [new_w_conv1, new_b_conv1])
        new_model.get_layers(layer_name,
                             next_layer=True,
                             type=['Conv2D', 'Conv2D_Pooling'
                                   ])[0].set_weights([new_w_conv2, b_conv2])

        return new_model
Beispiel #2
0
    def deeper_conv2d(self,
                      model,
                      layer_name,
                      config,
                      with_pooling,
                      kernel_size=3,
                      filters='same'):
        # construct graph
        new_graph = model.graph.copy()
        if with_pooling == False:
            type = 'Conv2D'
        else:
            type = 'Conv2D_Pooling'
        new_node = Node(type=type,
                        name='new',
                        config={
                            'kernel_size': kernel_size,
                            'filters': filters
                        })
        new_graph.deeper(layer_name, new_node)
        # logger.debug(new_graph.to_json())

        # construct model
        new_model = MyModel(config=config, graph=new_graph)

        # inherit weight
        # in fact there is no need to get w_conv1 and b_conv1
        # what we actually need is only w_conv1's shape
        # more specifically, only kh, kw and filters are needed, num_channel is not necessary
        node_type = model.graph.get_nodes(layer_name)[0].type
        if node_type == 'Conv2D' or node_type == 'Conv2D_Pooling':
            w_conv1, b_conv1 = new_model.get_layers(
                layer_name)[0].get_weights()
            # tensorflow kernel format: [filter_height, filter_width, in_channels, out_channels] channels_last
            # theano kernel format:     [output_channels, input_channels, filter_rows, filter_columns] channels_first
            if K.image_data_format() == "channels_first":  # theano format
                # convert_kernel function Converts a Numpy kernel matrix from Theano format to TensorFlow format, vise versa
                w_conv1 = convert_kernel(w_conv1)
            kh, kw, num_channel, filters = w_conv1.shape
        elif node_type == 'Group':
            kh, kw, filters = 3, 3, model.graph.get_nodes(
                layer_name)[0].config['filters']

        w_conv2, b_conv2 = new_model.get_layers(
            layer_name, next_layer=True)[0].get_weights()

        new_w_conv2, new_b_conv2 = Net2Net._deeper_conv2d_weight(
            kh=kh, kw=kw, filters=filters)

        new_model.get_layers(layer_name, next_layer=True)[0].set_weights(
            [new_w_conv2, new_b_conv2])
        self.copy_weight(model, new_model)
        return new_model
Beispiel #3
0
    def wider_group_conv2d(self, model, layer_name, new_width, config):
        # modify graph
        new_graph = model.graph.copy()
        node = new_graph.get_nodes(layer_name)[0]
        assert node.type == 'Group', 'must wide a group layer'
        node.config['filters'] = new_width

        new_model = MyModel(config=config, graph=new_graph)
        self.copy_weight(model, new_model)

        filter_num = int(new_width / node.config['group_num'])

        for i in range(node.config['group_num']):
            if i == node.config['group_num'] - 1:  # last group
                filter_num = new_width - i * int(
                    (new_width / node.config['group_num']))

            layer_name_conv_1 = layer_name + '_conv2d_' + str(i) + '_1'
            layer_name_conv_2 = layer_name + '_conv2d_' + str(i) + '_2'

            # use keras get_layer function
            w_conv1, b_conv1 = model.model.get_layer(
                layer_name_conv_1).get_weights()
            w_conv2, b_conv2 = model.model.get_layer(
                layer_name_conv_2).get_weights()
            new_w_conv1, new_b_conv1, new_w_conv2 = Net2Net._wider_conv2d_weight(
                w_conv1, b_conv1, w_conv2, filter_num, "net2wider")

            new_model.model.get_layer(layer_name_conv_1).set_weights(
                [new_w_conv1, new_b_conv1])
            # new_model.model.get_layer(layer_name_conv_2).set_weights([new_w_conv2, b_conv2])

            if i == 0:
                w_conv_group = new_w_conv2
                b_conv_group = b_conv2
            else:
                w_conv_group = np.concatenate((w_conv_group, new_w_conv2),
                                              axis=3)
                b_conv_group = np.concatenate((b_conv_group, b_conv2), axis=0)

        # find group layer's next conv layer

        w_conv2, b_conv2 = model.get_layers(
            layer_name,
            next_layer=True,
            type=['Conv2D', 'Conv2D_Pooling', 'Group'])[0].get_weights()

        new_w_conv_group, new_b_conv_group, new_w_conv2 = Net2Net._wider_conv2d_weight(
            w_conv_group, b_conv_group, w_conv2, new_width, "net2wider")

        for i in range(node.config['group_num']):
            layer_name_conv_2 = layer_name + '_conv2d_' + str(i) + '_2'

            if i == node.config['group_num'] - 1:
                new_model.model.get_layer(layer_name_conv_2).set_weights([
                    new_w_conv_group[:, :, :, i * filter_num:],
                    new_b_conv_group[i * filter_num:]
                ])
            else:
                new_model.model.get_layer(layer_name_conv_2).set_weights([
                    new_w_conv_group[:, :, :,
                                     i * filter_num:(i + 1) * filter_num],
                    new_b_conv_group[i * filter_num:(i + 1) * filter_num]
                ])

        new_model.get_layers(layer_name,
                             next_layer=True,
                             type=['Conv2D', 'Conv2D_Pooling', 'Group'
                                   ])[0].set_weights([new_w_conv2, b_conv2])

        return new_model