【问题标题】:Attaching class labels to a Keras model将类标签附加到 Keras 模型
【发布时间】:2017-11-02 18:34:53
【问题描述】:

我正在使用 Keras Sequential 模型来训练多个多类分类器。

在评估时,Keras 输出一个置信度向量,我可以使用 argmax 从中推断出正确的类 id。然后我可以使用查找表来接收实际的类标签(例如字符串)。

目前解决方案是加载训练好的模型,然后单独加载查找表。由于我有相当多的分类器,我希望将两种结构都保存在一个文件中。

所以我正在寻找一种将实际标签查找向量集成到 Keras 模型中的方法。这将允许我拥有一个能够获取一些输入数据并为该数据返回正确类标签的分类器文件。

解决这个问题的一种方法是将模型和查找表都存储在一个元组中,然后将该元组写入一个pickle,但这似乎不是很优雅。

【问题讨论】:

  • 我想知道这不是内置的默认行为。没有标签的分类器模型有什么用?

标签: python keras


【解决方案1】:

所以我自己尝试了一个解决方案,这似乎有效。不过,我希望有更简单的东西。

我认为第二次打开模型文件并不是最佳选择。如果有人可以做得更好,一定要做到。

import h5py

from keras.models import load_model
from keras.models import save_model


def load_model_ext(filepath, custom_objects=None):
    model = load_model(filepath, custom_objects=None)
    f = h5py.File(filepath, mode='r')
    meta_data = None
    if 'my_meta_data' in f.attrs:
        meta_data = f.attrs.get('my_meta_data')
    f.close()
    return model, meta_data
   

def save_model_ext(model, filepath, overwrite=True, meta_data=None):
    save_model(model, filepath, overwrite)
    if meta_data is not None:
        f = h5py.File(filepath, mode='a')
        f.attrs['my_meta_data'] = meta_data
        f.close()

由于 h5 文件不接受 python 容器,您应该考虑将元数据转换为字符串。假设您的元数据以字典或列表的形式存在,您可以使用 json 进行转换。这还允许您在模型中存储更复杂的数据结构。

完整用法示例:

import json
import keras

# prepare model and label lookup
model = keras.Sequential();
model.add(keras.layers.Dense(10, input_dim=8, activation='relu'));
model.add(keras.layers.Dense(3, activation='softmax'))
model.compile()

filepath = r".\mymodel.h5"

labels = ["dog", "cat", "automobile"]

# save
labels_string = json.dumps(labels)
save_model_ext(model, filepath, meta_data=labels_string)

# load
loaded_model, loaded_labels_string = load_model_ext(filepath)
loaded_labels = json.loads(loaded_labels_string)

# label of class 0: "dog"
print(loaded_labels[0])

如果您希望为您的类提供字典,请注意 json 会将数字字典键转换为字符串,因此您必须在加载后将它们转换回数字。

【讨论】:

  • 接受我自己的答案,因为缺乏替代方案。如果有人提出更好的解决方案,我会接受他们的。
  • 我正在尝试解决同样的问题。但是您的解决方案对我不起作用:save_model_ext(mod1, filepath = 'test_model.h5', meta_data = {0: 'c1', 1: 'c2'}) 产生错误:``` TypeError: Object dtype dtype('O') has no native HDF5 equivalent ```您的函数期望meta_data 是什么类型?
  • 你好。您必须使用可以转换为 HDF5 的数据。 dtype="O" 表示您的数据包含一个显然无效的 Python 对象。如果我记得,我使用 python 字典没有问题。这真的是您尝试过的代码还是事实更复杂?
  • 我在使用字典时遇到了同样的错误('Object dtype dtype('O') has no native HDF5 equivalent')。 (Python 3.5)。还尝试使用列表并得到“TypeError: No conversion path for dtype: dtype('
  • @sh37211 感谢您的建议。我在编码字典时遇到了一些麻烦,所以我提供了一个使用 json 进行编码和解码的替代方案。这应该允许使用列表和字典。
【解决方案2】:

可以直接在 keras 模型中保存标签的“列表”。您需要使用 lambda。您只需将 lambda 的输出替换为包含标签的字符串张量。这是一个如何执行标签“注入”的虚拟示例

# assume we get labels as list
labels = ["cat","dog","horse","tomato"]
# here we start building our model with input image 299x299 and one output layer
xx = Input(shape=(299,299,3))
flat = Flatten()(xx)
output = Dense(shape=(4))(flat)
# here we perform injection of labels
tf_labels = tf.constant([labels],dtype="string")
# adding ? dimension to tf tensor
tf_labels = tf.tile(labels,[tf.shape(xx)[0],1])
output_labels = Lambda(lambda x: tf_labels,name="label_injection")(xx)
#and finaly creating a model
model=tf.keras.Model(xx,[output,output_labels])

此模型现在存储标签并返回它们。 tf.tile 的所有这些混乱都是必要的,因为形状 (N) 的 keras 层实际上是形状 (?,N) 的 tf 张量,我们添加了这个?标签张量的维度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2011-10-01
    • 2016-12-22
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    相关资源
    最近更新 更多