Serialization 分层后火炬中的序列化神经网络大小
在训练一个神经网络之后,比如说一个多层感知器,在预测的时候,我想把第一层从所有其他层中分离出来。 要做到这一点,我发现要获得正确大小的文件,唯一的方法是: 我循环遍历所有层,并将它们添加到两个容器中的一个(Serialization 分层后火炬中的序列化神经网络大小,serialization,lua,neural-network,torch,Serialization,Lua,Neural Network,Torch,在训练一个神经网络之后,比如说一个多层感知器,在预测的时候,我想把第一层从所有其他层中分离出来。 要做到这一点,我发现要获得正确大小的文件,唯一的方法是: 我循环遍历所有层,并将它们添加到两个容器中的一个(第一层或所有其他层),我将使用火炬。保存功能单独保存。有趣的是,我需要在将每个层的参数添加到两个容器中的任何一个之前检索它们,否则在保存时,两个文件(第一层和所有其他层)都具有相同的文件大小 代码片段将比我之前的所有解释更有帮助: local function split_model(netw
第一层
或所有其他层
),我将使用火炬。保存
功能单独保存。有趣的是,我需要在将每个层的参数添加到两个容器中的任何一个之前检索它们,否则在保存时,两个文件(第一层
和所有其他层
)都具有相同的文件大小
代码片段将比我之前的所有解释更有帮助:
local function split_model(network)
-- for some reason all the models when saved have the same size
-- if not splitted calling 'getParameters()' first.
first_layer = nn.Sequential()
all_the_rest = nn.Sequential()
for i = 1, network:size() do
local l = network:get(i)
local l_params, _ = l:getParameters()
if i == 1 then
first_layer:add(l)
else
all_the_rest:add(l)
end
end
return first_layer, all_the_rest
end
local first_layer, all_the_rest = split_model(network)
torch.save("checkpoints/mlp.t7", .network)
torch.save("checkpoints/first_layer.t7", first_layer)
torch.save("checkpoints/all_the_rest.t7", all_the_rest)
同样的问题贴在,这是Alban Desmaison的回答:
嗨
此行为的原因在于getParameters
的工作方式
为了能够返回包含所有参数的平坦张量,它
实际上创建一个包含所有权重的存储,然后
每个模块的重量都是此存储的一部分。当您保存
网络中任何元素的权重,都必须保存权重
要执行此操作,请保存底层存储。因此,如果你打电话
getParameters
在整个网络上,如果保存任何模块,则
将保存所有网络权重。这里,当你打电话的时候
getParameters
在单个模块上,它实际上重新创建了
单个存储,但对于此单个模块,因此,当您保存它时,它
仅包含所需的权重。但要注意的是
在上执行的getParameters
返回的参数
完整的网络不再有效
这里有两种解决方案:
-如果不想在整个网络上使用来自getParameters
的参数,只需调用
getParameters
在保存网络的每个子集之前。
这将中断基础存储的更改,使其仅包含此
网络的子集,您将只保存所需内容(共享)
存储只存储一次)。
-如果您希望能够继续使用原始getParameters
中的参数,可以执行与上面相同的操作,但使用克隆版本
其中一个用于执行getParameters
并保存
因为代码片段总是更好:
同样的问题贴在,这是Alban Desmaison的回答:
嗨
此行为的原因在于getParameters
的工作方式
为了能够返回包含所有参数的平坦张量,它
实际上创建一个包含所有权重的存储,然后
每个模块的重量都是此存储的一部分。当您保存
网络中任何元素的权重,都必须保存权重
要执行此操作,请保存底层存储。因此,如果你打电话
getParameters
在整个网络上,如果保存任何模块,则
将保存所有网络权重。这里,当你打电话的时候
getParameters
在单个模块上,它实际上重新创建了
单个存储,但对于此单个模块,因此,当您保存它时,它
仅包含所需的权重。但要注意的是
在上执行的getParameters
返回的参数
完整的网络不再有效
这里有两种解决方案:
-如果不想在整个网络上使用来自getParameters
的参数,只需调用
getParameters
在保存网络的每个子集之前。
这将中断基础存储的更改,使其仅包含此
网络的子集,您将只保存所需内容(共享)
存储只存储一次)。
-如果您希望能够继续使用原始getParameters
中的参数,可以执行与上面相同的操作,但使用克隆版本
其中一个用于执行getParameters
并保存
因为代码片段总是更好:
require 'nn'
local subset1 = nn.Linear(2,2)
local subset2 = nn.Linear(2,2)
local network = nn.Sequential():add(subset1):add(subset2)
print("Before getParameters:", subset1.weight:storage():size()) -- 4 elements
network_params,_ = network:getParameters()
print("After getParameters:", subset1.weight:storage():size()) -- 12 elements
subset1.weight:random() -- Change weights to see if linking is still working
print("network_params is valid?", network_params[1] == subset1.weight[1][1]) -- true
-- Keeping network_params valid
local clone_subset1 = subset1:clone()
print("Cloned subset1 before getParameters:", clone_subset1.weight:storage():size()) -- 12 elements
clone_subset1:getParameters()
print("Cloned subset1 after getParameters:", clone_subset1.weight:storage():size()) -- 6 elements (4 weights + 2 bias)
subset1.weight:random() -- Change weights to see if linking is still working
print("network_params is valid?", network_params[1] == subset1.weight[1][1]) -- true
-- Not keeping network_params valid (should be faster)
local clone_subset1 = subset1:clone()
print("subset1 before getParameters:", subset1.weight:storage():size()) -- 12 elements
subset1:getParameters()
print("subset1 after getParameters:", subset1.weight:storage():size()) -- 6 elements (4 weights + 2 bias)
subset1.weight:random() -- Change weights to see if linking is still working
print("network_params is valid?", network_params[1] == subset1.weight[1][1]) -- false