上传文件至 /
parent
a87911a061
commit
90f3dcffd0
|
@ -0,0 +1,107 @@
|
|||
# 12月5日科研工作进展
|
||||
|
||||
## 目前进度
|
||||
|
||||
### 1.对之前的代码与数据进行了梳理、错误检查与修正
|
||||
|
||||
#### 问题解决:
|
||||
|
||||
##### (1)在低聚类的情况下,存在模型不能很好引导训练的情况:
|
||||
|
||||
如图,在聚类数较小的情况下,acc_proto应该较高,因为原型数本就较少,但之前的训练存在acc_proto在热身结束后接近0的情况,这存在问题。
|
||||
|
||||
![log5](/home/ringo/文档/PCL/experiment/log4.png)
|
||||
|
||||
###### 原因:
|
||||
|
||||
1️⃣在较小的聚类条件下,单个簇中样本数目大,分布较为分散,此时查询样本q可能存在于簇边缘和聚类中心的相似度较低,而训练初期模型其实并不确定该样本的归属,强行拉近可能存在错误。
|
||||
|
||||
2️⃣在较小的聚类条件下,由于总簇数cluster_result(如10个聚类)小于batchsize样本数(如64),在采样过程中会导致多个样本被分到一个聚类中,导致每个样本分配的原型pos_proto_id出现重复(如[2,2, 2, 1, 0])。但样本的标签依旧保持顺序分布(如[0, 1, 2, 3, 4]),这使得在计算loss时将相同id的聚类推开,导致训练异常,同时导致计算loss与精度的问题。
|
||||
|
||||
```python
|
||||
all_proto_id = [i for i in range(im2cluster.max()+1)]
|
||||
|
||||
pos_proto_id = im2cluster[index]
|
||||
pos_prototypes = prototypes[pos_proto_id]
|
||||
|
||||
neg_proto_id = set(all_proto_id)-set(pos_proto_id.tolist())
|
||||
neg_proto_id = sample(neg_proto_id,self.r)
|
||||
neg_prototypes = prototypes[neg_proto_id]
|
||||
|
||||
proto_selected = torch.cat([pos_prototypes,neg_prototypes],dim=0)
|
||||
|
||||
logits_proto = torch.mm(q,proto_selected.t())
|
||||
labels_proto = torch.linspace(0, q.size(0)-1, steps=q.size(0)).long().cuda()
|
||||
|
||||
loss = loss_criterion(logits_proto, labels_proto)
|
||||
```
|
||||
|
||||
###### 解决办法:
|
||||
|
||||
(1)目前使用了调整标签的方法进行了修正,即根据选择原型的id修正查询样本的标签,如原型id为[2, 2, 2, 1, 0],样本的为[0, 1, 2, 3, 4],调整后为[0, 0, 0, 3, 4],代码如下:
|
||||
|
||||
```python
|
||||
def adjust_labels(proto_selected, labels_proto):
|
||||
for value in torch.unique(proto_selected):
|
||||
# 获取B中该元素的所有位置
|
||||
indices = torch.nonzero(proto_selected == value).squeeze()
|
||||
# 确保 indices 是一维张量,避免0维张量的问题
|
||||
indices = indices.reshape(-1)
|
||||
# 确保indices有元素,防止空张量错误
|
||||
if indices.numel() > 0:
|
||||
# 获取最小的位置(即第一个出现的位置)
|
||||
min_index = indices[0].item() # 使用.item()获取标量值
|
||||
# 检查 min_index 是否越界
|
||||
if min_index < len(labels_proto):
|
||||
# 将labels_proto中这些位置的元素替换为labels_proto中min_index位置的值
|
||||
labels_proto[indices] = labels_proto[min_index].clone()
|
||||
else:
|
||||
continue
|
||||
return labels_proto
|
||||
```
|
||||
|
||||
调整效果:
|
||||
|
||||
可见loss与acc正常工作了,在热身结束后acc_proto相较之前提升巨大,且随着训练与聚类数的提升而不断增加,在epoch25左右达到顶峰(聚类数3,6,15)。loss__proto则在epoch37左右达到最低(聚类数60,120,240),怀疑为训练数据集的100分类引起。
|
||||
|
||||
![log6](/home/ringo/文档/PCL/log6.png)
|
||||
|
||||
(2)针对原因1️⃣的问题,决定使用新的loss方式对聚类数较低时进行调整:
|
||||
|
||||
直接最小化样本与其**最相似原型**之间的距离可能在某些情况下过于强硬,特别是当数据本身存在一定的噪声或存在多个相似的原型时,这种方法可能导致不理想的聚类结果。为了避免这种情况,可以采用以下两种思路:**最小化样本与最相似的 K 个原型之间的距离**,或**最大化样本与不相似原型之间的距离**。
|
||||
|
||||
##### 实现方法:
|
||||
|
||||
- **K 最近原型**:对于每个样本,计算它与所有原型之间的距离,然后选择距离最小的 K 个原型。
|
||||
- **加权距离**:为了更好地处理样本与多个原型之间的关系,可以给每个原型分配一个权重(通常根据距离反比或其他策略来决定权重),然后计算加权距离作为损失的一部分。
|
||||
|
||||
###### 损失函数设计:
|
||||
|
||||
1️⃣**最小化样本与最相似的 K 个原型之间的距离,最大化与不相似的原型之间的距离**
|
||||
|
||||
假设有一个样本$$x_i$$ ,它与$$K$$个原型的相似度分别为$$s_{i1},s_{i2},...,s_{iK}$$。可以设计如下损失函数:
|
||||
$$
|
||||
Loss_i=∑_{k=1}^Kw_k⋅∥x_i−μ_k∥2
|
||||
$$
|
||||
其中,$$w_k$$是与原型 $$μ_k$$相关的权重(例如与距离成反比),$$∥⋅∥$$是距离度量。
|
||||
|
||||
总的损失为最小化样本与最相似的 K 个原型之间的距离,又最大化样本与不相似的原型之间的距离:
|
||||
|
||||
$$
|
||||
\mbox{Total Loss}=∑_{k=1}^Kw_k⋅∥x_i−μ_k∥^2+λ⋅∑_{k=K+1}^Mmax(0,\alpha-∥x_i−μ_k∥^2)
|
||||
$$
|
||||
第二项为最大化样本与不相似原型(第 K+1 到第 M 个原型)之间的距离,$$λ$$ 是调节两部分之间平衡的超参数,$$\alpha$$是推远距离的阈值。
|
||||
|
||||
通过最小化这个损失函数,我们可以确保每个样本与多个原型保持一定的关系,而不是仅仅依赖于最相似的一个原型。
|
||||
|
||||
### 2.下游任务代码构建部分完成
|
||||
|
||||
目前下游任务暂定为**少样本/半监督图像分类**、**目标检测**等,目前完成**少样本/半监督图像分类**代码,微调数据和测试集暂定为PASCAL VOC2007和mini_imagenet
|
||||
|
||||
### 3.阅读论文Adaptive Multi-head Contrastive Learning,对投影头设计有了新的方向
|
||||
|
||||
## 下周任务
|
||||
|
||||
#### 1.实现新的损失函数代码设计与测试
|
||||
|
||||
#### 2.对现有模型的超参数进行调整
|
Loading…
Reference in New Issue