基于统计生成相似句(同义句),再用神经网络rnn语言模型判断句子的通顺性!

您所在的位置:网站首页 weigh同义句转换 基于统计生成相似句(同义句),再用神经网络rnn语言模型判断句子的通顺性!

基于统计生成相似句(同义句),再用神经网络rnn语言模型判断句子的通顺性!

2023-09-10 10:24| 来源: 网络整理| 查看: 265

主要生成相似句 再用神经网络判定句子的通顺性

直接上代码  

两部分工作:

第一部分基于统计生成相似语料:

         借助网上的python的github上的synonyms(自行百度):https://github.com/huyingxi/Synonyms   这里要说一下 分词不要用         垃圾 的jieba 可以考虑hanlp 或者其他的 ;

        效果如下:

       例如 ”查看公司财务“

        生成的句子:

          查看公司的财务         查看公司的财政         查看公司的财务状况        查看公司的公司财务       查看公司的税务       查看公司的负债      查看公司的财务管理     查看公司的帐目     查看公司的人力资源     查看公司的人事管理      查看该公司的财务        查看该公司的财政          查看该公司的财务状况          查看该公司的公司财务              查看该公司的税务              查看该公司的负债                查看该公司的财务管理                  查看该公司的帐目                  查看该公司的人力资源                     查看该公司的人事管理                         查看的公司的财务                         查看的公司的财政                          查看的公司的财务状况

自己思路: 中文语料库进行分词,然后进行获取同义词替换,这里可以考虑n-gram   n=1,2,3  做

       Bi-Gram:  P(T)=p(w1|begin)*p(w2|w1)*p(w3|w2)***p(wn|wn-1)

       Tri-Gram:  P(T)=p(w1|begin1,begin2)*p(w2|w1,begin1)*p(w3|w2w1)***p(wn|wn-1,wn-2)

       里面的概率用统计词频来处理求解  具体求解可以参考:https://blog.csdn.net/weixin_37767223/article/details/83187802

       最后根据概率大小判定句子是不是通顺, 这个 我这里就没做 感兴趣的可以做一下 比较简单  

 

第二部分神经网络模型判定句子通顺性:

      例如:我的顺心很不工作      分数: 11.457166507915696

                   我的工作很不顺心    分数: 37.69209207976687  

后面优化如下:

由于数据量大(500w)后面做一些改进

1. softmax 进行优化 主要把softmax   改写成  hierarchical softmax  

2.主要把句子通顺性的对比进行阈值的确定

网络模型代码:

def main(): parser = argparse.ArgumentParser() parser.add_argument('--data_dir', type=str, default='data/', help='data directory containing input.txt') parser.add_argument('--batch_size', type=int, default=120, help='minibatch size') parser.add_argument('--win_size', type=int, default=20, help='context sequence length') parser.add_argument('--hidden_num', type=int, default=64, help='number of hidden layers') parser.add_argument('--word_dim', type=int, default=50, help='number of word embedding') parser.add_argument('--num_epochs', type=int, default=10, help='number of epochs') parser.add_argument('--grad_clip', type=float, default=10., help='clip gradients at this value') args = parser.parse_args() data_loader = TextLoader(args.data_dir, args.batch_size, args.win_size) args.vocab_size = data_loader.vocab_size graph = tf.Graph() with graph.as_default(): input_data = tf.placeholder(tf.int64, [args.batch_size, args.win_size]) targets = tf.placeholder(tf.int64, [args.batch_size, 1]) with tf.variable_scope('nnlm' + 'embedding'): embeddings = tf.Variable(tf.random_uniform([args.vocab_size, args.word_dim], -1.0, 1.0)) embeddings = tf.nn.l2_normalize(embeddings, 1) #范化的 按行还是按列进行范化 with tf.variable_scope('nnlm' + 'weight'): weight_h = tf.Variable(tf.truncated_normal([args.win_size * args.word_dim, args.hidden_num], stddev=1.0 / math.sqrt(args.hidden_num))) softmax_w = tf.Variable(tf.truncated_normal([args.win_size * args.word_dim, args.vocab_size], stddev=1.0 / math.sqrt(args.win_size * args.word_dim))) softmax_u = tf.Variable(tf.truncated_normal([args.hidden_num, args.vocab_size], stddev=1.0 / math.sqrt(args.hidden_num))) b_1 = tf.Variable(tf.random_normal([args.hidden_num])) b_2 = tf.Variable(tf.random_normal([args.vocab_size])) def infer_output(input_data): # """ # hidden = tanh(x * H + b_1) # output = softmax(x * W + hidden * U + b_2) # """ input_data_emb = tf.nn.embedding_lookup(embeddings,input_data) #选取一个张量里面索引对应的元素 input_data_emb = tf.reshape(input_data_emb, [-1, args.win_size * args.word_dim]) #行数不变 宽度改变 hidden = tf.tanh(tf.matmul(input_data_emb, weight_h)) + b_1 hidden_output = tf.matmul(hidden, softmax_u) + tf.matmul(input_data_emb, softmax_w) + b_2 output = tf.nn.softmax(hidden_output) return output outputs = infer_output(input_data) #input_data 数据格式 one_hot_targets = tf.one_hot(tf.squeeze(targets), args.vocab_size, 1.0, 0.0) #把这个映射成one_hot形式 loss = -tf.reduce_mean(tf.reduce_sum(tf.log(outputs) * one_hot_targets, 1)) # Clip grad. optimizer = tf.train.AdagradOptimizer(0.1) gvs = optimizer.compute_gradients(loss) capped_gvs = [(tf.clip_by_value(grad, -args.grad_clip, args.grad_clip), var) for grad, var in gvs] optimizer = optimizer.apply_gradients(capped_gvs) embeddings_norm = tf.sqrt(tf.reduce_sum(tf.square(embeddings), 1, keep_dims=True)) normalized_embeddings = embeddings / embeddings_norm with tf.Session(graph=graph) as sess: tf.global_variables_initializer().run() for e in range(args.num_epochs): #迭代的次数 data_loader.reset_batch_pointer() for b in range(data_loader.num_batches): start = time.time() x, y = data_loader.next_batch() feed = {input_data: x, targets: y} train_loss, _ = sess.run([loss, optimizer], feed) end = time.time() print("{}/{} (epoch {}), train_loss = {:.3f}, time/batch = {:.3f}".format( b, data_loader.num_batches, e, train_loss, end - start)) np.save('nnlm_word_embeddings.zh', normalized_embeddings.eval())

