赞
踩
之前提到过 自定义Loss与metrics,下面盘点下 Keras中常用的损失函数,当然也是日常生产开发中常用的损失函数供今后自定义损失函数使用。损失函数虽然有很多形式,但万变不离其宗,损失函数都是将随机事件例如回归,分类等问题的目标抽象为非负的实数从而衡量该事件的损失或风险,从而矫正模型,希望模型朝着损失最小的方向进行,但是这里只是大多数情况,例如一些图像结合算法中,也会最大化损失使得图像的表达更加多元化,抽象化。
\(MAE(pre,y) = \frac{1}{n}\sum_{i=1}^{n}\left | pre^{(i)}-y^{(i)} \right |\)
pre为预测值,y为真实值,MAE为预测值与真实值差的绝对值之和
- # Mean Ablsolutely Error
- def getMaeLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.mean_absolute_error(label, predict))
- return loss
模拟100个样本进行 Loss 计算,下述如无特殊声明默认使用该样本进行 Loss 计算。
- numSamples = 100
- predict = np.random.randint(0, 2, size=(numSamples,)).astype('float32')
- label = np.random.randint(0, 2, size=(numSamples,)).astype('float32')
-
- maeLoss = getMaeLoss(predict, label).numpy()
- print("Mae Loss:", maeLoss)
\(\fn_cm MSE(pre,y) = \frac{1}{n}\sum_{i=1}^{n}(pre^{(i)}-y^{(i)} )^2\)
pre为预测值,y为真实值,MSE为预测值与真实值差的平方之和,与MAE相同,不论 pre 比 y 高还是低于同一个数,计算得到的结果都是相同的。
- # Mean Squared Error
- def getMseLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.mean_squared_error(label, predict))
- return loss
\(RMSE(pre,y) = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(pre^{(i)}-y^{(i)} )^2}\)
RMSE 其实和 MSE 表征大小没有区别,只不过是类似于方差和标准差的区别,如果预测目标为万元,则 MSE 的单位是万*万,而 RMSE 则是万,这里类似做一个标准化的过程。
- # Root Mean Squared Error
- def getRmseLoss(predict, label):
- loss = tf.sqrt(tf.reduce_mean(tf.losses.mean_squared_error(label, predict)))
- return loss
\(MAPE(pre,y) = \frac{1}{n}\sum_{i=1}^{n}\left \| \frac{y^{(i)}-pre^{(i)}}{y^{(i)}} \right \| \cdot 100%\)
MAPE 为0%表示完美模型,MAPE 大于 100 %则表示劣质模型。这里需要注意分母为0的情况。
- # mean_absolute_percentage_error
- def getMapeLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.mean_absolute_percentage_error(label, predict))
- return loss
\(\fn_cm MSLE(pre,y) = \frac{1}{n}\sum_{i=1}^{n}(log(y^{(i)}+1)-log(pre^{(i)}+1))^2\)
- # Mean Squared Logarithmic Error (MSLE)
- def getMsleLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.mean_squared_logarithmic_error(label, predict))
- return loss
(1) 可以看出来在均方根误差相同的情况下,预测值比真实值小这种情况的错误比较大,即对于预测值小这种情况惩罚较大。
(2) 当数据当中有少量的值和真实值差值较大的时候,使用log函数能够减少这些值对于整体误差的影响。
- y = np.array([2.,3.,4.,5.,6.])
- predict = y + 2
- print("预测值大于真实值:",getMsleLoss(predict, y))
- predict = y - 2
- print("预测值小于真实值:",getMsleLoss(predict, y))
- 预测值大于真实值: tf.Tensor(0.13689565089565417, shape=(), dtype=float64)
- 预测值小于真实值: tf.Tensor(0.44519201856286134, shape=(), dtype=float64)
\(similarity=cos(\theta)=\frac{pre \cdot y}{\left \| pre \right \|\left \| y \right \|}=\frac{\sum_{i=1}^{n} pre_i \cdot y_i}{\sqrt{\sum_{i=1}^{n}(pre_i)^2}x\sum_{i=1}^{n}(y_i)^2}\)
余弦相似度一般通过夹角考虑两个向量在空间的相似度,比如常见的 User-embedding,Item-embedding 相关的相似性计算。
- # Cosine Loss
- def getCosLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.cosine_similarity(label, predict))
- return loss
\(BinaryCrossentropy= -\frac{1}{n}\sum_{i=1}^{n} y_i \cdot log^{pre_i} + (i-y_i) \cdot log^{1-pre_i}\)
用于二值分类,IMDB 情感分析,性别预测等等都会用到。
- # Binary Loss
- def getBinaryLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.binary_crossentropy(label, predict))
- return loss
- predict = utils.to_categorical(np.random.randint(0, 2, size=(numSamples,)).astype('int32'), num_classes=2)
- label = utils.to_categorical(np.random.randint(0, 2, size=(numSamples,)).astype('int32'), num_classes=2)
-
- binaryLoss = getBinaryLoss(predict, label).numpy()
- print("Binary Loss: ", binaryLoss)
\(CategoryCrossentropy=-\sum_{i=1}^{n}y_i \cdot log^{pre_i}\)
用于多类别分析,最常见的手写数字识别就用了交叉熵损失函数,常与 softmax 函数结合使用。
- # Category Loss
- def getCategoryLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.categorical_crossentropy(label, predict))
- return loss
- predict = utils.to_categorical(np.random.randint(0, 10, size=(numSamples,)).astype('int32'), num_classes=10)
- label = utils.to_categorical(np.random.randint(0, 10, size=(numSamples,)).astype('int32'), num_classes=10)
-
- categoryLoss = getCategoryLoss(predict, label).numpy()
- print("Category Loss: ", categoryLoss)
\(\fn_cm D_{KL} (P||Q)= \sum_{i=1}^{n}p(x_i)logp(x_i)-p(x_i)logq(x_i)\)
这里信息熵定义为:
\(H = -\sum_{i=1}^{n}p(x)logp(x)\)
K-L散度在统计学中用于衡量两个分步的相似程度,这里P,Q可以看做是真实值与预测值。
- # KL Loss
- def getKLLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.kullback_leibler_divergence(label, predict))
- return loss
\(Hinge = max(0, (1-y) \cdot pre)\)
Hinge Loss 又叫合页损失,因为它的函数图像和门的合页特别像,最常见的应用场景是 SVM 支持向量机。
- # Hinge Loss
- def getHingeLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.hinge(label, predict))
- return loss
- predict = np.where(predict < 1, -1, 1).astype('float32')
- label = np.where(label < 1, -1, 1).astype('float32')
- hingeLoss = getHingeLoss(predict, label).numpy()
- print("Hinge Loss: ", hingeLoss)
\(Possion = pre - y * log(pre)\)
参考官方 API 这里为了防止 pre 出现为0的情况,所以后面改写为 y * log(pre + epsilon()) ,其中 epsilon() = 1e-07
- # Possion Loss
- def getPossionLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.poisson(label, predict))
- return loss
Huber 顾名思义平滑绝对误差,其构造为分段函数,它介于 MAE 与 MSE 之间,平滑程度取决于 δ 的取值范围,当Huber损失在 [0-δ,0+δ] 区间内,等价为MSE,而在[-∞,δ]和[δ,+∞]时为MAE。所以 Huber 对数据中的异常点没有平方误差敏感。
- # Huber Loss
- def getHuberLoss(predict, label):
- loss = tf.reduce_mean(tf.losses.huber(label, predict))
- return loss
更多推荐算法相关深度学习:深度学习导读专栏
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。