机器学习模型现在比以往任何时候都更多地用于生产。Keras是一种用于创建强大的机器学习和深度学习模型的流行库。然而,这些模型的训练过程通常计算量大且耗时,具体取决于处理的实际数据和模型架构。有些模型需要几周到几个月的时间来训练。因此,能够在本地存储模型并在需要预测时再次检索它们变得至关重要。但是,如果由于某种原因保存的模型无法正确加载怎么办?我会尝试根据自己的经验给出答案。我不会详细介绍如何使用和保存Keras模型,只是假设读者熟悉该过程并直接了解如何处理加载时的意外模型行为。也就是说,在训练完存储在Model变量中的Keras模型后,我们希望按原样保存它,以便下次加载它时我们可以跳过训练而只进行预测。我的首选方法是保存模型的权重,这些权重在模型创建之初随机化,并随着模型的训练而更新。所以我点击了model.save_weights("model.h5")。创建一个“model.h5”文件,其中包含模型学习的权重。接下来,在另一个会话中,我使用与之前相同的架构重建模型,并使用new_model.load_weights("model.h5")加载我保存的训练权重。一切似乎都很好。只是我点击new_model.predict(test_data)后,得到的准确率是零,不知道为什么。事实证明,模型未能做出正确预测的原因有很多。在本文中,我尝试总结最常见的原因以及解决方法。1.首先仔细检查数据。我知道这似乎很明显,但是从磁盘重新加载模型时的疏忽可能会导致性能下降。例如,如果您正在构建语言模型,则应确保在每个新会话中执行以下操作:重新检查类标签的顺序。如果将它们映射到数字,请仔细检查每个类标签在每个会话中是否具有相同的数字。如果您使用list(set())函数进行检索,则可能会发生这种情况,该函数每次都以不同的顺序返回您的标签。这最终可能会打乱您的标签预测。检查数据集。如果您的测试数据不在另一个文件中,请检查训练测试拆分是否不是随机的,这样每次您进行预测时,您都是在对不同的数据进行预测,因此您的预测准确性最终会不一致。当然,根据您在哪个领域工作,您可能会遇到其他与数据相关的问题。但是,始终检查数据表示的一致性。2.指标问题错误或结果不一致的另一个原因是准确性指标的选择。在构建模型并保存其权重时,我们通常会执行以下操作:defbuild_model(max_len,n_tags):input_layer=Input(shape=(max_len,))output_layer=Dense(n_tags,activation='softmax')(input_layer)model=模型(输入层,输出层)返回模型模型=build_model()model.compile(optimizer="adam",loss="sparse_categorical_crossentropy",metrics=["accuracy"])model.fit(..)model.save_weights("model.h5")如果我们需要在新的会话/脚本中打开它,我们需要执行以下操作:defbuild_model(max_len,n_tags):input_layer=Input(shape=(max_len,))output_layer=Dense(n_tags,activation='softmax')(input_layer)model=Model(input_layer,output_layer)returnmodelmodel=build_model()model.compile(optimizer="adam",loss="sparse_categorical_crossentropy",metrics=["accuracy"])model.load_weights("model.h5")model.evaluate()这可能会引发错误,具体取决于所使用的特定Keras/Tensorflow版本。编译模型并选择“准确性”作为指标时会出现问题。Keras认可准确度的各种定义:“稀疏分类准确度”、“分类准确度”等;根据您使用的数据,不同的定义是首选解决方案。这是因为如果我们将指标设置为“准确度”,Keras将尝试分配一种特定的准确度类型,具体取决于它认为最适合数据分布的准确度类型。它可能会在不同的运行中推断出不同的准确性指标。这里最好的解决方案是始终显式设置准确性指标,而不是让Keras选择它。例如,将model.compile(optimizer="adam",loss="sparse_categorical_crossentropy",metrics=["accuracy"])替换为:model.compile(optimizer="adam",loss="sparse_categorical_crossentropy",metrics=["sparse_categorical_accuracy"])3.随机性当使用与之前相同的数据重新训练Keras神经网络时,您很少会两次得到相同的结果。这是由于Keras中的神经网络在初始化其权重时使用了随机性,因此每次运行时权重的初始化方式不同,因此在学习过程中这些权重的更新方式不同,因此不太可能得到相同精度的结果。如果由于某种原因需要在训练前均衡权重,可以在代码前设置随机数生成器:fromnumpy.randomimportseedseed(42)fromtensorflowimportset_random_seedset_random_seed(42)Keras中使用了numpy随机种子,而对于Tensorflow后端,我们需要将其自身的随机数生成器设置为相等的种子。此代码片段将确保您的神经网络权重在每次运行代码时均等初始化。4.注意自定义层的使用Keras提供了很多层(Dense、LSTM、Dropout、BatchNormalizaton等),但有时我们想对模型中的数据进行特定的操作,却没有定义具体的层为了它。通常,Keras提供两种类型的层:Lambda和基础层类。但是要小心这两层,尤其是当你以json格式保存你的模型模式时。Lambda层的棘手部分是序列化限制。由于它是用Python字节码序列化保存的,它只能加载到保存它的同一环境中,即它不可移植。遇到这个问题,通常建议重写keras.layers.Layer层,或者只保存它的权重,从头开始重建模型,而不是保存整个模型。5.自定义对象很多时候你会想使用自定义函数来应用于数据,或者计算损失/准确度等指标。Keras通过允许我们在保存/加载模型时指定其他参数来允许这种用法。假设我们想用之前保存的模型加载我们自己的特殊损失函数:model=load_model("model.h5",custom_objects={"custom_loss":custom_loss})新环境,因为默认情况下,保存模型时不会记住这些功能。即使我们保存模型的整个模式,它也会保存这个自定义函数的名称,但是函数体是我们需要额外提供的。6.全局变量初始值设定项如果您使用Tensorflow1.x作为后端,这一点尤其重要——对于许多应用程序,您可能仍然需要该后端。运行tf1.x会话时,需要运行tf.global_variables_initializer(),它会随机初始化所有变量。这样做的一个副作用是,当您尝试保存模型时,它可能会重新初始化所有权重。您可以通过运行以下命令手动停止此行为:fromkeras.backendimportmanual_variable_initializationmanual_variable_initialization(True)结语本文列出了最常阻止您的Keras模型在新环境中正确加载的几个因素。有时这些问题会导致不可预知的结果,而在其他情况下它们只会抛出错误。它们发生的时间和方式在很大程度上也取决于您使用的Python版本以及Tensorflow和Keras的版本,因为其中一些不兼容,从而导致意外行为。希望在阅读本文后,您下次遇到此类问题时会知道从哪里开始。原标题:为什么加载以前保存的Keras模型会产生不同的结果:经验教训,作者:KristinaPopova
