一、疑问
- 卷积层究竟学到了什么内容?
- 同一卷积层中不同通道学习到的内容有什么区别?
- 浅层的卷积和深层的卷积学习到的内容有什么区别?
二、Deep Dream技术原理
1. 利用CNN进行图像分类:
2. Deep Dream
使用梯度上升的方法可视化网络每一层的特征,即用一张噪声图像输入网络,反向更新的时候不更新网络权重,而是更新初始图像的像素值,(这里卷积神经网络是固定的,使用预训练好的ImageNet图像识别模型),以这种“训练图像”的方式可视化网络。
三、Inception模型文件导入与卷积层分析
1. 模型的加载
TensorFlow提供了以下两种方式来存储和加载模型:
- 生成检查点文件(checkpoint file),拓展名一般为.ckpt,通过在tf.train.Saver对象上调用Saver.save()生成,通过saver.restore()来加载。
- 生成图协议文件(graph proto file),这是一个二进制文件,拓展名一般为.pb,用tf.train.write_graph()保存,然后使用tf.import_graph_def()来加载图。
2. 图模型的加载
#图模型的加载
import tensorflow as tf
# 图的保存
v = tf.Variable(1.0, name='my_variable')
with tf.Session() as sess:
tf.train.write_graph(sess.graph_def,'./tfmodel','test_pb.pb',as_text=False)
# 图的加载
with tf.Session() as sess:
with tf.gfile.FastGFile('./tfmodel/test_pb.pb','rb')as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
sess.graph.as_default()
tf.import_graph_def(graph_def,name='tf.graph')
print(graph_def)
3. 导入Inception模型
# 导入库
from _future_ import print_function
import os
from io import BytestIO
import numpy as np
from functools import partial
import PIL.Image
import scipy.misc
import tensorflow as tf
# 创建图和会话
graph = tf.Graph()
sess = tf.InteractiveSession(graph=graph)
# 导入Inception网络
model_fn = 'tensorflow_inception_graph.pb'
# tensorflow_inception_graph.pb文件的下载:
# https://storage.gooleapis.com/download.tensorflow.org/models/inception5h.zip
with tf.gfile.FastGFile(model_fn,'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
# 定义输入图像的占位符
t_input = tf.placeholder(np.float32, name='input')
# 图像预处理——减均值
imagenet_mean = 117.0
# 在训练Inception模型时做了减均值预处理,此处也需减同样的均值以保持一致
# 图像预处理——增加维度
# 图像数据格式一般是(height, width, channels),为同时将多张图片输入网络而在前面增加一维
# tf.expand_dims(input,dim,name=None)
# 向tensor插入维度1,插入位置就是参数代表的位置(维度从0开始)
t_preprocessed = tf.expand_dims(t_input - imagenet_mean, 0)
# 导入模型并将经预处理的图像送入网络中
tf.import_graph_def(graph_def,{'input':t_preprocessed})
4. 图的基本操作
- 创建、重置和获得默认图
import numpy as np
import tensorflow as tf
g = tf.Graph() # 创建新的图
with g.as_default():
c1 = tf.constant(0,0) # 在新图中添加变量
print(c1) #Tensor("Const:0", shape=(), dtype = float32)
# 可通过变量的'.graph'可获得其所在的图
print("c1.graph:", c1.graph)
#c1.graph:
tf.reset_default_graph() # 重置默认图
g2 = tf.get_default_graph() # 获得默认图
print("g2:", g2)
#g2:
- 获取张量:get_tensor_by_name
# 先获取张量的名字
print(c1.name) #Const:0
# 然后将张量名字放到tf.Graph().get_tensor_by_name(name="")中
t = g.get_tensor_by_name(name = "Const:0")
# 通过打印 t 验证get_tensor_by_name所获取的张量就是前面定义的张量c1
print(t) #Tensor("Const:0",shape=(),dtype=float32)
- 获取节点操作:get_operation_by_name
a = tf.constant([[1.0,2.0]])
b = tf.constant([[1.0],[2.0]])
tensor1 = tf.matmul(a,b,name='example_op')
print(tensor1) #Tensor("example_op:0",shape=(1,1),dtype=float32)
print(tensor1.name) #example_op:0
# 先把op的名字打印出来
print(tensor1.op.name) #example_op
# 然后get_operation_by_name函数
test_op = g2.get_operation_by_name("example_op")
print(test_op)
5. 模型中各卷积层分析
# 找出卷积层
layers = [op.name for op in graph.get_operations() if op.type == 'Conv2D']
# 输出卷积层层数
print('Number of layers',len(layers))
#Number of layers 59
# 输出所有卷积层名称
print(layers)
# 还可输出指定卷积层的参数
name1 = 'mixed4d_3x3_bottleneck_pre_relu'
print('shape of %s:%s' % (name1,str(graph.get_tensor_by_name('import/'+name1+':0').get_shape())))