Keras/Tensorflow中的基于滑动的赋值?

2024-10-06 06:50:07 发布

您现在位置:Python中文网/ 问答频道 /正文

请看我的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,这是一个完全有效的代码)


Tags: 代码inpytruecustomlinemeanfile
1条回答
网友
1楼 · 发布于 2024-10-06 06:50:07

我认为切片分配可以避免这种定制损失。如果要调整sqerr[:, 4:-1:7]的损失值,可以从总损失中减去原始值,然后再将调整后的损失值相加。在

def custom_loss_keras(y_true, y_pred):
    # first sum up the squared error column-wise
    sqerr = K.square(y_true - y_pred)
    loss = K.sum(sqerr, axis=-1)

    # subtract the loss for the sliced part
    loss -= K.sum(sqerr[:, 4:-1:7], axis=-1)

    # add back the adjusted loss for the sliced part
    denominator = K.maximum(y_true[:, 2:-1:7], K.epsilon())  # handle zero-division
    numerator = y_true[:, 2:-1:7] - y_true[:, 3:-1:7]
    loss += K.sum(sqerr[:, 4:-1:7] * K.square(numerator / denominator), axis=-1)

    # take average
    ncols = K.int_shape(y_pred)[-1]
    loss /= ncols
    return K.mean(loss)

您可以通过将其与原始numpy版本进行比较来验证此功能:

^{pr2}$

相关问题 更多 >