Как добавить несколько бинарных классификаторов в конце MLP с помощью Keras?

Скажем, у меня есть MLP, который выглядит так:

model = models.Sequential()

model.add(layers.Dense(200, activation = "relu", input_dim=250))
model.add(layers.Dense(100, activation="relu"))
model.add(layers.Dense(75, activation="relu"))
model.add(layers.Dense(50, activation="relu"))
model.add(layers.Dense(17, activation = "softmax"))


model.compile(optimizer = optimizers.Adam(lr=0.001), 
         loss = "categorical_crossentropy", 
         metrics = ['MeanSquaredError', 'AUC' , 'accuracy',tf.keras.metrics.Precision()])

history = model.fit(X_train, y_train, epochs = 100,
               validation_data = (X_val, y_val))

Теперь я хочу, на последнем уровне, добавить двоичный классификатор для каждого из 17 классов, вместо того, чтобы выводить все 17 классов вместе с softmax; Это означает, что все бинарные классификаторы должны разветвляться от до последнего уровня. Возможно ли это сделать в Керасе? Я предполагаю, что это должен быть другой тип модели, а не Sequential()?

ИЗМЕНИТЬ:

Я понял, что не могу использовать Sequential, и изменил модель так, чтобы:

from tensorflow.keras import Input
from tensorflow.keras import Model
from tensorflow.keras.layers import Dense, Dropout

def test_model(layer_in):

    dense1 = Dense(200, activation = "relu") (layer_in)
    drop1 = Dropout(rate=0.02)(dense1)
    dense2 = Dense(100, activation="relu")(drop1)
    drop2 = Dropout(rate=0.02)(dense2)
    dense3 = Dense(75, activation="relu")(drop2)
    drop3 = Dropout(rate=0.02)(dense3)
    dense4 = Dense(50, activation="relu")(drop3)
    drop4 = Dropout(rate=0.01)(dense4)
    out = Dense(17, activation= "softmax")(drop4)
    return out


layer_in = Input(shape=(250,))
layer_out = test_model(layer_in)

model = Model(inputs=layer_in, outputs=layer_out)

plot_model(model, show_shapes=True)

введите здесь описание изображения

Итак, я предполагаю, что конечная цель состоит в том, чтобы иметь 17 двоичных слоев в конце с сигмовидной функцией, каждый из которых подключен к drop4...


person La Cordillera    schedule 14.06.2021    source источник
comment
Я не могу визуализировать вашу модель. Пожалуйста, нарисуйте архитектуру, и затем модель может быть нарисована соответствующим образом. Тем временем я дал вам идею о том, как вы можете создать модель с несколькими выходами. Теперь вы можете настроить модель в соответствии с вашим использованием   -  person Varun Singh    schedule 15.06.2021
comment
Вопрос @VarunSingh отредактирован, чтобы помочь вам с этим...   -  person La Cordillera    schedule 15.06.2021


Ответы (1)


В вашей проблеме вы пытаетесь использовать Sequential API для создания модели. Существуют ограничения для Sequential API, вы можете просто создать послойную модель. Он не может обрабатывать несколько входов/выходов. Его также нельзя использовать для ветвления.

Ниже текст с официального сайта Keras: https://keras.io/guides/functional_api/

Функциональный API упрощает работу с несколькими входными и выходными данными. Это невозможно обработать с помощью Sequential API.

Также вам будет полезна эта ссылка на стек: Последовательный и функциональный API Keras для нейронной сети многозадачного обучения

Теперь вы можете создать модель с помощью функционального API или подкласса модели.

В случае функционального API Ваша Модель будет

Предположим, что Результат_1 — это классификация с 17 классами. Результат_2 — это классификация с 2 классами, а Результат_3 — регрессия

input_layer=Input(shape=(250))
x=Dense(200, activation = "relu")(input_layer)
x=Dense(100, activation = "relu")(x)
x=Dense(75, activation = "relu")(x)
x=Dense(50, activation = "relu")(x)
output_1=Dense(17, activation = "softmax",name='output_1')(x)
output_2=Dense(3, activation = "softmax",name='output_2')(x)
output_3=Dense(1,name='output_3')(x)
model=Model(inputs=input_layer,outputs=[output_1,output_2,output_3])
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.01), 
              loss = {'output_1' : tf.keras.losses.CategoricalCrossentropy(),
                      'output_2' : tf.keras.losses.CategoricalCrossentropy(),
                      'output_3' : "mse"
                     },
              metrics = {'output_1' :'accuracy',
                         'output_2': 'accuracy',
                         'output_3' : tf.keras.metrics.RootMeanSquaredError()
                       }
             )

Обновление Ниже приведен код, предполагающий, что у вас есть 6 классов. Вы можете просто расширить то же самое для 17 классов.

input_layer=Input(shape=(250))
x=Dense(200, activation = "relu")(input_layer)
x=Dense(100, activation = "relu")(x)
x=Dense(75, activation = "relu")(x)
x=Dense(50, activation = "relu")(x)
output_1=Dense(1,activation='softmax', name='output_1')(x)
output_2=Dense(1,activation='softmax',name='output_2' )(x)
output_3=Dense(1,activation='softmax',name='output_3')(x)
output_4=Dense(1,activation='softmax', name='output_4')(x)
output_5=Dense(1,activation='softmax',name='output_5' )(x)
output_6=Dense(1,activation='softmax',name='output_6')(x)
model=Model(inputs=input_layer,outputs=[output_1,output_2,output_3])
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.01), 
              loss = {'output_1' : tf.keras.losses.SparseCategoricalCrossentropy(),
                         'output_2':  tf.keras.losses.SparseCategoricalCrossentropy(),
                         'output_3' : tf.keras.losses.SparseCategoricalCrossentropy(),
                         'output_4' :tf.keras.losses.SparseCategoricalCrossentropy(),
                         'output_5' :tf.keras.losses.SparseCategoricalCrossentropy(),
                         'output_6' :tf.keras.losses.SparseCategoricalCrossentropy()
                     },
              metrics = {'output_1' : 'accuracy',
                         'output_2':  'accuracy',
                         'output_3' : 'accuracy',
                         'output_4' :'accuracy',
                         'output_5' :'accuracy',
                         'output_6' :'accuracy'
                       }
             )
person Varun Singh    schedule 15.06.2021
comment
спасибо, что заглянули. Я не уверен, правильно ли я понимаю ваши три выхода? Не могли бы вы объяснить их немного подробнее? В вопросе я прошу иметь 17 двоичных выходов для каждого класса. Я не уверен, что это то, что я вернусь с вашим решением - person La Cordillera; 15.06.2021
comment
это просто выходные данные в последнем слое. - person Varun Singh; 15.06.2021
comment
Вы хотите 17 двоичных выходов. Значит, вы хотите 17 выходов двоичной классификации? И он может принадлежать нескольким классам? - person Varun Singh; 15.06.2021
comment
Да. Мои исходные данные имеют 17 меток, и мультиметка работает не очень хорошо (я предполагаю, что метки не являются взаимоисключающими). Поэтому я подумал, что, возможно, обходным путем будет вывод 17 двоичных классификаций, а не вывод softmax. - person La Cordillera; 15.06.2021
comment
И да, каждая точка данных может принадлежать разным меткам. - person La Cordillera; 15.06.2021
comment
Вы можете использовать потери и метрики в соответствии с вашим собственным вариантом использования. Но вот как это можно сделать - person Varun Singh; 15.06.2021
comment
Да, это работает. - person La Cordillera; 15.06.2021