Tensorflow案例实战-11卷积神经网络模型架构(minst10分类任务)
网络模型
前期准备
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import input_data
minst=input_data.read_data_sets('data/',one_hot=True)
trainimg=minst.train.images
trainlabel=minst.train.labels
testimg=minst.test.images
testlabel=minst.test.labels
参数设置
n_input=784
n_output=10
weights={
#filter:w,h 连接的输入的深度 输出
'wc1':tf.Variable(tf.random_normal([3,3,1,64],stddev=0.1)),
'wc2':tf.Variable(tf.random_normal([3,3,64,128],stddev=0.1)),
#2*2变为1*1,即变为原来一半。28/2,两次pool,即为7.全连接层转换成向量所以是1024
'wd1':tf.Variable(tf.random_normal([7*7*128,1024],stddev=0.1)),
#前面是1024维向量,后面代表是10分类任务
'wd2':tf.Variable(tf.random_normal([1024,n_output],stddev=0.1)),
}
biases={
'bc1':tf.Variable(tf.random_normal([64],stddev=0.1)),
'bc2':tf.Variable(tf.random_normal([128],stddev=0.1)),
'bd1':tf.Variable(tf.random_normal([1024],stddev=0.1)),
'bd2':tf.Variable(tf.random_normal([n_output],stddev=0.1)),
}
函数
def conv_basic(_input,_w,_b,_keepratio):
#input预处理(转换成四维:batch_size,h,w,channel),-1:tensorflow自己推断
_input_r=tf.reshape(_input,shape=[-1,28,28,1])
#conv layer 1
#strides:四个维度的stride
_conv1=tf.nn.conv2d(_input_r,_w['wc1'],strides=[1,1,1,1],padding='SAME')
#mean,_var=tf.nn.moments(_conv1,[0,1,2])
#_conv1=tf.nn.batch_normalization(_conv1,_mean,_var,0,1,0.0001)
_conv1=tf.nn.relu(tf.nn.bias_add(_conv1,_b['bc1']))
_pool1=tf.nn.max_pool(_conv1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
#随机杀死节点,keepratio:保留比例
_pool_dr1=tf.nn.dropout(_pool1,_keepratio)
#conv layer2
_conv2=tf.nn.conv2d(_pool_dr1,_w['wc2'],strides=[1,1,1,1],padding='SAME')
#mean,_var=tf.nn.moments(_conv2,[0,1,2])
#_conv2=tf.nn.batch_normalization(_conv2,_mean,_var,0,1,0.0001)
_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
_densel=tf.reshape(_pool_dr2,[-1,_w['wd1'].get_shape().as_list()[0]])
#fully connected layer1
_fc1=tf.nn.relu(tf.add(tf.matmul(_densel,_w['wd1']),_b['bd1']))
_fc_dr1=tf.nn.dropout(_fc1,_keepratio)
#fully connected layer2
_out=tf.add(tf.matmul(_fc_dr1,_w['wd2']),_b['bd2'])
#return
out={'input_r':_input_r,'_conv1':_conv1,'pool1':_pool1,'pool_dr1':_pool_dr1,
'conv2':_conv2,'pool2':_pool2,'pool_dr2':_pool_dr2,'densel':_densel,
'fcl':_fc1,'fc_dr1':_fc_dr1,'out':_out
}
return out
TensorFlow中CNN的两种padding方式“SAME”和“VALID”:
步长为2,当向右滑动两步之后,VALID方式发现余下的窗口不到2×2 所以直接将第三列舍弃,而SAME方式并不会把多出的一列丢弃,但是只有一列了不够2×2怎么办?填充!
SAME会增加第四列以保证可以达到2×2,但为了不影响原始信息,一般以0来填充。这就不难理解不同的padding方式输出的形状会有所不同了。
x=tf.placeholder(tf.float32,[None,n_input])
y=tf.placeholder(tf.float32,[None,n_output])
keepratio=tf.placeholder(tf.float32)
#function
_pred=conv_basic(x,weights,biases,keepratio)['out']
cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=_pred,labels=y))
optm=tf.train.AdamOptimizer(learning_rate=0.001).minimize(cost)
_corr=tf.equal(tf.argmax(_pred,1),tf.argmax(y,1))
accr=tf.reduce_mean(tf.cast(_corr,tf.float32))
init=tf.global_variables_initializer()
训练
training_epochs=15
batch_size=16
display_step=1
#session
sess=tf.Session()
sess.run(init)
#mini-batch leaning
for epoch in range(training_epochs):
avg_cost=0
#num_batch=int(minst.train.num_examples/batch_size)
num_batch=10
for i in range(num_batch):
batch_xs,batch_ys=minst.train.next_batch(batch_size)
#fit training using batch data
sess.run(optm,feed_dict={x:batch_xs,y:batch_ys,keepratio:0.7})
avg_cost+=sess.run(cost,feed_dict={x:batch_xs,y:batch_ys,keepratio:1.})
avg_cost=avg_cost/num_batch
#display
if epoch % display_step==0:
print("Epoch:%03d/%03d cost: %.9f"%(epoch,training_epochs,avg_cost))
feeds_train={x:batch_xs,y:batch_ys,keepratio:1.}
train_acc=sess.run(accr,feed_dict=feeds_train)
print("Train accrancy:%.3f"%(train_acc))
feeds={x:minst.test.images,y:minst.test.labels,keepratio:1.}
test_acc=sess.run(accr,feed_dict=feeds)
print("Test accrancy:%.3f"%(test_acc))
print("optimization Done")