首页 >资讯 > > 正文

python实现Bi-GRU语义解析实现中文人物关系分析【文末源码】|焦点热讯

来源:哔哩哔哩 2023-04-25 20:03:42

Bi-GRU语义解析实现中文人物关系分析

引言语义解析作为自然语言处理的重要方面,其主要作用如下:在词的层次上,语义分析的基本任务是进行词义消歧;在句子层面上,语义角色标注是所关心的问题;在文章层次上,指代消解、篇章语义分析是重点。


(资料图)

而实体识别和关系抽取是构建知识图谱等上层自然语言处理应用的基础。关系抽取可以简单理解为一个分类问题:给定两个实体和两个实体共同出现的句子文本,判别两个实体之间的关系。

使用CNN或者双向RNNAttention的深度学习方法被认为是现在关系抽取stateofart的解决方案。已有的文献和代码,大都是针对英文语料,使用词向量作为输入进行训练。这里以实践为目的,介绍一个用双向GRU、字与句子的双重Attention模型,以天然适配中文特性的字向量(characterembedding)作为输入,网络爬取数据作为训练语料构建的中文关系抽取模型。代码主要是基于清华的开源项目thunlp/TensorFlow-NRE开发,其中效果如下:

一、实验前的准备:

首先我们使用的python版本是3.6.5所用到的模块如下:

tensorflow模块用来创建整个模型训练和保存调用以及网络的搭建框架等等。

numpy模块用来处理数据矩阵运算。

Sklearn模块是一些机器学习算法的集成模块。

二、模型的网络搭建

其中模型的网络图如下:

双向GRU加字级别attention的模型想法来自文章“Attention-BasedBidirectional Long Short-Term Memory Networks for RelationClassification” [Zhou etal.,2016]。这里将原文的模型结构中的LSTM改为GRU,且对句子中的每一个中文字符输入为characterembedding。这样的模型对每一个句子输入做训练,加入字级别的attention

句子级别attention的想法来自文章“NeuralRelation Extraction with Selective Attention over Instances”[Lin etal.,2016]。原文模型结构图如下,这里将其中对每个句子进行encodingCNN模块换成上面的双向GRU模型。这样的模型对每一种类别的句子输入做共同训练,加入句子级别的attention

建立network.py文件,定义词向量大小、步数、类别数等等:def__init__(self):   self.vocab_size= 16691   self.num_steps= 70   self.num_epochs= 10   self.num_classes= 12   self.gru_size= 230   self.keep_prob= 0.5   self.num_layers= 1   self.pos_size= 5   self.pos_num= 123   #the number of entity pairs of each batch during training or testing   self.big_num= 50

然后建立GRU网络。按照所给出的网络模型图,定义出网络基本框架作为具体参数的调用:

