损失函数
损失函数用于衡量真实值y_true和预测值y_pred之间的差异。通常情况下y_true和y_pred维度相同,但特殊情况下维度不同,一般来讲框架(包括tensorflow和mindspore)会支持此情况, 但要求两者的shape可广播,所谓可广播,是指被广播的维数维1。
以mindspore为例:
from mindspore import nn, Tensor, Model
from mindspore import dataset as ds
import mindspore
from mindspore.train.callback import LossMonitor
import numpy as np
mae = nn.MAELoss()
# 简单情况下
y_true = Tensor(np.array([[[1, 0, 0], [0, 1, 0]]]), mindspore.float32) # 被广播为shape=(2, 2, 3)
y_pred = Tensor(np.array([[[1, 0, 0]], [[1, 0, 0]]]), mindspore.float32) # 被广播为shape=(2, 2, 3)
print(y_pred.shape, y_true.shape)
output = mae(y_pred, y_true)
print(output)
# output:
# (2, 1, 3) (1, 2, 3)
# 0.33333334
# 和高阶API:model配合使用时
ef generator_data(num_data):
for i in range(num_data):
yield np.random.rand(4, 8).astype(np.float32), np.random.rand(1, 2).astype(np.float32)
class Net(nn.Cell):
def __init__(self):
super(Net, self).__init__()
self.dense = nn.Dense(8, 2)
def construct(self, x):
return self.dense(x)
net = Net()
data = ds.GeneratorDataset(list(generator_data(8)), column_names=['data', 'label'])
model = Model(net, loss_fn=mae, optimizer=nn.Adam(net.trainable_params(), 0.01))
model.train(epoch=1, train_dataset=data, callbacks=[LossMonitor()], dataset_sink_mode=False)
输出:
epoch: 1
step: 1
epoch: 1 step: 1, loss is 0.6364217
epoch: 1
step: 2
epoch: 1 step: 2, loss is 0.24072668
epoch: 1
step: 3
epoch: 1 step: 3, loss is 0.7317909
epoch: 1
step: 4
epoch: 1 step: 4, loss is 0.6150454
以tensorflow为例:简单情况下支持shape不同的情况;当使用model接口输入为numpy直接fit时,需要保持shape匹配。
import tensorflow as tf
import numpy as np
tf.enable_eager_execution()
mae = tf.keras.losses.MeanAbsoluteError()
y_true = np.array([[[1, 0, 0], [0, 1, 0]]]).astype(np.float32)
y_pred = np.array([[[1, 0, 0]], [[1, 0, 0]]]).astype(np.float32)
with tf.Session() as sess:
print(mae(y_true, y_pred).eval())
# out: 0.33333334
X = np.random.rand(4, 8)
y_true = np.random.rand(1, 2)
model = tf.keras.Sequential([tf.keras.layers.Dense(2, input_shape=(8,))])
model.compile(loss=mae, optimizer='adam')
model.fit(X, y_true, batch_size=2)
Train on 4 samples
4/4 [==============================] - 2s 439ms/sample - loss: 0.4454
MindSpore损失函数接口整理:
通常用于回归:
mindspore.nn.MAELoss
/mindspore.nn.L1Loss
:实现相同,求绝对值
mindspore.nn.MSELoss
/mindspore.nn.RMSELoss
mindspore.nn.SmoothL1Loss(beta=1.0)
:结合了L1loss和L2loss,L2loss通常收敛较快但对异常值鲁棒性较差。
通常用于分类:
mindspore.nn.BCELoss(weight=None, reduction="none")
:二值交叉熵损失,用于二分类。预测值在0-1之间,真实值只能为0和1。
mindspore.nn.BCEWithLogitsLoss(reduction="mean", weight=None, pos_weight=None)
:在logits输入加入了sigmoid方程,计算二值交叉熵,用于二分类。
mindspore.nn.SoftMarginLoss(reduction="mean")
:二分类。其中真实label只包含1和-1.
mindspore.nn.SoftmaxCrossEntropyWithLogits(sparse=False, reduction="none")
:交叉熵损失函数,用于多分类模型。当标签数据不是one-hot编码形式时,需要输入参数sparse为True。
mindspore.nn.SampledSoftmaxLoss(num_sampled, num_classes, num_true=1, sampled_values=None, remove_accidental_hits=True, seed=0, reduction="none")
:在类别数较多的情况下,加速训练。
mindspore.nn.CosineEmbeddingLoss(margin=0.0, reduction="mean")
:cosine相似性
通常用于CV:
mindspore.nn.DiceLoss(smooth=1e-5)
:衡量集合相似度,广泛用于医学影像分割。语义分割中一般用交叉熵来做损失函数,而评价的时候却使用IOU来作为评价指标,原因是梯度形式更优。参考https://zhuanlan.zhihu.com/p/86704421。
mindspore.nn.MultiClassDiceLoss(weights=None, ignore_indiex=None, activation="softmax")
:用于多标签问题,label被转换为多个二元分类。其中weights
:多个二元分类的权重; ignore_index
:忽略的类别index;activation
:用于logits转化。
mindspore.nn.FocalLoss(weight=None, gamma=2.0, reduction="mean")
:通常用于目标检测,解决了类别不平衡问题。