卷积神经网络CNN


  CNN是一种至少包含一层卷积层的神经网络模型,卷积层的目的是将卷积核应用到图像张量的所有点上,并通过将卷积核在输入张量上滑动生成经过滤波处理的张量.简单的CNN架构通常会包含卷积层,池化层,非线性变换层,全连接层.通过这些层网络会被填充大量的信息,因此模型便可以进行复杂的模式匹配.
本文主要是通过TF1.5这个工具,展示CNN中各个层对图像信息的加工过程.
主要内容:

  • 张量在TF中的表示TensorFlow基础知识
  • 卷积层
  • 激活函数
  • 池化层
import tensorflow as tf
import matplotlib.pyplot as plt
# 图像经过解码后是一张量的形式表示
# 定义一个包含两个张量[图像]的常量
image_batch = tf.constant([
    [
        [[0, 255, 0], [0, 255, 0], [0, 255, 0]],
        [[0, 255, 0], [0, 255, 0], [0, 255, 0]]
    ],
    [
        [[0, 0, 255], [0, 0, 255], [0, 0, 255]],
        [[0, 0, 255], [0, 0, 255], [0, 0, 255]]
    ]
])
image_batch.get_shape()

     重绘图像

         

非图像数据分类的神经网络有哪些 cnn处理非图像_2d


卷积层

卷积是CNN的重要组成,通常也是网络的第一层,下面主要介绍卷积层对图像的一些操作

# 在TensorFlow中卷积运算通过tf.nn.conv2d()完成.同时TF还提供其特定的卷积运算.
# 定义一个张量,简单实现卷积运算
tensor_1 = tf.constant([
    [
        [[0.0],[1.0]],
        [[2.0],[3.0]]
    ],
])

# 卷积核
kernel_1 = tf.constant([
    [
        [[1.0, 2.0]]
    ]
])
# 张量的shape
tensor_1.get_shape()
# TensorShape[张量数量,张量高度,张量宽度,通道数]
TensorShape([Dimension(1), Dimension(2), Dimension(2), Dimension(1)])

# kernel_1
kernel_1.get_shape()

TensorShape([Dimension(1), Dimension(1), Dimension(1), Dimension(2)])


# 卷积后,得到一个新张量(特征图)
conv2d_1 = tf.nn.conv2d(tensor_1, kernel_1 ,strides=[1, 1, 1, 1],
                                                  padding='SAME')
sess.run(conv2d_1)
array([
    [
        [[0.0, 0.0], [1.0, 2.0]],
        [[2.0, 4.0], [3.0, 6.0]]
    ]
])
conv2d_1.get_shape()

TensorShape([Dimension(1), Dimension(2), Dimension(2), Dimension(2)])

sess.run(tensor_1)[0][1][1],sess.run(conv2d_1)[0][1][1]

(array([3.], dtype=float32), array([3., 6.], dtype=float32))

# tensor_2 [1x5x5x1]
tensor_2 = tf.constant([
    [
        [[2.0], [1.0], [0.0], [2.0], [3.0]],
        [[9.0], [5.0], [4.0], [2.0], [0.0]],
        [[2.0], [3.0], [4.0], [5.0], [6.0]],
        [[1.0], [2.0], [3.0], [1.0], [0.0]],
        [[0.0], [4.0], [4.0], [2.0], [8.0]],
    ],
])

# 卷积核[3x3x1x1]
kernel_2 = tf.constant([
    [
        [[-1.0]], [[0.0]], [[1.0]]
    ],
    [
        [[-1.0]], [[0.0]], [[1.0]]
    ],
    [
        [[-1.0]], [[0.0]], [[1.0]]
    ]
])
tensor_2.get_shape()
TensorShape([Dimension(1), Dimension(5), Dimension(5), Dimension(1)])

kernel_2.get_shape()
TensorShape([Dimension(3), Dimension(3), Dimension(1), Dimension(1)])

# 卷积,strides,padding(下面会介绍)
# padding = 'VALID',输入会比输入尺寸小
conv2d_2 = tf.nn.conv2d(tensor_2, kernel_2, strides =[1,1,1,1],
                        padding='VALID')
sess.run(conv2d_2)
array([
    [
     [[-5.],[ 0.],[ 1.]],
     [[-1.],[-2.],[-5.]],
     [[ 8.],[-1.],[ 3.]]
    ],
], dtype=float32)

在卷积过程中会遇到这种情况:卷积核未到达图像的边界时,下一步的移动会越过图像的边界.
针对这种情况,tensorflow提供的措施是对超出图像边界的部分进行填充,即边界填充.
SAME:当卷积核超出图像边界时,会进行0填充,卷积的输出与输入相同
VALID:考虑卷积核的尺寸,尽量不越过图像边界.卷积输出小于输入

# 边缘检测卷积核
kernel_3 = tf.constant([
    [
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]],
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]],
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]]
    ],
    [
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]],
        [[ 8., 0., 0.], [0.,  8., 0.], [0., 0.,  8.]],
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]]
    ],
    [
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]],
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]],
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]]
    ]
])
# 卷积前图像
plt.imshow(sess.run(image))
plt.show()
sess.run(image).shape
(393, 700, 3)

