mask和class_conf_mask的作用

代码 

import torch
import torch.nn.functional as F
import numpy as np

# 模拟logits数据(随机生成)
batch_size = 4  # 假设有4个样本
class_num = 5  # 假设有5个类别

# 模拟教师模型输出的logits,维度为 [batch_size, class_num]
logits_teacher_weak = torch.randn(batch_size, class_num)

# 打印logits_teacher_weak的值
print("logits_teacher_weak:\n", logits_teacher_weak)

# 将logits通过softmax转换为概率分布
pred_teacher_weak = F.softmax(logits_teacher_weak.detach(), dim=1)

# 打印转换后的概率分布
print("\npred_teacher_weak (softmax output):\n", pred_teacher_weak)

# 计算每个样本的最大概率值(即置信度)和伪标签
confidence, pseudo_labels = pred_teacher_weak.max(dim=1)

# 打印每个样本的最大概率值(置信度)和伪标签
print("\nconfidence (max probabilities):\n", confidence)
print("\npseudo_labels (pseudo labels based on max probabilities):\n", pseudo_labels)

# 分离置信度,确保它不参与梯度计算
confidence = confidence.detach()

# 计算50%分位数(即中位数),作为阈值
conf_thresh = np.percentile(
    confidence.cpu().numpy().flatten(), 50
)

# 打印置信度阈值
print("\nconf_thresh (confidence threshold, 50th percentile):\n", conf_thresh)

# 生成mask,标记置信度小于等于阈值的样本
mask = confidence.le(conf_thresh).bool()

# 打印mask
print("\nmask (samples with confidence <= threshold):\n", mask)

# ============== 类别置信度部分 ==============
# 计算每个类别的置信度(所有样本在该类别上的预测概率之和)
class_confidence = torch.sum(pred_teacher_weak, dim=0)

# 打印类别置信度
print("\nclass_confidence (sum of probabilities across samples for each class):\n", class_confidence)

# 分离类别置信度,确保它不参与梯度计算
class_confidence = class_confidence.detach()

# 计算类别置信度的50%分位数作为阈值
class_confidence_thresh = np.percentile(
    class_confidence.cpu().numpy().flatten(), 50
)

# 打印类别置信度阈值
print("\nclass_confidence_thresh (class confidence threshold, 50th percentile):\n", class_confidence_thresh)

# 生成class_conf_mask,标记类别置信度小于等于阈值的类别
class_conf_mask = class_confidence.le(class_confidence_thresh).bool()

# 打印类别掩码
print("\nclass_conf_mask (classes with confidence <= threshold):\n", class_conf_mask)

逐行解释1

  • logits_teacher_weak = torch.randn(batch_size, class_num)

    • 随机生成一组教师模型的logits输出,模拟批次中每个样本对各个类别的预测。
    • 输出:一个形状为 [batch_size, class_num] 的tensor,表示教师模型在弱增强数据上的logits。
  • pred_teacher_weak = F.softmax(logits_teacher_weak.detach(), dim=1)

    • 使用 softmax 将logits转换为概率分布,dim=1 表示在类别维度上进行softmax操作。
    • 输出:每个样本在每个类别上的预测概率。
  • confidence, pseudo_labels = pred_teacher_weak.max(dim=1)

    • 找到每个样本预测概率的最大值(即置信度)以及对应的类别(伪标签)。
    • 输出
      • confidence:每个样本的最大概率(置信度)。
      • pseudo_labels:每个样本的伪标签(概率最大的类别)。
  • confidence = confidence.detach()

    • confidence 与计算图分离,确保它不参与梯度计算(为了防止反向传播时对置信度进行梯度更新)。
    • 输出:与之前相同的置信度,但不参与梯度计算。
  • conf_thresh = np.percentile(confidence.cpu().numpy().flatten(), 50)

    • 计算置信度的50%分位数(即中位数),作为后续生成掩码的阈值。
    • 输出:表示所有样本置信度的中位数。
  • mask = confidence.le(conf_thresh).bool()

    • 生成一个布尔掩码,标记置信度小于等于阈值的样本。le 表示小于等于操作。
    • 输出:一个布尔向量,True 表示该样本的置信度低于或等于阈值。

输出示例1

假设我们随机生成的 logits_teacher_weak 如下:

logits_teacher_weak:
 tensor([[ 1.5074, -0.3623, -0.3050,  0.7985,  1.3345],
        [-0.2311, -0.7265,  0.3124, -0.3955, -0.5713],
        [-0.0377,  0.0672, -0.6561, -0.3366, -1.2700],
        [ 0.3643, -0.2974,  0.4942, -1.3482,  0.1723]])

经过softmax转换后,得到概率分布:

pred_teacher_weak (softmax output):
 tensor([[0.4005, 0.0641, 0.0678, 0.1913, 0.2763],
        [0.2145, 0.1300, 0.3662, 0.1841, 0.1051],
        [0.2463, 0.2726, 0.1460, 0.1970, 0.1381],
        [0.2883, 0.1476, 0.3273, 0.0457, 0.1910]])

置信度和伪标签:

confidence (max probabilities):
 tensor([0.4005, 0.3662, 0.2726, 0.3273])

pseudo_labels (pseudo labels based on max probabilities):
 tensor([0, 2, 1, 2])

置信度的阈值(50%分位数):

conf_thresh (confidence threshold, 50th percentile):
 0.3368

生成的mask:

mask (samples with confidence <= threshold):
 tensor([False, False,  True,  True])

