一个项目文件,首先要包括
data_loader.py
数据集类文件
class SYSUData(data.Dataset):# class数据集名称(data是从torch.utils中导入的模块)
#该类下一般有三个函数,初始化函数__init__、生成函数getitem和长度获取函数len;
def init(self, data_dir,):
1.该函数中一般是用来获取图像和标签的地址;
地址的语法:
./当前目录
…/上级目录
| Windows | ubuntu | |
|---|---|---|
| 相对地址 | …/Datasets/SYSU-MM01/ | …/Datasets/SYSU-MM01/ |
| 绝对地址 | “G:xsfastfunction_representation_learning-master” | ‘/home/jdk1.8.0_65/bin/java’ |
np文件操作相关语法:
变量名 = np.load(文件夹地址 + 文件名),例如:
data_dir = '../Datasets/SYSU-MM01/'
self.train_label = np.load(data_dir + 'train _label.npy')
2.常用语法
Self.名字=名字(实例化类时传入的变量)
def __getitem__(self, index):
img1 = self.transform(img1)
img2 = self.transform(img2)
return img1, img2, target1, target2
#python类中的__getitem__方法,可以将实例化的类,实现字典dict的键值形式。实例对象的key不管是否存在都会调用类中的__getitem__()方法。而且返回值就是__getitem__()方法中规定的return值。语法: 实例化名称【字典中的键值】
def len(self):
return len(self.train_color_label)
Train.py
1、 添加参数
一般常用参数有:数据集名称和路径、学习率、参数优化方式、backbone、模型路径、训练日志路径、输入图像的宽和高、batchsize、gpu选择等,在输入运行命令时可以改变
2、 OS文件操作相关:
os.path.makedirs 创建文件夹
os.path.isdir 判断是否存在该文件夹
3、 确保训练生成的日志的路径正确,以及日志打印是的格式。
4、 打印信息
```handlebars
```handlebars
print("==========nArgs:{}n==========".format(args))
print('==> Loading data..')
print('Dataset 名字 statistics:)
print(' subset | # ids | # images')
print(' ------------------------------')
print(' visible | 类别数 | 训练集标签长度)
print(' query | {:5d} | {:8d}'.format(len(np.unique(query_label)), nquery))#搜寻标签
print(' gallery | {:5d} | {:8d}'.format(len(np.unique(gall_label)), ngall))#图库标签
print(' ------------------------------')
print('Data Loading Time:t {:.3f}'.format(time.time() - end))
print('==> Building model..')
print('Epoch: [{}][{}/{}] '
'Time: {batch_time.val:.3f} ({batch_time.avg:.3f}) '
'lr:{:.3f} '
'Loss: {train_loss.val:.4f} ({train_loss.avg:.4f}) '
'iLoss: {id_loss.val:.4f} ({id_loss.avg:.4f}) '
'TLoss: {tri_loss.val:.4f} ({tri_loss.avg:.4f}) '
'Accu: {:.2f}'.format(
epoch, batch_idx, len(trainloader), current_lr,
100. * correct / total, batch_time=batch_time,
train_loss=train_loss, id_loss=id_loss, tri_loss=tri_loss))
print('Extracting Gallery Feature...')#提取图库特征所用时间
print('Extracting Time:t {:.3f}'.format(time.time() - start))
print('Extracting Query Feature...') #提取要搜寻的行人的特征所用时间
print('Extracting Time:t {:.3f}'.format(time.time() - start))
5、 选择模型采用方法,base or 加强版,
6、 定义损失函数,优化方式,以及Epoch
7、 定义训练类:
从迭代器中获取数据(包括iamge和label)
将输入送入定义好的net类获得feature和output
计算损失,梯度回传,参数优化,更新损失,打印信息,添加scaler(?)
8、 定义测试类:
初始化参数以及从迭代器中获取输入
将net换为评估版本
计算相关指标
9、 正式开始训练
每两个epoch打印一次训练信息并保留最佳模型
Aligned-ReID
1.计算DIST
inputs=torch.Tensor([[1,2,3],[4,5,6],[7,8,9]])
target=torch.Tensor([0,5,2])
print(inputs)
tensor([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]])
dist=torch.pow(inputs,2)
print(dist)
tensor([[ 1., 4., 9.],
[16., 25., 36.],
[49., 64., 81.]])
dist = torch.pow(inputs, 2).sum(dim=1, keepdim=True)
print(dist)
tensor([[ 14.],
[ 77.],
[194.]])
dist = torch.pow(inputs, 2).sum(dim=1, keepdim=True).expand(3, 3)
print(dist)
tensor([[ 14., 14., 14.],
[ 77., 77., 77.],
[194., 194., 194.]])
print(dist.t())
tensor([[ 14., 77., 194.],
[ 14., 77., 194.],
[ 14., 77., 194.]])
dist = dist + dist.t()
print(dist)
tensor([[ 28., 91., 208.],
[ 91., 154., 271.],
[208., 271., 388.]])
dist.addmm_(1, -2, inputs, inputs.t())
print(dist)
tensor([[ 0., 27., 108.],
[ 27., 0., 27.],
[108., 27., 0.]])
2、判断正负例 、硬例挖掘
mask = target.expand(n, n).eq(targets.expand(n, n).t())
mask
Out[46]:
tensor([[ True, False, False],
[False, True, False],
[False, False, True]])
dist_ap, relative_p_inds=torch.max(dist[mask].contiguous().view(n, -1), 1, keepdim=True)
print(relative_p_inds)
tensor([[0],
[0],
[0]])
dist_ap
Out[44]:
tensor([[0.],
[0.],
[0.]])
dist_an, relative_n_inds=torch.min(dist[mask==False].contiguous().view(n, -1), 1, keepdim=True)
dist_an
Out[48]:
tensor([[27.],
[27.],
[27.]])
print(relative_n_inds)
tensor([[0],
[0],
[1]])
Return inds
ind1 = target.new().resize_as_(target) # 随机生成一个新的同样维度的Tensor
ind1
Out[52]: tensor([5.0944e-14, 0.0000e+00, 0.0000e+00])
ind2=ind1.copy_(torch.arange(0, N).long()) #用torch.arange(0, N)生成的数重写Tensor,
#torch.arange(0, N) 用来生成 tensor([0,1, 2, 3, 4, ,,,N-1]), .long()后变为长整型(加小数点)
ind2
Out[55]: tensor([0., 1., 2.])
ind=ind2.unsqueeze(0).expand(n, n)
ind #unsqueeze是扩展维度(dim等于多少就加上哪个维度)
ind=ind2.unsqueeze(0)
ind
Out[60]: tensor([[0., 1., 2.]])
Out[57]:
.expand(n, n)
tensor([[0., 1., 2.],
[0., 1., 2.],
[0., 1., 2.]])
pytorch中的gather函数
可以看成是将 input中的值进行挑选后赋给output,挑选规则为:output中的第i行第j列的的值是input中第Index(i,j)行,第j列的值,此时dim=0,相当于列不变;或者是第i行,第Index(i,j)列的值,此时dim=1。Index的维度与output相同。
换一种思路,我们可以理解为根据我们想要的output,观察input,设计index
Input= 1 2 3
4 5 6
我们希望 output= 1 2
6 4
按行gather:
DIM=0 希望output(0,0)=1, 1在input的(0,0)位置,故希望index(0,0)=0
希望output(0,1)=2, 2在input的(0,1)位置,故希望index(0,1)=0
.。。。。。。
DIM=1 希望output(0,0)=1, 1在input的(0,0)位置,故希望index(0,0)=0
希望output(0,1)=2, 2在input的(0,1)位置,故希望index(0,1)=1
希望output(1,0)=6, 6在input的(1,2)位置,故希望index(1,0)=2
希望output(1,1)=4, 4在input的(1,0)位置,故希望index(1,1)=0
.。。。。。。。。。
Index = 0 1
2 0
总结,dim=1,我们想要output[i][j]对应input中i行m列的位置(同一行中找),我们就让Index(i,j)=m
Out[i][j]=input[i,index[i,j]],其中index[i,j]=m
dim=0,我们想要output[i][j]对应input中m行j列的位置(同一列中找),我们就让Index(i,j)=m
Out[i][j]=input[index[i,j],j],其中index[i,j]=m
Return_id:
ind
Out[64]:
tensor([[0., 1., 2.],
[0., 1., 2.],
[0., 1., 2.]])
ind[mask]
Out[65]: tensor([0., 1., 2.])
ind[mask].contiguous().view(n, -1)
Out[68]:
tensor([[0.],
[1.],
[2.]])#size=(3,1)
relative_p_inds.data
Out[69]:
tensor([[0],
[0],
[0]])
torch.gather(ind[mask].contiguous().view(n, -1), 1, relative_p_inds.data)
Out[70]:
tensor([[0.],
[1.],
[2.]])
torch.gather(ind[mask==0].contiguous().view(n, -1), 1, relative_n_inds.data)
Out[71]:
tensor([[1.],
[0.],
[1.]])



