
    ij                         d dl Z 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 d dl
mZ d dlmZ  ed	       G d
 de	             Zd Zy)    N)parse)backend)keras_export)Layer)convert_to_numpy)convert_to_tensor)in_safe_modezkeras.layers.TorchModuleWrapperc                   p     e Zd ZdZd fd	ZddZd ZdddZd Zd	 Z	 fd
Z
 fdZed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.

    `TorchModuleWrapper` is only compatible with the PyTorch backend and
    cannot be used with the TensorFlow or JAX backends.

    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).
        output_shape :The shape of the output of this layer. It helps Keras
            perform automatic shape inference.
        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
    import torch.nn as nn
    import torch.nn.functional as F

    import keras
    from keras.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                 4   t        |   dd|i| dd lm} ddlm} t        ||j                  j                  j                        r|j                         rt        d|       |j                   |             | _        | j                          || _        y )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output_shape)selfr   r   r   kwargsr   r   	__class__s          p/var/www/html/emotional.easysim.app/public_html/venv/lib/python3.12/site-packages/keras/src/utils/torch_utils.pyr   zTorchModuleWrapper.__init__W   s    -d-f-; vrzz>>?//1==CHF  ii
-%%'(    c                 :    | j                   j                  |      S )N)recurse)r   
parameters)r   r%   s     r"   r&   zTorchModuleWrapper.parametersk   s    {{%%g%66r#   c                     | j                   j                         D ]4  }t        j                  ||j                        }| j                  |       6 d| _        y )N)initializer	trainableT)r   r&   r   Variablerequires_grad_track_variablebuilt)r   paramvariables      r"   r   z+TorchModuleWrapper._track_module_parametersn   sT    [[++- 	+E ''!U-@-@H   *	+ 
r#   )trainingc                p    |du r| j                          n| j                           | j                  |i |S )NF)evaltrainr   )r   r0   argsr    s       r"   callzTorchModuleWrapper.callx   s2    uIIKJJLt{{D+F++r#   c                     | j                   j                         }|j                         D ]  }t        ||         ||<    y)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   storer7   keys       r"   save_own_variablesz%TorchModuleWrapper.save_own_variables   s>     [[++-
??$ 	;C)*S/:E#J	;r#   c                     i }|j                         D ]3  }t        |t              r|j                         }t	        ||         ||<   5 | j
                  j                  |       y)z%Loads model's state via `state_dict`.N)r8   r   bytesdecoder   r   load_state_dictr9   s       r"   load_own_variablesz%TorchModuleWrapper.load_own_variables   sW    
::< 	<C#u%jjl/c
;JsO	< 	##J/r#   c                 R    | j                   t        | 	  |      S | j                   S )N)r   r   compute_output_shape)r   input_shaper!   s     r"   rC   z'TorchModuleWrapper.compute_output_shape   s+    $7/<<   r#   c                    t         |          }dd l}t        j                         }|j                  | j                  |       t        j                  |j                               j                  d      }|| j                  d}i ||S )Nr   ascii)r   r   )r   
get_configtorchioBytesIOsaver   base64	b64encodegetvaluer?   r   )r   base_configrH   buffer
buffer_b64configr!   s         r"   rG   zTorchModuleWrapper.get_config   sw    g(*

4;;'%%foo&78??H
  --
 )+(((r#   c                     dd l }d|v ro||n	t               }|durt        d      t        j                  |d   j                  d            }t        j                  |      }|j                  |d      |d<    | di |S )Nr   r   Fad  Requested the deserialization of a `torch.nn.Module` object via `torch.load()`. This carries a potential risk of arbitrary code execution and thus it is disallowed by default. If you trust the source of the artifact, you can override this error by passing `safe_mode=False` to the loading function, or calling `keras.config.enable_unsafe_deserialization().rF   )weights_onlyr   )	rH   r	   r   rL   	b64decodeencoderI   rJ   load)clsrR   custom_objects	safe_moderH   effective_safe_modebuffer_bytesrP   s           r"   from_configzTorchModuleWrapper.from_config   s    v '2	   #%/ E  "++F8,<,C,CG,LMLZZ-F$zz&uzEF8}V}r#   )NN)T)__name__
__module____qualname____doc__r   r&   r   r5   r<   rA   rC   rG   classmethodr]   __classcell__)r!   s   @r"   r   r      sK    EN)(7 $( ,;0!
)  r#   r   c                 r    dd l }t        |j                        t        d      k\  r|j                  |       S | S )Nr   z2.1.0)rH   r   __version__no_grad)	orig_funcrH   s     r"   rf   rf      s1    U5>1}}Y''r#   )rL   rI   packaging.versionr   	keras.srcr   keras.src.api_exportr   keras.src.layersr   keras.src.opsr   r   "keras.src.saving.serialization_libr	   r   rf   r   r#   r"   <module>rn      sJ     	 #  - " * + ; /0r r 1rjr#   