逐行解释2

  1. class_confidence = torch.sum(pred_teacher_weak, dim=0)

    • 计算每个类别的总置信度,即将所有样本在该类别上的预测概率进行求和。结果是一个长度为 class_num 的向量,表示每个类别的总置信度。
    • 输出:每个类别的置信度总和。
  2. class_confidence = class_confidence.detach()

    • 将类别置信度与计算图分离,确保它不参与梯度计算。
  3. class_confidence_thresh = np.percentile(class_confidence.cpu().numpy().flatten(), 50)

    • 计算类别置信度的50%分位数,作为后续生成 class_conf_mask 的阈值。这个阈值用于区分置信度高和低的类别。
  4. class_conf_mask = class_confidence.le(class_confidence_thresh).bool()

    • 生成类别掩码 class_conf_mask,标记置信度低于或等于阈值的类别。le 表示小于等于操作。

输出示例2

假设我们随机生成的 logits_teacher_weak 如下:

logits_teacher_weak:
 tensor([[ 0.6654, -0.3170, -0.3315,  0.5557, -0.0610],
        [ 0.1992, -0.4481, -0.5696,  0.3045, -0.5566],
        [-0.2331,  1.5880,  1.1310,  1.1659,  0.0431],
        [-0.6817, -0.4727, -0.1713, -0.3666,  0.1745]])

经过 softmax 转换后:

pred_teacher_weak (softmax output):
 tensor([[0.3366, 0.1341, 0.1322, 0.3018, 0.0953],
        [0.2830, 0.1609, 0.1422, 0.3155, 0.0985],
        [0.0408, 0.3931, 0.2492, 0.2565, 0.0604],
        [0.1835, 0.2246, 0.3039, 0.2501, 0.0379]])

类别置信度和阈值如下:

class_confidence (sum of probabilities across samples for each class):
 tensor([0.8439, 0.9127, 0.8275, 1.1239, 0.2919])

class_confidence_thresh (class confidence threshold, 50th percentile):
 0.8439

生成的 class_conf_mask

class_conf_mask (classes with confidence <= threshold):
 tensor([ True, False,  True, False,  True])

这个 class_conf_mask 表示第1、第3和第5类的置信度小于等于阈值,标记为 True

10-21
这段代码:def evaluate_attributes(y_true, y_prob, y_conf, prob_threshold, conf_threshold): """ 通用的属性识别性能评价函数。 Args: y_true (np.ndarray): 真实标签, shape (N, C), -1 代表未知。 y_prob (np.ndarray): 预测的属性概率, shape (N, C)。 y_conf (np.ndarray): 预测的置信度, shape (N, 1) 或 (N, C)。 prob_threshold (float): 属性概率阈值。 conf_threshold (float): 置信度阈值。 Returns: pd.DataFrame: 包含每个子属性 Precision, Recall, F1-Score 的报告。 """ y_pred = np.full_like(y_prob, -1, dtype=int) #处理二元属性 binary_indices = [v['idx'] for k, v in ATTRIBUTE_MAPPING.items() if isinstance(v['idx'], int)] # 提取二元属性对应的数据 binary_prob = y_prob[:, binary_indices] # 根据 y_conf 的形状,正确提取置信度 binary_conf = y_conf if y_conf.shape[1] > 1 else y_conf[:, 0:1] # 应用二元属性的预测逻辑 ##################这里是大于等于小于等于 cond_predict_1 = (binary_conf >= conf_threshold) & (binary_prob >= prob_threshold) if prob_threshold!=0.5: cond_predict_0 = (binary_conf >= conf_threshold) & (binary_prob <= (1-prob_threshold)) else: cond_predict_0 = (binary_conf >= conf_threshold) & (binary_prob < (1-prob_threshold)) binary_pred = np.select([cond_predict_1, cond_predict_0], [1, 0], default=-1) y_pred[:, binary_indices] = binary_pred # --- 处理互斥多分类属性 (lower_body) --- multi_class_slice = ATTRIBUTE_MAPPING['lower_body']['idx'] # 提取下装类型对应的数据 multi_class_prob = y_prob[:, multi_class_slice] # 根据 y_conf 形状,正确提取并计算该组的置信度 if y_conf.shape[1] > 1: # 逐属性置信度:取该组的平均值 multi_class_conf = np.mean(y_conf[:, multi_class_slice], axis=1) else: # 全局置信度 multi_class_conf = y_conf.flatten() # 筛选出置信度达标的样本 confident_samples_mask = multi_class_conf >= conf_threshold if np.any(confident_samples_mask): confident_probs = multi_class_prob[confident_samples_mask] # 找到最大概率及其索引 max_probs = np.max(confident_probs, axis=1) argmax_indices = np.argmax(confident_probs, axis=1) # 在置信度达标的样本中,再次筛选出最大概率也达标的样本 #################裤子判断标准为大于等于 passes_prob_thresh_mask = max_probs >= prob_threshold # passes_prob_thresh_mask = max_probs >= 0 # 获取最终要更新的样本的索引 final_update_indices = np.where(confident_samples_mask)[0][passes_prob_thresh_mask] final_argmax_indices = argmax_indices[passes_prob_thresh_mask] # 创建 one-hot 预测结果并更新到 y_pred # 只有在 final_update_indices 中的样本才会被更新(从-1变为0或1) final_predictions = np.zeros((len(final_update_indices), 3), dtype=int) final_predictions[np.arange(len(final_update_indices)), final_argmax_indices] = 1 y_pred[final_update_indices, multi_class_slice] = final_predictions:中所有类别的概率阈值置信度阈值是统一的,能否修改为不同类别使用不同的阈值。
10-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值