1. 程式人生 > >TensorFlow——卷積神經網路的相關函式

TensorFlow——卷積神經網路的相關函式

在TensorFlow中,使用tr.nn.conv2d來實現卷積操作,使用tf.nn.max_pool進行最大池化操作。通過闖傳入不同的引數,來實現各種不同型別的卷積與池化操作。

卷積函式tf.nn.conv2d

TensorFlow裡使用tf.nn.conv2d函式來實現卷積,其格式如下:

tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None),引數的含義如下:

input:需要進行卷積操作的影象,它要求是一個Tensor,具有[ batch, in_height, in_width, in_channels ]的形狀,這是一個四維的資料,其中各個位置引數的具體含義是:訓練時一個batch的圖片數量,圖片高度,圖片寬度,圖片通道數,資料的型別是float。

filter:相當於CNN中的卷積核,它要求是一個Tensor,具有[ filter_height,filter_width,in_channels,out_channels ]這樣的shape,其中具體的含義是“卷積核的高度,卷積核寬度,圖片的通道數,濾波器的個數”,要求型別與引數input相同。有一個地方需要關注意,第三維in_channels就是引數input的第四維。

strides:卷積是在影象每一位的步長,這是一個一維的向量,長度為4。

padding:定義元素邊框與元素內容之間的空間。string型別的量,只能是SAME和VALID其中之一,這個值決定不同的卷積方式,padding的值VALID時,表示邊緣不填充,當其為SAME時,表示填充

到濾波器可以到達影象邊緣。

use_cudnn_on_gpu:bool型別,是否使用cudnn加速,預設為true。

返回值:函式的返回值仍然是一個Tensor,就是feature map。

import tensorflow as tf
import numpy as np

# [batch, im_height, im_weight, in_channels]

input = tf.Variable(tf.constant(1.0, shape=[1, 5, 5, 1]))
input2 = tf.Variable(tf.constant(1.0, shape=[1, 5, 5, 2]))
input3 = tf.Variable(tf.constant(1.0, shape=[1, 4, 4, 1]))

# [filter_height, filter_weight, in_channels, in_channels]
filter1 = tf.Variable(tf.constant([-1.0, 0, 0, -1], shape=[2, 2, 1, 1]))
filter2 = tf.Variable(tf.constant([-1.0, 0, 0, -1, -1, 0, 0, 1], shape=[2, 2, 1, 2]))
filter3 = tf.Variable(tf.constant([-1.0, 0, 0, -1,
                                   -1.0, 0, 0, -1,
                                   -1.0, 0, 0, -1], shape=[2, 2, 1, 3]))

filter4 = tf.Variable(tf.constant([-1.0, 0, 0, -1,
                                   -1.0, 0, 0, -1,
                                   -1.0, 0, 0, -1,
                                   -1.0, 0, 0, -1], shape=[2, 2, 2, 2]))

filter5 = tf.Variable(tf.constant([-1.0, 0, 0, -1, -1.0, 0, 0, -1], shape=[2, 2, 2, 1]))

op1 = tf.nn.conv2d(input, filter1, strides=[1, 2, 2, 1], padding='SAME')

op2 = tf.nn.conv2d(input, filter2, strides=[1, 2, 2, 1], padding='SAME')

op3 = tf.nn.conv2d(input, filter3, strides=[1, 2, 2, 1], padding='SAME')

op4 = tf.nn.conv2d(input2, filter4, strides=[1, 2, 2, 1], padding='SAME')

op5 = tf.nn.conv2d(input2, filter5, strides=[1, 2, 2, 1], padding='SAME')

vop1 = tf.nn.conv2d(input, filter1, strides=[1, 2, 2, 1], padding='VALID')

op6 = tf.nn.conv2d(input3, filter1, strides=[1, 2, 2, 1], padding='SAME')

