
    &Vf3                         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S )
    N)ops)utils)keras_export)Layer)serialization_libzkeras.layers.Bidirectionalc                        e Zd ZdZ	 	 	 d fd	Zd ZddZ	 	 	 ddZd Zd	 Z	e
d
             ZddZd Z fdZedd            Z xZS )Bidirectionala~  Bidirectional wrapper for RNNs.

    Args:
        layer: `keras.layers.RNN` instance, such as
            `keras.layers.LSTM` or `keras.layers.GRU`.
            It could also be a `keras.layers.Layer` instance
            that meets the following criteria:
            1. Be a sequence-processing layer (accepts 3D+ inputs).
            2. Have a `go_backwards`, `return_sequences` and `return_state`
            attribute (with the same semantics as for the `RNN` class).
            3. Have an `input_spec` attribute.
            4. Implement serialization via `get_config()` and `from_config()`.
            Note that the recommended way to create new RNN layers is to write a
            custom RNN cell and use it with `keras.layers.RNN`, instead of
            subclassing `keras.layers.Layer` directly.
            When `return_sequences` is `True`, the output of the masked
            timestep will be zero regardless of the layer's original
            `zero_output_for_mask` value.
        merge_mode: Mode by which outputs of the forward and backward RNNs
            will be combined. One of `{"sum", "mul", "concat", "ave", None}`.
            If `None`, the outputs will not be combined,
            they will be returned as a list. Defaults to `"concat"`.
        backward_layer: Optional `keras.layers.RNN`,
            or `keras.layers.Layer` instance to be used to handle
            backwards input processing.
            If `backward_layer` is not provided, the layer instance passed
            as the `layer` argument will be used to generate the backward layer
            automatically.
            Note that the provided `backward_layer` layer should have properties
            matching those of the `layer` argument, in particular
            it should have the same values for `stateful`, `return_states`,
            `return_sequences`, etc. In addition, `backward_layer`
            and `layer` should have different `go_backwards` argument values.
            A `ValueError` will be raised if these requirements are not met.

    Call arguments:
        The call arguments for this layer are the same as those of the
        wrapped RNN layer. Beware that when passing the `initial_state`
        argument during the call of this layer, the first half in the
        list of elements in the `initial_state` list will be passed to
        the forward RNN call and the last half in the list of elements
        will be passed to the backward RNN call.

    Note: instantiating a `Bidirectional` layer from an existing RNN layer
    instance will not reuse the weights state of the RNN layer instance -- the
    `Bidirectional` layer will have freshly initialized weights.

    Examples:

    ```python
    model = Sequential([
        Input(shape=(5, 10)),
        Bidirectional(LSTM(10, return_sequences=True),
        Bidirectional(LSTM(10)),
        Dense(5, activation="softmax"),
    ])
    model.compile(loss='categorical_crossentropy', optimizer='rmsprop')

    # With custom backward layer
    forward_layer = LSTM(10, return_sequences=True)
    backward_layer = LSTM(10, activation='relu', return_sequences=True,
                          go_backwards=True)
    model = Sequential([
        Input(shape=(5, 10)),
        Bidirectional(forward_layer, backward_layer=backward_layer),
        Dense(5, activation="softmax"),
    ])
    model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
    ```
    concatNc                    t          |t                    st          d|           |'t          |t                    st          d|           |dvrt          d| d           t                      j        di | t          j        |          }dt          j        |j	        d          z   |d         d<   t          j
        |          | _        |_t          j        |          }d	|d         d
<   dt          j        |j	        d          z   |d         d<   t          j
        |          | _        n|| _        |                                  d } || j                    || j                   || _        |r=t          |          }|d |dz           | j        _        ||dz  d          | j        _        |j        | _        |j        | _        |j        | _        d	| _        |j        | _        d S )NzXPlease initialize `Bidirectional` layer with a `keras.layers.Layer` instance. Received: zG`backward_layer` need to be a `keras.layers.Layer` instance. Received: )summulaver
   NzInvalid merge mode. Received: zC. Merge mode should be one of {"sum", "mul", "ave", "concat", None}forward_confignameTgo_backwards	backward_c                 D    t          | dd           | j        | _        d S d S )Nzero_output_for_mask)getattrreturn_sequencesr   )layers    _/var/www/html/software/conda/lib/python3.11/site-packages/keras/src/layers/rnn/bidirectional.pyforce_zero_output_for_maskz:Bidirectional.__init__.<locals>.force_zero_output_for_mask   s/    u4d;;G-2-C*** HG        )
