TensorFlow+深度学习笔记3

TensorFlow+深度学习笔记3

标签(空格分隔): TensorFlow+深度学习笔记


本周掌握的知识:

  • 熟悉AlexNet网络模型结构,并使用AlexNet网络在ImageNet数据集上训练好的模型进行Inference
  • 熟悉VGG网络模型结构,并使用VGG网络在ImageNet数据集上训练好的模型进行Inference
  • 了解将caffe模型转换为TensorFlow模型

Task 4 Deeper Network

  在了解了深度学习基本概念之后,大家就需要开始接触一些经典的网络模型
了。上周的 LeNet 是最简单的 DCNN(Deep Convolutional Neural Network),本周
大家将接触层数更多的 AlexNet 和 VGG。


1 学习清单

  • 学习理解 AlexNet。

  • 学习理解 VGG。

  • 分别使用两个网络在 ImageNet 数据集上训练好的模型进行 Inference(比如
    输入一张猫的图像,模型判断出是猫)

2 参考资料

3 周报内容

  • 跟上周一样,解释两个网络每一个层的功能、具体如何实现(比如卷积是怎
    么做的、pooling 怎么做、fully connected 怎么做)、每个参数对应的意义。贴
    上代码,并解释每一句关键代码的意义。

  • 不需要进行训练。只需要用参考资料提供的代码和模型进行 Inference。在网
    上找多一些图像去测试,实验结果截图贴报告里(如下图。当然,这张图片
    的预测结果错了= =)。
    1.png-219kB


学习理解 AlexNet


AlexNet模型结构

  文件myalexnet_forward.py不是用来训练模型的,它的作用是将输入的图像经过AlexNet网络转变为特定值,然后输出结果。
  所以在开始前,先来了解AlexNet的网络结构。参考链接深度学习AlexNet模型详细分析
  1.png-90.4kB

  如上图所示,采用是两台GPU服务器,所有会看到两个流程图,以一台GPU服务器为例做描述。该模型一共分为八层(5个卷基层+3个全连接层)在每一个卷积层中包含了激励函数RELU以及正则化处理,然后再经过Max池化层

代码的AlexNet网络结构(我根据AlexNet网络论文和参考链接画出代码使用的AlexNet的结构):

  • conv1

  2.png-64.5kB
  说明:论文第1层卷积层的padding方式是”VALID”,但是代码中使用的是”SAME”,所以在这一层中作者代码输出的结果为28*28*96,而论文的为27*27*96。关于padding两种不同方式的解释参考连接关于padding参数详解参考

  对于“SAME”,输出的形状计算如:new_height = new_widht = [W/S]
  对于“VALID”,输出的形状计算如:new_height = new_widht = [(W-F+1)/S]
  其中W为输入的size,F为filter的size,S为步长,[]为向上取整

  • conv2

  3.png-86.4kB

  • conv3

  4.png-35kB

  • conv4

  5.png-45.8kB

  • conv5

  6.png-45.8kB

  • fc6

  7.png-46.8kB

  • fc7

  8.png-50.8kB

  • fc8

  9.png-22.6kB

AlexNet代码解释

# coding: utf-8
################################################################################
#Michael Guerzhoy and Davi Frossard, 2016
#AlexNet implementation in TensorFlow, with weights
#Details: 
#http://www.cs.toronto.edu/~guerzhoy/tf_alexnet/
#
#With code from https://github.com/ethereon/caffe-tensorflow
#Model from  https://github.com/BVLC/caffe/tree/master/models/bvlc_alexnet
#Weights from Caffe converted using https://github.com/ethereon/caffe-tensorflow
#
#
################################################################################

from numpy import *
import os
from pylab import *
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import time
from scipy.misc import imread
from scipy.misc import imresize
import matplotlib.image as mpimg
from scipy.ndimage import filters
import urllib
from numpy import random


import tensorflow as tf

from caffe_classes import class_names

train_x = zeros((1, 227,227,3)).astype(float32)
train_y = zeros((1, 1000))
xdim = train_x.shape[1:]
ydim = train_y.shape[1]



