1 . gerattrsetattr__getattr____setattr__

  • result = obj.name 会调用 buildin 函数 getattr(obj, 'name'),如果该属性找不到,会调用 obj.__getattr__('name'),没有实现 __getattr__ 或者 __getattr__ 也无法处理的就会 raise AttributeError;
  • obj.name = value 会调用 buildin 函数 setattr(obj, 'name', value),如果 obj 对象实现了 __setattr__ 方法,setattr 会直接调用 obj.__setattr__('name', value)

nn.Module 实现了自定义的 __setattr__ 函数,当执行 module.name = value 时,会在 __setattr__ 中判断 value 是否为 Parameternn.Module 对象,如果是则将这些对象加到 _parameters_modules 这两个字典中,而如果是其他类型的对象,如 Variablelistdict 等,则调用默认的操作,将这个值保存在 __dict__ 中。

Input:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import torch as t
from torch import nn

module = nn.Module()
module.param = nn.Parameter(t.ones(2, 2))
print(module._parameters)

submodule1 = nn.Linear(2, 2)
submodule2 = nn.Linear(2, 2)
module_list = [submodule1, submodule2]
# 对于 list 对象,调用 buildin 函数,保存在 __dict__ 中
module.submodules = module_list
print('_modules: ', module._modules)
print("__dict__['submodules']:", module.__dict__.get('submodules'))

module_list = nn.ModuleList(module_list)
module.submodules = module_list
print('ModuleList is instance of nn.Module: ', isinstance(module_list, nn.Module))
print('_modules: ', module._modules)
print("__dict__['submodules']: ", module.__dict__.get('submodules'))

Output:

_modules_parameters 中的 item 未保存在 dict 中,所以默认的 getattr 方法无法获取它,因而 nn.Module 实现了自定义的 __getattr__ 方法,如果默认的 getattr 无法处理,就调用自定义的 __getattr__ 方法,尝试从 _modules_parameters_buffers 这三个字典中获取。

Input:

1
2
3
4
5
6
7
8
9
10
11
print(getattr(module, 'training'))  # 等价于 module.training
# error
# print(module.__getattr__('training'))

module.attr1 = 2
print(getattr(module, 'attr1'))
# error
# print(module.__getattr__('attr1'))

# 即 module.param,会调用 module.__getattr__('param')
print(getattr(module, 'param'))

Output:


2 . 在 PyTorch 中保存模型十分简单,所有的 Module 对象都具有 state_dict() 函数,返回当前 Module 所有的状态数据,将这些状态数据保存后,下次使用模型时即可利用 model.load_state_dict() 函数将状态加载进来。

1
2
3
4
5
6
# 保存模型
t.save(net.state_dict(), 'net.pth')

# 加载已保存的模型
net2 = Net()
net2.load_state_dict(t.load('net.pth))

3 . 将 Module 放在 GPU 上运行只需两步:

  • model = model.cuda():将模型的所有参数都转存到 GPU 上;
  • input.cuda():将输入数据也放置到 GPU 上。

如何在多个 GPU 上并行计算,PyTorch 也提供了两个函数,可实现简单高效的并行 GPU 计算:

  • nn.parallel.data_parallel(module, inputs, device_ids=None, output_device=None, dim=0, module_kwargs=None)
  • class torch.nn.DataParallel(module, device_ids=None, output_device=None, dim=0)

二者的参数十分相似,通过 device_ids 参数可以指定在哪些 GPU 上进行优化,output_device 指定输出到哪个 GPU 上,唯一的不同就在于前者直接利用多GPU并行计算得出结果,而后者返回一个新的 Module,能够自动在多GPU上进行并行计算。

1
2
3
4
5
6
# method1
output = nn.parallel.data_parallel(net, input, device_ids=[0, 1])

# method2
new_net = nn.DataParallel(net, device_ids=[0, 1])
output = new_net(input)

笔记来源:《pytorch-book》