prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Pytorch track_gradients_dists errors out if some parameters don't have gradients
  ## 🐛 Bug
  
  When collecting gradients for each layer weight of a model, the function `get_model_layers` errors out if some model parameters don't have gradients.
  
  ### Expected behavior
  
  Ignore weights if grad is None.
  
  ### Environment
  
  - Aim Version (e.g., 3.11.1)
  - Python version 3.10
  - pip version 22.0
  - Any OS
  
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `aim/sdk/adapters/pytorch.py`
  Content:
  ```
  1 def track_params_dists(model, run):
  2     from aim import Distribution
  3     data_hist = get_model_layers(model, 'data')
  4 
  5     for name, params in data_hist.items():
  6         if 'weight' in params:
  7             run.track(
  8                 Distribution(params['weight']),
  9                 name=name,
  10                 context={
  11                     'type': 'data',
  12                     'params': 'weights',
  13                 }
  14             )
  15         if 'bias' in params:
  16             run.track(
  17                 Distribution(params['bias']),
  18                 name=name,
  19                 context={
  20                     'type': 'data',
  21                     'params': 'biases',
  22                 }
  23             )
  24 
  25 
  26 def track_gradients_dists(model, run):
  27     from aim import Distribution
  28     grad_hist = get_model_layers(model, 'grad')
  29 
  30     for name, params in grad_hist.items():
  31         if 'weight' in params:
  32             run.track(
  33                 Distribution(params['weight']),
  34                 name=name,
  35                 context={
  36                     'type': 'gradients',
  37                     'params': 'weights',
  38                 }
  39             )
  40         if 'bias' in params:
  41             run.track(
  42                 Distribution(params['bias']),
  43                 name=name,
  44                 context={
  45                     'type': 'gradients',
  46                     'params': 'biases',
  47                 }
  48             )
  49 
  50 
  51 def get_model_layers(model, dt, parent_name=None):
  52     layers = {}
  53     for name, m in model.named_children():
  54         layer_name = '{}__{}'.format(parent_name, name) \
  55             if parent_name \
  56             else name
  57         layer_name += '.{}'.format(type(m).__name__)
  58 
  59         if len(list(m.named_children())):
  60             layers.update(get_model_layers(m, dt, layer_name))
  61         else:
  62             layers[layer_name] = {}
  63             if hasattr(m, 'weight') \
  64                     and m.weight is not None \
  65                     and hasattr(m.weight, dt):
  66                 layers[layer_name]['weight'] = get_pt_tensor(getattr(m.weight, dt)).numpy()
  67 
  68             if hasattr(m, 'bias') \
  69                     and m.bias is not None \
  70                     and hasattr(m.bias, dt):
  71                 layers[layer_name]['bias'] = get_pt_tensor(getattr(m.bias, dt)).numpy()
  72 
  73     return layers
  74 
  75 
  76 # Move tensor from GPU to CPU
  77 def get_pt_tensor(t):
  78     return t.cpu() if hasattr(t, 'is_cuda') and t.is_cuda else t
  79
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/aim/sdk/adapters/pytorch.py b/aim/sdk/adapters/pytorch.py
  --- a/aim/sdk/adapters/pytorch.py
  +++ b/aim/sdk/adapters/pytorch.py
  @@ -60,15 +60,17 @@
               layers.update(get_model_layers(m, dt, layer_name))
           else:
               layers[layer_name] = {}
  -            if hasattr(m, 'weight') \
  -                    and m.weight is not None \
  -                    and hasattr(m.weight, dt):
  -                layers[layer_name]['weight'] = get_pt_tensor(getattr(m.weight, dt)).numpy()
  +            weight = None
  +            if hasattr(m, 'weight') and m.weight is not None:
  +                weight = getattr(m.weight, dt, None)
  +                if weight is not None:
  +                    layers[layer_name]['weight'] = get_pt_tensor(weight).numpy()
   
  -            if hasattr(m, 'bias') \
  -                    and m.bias is not None \
  -                    and hasattr(m.bias, dt):
  -                layers[layer_name]['bias'] = get_pt_tensor(getattr(m.bias, dt)).numpy()
  +            bias = None
  +            if hasattr(m, 'bias') and m.bias is not None:
  +                bias = getattr(m.bias, dt, None)
  +                if bias is not None:
  +                    layers[layer_name]['bias'] = get_pt_tensor(bias).numpy()
   
       return layers
  
verification_info: {"golden_diff": "diff --git a/aim/sdk/adapters/pytorch.py b/aim/sdk/adapters/pytorch.py\n--- a/aim/sdk/adapters/pytorch.py\n+++ b/aim/sdk/adapters/pytorch.py\n@@ -60,15 +60,17 @@\n             layers.update(get_model_layers(m, dt, layer_name))\n         else:\n             layers[layer_name] = {}\n-            if hasattr(m, 'weight') \\\n-                    and m.weight is not None \\\n-                    and hasattr(m.weight, dt):\n-                layers[layer_name]['weight'] = get_pt_tensor(getattr(m.weight, dt)).numpy()\n+            weight = None\n+            if hasattr(m, 'weight') and m.weight is not None:\n+                weight = getattr(m.weight, dt, None)\n+                if weight is not None:\n+                    layers[layer_name]['weight'] = get_pt_tensor(weight).numpy()\n \n-            if hasattr(m, 'bias') \\\n-                    and m.bias is not None \\\n-                    and hasattr(m.bias, dt):\n-                layers[layer_name]['bias'] = get_pt_tensor(getattr(m.bias, dt)).numpy()\n+            bias = None\n+            if hasattr(m, 'bias') and m.bias is not None:\n+                bias = getattr(m.bias, dt, None)\n+                if bias is not None:\n+                    layers[layer_name]['bias'] = get_pt_tensor(bias).numpy()\n \n     return layers\n", "issue": "Pytorch track_gradients_dists errors out if some parameters don't have gradients\n## \ud83d\udc1b Bug\r\n\r\nWhen collecting gradients for each layer weight of a model, the function `get_model_layers` errors out if some model parameters don't have gradients.\r\n\r\n### Expected behavior\r\n\r\nIgnore weights if grad is None.\r\n\r\n### Environment\r\n\r\n- Aim Version (e.g., 3.11.1)\r\n- Python version 3.10\r\n- pip version 22.0\r\n- Any OS\r\n\r\n\n", "before_files": [{"content": "def track_params_dists(model, run):\n    from aim import Distribution\n    data_hist = get_model_layers(model, 'data')\n\n    for name, params in data_hist.items():\n        if 'weight' in params:\n            run.track(\n                Distribution(params['weight']),\n                name=name,\n                context={\n                    'type': 'data',\n                    'params': 'weights',\n                }\n            )\n        if 'bias' in params:\n            run.track(\n                Distribution(params['bias']),\n                name=name,\n                context={\n                    'type': 'data',\n                    'params': 'biases',\n                }\n            )\n\n\ndef track_gradients_dists(model, run):\n    from aim import Distribution\n    grad_hist = get_model_layers(model, 'grad')\n\n    for name, params in grad_hist.items():\n        if 'weight' in params:\n            run.track(\n                Distribution(params['weight']),\n                name=name,\n                context={\n                    'type': 'gradients',\n                    'params': 'weights',\n                }\n            )\n        if 'bias' in params:\n            run.track(\n                Distribution(params['bias']),\n                name=name,\n                context={\n                    'type': 'gradients',\n                    'params': 'biases',\n                }\n            )\n\n\ndef get_model_layers(model, dt, parent_name=None):\n    layers = {}\n    for name, m in model.named_children():\n        layer_name = '{}__{}'.format(parent_name, name) \\\n            if parent_name \\\n            else name\n        layer_name += '.{}'.format(type(m).__name__)\n\n        if len(list(m.named_children())):\n            layers.update(get_model_layers(m, dt, layer_name))\n        else:\n            layers[layer_name] = {}\n            if hasattr(m, 'weight') \\\n                    and m.weight is not None \\\n                    and hasattr(m.weight, dt):\n                layers[layer_name]['weight'] = get_pt_tensor(getattr(m.weight, dt)).numpy()\n\n            if hasattr(m, 'bias') \\\n                    and m.bias is not None \\\n                    and hasattr(m.bias, dt):\n                layers[layer_name]['bias'] = get_pt_tensor(getattr(m.bias, dt)).numpy()\n\n    return layers\n\n\n# Move tensor from GPU to CPU\ndef get_pt_tensor(t):\n    return t.cpu() if hasattr(t, 'is_cuda') and t.is_cuda else t\n", "path": "aim/sdk/adapters/pytorch.py"}], "after_files": [{"content": "def track_params_dists(model, run):\n    from aim import Distribution\n    data_hist = get_model_layers(model, 'data')\n\n    for name, params in data_hist.items():\n        if 'weight' in params:\n            run.track(\n                Distribution(params['weight']),\n                name=name,\n                context={\n                    'type': 'data',\n                    'params': 'weights',\n                }\n            )\n        if 'bias' in params:\n            run.track(\n                Distribution(params['bias']),\n                name=name,\n                context={\n                    'type': 'data',\n                    'params': 'biases',\n                }\n            )\n\n\ndef track_gradients_dists(model, run):\n    from aim import Distribution\n    grad_hist = get_model_layers(model, 'grad')\n\n    for name, params in grad_hist.items():\n        if 'weight' in params:\n            run.track(\n                Distribution(params['weight']),\n                name=name,\n                context={\n                    'type': 'gradients',\n                    'params': 'weights',\n                }\n            )\n        if 'bias' in params:\n            run.track(\n                Distribution(params['bias']),\n                name=name,\n                context={\n                    'type': 'gradients',\n                    'params': 'biases',\n                }\n            )\n\n\ndef get_model_layers(model, dt, parent_name=None):\n    layers = {}\n    for name, m in model.named_children():\n        layer_name = '{}__{}'.format(parent_name, name) \\\n            if parent_name \\\n            else name\n        layer_name += '.{}'.format(type(m).__name__)\n\n        if len(list(m.named_children())):\n            layers.update(get_model_layers(m, dt, layer_name))\n        else:\n            layers[layer_name] = {}\n            weight = None\n            if hasattr(m, 'weight') and m.weight is not None:\n                weight = getattr(m.weight, dt, None)\n                if weight is not None:\n                    layers[layer_name]['weight'] = get_pt_tensor(weight).numpy()\n\n            bias = None\n            if hasattr(m, 'bias') and m.bias is not None:\n                bias = getattr(m.bias, dt, None)\n                if bias is not None:\n                    layers[layer_name]['bias'] = get_pt_tensor(bias).numpy()\n\n    return layers\n\n\n# Move tensor from GPU to CPU\ndef get_pt_tensor(t):\n    return t.cpu() if hasattr(t, 'is_cuda') and t.is_cuda else t\n", "path": "aim/sdk/adapters/pytorch.py"}]}