################################################################################
#Read Image, and change to BGR
#将每张图像的R通道(红色)和B通道(蓝色)互换

im1 = (imread("rabbit1.jpg")[:,:,:3]).astype(float32)
im1 = imresize(im1, (227, 227))
im1 = im1 - mean(im1)
im1[:, :, 0], im1[:, :, 2] = im1[:, :, 2], im1[:, :, 0]

im2 = (imread("dog.png")[:,:,:3]).astype(float32)
im2 = imresize(im2, (227, 227))
im2[:, :, 0], im2[:, :, 2] = im2[:, :, 2], im2[:, :, 0]


################################################################################

# (self.feed('data')
#         .conv(11, 11, 96, 4, 4, padding='VALID', name='conv1')
#         .lrn(2, 2e-05, 0.75, name='norm1')
#         .max_pool(3, 3, 2, 2, padding='VALID', name='pool1')
#         .conv(5, 5, 256, 1, 1, group=2, name='conv2')
#         .lrn(2, 2e-05, 0.75, name='norm2')
#         .max_pool(3, 3, 2, 2, padding='VALID', name='pool2')
#         .conv(3, 3, 384, 1, 1, name='conv3')
#         .conv(3, 3, 384, 1, 1, group=2, name='conv4')
#         .conv(3, 3, 256, 1, 1, group=2, name='conv5')
#         .fc(4096, name='fc6')
#         .fc(4096, name='fc7')
#         .fc(1000, relu=False, name='fc8')
#         .softmax(name='prob'))

#In Python 3.5, change this to:
#net_data = load(open("bvlc_alexnet.npy", "rb"), encoding="latin1").item()
net_data = load("bvlc_alexnet.npy").item()

#参数解释
#input代表输入的数据,可能是多张图像同时传入;kernel是权重;biases是偏移;k_h, k_w是kernel的高宽;c_0是输出的通道数
#s_h, s_w是strides的高和宽;padding="VALID"代表不补零
def conv(input, kernel, biases, k_h, k_w, c_o, s_h, s_w,  padding="VALID", group=1):
    '''From https://github.com/ethereon/caffe-tensorflow
    '''
    #input.get_shape()中input的数据类型只能是tensor,且返回的是一个元组(tuple),记录了每一个维度的数值
    #这里返回[Dimension(None.),Dimension(227),Dimension(227),Dimension(3)]
    #所以c_i的值为3,代表输入的图像的通道数为3
    c_i = input.get_shape()[-1]
    #判断c_i%group==0、c_o%group==0,否则出错
    assert c_i%group==0
    assert c_o%group==0
    convolve = lambda i, k: tf.nn.conv2d(i, k, [1, s_h, s_w, 1], padding=padding)

    #这里的作用就是加快速度,如果group等于1,就把所有数据丢到一个GPU上运行
    #如果group>1,意思就是将图像数据按照第三维度切割分成group个,然后放到group个GPU上运行
    if group==1:
        conv = convolve(input, kernel)
    else:
        #tf.split(dimension, num_split, input):dimension的意思就是输入张量的哪一个维度,
        #如果是0就表示对第0维度进行切割。num_split就是切割的数量,如果是2就表示输入张量被切成2份,每一份是一个列表。
        input_groups = tf.split(input, group, 3)
        kernel_groups = tf.split(kernel, group, 3)
        output_groups = [convolve(i, k) for i,k in zip(input_groups, kernel_groups)]
        #在第3维度连接output_groups
        conv = tf.concat(output_groups,3)
        #将得到的结果加上bisaes,然后再reshape成[-1]+conv.get_shape().as_list()[1:]
        #conv.get_shape().as_list()[1:]代表卷积操作conv2d后每张图像的[长、宽、通道数]
        #[-1]代表输入的数据可能是多张图像
    return  tf.reshape(tf.nn.bias_add(conv, biases), [-1]+conv.get_shape().as_list()[1:])


#(None,)代表输入的数据可能是多张图像
#xdim代表(227,227,3)
x = tf.placeholder(tf.float32, (None,) + xdim)


