基于LSTM/BLSTM/CNNBLSTM的命名实体识别任务代码的解析--2

程序主要包括:

main.py   主程序

model.py  神经网络模型设置程序

pretreatment.py :数据预处理程序

 

2、model.py

在该py文件中,主要有一个父类,三个子类,分别对应网络:LSTM、BLSTM、CNNBLSTM

现在对各个部分进行介绍

1)父类

由于篇幅的原因相关的程序代码在git上,大家自行下载对照阅读

从main.py文件通过run()函数进入model.py文件,所以再看代码的时候,找到def run()函数,下面对run()函数中的主要代码进行介绍:

def run(self,train_x,train_y,train_lens,valid_x,valid_y,valid_lens,test_x,test_y,test_lens,FLAGS=None):
    self.lr = FLAGS.lr
    self.training_iter = FLAGS.train_steps  ##迭代的次数,即训练的轮数epoch
    self.train_file_path = FLAGS.train_data  ##训练语料的路径
    self.test_file_path = FLAGS.valid_data   ##开发集语料的路径
    self.display_step = FLAGS.display_step   ##控制运行多少步进行训练情况的显示

    pred = self.inference(self.X,self.X_len)  ##预测
    cost = self.loss(pred)  ##评估

 

传入到函数的参数分别是训练语料、开发集语料、测试语料的字所对应的id、标签以及各个句子的长度(具体的样式见上一篇博客的文章末尾)

 

pred = self.inference(self.X,self.X_len)  ##得出的是预测的标签值,该函数在各个子类中进行实现

 

 cost = self.loss(pred)  ##loss的计算,即损失值的计算

损失函数(loss function)是用来估量你模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的鲁棒性就越好

 

with tf.name_scope('train'):
    global_step = tf.Variable(0,name='tr_global_step',trainable=False)
    optimizer = tf.train.AdamOptimizer(learning_rate=self.lr).minimize(cost,global_step=global_step)

tf.name_scope可以让变量有相同的命名

Global_step.name() :train/tr_global_step  ???

模型的保存:

with tf.name_scope('saveModel'):
    localtime = time.strftime("%X-%Y-%m-%d", time.localtime())
    saver = tf.train.Saver()
    save_dir = FLAGS.model_dir + localtime + '/'
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)

在tensorflow中,保存模型和加载模型所用到的类是tf.train.Saver(),在保存好模型之后,一般会出现下面四个文件 :

.meta文件:保存了tensorflow的graph,包括variables、operations、collections等等

checkpoint files:二进制文件,保存了所有weights,biases,gradient and all the other variables的值。也就是上图中的.data-00000-of-00001和.index文件。.data文件包含了所有的训练变量。以前的TensorFlow版本是一个ckpt文件,现在就是这两个文件了。与此同时,Tensorflow还有一个名为checkpoint的文件,只保存最新检查点文件的记录,即最新的保存路径。

import tensorflow as tf

saver = tf.train.Saver()

sess = tf.Session()

saver.save(sess, save_dir, global_step=step) ##保存模型

#save_dir:保存路径单位

#global_step:给定一个数字,用于保存文件时tensorflow帮你命名,主要是说明了迭代了多少次后保存了

(此处模型保存的介绍来源其他博客)

 

模型的训练:

with tf.Session() as sess:
    max_acc,bestIter = 0.,0
    sess.run(tf.global_variables_initializer())
    for epoch in xrange(self.training_iter):
        for train,num in self.get_batch_data(train_x,train_y,train_lens,self.batch_size,(1-self.drop_rate)):
            _,step,trans_matrix,loss,predication = sess.run([optimizer,global_step,self.transition,cost,pred],feed_dict=train)
            tags_seqs,_ = self.viterbi_decode(num,predication,train[self.X_len],trans_matrix)
            f = self.evaluate(num,tags_seqs,train[self.Y],train[self.X_len])
            print 'Iter {}: mini-batch loss={:.6f}, acc={:.6f}'.format(step, loss, f)
        save_path = saver.save(sess, save_dir, global_step=step)
        print "[+] Model saved in file: %s" % save_path

        if epoch%self.display_step == 0:
            rd,loss,acc = 0,0.,0.
            for valid,num in self.get_batch_data(valid_x,valid_y,valid_lens,self.batch_size):
                trans_matrix,_loss,predication = sess.run([self.transition,cost,pred],feed_dict=valid)
                loss += _loss
                tags_seqs,_ = self.viterbi_decode(num,predication,valid[self.X_len],trans_matrix)
                f = self.evaluate(num,tags_seqs,valid[self.Y],valid[self.X_len])

                acc += f
                rd += 1

            loss /= rd
            acc /= rd
            if acc >max_acc:
                max_acc = acc
                bestIter = step
            print '----------{}----------'.format(time.strftime("%Y-%m-%d %X", time.localtime()))
            print 'Iter {}: valid loss(avg)={:.6f}, acc(avg)={:.6f}'.format(step, loss, acc)
            print 'round {}: max_acc={} BestIter={}\n'.format(epoch, max_acc, bestIter)
    print 'Optimization Finished!'

    pred_test_y = []
    acc,loss,rd = 0.,0.,0
    for test,num in self.get_batch_data(test_x,test_y,test_lens,self.batch_size,shuffle=False):
        trans_matrix,_loss,predication = sess.run([self.transition,cost,pred],feed_dict=test)
        loss += _loss
        rd += 1
        tags_seqs,tags_scores = self.viterbi_decode(num,predication,test[self.X_len],trans_matrix)
        f = self.evaluate(num,tags_seqs,test[self.Y],test[self.X_len])
        acc += f
        pred_test_y.extend(tags_seqs)
    acc /= rd
    loss /= rd
    return pred_test_y,loss,acc

 

训练时显示出的结果如下图所示:

sess.run(tf.global_variables_initializer()) :初始化模型的参数

global_variables_initializer 返回一个用来初始化计算图中所有global variable的op:

函数中调用了variable_initializer()和global_variables()

global_variables()返回一个 Variable list,里面保存的是gloabal variables

variable_initializer()将Variable list中的所有Variable取出来,将其variable.initializer属性做成一个op group

然后看Variable类的源码可以发现,variable.initializer就是一个assign op

所以:

sess.run(tf.global_variables_initializer())就是run了所有global Variable的assign op,这就是初始化参数的本来面目

https://blog.csdn.net/qq_26591517/article/details/80601225

 

nitialize_all_variables已被弃用,更新成tf.global_variables_initializer

写了init = tf.global_variables_initializer()后不会执行,要在session里加上sess.run(init)后才会执行,否则会有一系列报错

 

今天暂时写到这里了,后续继续更新

猜你喜欢

转载自blog.csdn.net/yangfengling1023/article/details/81135811