def__init__(self,is_training, word_embeddings, settings):    self.num_steps= num_steps = settings.num_steps    self.vocab_size= vocab_size=settings.vocab_size    self.num_classes= num_classes = settings.num_classes    self.gru_size= gru_size = settings.gru_size    self.big_num= big_num = settings.big_num    self.input_word= tf.placeholder(dtype=tf.int32,shape=[None,num_steps], name='input_word')   self.input_pos1= tf.placeholder(dtype=tf.int32,shape=[None,num_steps], name='input_pos1')   self.input_pos2= tf.placeholder(dtype=tf.int32,shape=[None,num_steps], name='input_pos2')   self.input_y= tf.placeholder(dtype=tf.float32,shape=[None,num_classes], name='input_y')   self.total_shape= tf.placeholder(dtype=tf.int32,shape=[big_num+ 1],name='total_shape')   total_num = self.total_shape[-1]   word_embedding = tf.get_variable(initializer=word_embeddings,name='word_embedding')   pos1_embedding = tf.get_variable('pos1_embedding',[settings.pos_num, settings.pos_size])    pos2_embedding =tf.get_variable('pos2_embedding',[settings.pos_num, settings.pos_size])    attention_w =tf.get_variable('attention_omega',[gru_size, 1])   sen_a = tf.get_variable('attention_A',[gru_size])    sen_r = tf.get_variable('query_r',[gru_size, 1])   relation_embedding = tf.get_variable('relation_embedding',[self.num_classes,gru_size])    sen_d = tf.get_variable('bias_d',[self.num_classes])   gru_cell_forward = tf.contrib.rnn.GRUCell(gru_size)   gru_cell_backward = tf.contrib.rnn.GRUCell(gru_size)    ifis_trainingandsettings.keep_prob< 1:       gru_cell_forward =tf.contrib.rnn.DropoutWrapper(gru_cell_forward,output_keep_prob=settings.keep_prob)       gru_cell_backward =tf.contrib.rnn.DropoutWrapper(gru_cell_backward,output_keep_prob=settings.keep_prob)   cell_forward = tf.contrib.rnn.MultiRNNCell([gru_cell_forward] *settings.num_layers)    cell_backward =tf.contrib.rnn.MultiRNNCell([gru_cell_backward] *settings.num_layers)    sen_repre = []    sen_alpha = []   sen_s = []    sen_out = []    self.prob= []    self.predictions= []    self.loss= []    self.accuracy= []    self.total_loss= 0.0   self._initial_state_forward= cell_forward.zero_state(total_num, tf.float32)   self._initial_state_backward= cell_backward.zero_state(total_num, tf.float32)    #embedding layer    inputs_forward= tf.concat(axis=2,values=[tf.nn.embedding_lookup(word_embedding,self.input_word),                                             tf.nn.embedding_lookup(pos1_embedding, self.input_pos1),                                             tf.nn.embedding_lookup(pos2_embedding, self.input_pos2)])   inputs_backward = tf.concat(axis=2,                              values=[tf.nn.embedding_lookup(word_embedding,tf.reverse(self.input_word,[1])),                                      tf.nn.embedding_lookup(pos1_embedding, tf.reverse(self.input_pos1,[1])),                                      tf.nn.embedding_lookup(pos2_embedding,                                                             tf.reverse(self.input_pos2,[1]))])   outputs_forward = []    state_forward =self._initial_state_forward   #Bi-GRU layer    withtf.variable_scope('GRU_FORWARD')asscope:       forstepinrange(num_steps):           ifstep> 0:               scope.reuse_variables()           (cell_output_forward, state_forward) = cell_forward(inputs_forward[:,step, :], state_forward)           outputs_forward.append(cell_output_forward)    outputs_backward= []    state_backward = self._initial_state_backward   withtf.variable_scope('GRU_BACKWARD')asscope:       forstepinrange(num_steps):           ifstep> 0:               scope.reuse_variables()           (cell_output_backward, state_backward) =cell_backward(inputs_backward[:, step, :], state_backward)          outputs_backward.append(cell_output_backward)   output_forward = tf.reshape(tf.concat(axis=1,values=outputs_forward),[total_num, num_steps, gru_size])    output_backward =tf.reverse(        tf.reshape(tf.concat(axis=1,values=outputs_backward),[total_num, num_steps, gru_size]), [1])   #word-level attention layer    output_h= tf.add(output_forward, output_backward)    attention_r =tf.reshape(tf.matmul(tf.reshape(tf.nn.softmax(       tf.reshape(tf.matmul(tf.reshape(tf.tanh(output_h), [total_num *num_steps, gru_size]), attention_w),                  [total_num, num_steps])), [total_num, 1,num_steps]), output_h), [total_num, gru_size])    

三、模型的训练和使用

其中用来训练的语料获取,由于中文关系抽取的公开语料比较少。我们从distantsupervision的方法中获取灵感,希望可以首先找到具有确定关系的实体对,然后再去获取该实体对共同出现的语句作为正样本。负样本则从实体库中随机产生没有关系的实体对,再去获取这样实体对共同出现的语句。

对于具有确定关系的实体对,我们从复旦知识工厂得到,感谢他们提供的免费API!一个小问题是,相同的关系label在复旦知识工厂中可能对应着不同的标注,比如“夫妻”,抓取到的数据里有的是“丈夫”,有的是“妻子”,有的是“伉俪”等等,需要手动对齐。

模型的训练:

建立train_GRU文件,通过训练已经经过处理后得到的npy文件进行训练。

其中训练的数据如下:

代码如下:

