在keras的自定义损失函数中做一些数学运算
doing some math in custom loss function in keras
我创建了一个具有三个密集层的 keras 顺序模型,我只是创建了一个自定义损失函数,如下所示:
def lossFunctionality(y_t, y_p):
# 'y_t' shape is (bach_size, 500)
# 'y_p' shape is (bach_size, 256) (output of last layer)
# 'v' is np array of shape (500, 256)
p = K.exp(K.dot(y_p, K.transpose(v)))
sp = K.sum(p,axis=1)
sp = K.expand_dims(sp, axis=1)
sp = K.tile(sp,(1, len(v)))
soft = p/sp
soft=K.clip(soft, 0.0000001, 0.9999999)
obj = K.categorical_crossentropy(soft, y_t)
return obj
有了这个损失函数,一切都很好。
但现在假设我对 'y_p' 中的每条记录都有特定的 'v' 数组,并且我想执行代码的第 5 行以获得 'y_p' 与记录特定 'v'数组。换句话说,我有 bach_size 个 'v' 向量的数量,我想将 'y_p' 中的每条记录生成到那个特定的 'v' 数组。我想要的是显示波纹管:
def lossFunctionality(y_t, y_p):
tempArray=[]
for record in y_p:
tempArray.append(K.exp(K.dot(record, K.transpose(v))))
p=np.array(tempArray)
sp = K.sum(p,axis=1)
sp = K.expand_dims(sp, axis=1)
sp = K.tile(sp,(1, len(v)))
soft = p/sp
soft=K.clip(soft, 0.0000001, 0.9999999)
obj = K.categorical_crossentropy(soft, y_t)
return obj
但我收到错误“'Tensor' 对象不可迭代。”
我怎样才能以正确的方式实现我的损失函数
非常感谢您的帮助
你真的不应该在损失函数中迭代张量或使用列表、numpy 数组等。
理想情况下,您必须使用 backend 函数来完成所有事情,这些函数可以与张量一起正常工作。
如果我理解正确,你需要的是一个 batch_dot
函数,如果你真的需要转置 "v",也许与 permute_dimensions
相关联。
我假设您有一个“v”向量列表,对吧?我会回答它,就好像我代码中的“v”是一个形状为 (batch_size, 500, 256)
.
的 numpy 数组
import keras.backend as K
--------------
#transform v in a tensor
vTens = K.variable(v) #maybe having vTens already instanced and transposed outside the loss function would result in better performance (if it's constant)
#transposing v without changing the batch dimension
vTrans = K.permute_dimensions(vTens,(0,2,1))
#doing a batch dot
dotResult = K.batch_dot(y_p,vTrans,axes=[1,2])
在batch_dot
中,考虑了轴1和2,而轴0是批量大小,将保持不变。
关于您的功能的重要说明:
您将无法让 y_p
和 y_t
具有不同的维度。这简直让人无法接受。您的模型预测必须与您的真实值具有完全相同的形状。
肯定会在 fit
方法(或任何其他训练方法)中出现错误,告诉您尺寸不匹配。
在达到损失函数之前,您确实需要一个层来转换输出,因此y_p
和y_t
具有相同的维度。
为此,使用 LambdaLayer
model.add(LambdaLayer(transformOutput, output_shape=(500,))
其中 transformOutput
是您之前描述的函数,也使用张量。
def transformOutput(x):
#transform v in a tensor
vTens = K.variable(v) #maybe having vTens already instanced and transposed outside the loss function would result in better performance (if it's constant)
#transposing v without changing the batch dimension
vTrans = K.permute_dimensions(vTens,(0,2,1))
#doing a batch dot
return K.batch_dot(x,vTrans,axes=[1,2])
我创建了一个具有三个密集层的 keras 顺序模型,我只是创建了一个自定义损失函数,如下所示:
def lossFunctionality(y_t, y_p):
# 'y_t' shape is (bach_size, 500)
# 'y_p' shape is (bach_size, 256) (output of last layer)
# 'v' is np array of shape (500, 256)
p = K.exp(K.dot(y_p, K.transpose(v)))
sp = K.sum(p,axis=1)
sp = K.expand_dims(sp, axis=1)
sp = K.tile(sp,(1, len(v)))
soft = p/sp
soft=K.clip(soft, 0.0000001, 0.9999999)
obj = K.categorical_crossentropy(soft, y_t)
return obj
有了这个损失函数,一切都很好。
但现在假设我对 'y_p' 中的每条记录都有特定的 'v' 数组,并且我想执行代码的第 5 行以获得 'y_p' 与记录特定 'v'数组。换句话说,我有 bach_size 个 'v' 向量的数量,我想将 'y_p' 中的每条记录生成到那个特定的 'v' 数组。我想要的是显示波纹管:
def lossFunctionality(y_t, y_p):
tempArray=[]
for record in y_p:
tempArray.append(K.exp(K.dot(record, K.transpose(v))))
p=np.array(tempArray)
sp = K.sum(p,axis=1)
sp = K.expand_dims(sp, axis=1)
sp = K.tile(sp,(1, len(v)))
soft = p/sp
soft=K.clip(soft, 0.0000001, 0.9999999)
obj = K.categorical_crossentropy(soft, y_t)
return obj
但我收到错误“'Tensor' 对象不可迭代。” 我怎样才能以正确的方式实现我的损失函数 非常感谢您的帮助
你真的不应该在损失函数中迭代张量或使用列表、numpy 数组等。
理想情况下,您必须使用 backend 函数来完成所有事情,这些函数可以与张量一起正常工作。
如果我理解正确,你需要的是一个 batch_dot
函数,如果你真的需要转置 "v",也许与 permute_dimensions
相关联。
我假设您有一个“v”向量列表,对吧?我会回答它,就好像我代码中的“v”是一个形状为 (batch_size, 500, 256)
.
import keras.backend as K
--------------
#transform v in a tensor
vTens = K.variable(v) #maybe having vTens already instanced and transposed outside the loss function would result in better performance (if it's constant)
#transposing v without changing the batch dimension
vTrans = K.permute_dimensions(vTens,(0,2,1))
#doing a batch dot
dotResult = K.batch_dot(y_p,vTrans,axes=[1,2])
在batch_dot
中,考虑了轴1和2,而轴0是批量大小,将保持不变。
关于您的功能的重要说明:
您将无法让 y_p
和 y_t
具有不同的维度。这简直让人无法接受。您的模型预测必须与您的真实值具有完全相同的形状。
肯定会在 fit
方法(或任何其他训练方法)中出现错误,告诉您尺寸不匹配。
在达到损失函数之前,您确实需要一个层来转换输出,因此y_p
和y_t
具有相同的维度。
为此,使用 LambdaLayer
model.add(LambdaLayer(transformOutput, output_shape=(500,))
其中 transformOutput
是您之前描述的函数,也使用张量。
def transformOutput(x):
#transform v in a tensor
vTens = K.variable(v) #maybe having vTens already instanced and transposed outside the loss function would result in better performance (if it's constant)
#transposing v without changing the batch dimension
vTrans = K.permute_dimensions(vTens,(0,2,1))
#doing a batch dot
return K.batch_dot(x,vTrans,axes=[1,2])