Report/12月5日汇报.md

107 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 12月5日科研工作进展
## 目前进度
### 1.对之前的代码与数据进行了梳理、错误检查与修正
#### 问题解决:
##### 1在低聚类的情况下存在模型不能很好引导训练的情况
如图在聚类数较小的情况下acc_proto应该较高因为原型数本就较少但之前的训练存在acc_proto在热身结束后接近0的情况这存在问题。
![log5](/pic/log4.png)
###### 原因:
1⃣在较小的聚类条件下单个簇中样本数目大分布较为分散此时查询样本q可能存在于簇边缘和聚类中心的相似度较低而训练初期模型其实并不确定该样本的归属强行拉近可能存在错误。
2⃣在较小的聚类条件下由于总簇数cluster_result如10个聚类小于batchsize样本数如64在采样过程中会导致多个样本被分到一个聚类中导致每个样本分配的原型pos_proto_id出现重复如[22, 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左右达到顶峰聚类数3615。loss__proto则在epoch37左右达到最低聚类数60120240怀疑为训练数据集的100分类引起。
![log6](/pic/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 个原型之间的距离,又最大化样本与不相似的原型之间的距离:
$$
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.对现有模型的超参数进行调整