zf:tf7: RNN—古诗词

代码:

https://download.csdn.net/download/richgene/10413943 

训练数据:

https://download.csdn.net/download/richgene/10466872


RNN不像传统的神经网络-它们的输出输出是固定的,而RNN允许我们输入输出向量序列。RNN是为了对序列数据进行建模而产生的。

样本序列性:样本间存在顺序关系,每个样本和它之前的样本存在关联。比如说,在文本中,一个词和它前面的词是有关联的;在气象数据中,一天的气温和前几天的气温是有关联的。

例如本帖要使用RNN生成古诗,你给它输入一堆古诗词,它会学着生成和前面相关联的字词。如果你给它输入一堆姓名,它会学着生成姓名;给它输入一堆古典乐/歌词,它会学着生成古典乐/歌词,甚至可以给它输入源代码。

关于RNN:

本帖代码移植自char-rnn,它是基于Torch的洋文模型,稍加修改即可应用于中文。char-rnn使用文本文件做为输入、训练RNN模型,然后使用它生成和训练数据类似的文本。

使用的数据集:全唐诗(43030首):https://download.csdn.net/download/richgene/10466872

训练:

[python]  view plain  copy
  1. import collections  
  2. import numpy as np  
  3. import tensorflow as tf  
  4.    
  5. #-------------------------------数据预处理---------------------------#  
  6.    
  7. poetry_file ='poetry.txt'  
  8.    
  9. # 诗集  
  10. poetrys = []  
  11. with open(poetry_file, "r", encoding='utf-8',) as f:  
  12.     for line in f:  
  13.         try:  
  14.             title, content = line.strip().split(':')  
  15.             content = content.replace(' ','')  
  16.             if '_' in content or '(' in content or '(' in content or '《' in content or '[' in content:  
  17.                 continue  
  18.             if len(content) < 5 or len(content) > 79:  
  19.                 continue  
  20.             content = '[' + content + ']'  
  21.             poetrys.append(content)  
  22.         except Exception as e:   
  23.             pass  
  24.    
  25. # 按诗的字数排序  
  26. poetrys = sorted(poetrys,key=lambda line: len(line))  
  27. print('唐诗总数: ', len(poetrys))  
  28.    
  29. # 统计每个字出现次数  
  30. all_words = []  
  31. for poetry in poetrys:  
  32.     all_words += [word for word in poetry]  
  33. counter = collections.Counter(all_words)  
  34. count_pairs = sorted(counter.items(), key=lambda x: -x[1])  
  35. words, _ = zip(*count_pairs)  
  36.    
  37. # 取前多少个常用字  
  38. words = words[:len(words)] + (' ',)  
  39. # 每个字映射为一个数字ID  
  40. word_num_map = dict(zip(words, range(len(words))))  
  41. # 把诗转换为向量形式,参考TensorFlow练习1  
  42. to_num = lambda word: word_num_map.get(word, len(words))  
  43. poetrys_vector = [ list(map(to_num, poetry)) for poetry in poetrys]  
  44. #[[314, 3199, 367, 1556, 26, 179, 680, 0, 3199, 41, 506, 40, 151, 4, 98, 1],  
  45. #[339, 3, 133, 31, 302, 653, 512, 0, 37, 148, 294, 25, 54, 833, 3, 1, 965, 1315, 377, 1700, 562, 21, 37, 0, 2, 1253, 21, 36, 264, 877, 809, 1]  
  46. #....]  
  47.    
  48. # 每次取64首诗进行训练  
  49. batch_size = 64  
  50. n_chunk = len(poetrys_vector) // batch_size  
  51. x_batches = []  
  52. y_batches = []  
  53. for i in range(n_chunk):  
  54.     start_index = i * batch_size  
  55.     end_index = start_index + batch_size  
  56.    
  57.     batches = poetrys_vector[start_index:end_index]  
  58.     length = max(map(len,batches))  
  59.     xdata = np.full((batch_size,length), word_num_map[' '], np.int32)  
  60.     for row in range(batch_size):  
  61.         xdata[row,:len(batches[row])] = batches[row]  
  62.     ydata = np.copy(xdata)  
  63.     ydata[:,:-1] = xdata[:,1:]  
  64.     """ 
  65.     xdata             ydata 
  66.     [6,2,4,6,9]       [2,4,6,9,9] 
  67.     [1,4,2,8,5]       [4,2,8,5,5] 
  68.     """  
  69.     x_batches.append(xdata)  
  70.     y_batches.append(ydata)  
  71.    
  72.    
  73. #---------------------------------------RNN--------------------------------------#  
  74.    
  75. input_data = tf.placeholder(tf.int32, [batch_size, None])  
  76. output_targets = tf.placeholder(tf.int32, [batch_size, None])  
  77. # 定义RNN  
  78. def neural_network(model='lstm', rnn_size=128, num_layers=2):  
  79.     if model == 'rnn':  
  80.         cell_fun = tf.nn.rnn_cell.BasicRNNCell  
  81.     elif model == 'gru':  
  82.         cell_fun = tf.nn.rnn_cell.GRUCell  
  83.     elif model == 'lstm':  
  84.         cell_fun = tf.nn.rnn_cell.BasicLSTMCell  
  85.    
  86.     cell = cell_fun(rnn_size, state_is_tuple=True)  
  87.     cell = tf.nn.rnn_cell.MultiRNNCell([cell] * num_layers, state_is_tuple=True)  
  88.    
  89.     initial_state = cell.zero_state(batch_size, tf.float32)  
  90.    
  91.     with tf.variable_scope('rnnlm'):  
  92.         softmax_w = tf.get_variable("softmax_w", [rnn_size, len(words)+1])  
  93.         softmax_b = tf.get_variable("softmax_b", [len(words)+1])  
  94.         with tf.device("/cpu:0"):  
  95.             embedding = tf.get_variable("embedding", [len(words)+1, rnn_size])  
  96.             inputs = tf.nn.embedding_lookup(embedding, input_data)  
  97.    
  98.     outputs, last_state = tf.nn.dynamic_rnn(cell, inputs, initial_state=initial_state, scope='rnnlm')  
  99.     output = tf.reshape(outputs,[-1, rnn_size])  
  100.    
  101.     logits = tf.matmul(output, softmax_w) + softmax_b  
  102.     probs = tf.nn.softmax(logits)  
  103.     return logits, last_state, probs, cell, initial_state  
  104. #训练  
  105. def train_neural_network():  
  106.     logits, last_state, _, _, _ = neural_network()  
  107.     targets = tf.reshape(output_targets, [-1])  
  108.     loss = tf.nn.seq2seq.sequence_loss_by_example([logits], [targets], [tf.ones_like(targets, dtype=tf.float32)], len(words))  
  109.     cost = tf.reduce_mean(loss)  
  110.     learning_rate = tf.Variable(0.0, trainable=False)  
  111.     tvars = tf.trainable_variables()  
  112.     grads, _ = tf.clip_by_global_norm(tf.gradients(cost, tvars), 5)  
  113.     optimizer = tf.train.AdamOptimizer(learning_rate)  
  114.     train_op = optimizer.apply_gradients(zip(grads, tvars))  
  115.    
  116.     with tf.Session() as sess:  
  117.         sess.run(tf.initialize_all_variables())  
  118.    
  119.         saver = tf.train.Saver(tf.all_variables())  
  120.    
  121.         for epoch in range(50):  
  122.             sess.run(tf.assign(learning_rate, 0.002 * (0.97 ** epoch)))  
  123.             n = 0  
  124.             for batche in range(n_chunk):  
  125.                 train_loss, _ , _ = sess.run([cost, last_state, train_op], feed_dict={input_data: x_batches[n], output_targets: y_batches[n]})  
  126.                 n += 1  
  127.                 print(epoch, batche, train_loss)  
  128.             if epoch % 7 == 0:  
  129.                 saver.save(sess, 'poetry.module', global_step=epoch)  
  130.    
  131. train_neural_network()  