#conv1 第1层输入数据为原始的227*227*3的图像,输出28*28*96的图像
#conv(11, 11, 96, 4, 4, padding='VALID', name='conv1')
k_h = 11; k_w = 11; c_o = 96; s_h = 4; s_w = 4
#从bvlc_alexnet.npy中取出第一层卷积层的kernel、biases参数
conv1W = tf.Variable(net_data["conv1"][0])
conv1b = tf.Variable(net_data["conv1"][1])
#论文的第一层卷积层的padding是VALID的,但是代码作者使用了SAME
#对于“SAME”,输出的形状计算如:new_height = new_widht = [W/S]
#对于“VALID”,输出的形状计算如:new_height = new_widht = [(W-F+1)/S]
#关于padding参数详解参考:https://blog.csdn.net/wuzqchom/article/details/74785643
#其中W为输入的size,F为filter的size,S为步长,[]为向上取整,所以这一步得到的结果为57*57*96
conv1_in = conv(x, conv1W, conv1b, k_h, k_w, c_o, s_h, s_w, padding="SAME", group=1)
#激活函数
conv1 = tf.nn.relu(conv1_in)

#lrn1 一种正则化方法,返回的数据和输入数据具有相同的shape
#具体参考链接https://blog.csdn.net/mao_xiao_feng/article/details/53488271
#lrn(2, 2e-05, 0.75, name='norm1')
radius = 2; alpha = 2e-05; beta = 0.75; bias = 1.0
lrn1 = tf.nn.local_response_normalization(conv1,
                                                  depth_radius=radius,
                                                  alpha=alpha,
                                                  beta=beta,
                                                  bias=bias)

#maxpool1 最大化池化层,等价于下采样操作
#模板的长宽为3,垂直水平的步长都为2,所以这一步得到的结果为28*28*96
#max_pool(3, 3, 2, 2, padding='VALID', name='pool1')
k_h = 3; k_w = 3; s_h = 2; s_w = 2; padding = 'VALID'
maxpool1 = tf.nn.max_pool(lrn1, ksize=[1, k_h, k_w, 1], strides=[1, s_h, s_w, 1], padding=padding)


#conv2 第2层输入数据为原始的28*28*96的图像,输出13*13*256的图像
#conv(5, 5, 256, 1, 1, group=2, name='conv2')
k_h = 5; k_w = 5; c_o = 256; s_h = 1; s_w = 1; group = 2
conv2W = tf.Variable(net_data["conv2"][0])
conv2b = tf.Variable(net_data["conv2"][1])
#这一步输出的结果为[28/1] -> 28*28*256
conv2_in = conv(maxpool1, conv2W, conv2b, k_h, k_w, c_o, s_h, s_w, padding="SAME", group=group)
conv2 = tf.nn.relu(conv2_in)


#lrn2
#lrn(2, 2e-05, 0.75, name='norm2')
radius = 2; alpha = 2e-05; beta = 0.75; bias = 1.0
lrn2 = tf.nn.local_response_normalization(conv2,
                                                  depth_radius=radius,
                                                  alpha=alpha,
                                                  beta=beta,
                                                  bias=bias)

#maxpool2
#max_pool(3, 3, 2, 2, padding='VALID', name='pool2') 这一步输出的结果为[(28-3+1)/2]=13 -> 13*13*256                                           
k_h = 3; k_w = 3; s_h = 2; s_w = 2; padding = 'VALID'
maxpool2 = tf.nn.max_pool(lrn2, ksize=[1, k_h, k_w, 1], strides=[1, s_h, s_w, 1], padding=padding)

#conv3 第3层输入数据为原始的13*13*256的图像,输出13*13*384的图像
#conv(3, 3, 384, 1, 1, name='conv3') 
k_h = 3; k_w = 3; c_o = 384; s_h = 1; s_w = 1; group = 1
conv3W = tf.Variable(net_data["conv3"][0])
conv3b = tf.Variable(net_data["conv3"][1])
#这一步输出的结果为[13/1] -> 13*13*384
conv3_in = conv(maxpool2, conv3W, conv3b, k_h, k_w, c_o, s_h, s_w, padding="SAME", group=group)
conv3 = tf.nn.relu(conv3_in)