defmain(_):   #the path to save models    save_path= './model/'   print('readingwordembedding')   wordembedding = np.load('./data/vec.npy')   print('readingtraining data')   train_y = np.load('./data/train_y.npy')   train_word = np.load('./data/train_word.npy')   train_pos1 = np.load('./data/train_pos1.npy')   train_pos2 = np.load('./data/train_pos2.npy')   settings = network.Settings()    settings.vocab_size =len(wordembedding)   settings.num_classes = len(train_y[0])   big_num=settings.big_num    withtf.Graph().as_default():       sess = tf.Session()        withsess.as_default():           initializer = tf.contrib.layers.xavier_initializer()           withtf.variable_scope("model",reuse=None,initializer=initializer):               m = network.GRU(is_training=True,word_embeddings=wordembedding,settings=settings)           global_step = tf.Variable(0,name="global_step",trainable=False)           optimizer = tf.train.AdamOptimizer(0.0005)           train_op = optimizer.minimize(m.final_loss,global_step=global_step)           sess.run(tf.global_variables_initializer())          saver = tf.train.Saver(max_to_keep=None)           merged_summary = tf.summary.merge_all()           summary_writer = tf.summary.FileWriter(FLAGS.summary_dir +'/train_loss',sess.graph)            deftrain_step(word_batch,pos1_batch, pos2_batch, y_batch, big_num):               feed_dict = {}                total_shape = []              total_num = 0               total_word= []                total_pos1 = []               total_pos2 = []                foriinrange(len(word_batch)):                   total_shape.append(total_num)                  total_num += len(word_batch[i])                   forwordinword_batch[i]:                       total_word.append(word)                  forpos1inpos1_batch[i]:                       total_pos1.append(pos1)                  forpos2inpos2_batch[i]:                       total_pos2.append(pos2)               total_shape.append(total_num)                total_shape =np.array(total_shape)                total_word =np.array(total_word)                total_pos1 =np.array(total_pos1)                total_pos2 =np.array(total_pos2)                feed_dict[m.total_shape] =total_shape                feed_dict[m.input_word] =total_word                feed_dict[m.input_pos1] = total_pos1               feed_dict[m.input_pos2] = total_pos2               feed_dict[m.input_y] = y_batch                temp, step,loss, accuracy, summary, l2_loss, final_loss = sess.run(                  [train_op, global_step, m.total_loss, m.accuracy,merged_summary, m.l2_loss, m.final_loss],                   feed_dict)                time_str =datetime.datetime.now().isoformat()                accuracy =np.reshape(np.array(accuracy), (big_num))                acc =np.mean(accuracy)               summary_writer.add_summary(summary, step)                ifstep% 50==0:                   tempstr = "{}:step {}, softmax_loss {:g}, acc {:g}".format(time_str,step, loss, acc)                    print(tempstr)           forone_epochinrange(settings.num_epochs):               temp_order = list(range(len(train_word)))               np.random.shuffle(temp_order)                foriinrange(int(len(temp_order)/ float(settings.big_num))):                   temp_word = []                    temp_pos1= []                    temp_pos2 = []                   temp_y = []                    temp_input = temp_order[i *settings.big_num:(i + 1)* settings.big_num]                    forkintemp_input:                       temp_word.append(train_word[k])                      temp_pos1.append(train_pos1[k])                       temp_pos2.append(train_pos2[k])                       temp_y.append(train_y[k])                    num = 0                   forsingle_wordintemp_word:                       num += len(single_word)                   ifnum> 1500:                       print('outof range')                       continue                   temp_word= np.array(temp_word)                    temp_pos1 =np.array(temp_pos1)                    temp_pos2 =np.array(temp_pos2)                    temp_y =np.array(temp_y)                    train_step(temp_word,temp_pos1, temp_pos2, temp_y, settings.big_num)                   current_step = tf.train.global_step(sess, global_step)                   ifcurrent_step> 8000andcurrent_step% 100==0:                       print('savingmodel')                       path = saver.save(sess, save_path +'ATT_GRU_model',global_step=current_step)                       tempstr = 'havesaved model to ' +path                        print(tempstr)

训练过程:

2.模型的测试:

