有人在加载Keras保存的模型时遇到了“AttributeError: 'str' object has no attribute 'decode'”错误吗?

99

训练完成后,我使用了Keras整个模型和仅权重的保存方法

model.save_weights(MODEL_WEIGHTS) and model.save(MODEL_NAME)

模型和权重已成功保存,没有错误。我可以使用model.load_weights轻松地成功加载权重,但当我尝试通过load_model加载保存的模型时,出现了错误。

File "C:/Users/Rizwan/model_testing/model_performance.py", line 46, in <module>
Model2 = load_model('nasnet_RS2.h5',custom_objects={'euc_dist_keras': euc_dist_keras})
File "C:\Users\Rizwan\AppData\Roaming\Python\Python36\site-packages\keras\engine\saving.py", line 419, in load_model
model = _deserialize_model(f, custom_objects, compile)
File "C:\Users\Rizwan\AppData\Roaming\Python\Python36\site-packages\keras\engine\saving.py", line 321, in _deserialize_model
optimizer_weights_group['weight_names']]
File "C:\Users\Rizwan\AppData\Roaming\Python\Python36\site-packages\keras\engine\saving.py", line 320, in <listcomp>
n.decode('utf8') for n in
AttributeError: 'str' object has no attribute 'decode'

我以前从未遇到过这个错误,而且我曾经成功地加载了任何模型。我正在使用带有tensorflow后端的Keras 2.2.4和Python 3.6。我的训练代码是:

from keras_preprocessing.image import ImageDataGenerator
from keras import backend as K
from keras.models import load_model
from keras.callbacks import ReduceLROnPlateau, TensorBoard, 
ModelCheckpoint,EarlyStopping
import pandas as pd

MODEL_NAME = "nasnet_RS2.h5"
MODEL_WEIGHTS = "nasnet_RS2_weights.h5"
def euc_dist_keras(y_true, y_pred):
return K.sqrt(K.sum(K.square(y_true - y_pred), axis=-1, keepdims=True))
def main():

# Here, we initialize the "NASNetMobile" model type and customize the final 
#feature regressor layer.
# NASNet is a neural network architecture developed by Google.
# This architecture is specialized for transfer learning, and was discovered via Neural Architecture Search.
# NASNetMobile is a smaller version of NASNet.
model = NASNetMobile()
model = Model(model.input, Dense(1, activation='linear', kernel_initializer='normal')(model.layers[-2].output))

#    model = load_model('current_best.hdf5', custom_objects={'euc_dist_keras': euc_dist_keras})

# This model will use the "Adam" optimizer.
model.compile("adam", euc_dist_keras)
lr_callback = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=5, min_lr=0.003)
# This callback will log model stats to Tensorboard.
tb_callback = TensorBoard()
# This callback will checkpoint the best model at every epoch.
mc_callback = ModelCheckpoint(filepath='current_best_mem3.h5', verbose=1, save_best_only=True)
es_callback=EarlyStopping(monitor='val_loss', min_delta=0, patience=4, verbose=0, mode='auto', baseline=None, restore_best_weights=True)

# This is the train DataSequence.
# These are the callbacks.
#callbacks = [lr_callback, tb_callback,mc_callback]
callbacks = [lr_callback, tb_callback,es_callback]

train_pd = pd.read_csv("./train3.txt", delimiter=" ", names=["id", "label"], index_col=None)
test_pd = pd.read_csv("./val3.txt", delimiter=" ", names=["id", "label"], index_col=None)

 #    train_pd = pd.read_csv("./train2.txt",delimiter=" ",header=None,index_col=None)
 #    test_pd = pd.read_csv("./val2.txt",delimiter=" ",header=None,index_col=None)
#model.summary()
batch_size=32
datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = datagen.flow_from_dataframe(dataframe=train_pd, 
directory="./images", x_col="id", y_col="label",
                                              has_ext=True, 
class_mode="other", target_size=(224, 224),
                                              batch_size=batch_size)
valid_generator = datagen.flow_from_dataframe(dataframe=test_pd, directory="./images", x_col="id", y_col="label",
                                              has_ext=True, class_mode="other", target_size=(224, 224),
                                              batch_size=batch_size)

STEP_SIZE_TRAIN = train_generator.n // train_generator.batch_size
STEP_SIZE_VALID = valid_generator.n // valid_generator.batch_size
model.fit_generator(generator=train_generator,
                    steps_per_epoch=STEP_SIZE_TRAIN,
                    validation_data=valid_generator,
                    validation_steps=STEP_SIZE_VALID,
                    callbacks=callbacks,
                    epochs=20)