具体的分批次 以及分割数据 :

class TextLoader(): def __init__(self, data_dir, batch_size, seq_length, mini_frq=3): self.data_dir = data_dir self.batch_size = batch_size self.seq_length = seq_length self.mini_frq = mini_frq input_file = os.path.join(data_dir, "text_test.txt") vocab_file = os.path.join(data_dir, "vocab.zh.pkl") self.preprocess(input_file, vocab_file) #处理数据 把文本处理句子成 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 78, 1, 1, 530, 86, 108, 107, 1, 810, 3, 427, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] self.create_batches() self.reset_batch_pointer() def build_vocab(self, sentences): word_counts = collections.Counter() if not isinstance(sentences, list): sentences = [sentences] for sent in sentences: word_counts.update(sent) vocabulary_inv = ['', '', ''] + \ [x[0] for x in word_counts.most_common() if x[1] >= self.mini_frq] #进行频率的筛选的过程 vocabulary = {x: i for i, x in enumerate(vocabulary_inv)} #每个不重复词的位置id索引字典 return [vocabulary, vocabulary_inv] def preprocess(self, input_file, vocab_file): with codecs.open(input_file, 'r', 'utf-8') as f: lines = f.readlines() if lines[0][:1] == codecs.BOM_UTF8: lines[0] = lines[0][1:] lines = [line.strip().split() for line in lines] #把文本数据全部放到一个list [['上学','生活'],,,,,,,] self.vocab, self.words = self.build_vocab(lines) # 一个词的列表 一个是关于字典的词 以及独一无二的词的索引位置 self.vocab_size = len(self.words) #统计词量 #print 'word num: ', self.vocab_size with open(vocab_file, 'wb') as f: cPickle.dump(self.words, f) #把字典的词频系列写进去文档保存 raw_data = [[0] * self.seq_length+[self.vocab.get(w, 1) for w in line] +[2] * self.seq_length for line in lines] self.raw_data = raw_data #把每句话转换成 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 78, 1, 1, 530, 86, 108, 107, 1, 810, 3, 427, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] #对应的数值为词表里面的id下标,前面的0和后面的2 def create_batches(self): xdata, ydata = list(),list() for row in self.raw_data: #row 为每一个句子向量化的东西 for ind in range(self.seq_length, len(row)): #20 60 xdata.append(row[ind-self.seq_length:ind]) ydata.append([row[ind]]) #下一个单词 目标单词 # print(xdata) # print(ydata) # input() #[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]] #[[1], [94]] self.num_batches = int(len(xdata) / self.batch_size) # print(self.num_batches) # input() if self.num_batches == 0: assert False, "Not enough data. Make seq_length and batch_size small." xdata = np.array(xdata[:self.num_batches * self.batch_size]) ydata = np.array(ydata[:self.num_batches * self.batch_size]) # print(xdata[:self.num_batches * self.batch_size]) # print(ydata) # input() self.x_batches = np.split(xdata, self.num_batches, 0) #分割批次进行喂数据 self.y_batches = np.split(ydata, self.num_batches, 0)#分割批次进行喂数据 def next_batch(self): x, y = self.x_batches[self.pointer], self.y_batches[self.pointer] self.pointer += 1 return x, y def reset_batch_pointer(self): self.pointer = 0

 

代码的链接:https://gitee.com/zhoubingbing/rnn_neuroreticulum/tree/master

 



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3