
    &Vf                         d dl Z d dlmZ d dlmZ d dlmZ d dlmZ d dlm	Z	  ed           G d d	e                      Z
d
 ZdS )    N)parse)keras_export)Layer)convert_to_numpy)convert_to_tensorzkeras.layers.TorchModuleWrapperc                   d     e Zd ZdZd fd	ZddZd Zd Zd Zd	 Z	 fd
Z
ed             Z xZS )TorchModuleWrappera
  Torch module wrapper layer.

    `TorchModuleWrapper` is a wrapper class that can turn any
    `torch.nn.Module` into a Keras layer, in particular by making its
    parameters trackable by Keras.

    Args:
        module: `torch.nn.Module` instance. If it's a `LazyModule`
            instance, then its parameters must be initialized before
            passing the instance to `TorchModuleWrapper` (e.g. by calling
            it once).
        name: The name of the layer (string).

    Example:

    Here's an example of how the `TorchModuleWrapper` can be used with vanilla
    PyTorch modules.

    ```python
    import torch.nn as nn
    import torch.nn.functional as F

    import keras
    from keras.src.layers import TorchModuleWrapper

    class Classifier(keras.Model):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            # Wrap `torch.nn.Module`s with `TorchModuleWrapper`
            # if they contain parameters
            self.conv1 = TorchModuleWrapper(
                nn.Conv2d(in_channels=1, out_channels=32, kernel_size=(3, 3))
            )
            self.conv2 = TorchModuleWrapper(
                nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3))
            )
            self.pool = nn.MaxPool2d(kernel_size=(2, 2))
            self.flatten = nn.Flatten()
            self.dropout = nn.Dropout(p=0.5)
            self.fc = TorchModuleWrapper(nn.Linear(1600, 10))

        def call(self, inputs):
            x = F.relu(self.conv1(inputs))
            x = self.pool(x)
            x = F.relu(self.conv2(x))
            x = self.pool(x)
            x = self.flatten(x)
            x = self.dropout(x)
            x = self.fc(x)
            return F.softmax(x, dim=1)


    model = Classifier()
    model.build((1, 28, 28))
    print("Output shape:", model(torch.ones(1, 1, 28, 28).to("cuda")).shape)

    model.compile(
        loss="sparse_categorical_crossentropy",
        optimizer="adam",
        metrics=["accuracy"]
    )
    model.fit(train_loader, epochs=5)
    ```
    Nc                 L    t                      j        dd|i| dd lm} ddlm} t          ||j        j        j	                  r&|
                                rt          d|           |                     |                      | _        |                                  d S )Nnamer   )
get_devicezmLazyModules are not supported unless they are already initialized. Received uninitialized LazyModule: module= )super__init__torch.nnnnkeras.src.backend.torch.corer   
isinstancemoduleslazyLazyModuleMixinhas_uninitialized_params
ValueErrortomodule_track_module_parameters)selfr   r   kwargsr   r   	__class__s         X/var/www/html/software/conda/lib/python3.11/site-packages/keras/src/utils/torch_utils.pyr   zTorchModuleWrapper.__init__N   s    --d-f---;;;;;; vrz>??	//11	 F=CF F   ii

--%%'''''    Tc                 8    | j                             |          S )N)recurse)r   
parameters)r   r"   s     r   r#   zTorchModuleWrapper.parametersa   s    {%%g%666r    c                     ddl m} | j                                        D ])} |||j                  }|                     |           *d| _        d S )Nr   )Variable)initializer	trainableT)keras.src.backend.torchr%   r   r#   requires_grad_track_variablebuilt)r   r%   paramvariables       r   r   z+TorchModuleWrapper._track_module_parametersd   su    444444[++-- 	+ 	+E  x!U-@  H   ****


r    c                      | j         |i |S N)r   )r   argsr   s      r   callzTorchModuleWrapper.callp   s    t{D+F+++r    c                     | j                                         }|                                D ]}t          ||                   ||<   dS )zSaves model's state from `state_dict`.
        `model.parameters` excludes some of model's state like
        `BatchNorm` mean and variance. So, use `state_dict` to obtain
        all of model's state.
        N)r   
state_dictkeysr   r   storer3   keys       r   save_own_variablesz%TorchModuleWrapper.save_own_variabless   sQ     [++--
??$$ 	; 	;C)*S/::E#JJ	; 	;r    c                     i }|                                 D ]C}t          |t                    r|                                }t	          ||                   ||<   D| j                            |           dS )z%Loads model's state via `state_dict`.N)r4   r   bytesdecoder   r   load_state_dictr5   s       r   load_own_variablesz%TorchModuleWrapper.load_own_variables}   sp    
::<< 	< 	<C#u%% #jjll/c
;;JsOO##J/////r    c                     t                                                      }dd l}t          j                    }|                    | j        |           d|                                i}i ||S )Nr   r   )r   
get_configtorchioBytesIOsaver   getvalue)r   base_configr@   bufferconfigr   s        r   r?   zTorchModuleWrapper.get_config   sf    gg((**

4;'''FOO--.(+(((r    c                     dd l }d|v r2t          j        |d                   }|                    |          |d<    | di |S )Nr   r   r   )r@   rA   rB   load)clsrG   r@   rF   s       r   from_configzTorchModuleWrapper.from_config   sR    vZx 011F$zz&11F8s}}V}}r    r/   )T)__name__
__module____qualname____doc__r   r#   r   r1   r8   r=   r?   classmethodrK   __classcell__)r   s   @r   r	   r	      s        ? ?B( ( ( ( ( (&7 7 7 7
 
 
, , ,; ; ;0 0 0) ) ) ) )   [    r    r	   c                     dd l }t          |j                  t          d          k    r|                    |           S | S )Nr   z2.1.0)r@   r   __version__no_grad)	orig_funcr@   s     r   rT   rT      s?    LLLU5>>11}}Y'''r    )rA   packaging.versionr   keras.src.api_exportr   keras.src.layersr   keras.src.opsr   r   r	   rT   r   r    r   <module>rZ      s    				 # # # # # # - - - - - - " " " " " " * * * * * * + + + + + + /00J J J J J J J 10JZ    r    