keras: обучение без учителя с внешними ограничениями - PullRequest
0 голосов
/ 06 ноября 2018

Я должен натренировать сеть на немаркированных данных двоичного типа (True / False), что звучит как неконтролируемое обучение. Вот как выглядят нормализованные данные:

array([[-0.05744527, -1.03575495, -0.1940105 , -1.15348956, -0.62664491,
    -0.98484037],
   [-0.05497629, -0.50935675, -0.19396862, -0.68990988, -0.10551919,
    -0.72375012],
   [-0.03275552,  0.31480204, -0.1834951 ,  0.23724946,  0.15504367,
     0.29810553],
   ...,
   [-0.05744527, -0.68482282, -0.1940105 , -0.87534175, -0.23580062,
    -0.98484037],
   [-0.05744527, -1.50366446, -0.1940105 , -1.52435329, -1.14777063,
    -0.98484037],
   [-0.05744527, -1.26970971, -0.1940105 , -1.33892142, -0.88720777,
    -0.98484037]])

Однако у меня есть ограничение на общее количество меток True в моих данных. Это не значит, что я могу построить классическую пользовательскую функцию потерь в Keras, принимая необходимые аргументы (y_true, y_pred): мое внешнее ограничение только на прогнозируемую сумму True и False, а не на отдельные метки.

Мой вопрос заключается в том, существует ли несколько «стандартный» подход к решению подобных проблем, и как он реализуется в Keras.

ВОЗМОЖНОЕ РЕШЕНИЕ

Должен ли я произвольно присвоить y_true как 0/1, вернуть по сети y_pred как 1/0 с функцией активации сигмоида, а затем определить мою функцию потерь как

sum_y_true = 500 # arbitrary constant known a priori

def loss_function(y_true, y_pred):
    loss = np.abs(y_pred.sum() - sum_y_true)
    return loss

1 Ответ

0 голосов
/ 19 ноября 2018

В итоге я выбрал следующее решение, которое сработало.

1) Определите пакеты в вашем фрейме данных df с помощью столбца batch_id, чтобы в каждом пакете Y_train была ваша идентичная «правда наземной партии» (в моем случае, общее количество Истинных этикеток в партии). Затем вы можете передать эти экземпляры вместе в сеть. Это можно сделать с помощью генератора:

def grouper(g,x,y):
    while True:
        for gr in g.unique():
            # this assigns indices to the entire set of values in g,
            # then subsects to all the rows in which g == gr
            indices = g == gr
            yield (x[indices],y[indices])

# train set
train_generator = grouper(df.loc[df['set'] == 'train','batch_id'], X_train, Y_train)
# validation set
val_generator = grouper(df.loc[df['set'] == 'val','batch_id'], X_val, Y_val)

2) определить пользовательскую функцию потерь, чтобы отследить, насколько близко общее число экземпляров, предсказанных как истинные, соответствует основной истине:

def custom_delta(y_true, y_pred):

loss = K.abs(K.mean(y_true) - K.sum(y_pred))

return loss


def custom_wrapper():

    def custom_loss_function(y_true, y_pred):
        return custom_delta(y_true, y_pred)

    return custom_loss_function

Обратите внимание, что здесь

a) Каждая метка y_true уже уже является суммой основной истины в нашей партии (потому что у нас нет индивидуальных значений). Вот почему y_true не суммируется;

b) K.mean на самом деле немного излишне, чтобы извлечь единственный скаляр из этого равномерного тензора, в котором все значения y_true в каждом пакете идентичны - K.min или K.max также будет работать, но у меня нет не проверял, быстрее ли их производительность.

3) Используйте fit_generator вместо fit:

fmodel = Sequential()
# ...your layers...
# Create the loss function object using the wrapper function above
loss_ = custom_wrapper()
fmodel.compile(loss=loss_, optimizer='adam')

history1 = fmodel.fit_generator(train_generator, steps_per_epoch=total_batches, 
    validation_data=val_generator,
    validation_steps=df.loc[encs.df['set'] == 'val','batch_id'].nunique(),
    epochs=20, verbose = 2)

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

Этот подход не только дал мне y_pred, который близко соответствует итоговым значениям, которые я знаю на партию. На самом деле он находит две группы (True / False), которые занимают разные части пространства параметров.

...