其中得到训练后的模型如下:

whileTrue:   #try:       #BUG: Encoding error if user input directly from commandline.        line= input('请输入中文句子,格式为"name1name2 sentence":')       #Readfile from test file        '''       infile = open('test.txt', encoding='utf-8')        line= ''        for orgline in infile:            line =orgline.strip()            break        infile.close()       '''        en1,en2, sentence = line.strip().split()        print("实体1:" +en1)        print("实体2:" +en2)        print(sentence)       relation=0       en1pos= sentence.find(en1)        ifen1pos== -1:           en1pos = 0       en2pos= sentence.find(en2)        ifen2pos== -1:           en2post=0       output= []        #length of sentence is 70        fixlen= 70       #max length of position embedding is 60 (-60~+60)        maxlen=60       #Encodingtest x        foriinrange(fixlen):           word = word2id['BLANK']           rel_e1 = pos_embed(i - en1pos)            rel_e2 =pos_embed(i - en2pos)            output.append([word, rel_e1,rel_e2])        foriinrange(min(fixlen,len(sentence))):           word=0           ifsentence[i]notin word2id:               #print(sentence[i])               #print('==')                word= word2id['UNK']               #print(word)           else:               #print(sentence[i])               #print('||')                word= word2id[sentence[i]]                #print(word)           output[i][0]= word        test_x = []        test_x.append([output])       #Encodingtest y        label= [0foriinrange(len(relation2id))]       label[0]= 1       test_y= []        test_y.append(label)        test_x =np.array(test_x)        test_y = np.array(test_y)       test_word = []        test_pos1 = []        test_pos2 =[]        foriinrange(len(test_x)):           word = []            pos1 = []            pos2= []            forjintest_x[i]:               temp_word = []                temp_pos1 = []               temp_pos2 = []                forkinj:                   temp_word.append(k[0])                   temp_pos1.append(k[1])                   temp_pos2.append(k[2])               word.append(temp_word)               pos1.append(temp_pos1)                pos2.append(temp_pos2)           test_word.append(word)           test_pos1.append(pos1)            test_pos2.append(pos2)      test_word = np.array(test_word)        test_pos1 =np.array(test_pos1)        test_pos2 = np.array(test_pos2)        prob,accuracy = test_step(test_word, test_pos1, test_pos2, test_y)       prob = np.reshape(np.array(prob), (1,test_settings.num_classes))[0]       print("关系是:")       #print(prob)       top3_id= prob.argsort()[-3:][::-1]       forn,rel_id inenumerate(top3_id):           print("No."+str(n+1)+ ":" +id2relation[rel_id] + ",Probability is " +str(prob[rel_id]))  测试效果:

完整代码:https://gitcode.net/qq_42279468/python-bi-gru.git

上一篇:季后赛大黑马诞生!浓眉12分也能赢,西部没对手,湖人剑指总决赛 下一篇:每日焦点!“恒心”与“耐心”,师范生分享写一手好字的秘诀
x
推荐阅读

《绝地求生手游》美服连接不上是什么原因

2023-07-03

世界资讯:大王卡超级会员怎么退订(大王卡超级会员)

2023-07-03

每日短讯:《动植物油脂 紫外吸光度的测定》国家标准征求意见

2023-07-03

江苏舜天被罚千万 13年间虚增营收超百亿 董事长遭市场禁入3年

2023-07-03

董秘“三会”规范运作的九个要点-世界动态

2023-07-03

联合王国是一个国家吗_联合王国是哪个国家 当前快讯

2023-07-03

天天亮点!中国利郎上半年“LILANZ”产品的零售金额同比取得高单位数增长

2023-07-03

uc下载的视频在哪里可以找到[多图] uc下载的视频怎么找 世界快报

2023-07-03

焦点讯息:我们可以治愈几乎所有的人类疾病。这就是方法

2023-07-03

全球资讯:关于征求省标《福建省居住建筑节能设计标准》(征求意见稿)意见的通知

2023-07-03

NBA生涯至今哈登从未缺席季后赛_天天即时看

2023-07-03

热文:生产流程设计(生产流程)

2023-07-03

世界消息!废品中藏烟头 居民捡回家引燃车库

