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
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
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