tensorflow中的sequence_loss_by_example


在編寫RNN程序時,一個很常見的函數就是sequence_loss_by_example

loss = tf.contrib.legacy_seq2seq.sequence_loss_by_example(logits_list, targets_list, weights_list, average_across_timesteps)

這個函數在contrib中的legacy(遺產)中,可見這個函數不是tensorflow支持的官方函數。

import numpy as np
import tensorflow as tf


def sequence_loss_by_example(logits,
                             targets,
                             weights,
                             average_across_timesteps=True,
                             softmax_loss_function=None,
                             name=None):
    """Weighted cross-entropy loss for a sequence of logits (per example).

    Args:
      logits: List of 2D Tensors of shape [batch_size x num_decoder_symbols].
      targets: List of 1D batch-sized int32 Tensors of the same length as logits.
      weights: List of 1D batch-sized float-Tensors of the same length as logits.
      average_across_timesteps: If set, divide the returned cost by the total
        label weight.
      softmax_loss_function: Function (labels, logits) -> loss-batch
        to be used instead of the standard softmax (the default if this is None).
        **Note that to avoid confusion, it is required for the function to accept
        named arguments.**
      name: Optional name for this operation, default: "sequence_loss_by_example".

    Returns:
      1D batch-sized float Tensor: The log-perplexity for each sequence.

    Raises:
      ValueError: If len(logits) is different from len(targets) or len(weights).
    """
    # 此三者都是列表,長度都應該相同
    if len(targets) != len(logits) or len(weights) != len(logits):
        raise ValueError("Lengths of logits, weights, and targets must be the same "
                         "%d, %d, %d." % (len(logits), len(weights), len(targets)))
    with tf.name_scope(name, "sequence_loss_by_example",
                       logits + targets + weights):
        log_perp_list = []
        # 計算每個時間片的損失
        for logit, target, weight in zip(logits, targets, weights):
            if softmax_loss_function is None:
                # 默認使用sparse
                target = tf.reshape(target, [-1])
                crossent = tf.nn.sparse_softmax_cross_entropy_with_logits(
                    labels=target, logits=logit)
            else:
                crossent = softmax_loss_function(labels=target, logits=logit)
            log_perp_list.append(crossent * weight)
        # 把各個時間片的損失加起來
        log_perps = tf.add_n(log_perp_list)
        # 對各個時間片的損失求平均數
        if average_across_timesteps:
            total_size = tf.add_n(weights)
            total_size += 1e-12  # Just to avoid division by 0 for all-0 weights.
            log_perps /= total_size
    return log_perps


"""
考慮many2many形式的RNN用法,每次輸入一個就會得到一個輸出
這些輸出需要計算平均損失,我們可以指定:
* 每個樣本的權重
* 每個時間片的權重
"""
sample_count = 4
target_count = 3
frame_count = 2
# 各個時間片我的答案
logits = [tf.random_uniform((sample_count, target_count)) for i in range(frame_count)]
# 各個時間片的真正答案
targets = [tf.constant(np.random.randint(0, target_count, (sample_count,))) for i in range(frame_count)]
# 每個時間片,每個樣本的權重。利用weights我們可以指定時間片權重和樣本權重
weights = [tf.ones((sample_count,), dtype=tf.float32) * (i + 1) for i in range(frame_count)]
loss1 = sequence_loss_by_example(logits, targets, weights, average_across_timesteps=True)
loss = tf.contrib.legacy_seq2seq.sequence_loss_by_example(logits, targets, weights, True)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    x, y, = sess.run([loss, loss1])
    print(x)
    print(y)
    print(x.shape, y.shape)

這個函數非常有用,tensorflow.nn中的sparse_softmax_cross_entropy無法指定樣本的權重,這個函數可以。
使用時,只需要傳入一個時間片即可。如果各個樣本權重都為1,最后得到的結果跟sparse_softmax_cross_entropy得到的結果是一樣的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM