|
02、VGG16预训练好的参数加载与模型网络构建_笔记
vgg16与vgg19预训练好的参数文件下载【回复本帖可见】:
- # -*- coding: utf-8 -*-
- __author__ = 'dongfangyao'
- __date__ = '2019/3/12 下午5:19'
- __product__ = 'PyCharm'
- __filename__ = '1_vgg16_content'
- import numpy as np
- vgg16_data = np.load('vgg16.npy', encoding='latin1')
- print(type(vgg16_data))
- data_dict = vgg16_data.item()
- print(type(data_dict))
- print(data_dict.keys())
- print(len(data_dict))
- conv1_1 = data_dict['conv1_1']
- print(len(conv1_1))
- w, b = conv1_1
- print(w.shape)
- print(b.shape)
- conv3_1 = data_dict['conv3_1']
- print(len(conv3_1))
- w, b = conv3_1
- print(w.shape)
- print(b.shape)
- fc6 = data_dict['fc6']
- w, b = fc6
- print(w.shape)
- print(b.shape)
- fc8 = data_dict['fc8']
- w, b = fc8
- print(w.shape)
- print(b.shape)
复制代码
- # -*- coding: utf-8 -*-
- __author__ = 'dongfangyao'
- __date__ = '2019/3/12 下午5:33'
- __product__ = 'PyCharm'
- __filename__ = '2_image_style_con'
- import tensorflow as tf
- from tensorflow import logging
- import os
- import time
- import numpy as np
- logging.set_verbosity(logging.INFO)
- # logging.info('dfy_88888')
- # vgg net 中写死的 归一化的数据预处理
- VGG_MEAN = [103.939, 116.779, 123.68]
- class VGGNet:
- """
- 构建VGG16的网络结构 并从预训练好的模型提取参数 加载
- """
- def __init__(self, data_dict):
- self.data_dict = data_dict
- def get_conv_kernel(self, name):
- # 卷积核的参数:w 0 b 1
- return tf.constant(self.data_dict[name][0], name='conv')
- def get_fc_weight(self, name):
- return tf.constant(self.data_dict[name][0], name='fc')
- def get_bias(self, name):
- return tf.constant(self.data_dict[name][1], name='bias')
- def conv_layer(self, inputs, name):
- """
- 构建一个卷积计算层
- :param inputs: 输入的feature_map
- :param name: 卷积层的名字 也是获得参数的key 不能出错
- :return:
- """
- with tf.name_scope(name):
- """
- 多使用name_scope的好处:1、防止参数命名冲突 2、tensorboard可视化时很规整
- 如果scope里面有变量需要训练时则用tf.variable_scope
- """
- conv_w = self.get_conv_kernel(name)
- conv_b = self.get_bias(name)
- # tf.layers.conv2d() 这是一个封装更高级的api
- # 里面并没有提供接口来输入卷积核参数 这里不能用 平时训练cnn网络时非常好用
- result = tf.nn.conv2d(input=inputs, filter=conv_w, strides=[1, 1, 1, 1], padding='SAME', name=name)
- result = tf.nn.bias_add(result, conv_b)
- result = tf.nn.relu(result)
- return result
- def pooling_layer(self, inputs, name):
- # tf.layers.max_pooling2d()
- # tf.nn.max_pool 这里的池化层没有参数 两套api都可以用
- return tf.nn.max_pool(inputs, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME', name=name)
- def fc_layer(self, inputs, name, activation=tf.nn.relu):
- """
- 构建全连接层
- :param inputs: 输入
- :param name:
- :param activation: 是否有激活函数的封装
- :return:
- """
- with tf.name_scope(name):
- fc_w = self.get_fc_weight(name)
- fc_b = self.get_bias(name)
- # fc: wx+b 线性变换
- result = tf.nn.bias_add(tf.matmul(inputs, fc_w), fc_b)
- if activation is None:
- # vgg16的最后是不需relu激活的
- return result
- else:
- return activation(result)
- def flatten_op(self, inputs, name):
- # 展平操作 为了后续的fc层必须将维度展平
- with tf.name_scope(name):
- # [NHWC]---> [N, H*W*C]
- x_shape = inputs.get_shape().as_list()
- dim = 1
- for d in x_shape[1:]:
- dim *= d
- inputs = tf.reshape(inputs, shape=[-1, dim])
- # 直接用现成api也是可以的
- # return tf.layers.flatten(inputs)
- return inputs
- def build(self, input_rgb):
- """
- 构建vgg16网络结构 抽取特征 FP过程
- :param input_rgb: [1, 224, 224, 3]
- :return:
- """
- start_time = time.time()
- logging.info('building start...')
- # 在通道维度上分离 深度可分离卷积中也需要用到这个api
- r, g, b = tf.split(input_rgb, num_or_size_splits=3, axis=3)
- # 在通道维度上拼接
- # 输入vgg网络的图像是bgr的(与OpenCV一样 倒序的)而不是rgb
- x_bgr = tf.concat(values=[
- b - VGG_MEAN[0],
- g - VGG_MEAN[1],
- r - VGG_MEAN[2],
- ], axis=3)
- assert x_bgr.get_shape().as_list()[1:] == [224, 224, 3]
- # 构建网络
- # stage 1
- self.conv1_1 = self.conv_layer(x_bgr, 'conv1_1')
- self.conv1_2 = self.conv_layer(self.conv1_1, 'conv1_2')
- self.pool1 = self.pooling_layer(self.conv1_2, 'pool1')
- # stage 2
- self.conv2_1 = self.conv_layer(self.pool1, 'conv2_1')
- self.conv2_2 = self.conv_layer(self.conv2_1, 'conv2_2')
- self.pool2 = self.pooling_layer(self.conv2_2, 'pool2')
- # stage 3
- self.conv3_1 = self.conv_layer(self.pool2, 'conv3_1')
- self.conv3_2 = self.conv_layer(self.conv3_1, 'conv3_2')
- self.conv3_3 = self.conv_layer(self.conv3_2, 'conv3_3')
- self.pool3 = self.pooling_layer(self.conv3_3, 'pool3')
- # stage 4
- self.conv4_1 = self.conv_layer(self.pool3, 'conv4_1')
- self.conv4_2 = self.conv_layer(self.conv4_1, 'conv4_2')
- self.conv4_3 = self.conv_layer(self.conv4_2, 'conv4_3')
- self.pool4 = self.pooling_layer(self.conv4_3, 'pool4')
- # stage 5
- self.conv5_1 = self.conv_layer(self.pool4, 'conv5_1')
- self.conv5_2 = self.conv_layer(self.conv5_1, 'conv5_2')
- self.conv5_3 = self.conv_layer(self.conv5_2, 'conv5_3')
- self.pool5 = self.pooling_layer(self.conv5_3, 'pool5')
- # flatten_op
- self.flatten = self.flatten_op(self.pool5, 'flatten_op')
- # fc
- self.fc6 = self.fc_layer(self.flatten, 'fc6')
- self.fc7 = self.fc_layer(self.fc6, 'fc7')
- self.fc8 = self.fc_layer(self.fc7, 'fc8', activation=None)
- self.logits = tf.nn.softmax(self.fc8, name='logits')
- logging.info('building end... 耗时%3d秒' % (time.time() - start_time))
- vgg16_npy_path = './vgg16.npy'
- vgg16_data = np.load(vgg16_npy_path, encoding='latin1')
- print(type(vgg16_data))
- data_dict = vgg16_data.item()
- vgg16_for_result = VGGNet(data_dict)
- image_rgb = tf.placeholder(dtype=tf.float32, shape=[1, 224, 224, 3], name='image_rgb')
- vgg16_for_result.build(image_rgb)
- print(vgg16_for_result.conv1_1)
- print(vgg16_for_result.fc6)
复制代码
|
|