一、经典损失函数
1.1 分类问题
1.1.1 cross entropy
刻画概率之间的距离.
1.1.1.1 自实现
使用tf.clip_by_value
粗略估计。
cross_entropy = -tf.reduce_mean(
y * tf.log(tf.clip_by_value(predict, 1e-10, 1.0))
)
*表示矩阵点乘
如果不使用tf.clip_by_value的话, predict可能出现>1的值,如果此时的y对应为1,则loss会出现负数。
1.1.1.2 tf.nn.softmax_cross_entropy_with_logits_v2
tf.nn.softmax_cross_entropy_with_logits_v2(
labels, logits, axis=None, name=None, dim=None
)
- labels:
需要是one-hot格式 - logits:
未经softmax的概率
1.1.1.3 tf.nn.sparse_softmax_cross_entropy_with_logits
适用于只有一个正确答案的分类问题中
tf.nn.sparse_softmax_cross_entropy_with_logits(
_sentinel=None, labels=None, logits=None, name=None
)
- labels:
正确类的类别id
1.2 回归问题
1.2.1 均方误差
1.2.1.1 自实现
mse = tf.reduce_mean(tf.math.square(y - predict))
1.3 惩罚项
二、自定义损失
2.1 分段损失
实现:
因为分段,使用了tf.where()。 如果是多分段呢?
loss = tf.reduce_mean(tf.where(tf.greater(x, y), a*(x-y), b*(y-x)))
使用了tf.where(),第一个参数为选择条件,如果为True, 选择第二个,否则选择第三个。
2.2 kld散度
注意:kld散度, 虽然部分分量可能<0, 但最后的结果一定是>0的,
实现:
kld_loss = tf.reduce_mean(post_distribution *
safe_log(post_distribution / tf.clip_by_value(prior_distribution, 1e-9, 1.0)))
注意:这里的clip_by_value主要是为了保证分母的值不会太小。
三、细节:
3.1 tf.nn 与 tf.losses中的区别
使用tf.nn.sparse_softmax_cross_entropy_with_logits 或 tf.nn.softmax_cross_entropy_with_logits 得到的loss shape同标签 y.
使用tf.losses.softmax_cross_entropy 或 tf.losses.sparse_softmax_cross_entropy得到的loss shape默认是单值scale. 如果需要shape同标签, 需要指定reduction参数.
import tensorflow as tf
import numpy as np
inputs = tf.placeholder(shape=[None, 5, 100], dtype=tf.float32)
y = tf.placeholder(shape=[None, 5], dtype=tf.int64)
logits = tf.layers.dense(inputs, units=10, activation=tf.nn.relu)
# loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=y)
loss = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=tf.one_hot(y, depth=10))
# loss = tf.losses.sparse_softmax_cross_entropy(logits=logits, labels=y, reduction="none") # 自动对batch做了一个/N.
# tf.losses.softmax_cross_entropy(reduction=) # 原始如此.
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
X_ = np.random.normal(size=[4, 5, 100])
y_ = np.random.randint(0, 10, size=[4, 5])
print(y_)
loss_ = sess.run([loss], feed_dict={inputs: X_,
y: y_})
print(loss_)