Для обеспечения неотрицательных выходов используйте неотрицательную активацию, такую как 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)
...