网络结构:
#28*28 图片,
n_input = 784
#输出的大小
n_output = 10 # one_hot 5 0000010000
# 权重
#
weights = {
'wc1': tf.Variable(tf.random_normal([5, 5, 1, 20], stddev=0.1)),
'wc2': tf.Variable(tf.random_normal([5, 5, 20, 50], stddev=0.1)),
'wd1': tf.Variable(tf.random_normal([7*7*50, 500], stddev=0.1)),
'wd2': tf.Variable(tf.random_normal([500, n_output], stddev=0.1))
}
# 表数字 i 类的偏置量
biases = {'bc1': tf.Variable(tf.random_normal([20], stddev=0.1)),
'bc2': tf.Variable(tf.random_normal([50], stddev=0.1)),
'bd1': tf.Variable(tf.random_normal([500], stddev=0.1)),
'bd2': tf.Variable(tf.random_normal([n_output], stddev=0.1))}
使用2个卷积层,2个全连接层
layer1:conv2d, relu, maxpooling, dropout
layer2: conv2d,relu, maxpooling, dropout
fc1: 全连接, relu, dropout
fc2: 全连接 ,softmax
完整代码:
# -*- coding: utf-8 -*-
"""
Created on Sun Jul 8 21:26:34 2018
@author:
"""
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import input_data
mnist = input_data.read_data_sets('data/', one_hot=True)
trainimg = mnist.train.images
trainlabel = mnist.train.labels
testimg = mnist.test.images
testlabel = mnist.test.labels
print ("MNIST ready")
#28*28 图片,
n_input = 784
#输出的大小
n_output = 10 # one_hot 5 0000010000
# 权重
#
weights = {
'wc1': tf.Variable(tf.random_normal([5, 5, 1, 20], stddev=0.1)),
'wc2': tf.Variable(tf.random_normal([5, 5, 20, 50], stddev=0.1)),
'wd1': tf.Variable(tf.random_normal([7*7*50, 500], stddev=0.1)),
'wd2': tf.Variable(tf.random_normal([500, n_output], stddev=0.1))
}
# 表数字 i 类的偏置量
biases = {'bc1': tf.Variable(tf.random_normal([20], stddev=0.1)),
'bc2': tf.Variable(tf.random_normal([50], stddev=0.1)),
'bd1': tf.Variable(tf.random_normal([500], stddev=0.1)),
'bd2': tf.Variable(tf.random_normal([n_output], stddev=0.1))}
#%%
def conv_basic(_input, _w, _b, _keepratio):
# [55000,784]
# INPUT,转换矩阵形状,改成一个28*28*1的,厚度自动
_input_r = tf.reshape(_input, shape=[-1, 28, 28, 1])
# CONV LAYER 1
#tf.nn.conv2d是TensorFlow里面实现卷积的函数
#tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)
#除去name参数用以指定该操作的name,与方法有关的一共五个参数:
#第一个参数input:指需要做卷积的输入图像,它要求是一个Tensor,具有[batch, in_height, in_width, in_channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数],注意这是一个4维的Tensor,要求类型为float32和float64其中之一
#第二个参数filter:相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height, filter_width, in_channels, out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,有一个地方需要注意,第三维in_channels,就是参数input的第四维
#第三个参数strides:卷积时在图像每一维的步长,这是一个一维的向量,长度4
#第四个参数padding:string类型的量,只能是"SAME","VALID"其中之一,当其为‘SAME’时,表示卷积核可以停留在图像边缘
#第五个参数:use_cudnn_on_gpu:bool类型,是否使用cudnn加速,默认为true
#结果返回一个Tensor,这个输出,就是我们常说的feature map
_conv1 = tf.nn.conv2d(_input_r, _w['wc1'], strides=[1, 1, 1, 1], padding='SAME')
#tf.nn.relu:修正线性,max(features, 0)
#tf.nn.bias_add:这个函数的作用是将偏差项 bias 加到 value 上面。
#这个操作你可以看做是 tf.add 的一个特例,其中 bias 必须是一维的。
#该API支持广播形式,因此 value 可以有任何维度。
#但是,该API又不像 tf.add ,可以让 bias 的维度和 value 的最后一维不同。
_conv1 = tf.nn.relu(tf.nn.bias_add(_conv1, _b['bc1']))
#最大池化
#value: 一个四维的Tensor。数据维度是 [batch, height, width, channels]。数据类型是float32,float64,qint8,quint8,qint32。
#ksize: 一个长度不小于4的整型数组。每一位上面的值对应于输入数据张量中每一维的窗口对应值。
#strides: 一个长度不小于4的整型数组。该参数指定滑动窗口在输入数据张量每一维上面的步长。
#padding: 一个字符串,取值为 SAME 或者 VALID 。
#name: (可选)为这个操作取一个名字。
_pool1 = tf.nn.max_pool(_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
#处理过拟合操作
_pool_dr1 = tf.nn.dropout(_pool1, _keepratio)
# CONV LAYER 2
_conv2 = tf.nn.conv2d(_pool_dr1, _w['wc2'], strides=[1, 1, 1, 1], padding='SAME')
_conv2 = tf.nn.relu(tf.nn.bias_add(_conv2, _b['bc2']))
_pool2 = tf.nn.max_pool(_conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
_pool_dr2 = tf.nn.dropout(_pool2, _keepratio)
# VECTORIZE 向量化
_dense1=tf.reshape(_pool_dr2,[-1,_w['wd1'].get_shape().as_list()[0]])
'fully connectied layer'
_fc1=tf.nn.relu(tf.add( tf.matmul(_dense1,_w['wd1']),_b['bd1'] ))
_fc_dr1=tf.nn.dropout(_fc1,_keepratio)
'fully connected layer 2'
_out=tf.add(tf.matmul(_fc_dr1,_w['wd2']),_b['bd2'])
# RETURN
out = { 'input_r': _input_r, 'conv1': _conv1, 'pool1': _pool1, 'pool1_dr1': _pool_dr1,
'conv2': _conv2, 'pool2': _pool2, 'pool_dr2': _pool_dr2, 'dense1': _dense1,
'fc1': _fc1, 'fc_dr1': _fc_dr1, 'out': _out
}
return out
print ("CNN READY")
#%%
a=tf.Variable(tf.random_normal([3,3,1,64],stddev=.1))
print(a)
#a=tf.Print(a,[a],'a=')
'variable 初始化'
init= tf.global_variables_initializer()
sess=tf.Session()
sess.run(init)
sess.run(a)
#%%
'''
#通过操作符号变量来描述这些可交互的操作单元
#x不是一个特定的值,而是一个占位符placeholder,我们在TensorFlow运行计算时输入这个值。
#我们希望能够输入任意数量的MNIST图像,每一张图展平成784维的向量。
#我们用2维的浮点数张量来表示这些图,这个张量的形状是[None,784 ](这里的None表示此张量的第一个维度可以是任何长度的。)
'''
x=tf.placeholder(tf.float32,[None,n_input])
y=tf.placeholder(tf.float32,[None,n_output])
keep_ratio=tf.placeholder(tf.float32)
'FUNCTIONS'
'调用CNN函数,返回运算完成的结果'
_pred=conv_basic(x,weights,biases,keep_ratio)['out']
'''
#交叉熵
#首先看输入logits,它的shape是[batch_size, num_classes] ,
#一般来讲,就是神经网络最后一层的输出z。
#另外一个输入是labels,它的shape也是[batch_size, num_classes],就是我们神经网络期望的输出。
#这个函数的作用就是计算最后一层是softmax层的cross entropy,只不过tensorflow把softmax计算与cross entropy计算放到一起了。
#用一个函数来实现,用来提高程序的运行速度
#http://www.jianshu.com/p/fb119d0ff6a6
'''
cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=_pred,labels=y))
'''
#Adam算法
AdamOptimizer通过使用动量(参数的移动平均数)来改善传统梯度下降,促进超参数动态调整。
我们可以通过创建标签错误率的摘要标量来跟踪丢失和错误率
一个寻找全局最优点的优化算法,引入了二次方梯度校正。
相比于基础SGD算法,1.不容易陷于局部优点。2.速度更快
'''
optm=tf.train.AdamOptimizer(learning_rate=.001).minimize(cost)
corr=tf.equal(tf.argmax(_pred,1),tf.argmax(y,1))
#cast:将x或者x.values转换为dtype
#tf.reduce_mean 求tensor中平均值
#http://blog.csdn.net/lenbow/article/details/52152766
accr=tf.reduce_mean(tf.cast(corr,tf.float32))
'初始化'
init=tf.global_variables_initializer()
init_local=tf.local_variables_initializer()
'SAVEER'
print('GRAPH READY')
#%%
sess=tf.Session()
sess.run(init)
sess.run(init_local)
'训练次数'
training_epochs=15
batch_size=100
display_step=10
for epoch in range(training_epochs):
'平均误差'
avg_cost=0.
total_batch=int(mnist.train.num_examples/batch_size)
for i in range(total_batch):
if i%10==0:
print(i,'/',total_batch)
batch_xs,batch_ys=mnist.train.next_batch(batch_size)
feeds={x:batch_xs,y:batch_ys,keep_ratio:.7}
sess.run(optm,feed_dict=feeds)
avg_cost+=sess.run(cost,feed_dict=feeds)/total_batch
train_acc=sess.run(accr,feed_dict=feeds)
if epoch%2==0:
print ("Epoch: %03d/%03d cost: %.9f" % (epoch, training_epochs, avg_cost))
train_acc = sess.run(accr, feed_dict={x: batch_xs, y: batch_ys, keep_ratio:1.})
print (" Training accuracy: %.3f" % (train_acc))
test_acc = sess.run(accr, feed_dict={x: testimg, y: testlabel, keep_ratio:1.})
print (" Test accuracy: %.3f" % (test_acc))
print ("OPTIMIZATION FINISHED")
#%%