Beispiel #1
0
def model_summarize(model, show_weights=True, show_parameters=True):
    """Summarizes torch model by showing trainable parameters and weights."""
    tmpstr = model.__class__.__name__ + ' (\n'
    params_num = 0
    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 = model_summarize(module)
        else:
            modstr = module.__repr__()

        if isinstance(modstr, str):
            modstr = _addindent(modstr, 2)
        elif isinstance(modstr, tuple):
            modstr = _addindent(modstr[0], 2)

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

        # rest = b if b > 0 else params
        # params_num = params_num + rest
        params_num += params

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

    tmpstr = tmpstr + ')'
    return tmpstr, params_num * 4. / (1024**2)
Beispiel #2
0
    def __repr__(self):
        main_str = self._get_name() + '('

        if self.regular is not None:
            mod_str = _addindent(repr(self.regular), 2)
            main_str += '\n  (Regular & Fusion): ' + mod_str
        if self.fuse is not None:
            mod_str = _addindent(repr(self.fuse), 2)
            main_str += '\n  (Fuse): ' + mod_str
        if self.combined is not None:
            mod_str = _addindent(repr(self.combined), 2)
            main_str += '\n  (Combined): ' + mod_str

        return main_str
Beispiel #3
0
def torch_summarize(model, show_weights=True, show_parameters=True):
    """
    SOURCE: https://stackoverflow.com/a/45528544
    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 + ')'

    print("\n\n\n" + 20 * "=")
    print("Total number of params: {}\n".format(
        sum([param.nelement() for param in model.parameters()])))
    print(tmpstr)
    print(20 * "=" + "\n\n")
    def __repr__(self):
        # We don't want to show `LinearPackedParams` children, hence custom
        # `__repr__`. This is the same as nn.Module.__repr__, except the check
        # for the `LinearPackedParams`.
        # You should still override `extra_repr` to add more info.
        extra_lines = []
        extra_repr = self.extra_repr()
        # empty string will be split into list ['']
        if extra_repr:
            extra_lines = extra_repr.split('\n')
        child_lines = []
        for key, module in self._modules.items():
            mod_str = repr(module)
            mod_str = _addindent(mod_str, 2)
            child_lines.append('(' + key + '): ' + mod_str)
        lines = extra_lines + child_lines

        main_str = self._get_name() + '('
        if lines:
            # simple one-liner info, which most builtin Modules will use
            if len(extra_lines) == 1 and not child_lines:
                main_str += extra_lines[0]
            else:
                main_str += '\n  ' + '\n  '.join(lines) + '\n'

        main_str += ')'
        return main_str
Beispiel #5
0
    def summarize(model, num_params, show_weights=True, show_parameters=True):
        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, num_params_rec = summarize(module, num_params,
                                                   show_weights,
                                                   show_parameters)
                num_params += num_params_rec
            else:
                modstr = module.__repr__()
            modstr = _addindent(modstr, 2)

            params = sum([np.prod(p.size()) for p in module.parameters()])
            num_params += params
            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, num_params
def torch_summarize(model, show_weights=True, show_parameters=True):
    """
    This function will give an overview of the created neural network
    by printing out all the weights and parameters
    """

    tmpstr = model.__class__.__name__ + ' (\n'
    for key, module in model._modules.items():
        # if it contains layers 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
Beispiel #7
0
    def repr(model):
        # We treat the extra repr like the sub-module, one item per line
        extra_lines = []
        extra_repr = model.extra_repr()
        # empty string will be split into list ['']
        if extra_repr:
            extra_lines = extra_repr.split('\n')
        child_lines = []
        total_params = 0
        for key, module in model._modules.items():
            mod_str, num_params = repr(module)
            mod_str = _addindent(mod_str, 2)
            child_lines.append('(' + key + '): ' + mod_str)
            total_params += num_params
        lines = extra_lines + child_lines

        for name, p in model._parameters.items():
            if hasattr(p, 'shape'):
                total_params += reduce(lambda x, y: x * y, p.shape)

        main_str = model._get_name() + '('
        if lines:
            # simple one-liner info, which most builtin Modules will use
            if len(extra_lines) == 1 and not child_lines:
                main_str += extra_lines[0]
            else:
                main_str += '\n  ' + '\n  '.join(lines) + '\n'

        main_str += ')'
        if file is sys.stdout:
            main_str += ', \033[92m{:,}\033[0m params'.format(total_params)
        else:
            main_str += ', {:,} params'.format(total_params)
        return main_str, total_params
Beispiel #8
0
    def summarize(cls, model, params_switch=True, weights_switch=True):
        """
            Summarizes torch model by showing trainable parameters and weights.
        """
        from torch.nn.modules.module import _addindent
        tmpstr = model.__class__.__name__ + '(\n'
        for key, module in model._modules.items():
            if type(module) in [
                    torch.nn.modules.container.Container,
                    torch.nn.modules.container.Sequential
            ]:
                modstr = cls.summarize(module)
            else:
                modstr = module.__repr__()
            modstr = _addindent(modstr, 2)

            tmpstr += '  (' + key + '): ' + modstr
            if params_switch:
                params = sum([np.prod(p.size()) for p in module.parameters()])
                tmpstr += ',  parameters={}'.format(params)
            if weights_switch:
                weights = tuple([tuple(p.size()) for p in module.parameters()])
                tmpstr += ',  weights={}'.format(weights)
            tmpstr += '\n'

        tmpstr = tmpstr + ')'
        return tmpstr
Beispiel #9
0
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
Beispiel #10
0
def hide_packed_params_repr(self, params):
    # We don't want to show `PackedParams` children, hence custom
    # `__repr__`. This is the same as nn.Module.__repr__, except the check
    # for the `params module`.
    extra_lines = []
    extra_repr = self.extra_repr()
    # empty string will be split into list ['']
    if extra_repr:
        extra_lines = extra_repr.split('\n')
    child_lines = []
    for key, module in self._modules.items():
        if isinstance(module, params):
            continue
        mod_str = repr(module)
        mod_str = _addindent(mod_str, 2)
        child_lines.append('(' + key + '): ' + mod_str)
    lines = extra_lines + child_lines

    main_str = self._get_name() + '('
    if lines:
        # simple one-liner info, which most builtin Modules will use
        if len(extra_lines) == 1 and not child_lines:
            main_str += extra_lines[0]
        else:
            main_str += '\n  ' + '\n  '.join(lines) + '\n'

    main_str += ')'
    return main_str
Beispiel #11
0
def torch_summarize(model, show_weights=False, show_parameters=True):
    """
    Summarizes torch model by showing trainable parameters and weights
    author: wassname
    url: https://gist.github.com/wassname/0fb8f95e4272e6bdd27bd7df386716b7
    license: MIT
    """
    tmpstr = model.__class__.__name__ + ' (\n'
    for key, module in model.network._modules.items():
        # if it contains layers let call it recursively to get params and weights
        is_container = type(module) in [
            torch.nn.modules.container.Container,
            torch.nn.modules.container.Sequential, torch.nn.Module
        ]
        if is_container:
            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'
        if is_container:
            tmpstr += '\n'

    tmpstr = tmpstr + ')'
    return tmpstr
Beispiel #12
0
    def torch_summarize(self, model, show_weights=True, show_parameters=True):
        """Summarizes torch model by showing trainable parameters and weights.
        Taken from wassname on Stackoverflow: https://stackoverflow.com/a/45528544
        """
        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
Beispiel #13
0
    def __repr__(self):
        # We treat the extra repr like the sub-module, one item per line
        extra_lines = []
        extra_repr = self.extra_repr()
        # empty string will be split into list ['']
        if extra_repr:
            extra_lines = extra_repr.split('\n')
        child_lines = []
        for key, module in self._modules.items():
            mod_str = repr(module)
            mod_str = _addindent(mod_str, 2)
            child_lines.append('(' + key + '): ' + mod_str)
        lines = extra_lines + child_lines

        main_str = self._get_name() + '\tnum_heads:' + str(
            self.num_heads) + '\t qkv_dim:' + str(self.qkv_dim)
        if lines:
            # simple one-liner info, which most builtin Modules will use
            if len(extra_lines) == 1 and not child_lines:
                main_str += extra_lines[0]
            else:
                main_str += '\n  ' + '\n  '.join(lines) + '\n'

        main_str += ')'
        return main_str
Beispiel #14
0
def torch_summarize(model, show_weights=True, show_parameters=True):
    """Resume el modelo torch mostrando parámetros y pesos entrenables."""
    tmpstr = model.__class__.__name__ + ' (\n'
    for key, module in model._modules.items():
        # Si contiene capas, llamemos recursivamente para obtener parámetros y pesos
        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 += ', pesos={}'.format(weights)
        if show_parameters:
            tmpstr += ', parametros={}'.format(params)
        tmpstr += '\n'

    tmpstr = tmpstr + ')'
    return tmpstr
Beispiel #15
0
def summary(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
Beispiel #16
0
    def print_summary(self, show_weights=False, show_parameters=False):
        """
        Summarizes torch model by showing trainable parameters and weights.
        """
        tmpstr = self.__class__.__name__ + ' (\n'
        for key, module in self._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 = self.print_summary()
            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 + ')'
        print(f'========== {self.name} Model Summary ==========')
        print(tmpstr)
        num_params = sum(p.numel() for p in self.parameters()
                         if p.requires_grad)
        print(f"Params #: {'{:,}'.format(num_params)}")
        print('==================================================')
Beispiel #17
0
    def repr(model):
        # We treat the extra repr like the sub-module, one item per line
        extra_lines = []
        extra_repr = model.extra_repr()
        # empty string will be split into list ['']
        if extra_repr:
            extra_lines = extra_repr.split("\n")
        child_lines = []
        total_params = 0
        for key, module in model._modules.items():
            mod_str, num_params = repr(module)
            mod_str = _addindent(mod_str, 2)
            child_lines.append("(" + key + "): " + mod_str)
            total_params += num_params
        lines = extra_lines + child_lines

        for name, p in model._parameters.items():
            if p is not None:
                total_params += reduce(lambda x, y: x * y, p.shape)

        main_str = model._get_name() + "("
        if lines:
            # simple one-liner info, which most builtin Modules will use
            if len(extra_lines) == 1 and not child_lines:
                main_str += extra_lines[0]
            else:
                main_str += "\n  " + "\n  ".join(lines) + "\n"

        main_str += ")"
        main_str += ", {:,} params".format(total_params)
        return main_str, total_params
Beispiel #18
0
    def torch_summarize(self, show_weights=True, show_parameters=True):
        """Summarizes torch model by showing trainable parameters and weights."""
        tmpstr = self.network.__class__.__name__ + ' (\n'
        total_params = 0
        total_params_wo_embedding = 0
        for key, module in self.network._modules.items():
            # if it contains layers let call it recursively to get params and weights
            if type(module) in [
                    nn.modules.container.Container,
                    nn.modules.container.Sequential
            ]:
                modstr = self.torch_summarize(self.network)
            else:
                modstr = module.__repr__()
            modstr = _addindent(modstr, 2)

            params = sum([np.prod(p.size()) for p in module.parameters()])
            total_params += params
            if key != 'encoder':
                total_params_wo_embedding += params
            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 += ')\ntotal_params: %d, total_params_wo_embedding: %d' % \
                  (total_params, total_params_wo_embedding)
        self.num_free_params = total_params_wo_embedding
        return tmpstr
Beispiel #19
0
def torch_summarize(model, show_weights=True, show_parameters=True):
    """Summarizes torch model by showing trainable parameters and weights."""
    tmpstr = model.__class__.__name__ + ' (\n'
    total_params = 0
    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()])
        total_params += params
        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 + ')'
    tmpstr += '\n {} learnable parameters'.format(total_params)
    return tmpstr
Beispiel #20
0
def torch_summarize(model, show_weights=True, show_parameters=True):
    """Summarizes torch model by showing trainable parameters and weights."""
    tmpstr = model.__class__.__name__ + ' (\n'
    parameters = 0
    convs = 0
    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, p, cnvs = torch_summarize(module)
            parameters += p
            convs += cnvs
        else:
            modstr = module.__repr__()
            convs += len(modstr.split('Conv2d')) - 1

        modstr = _addindent(modstr, 2)
        # if 'conv' in key:
        #     convs += 1

        params = sum([np.prod(p.size()) for p in module.parameters()])
        parameters += params
        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, parameters)
        tmpstr += ', convs={}'.format(convs)
        tmpstr += '\n'

    tmpstr = tmpstr + ')'
    return tmpstr, parameters, convs
Beispiel #21
0
    def nested_str(self) -> str:
        """
        Return the Python code generated for current GraphModule and its children GraphModules
        """
        module_code = self.code
        module_code = module_code.lstrip('\n')
        module_code = f"class {self._get_name()}(torch.nn.Module):\n" + module_code
        module_code = _addindent(module_code, 4)

        submodule_code_list = [""]
        for submodule in self.children():
            if isinstance(submodule, GraphModule):
                submodule_code_list.append(submodule.__nested_code())
        submodule_code = "\n".join(submodule_code_list)
        submodule_code = _addindent(submodule_code, 4)

        return module_code + submodule_code
Beispiel #22
0
def torch_summarize(model,
                    show_weights=True,
                    show_parameters=True,
                    show_trainable=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__()

        # ====================== Extra stuff (for displaying nn.Parameter) ======================
        lst_params = []
        for name, p in module.named_parameters():
            if (type(p) == torch.nn.parameter.Parameter
                    and "weight" not in name and "bias" not in name):
                lst_params.append("  ({}): Parameter{}".format(
                    name, tuple(p.size())))

        if (lst_params):
            modstr = modstr[:-1]
            modstr += "\n".join(lst_params)
            modstr += "\n)"
        # ====================== Extra stuff (for displaying nn.Parameter) ======================

        modstr = _addindent(modstr, 2)

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

        total_params = sum([
            torch.LongTensor(list(p.size())).prod()
            for p in module.parameters()
        ])
        trainable_params = sum([
            torch.LongTensor(list(p.size())).prod()
            for p in module.parameters() if p.requires_grad
        ])

        tmpstr += "  (" + key + "): " + modstr
        if show_weights:
            tmpstr += ", weights = {}".format(weights)
        if show_parameters:
            tmpstr += ", parameters = {:,}".format(params)
        if show_trainable and total_params != 0 and total_params == trainable_params:
            tmpstr += " (Trainable)"
        tmpstr += "\n"

    tmpstr = tmpstr + ")"
    return tmpstr
Beispiel #23
0
 def __repr__(self):
     """ Overwrite the repr method to get a nice representation."""
     tmpstr = self.__class__.__name__ + '(\n'
     for key, module in self._modules.items():
         modstr = module.__repr__()
         modstr = _addindent(modstr, 2)
         tmpstr = tmpstr + '  ({}, {}): '.format(
             key, self._num_parameters(module)) + modstr + '\n'
     tmpstr = tmpstr + ')'
     return tmpstr
    def __repr__(self):
        # A simplified version of torch.nn.Module.__repr__
        from torch.nn.modules.module import _addindent

        child_lines = []
        for idx, module in enumerate(self._modules):
            mod_str = repr(module)
            mod_str = _addindent(mod_str, 2)
            child_lines.append('(' + str(idx) + '): ' + mod_str)

        main_str = self.__class__.__name__ + '('
        if child_lines:
            main_str += '\n  ' + '\n  '.join(child_lines) + '\n'
        main_str += ')'
        return main_str
def get_model_parameter_str(model):
    """Get a summary string with model parameters

  Adapted from https://stackoverflow.com/a/45528544
  """
    def is_leaf(module):
        if isinstance(module, (nn.ModuleList, nn.Sequential)):
            return False
        elif any((isinstance(module, (nn.ModuleList, nn.Sequential))
                  for module in module._modules.values())):
            return False

        return all((is_leaf(m) for m in module._modules.values()))

    from torch.nn.modules.module import _addindent
    tmpstr = model.__class__.__name__ + ' (\n'

    total_params = 0
    for key, module in model._modules.items():
        if module is None:
            continue

        if is_leaf(module):
            modstr = module.__repr__()
            leaf = True
        else:
            modstr = get_model_parameter_str(module)
            leaf = False

        modstr = _addindent(modstr, 2)

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

        tmpstr += '  (' + key + '): ' + modstr
        if leaf and params > 0:
            tmpstr += ', parameters={}'.format(params)
        tmpstr += '\n'

    tmpstr = tmpstr + ')'
    if total_params > 0:
        tmpstr += ', parameters={}'.format(total_params)

    return tmpstr