【发布时间】:2018-04-09 11:19:21
【问题描述】:
看我的 Keras 自定义损失函数:
def custom_loss(y_true, y_pred):
sqerr = (y_true - y_pred)**2
sqerr[:,4:-1:7] = sqerr[:,4:-1:7] * ((y_true[:,2:-1:7]-y_true[:,3:-1:7])/y_true[:,2:-1:7])**2
return sqerr.mean()
但是 'sqerr' 不是一个 numpy 数组,所以这段代码会导致错误
TypeError: 'Tensor' 对象不支持项目分配
于是我阅读了"How to do slice assignment in Tensorflow" 的帖子,包括jdehesa's answer 和GitHub page on this discussion。所以这就是我现在所拥有的......
def custom_loss(y_true, y_pred):
sqerr = K.square(y_true-y_pred)
sqerr = tf.Variable( sqerr , validate_shape=False )
with tf.control_dependencies([sqerr[:,4:-1:7].assign( sqerr[:,4:-1:7] * ((y_true[:,2:-1:7]-y_true[:,3:-1:7])/y_true[:,2:-1:7])**2 )]):
sqerr = tf.identity(sqerr)
return K.mean(sqerr)
...但显然我在实际使用它时搞砸了:
Traceback(最近一次调用最后一次):文件“my_awesome_nn.py”,行 119,在 setup_model 中
model.compile(loss=custom_loss, optimizer=opt)文件“/opt/anaconda/envs/py35/lib/python3.5/site-packages/keras/engine/training.py”, 第 850 行,编译中
sample_weight, mask)文件“/opt/anaconda/envs/py35/lib/python3.5/site-packages/keras/engine/training.py”, 第 465 行,加权
score_array = K.mean(score_array, axis=list(range(weight_ndim, ndim)))TypeError: 'NoneType' 对象不能被解释为整数
发生的事情是,TF 切片只允许应用于变量,而不是一般张量,所以我正在转换为变量。但是当我转换为变量时,它想知道形状,但形状在那时是“动态定义的”(即第一个元素是“?”)。所以设置 validate_shape=False 让我实际上定义了一个变量,但这会破坏 Keras 以后想要的维度信息。观察:
def custom_loss(y_true, y_pred):
sqerr = K.square(y_true-y_pred)
print("K.ndim(sqerr) #1 = ",K.ndim(sqerr))
sqerr = tf.Variable( sqerr , validate_shape=False )
print("K.ndim(sqerr) #2 = ",K.ndim(sqerr))
with tf.control_dependencies([sqerr[:,4:-1:7].assign( sqerr[:,4:-1:7] * ((y_true[:,2:-1:7]-y_true[:,3:-1:7])/y_true[:,2:-1:7])**2 )]):
sqerr = tf.identity(sqerr)
return K.mean(sqerr)
...输出结果
K.ndim(sqerr) #1 = 2
K.ndim(sqerr) #2 = 无
因此,稍后,当 Keras training.py 代码说“ndim = K.ndim(score_array)”时,它以 None 结束,因此出现 NoneType 错误。
任何人都可以阐明如何做我需要的事情吗?似乎我不能在不转换为变量的情况下进行切片,无法为动态形状的张量定义变量,以保留动态形状。
(如果我只是省略上面的“中间 3 行”并将我的自定义损失设为常规 MSE,这是一个完全有效的代码)
【问题讨论】:
-
您可以尝试包含更多相关代码吗?你在哪里计算
score_array?你能向我们展示更多关于你的模型的声明和编译的代码吗? -
我可以包含它,但它不是我的代码,因为 score_array 显示为在 Keras 发行版中进行评估,例如在github.com/fchollet/keras/blob/master/keras/engine/training.py。在组装损失时,甚至还没有构建模型。目前,问题似乎是作为变量的转换(切片需要),并且需要 validate_shape=False 因为张量形状在那时是“松散定义的”。但这会导致 K.dim(sqerr) = None。我将编辑帖子以反映这一点...
标签: python numpy tensorflow keras slice