10.1_.jpg

 穿插整理一系列以前的笔记,将围绕TensorFlow来讲解深度学习的知识,形式以原理解说+代码演示为主,首先来讲讲TensorFlow的基础知识。



TensorFlow是基于计算图模型的深度学习框架,每个TensorFlow程序都有一个默认图,一般情况下我们在程序中所添加的操作(operation,简称op)都是添加到这个默认图上面的,并且,每一个操作op的执行结果都会得到一个Tensor变量,这个变量里面储存着数值。



通常,在写TensorFlow程序之前,需要在python文件的开头导入TensorFlow库,我们把这个库简记为tf,如下所示:

import tensorflow as tf



首先,我们来看一下Tensor变量的例子。例如我们首先定义一个长度为32的线性向量:

num = 32

x = tf.linspace(-3.0,3.0,num)




那么,定义好了x以后,此时x就是一个Tensor了,也就是说我们已经构造了一幅计算图了,这幅图的作用就是计算出向量x,因此,为了得到x的具体数值,我们需要启动这幅计算图并执行计算,这里启动图的操作就有tf.Session()会话来完成,注意启动了会话要记得关闭会话以释放资源,这里我们使用with句式来自动关闭会话:

with tf.Session() as sess:

    result = sess.run(x)




另外,如果我们不想用这种方式来启动计算图的话,还可以使用另外一种会话方式,那就是InteractiveSession(),然后直接对Tensor调用eval()方法即可得到Tensor的具体数值,使用方式如下:

sess = tf.InteractiveSession()

x.eval()




接下来,我们将借助上面得到的x来构建一个均值为0方差为1的高斯分布,根据高斯分布的公式,那么我们可以直接借助TensorFlow自带的exp函数、neg函数、pow函数、sqrt函数来完成这个操作:

sigma = 1.0

mean = 0.0

z = (1.0/(sigma*tf.sqrt(2.0*3.14))) * tf.exp(tf.neg(tf.pow(x - mean,2,0)/(2.0*tf.pow(sigma,2.0))))




我们可以使用matplotlib库,来画出上面的高斯分布曲线:

import matplotlib.pyplot as plt

plt.plot(z)

plt.show()


10.2_.JPG




我们可以使用assert验证一下z所属的图是不是默认的计算图:

assert z.graph is tf.get_default_graph()



另外,Tensor的形状我们也可以获取,例如可以使用z.get_shape()得到z的形状,也可以使用z.get_shape().as_list()来获取,这种形式更加友好。但是,有时候对于一个变量我们可能事先并不知道它的形状,只有在图中计算过后才能知道,这个时候我们应该使用tf.shape(z).eval()来得到。


Tensor之间也可以进行合并,这时候可以使用tf.pack函数进行合并,例如tf.pack([tf.shape(z),tf.shape(z),[3],[4]]).eval()就可以得到合并以后的矩阵。



矩阵之间可以进行矩阵相乘,例如由于z是一个向量,我们可以把它转换成两个维度不同的矩阵,使用reshape进行维度变换,然后使用matmul进行矩阵相乘:

z_2d = tf.matmul(tf.reshape(z,[num,1]),tf.reshape(z,[1,num]))



接下来,我们可以创建一个gabor滤波器,根据定义,我们对之前那个向量计算正弦值,然后变形为矩阵形式,再创建一个全1矩阵与它相乘得到正弦矩阵,然后将这个正弦矩阵与上面得到的z_2d进行相乘即可:

x = tf.reshape(tf.sin(tf.linspace(-3.0,3.0,num)),[num,1])

y = tf.reshape(tf.ones_like(x),[1,num])

z = tf.mul(tf.matmul(x,y),z_2d)


plt.imshow(z.eval())

plt.show()


10.3_.jpg



我们也可以了列出到目前为止默认图中所有的操作op:

ops = tf.get_default_graph().get_operations()

print ([op.name for op in ops])




接下来,我们把以上创建gabor滤波器的过程放到一个函数里面:

def gabor(num=32, sigma=1.0, mean=0.0):

    x = tf.linspace(-3.0, 3.0, num)

    z = (tf.exp(tf.neg(tf.pow(x - mean, 2.0) /

                       (2.0 * tf.pow(sigma, 2.0)))) *

         (1.0 / (sigma * tf.sqrt(2.0 * 3.1415))))

    gauss_kernel = tf.matmul(

        tf.reshape(z, [num, 1]), tf.reshape(z, [1, num]))

    x = tf.reshape(tf.sin(tf.linspace(-3.0, 3.0, num)), [num, 1])

    y = tf.reshape(tf.ones_like(x), [1, num])

    gabor_kernel = tf.mul(tf.matmul(x, y), gauss_kernel)

    return gabor_kernel




直接调用plt.imshow(gabor().eval())与上面结果一样。

接下来我们再使用TensorFlow写一个简单的卷积函数,卷积函数的输入是一张图片,输出的是图片与权重之间的卷积的结果。由于我们的权重W是二维的,而tf.nn.conv2d函数要求的输入值必须为四维的,因此,如果输入图片是二维的,即w*h格式,那么我们需要将输入矩阵变换成(num,width,height,channel)形式,即由原来的(w,h)变换成(1,w,h,1)的维度,同样W也要做相同的变换成四维;而如果输入图片是三维格式,即(w,h,c),那么我们只用将其变换成(1,w,h,c)即可,而此时W的channel维度也要转换成c,所以对W做的变换就是(1,w,h,1)到(1,w,h,c),即复制c个w。最后,卷积的滑动步长stride设置为1,用0铺平的方式是与输入维度相同。



def convolve(img, W):

    if len(W.get_shape()) == 2:


        dims = W.get_shape().as_list() + [1, 1]

        W = tf.reshape(W, dims)




    if len(img.get_shape()) == 2:

        dims = [1] + img.get_shape().as_list() + [1]


        img = tf.reshape(img, dims)

    elif len(img.get_shape()) == 3:

        dims = [1] + img.get_shape().as_list()

        img = tf.reshape(img, dims)

        W = tf.concat(2, [W, W, W])




    convolved = tf.nn.conv2d(img, W,


                             strides=[1, 1, 1, 1], padding='SAME')

    return convolved





接下来我们将本期的题图与前面得到的gabor滤波器进行卷积,看看会发生什么。 再欣赏一次题图:

10.4_.jpg


这里,我们借助了python的Image模块来导入图片,题图的大小是899*682*3,卷积代码如下:

import Image

img = Image.open('title_pic.jpg')

img = np.array(img)

plt.imshow(img)

print(np.array(img).shape)

x = tf.placeholder(tf.float32, shape=img.shape)

out = convolve(x, gabor())


result = tf.squeeze(out).eval(feed_dict={x: img})


plt.imshow(result)

plt.show()


题图与gabor滤波器卷积过后如下图所示:

10.5_.jpg

 
 
 
 
来源:张泽旺 深度学习每日摘要
智造家