类感知对比半监督学习(Class-Aware Contrastive Semi-Supervised Learning)论文阅读笔记

文献地址:论文链接,Github代码:Github链接

1 研究背景

现有基于伪标签的半监督学习方法存在的问题:

  • 伪标签 → 存在确认偏差(Confirmation Bias)
  • 分布外噪声数据 → 影响模型的判别能力
  • 是否存在一种通用增益方法,可适用于各基于伪标签的半监督方法?
    • MixMatch[1](NIPS, 2019):数据Mixup → 预测锐化(Sharpen)
    • FixMatch[2](NIPS, 2020):置信度阈值,弱增强 → 生成伪标签 → 监督强增强

2 关键卖点

  • 提出一套缓解确认偏差(Confirmation Bias)的通用架构:
    • 对于可靠的分布内数据(In-distribution Data):使用有监督对比学习。
      • 分布内数据:指无标记数据集不包含新类别,或具有平衡的数据分布的数据。
    • 对于存在噪声的分布外数据(Out-of-distribution Data):对特征进行无监督对比学习。
      • 分布外数据:指无标记数据集包含未知类别,或具有不平衡的数据分布的数据。
  • 针对伪标签存在的噪声问题:进行权重分配。

3 主要架构

  • 整体架构目标:最小化相似性矩阵(Feature Affinity)和目标矩阵(Target Matrix)之间的有监督对比损失L_{con},无标签的强增强样本与弱增强样本生成的伪标签之间的交叉熵损失L_{u},以及有标签样本的交叉熵损失L_{x}。即\mathcal{L}=\mathcal{L}_{x}+\lambda_{u} \mathcal{L}_{u}+\lambda_{c} \mathcal{L}_{c}
  • 对于有标签样本:采用图像的弱增强视图进行有监督学习,优化交叉熵损失。
    •  通过预测层(Cls Head),计算交叉熵损失:\ell_{sup}=\frac{1}{B} \sum_{i=1}^{B} \mathrm{H}\left(y_{i}, P_{​{cls}}\left( Aug_{w}\left(x_{i}\right)\right)\right)

    • 输入:\mathcal{X}=\left\{\left(x_{i}, y_{i}\right): i \in(1, \ldots, B)\right\},其中x_{i}为第i张图片,y_{i}为该图片对应的one-hot向量,B为采样的一个批量大小。
    • 输出:p_{m}\left ( y|x \right ),模型对输入x产生的预测类别分布。
图1 CCSSL架构。给定一个批次的无标记图像,弱增强视图经过半监督模块,该模块可以采用任意的基于伪标签的半监督学习方法来产生模型预测结果。
  • 对于无标签样本:
    • 输入:\mathcal{U}=\left\{u_{i}: i \in(1, \ldots, \mu B)\right\},其中\mu是一个超参数,权衡有标签样本集\mathcal{X}和无标签样本集\mathcal{U}的相
"Structure-Aware Transformer for Graph Representation Learning"是一篇使用Transformer模型进行图表示学习的论文。这篇论文提出了一种名为SAT(Structure-Aware Transformer)的模型,它利用了图中节点之间的结构信息,以及节点自身的特征信息。SAT模型在多个图数据集上都取得了非常好的结果。 以下是SAT模型的dgl实现代码,代码中使用了Cora数据集进行示例: ``` import dgl import numpy as np import torch import torch.nn as nn import torch.nn.functional as F class GraphAttentionLayer(nn.Module): def __init__(self, in_dim, out_dim, num_heads): super(GraphAttentionLayer, self).__init__() self.num_heads = num_heads self.out_dim = out_dim self.W = nn.Linear(in_dim, out_dim*num_heads, bias=False) nn.init.xavier_uniform_(self.W.weight) self.a = nn.Parameter(torch.zeros(size=(2*out_dim, 1))) nn.init.xavier_uniform_(self.a.data) def forward(self, g, h): h = self.W(h).view(-1, self.num_heads, self.out_dim) # Compute attention scores with g.local_scope(): g.ndata['h'] = h g.apply_edges(fn.u_dot_v('h', 'h', 'e')) e = F.leaky_relu(g.edata.pop('e'), negative_slope=0.2) g.edata['a'] = torch.cat([e, e], dim=1) g.edata['a'] = torch.matmul(g.edata['a'], self.a).squeeze() g.edata['a'] = F.leaky_relu(g.edata['a'], negative_slope=0.2) g.apply_edges(fn.e_softmax('a', 'w')) # Compute output features g.ndata['h'] = h g.update_all(fn.u_mul_e('h', 'w', 'm'), fn.sum('m', 'h')) h = g.ndata['h'] return h.view(-1, self.num_heads*self.out_dim) class SATLayer(nn.Module): def __init__(self, in_dim, out_dim, num_heads): super(SATLayer, self).__init__() self.attention = GraphAttentionLayer(in_dim, out_dim, num_heads) self.dropout = nn.Dropout(0.5) self.norm = nn.LayerNorm(out_dim*num_heads) def forward(self, g, h): h = self.attention(g, h) h = self.norm(h) h = F.relu(h) h = self.dropout(h) return h class SAT(nn.Module): def __init__(self, in_dim, hidden_dim, out_dim, num_heads): super(SAT, self).__init__() self.layer1 = SATLayer(in_dim, hidden_dim, num_heads) self.layer2 = SATLayer(hidden_dim*num_heads, out_dim, 1) def forward(self, g, h): h = self.layer1(g, h) h = self.layer2(g, h) return h.mean(0) # Load Cora dataset from dgl.data import citation_graph as citegrh data = citegrh.load_cora() g = data.graph features = torch.FloatTensor(data.features) labels = torch.LongTensor(data.labels) train_mask = torch.BoolTensor(data.train_mask) val_mask = torch.BoolTensor(data.val_mask) test_mask = torch.BoolTensor(data.test_mask) # Add self loop g = dgl.remove_self_loop(g) g = dgl.add_self_loop(g) # Define model and optimizer model = SAT(features.shape[1], 64, data.num_classes, 8) optimizer = torch.optim.Adam(model.parameters(), lr=0.005, weight_decay=5e-4) # Train model for epoch in range(200): model.train() logits = model(g, features) loss = F.cross_entropy(logits[train_mask], labels[train_mask]) optimizer.zero_grad() loss.backward() optimizer.step() acc = (logits[val_mask].argmax(1) == labels[val_mask]).float().mean() if epoch % 10 == 0: print('Epoch {:03d} | Loss {:.4f} | Accuracy {:.4f}'.format(epoch, loss.item(), acc.item())) # Test model model.eval() logits = model(g, features) acc = (logits[test_mask].argmax(1) == labels[test_mask]).float().mean() print('Test accuracy {:.4f}'.format(acc.item())) ``` 在这个示例中,我们首先加载了Cora数据集,并将其转换为一个DGL图。然后,我们定义了一个包含两个SAT层的模型,以及Adam优化器。在训练过程中,我们使用交叉熵损失函数和验证集上的准确率来监控模型的性能。在测试阶段,我们计算测试集上的准确率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值