isinstancer   
ValueErrorsuper__init__r   serialize_keras_objectr   removeprefixr   deserialize_keras_objectforward_layerbackward_layer_verify_layer_config
merge_modeleninitial_weightsstatefulr   return_statesupports_masking
input_spec)
selfr   r(   weightsr&   kwargsr   r   nw	__class__s
            r   r!   zBidirectional.__init__S   sc    %'' 	D<AD D   %j.O.O%8'58 8   BBB8 8 8 8  
 	""6""" #9%@@#-0BJ
1
 1
 $
x  /GOO!&=eDDF/3F8^,'2U5G
K6 6 (F8V$ #4"L# #D #1D!!###	D 	D 	D
 	#"4#5666""4#6777$ 	EWB18271CD.29"'))2DD/ % 6!. $*r   c           
      ,   | j         j        | j        j        k    r)t          d| j         j         d| j        j                   d}|D ]K}t	          | j         |          }t	          | j        |          }||k    rt          d| d| d| d          LdS )	zBEnsure the forward and backward layers have valid common property.zrForward layer and backward layer should have different `go_backwards` value. Received: forward_layer.go_backwards z, backward_layer.go_backwards=)r+   r   r,   zTForward layer and backward layer are expected to have the same value for attribute "z", got "z" for forward layer and "z" for backward layerN)r%   r   r&   r   r   )r/   common_attributesaforward_valuebackward_values        r   r'   z"Bidirectional._verify_layer_config   s    *d.A.NNN6 %26 6
 &36 6   M" 		 		A#D$6::M$T%8!<<N.. =56= =%= = '= = =   /		 		r   c                    | j                             |          }| j        r|d         |dd          }}| j        dk    r/t	          |          }|dxx         dz  cc<   t          |          }n| j        ||g}| j        r2| j        t          |          |z   |z   S t          |g          |z   |z   S t          |          S )Nr      r
   r   )r%   compute_output_shaper,   r(   listtuple)r/   sequences_shapeinitial_state_shapeoutput_shapestate_shapes        r   r<   z"Bidirectional.compute_output_shape   s    )>>OO 	J(4Qabb9I+L?h&&--L! ..LL_$(,7L 	I&\**[8;FF,((K8KHH\"""r   c                 <   i }| j         j        r||d<   | j         j        r||d<   |+||}}t          |          dz  }|d |         }	||d          }
n	||}}d\  }	}
 | j         |fd|	i|} | j        |fd|
i|}| j        r2t          |dd          |dd          z             }|d         }|d         }t          j        || j	                  }t          j        || j	                  }| j
        rt          j        |d          }| j        d	k    rt          j        ||gd
          }nZ| j        dk    r||z   }nI| j        dk    r	||z   dz  }n5| j        dk    r||z  }n$| j        ||f}nt          d| j         d          | j        r| j        ||z   S |f|z   S |S )Ntrainingmaskr   NNinitial_stater:   r   )axisr
   r;   r   r   r   z/Unrecognized value for `merge_mode`. Received: z0Expected one of {"concat", "sum", "ave", "mul"}.)r%   _call_has_training_arg_call_has_mask_argr)   r&   r,   r>   r   castcompute_dtyper   flipr(   concatenater   )r/   	sequencesrG   rE   rD   r1   forward_inputsbackward_inputshalfforward_statebackward_stateyy_revstatesoutputs                  r   callzBidirectional.call   sT    4 	*!)F:0 	"!F6N$
 /8ON}%%*D)%4%0M*4551NN.7ON,6)M>D
 
*7
;A
 
 $#
 
+9
=C
 
  	1QRR559,--F!A!HEHQ*++ 233  	,HU+++E?h&&_aZb999FF_%%YFF_%%%i1_FF_%%YFF_$ZFFC!_C C C  
  	&&&9v%%r   c                 .    |                                   d S N)reset_stater/   s    r   reset_stateszBidirectional.reset_states  s    r   c                     | j         st          d          | j                                         | j                                         d S )NzLayer must be stateful.)r+   AttributeErrorr%   r\   r&   r]   s    r   r\   zBidirectional.reset_state  sK    } 	< !:;;;&&((('')))))r   c                     | j         j        r2| j        j        r&t          | j         j        | j        j        z             S d S r[   )r%   rW   r&   r>   r]   s    r   rW   zBidirectional.states  sC    $ 	Q)<)C 	Q+2T5H5OOPPPtr   c                     | j         j        s| j                             |           | j        j        s| j                            |           d| _        d S )NT)r%   builtbuildr&   )r/   r?   r@   s      r   rd   zBidirectional.build  sW    !' 	6$$_555"( 	7%%o666


r   c                    t          |t                    r|d         }| j        r| j        s||f}n|}n| j        sdnd }| j        r>| j        7d | j        D             }t          |t                    r||dz  z   S |f|dz  z   S |S )Nr   rF   c              3      K   | ]}d V  d S r[   r   ).0_s     r   	<genexpr>z-Bidirectional.compute_mask.<locals>.<genexpr>$  s"      441$444444r   r   )r   r=   r   r(   r,   rW   )r/   rh   rE   output_mask
state_masks        r   compute_maskzBidirectional.compute_mask  s    dD!! 	7D  	H? ##Tl".2oG,,4K 	3!844444J+t,, 4"Z!^33>JN22r   c                     d| j         i}t          j        | j                  |d<   t          j        | j                  |d<   t                                                      }i ||S )Nr(   r   r&   )r(   r   r"   r%   r&   r    
get_config)r/   r   base_configr3   s      r   rn   zBidirectional.get_config*  sr    0+B
 
w $5#K$
 $
  gg((**(+(((r   c                     t          j        |          }t          j        |d         |          |d<   |                    dd           }|t          j        ||          }||d<    | di |}|S )Nr   )custom_objectsr&   r   )copydeepcopyr   r$   pop)clsr   rq   backward_layer_configr&   r   s         r   from_configzBidirectional.from_config5  s     v&&+D7ON
 
 
w !'

+;T B B ,.G%n  N (6F#$fr   )r
   NNr[   )NNN)__name__
__module____qualname____doc__r!   r'   r<   rY   r^   r\   propertyrW   rd   rl   rn   classmethodrw   __classcell__)r3   s   @r   r	   r	   
   s4       E ET @+ @+ @+ @+ @+ @+D  0# # # #, ? ? ? ?B  * * *   X
     $	) 	) 	) 	) 	)    [    r   r	   )rr   	keras.srcr   r   keras.src.api_exportr   keras.src.layers.layerr   keras.src.savingr   r	   r   r   r   <module>r      s                 - - - - - - ( ( ( ( ( ( . . . . . . *++{ { { { {E { { ,+{ { {r   