keras - keras:具有外部约束的无监督学习
问题描述
我必须在二进制类型(真/假)的未标记数据上训练一个网络,这听起来像是无监督学习。这是标准化数据的样子:
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 标签的总数有限制。这并不意味着我可以(y_true, y_pred)
根据需要在 Keras 中构建一个经典的自定义损失函数:我的外部约束只是在 和 的预测总数上,True
而False
不是在单个标签上。
我的问题是这种问题是否有某种“标准”方法,以及如何在 Keras 中实现。
可能的解决方案
我是否应该y_true
随机分配为 0/1,y_pred
使用 sigmoid 激活函数将网络返回为 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
解决方案
最后,我采用了以下解决方案,该解决方案有效。
df
1)在数据框中用一列定义批次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
与我知道的每批总数非常匹配的结果。它实际上找到了两个组(真/假),它们占据了参数空间的预期不同部分。
推荐阅读
- css - 在 css 中将一个装满图像的容器居中
- neural-network - LSTM RNN 的有趣结果:训练和验证数据的滞后结果
- node.js - 如何使用 Node.Js twit (Github) 进行直接消息 Twitter API
- c# - 我的查询在 SSMS 中很快,但在我的应用程序中超过 1 小时
- regex - 正则表达式匹配多个电话号码组合
- mysql - 竞态条件下的 INSERT-SELECT 和 UPDATE
- python - 从熊猫系列中去除非空白字符
- neural-network - 在没有历史数据的情况下训练神经网络
- grub2 - 如何使用带有 UEFI 的 GRUB2 来安全启动 Ubuntu?
- php - PHP QR Code 不会显示 UTF-8 字符