# npy 的构造
查看 DRT 看到下面的代码:
data_transforms = { | |
src_path: transforms.Compose([ | |
transforms.Scale(256), | |
transforms.RandomHorizontalFlip(), | |
transforms.RandomCrop(224), | |
transforms.ToTensor(), | |
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) | |
]), | |
trg_path: transforms.Compose([ | |
transforms.Scale(256), | |
transforms.RandomHorizontalFlip(), | |
transforms.RandomCrop(224), | |
transforms.ToTensor(), | |
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) | |
]), | |
val_path: transforms.Compose([ | |
transforms.Scale(256), | |
transforms.CenterCrop(224), | |
transforms.ToTensor(), | |
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) | |
]), | |
} | |
dsets = dict() | |
src_dataset = DomainNetDataset(args.root, image_list=args.src_path, transform = data_transforms[src_path]) | |
dsets[src_path] = torch.utils.data.DataLoader(src_dataset, batch_size=batch_size, shuffle=True, num_workers=16, pin_memory=True) | |
trg_dataset = DomainNetDataset(args.root, image_list=args.trg_path, transform = data_transforms[trg_path]) | |
dsets[trg_path] = torch.utils.data.DataLoader(trg_dataset, batch_size=batch_size, shuffle=True, num_workers=16, pin_memory=True) | |
val_dataset = DomainNetDataset(args.root, image_list=args.val_path, transform = data_transforms[val_path]) | |
dsets[val_path] = torch.utils.data.DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers=16, pin_memory=True) |
# 训练过程中数据集的返回
由于现在数据集结构变成了 [domain 数量,domain 下的类别数量,一个类别下的图片数量,图片(3 位)],而之前是 [类别数量,一个类别下的图片数量,图片(3 位)],在加载数据集后分为 x 和 y,现在应该也是将它们根据类别数量分为 x 和 y,但是 domain 是不变的。
# 调用关系的分析
next_hierarchical (temp_img_classify_train)
load_data_cache_hie
construct_task
next_hierarchical 要改,因为这里存在着 if_val 这些,是对数据集的重新组织。
在 load_data_cache_hie 中调用 construct_task 逐个构造出 cluster ,
在 load_data_cache_hie 选择 domain,然后再将该 domain 下的 [类别数量,一个类别下的图片数量,图片(3 位)] 传入 construct_task , 这样的话 construct_task 应该是不需要该的。
传入 construct_task 的是 [类别数量,一个类别下的图片数量,图片(3 位)]
# 模型调用分析
temp_img_classify_train 中通过变量 config 定义了 base learner 模型的结构,然后将 config 传入 MAML 或者 Meta_hierarchical(同时还传入了一个 args 参数,看看参数中是否有 dataset 键,如果有的话,可以根据 dataset 构造 base learner)
在 meta_hierarchical_parallel 中定义了 Meta_hierarchical ,应该是通过 self.net = Learner (config) 构造的 base learner
reverse 参数尚未使用
看看模型是在哪里使用的,输入输出的数据是怎样的?
在 cluster_learning 方法中使用到 self.net,在调用它的 forward 方法的时候,好像是自己传入参数的,调用过程如下:
middle_weights = net.vars
fast_weights = middle_weights
logits_q = net.forward(x_qry[i], fast_weights, bn_training=True)
net.forward(x_spt[i], fast_weights, bn_training=True)
上面可以看出,forward 方法重新定义了,必须显式调用。
输入输出为:
torch.Size([8, 3, 84, 84]) torch.Size([8, 8])
输入必须得 4 维的吗?
先保存
现在只用上 G,观察 G 的输出(不只是维度,看看具体的值),再对比之前的 base learner 网络的输出。
现在是最后输出的维度的问题,现在输出是 [某某数量, 1000],也许可以在最后面加一个全连接层,将
网络参数问题,查看 drt 和原先的网络参数的模样。
net.vars
ParameterList(
(0): Parameter containing: [torch.FloatTensor of size 32x3x3x3]
(1): Parameter containing: [torch.FloatTensor of size 32]
(2): Parameter containing: [torch.FloatTensor of size 32]
(3): Parameter containing: [torch.FloatTensor of size 32]
(4): Parameter containing: [torch.FloatTensor of size 32x32x3x3]
(5): Parameter containing: [torch.FloatTensor of size 32]
(6): Parameter containing: [torch.FloatTensor of size 32]
(7): Parameter containing: [torch.FloatTensor of size 32]
(8): Parameter containing: [torch.FloatTensor of size 32x32x3x3]
(9): Parameter containing: [torch.FloatTensor of size 32]
(10): Parameter containing: [torch.FloatTensor of size 32]
(11): Parameter containing: [torch.FloatTensor of size 32]
(12): Parameter containing: [torch.FloatTensor of size 32x32x3x3]
(13): Parameter containing: [torch.FloatTensor of size 32]
(14): Parameter containing: [torch.FloatTensor of size 32]
(15): Parameter containing: [torch.FloatTensor of size 32]
(16): Parameter containing: [torch.FloatTensor of size 5x800]
(17): Parameter containing: [torch.FloatTensor of size 5]
)
也许不用把参数拿出来,控制更新就可以了。
问题是,现在怎么对网络进行更新呢?
# 当前思路
将最底层的网络 base learner 作为参数传入,这就意味着要看之前的使用代码
# 代码更改
最终情况:最底层的 model 作为参数传入,
当前的 base learner 是将参数拿出来进行 forward 的,尝试对这个进行更改,理解原因,并将 forward 的参数设置为只有 x。
# Learner
learner.py 中的 Learner 不用改,forward 中假如没有传入参数,就默认使用的内部的网络参数。
def parameters(self): | |
""" | |
override this function since initial parameters will return with a generator. | |
:return: | |
""" | |
return self.vars |
确定 parameters 的问题,哪个才算是 parameters,
参考 https://blog.csdn.net/qq_39463274/article/details/105295272
不能改变网络参数张量中的某个值(矩阵中的一个元素)
当 list (a.parameters ()) 的时候是另外开辟内存的吗?
定义在 self. 中的网络层才会作为整体网络的参数?因此 drt 的最后一个全连接层不要直接用?定义在一个 self 中。
目前在看的时候,应该是不能纯用 forward 和 backward 来做的,因为体现 maml 思想的算法流程是计算梯度,这些代码都是取出网络的参数手动进行相关的计算的。
Meta_hierarchical 类 (meta_hierarchical_parallel.py 中定义) 中的 self.net 是底层网络,
存在使用 self.net.vars [i].grad 这种情况,这个是获得参数的梯度的意思。
查找 parameters 最终是在哪里更新的,是手动计算的呢?还是自动计算的?
当前看来是手动计算的,那么这个样子就可以使用 list (net.parameters)
要不要每次都加载程序跑呢?不需要,只需要查看每次调用最底层的 base learner 的时候 的输入输出就行了。然后另外读取数据集保存这个一个输入,再把这部分代码给拿出来进行测试。
主要更改代码处:
meta_hierarchical_parallel.py 中的 cluster_learning ,调用的子函数 middle_step 就是使用的 base-learner
base-learner 本来的参数有没有用?
cluster_learning 方法的开始处 有将 base-learner 网络的参数拿出来,
在 middle_step 中传入了网络参数,原先的代码是直接用参数进行的计算,这里可以改成:将传入的参数赋值给网络,网络再直接 forword。(但是这样网络本来的参数改变了,思考这里要不要恢复呢?)
- 查找 base-learner 的参数更新是在哪里?
在 Meta_hierarchical 的 forward 的最后设置网络参数的梯度,然后进行 step 更新。
Meta_hierarchical 的 init 中定义网络和网络参数的优化器
先有 a,后来 b 拷贝了 a 的内存,对 b 进行了一系列的运算得到 z,z.backward () 的时候,a 有梯度吗?没有,内存分离了。
因为直接使用 net.parameters () 返回的是迭代器
能不能自定义一个值,将参数拿出来
在网络类中自定义一个方法,将网络的参数返回出来,并且指向的内存和原本的内存是一致的。(做不到)
暂时不能验证这种想法正确与否 :
- 网络参数的设定和
在网络中新建属性 net.var 将网络的参数拿出来为列表的形式。
# 随手记
假如 task_cluster_batch_num 的数量小于等于 domain 的数量,那么不重复取样,否则就采用重复取样。
# 笔记
测试训练
--dataset=domainnet --root=domainnet --train_split=270 --val_split=240 --epoch=60000 --imgsz=224 --n_way=5 --k_spt=1 --k_qry=1 --k_qry_test=1 --task_spt=5 --task_qry=5 --task_qry_test=5 --task_cluster_batch_num=12 --task_cluster_batch_num_test=12 --candidate_num=8 --top_lr=0.001 --middle_lr=0.001 --bottom_lr=0.001 --second_order=0 --third_order=0 --bottom_step_num=2 --bottom_step_num_test=2 --method=Hierarchical_MAML --sample_mode=hierarchical_concentrate --test_spt_task_from=meta_train --if_val=0 --scheme_name=test_run --gpu_id=0 --train_parallel=0