Смесь моделей Keras

Можно ли внедрить MLP-смесь экспертной методологии в Keras? Не могли бы вы направить меня простым кодом в Keras для двоичной проблемы с 2 экспертами.

Ему нужно определить функцию стоимости, например:

g = gate.layers[-1].output
o1 = mlp1.layers[-1].output
o2 = mlp2.layers[-1].output

def ME_objective(y_true, y_pred):
    A = g[0] * T.exp(-0.5*T.sqr(y_true – o1))
    B = g[1] * T.exp(-0.5*T.sqr(y_true – o2))
    return -T.log((A+B).sum())  # cost

Ответ 1

Model

Вы можете определенно моделировать такую ​​структуру в Keras, уровень слияния, который позволяет комбинировать разные входы. Вот SSCCE, который, мы надеемся, сможет адаптироваться к вашей структуре

import numpy as np
from keras.engine import Merge
from keras.models import Sequential
from keras.layers import Dense
import keras.backend as K

xdim = 4
ydim = 1
gate = Sequential([Dense(2, input_dim=xdim)])
mlp1 = Sequential([Dense(1, input_dim=xdim)])
mlp2 = Sequential([Dense(1, input_dim=xdim)])


def merge_mode(branches):
    g, o1, o2 = branches
    # I'd have liked to write
    # return o1 * K.transpose(g[:, 0]) + o2 * K.transpose(g[:, 1])
    # but it doesn't work, and I don't know enough Keras to solve it
    return K.transpose(K.transpose(o1) * g[:, 0] + K.transpose(o2) * g[:, 1])


model = Sequential()
model.add(Merge([gate, mlp1, mlp2], output_shape=(ydim,), mode=merge_mode))
model.compile(optimizer='Adam', loss='mean_squared_error')

train_size = 19
nb_inputs = 3  # one input tensor for each branch (g, o1, o2)
x_train = [np.random.random((train_size, xdim)) for _ in range(nb_inputs)]
y_train = np.random.random((train_size, ydim))
model.fit(x_train, y_train)

Пользовательская цель

Вот реализация цели, которую вы описали. Есть несколько математических проблем, чтобы иметь в виду (см. Ниже).

def me_loss(y_true, y_pred):
    g = gate.layers[-1].output
    o1 = mlp1.layers[-1].output
    o2 = mlp2.layers[-1].output
    A = g[:, 0] * K.transpose(K.exp(-0.5 * K.square(y_true - o1)))
    B = g[:, 1] * K.transpose(K.exp(-0.5 * K.square(y_true - o2)))
    return -K.log(K.sum(A+B))

# [...] edit the compile line from above example
model.compile(optimizer='Adam', loss=me_loss)

Некоторая математика

Краткая версия: где-то в вашей модели, я думаю, должно быть хотя бы одно ограничение (возможно, два):

Для любого x, sum(g(x)) = 1

Для любого x, g0(x) > 0 and g1(x) > 0 # не может быть строго необходимо

Исследование домена

  • Если o1(x) и o2(x) бесконечно далеко от y:

    • член exp стремится к +0
    • A -> B -> +-0 в зависимости от знаков g0(x) и g1(x)
    • cost -> +infinite или nan
  • Если o1(x) и o2(x) бесконечно закрыть до y:

    • член exp имеет тенденцию к 1
    • A -> g0(x) и B -> g1(x)
    • cost -> -log(sum(g(x)))

Проблема заключается в том, что log определяется только на ]0, +inf[. Это означает, что для того, чтобы цель всегда определялась, должно существовать ограничение где-то обеспечивающее sum(A(x) + B(x)) > 0 для любого x. Более ограничительная версия этого ограничения будет (g0(x) > 0 и g1(x) > 0).

Convergence

Еще более важная проблема здесь состоит в том, что эта цель, похоже, не предназначена для сближения к 0. Когда mlp1 и mlp2 начинают правильно предсказать y (случай 2.), в настоящее время ничего не мешает оптимизатор, чтобы sum(g(x)) имел тенденцию к +infinite, чтобы сделать loss тенденцией к -inifinite.

В идеале нам бы хотелось loss -> 0, т.е. sum(g(x)) -> 1