o
    2h3                     @   s`   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	 d	eZ
dS )
    N)ops)utils)keras_export)Layer)serialization_libzkeras.layers.Bidirectionalc                       s   e Zd ZdZ			d fdd	Zdd Zddd	Z			dd
dZdd Zdd Z	e
dd ZdddZdd Z fddZedddZ  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           	         sf  t |tstd| |d urt |tstd| |dvr(td| dt jdi | t|}dt|j	d |d d< t
|| _|d u rlt|}d	|d d
< dt|j	d |d d< t
|| _n|| _|   dd }|| j || j || _|rt|}|d |d  | j_||d 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                 S   s    t | dd d ur| j| _d S d S )Nzero_output_for_mask)getattrreturn_sequencesr   )layer r   ]/var/www/html/chatgem/venv/lib/python3.10/site-packages/keras/src/layers/rnn/bidirectional.pyforce_zero_output_for_mask   s   z:Bidirectional.__init__.<locals>.force_zero_output_for_mask   r   )
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__r   r   r   S   s\   





zBidirectional.__init__c              	   C   sz   | j j| jjkrtd| j j d| jj d}|D ] }t| j |}t| j|}||kr:td| d| d| dqd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_valuer   r   r   r"      s0   	z"Bidirectional._verify_layer_configc                 C   s   | j |}| jr|d |dd  }}| jdkr*t|}|d  d9  < t|}n	| jd u r3||g}| jrL| jd u rCt|| | S t|g| | S t|S )Nr      r   r   )r    compute_output_shaper'   r#   listtuple)r*   sequences_shapeinitial_state_shapeoutput_shapestate_shaper   r   r   r6      s   



z"Bidirectional.compute_output_shapec                 C   s  i }| j jr
||d< | j jr||d< |d ur.||}}t|d }|d | }	||d  }
n	||}}d\}	}
| j |fd|	i|}| j|fd|
i|}| jrft|dd  |dd   }|d }|d }t|| j	}t|| j	}| j
r~tj|dd}| jd	krtj||gd
d}n3| jdkr|| }n)| jdkr|| d }n| jdkr|| }n| jd u r||f}n	td| j d| jr| jd u r|| S |f| S |S )Ntrainingmaskr   NNinitial_stater4   r   )axisr   r5   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'   r8   r   castcompute_dtyper   flipr#   concatenater   )r*   	sequencesr@   r>   r=   r,   forward_inputsbackward_inputshalfforward_statebackward_stateyy_revstatesoutputr   r   r   call   sl   











zBidirectional.callc                 C   s   |    d S N)reset_stater*   r   r   r   reset_states  s   zBidirectional.reset_statesc                 C   s&   | j std| j  | j  d S )NzLayer must be stateful.)r&   AttributeErrorr    rT   r!   rU   r   r   r   rT     s   
zBidirectional.reset_statec                 C   s(   | j jr| jjrt| j j| jj S d S rS   )r    rP   r!   r8   rU   r   r   r   rP     s   zBidirectional.statesc                 C   s0   | j js
| j | | jjs| j| d S d S rS   )r    builtbuildr!   )r*   r9   r:   r   r   r   rY     s
   zBidirectional.buildc                 C   s   t |tr	|d }| jr| js||f}n
|}n| jsdnd }| jr@| jd ur@dd | jD }t |tr9||d  S |f|d  S |S )Nr   r?   c                 s   s    | ]}d V  qd S rS   r   ).0_r   r   r   	<genexpr>#  s    z-Bidirectional.compute_mask.<locals>.<genexpr>r   )r   r7   r   r#   r'   rP   )r*   r[   r>   output_mask
state_maskr   r   r   compute_mask  s   


zBidirectional.compute_maskc                    s@   d| j i}t| j|d< t| j|d< t  }i ||S )Nr#   r   r!   )r#   r   r   r    r!   r   
get_config)r*   r   base_configr.   r   r   r`   )  s   

zBidirectional.get_configc                 C   s\   t |}tj|d |d|d< |dd }|d ur%tj||d}||d< | di |}|S )Nr   )custom_objectsr!   r   )copydeepcopyr   r   pop)clsr   rb   backward_layer_configr!   r   r   r   r   from_config4  s   

zBidirectional.from_config)r   NNrS   )NNN)__name__
__module____qualname____doc__r   r"   r6   rR   rV   rT   propertyrP   rY   r_   r`   classmethodrh   __classcell__r   r   r.   r   r   
   s*    JB

A

r   )rc   	keras.srcr   r   keras.src.api_exportr   keras.src.layers.layerr   keras.src.savingr   r   r   r   r   r   <module>   s    