vop6 = tf.nn.conv2d(input3, filter1, strides=[1, 2, 2, 1], padding='VALID')

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)

    print('-op1:\n', sess.run([op1, filter1]))
    print('-------------------------------')

    print('-op2:\n', sess.run([op2, filter2]))
    print('-op3:\n', sess.run([op3, filter3]))
    print('-------------------------------')

    print('-op4:\n', sess.run([op4, filter4]))
    print('-op5:\n', sess.run([op5, filter5]))
    print('-------------------------------')

    print('-op1:\n', sess.run([op1, filter1]))
    print('-vop1:\n', sess.run([vop1, filter1]))
    print('-op6:\n', sess.run([op6, filter1]))
    print('-vop6:\n', sess.run([vop6, filter1]))
    print('-------------------------------')

根據上述程式的執行結果,仔細的分析就能理解卷積是如何的工作的,需要注意的是SAME padding補0的情況,

由於可知,op1的卷積操作的結果是3*3的feature map,其他的結果也是類似的情況。當影象是多通道的情況時,卷積操作的結果是將各個通道的feature map的結果相加,作為輸出的一張feature map。

影象卷積示例

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mping

path = 'image/1.jpg'

img = mping.imread(path)

plt.imshow(img)
plt.axis('off')
plt.show()
print(img.shape)

full = np.reshape(img, [1, 374, 560, 3])
inputfull = tf.Variable(tf.constant(1.0, shape=[1, 374, 560, 3]))

filter = tf.Variable(tf.constant([[-1.0, -1.0, -1.0], [0, 0, 0], [1.0, 1.0, 1.0],
                                  [-2.0, -2.0, -2.0], [0, 0, 0], [2.0, 2.0, 2.0],
                                  [-1.0, -1.0, -1.0], [0, 0, 0], [1.0, 1.0, 1.0]], shape=[3, 3, 3, 1]))


op = tf.nn.conv2d(inputfull, filter, strides=[1, 1, 1, 1], padding='SAME')

o = tf.cast(((op - tf.reduce_min(op))/(tf.reduce_max(op)-tf.reduce_min(op)))*255, tf.uint8)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    t, f = sess.run([o, filter], feed_dict={inputfull: full})

    t = np.reshape(t, [374, 560])

    plt.imshow(t, cmap='Greys_r')
    plt.axis('off')
    plt.show()

池化函式tf.nn.max_pool(avg_pool)

TensorFlow裡的池化函式如下:

tf.nn.max_pool(input, ksize, strides, padding, name)

tf.nn.avg_pool(input, ksize, strides, padding, name)

上述的兩個池化函式中,4個引數的意義如下:

input:進行池化操作的資料,一般的池化層是在卷積層之後,所以通常的輸入是feature map,依然是[ batch, height, width, channels ]的形狀。

ksize:池化視窗的大小,4維的向量,一般是[1, height, width, 1],在batch和channles通常是不做池化的。

strides:和卷積引數含義類似,視窗在每一個維度上面滑動,一般也是[1, strides,strides,1]

padding:和卷積引數含義一樣,也是取VALID或者SAME。

返回的Tensor:型別不變,shape仍然是[ batch, height, width, channels ]的形狀。

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mping

path = 'image/1.jpg'

img = mping.imread(path)

plt.imshow(img)
plt.axis('off')
plt.show()
print(img.shape)

full = np.reshape(img, [1, 374, 560, 3])
inputfull = tf.Variable(tf.constant(1.0, shape=[1, 374, 560, 3]))

pooling = tf.nn.max_pool(inputfull, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
pooling1 = tf.nn.max_pool(inputfull, [1, 2, 2, 1], [1, 1, 1, 1], padding='SAME')
pooling2 = tf.nn.max_pool(inputfull, [1, 4, 4, 1], [1, 1, 1, 1], padding='SAME')
pooling3 = tf.nn.max_pool(inputfull, [1, 4, 4, 1], [1, 4, 4, 1], padding='SAME')
pooling4 = tf.nn.max_pool(inputfull, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

o = tf.cast(((pooling - tf.reduce_min(pooling))/(tf.reduce_max(pooling)-tf.reduce_min(pooling)))*255, tf.uint8)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    t = sess.run(o, feed_dict={inputfull: full})

    print(t.shape)

    t = np.reshape(t, [187, 280, 3])

    plt.imshow(t)
    plt.axis('off')
    plt.show()

池化操作的作用是將特徵圖中的資訊進行放大,使得特性資訊更加的明顯。

&n