Как обеспечить монотонность для выходов (регрессии) модели в Keras? - PullRequest
0 голосов
/ 12 июня 2018

В настоящее время я работаю над проблемой, когда я предоставляю нейронную сеть с входной переменной a и другим входом x которая представляет собой монотонно возрастающую последовательность из N чисел.

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

a_input = Input(shape=[1], name='a')
x_input = Input(shape=[N], name='x')
nn = concatenate([a_input, x_input])
nn = Dense(100, activation='relu')(nn)
nn = Dense(N, activation='relu')(nn)
model = Model(inputs=[a_input, x_input], outputs=[nn])
model.compile(loss='mean_squared_error', optimizer="adam")

Я выполняю регрессию по входному пространству (где для каждого a последовательность x уникальна), и я хочу, чтобы сеть выводила монотонно возрастающую последовательность (неотрицательных) N чисел для каждого набора входов a и x .

Итак, я заметил, что до сих пор мои выводы не являются строго говоря монотонными, а выглядят так, как если бы вы «уменьшали».Под этим я подразумеваю для данного выбора a и x , если я хочу, чтобы мой выходной массив выглядел следующим образом:

[0, 0.5, 0.51, 0.7, 0.75, 0.9, 1.], 

Вместо этого я мог бы получить:

[0.001, 0.5, 0.48, 0.7, 0.75, 0.9, 1.].

Следовательно, я хотел бы знать, существуют ли стандартные способы или специальные инструменты, уже доступные в Keras, для ограничения моделей только монотонно увеличивающимся выводомпоследовательности?

1 Ответ

0 голосов
/ 12 июня 2018

Для обеспечения неотрицательных выходов используйте неотрицательную активацию, такую ​​как ReLU или сигмоид, в вашем выходном слое.

Я не знаю ни одного нейронного метода для обеспечения монотонности вваш вывод, но, на мой взгляд, разумным подходом было бы изменить выходное представление, чтобы сеть предсказывала разницу между двумя последовательными элементами.Например, вы можете преобразовать ваш выходной массив:

a=[0, 0.5, 0.51, 0.7, 0.75, 0.9, 1.]

в:

b=[0, 0.5, 0.01, 0.19, 0.05, 0.15, 0.1]

с b[0] = a[0] и b[i] = a[i]-a[i-1]для i>0.В этом контексте имеет смысл использовать рекуррентный слой в качестве выходного слоя, поскольку каждый выходной блок теперь зависит от предыдущих.Ваше исходное представление может быть легко восстановлено как a[0] = b[0] и a[i] = b[i]+a[i-1] для i>0, и результирующая последовательность будет монотонно увеличиваться, поскольку каждый вывод b[i] неотрицателен.


ОБНОВЛЕНИЕ 1 .LSTM должен вернуть полную последовательность.Вы можете попробовать построить модель следующим образом:

a_input = Input(shape=[1], name='a')
x_input = Input(shape=[N], name='x')
nn = concatenate([a_input, x_input])
nn = Dense(100, activation='relu')(nn)
nn = Dense(N, activation='relu')(nn)
nn = Lambda(lambda x: x[..., None])(nn)  # Output shape=(batch_size, nb_timesteps=N, input_dim=1)
nn = LSTM(1, return_sequences=True, activation='relu')(nn)  # Output shape=(batch_size, nb_timesteps=N, output_dim=1)
nn = Lambda(lambda x: keras.backend.squeeze(x, axis=-1))(nn)  # Output shape=(batch_size, N)
model = Model(inputs=[a_input, x_input], outputs=[nn])
model.compile(loss='mean_squared_error', optimizer="adam")

ОБНОВЛЕНИЕ 2 .LSTM с одним скрытым юнитом может быть недостаточно мощным.Я не уверен, поможет ли это, но вы можете попробовать добавить еще один слой LSTM с большим количеством единиц (т.е. 10) перед последним:

...
nn = Lambda(lambda x: x[..., None])(nn)  # Output shape=(batch_size, nb_timesteps=N, input_dim=1)
nn = LSTM(10, return_sequences=True)(nn)  # Output shape=(batch_size, nb_timesteps=N, output_dim=10)
nn = LSTM(1, return_sequences=True, activation='relu')(nn)  # Output shape=(batch_size, nb_timesteps=N, output_dim=1)
nn = Lambda(lambda x: keras.backend.squeeze(x, axis=-1))(nn)  # Output shape=(batch_size, N)
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...