几个概念
1、多通道的卷积
通道(Channel),是指图片中每个像素由几个数来表示,这几个数一般指的就是色彩。比如一个灰度图的通道就是1,一个彩色图的通道就是3(红、黄、蓝)。在卷积神经网络里,通道又分输入通道和输出通道。
- 输入通道:就是前面刚介绍的图片的通道。如是彩色图片,起始的输入通道就是3.如是中间层的卷积,输入通道就是上一层的输出通道个数,计算方法是,每个输入通道的图片都使用同一个卷积核进行卷积操作,生成与输入通道匹配的feature map(比如彩色图片就是3个),然后再把这几张feature map相同位置上的值加起来,生成一张feature map。
- 输出通道:很好理解了,想要输出几个feature map,就放几个卷积核,就是几个输出通道。
卷积函数tf.nn.conv2d
tf.nn.conv2d(input, filter, strides, padding, user_cudnn_on_gpu)
- input:指需要做卷积的输入图像,它要求是一个Tensor,具有[batch, in_height, in_width, in_channels]这样的形状(shape),具体含义是“训练时一个batch的图片数量,图片高度,图片宽度,图像通道数”,注意这是一个思维的Tensor,要求类型为float32和float64其中之一。
- filter:相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height, fitler_width, in_channels, out_channels]这样的shape,具体含义是”卷积核的高度,滤波器的宽度,图像通道数,滤波器个数“,要求类型与参数input相同。有一个地方需要注意,第三维in_channels,就是参数input的第四维。
- strides:卷积时在图像每一维的步长,这是一个一维的向量,长度为4。
- padding:定义元素边框与元素内容之间的空间。string类型的量,只能是SAME和VALID其中之一,这个值决定了不同的卷积方式,padding的值为”VALID“时,表示边缘不填充,当其为”SAME“时,表示填充到滤波器可以到达图像边缘。只有在步长为1时生成的feature map才会与输入值相等。
- use_cudnn_on_gpu:bool类型,是否使用cudnn加速,默认为true。
- 返回值:一个Tensor,就是常说的feature map。
实例:卷积计算
# 卷积核的使用
import tensorflow as tf
# [batch, in_height, in_width, in_channels]
# [训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数]
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_width, in_channels, out_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, 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]))
# padding的值为‘VALID’,表示边缘不填充,
# 当其为‘SAME’时,表示填充到卷积核可以到达图像边缘
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")
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print("op1:\n",sess.run([op1,filter1]))#1-1 后面补0
print("------------------")
print("op2:\n",sess.run([op2,filter2])) #1-2多卷积核 按列取
print("op3:\n",sess.run([op3,filter3])) #1-3
print("------------------")
实例:使用卷积提取图片的轮廓
# sobe算子提取轮廓
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import tensorflow as tf
myimg = mpimg.imread("img.png")
plt.imshow(myimg)
plt.axis('off')
plt.show()
print(myimg.shape) # (214, 282, 4)
full = np.reshape(myimg, [1, 214, 282, 4])
inputfull = tf.Variable(tf.constant(1.0, shape=[1,214,282,4]))
filter = tf.Variable(tf.constant([[-1.0,-1.0,-1.0], [0,0,0], [1.0,1.0,1.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],
[-1.0,-1.0,-1.0], [0,0,0], [1.0,1.0,1.0], [1.0,1.0,1.0]],shape = [3, 3, 4, 1]))
op = tf.nn.conv2d(inputfull, filter, strides=[1, 1, 1, 1], padding='SAME') #3个通道输入,生成1个feature ma
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})
#print(f)
t=np.reshape(t,[214,282])
plt.imshow(t,cmap='Greys_r') # 显示图片
plt.axis('off') # 不显示坐标轴
plt.show()

实例:使用卷积神经网络对图片分类
在CIFAR数据集上做图像识别的练习
与MNIST类似,TensorFlow中同样有一个下载和导入CIFAR数据集的代码文件,不同的是,Models模块分离了出来。
$ git clone https://github.com/tensorflow/models.git
将models/tutorials/image/路径下的cifar10目录中所有内容复制到本地的Python工作区即可。
![]()
数据集下载http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
目前tensorflow将cifar10数据集集成到 tensorflow_datasets中,所以需要安装tensorflow_datasets
pip install tensorflow_datasets
包含10个类别的50000条训练数据和10000条测试数据
导入并显示CIFAR数据集
import cifar10_input
import tensorflow as tf
import pylab
batch_size = 128
# inputs函数会将图片裁剪好,由原来的32x32x3,变成24x24x3。eval_data=True为测试集,False为训练集
images_test, labels_test = cifar10_input.inputs(eval_data = True, batch_size = batch_size)
sess = tf.Session()
tf.global_variables_initializer().run(session=sess)
tf.train.start_queue_runners(sess=sess) # 使用队列
image_batch, label_batch = sess.run([images_test, labels_test])
print("__\n",image_batch[0])
print("__\n",label_batch[0])
pylab.imshow(image_batch[0])
pylab.show()

提示:TensorFlow提供了一个队列机制,通过多线程将读取数据与计算数据分开。因为在处理海量数据集的训练时,无法把数据集一次全部载入到内存中,需要一边从硬盘中读取,一边进行训练计算。
网络结构:使用全局平均池化层来代替传统的全连接层,使用了3个卷积层的同卷积操作,滤波器为5x5,每个卷积层后面都会跟个步长为2x2的池化层,滤波器为2x2。2层的卷积池化后是输出为10个通道的卷积层,然后对这10个feature map进行全局平均池化,得到10个特征,再对这10个特征进行softmax计算,其结果来代表最终分类。
import cifar10_input
import tensorflow as tf
import numpy as np
batch_size = 128
print("begin")
images_train, labels_train = cifar10_input.inputs(eval_data = False, batch_size = batch_size)
images_test, labels_test = cifar10_input.inputs(eval_data = True, batch_size = batch_size)
print("begin data")
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding="SAME")
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1,2,2,1],strides=[1,6,6,1], padding="SAME")
def avg_pool_6x6(x):
return tf.nn.avg_pool(x, ksize=[1, 6, 6, 1],
strides=[1, 6, 6, 1], padding='SAME')
x = tf.placeholder(tf.float32, [None,24,24,3])
y = tf.placeholder(tf.float32, [None, 10])
# 第一层
W_conv1 = weight_variable([5, 5, 3, 64])
b_conv1 = bias_variable([64])
x_image = tf.reshape(x, [-1, 24, 24, 3])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
# 第二层
W_conv2 = weight_variable([5, 5, 64, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
# 第三层
W_conv3 = weight_variable([5, 5, 64, 10])
b_conv3 = bias_variable([10])
h_conv3 = tf.nn.relu(conv2d(h_pool2, W_conv3) + b_conv3)
nt_hpool3=avg_pool_6x6(h_conv3)#10
nt_hpool3_flat = tf.reshape(nt_hpool3, [-1, 10])
# 分类
y_conv=tf.nn.softmax(nt_hpool3_flat)
# 损失计算
cross_entropy = -tf.reduce_sum(y*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
# 训练
sess = tf.Session()
sess.run(tf.global_variables_initializer())
tf.train.start_queue_runners(sess=sess)
for i in range(15000):#20000
image_batch, label_batch = sess.run([images_train, labels_train])
label_b = np.eye(10,dtype=float)[label_batch] #one hot
train_step.run(feed_dict={x:image_batch, y: label_b},session=sess)
if i%200 == 0:
train_accuracy = accuracy.eval(feed_dict={
x:image_batch, y: label_b},session=sess)
print( "step %d, training accuracy %g"%(i, train_accuracy))
# 测试集
image_batch, label_batch = sess.run([images_test, labels_test])
label_b = np.eye(10,dtype=float)[label_batch]#one hot
print ("finished! test accuracy %g"%accuracy.eval(feed_dict={
x:image_batch, y: label_b},session=sess))
finished! test accuracy 0.492188准确率还比较低
本文介绍卷积神经网络相关概念,如多通道卷积的输入、输出通道,卷积函数tf.nn.conv2d的参数。还给出卷积计算、提取图片轮廓等实例,重点讲解在CIFAR数据集上用卷积神经网络进行图片分类,包括数据集下载、导入,以及网络结构等内容。
8608

被折叠的 条评论
为什么被折叠?



