【问题标题】:I get an error while trying to customize my loss function尝试自定义损失函数时出现错误
【发布时间】:2019-11-09 09:52:53
【问题描述】:

我正在尝试为我的深度学习模型创建自定义损失函数,但遇到了错误。

我将在这里给出一个我不想使用的代码示例,但如果我了解如何使这个小损失函数工作,那么我想我将能够使我的长期损失函数工作.所以我非常想寻求帮助以使下一个功能正常工作,就是这样。

    model.compile(optimizer='rmsprop',loss=try_loss(pic_try), metrics= 
    ['accuracy'])
    def try_loss(pic):
    def try_2_loss(y_true,y_pred):
     return tf.py_function(func=try_3_loss,inp=[y_pred,pic], Tout=tf.float32)
    return try_2_loss
    def try_3_loss(y_pred,pic):
     return tf.reduce_mean(pic)

现在我想知道以下内容: 1. 我在 model.compile 行中输入的图片是否需要是张量?它可以是一个numpy数组吗? 2.在我的try_3_loss函数中,我可以将tf.reduce_mean替换为np.mean吗? 3.在我的try_3_loss函数中,是否可以对y_pred使用普通的numpy命令,比如np.mean(y_pred)?

我主要是想使用尽可能多的 numpy 命令。

我尝试使用各种东西,我尝试让我的图片成为一个 numpy 数组,我尝试在我的 try_3_loss 函数中使用 np.mean (pic),我尝试让我的图片成为张量对象,然后在我的 try_3_project 中使用 tf.reduce_mean 并且我尝试在运行 model.compile 行之前执行 sess.run(pic) 并且在上述所有情况下我都收到以下错误:


TypeError                                 Traceback (most recent call 
last)
<ipython-input-75-ff45de7120bc> in <module>()
----> 1 model.compile(optimizer='rmsprop',loss=try_loss(pic_try), 
metrics=['accuracy'])

1 frames
/usr/local/lib/python3.6/dist-packages/keras/engine/training.py in 
compile(self, optimizer, loss, metrics, loss_weights, sample_weight_mode, 
weighted_metrics, target_tensors, **kwargs)
    340                 with K.name_scope(self.output_names[i] + 
'_loss'):
    341                     output_loss = weighted_loss(y_true, y_pred,
--> 342                                                 sample_weight, 
mask)
    343                 if len(self.outputs) > 1:
    344                     self.metrics_tensors.append(output_loss)

/usr/local/lib/python3.6/dist-packages/keras/engine/training_utils.py in 
weighted(y_true, y_pred, weights, mask)
    418             weight_ndim = K.ndim(weights)
    419             score_array = K.mean(score_array,
    --> 420                                  axis=list(range(weight_ndim, 
    ndim)))
    421             score_array *= weights
    422             score_array /= K.mean(K.cast(K.not_equal(weights, 0), 
K.floatx()))

TypeError: 'NoneType' object cannot be interpreted as an integer

