美文网首页Python机器学习python自学
解决多个Keras Model实例同时加载,导致运行结果混乱的问

解决多个Keras Model实例同时加载,导致运行结果混乱的问

作者: blade_he | 来源:发表于2018-12-18 16:23 被阅读11次

    最近做的一项任务,需要同时运行多个二分类模型(如果这些二分类结果稳定了,即可转为一个多标签分类模型)。

    问题描述

    假定分类模型分别为A和B
    示例代码如下:

    # 将kerasutil_A 与kerasutil_B 作为全局变量,可以一次加载多次应用,从而提升性能
    kerasutil_A = KerasUtil(rawtextpath=r'A.csv',
                                lstmmodelpath=r'A.h5',
                                modeltype='bilstm')
    
    kerasutil_B = KerasUtil(rawtextpath=r'B.csv',
                                lstmmodelpath=r'B.h5',
                                modeltype='bilstm')
    

    具体的使用方式为:

    resultlist = []
    if categoryid == 'A':
        resultlist = kerasutil_A.predictcategory(sentence)
    elif categoryid == 'B':
        resultlist = kerasutil_B.predictcategory(sentence)
    

    但是在运行过程中,发现莫名奇妙的问题。
    比如有两个与类别B相关的句子:
    sentence_B_1, Positive
    sentence_B_2, Negative

    在多个model实例加载完毕后,
    如果按照sentence_B_1, sentence_B_2的顺序去跑,会得到sentence_B_1:Positive, sentence_B_2依然是Positive的结果;
    如果按照sentence_B_2, sentence_B_1的顺序去跑,会得到sentence_B_2:Negative, sentence_B_1依然是Negative的结果;

    但是如果只在一个进程加载Model B,则无论sentence_B_1, sentence_B_2按照什么顺序去跑,结果都是正确的。

    事实上,KerasUtil中没有任何静态或类级别的变量,都是实例级别的变量(每个实例中的属性都是使用独立的内存地址):

    class KerasUtil:
        def __init__(self, rawtextpath, lstmmodelpath, modeltype='lstm', multiplelabels=False):
            self.max_fatures = 2000
            self.modelrawtextpath = rawtextpath
            self.modelpath = lstmmodelpath
            self.modeltype = modeltype
            self.multiplelabels = multiplelabels
            self.data = None
            self.lstmmodel = None
            self.tokenizer = None
            self.initialtokenizer()
    

    data,lstmmodel, tokenizer都是在实例化的时候,才去赋值,经过跟踪调试堆栈信息,也能够得出kerasutil_A与kerasutil_B中的属性都是独立,拥有各自特征的值。

    这确实是太奇怪了!!

    目前尚不能确定是否是底层的Tensorflow对同一个进程的多个模型的应用,导致出现类似问题。(模型内的张量出现混乱?)
    不过事实证明,基于Tensorflow的Keras在多模型同时运行时,无论是单纯的执行predict方法(容易出现错误,需要clear session或者重新加载模型),还是执行某个模型的分类结果,都是诡异的。

    解决方案

    将模型的初始化与加载逻辑,放置在应用业务分类的函数内。
    每次函数执行完毕,模型对象都会被释放。

    def confirmwithmachinelearning(categoryid, sentencelist):
        # 用多个model时,出于性能考虑,之前是作为全局变量加载的
        # 之后发现同时run多个文档的的时候,结果居然与单独去跑某个文档的结果不一致
        # 猜测是否是底层的tensorflow的张量信息缺失或互相窜了
        # 目前这种方式是在函数内加载对应模型,虽然慢了几秒,但结果是准确的
        kerasutil = None
        if categoryid == 'A':
            kerasutil = KerasUtil(rawtextpath=r'A.csv',
                                  lstmmodelpath=r'A.h5',
                                  modeltype='bilstm')
        if categoryid == 'B':
            kerasutil = KerasUtil(rawtextpath=r'B.csv',
                                  lstmmodelpath=r'B.h5',
                                  modeltype='bilstm')
    
        for sentence in sentencelist:
            resultlist = kerasutil.predictcategory(sentence)
        ...
    

    经过验证,诡异的现象消失了,类别结果不会因为多模型加载而造成不同的结果。
    附注:这种方式对于相对较小的模型,不会带来性能方面的明显损耗,但是对于较大的多个模型共用,建议API分离,才能通过全局变量一次加载多次应用的benefit

    相关文章

      网友评论

        本文标题:解决多个Keras Model实例同时加载,导致运行结果混乱的问

        本文链接:https://www.haomeiwen.com/subject/mellkqtx.html