#conv4 第4层输入数据为原始的13*13*384的图像,输出13*13*384的图像
#conv(3, 3, 384, 1, 1, group=2, name='conv4')
k_h = 3; k_w = 3; c_o = 384; s_h = 1; s_w = 1; group = 2
conv4W = tf.Variable(net_data["conv4"][0])
conv4b = tf.Variable(net_data["conv4"][1])
conv4_in = conv(conv3, conv4W, conv4b, k_h, k_w, c_o, s_h, s_w, padding="SAME", group=group)
conv4 = tf.nn.relu(conv4_in)


#conv5 第4层输入数据为原始的13*13*384的图像,输出13*13*256的图像
#conv(3, 3, 256, 1, 1, group=2, name='conv5')
k_h = 3; k_w = 3; c_o = 256; s_h = 1; s_w = 1; group = 2
conv5W = tf.Variable(net_data["conv5"][0])
conv5b = tf.Variable(net_data["conv5"][1])
conv5_in = conv(conv4, conv5W, conv5b, k_h, k_w, c_o, s_h, s_w, padding="SAME", group=group)
conv5 = tf.nn.relu(conv5_in)

#maxpool5 这一步输出的结果为[(13-3+1)/2]=6 -> 6*6*256 
#max_pool(3, 3, 2, 2, padding='VALID', name='pool5')
k_h = 3; k_w = 3; s_h = 2; s_w = 2; padding = 'VALID'
maxpool5 = tf.nn.max_pool(conv5, ksize=[1, k_h, k_w, 1], strides=[1, s_h, s_w, 1], padding=padding)

#fc6
#fc(4096, name='fc6')
#每个6*6*256尺寸的滤波器对第六层的输入数据进行卷积运算生成一个运算结果,
#通过一个神经元输出这个运算结果;共有4096个6*6*256尺寸的滤波器对输入数据进行卷积运算,
#通过4096个神经元输出运算结果;这4096个运算结果通过relu激活函数生成4096个值;并通过drop运算后输出4096个本层的输出结果值。
fc6W = tf.Variable(net_data["fc6"][0])
fc6b = tf.Variable(net_data["fc6"][1])
fc6 = tf.nn.relu_layer(tf.reshape(maxpool5, [-1, int(prod(maxpool5.get_shape()[1:]))]), fc6W, fc6b)

#fc7
#fc(4096, name='fc7')
#第六层输出的4096个数据与第七层的4096个神经元进行全连接,
#然后经由relu7进行处理后生成4096个数据,再经过dropout7处理后输出4096个数据。
fc7W = tf.Variable(net_data["fc7"][0])
fc7b = tf.Variable(net_data["fc7"][1])
fc7 = tf.nn.relu_layer(fc6, fc7W, fc7b)

#fc8
#fc(1000, relu=False, name='fc8')
#第七层输出的4096个数据与第八层的1000个神经元进行全连接,经过训练后输出被训练的数值。
fc8W = tf.Variable(net_data["fc8"][0])
fc8b = tf.Variable(net_data["fc8"][1])
fc8 = tf.nn.xw_plus_b(fc7, fc8W, fc8b)


#prob
#softmax(name='prob'))
prob = tf.nn.softmax(fc8)

init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

t = time.time()
output = sess.run(prob, feed_dict = {x:[im1,im2]})
################################################################################

#Output:


for input_im_ind in range(output.shape[0]):
    inds = argsort(output)[input_im_ind,:]
    print "Image", input_im_ind
    for i in range(5):
        print class_names[inds[-1-i]], output[input_im_ind, inds[-1-i]]

print time.time()-t

AlexNet实验结果

  刚开始遇到这个错误:
  18.png-31.8kB
  这是个由于TensorFlow版本的原因,解决方法如下:
  19.png-84.8kB
  修改好的代码如下:
  20.png-33.3kB
  注意:需要同时更改tf.split()和tf.concat()参数的位置

  • 输入图像1
      Image0
      laska.png-99.5kB
      Image1
      poodle.png-115.5kB
  • 输出结果1
      21.png-33.1kB

  • 输入图像2
      Image0
      cat1.jpg-7.6kB
      Image1
      horse1.jpg-16.6kB

  • 输出结果2
      22.png-25.2kB

  • 输入图像3
      Image0
      rabbit1.jpg-10.2kB
      Image1
      dog.png-117.9kB

  • 输出结果3
      23.png-26.2kB


