
    ~WhU                         d Z ddlZddlmc 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 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 )zBidirectional wrapper for RNNs.    N)backend)Layer)	InputSpec)	rnn_utils)Wrapper)serialization)generic_utils)
tf_inspect)tf_utils)keras_exportzkeras.layers.Bidirectionalc                        e Zd ZdZ	 	 	 d fd	Zed             Zd ZddZe	j
        d	             Zd fd
	Z	 	 	 	 ddZd Zd Zd Zed             Z fdZedd            Z xZS )BidirectionalaY  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 the `returns_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. Default
        value is '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.

    Raises:
      ValueError:
        1. If `layer` or `backward_layer` is not a `Layer` instance.
        2. In case of invalid `merge_mode` argument.
        3. If `backward_layer` has mismatched properties compared to `layer`.

    Examples:

    ```python
    model = Sequential()
    model.add(Bidirectional(LSTM(10, return_sequences=True),
                                 input_shape=(5, 10)))
    model.add(Bidirectional(LSTM(10)))
    model.add(Dense(5))
    model.add(Activation('softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='rmsprop')

    # With custom backward layer
    model = Sequential()
    forward_layer = LSTM(10, return_sequences=True)
    backward_layer = LSTM(10, activation='relu', return_sequences=True,
                          go_backwards=True)
    model.add(Bidirectional(forward_layer, backward_layer=backward_layer,
                            input_shape=(5, 10)))
    model.add(Dense(5))
    model.add(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          d| _         t	                      j        |fi | d| _        |                     |          | _        ||                     |d          | _        n || _        t          j
        |          | _        d	| j        j        z   | j        _        d
| j        j        z   | j        _        |                                  d } || j                    || j                   || _        |r=t!          |          }|d |dz           | j        _        ||dz  d          | j        _        |j        | _        |j        | _        |j        | _        d| _        |                    d|j                  | _        d| _        |j        | _        d S )Nz[Please initialize `Bidirectional` layer with a `tf.keras.layers.Layer` instance. Received: zJ`backward_layer` need to be a `tf.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}FT)go_backwardsforward_	backward_c                 D    t          | dd           | j        | _        d S d S )Nzero_output_for_mask)getattrreturn_sequencesr   )layers    d/var/www/html/movieo_spanner_bot/venv/lib/python3.11/site-packages/keras/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       	trainabler   )
isinstancer   
ValueError_setattr_trackingsuper__init___recreate_layer_from_configforward_layerbackward_layerr   serialize_keras_object_backward_layer_configname_name_verify_layer_config
merge_modeleninitial_weightsstatefulr   return_statesupports_maskinggetr    
_trainable_num_constants
input_spec)	selfr   r.   weightsr(   kwargsr   nw	__class__s	           r   r%   zBidirectional.__init__m   sc    %'' 	G?DG G   %j.O.O%8'58 8   BBB8 8 8 8   "'))&)))!% "==eDD!"&"B"BD #C # #D #1D
 +8*N+ +D' $.0B0G#G $/$2E2J$J!!!###	D 	D 	D
 	#"4#5666""4#6777$ 	EWB18271CD.29"'))2DD/ % 6!. $ **[%/BB*r   c                     | j         j        S N)r   !_use_input_spec_as_call_signaturer8   s    r   r?   z/Bidirectional._use_input_spec_as_call_signature   s    z;;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.ziForward layer and backward layer should have different `go_backwards` value.forward_layer.go_backwards = z,backward_layer.go_backwards = )r1   r   r2   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   )r8   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   Fc                    |                                 }|r|d          |d<   dt          j        |j        j                  j        v roi }t          |dd           }|>|j        ||j        j        <   t          |dg           }|D ]}|j        ||j        j        <   |j                            ||          S |j                            |          S )Nr   custom_objectscellcellsrG   )
get_configr
   getfullargspecr<   from_configargsr   __name__)r8   r   r   configrG   rH   stacked_cellscs           r   r&   z)Bidirectional._recreate_layer_from_config   s     !!## 	@)/)?%?F>"()DEEJK K  N5&$//D:>.t~67 'gr : :& G GA;<;N1;#788?..~ /    ?..v666r   c                 2   | j                             |          }| j        r;t          j        |dd          d          }t          j        |d         d          }nt          j        |d          }| j        dk    r9|                                }|dxx         dz  cc<   t          j        |          }n| j        |t          j	        |          g}| j        r<| j        ||z   t          j	        |          z   S |g|z   t          j	        |          z   S |S )N   F)	to_tuplesr   r   r   )
r'   compute_output_shaper2   r   convert_shapesr.   as_listtfTensorShapecopy)r8   input_shapeoutput_shapestate_shapes       r   rW   z"Bidirectional.compute_output_shape   sC   )>>{KK 
	"1QRR E  K $2Q5  LL $2  L ?h&&'//11L!>,77LL_$($)L*A*ABL 	I&#k1DIk4J4JJJ >K/$)K2H2HHHr   c                 ,   t          j        |||| j                  \  }}}t          |t                    r%t          |          dk    r
|dd         }|d         }|| t                      j        |fi |S g }g }|t          |          }|dz  dk    rt          d|           ||d<   ||z  }t          j
                            d |          }|d|dz           | j        _        ||dz  d         | j        _        ||z  }|i||d<   ||z  }d	 |D             }	|	| j        _        |	| j        _        ||	z  }t          |          | _        | j        | j        _        | j        | j        _        t!          j        t          j
                            |          d                   }
t          j
                            |          D ])}t!          j        |          |
k    rt          d
          *|
r|g|z   }d t'          t          t          j
                            |                              D             |z   }d|d<   d|d<   | j        }|| _         t                      j        |fi |}|| _        |S  t                      j        |fi |S )zN`Bidirectional.__call__` implements the same API as the wrapped
        `RNN`.rT   Nr   r   zWhen passing `initial_state` to a Bidirectional RNN, the state should be a list containing the states of the underlying RNNs. Received: initial_statec                 F    t          t          j        |                     S )Nshaper   r   	int_shape)states    r   <lambda>z(Bidirectional.__call__.<locals>.<lambda>*  s    ig.?.F.FGGG r   	constantsc                 R    g | ]$}t          t          j        |                     %S )rc   re   ).0constants     r   
<listcomp>z*Bidirectional.__call__.<locals>.<listcomp>3  s>         1( ; ;<<<  r   zThe initial state of a Bidirectional layer cannot be specified with a mix of Keras tensors and non-Keras tensors (a "Keras tensor" is a tensor that was returned by a Keras layer, or by `Input`)c                     g | ]}d S r>    rk   _s     r   rm   z*Bidirectional.__call__.<locals>.<listcomp>Q  s%         r   )r   standardize_argsr6   r!   listr/   r$   __call__r"   rZ   nestmap_structurer'   
state_specr(   constants_specr   is_keras_tensorflattenranger7   )r8   inputsra   ri   r:   additional_inputsadditional_specs
num_statesstate_specsrx   ry   tensor
full_inputfull_input_specoriginal_input_specoutputr<   s                   r   rt   zBidirectional.__call__
  s)    ,5+EM9d.A,
 ,
(y fd## 	6{{Q &qrr
AYF Y%6#577#F55f555 $]++JA~!! 1 "/1 1   '4F?#.'//GG K -88I*/8I,JD)-8q9J9J-KD*+ "+F;*  )  N 1?D-1?D.."%i..D040CD-151DD.!1GOO-..q1
 
 goo&788 	 	F&v../AA A   B  	6 $55J #C(?(?$@$@AA   !O '+F?#"&F; #'/-DO%UWW%j;;F;;F1DOM#577#F55f555r   c                 x   i }t          j        | j        j        d          r||d<   t          j        | j        j        d          r||d<   t          j        | j        j        d          r||d<   t          j        | j        j        d          rt	          |t
                    rt          |          dk    r|d         g}|d         g}t          |          | j        z
  dz  dz   }	||d|	         z  }| j        s|||	d         z  }n9|||	| j                  z  }||| j         d         z  }||| j         d         z  }d	\  }
}d|v rd|d<   n6|+||}}t          |          dz  }|d|         }
||d         }n	||}}d	\  }
} | j        |fd|
i|} | j	        |fd|i|}n | j        |fi |} | j	        |fi |}| j
        r%|dd         |dd         z   }|d         }|d         }| j        r/t          | j        d
d          rdnd}t          j        ||          }| j        dk    rt          j        ||g          }nZ| j        dk    r||z   }nI| j        dk    r	||z   dz  }n5| j        dk    r||z  }n$| j        ||g}nt#          d| j         d          | j
        r| j        ||z   S |g|z   S |S )zB`Bidirectional.call` implements the same API as the wrapped `RNN`.trainingmaskri   ra   rT   r   r   NNN
time_majorFr   r   r   r   z/Unrecognized value for `merge_mode`. Received: z3Expected values are ["concat", "sum", "ave", "mul"])r	   has_argr   callr!   rs   r/   r6   r'   r(   r2   r   r   r   reverser.   concatenater"   )r8   r|   r   r   ra   ri   r:   forward_inputsbackward_inputspivotforward_statebackward_statehalfyy_revstatestime_dimr   s                     r   r   zBidirectional.calla  s     *== 	*!)F: &99 	"!F6N +>> 	,"+F; /BB ,	:&$'' !;CKK!OO
 #))#)!9+Vt'::q@1D&5/1* F#veff~5OO $vet7J6J.J'KKO"fd.A-A-C-C&DDN#vt/B.B.D.D'EEO0:-~&((*.F;'*
 39&=))Q. -ete 4!.tuu!528&0:-~"" .;?E A (D' /=AG EE #"644V44A'D'99&99E 	qrrUU122Y&F!A!HE  	5T/uEEL1  OE844E?h&&(!U44FF_%%YFF_%%%i1_FF_%%YFF_$ZFFF!_F F F    	%&&8f$$r   c                 j    | j                                          | j                                         d S r>   )r'   reset_statesr(   r@   s    r   r   zBidirectional.reset_states  s2    '')))((*****r   c                 T   t          j        | j        j                  5  | j                            |           d d d            n# 1 swxY w Y   t          j        | j        j                  5  | j                            |           d d d            n# 1 swxY w Y   d| _        d S )NT)r   
name_scoper'   r+   buildr(   built)r8   r]   s     r   r   zBidirectional.build  s    2 788 	2 	2$$[111	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 3 899 	3 	3%%k222	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3


s#   AA
A
/BBBc                    t          |t                    r|d         }| j        r| j        s||g}n|}n| j        sd d gnd }| j        r>| j        j        }d |D             }t          |t                    r||dz  z   S |g|dz  z   S |S )Nr   c                     g | ]}d S r>   ro   rp   s     r   rm   z.Bidirectional.compute_mask.<locals>.<listcomp>  s    ///1$///r   r   )r!   rs   r   r.   r2   r'   r   )r8   r|   r   output_maskr   
state_masks         r   compute_maskzBidirectional.compute_mask  s    dD!! 	7D  	H? ##Tl".2oG4,,4K 	2'.F/////J+t,, 4"Z!^33=:>11r   c                     i }t          | j        d          r>|                    | j        j                   |                    | j        j                   |S )Nconstraints)hasattrr'   updater   r(   )r8   r   s     r   r   zBidirectional.constraints  sW    4%}55 	@t1=>>>t2>???r   c                 L   d| j         i}| j        r
| j        |d<   t          | d          r
| j        |d<   t	                                                      }t          t          |                                          t          |                                          z             S )Nr.   num_constantsr*   r(   )	r.   r6   r   r*   r$   rK   dictrs   items)r8   rP   base_configr<   s      r   rK   zBidirectional.get_config  s    0 	:&*&9F?#4122 	C'+'BF#$gg((**D**,,--V\\^^0D0DDEEEr   c                    t          j        |          }|                    dd          }ddlm}  ||d         |          |d<   |                    dd           }| |||          }||d<    | di |}||_        |S )Nr   r   )deserializer   rJ   r(   ro   )r\   deepcopypopkeras.layersr   r6   )clsrP   rG   r   deserialize_layerbackward_layer_configr(   r   s           r   rM   zBidirectional.from_config  s     v&&

?A66AAAAAA++7ON
 
 
w !'

+;T B B ,..%n  N (6F#$f,r   )r   NN)Fr   )NNNNr>   )rO   
__module____qualname____doc__r%   propertyr?   r-   r&   r   shape_type_conversionrW   rt   r   r   r   r   r   rK   classmethodrM   __classcell__)r<   s   @r   r   r   $   s       E ET H+ H+ H+ H+ H+ H+T < < X<  07 7 7 76 #  $#6U6 U6 U6 U6 U6 U6t ^ ^ ^ ^@+ + +    &   XF F F F F    [    r   r   )r   r\   tensorflow.compat.v2compatv2rZ   kerasr   keras.engine.base_layerr   keras.engine.input_specr   keras.layers.rnnr   keras.layers.rnn.base_wrapperr   keras.saving.legacyr   keras.utilsr	   r
   r    tensorflow.python.util.tf_exportr   r   ro   r   r   <module>r      s?   & %  ! ! ! ! ! ! ! ! !       ) ) ) ) ) ) - - - - - - & & & & & & 1 1 1 1 1 1 - - - - - - % % % % % % " " " " " "             : 9 9 9 9 9 *++a a a a aG a a ,+a a ar   