2023-07-03

小米换屏后屏幕经常失灵 环球资讯

2023-07-03

当前看点!朗特智能:人形机器人浪潮的三重奏

2023-07-03

阿里云与申电云达成战略合作 全球观速讯

2023-07-03

福建古田:翠屏湖景区风景如画引客来|简讯

2023-07-03

小区凌晨两三点清运垃圾 未央城管:调整至早6点后

2023-07-03

win7密码破解大白菜 win7密码破解 前沿热点

2023-07-03

环球看点!合肥选拔“土专家”“田秀才”“乡创客”

2023-07-03

环球头条:84消毒液的84什么意思_84消毒液的84什么意思详解

2023-07-03

心字组词2字_心字组词

2023-07-02

澳门和香港是什么时候回归祖国的_香港和澳门是几年几月几日回归祖国 天天快播

2023-07-02

谁说豪门不会做生意?皇马队史四笔经典交易狂赚2亿_天天实时

2023-07-02

现代汽车集团旗下品牌捷尼赛思全新G80已在韩国上市

2023-07-02

谁是原澳网单打、双打、混双全能王?

2023-07-02

外媒盘点:十件永远不要对PC玩家说的事 环球焦点

2023-07-02

全球最新:猪舌头怎么洗视频教程_猪舌头怎么洗

2023-07-02

全球热推荐:苍蝇屎在车上长时间不洗好吗(苍蝇屎)

2023-07-02

虹吸式马桶回气孔清理深度(虹吸式马桶回气孔清理)|全球快资讯

2023-07-02

苍山玉带云游路:夏日避暑好去处!(附攻略)

2023-07-02

p2p第三方支付流程图_P2P网贷第三方平台都有哪些|今日快讯

2023-07-02

成都市市场监管局、市消委会召开行业诚信座谈会—中国新闻网·四川新闻

2023-07-02

讯息:近期人民币汇率持续走低,专家表示:外汇市场基本面支撑有望逐步增强

2023-07-02

多家券商下调保证金利率 利好了谁?

2023-07-02

高校该不该开放?当高校游览参观被做成“付费生意” 环球快播报

2023-07-02

当前速递!郝志鹏父亲完整版_郝志鹏

2023-07-02

微头条丨邓字怎么组词二年级_邓字怎么组词

2023-07-02

笔记本电脑寿命一般几年_笔记本电脑寿命

2023-07-02

韩国最大在野党举行集会 谴责日本将福岛核污染水排海

2023-07-01

潘功胜升任央行新掌舵人,曾出版过四本书籍

2023-07-01

申请信用卡需要满足什么条件?必须符合这些要求! 热头条

2023-07-01

广州立白(番禺)有限公司招聘普工+质检员(有五险一金) 当前通讯

2023-07-01

【环球时快讯】图知道|开辟马克思主义中国化时代化新境界

2023-07-01

大头虾越式风味餐厅附近地铁站_大头虾越式风味餐厅|今日热门

2023-07-01

英雄联盟fps过低是怎么回事_英雄联盟fps过低

2023-07-01

斐讯商城官网_斐讯商城还正常吗_当前焦点

2023-07-01

穷极一生你都搞不懂的星座,只有他

2023-07-01

天天最新:预约下一站,每人40枚纪念币,要缩量了?

2023-07-01

中国“土乡”青海互助县:土族故土园集中展示土族文化|热资讯

2023-07-01

天天最资讯丨停车场一车起火呼呼冒黑烟,“白大褂”冲出来灭火

2023-07-01

修改照片像素和尺寸的软件_如何用photoshop修改照片尺寸大小-世界新消息

2023-07-01

新七小福龙之心mp3下载_新七小福龙之心

2023-07-01

马谡失街亭_马谡 当前时讯

2023-07-01

致中和:“节”德的传统价值与现代追寻 热闻

2023-07-01

摩尔庄园台服怎么下载_摩尔庄园台服

2023-07-01

【速看料】【公安心向党 护航新征程】暴雨!洪水!“警察蓝”逆行守护平安

2023-07-01

全球关注:lol虚空掠夺者出装手游_lol虚空掠夺者出装

2023-07-01

