请看我的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' object does not support item assignment
所以我读了文章"How to do slice assignment in Tensorflow",包括jdehesa's answer和{a3}。我现在得到的是。。。在
^{pr2}$……但很明显,当我真的需要使用它的时候,我却把它搞砸了:
Traceback (most recent call last): File "my_awesome_nn.py", line 119, in setup_model
model.compile(loss=custom_loss, optimizer=opt)
File "/opt/anaconda/envs/py35/lib/python3.5/site-packages/keras/engine/training.py", line 850, in compile
sample_weight, mask)
File "/opt/anaconda/envs/py35/lib/python3.5/site-packages/keras/engine/training.py", line 465, in weighted
score_array = K.mean(score_array, axis=list(range(weight_ndim, ndim)))
TypeError: 'NoneType' object cannot be interpreted as an integer
现在的情况是,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=无
所以后来,当培训.py代码的意思是“ndim=K.ndim(score_array)”,结果是None,因此出现了NoneType错误。在
有人能告诉我怎么做我需要的吗?似乎我不能在不转换为变量的情况下进行切片,也无法为动态形状的张量定义变量,以保持动态形状。在
(如果我省略上面的“中间3行”并让我的自定义损失为常规MSE,这是一个完全有效的代码)
我认为切片分配可以避免这种定制损失。如果要调整
sqerr[:, 4:-1:7]
的损失值,可以从总损失中减去原始值,然后再将调整后的损失值相加。在您可以通过将其与原始numpy版本进行比较来验证此功能:
^{pr2}$相关问题 更多 >
编程相关推荐