1 LeNet
代码摘自https://blog.csdn.net/Enchanted_ZhouH/article/details/76855108?utm_source=blogxgwz0
网络结构介绍见https://www.cnblogs.com/duanhx/articles/9655228.html和https://blog.csdn.net/sinat_24143931/article/details/78958931
各个博客描述不同的地方是第二个卷积层。上一个博客所写:
第一次池化之后得到6个 1414 的特征图,之后第二次卷积,卷积核大小是 55.,第二次卷积的输出是16个10x10的特征图,怎么从6 个特征图得到 16个特征图了? 这里是通过对S2 的特征图特殊组合计算得到的16个特征图。具体如下:
这种不对称的组合连接有利于提取多种组合特征,有(5x5x3+1)x6 + (5x5x4 + 1) x 3 + (5x5x4 +1)x6 + (5x5x6+1)x1 = 1516个训练参数,共有1516x10x10=151600个连接
但是根据《TensorFlowz实战Google深度学习框架》,第二个卷积层就是一个常规的556的三维卷积核,共(556+1)16=2416个参数,101016(25+1)=41600个连接。下面的代码是根据后者。
#coding:utf-8 -*-
from skimage import io,transform
import os
import glob
import numpy as np
import tensorflow as tf
#将所有的图片重新设置尺寸为32*32
w = 32
h = 32
c = 1
#mnist数据集中训练数据和测试数据保存地址
train_path = "/home/zhangjin/zhangjinming/python/20181025/mnist/train/"
test_path = "/home/zhangjin/zhangjinming/python/20181025/mnist/test/"
#读取图片及其标签函数
def read_image(path):
label_dir = [path+x for x in os.listdir(path) if os.path.isdir(path+x)]
images = []
labels = []
for index,folder in enumerate(label_dir):
for img in glob.glob(folder+'/*.png'):
print("reading the image:%s"%img)
image = io.imread(img)
image = transform.resize(image,(w,h,c))
images.append(image)
labels.append(index)
return np.asarray(images,dtype=np.float32),np.asarray(labels,dtype=np.int32)
#读取训练数据及测试数据
train_data,train_label = read_image(train_path)
test_data,test_label = read_image(test_path)
#打乱训练数据及测试数据
train_image_num = len(train_data)
train_image_index = np.arange(train_image_num)
np.random.shuffle(train_image_index)
train_data = train_data[train_image_index]
train_label = train_label[train_image_index]
test_image_num = len(test_data)
test_image_index = np.arange(test_image_num)
np.random.shuffle(test_image_index)
test_data = test_data[test_image_index]
test_label = test_label[test_image_index]
#搭建CNN
x = tf.placeholder(tf.float32,[None,w,h,c],name='x')
y_ = tf.placeholder(tf.int32,[None],name='y_')
def inference(input_tensor,train,regularizer):
#第一层:卷积层,过滤器的尺寸为5×5,深度为6,不使用全0补充,步长为1。
#尺寸变化:32×32×1->28×28×6
with tf.variable_scope('layer1-conv1'):
conv1_weights = tf.get_variable('weight',[5,5,c,6],initializer=tf.truncated_normal_initializer(stddev=0.1))
conv1_biases = tf.get_variable('bias',[6],initializer=tf.constant_initializer(0.0))
conv1 = tf.nn.conv2d(input_tensor,conv1_weights,strides=[1,1,1,1],padding='VALID')
relu1 = tf.nn.relu(tf.nn.bias_add(conv1,conv1_biases))
#第二层:池化层,过滤器的尺寸为2×2,使用全0补充,步长为2。
#尺寸变化:28×28×6->14×14×6
with tf.name_scope('layer2-pool1'):
pool1 = tf.nn.max_pool(relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
#第三层:卷积层,过滤器的尺寸为5×5,深度为16,不使用全0补充,步长为1。
#尺寸变化:14×14×6->10×10×16
with tf.variable_scope('layer3-conv2'):
conv2_weights = tf.get_variable('weight',[5,5,6,16],initializer=tf.truncated_normal_initializer(stddev=0.1))
conv2_biases = tf.get_variable('bias',[16],initializer=tf.constant_initializer(0.0))
conv2 = tf.nn.conv2d(pool1,conv2_weights,strides=[1,1,1,1],padding='VALID')
relu2 = tf.nn.relu(tf.nn.bias_add(conv2,conv2_biases))
#第四层:池化层,过滤器的尺寸为2×2,使用全0补充,步长为2。
#尺寸变化:10×10×6->5×5×16
with tf.variable_scope('layer4-pool2'):
pool2 = tf.nn.max_pool(relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
#将第四层池化层的输出转化为第五层全连接层的输入格式。第四层的输出为5×5×16的矩阵,然而第五层全连接层需要的输入格式
#为向量,所以我们需要把代表每张图片的尺寸为5×5×16的矩阵拉直成一个长度为5×5×16的向量。
#举例说,每次训练64张图片,那么第四层池化层的输出的size为(64,5,5,16),拉直为向量,nodes=5×5×16=400,尺寸size变为(64,400)
pool_shape = pool2.get_shape().as_list()
nodes = pool_shape[1]*pool_shape[2]*pool_shape[3]
reshaped = tf.reshape(pool2,[-1,nodes])
#第五层:全连接层,nodes=5×5×16=400,400->120的全连接
#尺寸变化:比如一组训练样本为64,那么尺寸变化为64×400->64×120
#训练时,引入dropout,dropout在训练时会随机将部分节点的输出改为0,dropout可以避免过拟合问题。
#这和模型越简单越不容易过拟合思想一致,和正则化限制权重的大小,使得模型不能任意拟合训练数据中的随机噪声,以此达到避免过拟合思想一致。
#本文最后训练时没有采用dropout,dropout项传入参数设置成了False,因为训练和测试写在了一起没有分离,不过大家可以尝试。
with tf.variable_scope('layer5-fc1'):
fc1_weights = tf.get_variable('weight',[nodes,120],initializer=tf.truncated_normal_initializer(stddev=0.1))
if regularizer != None:
tf.add_to_collection('losses',regularizer(fc1_weights))
fc1_biases = tf.get_variable('bias',[120],initializer=tf.constant_initializer(0.1))
fc1 = tf.nn.relu(tf.matmul(reshaped,fc1_weights) + fc1_biases)
if train:
fc1 = tf.nn.dropout(fc1,0.5)
#第六层:全连接层,120->84的全连接
#尺寸变化:比如一组训练样本为64,那么尺寸变化为64×120->64×84
with tf.variable_scope('layer6-fc2'):
fc2_weights = tf.get_variable('weight',[120,84],initializer=tf.truncated_normal_initializer(stddev=0.1))
if regularizer != None:
tf.add_to_collection('losses',regularizer(fc2_weights))
fc2_biases = tf.get_variable('bias',[84],initializer=tf.truncated_normal_initializer(stddev=0.1))
fc2 = tf.nn.relu(tf.matmul(fc1,fc2_weights) + fc2_biases)
if train:
fc2 = tf.nn.dropout(fc2,0.5)
#第七层:全连接层(近似表示),84->10的全连接
#尺寸变化:比如一组训练样本为64,那么尺寸变化为64×84->64×10。最后,64×10的矩阵经过softmax之后就得出了64张图片分类于每种数字的概率,
#即得到最后的分类结果。
with tf.variable_scope('layer7-fc3'):
fc3_weights = tf.get_variable('weight',[84,10],initializer=tf.truncated_normal_initializer(stddev=0.1))
if regularizer != None:
tf.add_to_collection('losses',regularizer(fc3_weights))
fc3_biases = tf.get_variable('bias',[10],initializer=tf.truncated_normal_initializer(stddev=0.1))
logit = tf.matmul(fc2,fc3_weights) + fc3_biases
return logit
#正则化,交叉熵,平均交叉熵,损失函数,最小化损失函数,预测和实际equal比较,tf.equal函数会得到True或False,
#accuracy首先将tf.equal比较得到的布尔值转为float型,即True转为1.,False转为0,最后求平均值,即一组样本的正确率。
#比如:一组5个样本,tf.equal比较为[True False True False False],转化为float型为[1. 0 1. 0 0],准确率为2./5=40%。
regularizer = tf.contrib.layers.l2_regularizer(0.001)
y = inference(x,False,regularizer)
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y,labels=y_)
cross_entropy_mean = tf.reduce_mean(cross_entropy)
loss = cross_entropy_mean + tf.add_n(tf.get_collection('losses'))
train_op = tf.train.AdamOptimizer(0.001).minimize(loss)
correct_prediction = tf.equal(tf.cast(tf.argmax(y,1),tf.int32),y_)
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
#每次获取batch_size个样本进行训练或测试
def get_batch(data,label,batch_size):
for start_index in range(0,len(data)-batch_size+1,batch_size):
slice_index = slice(start_index,start_index+batch_size)
yield data[slice_index],label[slice_index]
#创建Session会话
with tf.Session() as sess:
#初始化所有变量(权值,偏置等)
sess.run(tf.global_variables_initializer())
#将所有样本训练10次,每次训练中以64个为一组训练完所有样本。
#train_num可以设置大一些。
train_num = 10
batch_size = 64
for i in range(train_num):
train_loss,train_acc,batch_num = 0, 0, 0
for train_data_batch,train_label_batch in get_batch(train_data,train_label,batch_size):
_,err,acc = sess.run([train_op,loss,accuracy], feed_dict={x:train_data_batch,y_:train_label_batch})
train_loss+=err
train_acc+=acc
batch_num+=1
print "train loss:%f",train_loss/batch_num
print "train acc:%f",train_acc/batch_num
test_loss,test_acc,batch_num = 0, 0, 0
for test_data_batch,test_label_batch in get_batch(test_data,test_label,batch_size):
err,acc = sess.run([loss,accuracy], feed_dict={x:test_data_batch,y_:test_label_batch})
test_loss+=err
test_acc+=acc
batch_num+=1
print "test loss:%f",test_loss/batch_num
print "test acc:%f",test_acc/batch_num
2 Alexnet
代码摘自https://blog.csdn.net/u013063099/article/details/74295796和https://github.com/stephen-v/tensorflow_alexnet_classify
#coding=utf-8
from __future__ import print_function
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data", one_hot=True)
import tensorflow as tf
# 定义网络超参数
learning_rate = 0.001
training_iters = 200000
batch_size = 64
display_step = 20
# 定义网络参数
n_input = 784 # 输入的维度
n_classes = 10 # 标签的维度
dropout = 0.75 # Dropout 的概率
# 占位符输入
x = tf.placeholder(tf.float32, [None, n_input])
y = tf.placeholder(tf.float32, [None, n_classes])
keep_prob = tf.placeholder(tf.float32)
# 卷积操作
def conv2d(name, l_input, w, b):
return tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(l_input, w, strides=[1, 1, 1, 1], padding='SAME'),b), name=name)
# 最大下采样操作
def max_pool(name, l_input, k):
return tf.nn.max_pool(l_input, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding='SAME', name=name)
# 归一化操作
def norm(name, l_input, lsize=4):
return tf.nn.lrn(l_input, lsize, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name=name)
# 存储所有的网络参数
weights = {
'wc1': tf.Variable(tf.random_normal([11, 11, 1, 64])),
'wc2': tf.Variable(tf.random_normal([5, 5, 64, 192])),
'wc3': tf.Variable(tf.random_normal([3, 3, 192, 384])),
'wc4': tf.Variable(tf.random_normal([3, 3, 384, 384])),
'wc5': tf.Variable(tf.random_normal([3, 3, 384, 256])),
'wd1': tf.Variable(tf.random_normal([4*4*256, 4096])),
'wd2': tf.Variable(tf.random_normal([4096, 4096])),
'out': tf.Variable(tf.random_normal([4096, 10]))
}
biases = {
'bc1': tf.Variable(tf.random_normal([64])),
'bc2': tf.Variable(tf.random_normal([192])),
'bc3': tf.Variable(tf.random_normal([384])),
'bc4': tf.Variable(tf.random_normal([384])),
'bc5': tf.Variable(tf.random_normal([256])),
'bd1': tf.Variable(tf.random_normal([4096])),
'bd2': tf.Variable(tf.random_normal([4096])),
'out': tf.Variable(tf.random_normal([n_classes]))
}
# 定义整个网络
def alex_net(_X, _weights, _biases, _dropout):
# 向量转为矩阵
_X = tf.reshape(_X, shape=[-1, 28, 28, 1])
# 第一层卷积
# 卷积
conv1 = conv2d('conv1', _X, _weights['wc1'], _biases['bc1'])
# 下采样
pool1 = max_pool('pool1', conv1, k=2)
# 归一化
norm1 = norm('norm1', pool1, lsize=4)
# 第二层卷积
# 卷积
conv2 = conv2d('conv2', norm1, _weights['wc2'], _biases['bc2'])
# 下采样
pool2 = max_pool('pool2', conv2, k=2)
# 归一化
norm2 = norm('norm2', pool2, lsize=4)
# 第三层卷积
# 卷积
conv3 = conv2d('conv3', norm2, _weights['wc3'], _biases['bc3'])
# 归一化
norm3 = norm('norm3', conv3, lsize=4)
# 第四层卷积
# 卷积
conv4 = conv2d('conv4', norm3, _weights['wc4'], _biases['bc4'])
# 归一化
norm4 = norm('norm4', conv4, lsize=4)
# 第五层卷积
# 卷积
conv5 = conv2d('conv5', norm4, _weights['wc5'], _biases['bc5'])
# 下采样
pool5 = max_pool('pool5', conv5, k=2)
# 归一化
norm5 = norm('norm5', pool5, lsize=4)
# 全连接层1,先把特征图转为向量
dense1 = tf.reshape(norm5, [-1, _weights['wd1'].get_shape().as_list()[0]])
dense1 = tf.nn.relu(tf.matmul(dense1, _weights['wd1']) + _biases['bd1'], name='fc1')
dense1 = tf.nn.dropout(dense1, _dropout)
# 全连接层2
dense2 = tf.reshape(dense1, [-1, _weights['wd2'].get_shape().as_list()[0]])
dense2 = tf.nn.relu(tf.matmul(dense1, _weights['wd2']) + _biases['bd2'], name='fc2') # Relu activation
dense2 = tf.nn.dropout(dense2, _dropout)
# 网络输出层
out = tf.matmul(dense2, _weights['out']) + _biases['out']
return out
# 构建模型
pred = alex_net(x, weights, biases, keep_prob)
# 定义损失函数和学习步骤
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = pred, labels = y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
# 测试网络
correct_pred = tf.equal(tf.argmax(pred,1), tf.argmax(y,1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
# 初始化所有的共享变量
init = tf.initialize_all_variables()
# 开启一个训练
with tf.Session() as sess:
sess.run(init)
step = 1
# Keep training until reach max iterations
while step * batch_size < training_iters:
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
# 获取批数据
sess.run(optimizer, feed_dict={x: batch_xs, y: batch_ys, keep_prob: dropout})
if step % display_step == 0:
# 计算精度
acc = sess.run(accuracy, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 1.})
# 计算损失值
loss = sess.run(cost, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 1.})
print ("Iter " + str(step*batch_size) + ", Minibatch Loss = " + "{:.6f}".format(loss) + ", Training Accuracy = " + "{:.5f}".format(acc))
step += 1
print ("Optimization Finished!")
# 计算测试精度
print ("Testing Accuracy:", sess.run(accuracy, feed_dict={x: mnist.test.images[:256], y: mnist.test.labels[:256], keep_prob: 1.}))
3 LSTM
import numpy as np
import tensorflow as tf
import matplotlib as mpl
from matplotlib import pyplot as plt
from tensorflow.contrib.learn.python.learn.estimators.estimator import SKCompat
# TensorFlow的高层封装TFLearn
learn = tf.contrib.learn
# 神经网络参数
HIDDEN_SIZE = 30 # LSTM隐藏节点个数
NUM_LAYERS = 2 # LSTM层数
TIMESTEPS = 10 # 循环神经网络截断长度
BATCH_SIZE = 32 # batch大小
# 数据参数
TRAINING_STEPS = 3000 # 训练轮数
TRAINING_EXAMPLES = 10000 # 训练数据个数
TESTING_EXAMPLES = 1000 # 测试数据个数
SAMPLE_GAP = 0.01 # 采样间隔
def generate_data(seq):
# 序列的第i项和后面的TIMESTEPS-1项合在一起作为输入,第i+TIMESTEPS项作为输出
X = []
y = []
for i in range(len(seq) - TIMESTEPS - 1):
X.append([seq[i:i + TIMESTEPS]])
y.append([seq[i + TIMESTEPS]])
return np.array(X, dtype=np.float32), np.array(y, dtype=np.float32)
# LSTM结构单元
def LstmCell():
lstm_cell = tf.contrib.rnn.BasicLSTMCell(HIDDEN_SIZE)
return lstm_cell
def lstm_model(X, y):
# 使用多层LSTM,不能用lstm_cell*NUM_LAYERS的方法,会导致LSTM的tensor名字都一样
cell = tf.contrib.rnn.MultiRNNCell([LstmCell() for _ in range(NUM_LAYERS)])
# 将多层LSTM结构连接成RNN网络并计算前向传播结果
output, _ = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)
output = tf.reshape(output, [-1, HIDDEN_SIZE])
# 通过无激活函数的全联接层计算线性回归,并将数据压缩成一维数组的结构
predictions = tf.contrib.layers.fully_connected(output, 1, None)
# 将predictions和labels调整为统一的shape
y = tf.reshape(y, [-1])
predictions = tf.reshape(predictions, [-1])
# 计算损失值
loss = tf.losses.mean_squared_error(predictions, y)
# 创建模型优化器并得到优化步骤
train_op = tf.contrib.layers.optimize_loss(
loss,
tf.train.get_global_step(),
optimizer='Adagrad',
learning_rate=0.1)
return predictions, loss, train_op
# 用sin生成训练和测试数据集
test_start = TRAINING_EXAMPLES * SAMPLE_GAP
test_end = (TRAINING_EXAMPLES + TESTING_EXAMPLES) * SAMPLE_GAP
train_X, train_y = generate_data(
np.sin(np.linspace(0, test_start, TRAINING_EXAMPLES, dtype=np.float32)))
test_X, test_y = generate_data(
np.sin(
np.linspace(test_start, test_end, TESTING_EXAMPLES, dtype=np.float32)))
# 建立深层循环网络模型
regressor = SKCompat(learn.Estimator(model_fn=lstm_model, model_dir='model/'))
# 调用fit函数训练模型
regressor.fit(train_X, train_y, batch_size=BATCH_SIZE, steps=TRAINING_STEPS)
# 使用训练好的模型对测试集进行预测
predicted = [[pred] for pred in regressor.predict(test_X)]
# 计算rmse作为评价指标
rmse = np.sqrt(((predicted - test_y)**2).mean(axis=0))
print('Mean Square Error is: %f' % (rmse[0]))
# 对预测曲线绘图,并存储到sin.jpg
fig = plt.figure()
plot_predicted, = plt.plot(predicted, label='predicted')
plot_test, = plt.plot(test_y, label='real_sin')
plt.legend([plot_predicted, plot_test], ['predicted', 'real_sin'])
plt.show()