我有大小为(100,100,4)的3级张量,我尝试使用自动编码器对其进行压缩和重构。我使用了出于身体原因的损失函数。从数学上来说是
L =-重叠(y_true,y_pred)+ | 1-范数(y_pred)^ 2 |
在代码中显示为:
def physical_loss(y_true,y_pred,norm=None):
return - tf.tensordot(y_true,y_pred,axes=([0,1,2],[0,1,2])) + tf.math.abs(1 - tf.tensordot(y_pred,y_pred,axes=([0,1,2],[0,1,2])))
第一项是输入和输出张量之间的重叠(我要最大化),第二项是防止输出张量爆炸,并且最理想的情况是范数为1(张量与其自身之间的重叠=范数)。因此理想情况下,损失降到-1(即y_pred = y_true和norm(y_pred)= 1)
我的模型是一个卷积自动编码器,可将大小减小到(50,50,4),(25,25,4)并重新构建。
cnn.compile(loss=physical_loss,optimizer="adam")
cnn.fit(x_train, x_train, epochs=num_epochs, batch_size=16,validation_data=(x_train,x_train))
现在,当我训练cnn时,损失会在16个时期内逐渐下降,最终达到val_loss = -0.67。但是,当我手动检查结果(即直接自己直接计算x_train和cnn.predict(x_train)之间的损失)时,平均得出0.75(正!)。
所以我的问题是评估时输出的keras / tensorflow是什么?
这可能是相关问题或其他问题,但是当我cnn.evaluate(x_train,x_train,batch_size = X)时,结果从+0.88到-0.88不等,介于两者之间的值取决于我如何选择批次大小X(得到选择无时相同-0.67,因此32)。我知道keras会分批完成所有操作,但这不应该改变总输出吗?同样,这也很难解释输出/培训的成功。
答案 0 :(得分:0)
我想我已经弄清楚了,问题在于keras / tensorflow期望一个已经矢量化的函数。上面的定义是针对3级张量的,但是keras / tensorflow总是处理批处理,因此3级张量的“列表”实际上不是列表,而是4级张量(第一个维度是“列表”)。
我发现矢量化这个损失函数并不是那么简单,但是找到了一个可行的解决方案,使用tf.map_fn(function,listed_tensor,dtype),其中list_tensor是提到的4级批处理。
def single_eval(duo):
return - tf.tensordot(duo[0],duo[1],axes=([0,1,2],[0,1,2])) + tf.keras.backend.abs(1 - tf.tensordot(duo[1],duo[1],axes=([0,1,2],[0,1,2])))
def physical_loss(y_true,y_pred,norm=None):
return tf.map_fn(single_eval,(y_true,y_pred),dtype=(tf.float32))
为了能够使用元组作为参数(即使用两个参数),必须指定dtype。