使用 Keras 了解 WeightedKappaLoss
Understanding WeightedKappaLoss using Keras
我正在使用 Keras 尝试使用一系列事件来预测得分向量 (0-1)。
例如,X 是一个包含 3 个向量的序列,每个向量由 6 个特征组成,而 y 是一个包含 3 个分数的向量:
X
[
[1,2,3,4,5,6], <--- dummy data
[1,2,3,4,5,6],
[1,2,3,4,5,6]
]
y
[0.34 ,0.12 ,0.46] <--- dummy data
我想将问题解决为序数 class化,因此如果实际值为 [0.5,0.5,0.5]
,则预测 [0.49,0.49,0.49]
优于 [0.3,0.3,0.3]
。我最初的解决方案是在我的最后一层使用 sigmoid
激活和 mse
作为损失函数,因此每个输出神经元的输出范围在 0-1 之间:
def get_model(num_samples, num_features, output_size):
opt = Adam()
model = Sequential()
model.add(LSTM(config['lstm_neurons'], activation=config['lstm_activation'], input_shape=(num_samples, num_features)))
model.add(Dropout(config['dropout_rate']))
for layer in config['dense_layers']:
model.add(Dense(layer['neurons'], activation=layer['activation']))
model.add(Dense(output_size, activation='sigmoid'))
model.compile(loss='mse', optimizer=opt, metrics=['mae', 'mse'])
return model
我的目标是了解 WeightedKappaLoss 的用法并在我的实际数据上实施它。我围绕这个想法创建了 this Colab 到 fiddle。在 Colab 中,我的数据是一个形状为 (5000,3,3)
的序列,我的目标形状是 (5000, 4)
,代表 4 个可能的 classes 中的 1 个。
我想让模型明白它需要 trim X 的浮点数才能预测正确的 y class:
[[3.49877793, 3.65873511, 3.20218196],
[3.20258153, 3.7578669 , 3.83365481],
[3.9579924 , 3.41765455, 3.89652426]], ----> y is 3 [0,0,1,0]
[[1.74290875, 1.41573056, 1.31195701],
[1.89952004, 1.95459796, 1.93148095],
[1.18668981, 1.98982041, 1.89025326]], ----> y is 1 [1,0,0,0]
新型号代码:
def get_model(num_samples, num_features, output_size):
opt = Adam(learning_rate=config['learning_rate'])
model = Sequential()
model.add(LSTM(config['lstm_neurons'], activation=config['lstm_activation'], input_shape=(num_samples, num_features)))
model.add(Dropout(config['dropout_rate']))
for layer in config['dense_layers']:
model.add(Dense(layer['neurons'], activation=layer['activation']))
model.add(Dense(output_size, activation='softmax'))
model.compile(loss=tfa.losses.WeightedKappaLoss(num_classes=4), optimizer=opt, metrics=[tfa.metrics.CohenKappa(num_classes=4)])
return model
拟合模型时,我可以在 TensorBoard 上看到以下指标:
我不确定以下几点,希望得到澄清:
- 我用对了吗?
- 在我原来的问题中,我预测了 3 个分数,而在 Colab 示例中我只预测了 1 个分数。如果我使用 WeightedKappaLoss,这是否意味着我需要转换每个分数100 one-hot 编码向量的分数?
- 有没有办法在原始浮点分数上使用 WeightedKappaLoss 而无需转换为 class化问题?
让我们把目标分成两个子目标,我们遍历目的、概念、数学先是Weighted Kappa
的details,然后总结一下在tensorflow
中尝试使用WeightedKappaLoss
时的注意事项
PS: 只关心用法的可以跳过理解部分
加权Kappa详解
由于Weighted Kappa可以看成Cohen's kappa + weights,所以我们需要了解Cohen's kappa 第一
Cohen 的 kappa 示例
假设我们有两个 classifier(A 和 B)试图 class将 50 个陈述分为两类(真和假),他们 class证明这些陈述的方式在偶然事件中彼此 wrt table:
B
True False
A True 20 5 25 statements A think is true
False 10 15 25 statements A think is false
30 statements B think is true
20 statements B think is false
现在假设我们想知道:A 和 B 做出的预测有多可靠?
我们可以做的是简单地取classA和B彼此一致的化验陈述的百分比,即观察到的一致的比例表示为Po
,所以:
Po = (20 + 15) / 50 = 0.7
但这是有问题的,因为有概率A和B随机一致,即期望概率一致的比例表示为Pe
,如果我们使用观察到的百分比作为期望概率,那么:
Pe = (probability statement A think is true) * (probability statement B think is true) +
(probability statement A think is false) * (probability statement B think is false)
= (25 / 50) * (30 / 50) +
(25 / 50) * (20 / 50)
= 0.5
Cohen 的 kappa 系数 表示为 K
合并了 Po
和 Pe
给我们关于预测 A 和B发:
K = (Po - Pe) / (1 - Pe) = 1 - (1 - Po) / (1 - Pe) = 1 - (1 - 0.7) / (1 - 0.5) = 0.4
我们可以看到 A 和 B 彼此越一致(Po
更高)并且他们因为偶然而越不一致(Pe
更低),Cohen 的越多kappa“认为”结果可靠
现在假设 A 是陈述的标签(ground truth),那么 K
告诉我们 B 的预测有多可靠,即当考虑随机机会时,预测与标签的一致性程度
Cohen 的 kappa 权重
我们正式定义偶然性table和m
classes:
classifier 2
class.1 class.2 class... class.k Sum over row
class.1 n11 n12 ... n1k n1+
class.2 n21 n22 ... n2k n2+
classifier 1 class... ... ... ... ... ...
class.k nk1 nk2 ... nkk nk+
Sum over column n+1 n+2 ... n+k N # total sum of all table cells
table 单元格包含交叉class化类别的计数,分别表示为 nij
、i,j
行和列索引
考虑那些 k
序数 classes 与两个分类 classes 分开,例如将 1, 0
分成五个 classes 1, 0.75, 0.5, 0.25, 0
具有平滑有序的过渡,我们不能说 class 是独立的,除了第一个和最后一个 class,例如 very good, good, normal, bad, very bad
、very good
和 good
不是独立的,good
应该更接近 bad
而不是 very bad
由于相邻的class是相互依赖的,那么为了计算与协议相关的数量,我们需要定义这种依赖关系,即权重表示为Wij
,它分配给意外事件 table 中的每个单元格,权重值(在范围 [0, 1] 内)取决于两个 classes
的接近程度
现在让我们看看 Weighted Kappa 中的 Po
和 Pe
公式:
以及 Po
和 Pe
公式 Cohen 的 kappa:
我们可以看到 Po
和 Pe
公式 Cohen 的 kappa 是 Weighted Kappa[=206= 公式的特例],其中 weight = 1
分配给所有对角线单元格,其他地方的权重 = 0,当我们使用 [=166= 中的 Po
和 Pe
公式计算 K
(Cohen 的 kappa 系数)时]加权 Kappa 我们还考虑了相邻 class 之间的依赖关系
这里有两种常用的权重系统:
- 线宽:
- 二次权重:
其中,|i-j|
是classes之间的距离,k
是classes的个数
加权 Kappa 损失
这种损失是在我们之前提到的情况下使用的,其中一个 classifier 是标签,这种损失的目的是使模型(另一个 classifier)的预测与可能,即鼓励模型做出更多与标签一致的预测,同时在考虑相邻 classes 之间的依赖性时减少随机猜测
Weighted Kappa Loss的公式由:
给出
它只是采用负 Cohen 的 kappa 系数 的公式并去掉常数 -1
然后应用 自然对数 , 其中 dij = |i-j|
代表 线性权重 , dij = (|i-j|)^2
代表 二次权重
下面是用tensroflow写的Weighted Kappa Loss的源码,可以看到只是实现了Weighted Kappa Loss的公式] 以上:
import warnings
from typing import Optional
import tensorflow as tf
from typeguard import typechecked
from tensorflow_addons.utils.types import Number
class WeightedKappaLoss(tf.keras.losses.Loss):
@typechecked
def __init__(
self,
num_classes: int,
weightage: Optional[str] = "quadratic",
name: Optional[str] = "cohen_kappa_loss",
epsilon: Optional[Number] = 1e-6,
dtype: Optional[tf.DType] = tf.float32,
reduction: str = tf.keras.losses.Reduction.NONE,
):
super().__init__(name=name, reduction=reduction)
warnings.warn(
"The data type for `WeightedKappaLoss` defaults to "
"`tf.keras.backend.floatx()`."
"The argument `dtype` will be removed in Addons `0.12`.",
DeprecationWarning,
)
if weightage not in ("linear", "quadratic"):
raise ValueError("Unknown kappa weighting type.")
self.weightage = weightage
self.num_classes = num_classes
self.epsilon = epsilon or tf.keras.backend.epsilon()
label_vec = tf.range(num_classes, dtype=tf.keras.backend.floatx())
self.row_label_vec = tf.reshape(label_vec, [1, num_classes])
self.col_label_vec = tf.reshape(label_vec, [num_classes, 1])
col_mat = tf.tile(self.col_label_vec, [1, num_classes])
row_mat = tf.tile(self.row_label_vec, [num_classes, 1])
if weightage == "linear":
self.weight_mat = tf.abs(col_mat - row_mat)
else:
self.weight_mat = (col_mat - row_mat) ** 2
def call(self, y_true, y_pred):
y_true = tf.cast(y_true, dtype=self.col_label_vec.dtype)
y_pred = tf.cast(y_pred, dtype=self.weight_mat.dtype)
batch_size = tf.shape(y_true)[0]
cat_labels = tf.matmul(y_true, self.col_label_vec)
cat_label_mat = tf.tile(cat_labels, [1, self.num_classes])
row_label_mat = tf.tile(self.row_label_vec, [batch_size, 1])
if self.weightage == "linear":
weight = tf.abs(cat_label_mat - row_label_mat)
else:
weight = (cat_label_mat - row_label_mat) ** 2
numerator = tf.reduce_sum(weight * y_pred)
label_dist = tf.reduce_sum(y_true, axis=0, keepdims=True)
pred_dist = tf.reduce_sum(y_pred, axis=0, keepdims=True)
w_pred_dist = tf.matmul(self.weight_mat, pred_dist, transpose_b=True)
denominator = tf.reduce_sum(tf.matmul(label_dist, w_pred_dist))
denominator /= tf.cast(batch_size, dtype=denominator.dtype)
loss = tf.math.divide_no_nan(numerator, denominator)
return tf.math.log(loss + self.epsilon)
def get_config(self):
config = {
"num_classes": self.num_classes,
"weightage": self.weightage,
"epsilon": self.epsilon,
}
base_config = super().get_config()
return {**base_config, **config}
加权 Kappa 损失的使用
只要我们可以将问题转化为序数分类问题,即classes,我们就可以使用加权Kappa损失形成一个平滑有序的过渡并且相邻的 class 是相互依赖的,就像用 very good, good, normal, bad, very bad
对某些东西进行排名一样,模型的输出应该像 Softmax
results
当我们尝试预测分数向量 (0-1) 时,即使它们总和为 1
,我们也不能使用 加权 Kappa 损失,因为 weights在vector的每个元素中是不同的,这个loss不是问减去的值有多少不同,而是问乘法的数字有多少,例如:
import tensorflow as tf
from tensorflow_addons.losses import WeightedKappaLoss
y_true = tf.constant([[0.1, 0.2, 0.6, 0.1], [0.1, 0.5, 0.3, 0.1],
[0.8, 0.05, 0.05, 0.1], [0.01, 0.09, 0.1, 0.8]])
y_pred_0 = tf.constant([[0.1, 0.2, 0.6, 0.1], [0.1, 0.5, 0.3, 0.1],
[0.8, 0.05, 0.05, 0.1], [0.01, 0.09, 0.1, 0.8]])
y_pred_1 = tf.constant([[0.0, 0.1, 0.9, 0.0], [0.1, 0.5, 0.3, 0.1],
[0.8, 0.05, 0.05, 0.1], [0.01, 0.09, 0.1, 0.8]])
kappa_loss = WeightedKappaLoss(weightage='linear', num_classes=4)
loss_0 = kappa_loss(y_true, y_pred_0)
loss_1 = kappa_loss(y_true, y_pred_1)
print('Loss_0: {}, loss_1: {}'.format(loss_0.numpy(), loss_1.numpy()))
输出:
# y_pred_0 equal to y_true yet loss_1 is smaller than loss_0
Loss_0: -0.7053321599960327, loss_1: -0.8015820980072021
您在 Colab 中的代码在 序数分类问题 的上下文中正常工作,因为您形成的函数 X->Y
非常简单(int of X 是 Y 指数 + 1),所以模型学习它相当快速和准确,正如我们可以看到 K
(Cohen 的 kappa 系数)高达 1.0
和加权 Kappa 损失下降到 -13.0
以下(在实践中通常是我们可以期望的最小值)
总而言之,您可以使用加权 Kappa 损失,除非您可以将您的问题形成为 序数分类问题,其中标签在一个-热门时尚,如果你可以并尝试解决 LTR(学习排名)问题,那么你可以检查 this tutorial of implement ListNet and this tutorial of tensorflow_ranking 以获得更好的结果,否则你不应该使用 Weighted Kappa Loss,如果你的问题只能形成回归问题,那么你应该按照你原来的解决方案
参考:
Weighted Kappa in R: For Two Ordinal Variables
source code of WeightedKappaLoss in tensroflow-addons
Documentation of tfa.losses.WeightedKappaLoss
Difference between categorical, ordinal and numerical variables
我正在使用 Keras 尝试使用一系列事件来预测得分向量 (0-1)。
例如,X 是一个包含 3 个向量的序列,每个向量由 6 个特征组成,而 y 是一个包含 3 个分数的向量:
X
[
[1,2,3,4,5,6], <--- dummy data
[1,2,3,4,5,6],
[1,2,3,4,5,6]
]
y
[0.34 ,0.12 ,0.46] <--- dummy data
我想将问题解决为序数 class化,因此如果实际值为 [0.5,0.5,0.5]
,则预测 [0.49,0.49,0.49]
优于 [0.3,0.3,0.3]
。我最初的解决方案是在我的最后一层使用 sigmoid
激活和 mse
作为损失函数,因此每个输出神经元的输出范围在 0-1 之间:
def get_model(num_samples, num_features, output_size):
opt = Adam()
model = Sequential()
model.add(LSTM(config['lstm_neurons'], activation=config['lstm_activation'], input_shape=(num_samples, num_features)))
model.add(Dropout(config['dropout_rate']))
for layer in config['dense_layers']:
model.add(Dense(layer['neurons'], activation=layer['activation']))
model.add(Dense(output_size, activation='sigmoid'))
model.compile(loss='mse', optimizer=opt, metrics=['mae', 'mse'])
return model
我的目标是了解 WeightedKappaLoss 的用法并在我的实际数据上实施它。我围绕这个想法创建了 this Colab 到 fiddle。在 Colab 中,我的数据是一个形状为 (5000,3,3)
的序列,我的目标形状是 (5000, 4)
,代表 4 个可能的 classes 中的 1 个。
我想让模型明白它需要 trim X 的浮点数才能预测正确的 y class:
[[3.49877793, 3.65873511, 3.20218196],
[3.20258153, 3.7578669 , 3.83365481],
[3.9579924 , 3.41765455, 3.89652426]], ----> y is 3 [0,0,1,0]
[[1.74290875, 1.41573056, 1.31195701],
[1.89952004, 1.95459796, 1.93148095],
[1.18668981, 1.98982041, 1.89025326]], ----> y is 1 [1,0,0,0]
新型号代码:
def get_model(num_samples, num_features, output_size):
opt = Adam(learning_rate=config['learning_rate'])
model = Sequential()
model.add(LSTM(config['lstm_neurons'], activation=config['lstm_activation'], input_shape=(num_samples, num_features)))
model.add(Dropout(config['dropout_rate']))
for layer in config['dense_layers']:
model.add(Dense(layer['neurons'], activation=layer['activation']))
model.add(Dense(output_size, activation='softmax'))
model.compile(loss=tfa.losses.WeightedKappaLoss(num_classes=4), optimizer=opt, metrics=[tfa.metrics.CohenKappa(num_classes=4)])
return model
拟合模型时,我可以在 TensorBoard 上看到以下指标:
我不确定以下几点,希望得到澄清:
- 我用对了吗?
- 在我原来的问题中,我预测了 3 个分数,而在 Colab 示例中我只预测了 1 个分数。如果我使用 WeightedKappaLoss,这是否意味着我需要转换每个分数100 one-hot 编码向量的分数?
- 有没有办法在原始浮点分数上使用 WeightedKappaLoss 而无需转换为 class化问题?
让我们把目标分成两个子目标,我们遍历目的、概念、数学先是Weighted Kappa
的details,然后总结一下在tensorflow
WeightedKappaLoss
时的注意事项
PS: 只关心用法的可以跳过理解部分
加权Kappa详解
由于Weighted Kappa可以看成Cohen's kappa + weights,所以我们需要了解Cohen's kappa 第一
Cohen 的 kappa 示例
假设我们有两个 classifier(A 和 B)试图 class将 50 个陈述分为两类(真和假),他们 class证明这些陈述的方式在偶然事件中彼此 wrt table:
B
True False
A True 20 5 25 statements A think is true
False 10 15 25 statements A think is false
30 statements B think is true
20 statements B think is false
现在假设我们想知道:A 和 B 做出的预测有多可靠?
我们可以做的是简单地取classA和B彼此一致的化验陈述的百分比,即观察到的一致的比例表示为Po
,所以:
Po = (20 + 15) / 50 = 0.7
但这是有问题的,因为有概率A和B随机一致,即期望概率一致的比例表示为Pe
,如果我们使用观察到的百分比作为期望概率,那么:
Pe = (probability statement A think is true) * (probability statement B think is true) +
(probability statement A think is false) * (probability statement B think is false)
= (25 / 50) * (30 / 50) +
(25 / 50) * (20 / 50)
= 0.5
Cohen 的 kappa 系数 表示为 K
合并了 Po
和 Pe
给我们关于预测 A 和B发:
K = (Po - Pe) / (1 - Pe) = 1 - (1 - Po) / (1 - Pe) = 1 - (1 - 0.7) / (1 - 0.5) = 0.4
我们可以看到 A 和 B 彼此越一致(Po
更高)并且他们因为偶然而越不一致(Pe
更低),Cohen 的越多kappa“认为”结果可靠
现在假设 A 是陈述的标签(ground truth),那么 K
告诉我们 B 的预测有多可靠,即当考虑随机机会时,预测与标签的一致性程度
Cohen 的 kappa 权重
我们正式定义偶然性table和m
classes:
classifier 2
class.1 class.2 class... class.k Sum over row
class.1 n11 n12 ... n1k n1+
class.2 n21 n22 ... n2k n2+
classifier 1 class... ... ... ... ... ...
class.k nk1 nk2 ... nkk nk+
Sum over column n+1 n+2 ... n+k N # total sum of all table cells
table 单元格包含交叉class化类别的计数,分别表示为 nij
、i,j
行和列索引
考虑那些 k
序数 classes 与两个分类 classes 分开,例如将 1, 0
分成五个 classes 1, 0.75, 0.5, 0.25, 0
具有平滑有序的过渡,我们不能说 class 是独立的,除了第一个和最后一个 class,例如 very good, good, normal, bad, very bad
、very good
和 good
不是独立的,good
应该更接近 bad
而不是 very bad
由于相邻的class是相互依赖的,那么为了计算与协议相关的数量,我们需要定义这种依赖关系,即权重表示为Wij
,它分配给意外事件 table 中的每个单元格,权重值(在范围 [0, 1] 内)取决于两个 classes
现在让我们看看 Weighted Kappa 中的 Po
和 Pe
公式:
以及 Po
和 Pe
公式 Cohen 的 kappa:
我们可以看到 Po
和 Pe
公式 Cohen 的 kappa 是 Weighted Kappa[=206= 公式的特例],其中 weight = 1
分配给所有对角线单元格,其他地方的权重 = 0,当我们使用 [=166= 中的 Po
和 Pe
公式计算 K
(Cohen 的 kappa 系数)时]加权 Kappa 我们还考虑了相邻 class 之间的依赖关系
这里有两种常用的权重系统:
- 线宽:
- 二次权重:
其中,|i-j|
是classes之间的距离,k
是classes的个数
加权 Kappa 损失
这种损失是在我们之前提到的情况下使用的,其中一个 classifier 是标签,这种损失的目的是使模型(另一个 classifier)的预测与可能,即鼓励模型做出更多与标签一致的预测,同时在考虑相邻 classes 之间的依赖性时减少随机猜测
Weighted Kappa Loss的公式由:
给出它只是采用负 Cohen 的 kappa 系数 的公式并去掉常数 -1
然后应用 自然对数 , 其中 dij = |i-j|
代表 线性权重 , dij = (|i-j|)^2
代表 二次权重
下面是用tensroflow写的Weighted Kappa Loss的源码,可以看到只是实现了Weighted Kappa Loss的公式] 以上:
import warnings
from typing import Optional
import tensorflow as tf
from typeguard import typechecked
from tensorflow_addons.utils.types import Number
class WeightedKappaLoss(tf.keras.losses.Loss):
@typechecked
def __init__(
self,
num_classes: int,
weightage: Optional[str] = "quadratic",
name: Optional[str] = "cohen_kappa_loss",
epsilon: Optional[Number] = 1e-6,
dtype: Optional[tf.DType] = tf.float32,
reduction: str = tf.keras.losses.Reduction.NONE,
):
super().__init__(name=name, reduction=reduction)
warnings.warn(
"The data type for `WeightedKappaLoss` defaults to "
"`tf.keras.backend.floatx()`."
"The argument `dtype` will be removed in Addons `0.12`.",
DeprecationWarning,
)
if weightage not in ("linear", "quadratic"):
raise ValueError("Unknown kappa weighting type.")
self.weightage = weightage
self.num_classes = num_classes
self.epsilon = epsilon or tf.keras.backend.epsilon()
label_vec = tf.range(num_classes, dtype=tf.keras.backend.floatx())
self.row_label_vec = tf.reshape(label_vec, [1, num_classes])
self.col_label_vec = tf.reshape(label_vec, [num_classes, 1])
col_mat = tf.tile(self.col_label_vec, [1, num_classes])
row_mat = tf.tile(self.row_label_vec, [num_classes, 1])
if weightage == "linear":
self.weight_mat = tf.abs(col_mat - row_mat)
else:
self.weight_mat = (col_mat - row_mat) ** 2
def call(self, y_true, y_pred):
y_true = tf.cast(y_true, dtype=self.col_label_vec.dtype)
y_pred = tf.cast(y_pred, dtype=self.weight_mat.dtype)
batch_size = tf.shape(y_true)[0]
cat_labels = tf.matmul(y_true, self.col_label_vec)
cat_label_mat = tf.tile(cat_labels, [1, self.num_classes])
row_label_mat = tf.tile(self.row_label_vec, [batch_size, 1])
if self.weightage == "linear":
weight = tf.abs(cat_label_mat - row_label_mat)
else:
weight = (cat_label_mat - row_label_mat) ** 2
numerator = tf.reduce_sum(weight * y_pred)
label_dist = tf.reduce_sum(y_true, axis=0, keepdims=True)
pred_dist = tf.reduce_sum(y_pred, axis=0, keepdims=True)
w_pred_dist = tf.matmul(self.weight_mat, pred_dist, transpose_b=True)
denominator = tf.reduce_sum(tf.matmul(label_dist, w_pred_dist))
denominator /= tf.cast(batch_size, dtype=denominator.dtype)
loss = tf.math.divide_no_nan(numerator, denominator)
return tf.math.log(loss + self.epsilon)
def get_config(self):
config = {
"num_classes": self.num_classes,
"weightage": self.weightage,
"epsilon": self.epsilon,
}
base_config = super().get_config()
return {**base_config, **config}
加权 Kappa 损失的使用
只要我们可以将问题转化为序数分类问题,即classes,我们就可以使用加权Kappa损失形成一个平滑有序的过渡并且相邻的 class 是相互依赖的,就像用 very good, good, normal, bad, very bad
对某些东西进行排名一样,模型的输出应该像 Softmax
results
当我们尝试预测分数向量 (0-1) 时,即使它们总和为 1
,我们也不能使用 加权 Kappa 损失,因为 weights在vector的每个元素中是不同的,这个loss不是问减去的值有多少不同,而是问乘法的数字有多少,例如:
import tensorflow as tf
from tensorflow_addons.losses import WeightedKappaLoss
y_true = tf.constant([[0.1, 0.2, 0.6, 0.1], [0.1, 0.5, 0.3, 0.1],
[0.8, 0.05, 0.05, 0.1], [0.01, 0.09, 0.1, 0.8]])
y_pred_0 = tf.constant([[0.1, 0.2, 0.6, 0.1], [0.1, 0.5, 0.3, 0.1],
[0.8, 0.05, 0.05, 0.1], [0.01, 0.09, 0.1, 0.8]])
y_pred_1 = tf.constant([[0.0, 0.1, 0.9, 0.0], [0.1, 0.5, 0.3, 0.1],
[0.8, 0.05, 0.05, 0.1], [0.01, 0.09, 0.1, 0.8]])
kappa_loss = WeightedKappaLoss(weightage='linear', num_classes=4)
loss_0 = kappa_loss(y_true, y_pred_0)
loss_1 = kappa_loss(y_true, y_pred_1)
print('Loss_0: {}, loss_1: {}'.format(loss_0.numpy(), loss_1.numpy()))
输出:
# y_pred_0 equal to y_true yet loss_1 is smaller than loss_0
Loss_0: -0.7053321599960327, loss_1: -0.8015820980072021
您在 Colab 中的代码在 序数分类问题 的上下文中正常工作,因为您形成的函数 X->Y
非常简单(int of X 是 Y 指数 + 1),所以模型学习它相当快速和准确,正如我们可以看到 K
(Cohen 的 kappa 系数)高达 1.0
和加权 Kappa 损失下降到 -13.0
以下(在实践中通常是我们可以期望的最小值)
总而言之,您可以使用加权 Kappa 损失,除非您可以将您的问题形成为 序数分类问题,其中标签在一个-热门时尚,如果你可以并尝试解决 LTR(学习排名)问题,那么你可以检查 this tutorial of implement ListNet and this tutorial of tensorflow_ranking 以获得更好的结果,否则你不应该使用 Weighted Kappa Loss,如果你的问题只能形成回归问题,那么你应该按照你原来的解决方案
参考:
Weighted Kappa in R: For Two Ordinal Variables
source code of WeightedKappaLoss in tensroflow-addons
Documentation of tfa.losses.WeightedKappaLoss
Difference between categorical, ordinal and numerical variables