学习理解 VGG


VGG模型结构

  下图是网站给的VGG16的模型图
  10.png-98.7kB

  11.png-307.4kB

  阅读作者的代码可以知道,作者使用的VGG是D列的configuration,有13个卷积层和3个全连接层。ps:在第一周中由于我理解错误的原因,一直认为使用池化层来划分卷积层(错误地认为有多少个池化层就有多少卷积层),在此纠正这个错误的认识。正确地认识应该改是只要进行了卷积操作,该层就是一个卷积层。
  在画结构图之前先来复习最重要的接口tf.nn.conv2d():
  1.png-173.9kB
  来自链接TF-卷积函数 tf.nn.conv2d 介绍

  • conv1_1

  12.png-43.3kB

  • conv1_2

  13.png-43.2kB

  • pool1

  14.png-18.1kB

  • 后面的结构都大同小异,只需要注意卷积操作、池化操作的参数即可,详细的解释请看VGG代码解释部分

VGG代码解释

# coding: utf-8
########################################################################################
# Davi Frossard, 2016                                                                  #
# VGG16 implementation in TensorFlow                                                   #
# Details:                                                                             #
# http://www.cs.toronto.edu/~frossard/post/vgg16/                                      #
#                                                                                      #
# Model from https://gist.github.com/ksimonyan/211839e770f7b538e2d8#file-readme-md     #
# Weights from Caffe converted using https://github.com/ethereon/caffe-tensorflow      #
########################################################################################

import tensorflow as tf
import numpy as np
from scipy.misc import imread, imresize
from imagenet_classes import class_names


