Отримайте ярлики класів від функціональної моделі Keras


76

У мене є функціональна модель у Керасі (Resnet50 із прикладів репо). Я навчав її ImageDataGeneratorі flow_from_directoryдані і зберіг модель в .h5файл. Коли я телефоную, model.predictя отримую масив імовірностей класу. Але я хочу пов’язати їх із мітками класів (у моєму випадку - іменами папок). Як я можу їх отримати? Я виявив, що можу використовувати model.predict_classesі model.predict_proba, але я не маю цих функцій у функціональній моделі, лише в послідовній.

Відповіді:


77
y_prob = model.predict(x) 
y_classes = y_prob.argmax(axis=-1)

Як запропоновано тут .


20
Це дає мені компенсацію, але я вже мав спосіб зрозуміти це ... як отримати назву етикетки?
Трейказ

10
Keras сортує мітки (назви папок у каталозі поїздів) за алфавітом. Якщо у вас є список названих міток labels, передбачувана назва мітки буде такою:predicted_label = sorted(labels)[y_classes]
Гійом

1
Ви також можете зателефонувати, model.predict_classesщоб отримати найвищий клас ймовірності в
мультикласовому

1
Привіт @Guillaume, не могли б ви, будь ласка, вказати мені документи, де це alphabetical orderingзгадується? Це дуже важлива інформація, яку я просто ніде не знаходжу. спасибі
ameet chaubal

1
nm, знайшов його в directory_iterator.pyу keras_preprocessingз кодом як, `classes = [] для піддиректору в сортуванні (os.listdir (каталог)): якщо os.path.isdir (os.path.join (каталог, піддиректорія)): classes.append (subdir) `
ameet chaubal

46

Коли використовується протокол flow_from_directory, проблема полягає в тому, як інтерпретувати вихідні дані імовірності. Як і в тому, як зіставити вихідні дані імовірності та мітки класів, як те, як flow_from_directory створює одноразові вектори, раніше невідомо.

Ми можемо отримати словник, який відображає мітки класів на індекс вектора прогнозування, який ми отримуємо як результат, коли ми використовуємо

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 у наведеному вище коді також містить той самий словник, що і той, що отриманий із функції class_indices потоку_від_каталогу.

Сподіваюся, це допомагає!


8
У моїй інтерпретації це відповідає на актуальне питання - отримання ярликів класів
CSquare

4
Я згоден, я думаю, що це має бути прийнятою відповіддю.
ганебний

2
Врятував мій день <3
Рохіт Свамі

14

ОНОВЛЕННЯ: Це більше не діє для нових версій Keras. Будь ласка, використовуйте, argmax()як у відповіді Емілії Апостолової.

Функціональні моделі 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


3
Наразі код для np.utils.py (див. Github.com/fchollet/keras/blob/master/keras/utils/np_utils.py ) не має методу probas_to_classes. Вони змінили це на якусь іншу функцію? Будь ласка, допоможи мені.
noobalert

1
У мене така ж проблема, як і @noobalert, про яку вже згадувалося, у неї немає функції.
Стівен Джонсон,

8
використовувати y_classes = y_proba.argmax(axis=-1)замість цього
Зак

3
AttributeError: модуль 'keras' не має атрибута 'np_utils'
Юрген К.

@Zach Чому вісь = -1, а не 1?
WaterRocket8236

6

На додаток до відповіді @Emilia Apostolova, щоб отримати основні ярлики правди, від

generator = train_datagen.flow_from_directory("train", batch_size=batch_size)

просто зателефонуйте

y_true_labels = generator.classes

1
Здається, це не дає назв ярликів, про що запитує OP.
Moondra

Як я вже говорив, це доповнення до відповіді @Emilia Apostolova, використовуючи це на додаток до сказаного вами, ви можете отримати імена етикеток просто використовуючи map. Зокрема, я використав це для створення матриці плутанини. Коли я опублікував це, у мене не було репутації коментувати її відповідь, тому що я розмістив тут.
Хемерсон Такан,

2

Ви повинні використовувати індекс міток, який у вас є, ось що я роблю для класифікації тексту:

# 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

2

Можна безпосередньо зберегти "список" міток у моделі 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. У цьому випадку файл містить мітки. Цю модель також можна експортувати до збереженої моделі та використовувати для обслуговування в хмарі.


1

Для зіставлення передбачуваних класів та імен файлів 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):
    ...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.