从 Keras 功能模型中获取类标签
Posted
技术标签:
【中文标题】从 Keras 功能模型中获取类标签【英文标题】:Get class labels from Keras functional model 【发布时间】:2016-12-22 14:46:42 【问题描述】:我在 Keras 中有一个功能模型(来自 repo 示例的 Resnet50)。我用ImageDataGenerator
和flow_from_directory
数据对其进行了训练,并将模型保存到.h5
文件中。当我打电话给model.predict
时,我得到了一个类概率数组。但我想将它们与类标签相关联(在我的情况下 - 文件夹名称)。我怎样才能得到它们?我发现我可以使用model.predict_classes
和model.predict_proba
,但是我在Functional模型中没有这些功能,只有在Sequential中。
【问题讨论】:
【参考方案1】:y_prob = model.predict(x)
y_classes = y_prob.argmax(axis=-1)
按照here的建议。
【讨论】:
这给了我偏移量,但我已经有办法弄清楚了……如何获得标签名称? Keras 按字母顺序对标签(train 目录中的文件夹名称)进行排序。如果您有一个名为labels
的标签列表,则预测的标签名称将为:predicted_label = sorted(labels)[y_classes]
也可以调用model.predict_classes
检索多类输出向量中概率最高的类
嘿@Guillaume 能否请您指出提到此alphabetical ordering
的文档?这是一个非常重要的信息,我似乎在任何地方都找不到。谢谢
nm,在keras_preprocessing
中的directory_iterator.py
中找到它,代码为,`classes = [] for subdir in sorted(os.listdir(directory)): if os.path.isdir(os .path.join(directory, subdir)): classes.append(subdir) `【参考方案2】:
当使用 flow_from_directory 时,问题是如何解释概率输出。例如,如何将概率输出和类标签映射为 flow_from_directory 如何创建 one-hot 向量是先前未知的。
我们可以得到一个字典,将类标签映射到我们使用时作为输出得到的预测向量的索引
generator= train_datagen.flow_from_directory("train", batch_size=batch_size)
label_map = (generator.class_indices)
label_map 变量就是这样的字典
'class_14': 5, 'class_10': 1, 'class_11': 2, 'class_12': 3, 'class_13': 4, 'class_2': 6, 'class_3': 7, 'class_1': 0, 'class_6': 10, 'class_7': 11, 'class_4': 8, 'class_5': 9, 'class_8': 12, 'class_9': 13
然后由此可以推导出概率分数和类名之间的关系。
基本上,您可以通过此代码创建此字典。
from glob import glob
class_names = glob("*") # Reads all the folders in which images are present
class_names = sorted(class_names) # Sorting them
name_id_map = dict(zip(class_names, range(len(class_names))))
上述代码中的变量name_id_map也包含与flow_from_directory的class_indices函数得到的字典相同的字典。
希望这会有所帮助!
【讨论】:
在我的解释中,这回答了实际问题 - 获取类标签 我同意,我认为这应该是公认的答案。 拯救了我的一天 我们是否应该反过来定义字典?dict(zip(range(len(class_names),class_names, )))
这样就可以直接使用argmax的输出作为key了?【参考方案3】:
更新:这对较新的 Keras 版本不再有效。请使用 argmax()
,就像 Emilia Apostolova 的回答一样。
功能 API 模型只有 predict()
函数,用于分类将返回类概率。然后,您可以使用probas_to_classes()
实用程序函数选择最可能的类。示例:
y_proba = model.predict(x)
y_classes = keras.np_utils.probas_to_classes(y_proba)
这相当于顺序模型上的model.predict_classes(x)
。
原因是函数式 API 支持更通用的任务类别,而 predict_classes()
没有意义。
更多信息:https://github.com/fchollet/keras/issues/2524
【讨论】:
目前,np.utils.py 的代码(参见github.com/fchollet/keras/blob/master/keras/utils/np_utils.py)没有 probas_to_classes 方法。他们是否将其更改为其他功能?请帮帮我。 我遇到了和@noobalert 提到的一样的问题,它没有这个功能。 改用y_classes = y_proba.argmax(axis=-1)
AttributeError: 模块 'keras' 没有属性 'np_utils'
@Zach 为什么轴 = -1 而不是 1?【参考方案4】:
除了@Emilia Apostolova 回答来获取基本事实标签,来自
generator = train_datagen.flow_from_directory("train", batch_size=batch_size)
打电话
y_true_labels = generator.classes
【讨论】:
这似乎没有给出 OP 要求的标签名称。 正如我所说,这是对@Emilia Apostolova 答案的补充,除了她所说的之外,您还可以使用map
获取标签名称。特别是我用它来制作混淆矩阵。回到我发布这个的时候,我没有在她的回答中发表评论的声誉,因为我在这里发布了。【参考方案5】:
你必须使用你拥有的标签索引,这里是我为文本分类所做的:
# data labels = [1, 2, 1...]
labels_index = "website" : 0, "money" : 1 ....
# to feed model
label_categories = to_categorical(np.asarray(labels))
然后,对于预测:
texts = ["hello, rejoins moi sur skype", "bonjour comment ça va ?", "tu me donnes de l'argent"]
sequences = tokenizer.texts_to_sequences(texts)
data = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)
predictions = model.predict(data)
t = 0
for text in texts:
i = 0
print("Prediction for \"%s\": " % (text))
for label in labels_index:
print("\t%s ==> %f" % (label, predictions[t][i]))
i = i + 1
t = t + 1
这给出了:
Prediction for "hello, rejoins moi sur skype":
website ==> 0.759483
money ==> 0.037091
under ==> 0.010587
camsite ==> 0.114436
email ==> 0.075975
abuse ==> 0.002428
Prediction for "bonjour comment ça va ?":
website ==> 0.433079
money ==> 0.084878
under ==> 0.048375
camsite ==> 0.036674
email ==> 0.369197
abuse ==> 0.027798
Prediction for "tu me donnes de l'argent":
website ==> 0.006223
money ==> 0.095308
under ==> 0.003586
camsite ==> 0.003115
email ==> 0.884112
abuse ==> 0.007655
【讨论】:
【参考方案6】:可以直接在 keras 模型中保存标签的“列表”。这样,使用模型进行预测并且没有任何其他信息来源的用户可以自己执行查找。这是一个如何执行标签“注入”的虚拟示例
# 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")
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])
当用于预测时,该模型返回分数的张量和字符串标签的张量。这样的模型可以保存到h5。在这种情况下,文件包含标签。该模型也可以导出到 saved_model 并用于云端服务。
【讨论】:
【参考方案7】:要使用ImageDataGenerator
映射预测的类和文件名,我使用:
# Data generator and prediction
test_datagen = ImageDataGenerator(rescale=1./255)
test_generator = test_datagen.flow_from_directory(
inputpath,
target_size=(150, 150),
batch_size=20,
class_mode='categorical',
shuffle=False)
pred = model.predict_generator(test_generator, steps=len(test_generator), verbose=0)
# Get classes by max element in np (as a list)
classes = list(np.argmax(pred, axis=1))
# Get filenames (set shuffle=false in generator is important)
filenames = test_generator.filenames
我可以循环使用预测的类和相关的文件名:
for f in zip(classes, filenames):
...
【讨论】:
以上是关于从 Keras 功能模型中获取类标签的主要内容,如果未能解决你的问题,请参考以下文章
如何在多个标签问题中为 tensorflow 模型设置类权重?
如何在 keras flow_from_directory 中手动指定类标签?
用于多标签问题的 keras 模型的 scikit 学习链分类器的拟合方法错误
.h5 keras 模型到 coreml 的分类转换在 IOS 中不起作用
给定从图像名称到类标签的映射,如何使用keras ImageDataGenerator flow_from_directory?