class vgg16:
    def __init__(self, imgs, weights=None, sess=None):
        self.imgs = imgs
        self.convlayers()
        self.fc_layers()
        self.probs = tf.nn.softmax(self.fc3l)
        if weights is not None and sess is not None:
            self.load_weights(weights, sess)


    def convlayers(self):
        self.parameters = []

        # zero-mean input
        # tf.name_scope可以让变量有相同的命名,只是限于tf.Variable的变量
        with tf.name_scope('preprocess') as scope:
            mean = tf.constant([123.68, 116.779, 103.939], dtype=tf.float32, shape=[1, 1, 1, 3], name='img_mean')
            images = self.imgs-mean

        # conv1_1 输入的数据是224*224*3,输出的数据是224*224*64
        with tf.name_scope('conv1_1') as scope:
            #kernel的size为3,in_channel=3,out_channel=64
            kernel = tf.Variable(tf.truncated_normal([3, 3, 3, 64], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            #有关tf.nn.conv2d()的复习参考上面链接
            conv = tf.nn.conv2d(images, kernel, [1, 1, 1, 1], padding='SAME')
            #tf.truncated_normal(shape, mean, stddev) :shape表示生成张量的维度,mean是均值,stddev是标准差。这个函数产生正太分布,均值和标准差自己设定。
            biases = tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv1_1 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # conv1_2 输入的数据是224*224*64,输出的数据是224*224*64
        with tf.name_scope('conv1_2') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 64], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            conv = tf.nn.conv2d(self.conv1_1, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv1_2 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # pool1 输入的数据是224*224*64,[224/2]=112所以输入的数据是112*112*64
        # kernel的size为2,垂直和水平步长都为2
        self.pool1 = tf.nn.max_pool(self.conv1_2,
                               ksize=[1, 2, 2, 1],
                               strides=[1, 2, 2, 1],
                               padding='SAME',
                               name='pool1')

        # conv2_1 输入的数据是112*112*64,输出的数据是112*112*128
        with tf.name_scope('conv2_1') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 128], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,但是通道数变了
            conv = tf.nn.conv2d(self.pool1, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[128], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv2_1 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # conv2_2 输入的数据是112*112*128,输出的数据是112*112*128
        with tf.name_scope('conv2_2') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 128, 128], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,通道数也没有变化
            conv = tf.nn.conv2d(self.conv2_1, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[128], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv2_2 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # pool2 输入的数据是112*112*128,[112/2]=56输出的数据是56*56*128
        self.pool2 = tf.nn.max_pool(self.conv2_2,
                               ksize=[1, 2, 2, 1],
                               strides=[1, 2, 2, 1],
                               padding='SAME',
                               name='pool2')

        # conv3_1 输入的数据是56*56*128,输出的数据是56*56*256
        with tf.name_scope('conv3_1') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 128, 256], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,通道数发生了变化
            conv = tf.nn.conv2d(self.pool2, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv3_1 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # conv3_2 输入的数据是56*56*256,输出的数据是56*56*256
        with tf.name_scope('conv3_2') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 256], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,通道数也没有变化
            conv = tf.nn.conv2d(self.conv3_1, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv3_2 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # conv3_3 输入的数据是56*56*256,输出的数据是56*56*256
        with tf.name_scope('conv3_3') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 256], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,通道数也没有变化
            conv = tf.nn.conv2d(self.conv3_2, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv3_3 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # pool3 输入的数据是56*56*256,[56/2]=28输出的数据是28*28*256
        self.pool3 = tf.nn.max_pool(self.conv3_3,
                               ksize=[1, 2, 2, 1],
                               strides=[1, 2, 2, 1],
                               padding='SAME',
                               name='pool3')

        # conv4_1 输入的数据是28*28*256,输出的数据是28*28*512
        with tf.name_scope('conv4_1') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 512], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,通道数发生了变化
            conv = tf.nn.conv2d(self.pool3, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv4_1 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # conv4_2 输入的数据是28*28*512,输出的数据是28*28*512
        with tf.name_scope('conv4_2') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 512, 512], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,通道数没有变化
            conv = tf.nn.conv2d(self.conv4_1, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv4_2 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # conv4_3 输入的数据是28*28*512,输出的数据是28*28*512
        with tf.name_scope('conv4_3') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 512, 512], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,通道数没有变化
            conv = tf.nn.conv2d(self.conv4_2, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv4_3 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # pool4 输入的数据是28*28*512,[28/2]=14输出的数据是14*14*512
        self.pool4 = tf.nn.max_pool(self.conv4_3,
                               ksize=[1, 2, 2, 1],
                               strides=[1, 2, 2, 1],
                               padding='SAME',
                               name='pool4')

        # conv5_1 输入的数据是14*14*512,输出的数据是14*14*512
        with tf.name_scope('conv5_1') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 512, 512], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,通道数没有变化
            conv = tf.nn.conv2d(self.pool4, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv5_1 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # conv5_2 输入的数据是14*14*512,输出的数据是14*14*512
        with tf.name_scope('conv5_2') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 512, 512], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,通道数没有变化
            conv = tf.nn.conv2d(self.conv5_1, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv5_2 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # conv5_3 输入的数据是14*14*512,输出的数据是14*14*512
        with tf.name_scope('conv5_3') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 512, 512], dtype=tf.float32,
                                                     stddev=1e-1), name='weights')
            # 这里步长为[1, 1, 1, 1],padding=‘SAME’,所以卷积完后长宽不变,通道数没有变化
            conv = tf.nn.conv2d(self.conv5_2, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),
                                 trainable=True, name='biases')
            out = tf.nn.bias_add(conv, biases)
            self.conv5_3 = tf.nn.relu(out, name=scope)
            self.parameters += [kernel, biases]

        # pool5 输入的数据是14*14*512,[14/2]=7输出的数据是7*7*512
        self.pool5 = tf.nn.max_pool(self.conv5_3,
                               ksize=[1, 2, 2, 1],
                               strides=[1, 2, 2, 1],
                               padding='SAME',
                               name='pool4')

    def fc_layers(self):
        # fc1 输入的数据是batches*14*14*512,输出的数据是batches*4096
        with tf.name_scope('fc1') as scope:
            #shape = 7*7*512
            shape = int(np.prod(self.pool5.get_shape()[1:]))
            fc1w = tf.Variable(tf.truncated_normal([shape, 4096],
                                                         dtype=tf.float32,
                                                         stddev=1e-1), name='weights')
            fc1b = tf.Variable(tf.constant(1.0, shape=[4096], dtype=tf.float32),
                                 trainable=True, name='biases')
            pool5_flat = tf.reshape(self.pool5, [-1, shape])
            # 矩阵相乘pool5_flat.shape=[-1,shape], fc1w.shape=[shape,4096]
            # tf.matmul(pool5_flat, fc1w).shape = [-1,4096]
            # fc1l.shape = [-1,4096]
            fc1l = tf.nn.bias_add(tf.matmul(pool5_flat, fc1w), fc1b)
            self.fc1 = tf.nn.relu(fc1l)
            self.parameters += [fc1w, fc1b]

        # fc2 输入的数据是batches*4096,输出的数据是batches*4096
        with tf.name_scope('fc2') as scope:
            fc2w = tf.Variable(tf.truncated_normal([4096, 4096],
                                                         dtype=tf.float32,
                                                         stddev=1e-1), name='weights')
            fc2b = tf.Variable(tf.constant(1.0, shape=[4096], dtype=tf.float32),
                                 trainable=True, name='biases')
            # 矩阵相乘self.fc1.shape=[-1,4096], fc2w.shape=[4096,4096]
            # tf.matmul(self.fc1, fc2w).shape = [-1,4096]
            # fc2l.shape = [-1,4096]
            fc2l = tf.nn.bias_add(tf.matmul(self.fc1, fc2w), fc2b)
            self.fc2 = tf.nn.relu(fc2l)
            self.parameters += [fc2w, fc2b]

        # fc3 输入的数据是batches*1000,输出的数据是batches*1000
        with tf.name_scope('fc3') as scope:
            fc3w = tf.Variable(tf.truncated_normal([4096, 1000],
                                                         dtype=tf.float32,
                                                         stddev=1e-1), name='weights')
            fc3b = tf.Variable(tf.constant(1.0, shape=[1000], dtype=tf.float32),
                                 trainable=True, name='biases')
            # 矩阵相乘self.fc2.shape=[-1,4096], fc3w.shape=[4096,1000]
            # tf.matmul(self.fc2, fc3w).shape = [-1,1000]
            # fc3l.shape = [-1,1000]
            self.fc3l = tf.nn.bias_add(tf.matmul(self.fc2, fc3w), fc3b)
            self.parameters += [fc3w, fc3b]

    # 加载模型
    def load_weights(self, weight_file, sess):
        weights = np.load(weight_file)
        keys = sorted(weights.keys())
        for i, k in enumerate(keys):
            print i, k, np.shape(weights[k])
            sess.run(self.parameters[i].assign(weights[k]))

if __name__ == '__main__':
    sess = tf.Session()
    # None代表传入未知数量的图像
    imgs = tf.placeholder(tf.float32, [None, 224, 224, 3])
    vgg = vgg16(imgs, 'vgg16_weights.npz', sess)

    img1 = imread('rabbit2.jpg')
    img1 = imresize(img1, (224, 224))[:,:,:3]

    prob = sess.run(vgg.probs, feed_dict={vgg.imgs: [img1]})[0]
    preds = (np.argsort(prob)[::-1])[0:5]
    for p in preds:
        print class_names[p], prob[p]

VGG实验结果

  运行的时候遇到这样的错误:
  24.png-4.6kB
  作者的源码是这样的:
  25.png-11.3kB
  修改成如下即可:
  26.png-10.5kB

  • 输入图像1
      laska.png-99.5kB
  • 输出结果1
      15.png-96.9kB

  • 输入图像2
      poodle.png-115.5kB

  • 输出结果2
      16.png-31kB

  • 输入图像3
      rabbit2.jpg-7.1kB

  • 输出结果3
      17.png-30.7kB

caffe模型转TensorFlow模型

作者已经提供了TensorFlow的模型,这部分可以了解下

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值