当前位置:   article > 正文

LSTM时间序列+NLP写诗-实践_lstm写诗

lstm写诗

简介:

       本次需要tensorflow第三方库,同时需要的是1.X版本

        其次通过我的上一偏的文章,对LSTM的基础理论做了一个简单的处理,在这通过实战加深对这个模型的印象,同时,这篇是对文本操作做处理,用到了自然语言处理(NLP)的一些理论。本次主要是实践为主,关于一些自然语言的内容也会简单的概述

语料库

        1:以此次为主,收集唐诗但本地,可以采用爬虫的形式。

        2:数据处理,可以将数据处理成一首诗保存一行,并且构建一个停用词库,去除一些不需要的成分

分词-词向量

       分词:

                将文本中的每句话进行分词操作,可以用的工具有jieba、pkuseg 等,一般jieba用到的比较多。之所以需要对文本进行分词,是因为计算机无法通过文字进行计算,需要转换成计算机能识别的形式(数字),因此需要每一个词映射成一个数字代表这个文字在本文中的ID是唯一的。再将ID转换成embadding词向量就可以对其进行计算

        词向量

                Ont-Hot编码:是比较常见的离散型数据,一个位置一个坑,比如下表1,基本基于欧式空间对距离和相似度的计算,在机器学习中的分类、回归和聚类用的较多,但是有缺点:按照一个词对去重之后个每一个词都做一个向量,当对于具有非常多类型的类别变量,变换后的向量维数过于巨大,且过于稀疏    。并且映射之间完全独立,并不能表示出不同类别之间的关系  。    

1000
0100
0010
0001

                                                                         表1

                

                       

准备数据

        读取本地的文件,去除停用词库里面的数据并且控制数量,需要给诗一个开始和结束的条件,对每首诗进行分词操作,再对词进行ID映射,统计词频进行排序

  1. def process_poems(file_name):
  2. poems=[]
  3. with open(file_name,'r',encoding='utf-8') as f :
  4. for line in f.readlines():
  5. try:
  6. title,content=line.strip().split(':')
  7. content=str(content).replace(' ','')
  8. if '_' in content or '(' in content or '(' in content or '《' in content or '[' in content or \
  9. start_token in content or end_token in content:
  10. continue
  11. if len(content) < 5 or len(content) > 79:
  12. continue
  13. content=start_token+content+end_token
  14. poems.append(content)
  15. except ValueError as e:
  16. pass
  17. poems=sorted(poems,key=lambda l:len(l))
  18. all_word=[]####保存但一个的每一个子
  19. for poem in poems:
  20. all_word+=[word for word in poem]
  21. counter=collections.Counter(all_word)
  22. ###对字段从大到小的排序
  23. count_pairs=sorted(counter.items(),key=lambda x:x[1],reverse=True)
  24. words, _ = zip(*count_pairs)
  25. #只那前面几个常用的
  26. words=words[:len(words)]+(' ',)
  27. ##映射ID
  28. word_int_map=dict(zip(words,range(len(words))))
  29. # print(word_int_map.get('山'))
  30. poems_vector=[list(map(lambda word:word_int_map.get(word,len(words)),poem)) for poem in poems]
  31. return poems_vector, word_int_map, words

batche处理

        每次对样本的处理,一次批量导入64首诗,由于每首诗的数量是不一样的,所以需要用padding做数据补充,最后用区分特征和标签用于后面模型的预测

  1. def generate_batch(batch_size, poems_vec, word_to_int):
  2. n_chunk=len(poems_vec)//batch_size
  3. ####一共540个样本,一个样本油64首诗歌的句子组成
  4. x_batches=[]
  5. y_batches=[]
  6. for i in range(n_chunk):
  7. '''获取数据的范围,起始数据喝最后的数据比如,[0:64],[1*64:128].....'''
  8. start_index=i*batch_size
  9. end_index=start_index+batch_size
  10. '''找到batch众最长的poem【64首诗歌中选取词最多的】'''
  11. batches=poems_vec[start_index:end_index]
  12. length=max(map(len,batches))
  13. '''通过找出来的长度padding填充'''
  14. # 填充一个这么大小的空batch,空的地方放空格对应的index标号,batch_siz行,length列
  15. x_data=np.full((batch_size,length),word_to_int[' '],np.int32)
  16. for row in range(batch_size):
  17. '''蒋每一行的诗句填充到x_data,多余的空出来的地方用’ ' 空格id来填充'''
  18. # x_data[row:len(batches[row])]=batches[row]
  19. x_data[row, :len(batches[row])] = batches[row]
  20. y_data=np.copy(x_data)
  21. '''y的话就是x向左边也就是前面移动一个'''
  22. y_data[:, :-1]=x_data[:, 1:]
  23. '''
  24. [[ 1 2 1 12]
  25. [ 1 2 1 12]]
  26. [[ 2 1 12 1]
  27. [ 2 1 12 1]]
  28. '''
  29. x_batches.append(x_data)
  30. y_batches.append(y_data)
  31. return x_batches, y_batches

