卷积神经网络实例1:CIFAR10

本文介绍卷积神经网络相关概念,如多通道卷积的输入、输出通道,卷积函数tf.nn.conv2d的参数。还给出卷积计算、提取图片轮廓等实例,重点讲解在CIFAR数据集上用卷积神经网络进行图片分类,包括数据集下载、导入,以及网络结构等内容。

几个概念

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准确率还比较低
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值