卷积神经网络(Convolutional Neural NetWork,CNN):
自然语言处理、医药发现、灾难气候发现、人工智能程序。
输入层:
整个神经网络的输入
卷积层:
卷积神经网络中最重要的部分,卷积层中每一个节点的输入只是上一层神经网络的一小块,一般为3x3或者5x5。
卷积层试图将神经网络中的每一小块进行更加深入的分析从而得到抽象程度更高的特征。
通过卷积层处理过的节点矩阵会变得更深,经过卷积层之后的节点矩阵深度增加。
池化层:
池化层神经网络不会改变三维矩阵的深度,但是可以缩小矩阵的大小。
通过池化层可以进一步缩小最后全连接层中节点个数,从而达到减少整个神经网络中参数的目的。
全连接层:
经过多轮卷积层和池化层之后,在卷积神经网络的最后一般由1-2个全连接层来给出最后的分类结果。
获取高信息量的特征,完成分类。
Softmax层:
Softmax层主要用于分类问题,通过Softmax层,可以得到当前样例属于不同种类的概率分布情况。
CNN结构
卷积层:
过滤器/内核
过滤器可以将当前神经网络上的一个子节点矩阵转化为下一层神经网络上的一个单位节点矩阵。
需要指定过滤器尺寸:常用的过滤器尺寸有3x3和5x5
过滤器处理的矩阵深度和当前层神经网络节点矩阵的深度是一致的,虽然节点矩阵是三维的,但是过滤器尺寸只需要指定这两个维度。
尺寸指的是过滤器输入节点矩阵大小
需要指定过滤器深度:深度指的水输出单位节点矩阵的深度
卷积层的前向传播过程:通过将一个过滤器从神经网络当前层的左上角移动到右下角,并且在移动中计算每一个对应的单位矩阵。
过滤器每移动一次就会得到一个值。
卷积层前向传播得到的矩阵尺寸要小于当前层矩阵的尺寸。
为了避免尺寸变化,可以在当前层矩阵的边界加入0填充,可使卷积层前向传播结果矩阵大小和当前层矩阵保持一致。
可以设置过滤器移动的步长来 调整结果矩阵的大小。
共享每一个卷积层中的过滤器中的参数可以巨幅减少神经网络上的参数。
卷积层的参数个数个图片无关,它只和过滤器尺寸、深度以及当前层节点矩阵的深度有关。
池化层:
卷积层之间往往会加上池化层。
池化层可以非常有效的缩小矩阵的大小,减少最后全连接层中的参数。
使用池化层可以加快计算速度,防止过拟合。
使用的最多的池化层结构为最大池化层,使用较少的池化层为平均池化层。
池化层的过滤器需要人工设定过滤器尺寸、是否0填充、步长,等等设置。
卷积层和池化层的过滤器的方式是相似的,唯一的区别是卷积层使用的过滤器是横跨整个深度的,池化层使用的过滤器只影响一个深度上的点。
池化层的过滤器除了在厂矿移动之外还要在深度这个维度移动。
经典卷积神经网络:
LeNet-5模型:共7层。
卷积层(输入层)-池化层-卷积层-池化层-全连接层-全连接层-全连接层(输出层)
缺点:无法很好的处理类似于ImageNet这样比较大的图像数据集。
使用LeNet-5模型实现手写数字MNIST数据集识别
mnist_infernece.py:
import tensorflow as tf
INPUT_NODE = 784
OUTPUT_NODE = 10
IMAGE_SIZE = 28
NUM_CHANNELS = 1
NUM_LABELS = 10
CONV1_DEEP = 32
CONV1_SIZE = 5
CONV2_DEEP = 64
CONV2_SIZE = 5
FC_SIZE = 512
def inference(input_tensor, train, regularizer):
with tf.variable_scope('layer1-conv1'):
conv1_weights = tf.get_variable(
"weight", [CONV1_SIZE, CONV1_SIZE, NUM_CHANNELS, CONV1_DEEP],
initializer=tf.truncated_normal_initializer(stddev=0.1))
conv1_biases = tf.get_variable("bias", [CONV1_DEEP], initializer=tf.constant_initializer(0.0))
conv1 = tf.nn.conv2d(input_tensor, conv1_weights, strides=[1, 1, 1, 1], padding='SAME')
relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))
with tf.name_scope("layer2-pool1"):
pool1 = tf.nn.max_pool(relu1, ksize = [1,2,2,1],strides=[1,2,2,1],padding="SAME")
with tf.variable_scope("layer3-conv2"):
conv2_weights = tf.get_variable(
"weight", [CONV2_SIZE, CONV2_SIZE, CONV1_DEEP, CONV2_DEEP],
initializer=tf.truncated_normal_initializer(stddev=0.1))
conv2_biases = tf.get_variable("bias", [CONV2_DEEP], initializer=tf.constant_initializer(0.0))
conv2 = tf.nn.conv2d(pool1, conv2_weights, strides=[1, 1, 1, 1], padding='SAME')
relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))
with tf.name_scope("layer4-pool2"):
pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
pool_shape = pool2.get_shape().as_list()
nodes = pool_shape[1] * pool_shape[2] * pool_shape[3]
reshaped = tf.reshape(pool2, [pool_shape[0], nodes])
with tf.variable_scope('layer5-fc1'):
fc1_weights = tf.get_variable("weight", [nodes, FC_SIZE],
initializer=tf.truncated_normal_initializer(stddev=0.1))
if regularizer != None: tf.add_to_collection('losses', regularizer(fc1_weights))
fc1_biases = tf.get_variable("bias", [FC_SIZE], initializer=tf.constant_initializer(0.1))
fc1 = tf.nn.relu(tf.matmul(reshaped, fc1_weights) + fc1_biases)
if train: fc1 = tf.nn.dropout(fc1, 0.5)
with tf.variable_scope('layer6-fc2'):
fc2_weights = tf.get_variable("weight", [FC_SIZE, NUM_LABELS],
initializer=tf.truncated_normal_initializer(stddev=0.1))
if regularizer != None: tf.add_to_collection('losses', regularizer(fc2_weights))
fc2_biases = tf.get_variable("bias", [NUM_LABELS], initializer=tf.constant_initializer(0.1))
logit = tf.matmul(fc1, fc2_weights) + fc2_biases
return logit
mnist_train.py:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_infernece
import os
import numpy as np
BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.01
LEARNING_RATE_DECAY = 0.99
REGULARIZATION_RATE = 0.0001
TRAINING_STEPS = 10000
MOVING_AVERAGE_DECAY = 0.99
def train(mnist):
# 定义输出为4维矩阵的placeholder
x = tf.placeholder (tf.float32, [
BATCH_SIZE,
mnist_infernece.IMAGE_SIZE,
mnist_infernece.IMAGE_SIZE,
mnist_infernece.NUM_CHANNELS],
name='x-input')
y_ = tf.placeholder (tf.float32, [None, mnist_infernece.OUTPUT_NODE], name='y-input')
regularizer = tf.contrib.layers.l2_regularizer (REGULARIZATION_RATE)
y = mnist_infernece.inference (x, False, regularizer)
global_step = tf.Variable (0, trainable=False)
# 定义损失函数、学习率、滑动平均操作以及训练过程。
variable_averages = tf.train.ExponentialMovingAverage (MOVING_AVERAGE_DECAY, global_step)
variables_averages_op = variable_averages.apply (tf.trainable_variables ())
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits (logits=y, labels=tf.argmax (y_, 1))
cross_entropy_mean = tf.reduce_mean (cross_entropy)
loss = cross_entropy_mean + tf.add_n (tf.get_collection ('losses'))
learning_rate = tf.train.exponential_decay (
LEARNING_RATE_BASE,
global_step,
mnist.train.num_examples / BATCH_SIZE, LEARNING_RATE_DECAY,
staircase=True)
train_step = tf.train.GradientDescentOptimizer (learning_rate).minimize (loss, global_step=global_step)
with tf.control_dependencies ([train_step, variables_averages_op]):
train_op = tf.no_op (name='train')
# 初始化TensorFlow持久化类。
saver = tf.train.Saver ()
with tf.Session () as sess:
tf.global_variables_initializer ().run ()
for i in range (TRAINING_STEPS):
xs, ys = mnist.train.next_batch (BATCH_SIZE)
reshaped_xs = np.reshape (xs, (
BATCH_SIZE,
mnist_infernece.IMAGE_SIZE,
mnist_infernece.IMAGE_SIZE,
mnist_infernece.NUM_CHANNELS))
_, loss_value, step = sess.run ([train_op, loss, global_step], feed_dict={x: reshaped_xs, y_: ys})
if i % 1000 == 0:
print ("After %d training step(s), loss on training batch is %g." % (step, loss_value))
def main(argv=None):
mnist = input_data.read_data_sets("./MNIST_data", one_hot=True)
train(mnist)
if __name__ == '__main__':
main()
执行
mnist_train.py开始训练模型。
经典用于图片分类问题的卷积神经网络结构:
输入层—>(卷积层+ —>池化层?)+ —>全连接层+
大部分卷积神经网络中一般最多连续使用三层卷积层
在过滤器深度上,大部分卷积神经网络都采用逐层递增方式。
卷积层的步长一般为1-3。
池化层配置较为简单,用的最多的是最大池化层,过滤器边长和步长一般为2-3
Inception-v3模型
Inception模型结构是一种和LeNet-5结构完全不一样的卷积神经网络结构。
Inception-v3模型中Inception结构是将不同的卷积层通过并联的方式结合在一起。
Inception模型:
Inception可以使用不同尺寸的过滤器,然后再将得到的矩阵拼接起来。
Inception-v3总共有46层,由11个Inception模块组成。
代码: