轉載請注明出處:
http://www.cnblogs.com/darkknightzh/p/6221633.html
torch中的apply函數通過可以不斷遍歷model的各個模塊。實際上其使用的是深度優先算法。
其具體代碼如下所示(代碼見torch/install/share/lua/5.1/nn/Module.lua):
-- Run a callback (called with the module as an argument) in preorder over this -- module and its children. -- function Module:apply(callback) callback(self) if self.modules then for _, module in ipairs(self.modules) do module:apply(callback) end end end
可見,apply遞歸調用自身,直到不存在模塊為止(這樣說不太合理)。
如下所示的測試代碼:
require "dpnn" function createModel() local net = nn.Sequential() net:add(nn.SpatialConvolutionMM(3, 64, 7, 7, 2, 2, 3, 3)) net:add(nn.SpatialBatchNormalization(64)) net:add(nn.ReLU()) net:add(nn.SpatialMaxPooling(3, 3, 2, 2, 1, 1)) net:add(nn.Inception{ inputSize = 192, kernelSize = {3, 5}, kernelStride = {1, 1}, outputSize = {128, 32}, reduceSize = {96, 16, 32, 64}, pool = nn.SpatialMaxPooling(3, 3, 1, 1, 1, 1), batchNorm = true }) net:add(nn.Inception{ inputSize = 256, kernelSize = {3, 5}, kernelStride = {1, 1}, outputSize = {128, 64}, reduceSize = {96, 32, 64, 64}, pool = nn.SpatialLPPooling(256, 2, 3, 3, 1, 1), batchNorm = false }) net:add(nn.SpatialAveragePooling(7, 7)) net:add(nn.View(320)) net:add(nn.Linear(320, 128)) net:add(nn.Normalize(2)) return net end torch.setdefaulttensortype('torch.FloatTensor') local model = createModel() --print(model) tt = 0 model:apply(function(module) tt = tt + 1 print(tt, module) end)
其輸出結果為:

