Python Keras/Tensorflow:带减法的损失函数-

Python Keras/Tensorflow:带减法的损失函数-,python,tensorflow,keras,Python,Tensorflow,Keras,我对keras或tensorflow并不完全陌生,但这是我的第一次深度潜水。我试着编写我自己的损失函数,这是与keras相比的mean\u absolute\u percentage\u error的一个微小变化。我可以用numpy来写: def np_平均值_相对百分比_误差(y_真,y_pred): err=np.abs((y_-true-y_-pred)/np.abs(y_-true)) diff=np.subtract(np.one(err.shape,dtype=float),err)

我对keras或tensorflow并不完全陌生,但这是我的第一次深度潜水。我试着编写我自己的损失函数,这是与keras相比的
mean\u absolute\u percentage\u error
的一个微小变化。我可以用numpy来写:

def np_平均值_相对百分比_误差(y_真,y_pred):
err=np.abs((y_-true-y_-pred)/np.abs(y_-true))
diff=np.subtract(np.one(err.shape,dtype=float),err)
返回100。*np.平均值(差值,轴=-1)
但是我不能用keras/tensorflow编写它,我当前(不工作)的版本看起来像下面的代码片段。如果有人完成了实现,或者告诉我如何用常数一个元素一个元素地减去张量,我将非常感激

第1版:

def平均相对百分比错误(y_真,y_pred):
err=K.abs((y_-true-y_-pred)/K.clip(K.abs(y_-true),K.epsilon(),None))
一个=K.one_like(err)
diff=K.update\u sub(一个,错误)
返回100。*K.平均值(差值,轴=-1)
回溯(最近一次呼叫最后一次):
文件“E:/Projekte/*ai/train.py”,第66行,在
列车(epochs=20,前缀='test\U new\U loss\U fn')
文件“E:/Projekte/i*/ai/train.py”,第46行,列车中
模型=创建模型((形状[0],形状[1],3),主干=主干,丢失功能=丢失fn,冻结主干=主干冻结,lr=学习率)
文件“E:\Projekte\*\ai\model\\uuuu init\uuuuu.py”,第48行,在create\u model中
损失=损失函数,度量=[平均相对百分比误差,度量。平均绝对误差])
文件“C:\Users\**\.conda\envs\tfGPU2\lib\site packages\keras\engine\training.py”,第342行,在compile中
样品(重量、面罩)
文件“C:\Users\***\.conda\envs\tfGPU2\lib\site packages\keras\engine\training\u utils.py”,第404行,以加权形式
分数数组=fn(y_真,y_pred)
文件“E:\Projekte\ai\p\ai\utils\loss.py”,第8行,平均相对百分比错误
diff=K.update\u sub(一个,e)
文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\keras\backend\tensorflow\u backend.py”,第999行,在更新子文件中
返回tf.assign_sub(x,减量)
文件“C:\Users\***f\.conda\envs\tfGPU2\lib\site packages\tensorflow\python\ops\state\u ops.py”,第160行,分配子文件
返回参考赋值(值)
AttributeError:“Tensor”对象没有属性“assign\u sub”
第2版:

def平均相对百分比错误(y_真,y_pred):
err=K.abs((y_-true-y_-pred)/K.clip(K.abs(y_-true),K.epsilon(),None))
one=K.变量(K.one_like(err))
diff=K.update\u sub(一个,错误)
返回100。*K.平均值(差值,轴=-1)
回溯(最近一次呼叫最后一次):
文件“E:/Projekte/*/ai/train.py”,第66行,在
列车(epochs=20,前缀='test\U new\U loss\U fn')
文件“E:/Projekte/*/ai/train.py”,第46行,列车中
模型=创建模型((形状[0],形状[1],3),主干=主干,丢失功能=丢失fn,冻结主干=主干冻结,lr=学习率)
文件“E:\Projekte\*\ai\model\\uuuu init\uuuuu.py”,第48行,在create\u model中
损失=损失函数,度量=[平均相对百分比误差,度量。平均绝对误差])
文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\keras\engine\training.py”,第342行,编译
样品(重量、面罩)
文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\keras\engine\training\u utils.py”,第404行,以加权方式显示
分数数组=fn(y_真,y_pred)
文件“E:\Projekte\*\ai\utils\loss.py”,第7行,平均相对百分比错误
one=K.变量(K.one_like(err))
变量中的文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\keras\backend\tensorflow\u backend.py”,第402行
v=tf.Variable(value,dtype=tf.as_dtype(dtype),name=name)
文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\tensorflow\python\ops\variables.py”,第183行,在调用中__
返回cls.\u变量\u v1\u调用(*args,**kwargs)
文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\tensorflow\python\ops\variables.py”,第146行,在变量调用中
聚合=聚合)
文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\tensorflow\python\ops\variables.py”,第125行,在
上一个\u getter=lambda**kwargs:默认\u变量\u创建者(无,**kwargs)
文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\tensorflow\python\ops\variable\u scope.py”,第2444行,在默认的\u variable\u creator中
预期形状=预期形状,导入范围=导入范围)
文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\tensorflow\python\ops\variables.py”,第187行,在u调用中__
返回super(VariableMetaclass,cls)。\调用(*args,**kwargs)
文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\tensorflow\python\ops\variables.py”,第1329行,在u init中__
约束=约束)
文件“C:\Users\*\.conda\envs\tfGPU2\lib\site packages\tensorflow\python\ops\variables.py”,第1472行,位于\u init \u from \u args
自身(初始值)
ValueError:初始值必须指定一个形状:张量(“丢失/密集\u 3\u丢失/类似于1的值:0”,形状=(?,?),数据类型=浮点32)

不需要复杂的技巧,您的损失可以通过以下方式实现:

def mean_relative_percentage_error(y_true, y_pred):
    err = K.abs((y_true - y_pred) / K.clip(K.abs(y_true), K.epsilon(), None))
    diff = 1.0 - err
    return 100. * K.mean(diff, axis=-1)

这在
1.0-err
计算中使用广播。

您只需执行diff=1.0-errVersion 2是正确的,因为损失函数希望处理张量。正如@MatiasValdenegro所说,您可以直接使用常量值
1
来利用广播的基本特性,而不需要像
这样的人
。感谢您的建议,这是我的“第一个”解决方案,但损失非常小(小于0,我预计大约>100)。所以我认为这是一个减法的问题,但它看起来更像一个数学问题。