使用训练好的模型生成古诗:

[python]  view plain  copy
  1. import collections  
  2. import numpy as np  
  3. import tensorflow as tf  
  4.    
  5. #-------------------------------数据预处理---------------------------#  
  6.    
  7. poetry_file ='poetry.txt'  
  8.    
  9. # 诗集  
  10. poetrys = []  
  11. with open(poetry_file, "r", encoding='utf-8',) as f:  
  12.     for line in f:  
  13.         try:  
  14.             title, content = line.strip().split(':')  
  15.             content = content.replace(' ','')  
  16.             if '_' in content or '(' in content or '(' in content or '《' in content or '[' in content:  
  17.                 continue  
  18.             if len(content) < 5 or len(content) > 79:  
  19.                 continue  
  20.             content = '[' + content + ']'  
  21.             poetrys.append(content)  
  22.         except Exception as e:   
  23.             pass  
  24.    
  25. # 按诗的字数排序  
  26. poetrys = sorted(poetrys,key=lambda line: len(line))  
  27. print('唐诗总数: ', len(poetrys))  
  28.    
  29. # 统计每个字出现次数  
  30. all_words = []  
  31. for poetry in poetrys:  
  32.     all_words += [word for word in poetry]  
  33. counter = collections.Counter(all_words)  
  34. count_pairs = sorted(counter.items(), key=lambda x: -x[1])  
  35. words, _ = zip(*count_pairs)  
  36.    
  37. # 取前多少个常用字  
  38. words = words[:len(words)] + (' ',)  
  39. # 每个字映射为一个数字ID  
  40. word_num_map = dict(zip(words, range(len(words))))  
  41. # 把诗转换为向量形式,参考TensorFlow练习1  
  42. to_num = lambda word: word_num_map.get(word, len(words))  
  43. poetrys_vector = [ list(map(to_num, poetry)) for poetry in poetrys]  
  44. #[[314, 3199, 367, 1556, 26, 179, 680, 0, 3199, 41, 506, 40, 151, 4, 98, 1],  
  45. #[339, 3, 133, 31, 302, 653, 512, 0, 37, 148, 294, 25, 54, 833, 3, 1, 965, 1315, 377, 1700, 562, 21, 37, 0, 2, 1253, 21, 36, 264, 877, 809, 1]  
  46. #....]  
  47.    
  48. batch_size = 1  
  49. n_chunk = len(poetrys_vector) // batch_size  
  50. x_batches = []  
  51. y_batches = []  
  52. for i in range(n_chunk):  
  53.     start_index = i * batch_size  
  54.     end_index = start_index + batch_size  
  55.    
  56.     batches = poetrys_vector[start_index:end_index]  
  57.     length = max(map(len,batches))  
  58.     xdata = np.full((batch_size,length), word_num_map[' '], np.int32)  
  59.     for row in range(batch_size):  
  60.         xdata[row,:len(batches[row])] = batches[row]  
  61.     ydata = np.copy(xdata)  
  62.     ydata[:,:-1] = xdata[:,1:]  
  63.     """ 
  64.     xdata             ydata 
  65.     [6,2,4,6,9]       [2,4,6,9,9] 
  66.     [1,4,2,8,5]       [4,2,8,5,5] 
  67.     """  
  68.     x_batches.append(xdata)  
  69.     y_batches.append(ydata)  
  70.    
  71.    
  72. #---------------------------------------RNN--------------------------------------#  
  73.    
  74. input_data = tf.placeholder(tf.int32, [batch_size, None])  
  75. output_targets = tf.placeholder(tf.int32, [batch_size, None])  
  76. # 定义RNN  
  77. def neural_network(model='lstm', rnn_size=128, num_layers=2):  
  78.     if model == 'rnn':  
  79.         cell_fun = tf.nn.rnn_cell.BasicRNNCell  
  80.     elif model == 'gru':  
  81.         cell_fun = tf.nn.rnn_cell.GRUCell  
  82.     elif model == 'lstm':  
  83.         cell_fun = tf.nn.rnn_cell.BasicLSTMCell  
  84.    
  85.     cell = cell_fun(rnn_size, state_is_tuple=True)  
  86.     cell = tf.nn.rnn_cell.MultiRNNCell([cell] * num_layers, state_is_tuple=True)  
  87.    
  88.     initial_state = cell.zero_state(batch_size, tf.float32)  
  89.    
  90.     with tf.variable_scope('rnnlm'):  
  91.         softmax_w = tf.get_variable("softmax_w", [rnn_size, len(words)+1])  
  92.         softmax_b = tf.get_variable("softmax_b", [len(words)+1])  
  93.         with tf.device("/cpu:0"):  
  94.             embedding = tf.get_variable("embedding", [len(words)+1, rnn_size])  
  95.             inputs = tf.nn.embedding_lookup(embedding, input_data)  
  96.    
  97.     outputs, last_state = tf.nn.dynamic_rnn(cell, inputs, initial_state=initial_state, scope='rnnlm')  
  98.     output = tf.reshape(outputs,[-1, rnn_size])  
  99.    
  100.     logits = tf.matmul(output, softmax_w) + softmax_b  
  101.     probs = tf.nn.softmax(logits)  
  102.     return logits, last_state, probs, cell, initial_state  
  103.    
  104. #-------------------------------生成古诗---------------------------------#  
  105. # 使用训练完成的模型  
  106.    
  107. def gen_poetry():  
  108.     def to_word(weights):  
  109.         t = np.cumsum(weights)  
  110.         s = np.sum(weights)  
  111.         sample = int(np.searchsorted(t, np.random.rand(1)*s))  
  112.         return words[sample]  
  113.    
  114.     _, last_state, probs, cell, initial_state = neural_network()  
  115.    
  116.     with tf.Session() as sess:  
  117.         sess.run(tf.initialize_all_variables())  
  118.    
  119.         saver = tf.train.Saver(tf.all_variables())  
  120.         saver.restore(sess, 'poetry.module-49')  
  121.    
  122.         state_ = sess.run(cell.zero_state(1, tf.float32))  
  123.    
  124.         x = np.array([list(map(word_num_map.get, '['))])  
  125.         [probs_, state_] = sess.run([probs, last_state], feed_dict={input_data: x, initial_state: state_})  
  126.         word = to_word(probs_)  
  127.         #word = words[np.argmax(probs_)]  
  128.         poem = ''  
  129.         while word != ']':  
  130.             poem += word  
  131.             x = np.zeros((1,1))  
  132.             x[0,0] = word_num_map[word]  
  133.             [probs_, state_] = sess.run([probs, last_state], feed_dict={input_data: x, initial_state: state_})  
  134.             word = to_word(probs_)  
  135.             #word = words[np.argmax(probs_)]  
  136.         return poem  
  137.    
  138. print(gen_poetry())  

