因为工作需要,同一个进程会使用到两个Keras Model, 我是通过写了一个KerasUtil类,然后创建了多个此类对象,以加载不同的Model:
kerasutil_merge = KerasUtil(rawtextpath=r'va_new/model/rawcontent/vamergebinary.csv',
lstmmodelpath=r'va_new/model/vamergebinarybilstm.h5',
modeltype='bilstm')
kerasutil_added = KerasUtil(rawtextpath=r'va_new/model/rawcontent/vaaddedbinary.csv',
lstmmodelpath=r'va_new/model/vaaddedbinarybilstm.h5',
modeltype='bilstm')
但是在运行的时候遇到问题了,如果两个model同时加载,并做predict的尝试,那么就发生疑似多model加载导致的issue:
Tensor embedding_2_input:0, specified in either feed_devices or fetch_devices was not found in the Graph
Exception ignored in: <bound method BaseSession._Callable.del of <tensorflow.python.client.session.BaseSession._Callable object at 0x000001B47CA91240>>
Traceback (most recent call last):
File “D:\python36\lib\site-packages\tensorflow\python\client\session.py”, line 1398, in del
self._session._session, self._handle, status)
File “D:\python36\lib\site-packages\tensorflow\python\framework\errors_impl.py”, line 519, in exit
c_api.TF_GetCode(self.status.status))
tensorflow.python.framework.errors_impl.InvalidArgumentError: No such callable handle: 1875572934464
一开始看到这个是慌张的,因为之前仅仅使用一个model的时候,是没有问题的,只是Flask提供Web API加载遇到了一些问题(请见我另一篇简书)
仔细想了想,应该是底层的Tensorflow在处理多Model切换时,懵逼了,是否每次predict的时候,遇到异常就尝试重新load呢?
代码修复的尝试如下:
def predictcategory(self, sentence, threshold=0.5):
self.initialforlstm()
cleantext = gensimutil.cleardatafordoc2vector(sentence)
twt = [cleantext]
twt = self.tokenizer.texts_to_sequences(twt)
# padding the tweet to have exactly the same shape as `embedding_2` input
twt = pad_sequences(twt, maxlen=80, dtype='int32', value=0)
# To avoid below exception:Tensor embedding_1_input:0,
# specified in either feed_devices or fetch_devices was not found in the Graph
try:
categoryresult = self.lstmmodel.predict(twt, batch_size=1, verbose=2)[0]
except Exception as e:
logger.info(e)
keras.backend.clear_session()
self.lstmmodel = load_model(self.modelpath)
categoryresult = self.lstmmodel.predict(twt, batch_size=1, verbose=2)[0]
logger.info('raw sentence: {0}'.format(sentence))
boolDict = {0: 'Negative', 1: 'Positive'}
if len(categoryresult) > 2:
logger.info('category is {0}, similarity: {1}'.format(self.categorydict[np.argmax(categoryresult)+1],
categoryresult[np.argmax(categoryresult)]))
result = {'categorycode': np.argmax(categoryresult) + 1,
'categoryname': self.categorydict[np.argmax(categoryresult)+1],
'similarity': categoryresult[np.argmax(categoryresult)]}
else:
result = 0
if np.argmax(categoryresult) == 1 and categoryresult[np.argmax(categoryresult)] > threshold:
result = 1
logger.info('category is {0}, similarity: {1}'.format(boolDict[result],
categoryresult[result]))
result = {'categorycode': result,
'categoryname': boolDict[result],
'similarity': categoryresult[result]}
return result
其中,这个是关键,即蒙圈了,就重新加载模型,效率或许低了些,但能够让程序run下去
try:
categoryresult = self.lstmmodel.predict(twt, batch_size=1, verbose=2)[0]
except Exception as e:
logger.info(e)
keras.backend.clear_session()
self.lstmmodel = load_model(self.modelpath)
categoryresult = self.lstmmodel.predict(twt, batch_size=1, verbose=2)[0]