# uint8转化为浮点型
image = tf.to_float(image)
# 转化为一个四维张量
conv2d_3 = tf.nn.conv2d(tf.reshape(image,[1,393,700,3]), kernel_3,
                        [1,1,1,1], padding='SAME')
conv2d_3.get_shape()
TensorShape([Dimension(1), Dimension(393), Dimension(700), Dimension(3)])

# tf.minimum()和tf.nn.relu()是将卷积后的像素值保持在RGB颜色值的合法范围内[0,255]
conved_image = tf.minimum(tf.nn.relu(conv2d_3), 255)
plt.imshow(sess.run(conved_image).reshape(393,700,3))
plt.show()
# 锐化卷积核
kernel_4 = tf.constant([
    [
        [[ 0., 0., 0.], [0.,  0., 0.], [0., 0.,  0.]],
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]],
        [[ 0., 0., 0.], [0.,  0., 0.], [0., 0.,  0.]]
    ],
    [
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]],
        [[ 5., 0., 0.], [0.,  5., 0.], [0., 0.,  5.]],
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]]
    ],
    [
        [[ 0., 0., 0.], [0.,  0., 0.], [0., 0.,  0.]],
        [[-1., 0., 0.], [0., -1., 0.], [0., 0., -1.]],
        [[ 0., 0., 0.], [0.,  0., 0.], [0., 0.,  0.]]
    ]
])

# 卷积
conv2d_4 = tf.nn.conv2d(tf.reshape(image,[1,393,700,3]), kernel_4,
              [1,1,1,1], padding='SAME')
sharpen_image = tf.minimum(tf.nn.relu(conv2d_4), 255)
# 通过索引访问第一个张量,就不用对图像张量进行resize操作了
plt.imshow(sess.run(sharpen_image)[0])
plt.show()
features = tf.to_float(tf.range(-20,20))
# Relu
plt.plot(sess.run(features), sess.run(tf.nn.relu(features)))
plt.grid(True)
plt.title('Relu')
plt.show()
# sigmoid
plt.plot(sess.run(features), sess.run(tf.sigmoid(features)))
plt.grid(True)
plt.title("Sigmoid")
plt.show()

        

非图像数据分类的神经网络有哪些 cnn处理非图像_非图像数据分类的神经网络有哪些_02

# tanh
plt.plot(sess.run(features), sess.run(tf.tanh(features)))
plt.title("Tanh")
plt.grid(True)
plt.show()
# drop
plt.scatter(sess.run(features), sess.run(tf.nn.dropout(features, keep_prob=0.5)))
plt.title("Dropout")
plt.grid(True)
plt.show()
# 输入张量
input_tensor = tf.constant([
    [
        [[1.0], [1.0], [2.0], [4.0]],
        [[5.0], [6.0], [7.0], [8.0]],
        [[3.0], [2.0], [1.0], [0.0]],
        [[1.0], [2.0], [3.0], [4.0]]
    ]
])
kernel_pool = [1, 2, 2, 1]
strides = [1, 2, 2, 1] # 跟卷积作用相同
max_pool = tf.nn.max_pool(input_tensor, kernel_pool, strides, 'VALID')
sess.run(max_pool)
array([
    [
        [[6.],[8.]],
        [[3.],[4.]]
    ]
], dtype=float32)
# 平均池化
avg_pool = tf.nn.avg_pool(input_tensor, kernel_pool, strides, 'VALID')
sess.run(avg_pool)
array([
    [
        [[3.25],[5.25]],
        [[2.],[2.]]
    ]
], dtype=float32)
# 下面分别对这副图像进行最大和平均池化
image_file2 = tf.gfile.FastGFile('123.jpg','rb').read()
image_2 = tf.image.decode_jpeg(image_file2)
plt.imshow(sess.run(image_2))
plt.show()
max_pool_image = tf.nn.max_pool(tf.reshape(image_2,[1,873,1070,3]),
                       [1,6,6,1],[1,5,5,1],'VALID')
plt.imshow(sess.run(max_pool_image)[0])
plt.show()
max_pool_image
<tf.Tensor 'MaxPool_8:0' shape=(1, 174, 214, 3) dtype=uint8>

# 平均池化层输入张量为浮点型数据
avg_pool_image = tf.nn.avg_pool(tf.to_float(tf.reshape(image_2,[1,873,1070,3])),
                                [1,1,2,1],[1,1,1,1],'VALID')
plt.imshow(sess.run(avg_pool_image)[0])
plt.show()
# 平均池化层输入张量为浮点型数据
avg_pool_image_1 = tf.nn.avg_pool(tf.to_float(tf.reshape(image_2,[1,873,1070,3])),
                                [1,2,2,1],[1,2,2,1],'VALID')
plt.imshow(sess.run(avg_pool_image_1)[0])
plt.show()