In [ ]:
In [5]:
# -*- coding: utf-8 -*-
#############################################实例描述###############################################
##构建一组序列,生成其对应的模拟回声序列。使用Tensorflow创建一个简单循环神经网络拟合这个回声序列###
#####################################################################################################
##################################################################################################
#################第一步:定义参数并生成样本数据###################################################
###################################################################################################
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
num_epochs = 5 #迭代轮数
total_series_length = 50000 #序列样本数据长度
truncated_backprop_length = 15 #测试时截取数据长度
state_size = 4 #中间状态长度
num_classes = 2 #输出类别个数
echo_step = 3 #回声步长
batch_size = 5 #小批量大小
##jisuan计算第一轮可以分为多少批
num_batches = total_series_length//batch_size//truncated_backprop_length #//为向下取整
# 生成原序列和回声序列数据,回声序列滞后原序列echo_step个步长, 返回原序列和回声序列组成的元组
def generateData():
#
x = np.array(np.random.choice(2, total_series_length, p=[0.5, 0.5])) #在0 和1 中选择total_series_length个数
y = np.roll(x, echo_step) #向右循环移位【1111000】---【0001111】
y[0:echo_step] = 0
x = x.reshape((batch_size, -1)) #5x10000
y = y.reshape((batch_size, -1)) #5x10000
return (x, y)
#########################################################################################################################
################# 第二步:定义占位符处理输入数据 ######################################################################
#########################################################################################################################
# 定义3个占位符, batch_x为原始序列,batch_y为回声序列真实值,init_state为循环节点的初始值。
#batch_x是逐个输入网络的,所以需要将输进去的数据打散,按照时间序列变成15个数组,每个数组有batch_size个元素,进行统一批处理
batchX_placeholder = tf.placeholder(tf.float32, [batch_size, truncated_backprop_length]) ##原始序列 5乘15
batchY_placeholder = tf.placeholder(tf.int32, [batch_size, truncated_backprop_length]) ##回声序列 作为标签 5乘15
init_state = tf.placeholder(tf.float32, [batch_size, state_size]) ##循环节点的初始状态值 5乘4
##将batch_x沿axis = 1(列)的轴进行拆分
#返回一个list 每个元素都是一个数组 [(5,),(5,)....] 一共15个元素,即15个序列
inputs_series = tf.unstack(batchX_placeholder, axis=1)#15个5*1的数组
labels_series = tf.unstack(batchY_placeholder, axis=1)
#################################################################################################################################
##############第三步:定义网络结构###############################################################################################
##################################################################################################################################
current_state = init_state #存放当前的状态
predictions_series = [] #存放一个小批量中每个输入样本的预测序列值 每个元素为5x2 共有15个元素
losses =[] #存放一个小批量中每个输入样本训练的损失值 每个元素是一个标量,共有15个元素
#使用一个循环,按照序列逐个输入
for current_input, labels in zip(inputs_series,labels_series):
#确定形状为batch_size x 1
current_input = tf.reshape(current_input, [batch_size, 1])
#加入初始状态 ,5 x 1序列值和 5 x 4中间状态 按列连接,得到 5 x 5数组 构成输入数据
input_and_state_concatenated = tf.concat([current_input, current_state],1)
#隐藏层激活函数选择tanh 5x4
next_state = tf.contrib.layers.fully_connected(input_and_state_concatenated,state_size ,activation_fn=tf.tanh)
current_state = next_state
#输出层 激活函数选择None,即直接输出 5x2
logits =tf.contrib.layers.fully_connected(next_state,num_classes,activation_fn=None)
loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels,logits=logits)
losses.append(loss)
# print (losses)
#经过softmax计算预测值 5x2 注意这里并不是标签值 这里是one_hot编码
predictions = tf.nn.softmax(logits)
predictions_series.append(predictions)
total_loss = tf.reduce_mean(losses) #求均值
train_step = tf.train.AdagradOptimizer(0.3).minimize(total_loss)
#实例化一个优化函数Adagrad,基于0.3的学习率进行梯度优化训练
#接着使用minimize()的操作,里面传入损失节点值loss,再启动一个外层循环,优化器就会按照循环的次数一次次沿着loss最小值的方向优化参数。
#####################################################################################################################################
##################第五步:测试模型及可视化###########################################################################
#####################################################################################################################################
'''
绘制一个小批量中每一个原序列样本,回声序列样本,预测序列样本图像
args:
loss_list:list 存放每一个批次训练的代价值
predictions_series:list长度为5 存放一个批次中每个输入序列的预测序列值 注意这里每个元素(5x2)都是one_hot编码
batchx:当前批次的原序列 5x15
batchy:当前批次的回声序列 5x15
'''
def plot(loss_list, predictions_series, batchX, batchY):
plt.subplot(2, 3, 1) #创建子图 2行3列选择第一个 绘制代价值
plt.cla()
plt.plot(loss_list)
#迭代每一个序列 循环5次
for batch_series_idx in range(batch_size):
#获取第batch_series_idx个序列的预测值(one_hot编码) 15x2
one_hot_output_series = np.array(predictions_series)[:, batch_series_idx, :]
#转换为标签值 (15,)
single_output_series = np.array([(1 if out[0] < 0.5 else 0) for out in one_hot_output_series])
#绘制第batch_series_idx + 2个子图
plt.subplot(2, 3, batch_series_idx + 2)
plt.cla()
plt.axis([0, truncated_backprop_length, 0, 2]) #设置x轴 y轴坐标值范围
left_offset = range(truncated_backprop_length) #获取原序列x坐标值
left_offset2 = range(echo_step,truncated_backprop_length+echo_step)#获取回声序列x坐标值 滞后3个步长
label1 = "past values"
label2 = "True echo values"
label3 = "Predictions"
plt.plot(left_offset2, batchX[batch_series_idx, :]*0.2+1.5, "o--b", label=label1) #绘制原序列
plt.plot(left_offset, batchY[batch_series_idx, :]*0.2+0.8,"x--b", label=label2) #绘制真实回声序列
plt.plot(left_offset, single_output_series*0.2+0.1 , "o--y", label=label3) #绘制预测回声序列
# 为了让三个序列看起来更明显,将其缩放0.2,并且调节每个图像的高度。
plt.legend(loc='best')
plt.draw()
plt.pause(0.0001)
#####################################################################################################################################
##################第四步:训练数据并可视化输出###########################################################################
#####################################################################################################################################
#建立session训练数据
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())#先对模型进行初始化
plt.ion()
plt.figure()
plt.show()
loss_list = [] #list 存放每一小批量的代价值
#开始迭代每一轮(总共5轮)
for epoch_idx in range(num_epochs):
x,y = generateData() #生成原序列和回声序列数据
#print (x)
#print(y)
_current_state = np.zeros((batch_size, state_size)) #初始化循环节点状态值
print("New data, epoch", epoch_idx)
#迭代每一小批量
for batch_idx in range(num_batches):#50000/ 5 /15=分成多少段
start_idx = batch_idx * truncated_backprop_length #计算当前batch的起始索引
end_idx = start_idx + truncated_backprop_length #计算当前batch的结束索引
batchX = x[:,start_idx:end_idx] #当前批次的原序列值
batchY = y[:,start_idx:end_idx] #当前批次的回声序列值
#开始训练当前批次样本
_total_loss, _train_step, _current_state, _predictions_series = sess.run(
[total_loss, train_step, current_state, predictions_series],
feed_dict={
batchX_placeholder:batchX,
batchY_placeholder:batchY,
init_state:_current_state
})
loss_list.append(_total_loss)
if batch_idx%100 == 0:
print("Step",batch_idx, "Loss", _total_loss)
#可视化输出
plot(loss_list, _predictions_series, batchX, batchY)
plt.ioff()
plt.show()
In [ ]: