最关键就是要理解到卷积神经网络的结构:
卷积层-激活函数-池化层-全连接层(大概就是卷积神经网络的机构了!)
来按惯例说一下为什么要用卷积神经网络,和为何他会那么热门。
答:因为好用,因为错误率低,反正就是牛逼。然后就看一下图,理解一下。(里面框起来的,就是经过三次这个流程。
按套路介绍一下各个层的特点:
- 神经网络(neural networks)的基本组成包括输入层、隐藏层、输出层。而卷积神经网络的特点在于隐藏层分为卷积层和池化层(pooling layer,又叫下采样层)。
- 卷积层:通过在原始图像上平移来提取特征,每一个特征就是一个特征映射。
- 池化层:通过特征后稀疏参数来减少学习的参数,降低网络的复杂度,(最大池化和平均池化)。
- (等下会说各个层的怎么去理解)
先说一下卷积层:(用通俗的话来解释何为卷积)
卷积,先意象一下,卷起来,然后积(“集”?)起来。
先了解:步长:下图就是步长的解释。一个方框(33也可以是任意任意)移动的距离、
橙色的那一个矩阵也就是过滤器filter(也叫卷积核)
先了解一下什么叫填充:
上图为步长为2的时候,如果当步长为3的时候,会出现一种情况就是,这个方框去到右边去了。
如图红色,那么有两种方式解决该问题。1.不越过,就是我不移动了,直接往下(VALID)。2.超过就零填充(SAME)(零填充是大家所推荐的方式)。
零填充如图:
了解完,那就了解一下什么叫卷积。
再重复一下:卷积,先意象一下,卷起来,然后积(“集”?)起来。
通俗的话来来将就是:将一堆数据(一个方阵下的数)转换成(或卷积成,意象一下)一个数字,集起来,转换成一个数字
对于激活函数:它的作用就是增加网络的非线性分割能力。通常选择有Sigmod 和 relu(更推荐relu)。
- why?
- 第一,采用sigmoid等函数,反向传播求误差梯度时,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多
- 第二,对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失的情况(求不出权重和偏置)
http://playground.tensorflow.org/ 该网址里面有激活函数选择后的产生学习速率的不同结果。
对于池化层:Pooling层主要的作用是特征提取,通过去掉Feature Map中不重要的样本,进一步减少参数数量。Pooling的方法很多,最常用的是Max Pooling。
为什么要这么做,因为在图片中,有很多相似的像素点存在,所以我只需要一个最大的那个,就可以了,不必要去对其他相似的像素点进行计算。
比如这个图片上,这三个方框里面的像素点其实都差不多的。
利用卷积神经网络来实现数字识别案例代码
def weight_variables(shape):
w = tf.Variable(tf.random_normal(shape=shape, mean=0.0, stddev=1.0))
return w
def bais_variable(shape):
bais = tf.Variable(tf.constant(0.0, shape=shape))
return bais
def model():
# 1、每一次训练数据都需要准备数据的占位符
with tf.variable_scope("data"):
x = tf.placeholder(tf.float32, [None, 784])
y_true = tf.placeholder(tf.int32, [None, 10])
# 2、开始卷积 ,第一层卷积, 卷积核大小5*5 32个卷积核 步长为1 零填充
with tf.variable_scope("conv1"):
# 关于权重都需要随机初始化,然后慢慢让他训练好
w_conv1 = weight_variables([5, 5, 1, 32]) # 第一个维度为5,第二个维度为5,第三个维度为1
b_conv1 = bais_variable([32])
x_reshape = tf.reshape(x, [-1, 28, 28, 1])
# [None, 28, 28, 1]-----> [None, 28, 28, 32]
x_relu1 = tf.nn.relu(tf.nn.conv2d(x_reshape, w_conv1, strides=[1, 1, 1, 1], padding="SAME") + b_conv1)
# 池化 2*2 ,strides2 [None, 28, 28, 32]---->[None, 14, 14, 32]
x_pool1 = tf.nn.max_pool(x_relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
# 3、二卷积层卷积: 5*5*32,64个filter,strides=1 激活: tf.nn.relu 池化:
with tf.variable_scope("conv2"):
# 随机初始化权重, 权重:[5, 5, 32, 64] 偏置[64]
w_conv2 = weight_variables([5, 5, 32, 64])
b_conv2 = bais_variable([64])
# 卷积,激活,池化计算
# [None, 14, 14, 32]-----> [None, 14, 14, 64]
x_relu2 = tf.nn.relu(tf.nn.conv2d(x_pool1, w_conv2, strides=[1, 1, 1, 1], padding="SAME") + b_conv2)
x_pool2 = tf.nn.max_pool(x_relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
# 4、全连接层 [None, 7, 7, 64]--->[None, 7*7*64]*[7*7*64, 10]+ [10] =[None, 10]
with tf.variable_scope("fc"):
w_fc = weight_variables([7 * 7 * 64, 10])
b_fc = bais_variable([10])
x_fc_reshape = tf.reshape(x_pool2, [-1, 7 * 7 * 64])
y_predict = tf.matmul(x_fc_reshape, w_fc) + b_fc
return x, y_true, y_predict
def conv_fc():
# 获取真实的数据
mnist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True)
# 定义模型,得出输出
x, y_true, y_predict = model()
# 进行交叉熵损失计算
# 3、求出所有样本的损失,然后求平均值
with tf.variable_scope("soft_cross"):
# 求平均交叉熵损失
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))
# 4、梯度下降求出损失
with tf.variable_scope("optimizer"):
train_op = tf.train.GradientDescentOptimizer(0.0001).minimize(loss)
# 5、计算准确率
with tf.variable_scope("acc"):
equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))
# equal_list None个样本 [1, 0, 1, 0, 1, 1,..........]
accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
# 定义一个初始化变量的op
init_op = tf.global_variables_initializer()
saver = tf.train.Saver()
# 开启回话运行
with tf.Session() as sess:
sess.run(init_op)
if FLAGES.is_juanji == 0:
# 循环去训练
for i in range(1000):
# 取出真实存在的特征值和目标值
mnist_x, mnist_y = mnist.train.next_batch(50)
# 运行train_op训练
sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})
print("训练第%d步,准确率为:%f" % (i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y})))
saver.save(sess, "./tmp/ckpt3/conv_fc_model")
elif FLAGES.is_juanji == 1:
saver.restore(sess, "./tmp/ckpt3/conv_fc_model")
for i in range(500):
# 取出真实存在的特征值和目标值
mnist_x, mnist_y = mnist.train.next_batch(50)
# 运行train_op训练
sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})
print("训练第%d步,准确率为:%f" % (i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y})))
saver.save(sess, "./tmp/ckpt3/conv_fc_model")
elif FLAGES.is_juanji == 2:
saver.restore(sess, "./tmp/ckpt3/conv_fc_model")
for i in range(100):
# 每次测试一张图片 [0,0,0,0,0,1,0,0,0,0]
x_test, y_test = mnist.test.next_batch(1)
print("第%d张图片,手写数字图片目标是:%d, 预测结果是:%d" % (
i,
tf.argmax(y_test, 1).eval(),
tf.argmax(sess.run(y_predict, feed_dict={x: x_test, y_true: y_test}), 1).eval()
))
return None
if __name__ == '__main__':
# full_connected()
conv_fc()