生成的“诗词”(至少格式对上了):

生成藏头诗:

[python]  view plain  copy
  1. def gen_poetry_with_head(head):  
  2.     def to_word(weights):  
  3.         t = np.cumsum(weights)  
  4.         s = np.sum(weights)  
  5.         sample = int(np.searchsorted(t, np.random.rand(1)*s))  
  6.         return words[sample]  
  7.    
  8.     _, last_state, probs, cell, initial_state = neural_network()  
  9.    
  10.     with tf.Session() as sess:  
  11.         sess.run(tf.initialize_all_variables())  
  12.    
  13.         saver = tf.train.Saver(tf.all_variables())  
  14.         saver.restore(sess, 'poetry.module-49')  
  15.    
  16.         state_ = sess.run(cell.zero_state(1, tf.float32))  
  17.         poem = ''  
  18.         i = 0  
  19.         for word in head:  
  20.             while word != ',' and word != '。':  
  21.                 poem += word  
  22.                 x = np.array([list(map(word_num_map.get, word))])  
  23.                 [probs_, state_] = sess.run([probs, last_state], feed_dict={input_data: x, initial_state: state_})  
  24.                 word = to_word(probs_)  
  25.                 time.sleep(1)  
  26.             if i % 2 == 0:  
  27.                 poem += ','  
  28.             else:  
  29.                 poem += '。'  
  30.             i += 1  
  31.         return poem  
  32.    
  33. print(gen_poetry_with_head('一二三四'))  

上面使用的TensroFlow版本为0.11,0.12版本貌似不能直接运行,简单修改如下代码:

读取模型的方法:

[python]  view plain  copy
  1. module_file = tf.train.latest_checkpoint('.')  
  2.     #print(module_file)  
  3.     saver.restore(sess, module_file)  

tf.initialize_all_variables()  deprecated,使用tf.global_variables_initializer()替代。

猜你喜欢

转载自blog.csdn.net/richgene/article/details/80621596