目录
1.1、tensorflow定义计算图和用会话执行计算... 3
第三章、tensorflow实现卷积神经网络(CNN)... 11
第一章Tensorflow的张量简单学习
1.1、tensorflow定义计算图和用会话执行计算
Tensor为张量,表明其数据结构;Flow就是“流”,体现其计算模型
tensorflow程序一般分为两个阶段:
1、定义计算图所有的计算
2、在session中执行计算
a、默认计算图以及如何查看一个运算所属的计算图(详情看computegraph.py):
importtensorflow as tf
a=tf.constant([1.0,2.0],name='a') # 定义一个常量使用tf.constant方法
b=tf.constant([1.0,2.0],name='b')
result =a+b
# 通过a.graph可以查看张量所属的计算图,如果没有特别指定,则属于当前默认的计算图
print(a.graphis tf.get_default_graph()) # 输出为True
b、tensorflow可以通过tf.Graph函数生成新的计算图。不同计算图上的张量和运算都不会共享(详情看different compute graph.py)。
importtensorflow as tf
g1=tf.Graph()
withg1.as_default():
# 在计算图g1中定义变量'v',并设置初始值为0。
v=tf.get_variable('v',initializer=tf.zeros_initializer()(shape= [1]))
g2=tf.Graph()
withg2.as_default():
# 在计算图g2中定义变量'v',并设置初始值微1。
v=tf.get_variable('v',initializer=tf.ones_initializer()(shape = [1]))
# 在计算图g1中读取变量'v'的取值
withtf.Session(graph=g1) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope('',reuse=True):
# 在计算图g1中,变量'v'的取值应该为0,下一行代码会输出[0.]。
print(sess.run(tf.get_variable('v')))
# 在计算图g2中读取变量'v'的取值
withtf.Session(graph=g2) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope('',reuse=True):
# 在计算图g2中,变量'v'的取值应该为1,下一行代码会输出[1.]。
print(sess.run(tf.get_variable('v')))
c、计算图可以通过tf.Graph.device函数来指定运行计算的设备,下面代码指定在GPU上运行加法计算(详情看graph device.py)。
import tensorflow astf
a=tf.constant([1.0,2.0],name='a') # 定义一个常量使用tf.constant方法
b=tf.constant([1.0,2.0],name='b')
result = a+b
g=tf.Graph()
# 指定计算运行的设备。
withg.device('/gpu:0'):
result=a+b
print(result)
d、在一个计算图中,可以通过集合(collection)来管理不同类别的资源
通过tf.add_to_collection函数可以将资源加入到一个或多个集合中。
通过tf.get_collection获取集合里的资源。
Tensorflow也自动管理了一些常用的集合:如表所示
集合名称
集合内容
使用场景
tf.GraphKeys.VARIABLES
所有变量
持久化tensorflow模型
tf.GraphKeys.TRAINABLE_VARIABLES
可学习的变量(一般指神经网络中的参数)
模型训练、生成模型可视化内容
tf.GraphKeys.SUMMARIES
日志生成相关的张量
tensorflow计算可视化
tf.GraphKeys.QUEUE_RUNNERS
处理输入的QueueRunner
输入处理
tf.GraphKeys.MOVING_AVERAGE_VARIABLES
所有计算了滑动平均值的变量
计算变量的滑动平均值
1.2、tensor张量理解
张量可以简单理解为一个多维数组,其中0阶张量表示标量,即一个数,第一阶张量也就是一个一维数组,第n阶张量可以理解为一个n维数组。(详情看tensor.py)
import tensorflow astf
# tf.constant是一个计算,这个计算的结果为一个张量,保存在变量a中。
a=tf.constant([1.0,2.0],name='a')#给a赋值一个张量
b=tf.constant([1.0,2.0],name='b')#给b赋值一个张量
result =tf.add(a,b,name='add')
print(result)
打印结果:
Tensor("add_18:0",shape=(2,), dtype=float32)
其中张量主要保存了三个属性:名字(name)、维度(shape)和类型(type)。
1.3、session(会话)的理解
Session用来执行定义好的运算。tensorFlow使用session的方式有三种:
明确调用会话生成函数和关闭会话函数
sess=tf.Session()
# 下面两个命令等价
print(sess.run(result))
print(result.eval(session=sess))
用with生成一个默认会话
sess=tf.Session()
with sess.as_default():
print(result.eval())
1.4、用张量、会话、计算图的简单示例
下面分别从定义二维张量、对数组求和、两个数组相乘、打印图片、生成裁剪图片
使用Tensorflow改变图像六个小程序来巩固上面对张量、计算图以及会话功能的掌握。
代码实现如下:
#定义二维张量
importnumpy as np
importtensorflow as tf
arr=np.array([(1,5.5,3,15,20),(10,20,30,40,50),(60,70,80,90,100)])#定义三维数组
tensor= tf.convert_to_tensor(arr)#将数组转换成张量
sess=tf.Session()#以第一种方式定义会话
print(sess.run(tensor))#打印
打印结果:
[[ 1. 5.5 3. 15. 20. ]
[ 10. 20. 30. 40. 50. ]
[ 60. 70. 80. 90. 100. ]]
#对数组求和
importnumpy as np
importtensorflow as tf
#定义两个数组
arr1=np.array([(1,2,3),(4,5,6)])
arr2=np.array([(7,8,9),(10,11,12)])
#两个数组相加
arr3=tf.add(arr1,arr2)
sess=tf.Session()
tensor=sess.run(arr3)
print(tensor)
打印结果:
[[8 10 12]
[14 16 18]]
#两个数组相乘
importnumpy as np
importtensorflow as tf
arr1=np.array([(1,2,3),(4,5,6)])
arr2=np.array([(7,8,9),(10,11,12)])
arr3=tf.multiply(arr1,arr2)
sess=tf.Session()
tensor=sess.run(arr3)
print(tensor)
打印结果:
[[7 16 27]
[40 55 72]]
#打印图片
importmatplotlib.image as img
importmatplotlib.pyplot as plot
myfile= "sheep.jpg"
myimage=img.imread(myfile)
print(myimage.ndim)
print(myimage.shape)#宽度为150,高度为150,颜色深度为3
plot.imshow(myimage)
plot.show()
打印结果:
3
(194,259, 3)
#使用tensorflows生成裁剪图片
importtensorflow as tf
importmatplotlib.image as img
importmatplotlib.pyplot as plot
myfile="sheep.jpg"
myimage=img.imread(myfile)#读取图爿
slice= tf.placeholder("int32",[None,None,3])#生成图片
cropped=tf.slice(myimage,[100,0,0],[20,-1,-1])#裁剪图片
sess=tf.Session()
result=sess.run(cropped,feed_dict={slice:myimage})
plot.imshow(result)
plot.show()
打印结果:
第二章使用Tensorflow改变图像
2.1图像预处理
图像预处理也可以用tensorflow来解决一些简单的图像的裁剪,上下旋转,左右旋转,图形的色调,对比度,亮度,以及手机上拍照的标注框等。下面以刘亦菲的图片作为简单示例进行代码演示。
#图像编码处理
import tensorflow as tf
import matplotlib.image as img
import matplotlib.pyplot as plot
#读取刘亦菲的照片
myimage=img.imread("yifei.jpg")
image=tf.Variable(myimage,name='image')
vars=tf.global_variables_initializer()
#创建会话
sess=tf.Session()
flipped=tf.transpose(image,perm=[1,0,2])
sess.run(vars)
#图像翻转
result=sess.run(flipped)
#打印矩阵
print(result)
plot.imshow(result)
plot.show()
#图像上下翻转
flipped1=tf.image.flip_up_down(myimage)
result1=sess.run(flipped1)
plot.imshow(result1)
plot.show()
#图像左右翻转
flipped2=tf.image.flip_left_right(myimage)
result2=sess.run(flipped2)
plot.imshow(result2)
plot.show()
#图像沿着对角线翻转
transposed=tf.image.transpose_image(myimage)
result3=sess.run(transposed)
plot.imshow(result3)
plot.show()
#图像调整亮度为-0.5(变暗)
adjusted=tf.image.adjust_brightness(myimage,-0.5)
result4=sess.run(adjusted)
plot.imshow(result4)
plot.show()
#图像调整亮度为+0.5(变亮)
adjusted1=tf.image.adjust_brightness(myimage,0.5)
result5=sess.run(adjusted1)
plot.imshow(result5)
plot.show()
#调整对比度
adjusted2=tf.image.adjust_contrast(myimage,-5)
result6=sess.run(adjusted2)
plot.imshow(result6)
plot.show()
#调整色相
adjusted3=tf.image.adjust_hue(myimage,0.3)
result7=sess.run(adjusted3)
plot.imshow(result7)
plot.show()
#调整饱和度
adjusted4=tf.image.adjust_saturation(myimage,3)
result8=sess.run(adjusted4)
plot.imshow(result8)
plot.show()
打印结果:
[[[214 213 229]
[215 214 230]
[216 215 231]
...
[ 86 71 50]
[ 88 73 52]
[ 89 74 53]]
[[214 213 229]
[215 214 230]
[216 215 231]
...
[ 88 73 52]
[ 88 76 54]
[ 88 76 54]]
[[215 214 230]
[215 214 230]
[216 215 231]
...
[ 88 76 54]
[ 89 77 55]
[ 89 77 55]]
...
[[206 205 223]
[206 205 223]
[206 205 223]
...
[132 102 52]
[131 101 51]
[131 101 51]]
[[206 205 223]
[206 205 223]
[206 205 223]
...
[134 102 53]
[134 102 53]
[133 101 52]]
[[206 205 223]
[206 205 223]
[206 205 223]
...
[136 104 55]
[135 103 54]
[135 103 54]]]
第三章、tensorflow实现卷积神经网络(CNN)
CNN是一个非常常用的神经网络模型,在图像识别领域、以及风格迁移有许多应用。
3.1CNN简介
卷积神经网络的基本结构图如下:
和全连接神经网络类似,CNN的每一个节点都是一个神经元;对于CNN,相邻两层之间的节点只有部分节点相连,为展示一层神经元的维度,每一层的卷积层的节点组织成一个三维矩阵。CNN的输入层为图像的原始像素,而输出层的每一个节点代表不同类别的可信度。
如上图所示,CNN主要由5种结构组成:
输入层:输入层为整个神经网络的输入,在处理CNN时,一般代表一张图片的像素矩阵
其中,三维矩阵的长与宽表示了图像的大小,深度则表示了图像的色彩通道,比如黑白图片的深度为1,RGB色彩模式下,图像的深度为3(由红、绿、蓝)组成。
该层对原始图像做预处理:
去均值:把输入数据各个维度都中心化为0。
归一化:幅度归一化到同样的范围,都变为相同的范围。白化:白化是对数据各个特征轴上的幅度归一化。
卷积层:此为CNN最重要部分。卷积层的每一个输入为上一层神经网络的亦小块,大小常用3*3或者5*5。可以改变深度。这个部分常被称作fitler和kernel。卷积层有几个神经元,depth深度就是多少;步长stride为窗口一次滑动的长度;
池化层:不会改变矩阵的深度,但是可压缩矩阵的大小,即可以将dpi高的转化为dpi低的。
全连接层:可以将卷积层和池化层看成特征提取的过程,之后依旧需要全连接层完成分类任务。
Softmax层:主要用于分类,可以得到当前属于不同种类的概率分布情况。
3.2风格迁移
风格迁移值的是将图像A的风格转换到图像B中去,得到新的图像,取个名字为new B,其中new B中既包含图像B的内容,也包含图像A的风格。
如输入原图片为:左边为背景图片,右边为内容图片(像素为水平800×高600)由于vgg-19层的模型文件较大,不作为上传。
输出图片
风格迁移示例代码(vgg-19自己去网上下载)
importtensorflow as tf#导入tensorflow库
importnumpy as np#导入数值计算库
importscipy.io#导入scipy库
importscipy.misc#导入数值计算库的misc
importos#导入操作系统的接口库
IMAGE_W= 800 #水平像素为800
IMAGE_H= 600 #锤子像素为600
CONTENT_IMG= './images/yifei.jpg'#路径下的内容图片
STYLE_IMG= './images/fengjing.jpg'#路径下的背景图片
OUTOUT_DIR= './results'#输出路径下的结果图片
OUTPUT_IMG= 'results.png'#输出图片
VGG_MODEL= 'imagenet-vgg-verydeep-19.mat'#VGG_MODEL模型
INI_NOISE_RATIO= 0.7#噪声比率
STYLE_STRENGTH= 500#风格强度
ITERATION= 5000#迭代次数
CONTENT_LAYERS=[('conv4_2',1.)]#内容图片的卷积
STYLE_LAYERS=[('conv1_1',1.),('conv2_1',1.),('conv3_1',1.),('conv4_1',1.),('conv5_1',1.)]#背景图片的卷积
MEAN_VALUES= np.array([123, 117, 104]).reshape((1,1,1,3))#将三维矩阵转变为四维矩阵
#建立神经网络的卷积池和池化池选择
defbuild_net(ntype, nin, nwb=None):
if ntype == 'conv':
return tf.nn.relu(tf.nn.conv2d(nin, nwb[0],strides=[1, 1, 1, 1], padding='SAME')+ nwb[1])
elif ntype == 'pool':
return tf.nn.avg_pool(nin, ksize=[1, 2, 2,1],
strides=[1, 2, 2, 1],padding='SAME')
#vgg的权重误差对比,返回权重和误差
defget_weight_bias(vgg_layers, i,):
weights = vgg_layers[i][0][0][0][0][0]
weights = tf.constant(weights)
bias = vgg_layers[i][0][0][0][0][1]
bias = tf.constant(np.reshape(bias,(bias.size)))
return weights, bias
#对19层vgg模型进行定义
defbuild_vgg19(path):
net = {}
vgg_rawnet = scipy.io.loadmat(path)
vgg_layers = vgg_rawnet['layers'][0]
#输入层
net['input'] = tf.Variable(np.zeros((1,IMAGE_H, IMAGE_W, 3)).astype('float32'))
#第一层卷积层×2
net['conv1_1'] =build_net('conv',net['input'],get_weight_bias(vgg_layers,0))
net['conv1_2'] =build_net('conv',net['conv1_1'],get_weight_bias(vgg_layers,2))
#第1层池化层×1
net['pool1'] = build_net('pool',net['conv1_2'])
#第2层卷积层×2
net['conv2_1'] =build_net('conv',net['pool1'],get_weight_bias(vgg_layers,5))
net['conv2_2'] = build_net('conv',net['conv2_1'],get_weight_bias(vgg_layers,7))
#第2层池化层×1
net['pool2'] = build_net('pool',net['conv2_2'])
#第3层卷积层×4
net['conv3_1'] =build_net('conv',net['pool2'],get_weight_bias(vgg_layers,10))
net['conv3_2'] =build_net('conv',net['conv3_1'],get_weight_bias(vgg_layers,12))
net['conv3_3'] =build_net('conv',net['conv3_2'],get_weight_bias(vgg_layers,14))
net['conv3_4'] =build_net('conv',net['conv3_3'],get_weight_bias(vgg_layers,16))
#第3层池化层×1
net['pool3'] = build_net('pool',net['conv3_4'])
#第4层卷积层×4
net['conv4_1'] =build_net('conv',net['pool3'],get_weight_bias(vgg_layers,19))
net['conv4_2'] =build_net('conv',net['conv4_1'],get_weight_bias(vgg_layers,21))
net['conv4_3'] =build_net('conv',net['conv4_2'],get_weight_bias(vgg_layers,23))
net['conv4_4'] =build_net('conv',net['conv4_3'],get_weight_bias(vgg_layers,25))
#第4层池化层×1
net['pool4'] = build_net('pool',net['conv4_4'])
#第5层卷积层×4
net['conv5_1'] =build_net('conv',net['pool4'],get_weight_bias(vgg_layers,28))
net['conv5_2'] =build_net('conv',net['conv5_1'],get_weight_bias(vgg_layers,30))
net['conv5_3'] =build_net('conv',net['conv5_2'],get_weight_bias(vgg_layers,32))
net['conv5_4'] =build_net('conv',net['conv5_3'],get_weight_bias(vgg_layers,34))
#第五层池化层
net['pool5'] = build_net('pool',net['conv5_4'])
return net
#建立内容损失值
defbuild_content_loss(p, x):
M = p.shape[1]*p.shape[2]
N = p.shape[3]
loss = (1./(2* N**0.5 * M**0.5 )) *tf.reduce_sum(tf.pow((x - p),2))
return loss
#得到最大矩阵
defgram_matrix(x, area, depth):
x1 = tf.reshape(x,(area,depth))
g = tf.matmul(tf.transpose(x1), x1)
return g
#得到转置后的最大矩阵
defgram_matrix_val(x, area, depth):
x1 = x.reshape(area,depth)
g = np.dot(x1.T, x1)
return g
#背景图片的损失
defbuild_style_loss(a, x):
M = a.shape[1]*a.shape[2]
N = a.shape[3]
A = gram_matrix_val(a, M, N )
G = gram_matrix(x, M, N )
loss = (1./(4 * N**2 * M**2)) *tf.reduce_sum(tf.pow((G - A),2))
return loss
#读取图片
defread_image(path):
image = scipy.misc.imread(path)
image = scipy.misc.imresize(image,(IMAGE_H,IMAGE_W))
image = image[np.newaxis,:,:,:]
image = image - MEAN_VALUES
return image
#写入图片
defwrite_image(path, image):
image = image + MEAN_VALUES
image = image[0]
image = np.clip(image, 0, 255).astype('uint8')
scipy.misc.imsave(path, image)
#主函数定义
defmain():
net = build_vgg19(VGG_MODEL)
sess = tf.Session()
sess.run(tf.initialize_all_variables())
noise_img = np.random.uniform(-20, 20, (1,IMAGE_H, IMAGE_W, 3)).astype('float32')
content_img = read_image(CONTENT_IMG)
style_img = read_image(STYLE_IMG)
sess.run([net['input'].assign(content_img)])
cost_content = sum(map(lambda l,:l[1]*build_content_loss(sess.run(net[l[0]]) , net[l[0]])
, CONTENT_LAYERS))
sess.run([net['input'].assign(style_img)])
cost_style = sum(map(lambda l:l[1]*build_style_loss(sess.run(net[l[0]]) , net[l[0]])
, STYLE_LAYERS))
cost_total = cost_content + STYLE_STRENGTH *cost_style
optimizer = tf.train.AdamOptimizer(2.0)
train = optimizer.minimize(cost_total)
sess.run(tf.initialize_all_variables())
sess.run(net['input'].assign(INI_NOISE_RATIO* noise_img + (1.-INI_NOISE_RATIO) * content_img))
if not os.path.exists(OUTOUT_DIR):
os.mkdir(OUTOUT_DIR)
for i in range(ITERATION):
sess.run(train)
if i%100 ==0:
result_img = sess.run(net['input'])
print( sess.run(cost_total))
write_image(os.path.join(OUTOUT_DIR,'%s.png'%(str(i).zfill(4))),result_img)
write_image(os.path.join(OUTOUT_DIR,OUTPUT_IMG),result_img)
if__name__ == '__main__':
main()