LSTM模型搭建

        使用lstm模型,模型写的相对比较简单好理解,基本对每一句话都进行了标注,先创建一个lstm对象,对与lstm来说都是属于神经网络,所以基本都是(输入层,隐藏层,输出层),lstm在传输的过程中多出了一些控制变量比如(控制门、遗忘门),如图,一个输入对应的隐藏层是5个细胞单元,每个是独立的结果也是不同的比如 ,所以输入层到隐藏层是3*5

        隐藏层:通常是线性变换后接着是非线性激活函数。隐藏层的工作是将输入转换为输出层可以使用的东西,而输出层则将隐藏层的激活转换为我们希望输出的任何比例

         

        

  1. def rnn_model(model, input_data, output_data, vocab_size, rnn_size=128, num_layers=2, batch_size=64,
  2. learning_rate=0.01):
  3. end_points={}
  4. if model=='rnn':cell_fun=tf.contrib.rnn.BasicRNNCell
  5. elif model=='gru':cell_fun=tf.contrib.rnn.GRUCell
  6. elif model=='lstm':cell_fun=tf.contrib.rnn.BasicLSTMCell
  7. '''128个细胞单元'''
  8. cell=cell_fun(rnn_size,state_is_tuple=True)
  9. '''这里设置两层的隐藏层数,每一层128个细胞单元'''
  10. cell=tf.contrib.rnn.MultiRNNCell([cell]*num_layers, state_is_tuple=True)
  11. '''初始化状态'''
  12. if output_data is not None:
  13. initial_state=cell.zero_state(batch_size, tf.float32)
  14. else:
  15. initial_state = cell.zero_state(1, tf.float32)
  16. '''通过词ID转换为词向量方便计算机识别'''
  17. with tf.device('/cpu:0'):
  18. embedding = tf.get_variable('embedding', initializer=tf.random_uniform( [vocab_size + 1, rnn_size], -1.0, 1.0))
  19. inputs = tf.nn.embedding_lookup(embedding, input_data)
  20. '''通过指定的RNN Cell来展开计算神经网络并且输出tf.nn.dynamic_rnn(单层),输出每一层的最后一个'''
  21. outputs,last_state=tf.nn.dynamic_rnn(cell, inputs, initial_state=initial_state)
  22. output = tf.reshape(outputs, [-1, rnn_size])
  23. '''使用激活函数对模型输出的结果做一个概率预测'''
  24. weights = tf.Variable(tf.truncated_normal([rnn_size, vocab_size + 1]))
  25. bias = tf.Variable(tf.zeros(shape=[vocab_size + 1]))
  26. logits = tf.nn.bias_add(tf.matmul(output, weights), bias=bias)
  27. if output_data is not None:
  28. '''汉字无法直接做计算,因此真实的输出汉字使用one-hot'''
  29. labels = tf.one_hot(tf.reshape(output_data, [-1]), depth=vocab_size + 1)
  30. '''损失函数计算预测与真实之间的差异'''
  31. loss = tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=logits)
  32. total_loss = tf.reduce_mean(loss)
  33. '''模型优化'''
  34. train_op = tf.train.AdamOptimizer(learning_rate).minimize(total_loss)
  35. '''模型保存的参数'''
  36. end_points['initial_state'] = initial_state
  37. end_points['output'] = output
  38. end_points['train_op'] = train_op
  39. end_points['total_loss'] = total_loss
  40. end_points['loss'] = loss
  41. end_points['last_state'] = last_state
  42. else:
  43. prediction = tf.nn.softmax(logits)
  44. end_points['initial_state'] = initial_state
  45. end_points['last_state'] = last_state
  46. end_points['prediction'] = prediction
  47. return end_points