1 nn.Sequential { [input -> (1) -> (2) -> (3) -> (4) -> (5) -> (6) -> (7) -> (8) -> (9) -> (10) -> output] (1): nn.SpatialConvolutionMM(3 -> 64, 7x7, 2,2, 3,3) (2): nn.SpatialBatchNormalization (3): nn.ReLU (4): nn.SpatialMaxPooling(3x3, 2,2, 1,1) (5): nn.Inception @ nn.DepthConcat { input |`-> (1): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> (6) -> output] | (1): nn.SpatialConvolution(192 -> 96, 1x1) | (2): nn.SpatialBatchNormalization | (3): nn.ReLU | (4): nn.SpatialConvolution(96 -> 128, 3x3, 1,1, 1,1) | (5): nn.SpatialBatchNormalization | (6): nn.ReLU | } |`-> (2): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> (6) -> output] | (1): nn.SpatialConvolution(192 -> 16, 1x1) | (2): nn.SpatialBatchNormalization | (3): nn.ReLU | (4): nn.SpatialConvolution(16 -> 32, 5x5, 1,1, 2,2) | (5): nn.SpatialBatchNormalization | (6): nn.ReLU | } |`-> (3): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.SpatialMaxPooling(3x3, 1,1, 1,1) | (2): nn.SpatialConvolution(192 -> 32, 1x1) | (3): nn.SpatialBatchNormalization | (4): nn.ReLU | } |`-> (4): nn.Sequential { [input -> (1) -> (2) -> (3) -> output] (1): nn.SpatialConvolution(192 -> 64, 1x1) (2): nn.SpatialBatchNormalization (3): nn.ReLU } ... -> output } (6): nn.Inception @ nn.DepthConcat { input |`-> (1): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.SpatialConvolution(256 -> 96, 1x1) | (2): nn.ReLU | (3): nn.SpatialConvolution(96 -> 128, 3x3, 1,1, 1,1) | (4): nn.ReLU | } |`-> (2): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.SpatialConvolution(256 -> 32, 1x1) | (2): nn.ReLU | (3): nn.SpatialConvolution(32 -> 64, 5x5, 1,1, 2,2) | (4): nn.ReLU | } |`-> (3): nn.Sequential { | [input -> (1) -> (2) -> (3) -> output] | (1): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.Square | (2): nn.SpatialAveragePooling(3x3, 1,1) | (3): nn.MulConstant | (4): nn.Sqrt | } | (2): nn.SpatialConvolution(256 -> 64, 1x1) | (3): nn.ReLU | } |`-> (4): nn.Sequential { [input -> (1) -> (2) -> output] (1): nn.SpatialConvolution(256 -> 64, 1x1) (2): nn.ReLU } ... -> output } (7): nn.SpatialAveragePooling(7x7, 1,1) (8): nn.View(320) (9): nn.Linear(320 -> 128) (10): nn.Normalize(2) } 2 nn.SpatialConvolutionMM(3 -> 64, 7x7, 2,2, 3,3) 3 nn.SpatialBatchNormalization 4 nn.ReLU 5 nn.SpatialMaxPooling(3x3, 2,2, 1,1) 6 nn.Inception @ nn.DepthConcat { input |`-> (1): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> (6) -> output] | (1): nn.SpatialConvolution(192 -> 96, 1x1) | (2): nn.SpatialBatchNormalization | (3): nn.ReLU | (4): nn.SpatialConvolution(96 -> 128, 3x3, 1,1, 1,1) | (5): nn.SpatialBatchNormalization | (6): nn.ReLU | } |`-> (2): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> (6) -> output] | (1): nn.SpatialConvolution(192 -> 16, 1x1) | (2): nn.SpatialBatchNormalization | (3): nn.ReLU | (4): nn.SpatialConvolution(16 -> 32, 5x5, 1,1, 2,2) | (5): nn.SpatialBatchNormalization | (6): nn.ReLU | } |`-> (3): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.SpatialMaxPooling(3x3, 1,1, 1,1) | (2): nn.SpatialConvolution(192 -> 32, 1x1) | (3): nn.SpatialBatchNormalization | (4): nn.ReLU | } |`-> (4): nn.Sequential { [input -> (1) -> (2) -> (3) -> output] (1): nn.SpatialConvolution(192 -> 64, 1x1) (2): nn.SpatialBatchNormalization (3): nn.ReLU } ... -> output } 7 nn.DepthConcat { input |`-> (1): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> (6) -> output] | (1): nn.SpatialConvolution(192 -> 96, 1x1) | (2): nn.SpatialBatchNormalization | (3): nn.ReLU | (4): nn.SpatialConvolution(96 -> 128, 3x3, 1,1, 1,1) | (5): nn.SpatialBatchNormalization | (6): nn.ReLU | } |`-> (2): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> (5) -> (6) -> output] | (1): nn.SpatialConvolution(192 -> 16, 1x1) | (2): nn.SpatialBatchNormalization | (3): nn.ReLU | (4): nn.SpatialConvolution(16 -> 32, 5x5, 1,1, 2,2) | (5): nn.SpatialBatchNormalization | (6): nn.ReLU | } |`-> (3): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.SpatialMaxPooling(3x3, 1,1, 1,1) | (2): nn.SpatialConvolution(192 -> 32, 1x1) | (3): nn.SpatialBatchNormalization | (4): nn.ReLU | } |`-> (4): nn.Sequential { [input -> (1) -> (2) -> (3) -> output] (1): nn.SpatialConvolution(192 -> 64, 1x1) (2): nn.SpatialBatchNormalization (3): nn.ReLU } ... -> output } 8 nn.Sequential { [input -> (1) -> (2) -> (3) -> (4) -> (5) -> (6) -> output] (1): nn.SpatialConvolution(192 -> 96, 1x1) (2): nn.SpatialBatchNormalization (3): nn.ReLU (4): nn.SpatialConvolution(96 -> 128, 3x3, 1,1, 1,1) (5): nn.SpatialBatchNormalization (6): nn.ReLU } 9 nn.SpatialConvolution(192 -> 96, 1x1) 10 nn.SpatialBatchNormalization 11 nn.ReLU 12 nn.SpatialConvolution(96 -> 128, 3x3, 1,1, 1,1) 13 nn.SpatialBatchNormalization 14 nn.ReLU 15 nn.Sequential { [input -> (1) -> (2) -> (3) -> (4) -> (5) -> (6) -> output] (1): nn.SpatialConvolution(192 -> 16, 1x1) (2): nn.SpatialBatchNormalization (3): nn.ReLU (4): nn.SpatialConvolution(16 -> 32, 5x5, 1,1, 2,2) (5): nn.SpatialBatchNormalization (6): nn.ReLU } 16 nn.SpatialConvolution(192 -> 16, 1x1) 17 nn.SpatialBatchNormalization 18 nn.ReLU 19 nn.SpatialConvolution(16 -> 32, 5x5, 1,1, 2,2) 20 nn.SpatialBatchNormalization 21 nn.ReLU 22 nn.Sequential { [input -> (1) -> (2) -> (3) -> (4) -> output] (1): nn.SpatialMaxPooling(3x3, 1,1, 1,1) (2): nn.SpatialConvolution(192 -> 32, 1x1) (3): nn.SpatialBatchNormalization (4): nn.ReLU } 23 nn.SpatialMaxPooling(3x3, 1,1, 1,1) 24 nn.SpatialConvolution(192 -> 32, 1x1) 25 nn.SpatialBatchNormalization 26 nn.ReLU 27 nn.Sequential { [input -> (1) -> (2) -> (3) -> output] (1): nn.SpatialConvolution(192 -> 64, 1x1) (2): nn.SpatialBatchNormalization (3): nn.ReLU } 28 nn.SpatialConvolution(192 -> 64, 1x1) 29 nn.SpatialBatchNormalization 30 nn.ReLU 31 nn.Inception @ nn.DepthConcat { input |`-> (1): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.SpatialConvolution(256 -> 96, 1x1) | (2): nn.ReLU | (3): nn.SpatialConvolution(96 -> 128, 3x3, 1,1, 1,1) | (4): nn.ReLU | } |`-> (2): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.SpatialConvolution(256 -> 32, 1x1) | (2): nn.ReLU | (3): nn.SpatialConvolution(32 -> 64, 5x5, 1,1, 2,2) | (4): nn.ReLU | } |`-> (3): nn.Sequential { | [input -> (1) -> (2) -> (3) -> output] | (1): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.Square | (2): nn.SpatialAveragePooling(3x3, 1,1) | (3): nn.MulConstant | (4): nn.Sqrt | } | (2): nn.SpatialConvolution(256 -> 64, 1x1) | (3): nn.ReLU | } |`-> (4): nn.Sequential { [input -> (1) -> (2) -> output] (1): nn.SpatialConvolution(256 -> 64, 1x1) (2): nn.ReLU } ... -> output } 32 nn.DepthConcat { input |`-> (1): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.SpatialConvolution(256 -> 96, 1x1) | (2): nn.ReLU | (3): nn.SpatialConvolution(96 -> 128, 3x3, 1,1, 1,1) | (4): nn.ReLU | } |`-> (2): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.SpatialConvolution(256 -> 32, 1x1) | (2): nn.ReLU | (3): nn.SpatialConvolution(32 -> 64, 5x5, 1,1, 2,2) | (4): nn.ReLU | } |`-> (3): nn.Sequential { | [input -> (1) -> (2) -> (3) -> output] | (1): nn.Sequential { | [input -> (1) -> (2) -> (3) -> (4) -> output] | (1): nn.Square | (2): nn.SpatialAveragePooling(3x3, 1,1) | (3): nn.MulConstant | (4): nn.Sqrt | } | (2): nn.SpatialConvolution(256 -> 64, 1x1) | (3): nn.ReLU | } |`-> (4): nn.Sequential { [input -> (1) -> (2) -> output] (1): nn.SpatialConvolution(256 -> 64, 1x1) (2): nn.ReLU } ... -> output } 33 nn.Sequential { [input -> (1) -> (2) -> (3) -> (4) -> output] (1): nn.SpatialConvolution(256 -> 96, 1x1) (2): nn.ReLU (3): nn.SpatialConvolution(96 -> 128, 3x3, 1,1, 1,1) (4): nn.ReLU } 34 nn.SpatialConvolution(256 -> 96, 1x1) 35 nn.ReLU 36 nn.SpatialConvolution(96 -> 128, 3x3, 1,1, 1,1) 37 nn.ReLU 38 nn.Sequential { [input -> (1) -> (2) -> (3) -> (4) -> output] (1): nn.SpatialConvolution(256 -> 32, 1x1) (2): nn.ReLU (3): nn.SpatialConvolution(32 -> 64, 5x5, 1,1, 2,2) (4): nn.ReLU } 39 nn.SpatialConvolution(256 -> 32, 1x1) 40 nn.ReLU 41 nn.SpatialConvolution(32 -> 64, 5x5, 1,1, 2,2) 42 nn.ReLU 43 nn.Sequential { [input -> (1) -> (2) -> (3) -> output] (1): nn.Sequential { [input -> (1) -> (2) -> (3) -> (4) -> output] (1): nn.Square (2): nn.SpatialAveragePooling(3x3, 1,1) (3): nn.MulConstant (4): nn.Sqrt } (2): nn.SpatialConvolution(256 -> 64, 1x1) (3): nn.ReLU } 44 nn.Sequential { [input -> (1) -> (2) -> (3) -> (4) -> output] (1): nn.Square (2): nn.SpatialAveragePooling(3x3, 1,1) (3): nn.MulConstant (4): nn.Sqrt } 45 nn.Square 46 nn.SpatialAveragePooling(3x3, 1,1) 47 nn.MulConstant 48 nn.Sqrt 49 nn.SpatialConvolution(256 -> 64, 1x1) 50 nn.ReLU 51 nn.Sequential { [input -> (1) -> (2) -> output] (1): nn.SpatialConvolution(256 -> 64, 1x1) (2): nn.ReLU } 52 nn.SpatialConvolution(256 -> 64, 1x1) 53 nn.ReLU 54 nn.SpatialAveragePooling(7x7, 1,1) 55 nn.View(320) 56 nn.Linear(320 -> 128) 57 nn.Normalize(2)
由上述結果可以看出,使用apply后,第1次輸出整個模型,此處為最頂層的。
第2-5次輸出:
2 nn.SpatialConvolutionMM(3 -> 64, 7x7, 2,2, 3,3)
3 nn.SpatialBatchNormalization
4 nn.ReLU
5 nn.SpatialMaxPooling(3x3, 2,2, 1,1)
為Inception之前的幾個層。
第6次為nn.Inception @ nn.DepthConcat,第7次為nn.DepthConcat。此處是第一個Inceptioin層。
第8次為Inception的第一個nn.Sequential,第9-14次為該層的具體層。此時已經到了第一個最底層。
第15次為Inception的第二個nn.Sequential,第16-21次為該層的具體層。此時已經到了第二個最底層。
第22次為Inception的第三個nn.Sequential,第23-26次為該層的具體層。此時已經到了第三個最底層。
第27次為Inception的第四個nn.Sequential,第28-30次為該層的具體層。此時已經到了第四個最底層。
至此,第一個Inception層通過深度優先的方式遍歷完畢。
第31次為nn.Inception @ nn.DepthConcat,第32次為nn.DepthConcat。此處是第二個Inceptioin層(注意,為了區分第一個Inception和第二個Inception層,這兩個層具體結構不完全一樣)。
第33次為Inception的第一個nn.Sequential,第34-37次為該層的具體層。此時已經到了第一個最底層。
第38次為Inception的第二個nn.Sequential,第39-42次為該層的具體層。此時已經到了第二個最底層。
第43次為Inception的第三個nn.Sequential。
第44次為第三個nn.Sequential的第一個小module(也是一個nn.Sequential)。第45-48依次遍歷此nn.Sequential。到了最底層后遍歷完畢。
第49-50為第三個nn.Sequential的最后兩層。
第51次為Inception的第四個nn.Sequential,第52-53次為該層的具體層。此時已經到了第四個最底層。
至此,第二個Inception層通過深度優先的方式遍歷完畢。
第54-57為最后的兩個層。
由上面可以看出,apply采用的是深度優先的方式進行遍歷。