美文网首页
【学习tensorflow2】损失函数

【学习tensorflow2】损失函数

作者: WILeroy | 来源:发表于2020-04-07 21:19 被阅读0次

    使用tensorflow2定义模型时, 损失函数可以使用keras模块提供的损失函数, 也可以自定义损失函数. 以分类问题的损失函数为例, 有以下几种形式.

    内置损失函数

    # 二元交叉熵
    tf.keras.losses.binary_crossentropy
    tf.keras.losses.BinaryCrossentropy
    #多分类交叉熵
    tf.keras.losses.categorical_crossentropy
    tf.keras.losses.CategoricalCrossentropy
    tf.keras.losses.sparse_categorical_crossentropy
    tf.keras.losses.SparseCategoricalCrossentropy
    

    以上3种交叉熵损失函数的不同写法, 其中使用lower_with_under命名风格的是函数形式, 而使用CapWords命名风格的是类形式, 二者实质上没有区别, 仅在使用时有不同. 下面是两种形式的使用:

    import numpy as np
    import tensorflow as tf
    
    labels = np.array([0, 1, 2], dtype=np.float32)
    labels_onehot = tf.keras.utils.to_categorical(labels)
    logits = np.array([2.9, .1, .05, .3, 1.9, .1, .05, .05, 1.9],
                      dtype=np.float32).reshape(-1, 3)
    logits_softmax = tf.keras.layers.Softmax()(logits)
    
    print(tf.keras.losses.CategoricalCrossentropy()(labels_onehot, logits_softmax))
    print(tf.keras.losses.categorical_crossentropy(labels_onehot, logits_softmax))
    # 输出结果为
    # tf.Tensor(0.23277493, shape=(), dtype=float32)
    # tf.Tensor([0.11212645 0.31276152 0.27343687], shape=(3,), dtype=float32)
    

    以上几种交叉熵损失函数的不同

    1. categorical_crossentropy要求labels是onehot编码, 因此使用to_categorical函数处理原始labels.
    2. 以上损失函数不会对logits做归一化, 因此使用softmax处理原始logits.
    3. sparse_categorical_crossentropy要求labels是序号编码.

    自定义损失函数

    自定义损失函数通常有两种方法. 直接定义函数作为损失函数, 该函数要求输入两个张量y_true, y_pred作为输入参数, 并输出一个标量作为损失函数值; 对tf.keras.losses.Loss进行子类化, 重写call方法实现损失的计算逻辑, 从而得到损失函数的类的实现.

    • 直接定义函数
    def categorical_cross_entropy(n_classes):
    
        def _categorical_cross_entropy(labels, logits):
            """ Computes cross entropy between labels and logits.
            Args:
                labels: an array of numpy or a 'Tensor', shape = [?, W, H, n_classes].
                logits: output of the model by softmax, shape = [?, W, H, n_classes].
        
            Returns:
                The value of the weighted cross entropy.
            """
    
            flat_labels = tf.cast(tf.reshape(labels, [-1, n_classes]), dtype=tf.float32)
            flat_logits = tf.cast(tf.reshape(logits, [-1, n_classes]), dtype=tf.float32)
    
            weight_cross_entropy = -tf.reduce_sum(
                tf.multiply(flat_labels*tf.math.log(flat_logits), weights),
                axis=1)
    
            return tf.reduce_mean(weight_cross_entropy)
    
        return _categorical_cross_entropy
    
    • 自定义复杂的损失函数, tf的模型在compile时需要显示地指定损失函数, 如果自定义损失函数, 只需要声明一个接受两个参数(y_true, y_pred)的函数.
    def mask_loss(y_true, y_pred):
        """
        y_pred: no scaled by softmax.
        """
        
        y_true = tf.reshape(y_true, [-1, 3])
        label = y_true[:, :-1]
        mask  = y_true[:, -1]
    
        y_pred = tf.reshape(y_pred, [-1, 2])
        
        loss_no_mask = tf.nn.softmax_cross_entropy_with_logits(label, y_pred)
        
        loss_mask = loss_no_mask * mask
        
        return tf.reduce_mean(loss_mask)
    

    相关文章

      网友评论

          本文标题:【学习tensorflow2】损失函数

          本文链接:https://www.haomeiwen.com/subject/bdbnphtx.html