gpt4 book ai didi

python - 使用 Keras 了解 WeightedKappaLoss

转载 作者:行者123 更新时间:2023-12-04 11:09:56 25 4
gpt4 key购买 nike

我正在使用 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
我想把这个问题作为序数分类,所以如果实际值为 [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
我的目标是了解 的用法加权 Kappa 损失 并在我的实际数据上实现它。我创建了 this Colab 摆弄这个想法。在 Colab 中,我的数据是一个序列形状的 (5000,3,3)我的目标形状是 (5000, 4)代表 4 个可能的类中的 1 个。
我希望模型理解它需要修剪 X 的浮点数以预测正确的 y 类:
[[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 上看到以下指标:
enter image description here enter image description here
我不确定以下几点,希望得到澄清:
  • 我用对了吗?
  • 在我最初的问题中,我预测了 3 个分数,而不是 Colab 示例,我只预测了 1 个。如果我使用的是 WeightedKappaLoss,是否意味着我需要将每个分数转换为向量100 个单热编码?
  • 有没有办法在原始浮点分数上使用 WeightedKappaLoss 而不转换为分类问题?
  • 最佳答案

    让我们把目标分成两个子目标,我们遍历用途 , 概念 , 数学细节Weighted Kappa首先,然后我们总结了我们尝试使用WeightedKappaLoss时的注意事项。在 tensorflow 中
    PS:如果只关心用法可以跳过理解部分

    加权Kappa详解
    加权 Kappa 可以看成科恩的 kappa + 权重 ,所以我们需要了解科恩的河童第一的
    科恩 kappa 的例子
    假设我们有两个分类器(A 和 B)试图将 50 个语句分为两类(真和假),它们在列联表中将这些语句相互分类:

             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 的预测有多可靠?
    我们可以做的只是简单地取A和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
    科恩的 kappa 系数 表示为 K包含 PoPe为我们提供关于预测 A 和 B 的可靠性的更可靠的预测:
    enter image description here
    K = (Po - Pe) / (1 - Pe) = 1 - (1 - Po) / (1 - Pe) = 1 - (1 - 0.7) / (1 - 0.5) = 0.4
    我们可以看到,A 和 B 越是一致( Po 更高),他们因偶然而一致越少( Pe 更低), 越多。科恩的河童 “认为”结果可靠
    现在假设 A 是陈述的标签(基本事实),然后 K告诉我们 B 的预测有多可靠,即当考虑随机机会时,预测与标签有多少一致
    Cohen 的 kappa 的权重
    我们用 m 定义列联表正式上课:
                                        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
    表格单元格包含交叉分类类别的计数,表示为 nij , i,j分别用于行和列索引
    考虑那些 k序数类与两个分类类分开,例如单独的 1, 0分为五个类 1, 0.75, 0.5, 0.25, 0具有平滑有序的过渡,我们不能说除了第一个和最后一个类之外的类是独立的,例如 very good, good, normal, bad, very bad , very goodgood不独立和 good应该更接近 bad比到 very bad由于相邻的类是相互依赖的,所以为了计算与协议(protocol)相关的数量,我们需要定义这个依赖关系,即 重量 表示为 Wij ,它分配给列联表中的每个单元格,权重的值(在 [0, 1] 范围内)取决于两个类的接近程度
    现在我们来看 PoPe 中的公式加权 Kappa :
    enter image description here
    PoPe 中的公式科恩的河童 :
    enter image description here
    我们可以看到 PoPe 中的公式科恩的河童 中公式的特例加权 Kappa ,其中 weight = 1当我们计算 K 时,分配给所有对角线单元格且权重 = 0 其他地方(科恩的 kappa 系数)使用 PoPe 中的公式加权 Kappa 我们还考虑了相邻类之间的依赖关系
    下面介绍两种常用的称重系统:
  • 线性权重:

  • enter image description here
  • 二次权重:

  • enter image description here
    哪里, |i-j|是类与 k 之间的距离是类的数量
    加权 Kappa 损失
    这种损失用于我们之前提到的一个分类器是标签的情况,这种损失的目的是使模型(另一个分类器)的预测尽可能可靠,即鼓励模型使更多的预测与标签一致,同时减少考虑相邻类之间的依赖性时的随机猜测
    的公式加权 Kappa 损失 由:
    enter image description here
    只需取负公式 科恩的 kappa 系数 并摆脱常数 -1然后申请 自然对数在它上面,哪里 dij = |i-j|线性重量 , dij = (|i-j|)^2二次权重
    以下是 的源代码加权 Kappa 损失 用tensroflow写的,你可以看到它只是实现了 的公式加权 Kappa 损失 以上:
    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 损失的使用
    我们可以使用 加权 Kappa 损失 每当我们可以将问题形成到 序数分类问题 ,即类形成平滑有序的过渡,相邻的类是相互依赖的,就像用 very good, good, normal, bad, very bad 对某事物进行排名一样,模型的输出应该像 Softmax结果
    我们不能使用 加权 Kappa 损失 当我们尝试预测分数 (0-1) 的向量时,即使它们的总和可以为 1 , 自 重量 在向量的每个元素中都是不同的,这种损失不是通过减法询问值有多大不同,而是通过乘法询问数字有多少,例如:
    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非常简单(X 的整数是 Y 索引 + 1),所以模型学习它相当快速和准确,如我们所见 K (Cohen 的 kappa 系数)高达 1.0和加权 Kappa 损失低于 -13.0 (这在实践中通常是我们可以预期的最低限度)
    总之,您可以使用 加权 Kappa 损失 除非您可以将您的问题发送至 序数分类问题以 one-hot 方式有标签,如果你可以尝试解决 LTR(学习排名)问题,那么你可以查看 this tutorial of implement ListNetthis tutorial of tensorflow_ranking为了更好的结果,否则你不应该使用 加权 Kappa 损失 ,如果您只能将问题形成到 回归问题 ,那么你应该像你原来的解决方案一样

    引用:
    Cohen's kappa on Wikipedia
    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

    关于python - 使用 Keras 了解 WeightedKappaLoss,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65305864/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com