【问题标题】:save and load numpy ndarray as txt file (keras weights)将 numpy ndarray 保存并加载为 txt 文件(keras 权重)
【发布时间】:2021-03-23 19:14:23
【问题描述】:

我想在具有不同 python 版本的不同计算机上使用我的 keras 模型

我不想使用 Pickle 和 numpy.savez,因为它在不同的环境中会导致问题

我从这个开始,它工作正常

import json
import numpy as np
from tensorflow import keras

def save_mod(model, name="my_model"):
    with open(name + '.json', 'w') as fp:
        json.dump(model.to_json(), fp)

    # save weights
    model_weights = model.get_weights()
    return model_weights

def load_mod(model_weights_, name="my_model"):
    # load config
    with open(name + ".json", "r") as read_file:
        json_string = json.load(read_file)
    model_ = keras.models.model_from_json(json_string, custom_objects={})

    # load weights
    model_.set_weights(model_weights_)
    return model_

model = keras.models.load_model("segmentation.h5")
weights = save_mod(model)
loaded_model = load_mod(weights)

然后我尝试保存和加载权重

np.savetxt('weights.txt', weights, fmt='%s')
loaded_weights = np.fromfile('weights.txt')

print(len(weights)) 
print(len(loaded_weights))

>> 112
>> 31013

我得到了 112 和 31013,方法不起作用

with open('test.txt', 'wb') as f:
    np.savetxt(f, np.column_stack(weights), fmt='%1.10f')

它说>>所有输入数组必须具有相同的维数,但索引 0 处的数组有 4 维,索引 1 处的数组有 2 维

我终于做到了

class EncodeNumpy(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)


we = np.array(weights)
print(a.shape)
json_dump = json.dumps({'we': we}, cls=EncodeNumpy)

json_load = json.loads(json_dump)
a_restored = np.asarray(json_load["we"])
print(a_restored.shape)

model.set_weights(a_restored)

它给了我 (112,) 和 (112,) 形状的数组

但是 model.set_weights(a_restored) 返回

AttributeError: 'list' object has no attribute 'shape'

【问题讨论】:

    标签: python numpy keras numpy-ndarray


    【解决方案1】:

    最后一个错误

    AttributeError: 'list' object has no attribute 'shape'
    

    是由于numpy由于大小不匹配而无法将内部列表转换为ndarrays。

    查看示例:大小相同的列表

    np.array([[1, 2, 3], [1, 2, 3]])
    # array([[1, 2, 3],
    #       [1, 2, 3]])
    

    对比具有不同大小的列表

    np.array([[1, 2, 3], [1, 2]])
    # array([list([1, 2, 3]), list([1, 2])], dtype=object)
    

    这不是你想要的。这种情况下正确的做法是将每个内部列表分别转成ndarray,而不是ndarray放入一个列表中。

    例如,您可以执行以下操作:

    a_restored = [np.asarray(el) for el in json_load["we"]]
    

    您现在应该可以加载重量了。

    json_load = json.loads(json_dump)
    a_restored = [np.asarray(el) for el in json_load["we"]]
    model.set_weights(a_restored)
    

    【讨论】:

      猜你喜欢
      • 2017-07-13
      • 2018-07-15
      • 1970-01-01
      • 1970-01-01
      • 2018-04-26
      • 2020-06-11
      • 2013-03-24
      • 1970-01-01
      相关资源
      最近更新 更多