from keras.models import load_model
model = load_model('xx.h5')
使用Django调用Keras模型的接口,首先第一步是导入Keras模型,作为一个全局变量,注意是全局变量,很多教程教的都是,每调用一次接口都导入一次模型,自己试了就知道,导入模型是一个很耗时的过程,不利于高速计算。
这里有个大坑,当Django导入或者创建模型后,使用模型进行第一次预测,会出现漫长的初始化,正常来说,我们单线程运行时,会在生成模型的时候进行初始化,这是TensorFlow的一个坑。虽然之后再预测都不会出现长时间的初始化,但是还是要符合现实逻辑,在创建模型的时候进行初始化。
方法一:
import Keras
keras.backend.clear_session()
这个方法是网上的,我没试过
方法二:
model.predict(data_temp)
直接在创建模型后,立即进行一次数据预测,这个方法我感觉也简单粗暴。
这个才是Django结合Keras最坑人的地方。
为了预测方便,往往会把预测封装成接口,当点击选择文件后就会去调用接口进行计算,逻辑上没有任何问题,但是这里Keras会报错。
不同版本的Keras会有不同的报错,这里不放具体什么报错,都没有用。像是线程报错,什么tensor报错,一堆问题,其实就只是很简单的版本问题。
Keras更新后会有各种冲突,只要换回2.2.5版本即可。
pip uninstall keras
pip install keras==2.2.5
换完可能还是报错,但是不用怕,运行后看TensorFlow的初始化输出,有很多的警告(Warning),按照警告的提示的方法,把TensorFlow源码的方法替换成新版本的,替换完就可以放心地多次调用predict。
网上的解决方法是每次调用predict前重新导入模型,其实只要继续挖掘就能发现是版本更新的问题。
PS:旧版本的Keras的save和load存在区别,如果换回旧版,记得重新保存一次模型。
方法三:
今天发现了一个新的操作,特地更新一波,只要把模型放在线程里面就可以了,方法一和二都是把模型放在全局变量区进行调用。
如果是把模型放在线程中,模型只生存在线程中,那么操作就变成了监听队列,当我们有数据进来,就可以把数据插入到队列中,线程是个while(flag){ if (queue.havesomething){ … } }的结构,当监听到队列有数据,就可以获取数据,然后进行预测,那么也是实现了从程序运行开始只使用一个模型。
from keras.models import load_model
class MyThread(Thread):
def __init__(self, input_queue, output_queue ):
super().__init__()
self.input_queue = input_queue # 输入队列
self.output_queue = output_queue # 输出队列
self.model = load_model('xx.h5') # 导入模型
self.flag = True # 用于线程中断
def run(self):
while flag:
# 判断队列是否有数据
if not self.input_queue.empty():
data = self.input_queue.get()
result = self.model.predict(data)
self.output_queue.put(result)
这个方法可以避免重复初始化模型,有个大bug要考虑的就是线程初始化,有可能线程初始化很慢,然后你的电脑CPU又很快,就会出现主线程调用thread.run()时,线程还没初始化完全,就会炸程序,主线程可以加个sleep来延迟,给线程初始化一点时间。
很久没有用TensorFlow,电脑更新了好几次显卡驱动,今天运行了一下以前的代码,发现全部GG,一开始以为是CUDA和CUDNN变得不兼容,然后测了mxnet,发现还是可以运行,最后查到就是Keras这恶心的配置把GPU内存全部拿了==
报错:
Failed to get convolution algorithm. This is probably because cuDNN failed to initialize
解决代码:
在开头加上Keras配置
import tensorflow as tf
config = tf.compat.v1.ConfigProto(allow_soft_placement=True)
config.gpu_options.per_process_gpu_memory_fraction = 0.3
tf.compat.v1.keras.backend.set_session(tf.compat.v1.Session(config=config))
有人问我关于Django调用Keras的目录结构,首先按照原始的结构就行,Keras算法部分我是封装成一个keras_class类在model.py的文件里,然后我在model.py全局变量区域实体了一个model = keras_class(),另外在这个文件中又用一个predict函数封装了预测的部分,最后再全局变量区调用一次predict函数(原因看方法二)。
以上准备工作完成,接着在view.py中
from model import predict
# 注意model.py的文件位置,如果在某个xxx文件夹里面要补上‘xxx.model’
一般来说只会把你的模型当做黑匣子,你给它输入数据,它给你输出结果,所以view.py中只会用到predict这个封装好的函数
只要前面各种库兼容不冲突,你的算法没问题,理论上这些用这个方法不会出事
PS:各位敲代码的一定要考虑维护问题,不要即兴发挥,能封装起来就封装起来,不然将来自己维护会吃亏的(如果你是要给别人维护就当我没说,不过要保护好自己 )