In [ ]:
# -*- coding: utf-8 -*-
########################################################################################################
####################第一步:准备样本####################################################################
##########################################################################################################
#######1、定义基本工具函数################################################################################
###引入头文件,然后定义相关函数########################################################################
import numpy as np
import tensorflow as tf
from tensorflow.contrib import rnn
import random
import time
from collections import Counter
start_time = time.time()
def elapsed(sec):
if sec<60:
return str(sec) + " sec"
elif sec<(60*60):
return str(sec/60) + " min"
else:
return str(sec/(60*60)) + " hr"
# 目标日志路径
tf.reset_default_graph()
training_file = 'wordstest.txt'
#处理多个中文文件
def readalltxt(txt_files):
labels = []
for txt_file in txt_files:
target = get_ch_lable(txt_file) #从文件里获取文本
labels.append(target)
return labels
#处理汉字
def get_ch_lable(txt_file):
labels= ""
with open(txt_file, 'rb') as f:
for label in f:
#labels =label.decode('utf-8')
labels =labels+label.decode('gb2312')
return labels
#优先转文件里的字符到向量
def get_ch_lable_v(txt_file,word_num_map,txt_label=None):#将文本数组转换成向量
words_size = len(word_num_map)
to_num = lambda word: word_num_map.get(word, words_size)
if txt_file!= None:
txt_label = get_ch_lable(txt_file)
labels_vector = list(map(to_num, txt_label))
return labels_vector
####2 、样本预处理#########################################################################################
##########读取整体样本
training_data =get_ch_lable(training_file)
print("Loaded training data...")
print(len(training_data))
counter = Counter(training_data)
words = sorted(counter)
words_size= len(words)
word_num_map = dict(zip(words, range(words_size)))
print(word_num_map)
print('字表大小:', words_size)
#将文本数组转换为向量
wordlabel = get_ch_lable_v(training_file,word_num_map)
print (wordlabel)
############################################################################################################
########第二步:构建模型####################################################################################
###############################################################################################################
###############1、参数设置################################################################################################
#学习率为0.001,迭代10000次,每1000次输出一次中间状态。每次输入4个字,来预测第5个字。
learning_rate = 0.001
training_iters = 10000
display_step = 1000
n_input = 4
#网络模型使用了3层的lstm,第一层为256个cell,第二层和第三层都是512个cell.
n_hidden1 = 256
n_hidden2 = 512
n_hidden3 = 512
# 定义占位符
x = tf.placeholder("float", [None, n_input,1]) #输入4个连续的汉字
wordy = tf.placeholder("float", [None, words_size]) #代表一个字,
######2、定义网络结构####################################################################################
#将x形状变换并按照时间序列裁分
x1 = tf.reshape(x, [-1, n_input])
x2 = tf.split(x1,n_input,1)
# 3层LSTM,每层有n_hidden个units
rnn_cell = rnn.MultiRNNCell([rnn.LSTMCell(n_hidden1),rnn.LSTMCell(n_hidden2),rnn.LSTMCell(n_hidden3)])
# 通过RNN得到输出,
outputs, states = rnn.static_rnn(rnn_cell, x2, dtype=tf.float32)
print (outputs)
# 通过全连接输出指定维度
pred = tf.contrib.layers.fully_connected(outputs[-1],words_size,activation_fn = None)
# 3、定义优化器
####tf.nn.softmax_cross_entropy_with_logits:计算交叉熵;tf.reduce_mean:计算均值
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=wordy))
####创建了一个优化函数AdamOptimizer,并基于一定的学习速率进行梯度训练。minimize():按照loss的最小值方向更新参数
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)
# 模型评估
correct_pred = tf.equal(tf.argmax(pred,1), tf.argmax(wordy,1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
##########4、训练模型########################################################################################################
##在训练过程中同样添加保存检查点功能。在session中每次随机取一个偏移量,然后取后面4个文字向量当作输入,
#第5个文字向量当成标签来计算loss
############################################################################################################
savedir = "A:/Users/yhh/Desktop/RNN实例/"
saver = tf.train.Saver(max_to_keep=1) # 生成saver
# 启动session
with tf.Session() as session:
session.run(tf.global_variables_initializer())
step = 0
offset = random.randint(0,n_input+1)
end_offset = n_input + 1
acc_total = 0
loss_total = 0
kpt = tf.train.latest_checkpoint(savedir)
print("kpt:",kpt)
startepo= 0
if kpt!=None:
saver.restore(session, kpt)
ind = kpt.find("-")
startepo = int(kpt[ind+1:])
print(startepo)
step = startepo
while step < training_iters:
# 随机取一个位置偏移
if offset > (len(training_data)-end_offset):
offset = random.randint(0, n_input+1)
inwords = [ [wordlabel[ i]] for i in range(offset, offset+n_input) ]#按照指定的位置偏移获取后面的4个文字向量当作输入
inwords = np.reshape(np.array(inwords), [-1, n_input, 1])
out_onehot= np.zeros([words_size], dtype=float)
out_onehot[wordlabel[offset+n_input]] = 1.0
out_onehot = np.reshape(out_onehot,[1,-1])#所有的字都变成onehot
_, acc, lossval, onehot_pred = session.run([optimizer, accuracy, loss, pred],feed_dict={x: inwords, wordy: out_onehot})
loss_total += lossval
acc_total += acc
if (step+1) % display_step == 0:
print("Iter= " + str(step+1) + ", Average Loss= " + \
"{:.6f}".format(loss_total/display_step) + ", Average Accuracy= " + \
"{:.2f}%".format(100*acc_total/display_step))
acc_total = 0
loss_total = 0
in2 = [words [wordlabel[i]] for i in range(offset, offset + n_input)]
out2 = words [wordlabel[offset + n_input]]
out_pred=words[int(tf.argmax(onehot_pred, 1).eval())]
print("%s - [%s] vs [%s]" % (in2,out2,out_pred))
saver.save(session, savedir+"./rnnwordtest.cpkt", global_step=step)
step += 1
offset += (n_input+1)#中间隔了一个,作为预测
print("Finished!")
saver.save(session, savedir+"./rnnwordtest.cpkt", global_step=step)
print("Elapsed time: ", elapsed(time.time() - start_time))
##########5、运行模型生成句子##################################################################################################
#####启用一个循环,等待输入文字,当收到输入文本后,通过eval计算onehot_pred节点,并进行文字的转义,得到预测文字。
####接下来将预测文字在循环输入模型中,预测下一个文字。代码中设置循环32次,输出32个字。
###########################################################################################################
while True:
prompt = "请输入%s个字: " % n_input
sentence = input(prompt)
inputword = sentence.strip()
if len(inputword) != n_input:
print("您输入的字符长度为:",len(inputword),"请输入4个字")
continue
try:
inputword = get_ch_lable_v(None,word_num_map,inputword)
for i in range(32):
keys = np.reshape(np.array(inputword), [-1, n_input, 1])
onehot_pred = session.run(pred, feed_dict={x: keys})
onehot_pred_index = int(tf.argmax(onehot_pred, 1).eval())
sentence = "%s%s" % (sentence,words[onehot_pred_index])
inputword = inputword[1:]
inputword.append(onehot_pred_index)
print(sentence)
except:
print("该字我还没学会")
In [ ]:
In [ ]: