2017-02-27 76 views
21

有没有什么办法,我可以像下面这样在Keras中打印一个模型的摘要,如model.summary()方法在Keras中做?pytorch中的模型概要

Model Summary: 
____________________________________________________________________________________________________ 
Layer (type)      Output Shape   Param #  Connected to      
==================================================================================================== 
input_1 (InputLayer)    (None, 1, 15, 27)  0            
____________________________________________________________________________________________________ 
convolution2d_1 (Convolution2D) (None, 8, 15, 27)  872   input_1[0][0]      
____________________________________________________________________________________________________ 
maxpooling2d_1 (MaxPooling2D) (None, 8, 7, 27)  0   convolution2d_1[0][0]    
____________________________________________________________________________________________________ 
flatten_1 (Flatten)    (None, 1512)   0   maxpooling2d_1[0][0]    
____________________________________________________________________________________________________ 
dense_1 (Dense)     (None, 1)    1513  flatten_1[0][0]     
==================================================================================================== 
Total params: 2,385 
Trainable params: 2,385 
Non-trainable params: 0 
+0

你见过模块上的state_dict()方法?它为您提供了模型的不同参数。没有直接的总结方法,但可以使用state_dict()方法构成一个方法 – Kashyap

回答

22

虽然参考script你不会得到有关模型的详细信息,就像在Keras的模型中一样。简单地说,打印模型会给你一些有关不同层次及其规格的想法。

例如:

from torchvision import models 
model = models.vgg16() 
print(model) 

在这种情况下,输出会是这样如下:

VGG (
    (features): Sequential (
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (1): ReLU (inplace) 
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (3): ReLU (inplace) 
    (4): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1)) 
    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (6): ReLU (inplace) 
    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (8): ReLU (inplace) 
    (9): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1)) 
    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (11): ReLU (inplace) 
    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (13): ReLU (inplace) 
    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (15): ReLU (inplace) 
    (16): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1)) 
    (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (18): ReLU (inplace) 
    (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (20): ReLU (inplace) 
    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (22): ReLU (inplace) 
    (23): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1)) 
    (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (25): ReLU (inplace) 
    (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (27): ReLU (inplace) 
    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 
    (29): ReLU (inplace) 
    (30): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1)) 
) 
    (classifier): Sequential (
    (0): Dropout (p = 0.5) 
    (1): Linear (25088 -> 4096) 
    (2): ReLU (inplace) 
    (3): Dropout (p = 0.5) 
    (4): Linear (4096 -> 4096) 
    (5): ReLU (inplace) 
    (6): Linear (4096 -> 1000) 
) 
) 

现在你可以,如Kashyap提到,使用state_dict方法得到的权重不同的层次。但是使用这些层的列表可能会提供更多的方向,就是创建一个帮助函数来获取类似于模型摘要的Keras!希望这可以帮助!

1

阿法克没有model.summary()之类相当于pytorch

同时您可以通过szagoruyko,这给出了一个很好的visualizaton像resnet18-example

干杯

10

这将显示模型的权重和参数(但不是输出形状)。

from torch.nn.modules.module import _addindent 
import torch 
import numpy as np 
def torch_summarize(model, show_weights=True, show_parameters=True): 
    """Summarizes torch model by showing trainable parameters and weights.""" 
    tmpstr = model.__class__.__name__ + ' (\n' 
    for key, module in model._modules.items(): 
     # if it contains layers let call it recursively to get params and weights 
     if type(module) in [ 
      torch.nn.modules.container.Container, 
      torch.nn.modules.container.Sequential 
     ]: 
      modstr = torch_summarize(module) 
     else: 
      modstr = module.__repr__() 
     modstr = _addindent(modstr, 2) 

     params = sum([np.prod(p.size()) for p in module.parameters()]) 
     weights = tuple([tuple(p.size()) for p in module.parameters()]) 

     tmpstr += ' (' + key + '): ' + modstr 
     if show_weights: 
      tmpstr += ', weights={}'.format(weights) 
     if show_parameters: 
      tmpstr += ', parameters={}'.format(params) 
     tmpstr += '\n' 

    tmpstr = tmpstr + ')' 
    return tmpstr 

# Test 
import torchvision.models as models 
model = models.alexnet() 
print(torch_summarize(model)) 

# # Output 
# AlexNet (
# (features): Sequential (
#  (0): Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2)), weights=((64, 3, 11, 11), (64,)), parameters=23296 
#  (1): ReLU (inplace), weights=(), parameters=0 
#  (2): MaxPool2d (size=(3, 3), stride=(2, 2), dilation=(1, 1)), weights=(), parameters=0 
#  (3): Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)), weights=((192, 64, 5, 5), (192,)), parameters=307392 
#  (4): ReLU (inplace), weights=(), parameters=0 
#  (5): MaxPool2d (size=(3, 3), stride=(2, 2), dilation=(1, 1)), weights=(), parameters=0 
#  (6): Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), weights=((384, 192, 3, 3), (384,)), parameters=663936 
#  (7): ReLU (inplace), weights=(), parameters=0 
#  (8): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), weights=((256, 384, 3, 3), (256,)), parameters=884992 
#  (9): ReLU (inplace), weights=(), parameters=0 
#  (10): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), weights=((256, 256, 3, 3), (256,)), parameters=590080 
#  (11): ReLU (inplace), weights=(), parameters=0 
#  (12): MaxPool2d (size=(3, 3), stride=(2, 2), dilation=(1, 1)), weights=(), parameters=0 
# ), weights=((64, 3, 11, 11), (64,), (192, 64, 5, 5), (192,), (384, 192, 3, 3), (384,), (256, 384, 3, 3), (256,), (256, 256, 3, 3), (256,)), parameters=2469696 
# (classifier): Sequential (
#  (0): Dropout (p = 0.5), weights=(), parameters=0 
#  (1): Linear (9216 -> 4096), weights=((4096, 9216), (4096,)), parameters=37752832 
#  (2): ReLU (inplace), weights=(), parameters=0 
#  (3): Dropout (p = 0.5), weights=(), parameters=0 
#  (4): Linear (4096 -> 4096), weights=((4096, 4096), (4096,)), parameters=16781312 
#  (5): ReLU (inplace), weights=(), parameters=0 
#  (6): Linear (4096 -> 1000), weights=((1000, 4096), (1000,)), parameters=4097000 
# ), weights=((4096, 9216), (4096,), (4096, 4096), (4096,), (1000, 4096), (1000,)), parameters=58631144 
#) 

编辑:isaykatsman有pytorch PR添加model.summary()是酷似keras https://github.com/pytorch/pytorch/pull/3043/files

+0

伟大的代码!这是你写的吗? – acgtyrant

+1

谢谢,是啊:)。我从火炬借用__repr__,但它递归并提供更多信息,如keras。 – wassname

+0

更新后的代码:https://gist.github.com/wassname/0fb8f95e4272e6bdd27bd7df386716b7/ – wassname