# we save the model.
model.save_weights(MODEL_WEIGHTS)
model.save(MODEL_NAME)
if __name__ == '__main__':
   # freeze_support() here if program needs to be frozen
    main()
10个回答

184

我采用的解决方案是降级 h5py 包(在我的情况下降到版本 2.10.0),显然仅将 Keras 和 Tensorflow 回退到正确版本是不够的。


5
关于这个问题,可以在以下链接中获取更多信息:https://github.com/tensorflow/tensorflow/issues/44467 - alexhg
3
根据alexhg提供的链接,我们将有人致力于使TF与h5py版本号大于等于3兼容,但这只会在TF 2.5或之后的版本中实现。这个问题出现的原因是因为TensorFlow无法与h5py v3及更高版本兼容。目前最新的2.x.y版本是2.10.0。 - Ben Butterworth
1
成功了!我试图加载一个格式为.h5的keras模型,然后将其保存为tflite模型。 - Freddy Daniel
很遗憾,对于2 GHz四核Intel Core i5处理器,版本2.10.0没有cp95轮,会出现不支持的错误,而3.1.0则存在问题。 - Arpan Saini
这对我有用,非常感谢! 一般的经验法则是检查Tensorflow、Keras或其他主要库,并与其他依赖项如numpy、h5py、opencv等相关联。使用常识和直觉调整版本。 - Mahmood Hussain
你需要哪个版本的Tensorflow和Keras才能使其正常工作? - Niels Hoogeveen

124

我使用以下命令降级了我的h5py软件包,

pip install 'h5py==2.10.0' --force-reinstall

重新启动了我的IPython内核,然后它就正常工作了。


4
使用这个确切的命令会因缺少RECORD文件而导致OSError错误。不过,使用conda install 'h5py==2.10.0'命令就可以了。 - moefasa
重启内核是关键。 - om471987
肯定有助于在Google Colab上使用。 - Elvin Aghammadzada

23

对我来说,h5py的版本比我之前使用的更好。
通过将版本设置为2.10.0解决了这个问题。


12
使用以下命令降级h5py软件包以解决问题:
pip install h5py==2.10.0 --force-reinstall

6

使用TF格式文件进行保存,不要使用h5py:save_format='tf'。在我的情况下:

model.save_weights("NMT_model_weight.tf",save_format='tf')

TypeError: save_weights() got an unexpected keyword argument 'save_format' - maciejwww

5

我有同样的问题,解决方法是在load_model中加入compile=False

model_ = load_model('path to your model.h5',custom_objects={'Scale': Scale()}, compile=False)
sgd = SGD(lr=1e-3, decay=1e-6, momentum=0.9, nesterov=True)
model_.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])

为什么我们需要 custom_objects={'Scale': Scale()} - hola
2
无论如何,compile = False 给了我这个错误:File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/saving.py", line 229, in load_model model_config = json.loads(model_config.decode('utf-8')) AttributeError: 'str' object has no attribute 'decode' - hola
1
我有同样的问题,但是compile=False无关紧要 :( - Marco Pestrin
2
它没有帮助。 - MichalSzczep

3

这可能是由于从不同版本的keras保存模型导致的。当我加载通过tensorflow.keras生成的模型(类似于keras 2.1.6 for tf 1.12)时,我遇到了相同的问题,而该模型来自于keras 2.2.6。

您可以使用model.load_weights加载权重,并从您想要使用的keras版本重新保存完整模型。


4
但是同样的错误也发生在我用来训练模型的那台电脑上。 - Rizwan
1
是的,您说得对,使用 model.load_weights 可以实现这一点,但我想知道为什么不能加载整个模型架构。 - Rizwan

2
我找到的解决方案是:

以下是具体步骤:

pip3 uninstall keras
pip3 uninstall tensorflow
pip3 install --upgrade pip3
pip3 install tensorflow
pip3 install keras

1

在我的环境中,即使安装了tensorflow==2.4.1、h5py==2.1.0和Python 3.8,我仍然遇到了这个错误。解决方法是将Python版本降级到3.6.9。


0

降级 Python、TensorFlow、Keras 和 h5py 可以解决这个问题。

python -> 3.6.2

pip install tensorflow==1.3.0
pip install keras==2.1.2
pip install 'h5py==2.10.0' --force-reinstall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接