使用深度神经网络处理NER命名实体识别cs224d第7天:项目2-使用DNN课程处理NER问题项目描述地址什么是NER?命名实体识别(NER)是指识别文本中具有特定含义的实体,主要包括人名、地名、机构名、专有名词等。命名实体识别是信息抽取、问答系统、句法分析、机器翻译等应用领域,是结构化信息抽取的重要步骤。摘自BosonNLP如何识别?先说一下解题逻辑,再解释主要代码。如果您有兴趣,请到这里查看完整代码。代码是在Tensorflow下搭建一个只有一个隐藏层的DNN来处理NER问题。1.问题识别:NER是一个分类问题。给定一个词,我们需要根据上下文来判断,它属于以下四类中的哪一类?如果不属于,则类别为0,即不是实体,所以这是一个需要分为5类的问题:?Person(PER)?Organization(ORG)?Location(LOC)?Miscellaneous(MISC)我们的训练数据有两列,第一列是单词,第二列是标签。EUORGrejectsOGermanMISCPeterPERBRUSSELSLOC2.模型:接下来我们用深度神经网络训练它。模型如下:输入层的x^(t)是以x_t为中心的窗口大小为3的context上下文,x_t是one-hotvector,x_t和L交互后就是对应的词向量,词向量的长度为d=50:我们搭建一个只有一个隐藏层的神经网络,隐藏层的维度为100,y^为得到的预测值,维度为5:使用cross-熵计算误差:J求导各个参数:得到如下计算求导公式:求导在TensorFlow中是自动实现的。这里使用Adam优化算法更新梯度,不断迭代,使loss越来越小,直到收敛。3.具体实现在deftest_NER()中,我们进行max_epochs次迭代,每次,使用训练数据训练模型得到一对train_loss,train_acc,然后用这个模型预测验证数据,得到一对ofval_loss,predictions,我们选择最小的val_loss,并保存相应的参数权重,***我们要用这些参数来预测测试数据的类别标签:deftest_NER():config=Config()withtf.Graph().as_default():model=NERModel(config)#主类init=tf.initialize_all_variables()saver=tf.train.Saver()withtf.Session()assession:best_val_loss=float('inf')#***value,它的lossepoch的迭代次数best_val_epoch=0session.run(init)forepochinxrange(config.max_epochs):print'Epoch{}'.format(epoch)start=time.time()###train_loss,train_acc=model.run_epoch(会话,model.X_train,model.y_train)#1。将train数据放入迭代运行,得到loss和accuracyval_loss,predictions=model.predict(session,model.X_dev,model.y_dev)#2。使用此模型预测开发数据并获得损失和预测print'Trainingloss:{}'.format(train_loss)print'Trainingacc:{}'.format(train_acc)print'Validationloss:{}'.format(val_loss)ifval_lossconfig.early_stopping:break###confusion=calculate_confusion(config,predictions,model.y_dev)#3。放入dev的lable数据,计算prediction的混淆print_confusion(confusion,model.num_to_tag)print'Totaltime:{}'.format(time.time()-start)saver.restore(session,'./weights/ner.weights')#再次加载保存的权重,使用测试数据进行预测,得到预测结果print'Test'print'=-=-='print'Writingpredictionstoq2_test.predicted'_,predictions=model.predict(session,model.X_test,model.y_test)save_predictions(predictions,"q2_test.predicted")#保存预测结果if__name__=="__main__":test_NER()4.模型是如何训练的?首先导入数据训练、验证、测试:#Loadthetrainingsetdocs=du.load_dataset('data/ner/train')#Loadthedevset(fortuninghyperparameters)docs=du.load_dataset('data/ner/dev')#Loadthetestset(dummylabelsonly)docs=du.load_dataset('data/ner/test.masked')将词转化为one-hot向量,再转化为词向量:defadd_embedding(self):#TheembeddinglookupiscurrentlyonlyimplementedfortheCPUwithtf.device('/cpu:0'):embedding=tf.get_variable('Embedding',[len(self.wv),self.config.embed_size])#Lwindowinassignment=tf.nn.embedding_lookup(embedding,self.input_placeholder)#在L中,直接固定window=中窗口大小上下文的wordvectortf.reshape(window,[-1,self.config.window_size*self.config.embed_size])returnwindow构建神经层,包括使用xavier初始化第一层,L2正则化和dropout减少过拟合联合处理:defadd_model(self,window):withtf.variable_scope('Layer1',initializer=xavier_weight_init())asscope:#使用initializer=xavier初始化***层W=tf.get_variable(#***层有W,b1,h'W',[self.config.window_size*self.config.embed_size,self.config.hidden_??size])b1=tf.get_variable('b1',[self.config.hidden_??size])h=tf.nn.tanh(tf.matmul(window,W)+b1)ifself.config.l2:#L2regularizationforWtf.add_to_collection('total_loss',0.5*self.config.l2*tf.nn.l2_loss(W))#0.5*self.config.l2*tf.nn.l2_loss(W)withtf.variable_scope('Layer2',initializer=xavier_weight_init())asscope:U=tf.get_variable('U',[self.config.hidden_??size,self.config.label_size])b2=tf.get_variable('b2',[self.config.label_size])y=tf.matmul(h,U)+b2ifself.config.l2:tf.add_to_collection('total_loss',0.5*self.config.l2*tf.nn.l2_loss(U))output=tf.nn.dropout(y,self.dropout_placeholder)#returnoutput,variable_scopes都有dropoutreturnoutput关于L2正则化和dropout,如何减少过拟合的问题,可以看看这篇博客,总结的简单明了使用交叉熵计算loss:defadd_loss_op(self,y):cross_entropy=tf.reduce_mean(#1.关键步骤:loss由交叉熵定义tf.nn.softmax_cross_entropy_with_logits(y,self.labels_placeholder))#y为模型预测值,计算crossentropytf.add_to_collection('total_loss',cross_entropy)#Storesvalueinthecollectionwiththegivenname.#collectionsarenotsets,itispossibletoaddavaluetoacollectionseveraltimes.loss=tf.add_n(tf.get_collection('total_loss'))#Addsallinputtensorselement-wise.inputs:AlistofTensorwithsameshapeandtypereturnloss接着用AdamOptimizer把lossMinimize:defadd_training_op(self,loss):optimizer=tf.train.AdamOptimizer(self.config.lr)global_step=tf.Variable(0,name='global_step',trainable=False)train_op=optimizer.minimize(loss,global_step=全局步骤)#2。关键步骤:使用AdamOptimizer最小化loss,所以比较关键的是lossreturntrain_op每次训练后,得到最小loss对应的weights。这样就解决了NER的分类问题。当然,为了提高准确率等问题,还是需要查阅文献来学习。下次,先实现一个RNN。