总流程

        主要是main()函数内,is_train=True是训练模型,is_train=False就是测试模型

  1. import os
  2. import numpy as np
  3. # from model import rnn_model
  4. # from poems_ import process_poems,generate_batch
  5. import tensorflow as tf
  6. from chai_epoch import process_poems,generate_batch,rnn_model
  7. start_token = 'G'
  8. end_token = 'E'
  9. tf.compat.v1.disable_eager_execution()
  10. def run_training():
  11. ###id,词+ID,词
  12. poems_vector,word_to_int,vocabularies=process_poems('poems.txt')
  13. batches_inputs,batches_outputs=generate_batch(64,poems_vector,word_to_int)
  14. input_data=tf.compat.v1.placeholder(tf.int32,64,None)
  15. output_targets = tf.compat.v1.placeholder(tf.int32, 64, None)
  16. end_points=rnn_model(model='lstm',input_data=input_data,output_data=output_targets,vocab_size=len(vocabularies),
  17. rnn_size=128,num_layers=2,batch_size=64,learning_rate=0.01)
  18. '''模型建立一个saver对象'''
  19. saver = tf.train.Saver(tf.global_variables())
  20. init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
  21. '''创建会话'''
  22. with tf.Session() as sess:
  23. sess.run(init_op)
  24. start_epoch = 0
  25. checkpoint = tf.train.latest_checkpoint('./checkpoints/poems/')
  26. if checkpoint:
  27. saver.restore(sess, checkpoint)
  28. print("[INFO] restore from the checkpoint {0}".format(checkpoint))
  29. start_epoch += int(checkpoint.split('-')[-1])
  30. print('[INFO] start training...')
  31. try:
  32. for epoch in range(start_epoch, 50):
  33. n = 0
  34. n_chunk = len(poems_vector) //64
  35. for batch in range(n_chunk):
  36. loss, _, _ = sess.run([
  37. end_points['total_loss'],
  38. end_points['last_state'],
  39. end_points['train_op']
  40. ], feed_dict={input_data: batches_inputs[n], output_targets: batches_outputs[n]})
  41. n += 1
  42. print('eoch: %d , batch: %d , training loss: %.6f' % (epoch, batch, loss))
  43. if epoch % 6 == 0:
  44. saver.save(sess, './model/', global_step=epoch)
  45. # saver.save(sess, os.path.join(FLAGS.checkpoints_dir, FLAGS.model_prefix), global_step=epoch)
  46. except KeyboardInterrupt:
  47. print('路径...')
  48. saver.save(sess, os.path.join('./checkpoints/poems/', 'poems'), global_step=epoch)
  49. print('保存的epoch {}.'.format(epoch))
  50. def to_word(predict, vocabs):
  51. t = np.cumsum(predict)
  52. s = np.sum(predict)
  53. sample = int(np.searchsorted(t, np.random.rand(1) * s))
  54. if sample > len(vocabs):
  55. sample = len(vocabs) - 1
  56. return vocabs[sample]
  57. def pretty_print_poem(poem):
  58. poem_sentences = poem.split('。')
  59. for s in poem_sentences:
  60. if s != '' and len(s) > 10:
  61. print(s + '。')
  62. def gen_poem(begin_word):
  63. batch_size = 1
  64. '''对样本数据做预处理'''
  65. poems_vector, word_int_map, vocabularies = process_poems('poems.txt')
  66. input_data = tf.placeholder(tf.int32, [batch_size, None])
  67. '''模型'''
  68. end_points = rnn_model(model='lstm', input_data=input_data, output_data=None, vocab_size=len(
  69. vocabularies), rnn_size=128, num_layers=2, batch_size=64, learning_rate=0.01)
  70. saver = tf.train.Saver(tf.global_variables())
  71. init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
  72. with tf.Session() as sess:
  73. sess.run(init_op)
  74. '''提取训练好的数据'''
  75. saver.restore(sess, './model/-24')
  76. '''获取每首诗的起始点'''
  77. x = np.array([list(map(word_int_map.get, start_token))])
  78. '''预测'''
  79. [predict, last_state] = sess.run([end_points['prediction'], end_points['last_state']],
  80. feed_dict={input_data: x})
  81. if begin_word:
  82. word = begin_word
  83. else:
  84. word = to_word(predict, vocabularies)
  85. poem = ''
  86. '''直到获取一句诗的结尾处'''
  87. while word != end_token:
  88. print ('runing')
  89. poem += word
  90. x = np.zeros((1, 1))
  91. x[0, 0] = word_int_map[word]
  92. [predict, last_state] = sess.run([end_points['prediction'], end_points['last_state']],
  93. feed_dict={input_data: x, end_points['initial_state']: last_state})
  94. word = to_word(predict, vocabularies)
  95. return poem
  96. def main(is_train):
  97. try:
  98. if is_train:
  99. print('训练唐诗')
  100. run_training()
  101. except:
  102. print('写入...')
  103. begin_word = input('输入起始字:')
  104. poem2 = gen_poem(begin_word)
  105. pretty_print_poem(poem2)
  106. if __name__ == '__main__':
  107. is_train=True
  108. main(is_train)

结论

        因为本次主要是代码的展示,中间一些NLP相关的知识点没有仔细去写,打算下次逐步对NLP相关知识点跟新补充,这次比较懒,后续会在修改补充一些,下面是我在学习的过程中看到写的word2vec比较详细的知识点可以参考

word2vec:  https://blog.csdn.net/qq_43477218/article/details/113097380

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/734629
推荐阅读
相关标签
  

闽ICP备14008679号