Модель Keras с несколькими выходами и функциями потерь, не сходящимися - PullRequest
0 голосов
/ 27 апреля 2020

В настоящее время я пытаюсь согласовать модель с двумя выходными данными: граница (двоичная классификация) и теги (классификация нескольких меток). Я работаю над постановкой проблемы НЛП и использую вложения Новостей Google.

Вывод «тегов» научился соответствовать набору данных, в то время как вывод «границы» всегда предсказывает 1. Потери, полученные из этого вывода всегда постоянна и достигает 16, в то время как другой выход начинается с 0,69 и в конечном итоге падает до 0,5.

Граничные классы вывода чрезвычайно искажены с соотношением около 1:49 ложь: истинные выборки. Итак, я добавил дополнительный вес для истинных образцов.

def create_model(size_sequence=50, size_w2v=300, size_context=3):
    size_window = size_context * 2 + 1

    inputs = keras.Input(shape=(size_sequence, size_w2v, size_window,))

    # CNN layers
    cnn_k4 = keras.layers.Conv2D(1, (4, size_w2v), activation='relu')(inputs)
    cnn_k3 = keras.layers.Conv2D(1, (3, size_w2v), activation='relu')(inputs)
    cnn_k2 = keras.layers.Conv2D(1, (2, size_w2v), activation='relu')(inputs)

    # Join outputs
    x = keras.layers.concatenate([cnn_k4, cnn_k3, cnn_k2], axis=1)
    x = keras.backend.squeeze(x, axis=2)

    # Run max-pool 1D
    x = keras.layers.MaxPool1D(pool_size=2)(x)

    # Flatten tensor
    x = keras.layers.Flatten()(x)
    x = tf.expand_dims(x, 1)

    # Pass through LSTM
    x = keras.layers.LSTM(256)(x)

    # Calculate attention
    w = keras.layers.Dense(256, activation='softmax')(x)
    x = keras.layers.Attention()([x, w])

    # Generate output
    x = keras.layers.Dense(128, activation='relu')(x)
    tags = keras.layers.Dense(15, activation='sigmoid')(x)
    bd = keras.layers.Dense(1, activation='softmax')(tags)

    # Generate model
    model = keras.Model(inputs=inputs, outputs=[bd, tags])

    return model
# Loss and gradient functions
_bce_loss_obj = keras.losses.BinaryCrossentropy()

def _loss(model, x, y_bd, y_tag, training, bd_wt_factor=98.5):
    # Get predictions
    pred_bd, pred_tag = model(x, training=training)

    # Calculate weighted boundary loss
    loss_bd = tf.nn.weighted_cross_entropy_with_logits(
        y_bd,
        tf.squeeze(pred_bd, axis=1),
        pos_weight=bd_wt_factor
    )
    loss_bd = keras.backend.sum(loss_bd)

    # Calculated tag loss
    loss_tag = _bce_loss_obj(y_true=y_tag, y_pred=pred_tag)

    # Return sum of losses
    return loss_bd + loss_tag

def grad(model, inputs, targets_bd, targets_tag):
    with tf.GradientTape() as tape:
        loss_value = _loss(model, inputs, targets_bd, targets_tag, training=True)

        grads = tape.gradient(loss_value, model.trainable_variables)
        grads = [grad if grad is not None else tf.zeros_like(var)
        for var, grad in zip(model.trainable_variables, grads)]

        return loss_value, grads
# Training
datasets = []
for book in glob.glob(fs.const.PATH_TRAIN_LIB + "/*.npz"):
    datasets.append(generate_dataset(book))
params = {
    'lr': 1e-4,
    'epochs': 10
}
optimizer = keras.optimizers.SGD(learning_rate=params['lr'])

model = create_model()

df_dict = {
    'Epoch Count': [],
    'Boundary FN': [],
    'Boundary FP': [],
    'Tag accuracy': [],
    'Average loss': [],
    'Epoch duration': [],
}

for epoch in range(params['epochs']):
    # Metrics
    epoch_duration = time.time()
    epoch_bd_fn = keras.metrics.FalseNegatives()
    epoch_bd_fp = keras.metrics.FalsePositives()
    epoch_tag_accuracy = keras.metrics.BinaryAccuracy()
    epoch_loss_avg = keras.metrics.Mean()

    for book in datasets:
        model.reset_states()
        for x, y_bd, y_tag in book:
            # Calculate and apply gradient
            loss_value, grads = grad(model, x, y_bd, y_tag)
            optimizer.apply_gradients(zip(grads, model.trainable_variables))

            # Track loss and metrics
            preds_bd, preds_tag = model(x, training=True)
            preds_bd = tf.squeeze(preds_bd, 1)

            epoch_bd_fn.update_state(y_bd, preds_bd)
            epoch_bd_fp.update_state(y_bd, preds_bd)
            epoch_tag_accuracy.update_state(y_tag, preds_tag)
            epoch_loss_avg.update_state(loss_value)

    # Print outputs
    df_dict['Epoch Count'].append(epoch + 1)
    df_dict['Boundary FN'].append(epoch_bd_fn.result().numpy())
    df_dict['Boundary FP'].append(epoch_bd_fp.result().numpy())
    df_dict['Tag accuracy'].append(epoch_tag_accuracy.result().numpy())
    df_dict['Average loss'].append(epoch_loss_avg.result().numpy())
    df_dict['Epoch duration'].append(time.time()-epoch_duration)
    IPython.display.clear_output()
    display(pd.DataFrame.from_dict(df_dict))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...