【问题讨论】:

    标签: deep-learning customization loss-function


    【解决方案1】:

    一些测试代码:

    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras.layers import *
    from tensorflow.keras.models import Model
    from tensorflow.keras import backend as K
    
    @tf.custom_gradient
    def py_loss_fn(y_true, y_pred):
      """ This function takes eager tensors as inputs which can be explicitly
      converted to np.arrays via EagerTensor.numpy() or implicitly converted
      by applying numpy operations to them.
    
      However, once tf operations are no longer used it means that the function has to
      implement its own gradient function.
      """
      def grad(dy):
        """ Compute gradients for function inputs.
            Ignore input[0] (y_true) since that is model.targets[0]
        """
        g = np.mean(-dy * np.sign(y_true - y_pred), axis=1)[:, np.newaxis]
        return None, g
    
      return np.mean(np.abs(y_true - y_pred), axis=1), grad
    
    def eager_loss_fn(y_true, y_pred):
      """ If tf operations are used on eager tensors auto diff works without issues
      """
      return tf.reduce_mean(tf.abs(y_true - y_pred))
    
    def loss_fn(y_true, y_pred, **kw_args):
      """ This function takes tensors as inputs. Numpy operations are not valid.
      """
    #   loss = tf.py_function(eager_loss_fn, inp=[y_true, y_pred], Tout=tf.float32)
      loss = tf.py_function(py_loss_fn, inp=[y_true, y_pred], Tout=tf.float32)
      return loss
    
    def make_model():
      """ Linear regression model with custom loss """
      inp = Input(shape=(4,))
      out = Dense(1, use_bias=False)(inp)
      model = Model(inp, out)
      model.compile('adam', loss_fn)
      return model
    
    model = make_model()
    model.summary()
    

    调用模型的测试代码:

    import numpy as np
    
    FACTORS = np.arange(4) + 1
    def test_fn(x):
      return np.dot(x, FACTORS.T)
    
    X = np.random.rand(3, 4)
    Y = np.apply_along_axis(test_fn, 1, X)
    
    history = model.fit(X, Y, epochs=1000, verbose=False)
    print(history.history['loss'][-1])
    

    【讨论】:

      【解决方案2】:

      非常感谢您的帮助!我实际上决定切换到 tf 2.0 并且编写函数要容易得多,虽然它在效率方面有点贵,但我总是可以很容易地从 np 数组切换到张量并返回,所以我只是用 numpy 数组格式编写了它并将其切换回来。因此,我所有函数的输入和输出都是张量,但在函数内部,我将其切换为 numpy 数组,在将其返回之前,我将其切换回张量,但仍然有错误。代码如下:

          model.compile(optimizer='rmsprop',loss=custom_loss(pic), 
          loss_weights=[None],metrics=['accuracy'])
      
          def my_loss(y_true, y_pred):
          return loss(y_pred,pic)
      
          def custom_loss(pic):
          return my_loss
      

      当我实际尝试运行损失函数(不在 model.compile 中)时:

          my_loss(x0,x0)
      

      我得到以下信息:

          orig shape x:  (1, 2501)
          shape x:  (2501,)
          shape pic:  (100, 100)
          shape a:  ()
          shape ms:  (2500,)
          r_size:  50
          c_size:  50
          <tf.Tensor: id=261, shape=(), dtype=float64, numpy=6.741635588952273>
      

      所以我确实得到了一个带有我想要的损失的张量输出。 (打印的内容有助于理解错误)但是当我尝试运行编译命令时,我得到了这个:

          orig shape x:  ()
      
          (...a bunch of unneccessary stuff...)
      
          ----> 4     x=np.reshape(x,(2501,1))
            5     x=np.reshape(x,(2501,))
            6     pic=np.array(pic)
      
          /usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py in reshape(a, 
          newshape, order)
          290            [5, 6]])
          291     """
          --> 292     return _wrapfunc(a, 'reshape', newshape, order=order)
          293 
          294 
      
          /usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py in 
          _wrapfunc(obj, method, *args, **kwds)
           54 def _wrapfunc(obj, method, *args, **kwds):
           55     try:
          ---> 56         return getattr(obj, method)(*args, **kwds)
           57 
           58     # An AttributeError occurs if the object does not have
      
          ValueError: cannot reshape array of size 1 into shape (2501,1)
      

      就像编译器不理解 y_pred 将具有我的模型输出的大小。

      我的模特:

          model = tf.keras.Sequential()
          #add model layers
          model.add(layers.Conv2D(64, kernel_size=3,activation='linear',input_shape= 
          (inputs_shape_0,inputs_shape_1,1)))
          #model.add(LeakyReLU(alpha=0.3))
          model.add(layers.Conv2D(32, kernel_size=3,activation='linear'))
          #model.add(LeakyReLU(alpha=0.3))
          model.add(layers.Flatten())
          model.add(layers.Dense(2501, activation='linear'))
      

      任何想法如何解决它?我还将查看您发送给我的测试代码以获取想法。

      谢谢!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-10
        • 1970-01-01
        • 2017-12-20
        • 1970-01-01
        • 1970-01-01
        • 2019-08-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多