进出口银行四川省分行开展防范非法集资宣传月活动 世界微动态

2023-06-30

《忍者神龟:变种大乱斗》发预告 团队行侠仗义

2023-06-30

学霸情侣本科毕业共同直博 被校长写进致辞

2023-06-30

美丽的梯田不单单属于南方,北京也有……_焦点关注

2023-06-30

全球观速讯丨6尺7寸是多少厘米_6尺7

2023-06-30

2023年“Web3.0信任科技大会”召开 推动信任科技发展-全球最资讯

2023-06-30

自考会计证需要什么条件_零基础如何自考会计证|看点

2023-06-30

全球通讯!香水服务软文:香水是一种令人愉悦的香气,能够让人们感到舒适和放松

2023-06-30

已有200多家企业确认参展 首届链博会招商招展工作顺利 当前消息

2023-06-30

南阳宛城区红泥湾镇:广栽产业“梧桐树” 聚“才”引智话发展 每日速读

2023-06-30

天天百事通!山东五级71位书记共话乡村振兴齐鲁样板!掌声背后的精彩值得期待

2023-06-30

黄蜂记者:PJ-华盛顿正在寻求一份大合同 多支球队对他有意|当前动态

2023-06-30

车辆未到投保期是什么意思

2023-06-30

信用卡逾期可以只还本金吗?信用卡逾期警察上门抓人是真的吗?_聚看点 今日讯

2023-06-30

每日视点!非洲好物网购节助力“非品”入湘

2023-06-30

桃李面包(603866)6月29日主力资金净卖出129.17万元

2023-06-30

田园东方_关于田园东方介绍 环球消息

2023-06-30

“初二学生单独关教室8天”调查:家委会要求单独开班

2023-06-30

新西兰联储将加大对稳定币和加密数字资产的监管力度 世界时讯

2023-06-30

关注:美股三大指数涨跌不一 苹果继续向3万亿美元市值迈进

2023-06-30

服务营销精要:概念、策略和案例_对于服务营销精要:概念、策略和案例简单介绍

2023-06-30

会炒一些家常菜可以开个小饭馆吗?

2023-06-30

全球热头条丨公开招标现场监督_公开招标

2023-06-29

“海员比武”观察:“数智时代”需要什么样的船员?

2023-06-29

当前观点:如果国内房价大幅下跌,会发生什么问题?答案可能出乎你的预料

2023-06-29

讲述“党章守护人”张人亚的故事,《力量密码》七一公映|天天热消息

2023-06-29

天天热门:《消失的她》为什么票房大卖?陈思诚:借电影拿出一个生活的剖面

2023-06-29

全球最新:易大宗(01733)6月29日斥资约20.64万港元回购20.2万股

2023-06-29

快快评 | “ X 年级的暑假”不可怕,贩卖焦虑才可怕-世界速看

2023-06-29

看点:肇民科技:接受兆天投资调研

2023-06-29

上海交通大学强基计划录取结果查询官网入口2023-当前最新

2023-06-29

Counterpoint:补贴削减难阻 2023 Q1 中国电动车销量保持强劲增长 天天短讯

2023-06-29

天天速讯:全场起立鼓掌!曾用声音感动全网的董丽娜,毕业了!

2023-06-29

天天快播:贴现利息怎么计算案例_贴现利息怎么计算

2023-06-29

陈劲:如何锻造高水平企业家精神,是我们非常关心的_每日热门

2023-06-29

64岁麦当娜被紧急送医!因细菌感染进ICU,身体状况有在好转!|天天动态

2023-06-29

【全球速看料】Daniel Gergely Diffuse:一款独特的调制混合混响插件

2023-06-29

卵巢卵泡卵子的关系_吃什么对卵巢好对卵泡好_焦点快报

2023-06-29

正和生态: 截止2023年6月20日,公司股东人数13607名|每日观察

2023-06-29

中国银行女儿金金条价格今天多少一克(2023年06月29日)

2023-06-29

2023阿里云创峰会暨长三角(镇江)数字经济发展高峰论坛举办 环球速读

2023-06-29

央行6月27日开展2190亿元7天期逆回购操作 今日要闻

2023-06-29