【问题标题】:keras: unsupervised learning with external constraintkeras:具有外部约束的无监督学习
【发布时间】:2019-04-09 15:41:53
【问题描述】:

我必须在二进制类型(真/假)的未标记数据上训练一个网络,这听起来像是无监督学习。这是标准化数据的样子:

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) 参数:我的外部约束只是在 TrueFalse 的预测总数上,而不是在单个标签上。

我的问题是,对于这类问题是否有某种“标准”的方法,以及如何在 Keras 中实现。

可能的解决方案

我是否应该将y_true 随机分配为 0/1,使用 sigmoid 激活函数让网络返回 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

【问题讨论】:

  • 据我了解,您需要限制 True 的数量和 False 标签的数量。我说的对吗?
  • 没错。它基本上就像一个 k 均值聚类问题,其中我知道 a) k = 2; b) 每个集群中最终需要多少数据点。

标签: keras constraints loss-function unsupervised-learning


【解决方案1】:

最后,我采用了以下解决方案,该解决方案奏效了。

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.minK.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,它与我知道的每批总数非常接近。它实际上找到了两个组(真/假),它们占据了参数空间的预期不同部分。

【讨论】:

    猜你喜欢
    • 2014-04-20
    • 2013-03-24
    • 2019-02-20
    • 2010-12-22
    • 2017-06-27
    • 2017-12-08
    • 2018-10-01
    • 2017-08-11
    • 2021-10-17
    相关资源
    最近更新 更多