卷积神经网络
提前了解~~
卷积层和池化层
相当于对原来的图像做了一个特征提取
卷积和激活一般都是联系在一起的,卷积后图像大小可以不变,每一次卷积就对应一次激活~~
但池化可以进行特征降维(常用的有Max pooling,Average pooling)
全连接层
把卷积层提取的特征再组合在一起,然后再用组合到一起的特征再进行分类
对全连接层(fully connected layer)的通俗理解:https://blog.csdn.net/qq_39521554/article/details/81385159
import tensorflow as tf
import random
import numpy as np
import matplotlib.pyplot as plt
import datetime
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("data/", one_hot=True)
输入层和输出层
tf.reset_default_graph() 用于清除默认图形堆栈并重置全局默认图形.说白了,就是每轮要清除无效的计算图。
注意:要放在 tf.Session() 前面
shape = [None, 28,28,1] 大部分情况下,处理的图像都是正方形,科学家证明过的,正方形比长方形好~,1指的是黑白图像,1个通道就行,RGB就得写3,3个通道。
None其实就是batchSize
tf.reset_default_graph()
sess = tf.InteractiveSession()
x = tf.placeholder("float", shape = [None, 28,28,1]) #shape in CNNs is always None x height x width x color channels
y_ = tf.placeholder("float", shape = [None, 10]) #shape is always None x number of classes
定义卷积层参数
从下面图像可以看到,这里定义的是一个3乘3大小的卷积核
[5, 5, 1, 32]: 这层卷积层总共设置32个神经元,也就是有32个卷积核去分别关注32个特征。窗口的大小是5×5,所以指向每个卷积层的权重也是5×5,因为图片是黑白色的,只有一个颜色通道,所以总共只有1个面,故每个卷积核都对应一组551的权重。
W_conv1 = tf.Variable(tf.truncated_normal([5, 5, 1, 32], stddev=0.1))#shape is filter x filter x input channels x output channels
b_conv1 = tf.Variable(tf.constant(.1, shape = [32])) #shape of the bias just has to match output channels of the filter
定义卷积层,池化层操作
input: 一个4维Tensor(N,H,W,C). 类型必须是以下几种类型之一: half, float32, float64.
filter: 卷积核. 类型和input必须相同,4维tensor, [filter_height, filter_width, in_channels, out_channels],如[5,5,3,32]
strides: 在input上切片采样时,每个方向上的滑窗步长,必须和format指定的维度同阶,如[1, 2, 2, 1],横,纵向步长为2
padding: 指定边缘填充类型: “SAME”, “VALID”. SAME表示卷积后图片保持不变,VALID则会缩小。
h_conv1 = tf.nn.conv2d(input=x, filter=W_conv1, strides=[1, 1, 1, 1], padding='SAME') + b_conv1 #卷积操作
h_conv1 = tf.nn.relu(h_conv1) #卷积完后用非线性激活函数进行映射
h_pool1 = tf.nn.max_pool(h_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') #池化操作
'''
可以用函数表达
'''
def conv2d(x, W):
return tf.nn.conv2d(input=x, filter=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, 2, 2, 1], padding='SAME')
第二次卷积
两次的卷积,
第一次以图像输入 28乘28乘1通道 ,以 14乘14乘32通道 输出
第二次以第一次的图输出 14乘14乘32 通道 为输入, 以 7乘7乘64通道 输出
32是输入了32张图,前面是只有黑白,也就1张图嘛,第三个参数必定和输入挂钩
64指的是神经元
#Second Conv and Pool Layers
W_conv2 = tf.Variable(tf.truncated_normal([5, 5, 32, 64], stddev=0.1)) #第二个卷积核
b_conv2 = tf.Variable(tf.constant(.1, shape = [64]))
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2) #第二次池化
两个全连接层
两次全连接
第一次,以卷积输出 7乘7乘64通道 全连接为 连接成为一个一维向量1024个数据,
第二次,以第一次的一维向量1024个元素输入,全连接为10个元素,
10个元素就对应,输出的每一维都是图片y属于该类别的概率。
一次池化减二分之一,经过了两次变成7乘7
此时,图片是7x7的大小。我们在这里加入一个有1024个神经元的全连接层。之后把刚才池化后输出的张量reshape成一个一维向量,再将其与权重相乘,加上偏置项,再通过一个ReLU激活函数。
#First Fully Connected Layer
W_fc1 = tf.Variable(tf.truncated_normal([7 * 7 * 64, 1024], stddev=0.1))
b_fc1 = tf.Variable(tf.constant(.1, shape = [1024]))
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64]) #把一个矩阵reshape成一个条,-1会自动适应,其实在这里就是1啦
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
#Dropout Layer
keep_prob = tf.placeholder("float") #指定一个保留率
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) #杀死部分神经元,防止过拟合
#Second Fully Connected Layer
W_fc2 = tf.Variable(tf.truncated_normal([1024, 10], stddev=0.1))
b_fc2 = tf.Variable(tf.constant(.1, shape = [10]))
#Final Layer
y = tf.matmul(h_fc1_drop, W_fc2) + b_fc2
利用的是跟前面回归一样的分类器
crossEntropyLoss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels = y_, logits = y))
trainStep = tf.train.AdamOptimizer().minimize(crossEntropyLoss)#会自适应调节学习率,一次比一次小,比梯度下降优化器更好
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
sess.run(tf.global_variables_initializer())
batchSize = 50
for i in range(1000):
batch = mnist.train.next_batch(batchSize)
trainingInputs = batch[0].reshape([batchSize,28,28,1])
trainingLabels = batch[1]
if i%100 == 0:
trainAccuracy = accuracy.eval(session=sess, feed_dict={x:trainingInputs, y_: trainingLabels, keep_prob: 1.0})
print ("step %d, training accuracy %g"%(i, trainAccuracy))
trainStep.run(session=sess, feed_dict={x: trainingInputs, y_: trainingLabels, keep_prob: 0.5})
输出结果:
step 0, training accuracy 0.1
step 100, training accuracy 0.94
step 200, training accuracy 0.98
step 300, training accuracy 1
step 400, training accuracy 0.98
step 500, training accuracy 0.96
step 600, training accuracy 0.94
step 700, training accuracy 0.98
step 800, training accuracy 0.98
step 900, training accuracy 0.98