很多时候看似自己懂了,其实不把自己的理解总结出来,永远不会发现自己真正不懂得地方。所以借着学习卷积神经网络的机会,记录一下自己的理解。如果有出现偏差的地方,希望大家指正,共同学习。
一 卷积神经网络
积神经网络(Convolutional Neural Network,CNN)是一种前馈神经网络,它的人工神经元可以响应一部分覆盖范围内的周围单元,对于大型图像处理有出色表现。[2] 它包括卷积层(convolutional layer)和池化层(pooling layer)。
二 卷积神经网络结构
卷积神经网络结构如上图所示,输入是图像处理后的数据,以矩阵的形式表示,如上面汽车图片;然后经过
卷积层CONV转换;在经过线性整流RELU;卷积层和线性整流层可以多次叠加;再经过池化POOL;卷积层,
线性整流层和池化过程也可以多次叠加;最后经过全连接FC;全连接也可以叠加多次。结构如下:
Input->((CONV->RELU)*m->POOL)*n->(FC)*k->output
输入图像如下,高度height,
宽度width,图片像素rgb表示channels,
所以图片表示如下,
X[width, height, channels]。
三 卷积层
卷积层主要要解决的问题是,我们使用全连接的神经网络处理图片输入,如果图片比较小,没有任何问题,但是当图片
信息量比较大时,这样全连接计算量就变得非常大,训练模型代价就非常昂贵。为了解决这个问题,卷积神经网络使用卷积
层的概念,将卷积层神经网络设计成m*n的大小k个filter网络层。如果用m*n的网络层对输入进行拟合呢,就需要用m*n的
视野在输入图片特征上进行滑动,滑动的步伐会再x和y方向进行[S1,S2]步长的滑动。m*n*k的神经网络在所有图片输入特征
上是共享的。
简化一下,我们只在图片的一个方向进行窗口滑动,如上图所示。我们在图片的X轴上进行滑动,我们再X轴上的视野是F=3,
图片在x轴的宽度W=5,我们用0补偿图片x轴的两边P=1,第一幅度滑动步长S=1,第二幅图步长S=2。卷积层的输出大小等于
SIZE(Output) = (W - F + 2*P)/S + 1,所以第一个神经网络的输出大小等于5,第二神经网络的输出大小等于3。
二维图片输入卷积过程,类似于上面简化的图片处理过程,只不过卷积的视野沿着x轴y轴的方向进行滑动,并产生二维的
输出结果。
四 线性整流(ReLU)
通常意义下,线性整流函数代指代数学中的斜坡函数,即
而在神经网络中,线性整流函数作为神经元的激活函数,定义了该神经元在线性变换
之后的的非线性输出结果。换言之,对于进入神经元的来自上一层神经网络的输入向量 X
,使用线性整流激活函数的神经元会输出
至下一层神经元或作为整个神经网络的输出(取决现神经元在网络结构中所处位置)。
五 池化
池化的过程是信息压缩的过程,池化层以上面卷积层和线性整流后的输出结果作为输入,然后对输入的图片信息,进行下采样,采样filter是一个width*height的窗口。如右图所示,输入是8*8的输入图片,通过2*2的filters,以S=2的步伐滑动,然后进行max采样,会产生2*2的输出特征。
五 全连接
全连接层是普通的神经网络结构,会把输入全部连接到全连接层神经元。
六 TensorFlow实现卷积神经网络
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
# Imports
import numpy as np
import tensorflow as tf
tf.logging.set_verbosity(tf.logging.INFO)
# Our application logic will be added here
def cnn_model_fn(features, labels, mode):
"""Model function for CNN."""
# Input Layer
input_layer = tf.reshape(features["x"], [-1, 28, 28, 1])
# Convolutional Layer #1
# 卷积层1
# 卷积核大小为5x5,卷积核数量为32, 激活方法使用RELU
# 输入Tensor维度: [batch_size, 28, 28, 1]
# 输出Tensor维度: [batch_size, 28, 28, 32]
conv1 = tf.layers.conv2d(
inputs=input_layer,
filters=32,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu)
# Pooling Layer #1
# 池化层1
# 采用2x2维度的最大化池化操作,步长为2
# 输入Tensor维度: [batch_size, 28, 28, 32]
# 输出Tenso维度: [batch_size, 14, 14, 32]
pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
# Convolutional Layer #2 and Pooling Layer #2
# 卷积层2
# 卷积核大小为5x5,卷积核数量为64, 激活方法使用RELU.
# 输入Tensor维度: [batch_size, 14, 14, 32]
# 输出Tensor维度: [batch_size, 14, 14, 64]
conv2 = tf.layers.conv2d(
inputs=pool1,
filters=64,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu)
# 池化层2
# 采用2x2维度的最大化池化操作,步长为2
# 输入Tensor维度: [batch_size, 14, 14, 64]
# 输出Tensor维度: [batch_size, 7, 7, 64]
pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
# Dense Layer
# 展开并列池化层输出Tensor为一个向量
# 输入Tensor维度: [batch_size, 7, 7, 64]
# 输出Tensor维度: [batch_size, 7 * 7 * 64]
pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])
# 全链接层
# 该全链接层具有1024神经元
# 输入Tensor维度: [batch_size, 7 * 7 * 64]
# 输出Tensor维度: [batch_size, 1024]
dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)
# 对全链接层的数据加入dropout操作,防止过拟合
# 40%的数据会被dropout,
dropout = tf.layers.dropout(
inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)
# Logits Layer
# Logits层,对dropout层的输出Tensor,执行分类操作
# 输入Tensor维度: [batch_size, 1024]
# 输出Tensor维度: [batch_size, 10]
logits = tf.layers.dense(inputs=dropout, units=10)
predictions = {
# Generate predictions (for PREDICT and EVAL mode)
"classes": tf.argmax(input=logits, axis=1),
# Add `softmax_tensor` to the graph. It is used for PREDICT and by the
# `logging_hook`.
"probabilities": tf.nn.softmax(logits, name="softmax_tensor")
}
if mode == tf.estimator.ModeKeys.PREDICT:
return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)
# Calculate Loss (for both TRAIN and EVAL modes)
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
# Configure the Training Op (for TRAIN mode)
if mode == tf.estimator.ModeKeys.TRAIN:
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
train_op = optimizer.minimize(
loss=loss,
global_step=tf.train.get_global_step())
return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)
# Add evaluation metrics (for EVAL mode)
eval_metric_ops = {
"accuracy": tf.metrics.accuracy(
labels=labels, predictions=predictions["classes"])}
return tf.estimator.EstimatorSpec(
mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
def main(unused_argv):
# Load training and eval data
mnist = tf.contrib.learn.datasets.load_dataset("mnist")
train_data = mnist.train.images # Returns np.array
train_labels = np.asarray(mnist.train.labels, dtype=np.int32)
eval_data = mnist.test.images # Returns np.array
eval_labels = np.asarray(mnist.test.labels, dtype=np.int32)
mnist_classifier = tf.estimator.Estimator(model_fn=cnn_model_fn, model_dir="/tmp/mnist_convnet_model")
# Set up logging for predictions
tensors_to_log = {"probabilities": "softmax_tensor"}
logging_hook = tf.train.LoggingTensorHook(tensors=tensors_to_log, every_n_iter=50)
# Train the model
train_input_fn = tf.estimator.inputs.numpy_input_fn(
x={"x": train_data},
y=train_labels,
batch_size=100,
num_epochs=None,
shuffle=True)
mnist_classifier.train(
input_fn=train_input_fn,
steps=10000,
hooks=[logging_hook])
# Evaluate the model and print results
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
x={"x": eval_data},
y=eval_labels,
num_epochs=1,
shuffle=False)
eval_results = mnist_classifier.evaluate(input_fn=eval_input_fn)
print(eval_results)
if __name__ == "__main__":
tf.app.run()
七 相关链接
- http://blog.csdn.net/witsmakemen/article/details/79183395
- http://blog.csdn.net/witsmakemen/article/details/79188393