a
    SicTU                     @   s   d Z ddlZddlm  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 deZdS )zBidirectional wrapper for RNNs.    N)backend)Layer)	InputSpec)	rnn_utils)Wrapper)generic_utils)
tf_inspect)tf_utils)keras_exportzkeras.layers.Bidirectionalc                       s   e Zd ZdZd fdd	Zedd Zdd	 Zd ddZe	j
dd Zd! fdd	Zd"ddZdd Zdd Zdd Zedd Z fddZed#ddZ  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                    s^  t |tstd| |d ur8t |ts8td| |dvrPtd| dd| _t j|fi | d| _| || _|d u r| j|dd| _n|| _t	
|| _d	| jj | j_d
| jj | j_|   dd }|| j || j || _|r(t|}|d |d  | j_||d d  | j_|j| _|j| _|j| _d| _d| _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_backwardsZforward_Z	backward_c                 S   s   t | dd d ur| j| _d S )Nzero_output_for_mask)getattrreturn_sequencesr   )layer r   Z/var/www/html/django/DPS/env/lib/python3.9/site-packages/keras/layers/rnn/bidirectional.pyforce_zero_output_for_mask   s    z:Bidirectional.__init__.<locals>.force_zero_output_for_mask   r   )
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lenZinitial_weightsstatefulr   return_statesupports_masking
_trainable_num_constants
input_spec)selfr   r&   weightsr    kwargsr   nw	__class__r   r   r   l   s\    




zBidirectional.__init__c                 C   s   | j jS N)r   !_use_input_spec_as_call_signaturer.   r   r   r   r5      s    z/Bidirectional._use_input_spec_as_call_signaturec              	   C   sz   | j j| jjkr,td| j j d| jj d}|D ]@}t| j |}t| j|}||kr4td| d| d| dq4d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 = )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aZforward_valueZbackward_valuer   r   r   r%      s,    	z"Bidirectional._verify_layer_configFc                 C   s   |  }|r|d  |d< dt|jjjv ri }t|dd }|d urx|j||jj< t|dg }|D ]}|j||jj< qd|jj||dS |j|S d S )Nr   custom_objectscellcellsr9   )
get_configr   getfullargspecr3   from_configargsr   __name__)r.   r   r   configr9   r:   Zstacked_cellscr   r   r   r      s$    z)Bidirectional._recreate_layer_from_configc                 C   s   | j |}| jr<tj|dd  dd}tj|d dd}ntj|dd}| jdkrx| }|d  d9  < t|}n| jd u r|t		|g}| jr| jd u r|| t		| S |g| t		| S |S )N   F)	to_tuplesr   r   r   )
r   compute_output_shaper)   r	   convert_shapesr&   as_listtfTensorShapecopy)r.   input_shapeoutput_shapestate_shaper   r   r   rG      s,    


z"Bidirectional.compute_output_shapec                    s  t |||| j\}}}t|trBt|dkr:|dd }|d }|du rf|du rft j|fi |S g }g }|durt|}|d dkrtd| ||d< ||7 }t	j
dd |}|d|d  | j_||d d | j_||7 }|durH||d	< ||7 }d
d |D }	|	| j_|	| j_||	7 }t|| _| j| j_| j| j_tt	j
|d }
t	j
|D ]}t||
krjtdqj|
r|g| }dd ttt	j
|D | }d|d< d|d	< | j}|| _t j|fi |}|| _|S t j|fi |S dS )zN`Bidirectional.__call__` implements the same API as the wrapped
        `RNN`.rD   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                 S   s   t t| dS )Nshaper   r   	int_shape)stater   r   r   <lambda>(      z(Bidirectional.__call__.<locals>.<lambda>	constantsc                 S   s   g | ]}t t|d qS )rQ   rS   ).0constantr   r   r   
<listcomp>1  s   z*Bidirectional.__call__.<locals>.<listcomp>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                 S   s   g | ]}d qS r4   r   rY   _r   r   r   r[   O  s   )r   standardize_argsr,   r   listr'   r   __call__r   rJ   nestmap_structurer   
state_specr    constants_specr   is_keras_tensorflattenranger-   )r.   inputsrP   rX   r0   additional_inputsadditional_specs
num_statesZstate_specsrd   re   tensor
full_inputfull_input_specZoriginal_input_specoutputr2   r   r   r`     s~    







zBidirectional.__call__c                 C   s  i }t | jjdr||d< t | jjdr4||d< t | jjdrL||d< t | jjdrt|tr"t|dkr"|d g}|d g}t|| j d d }	||d|	 7 }| js|||	d 7 }n<|||	| j  7 }||| j d 7 }||| j d 7 }d	\}
}d|v rnd|d< nL|dur\|| }}t|d }|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  }|d }|d }| jrt| jd
drdnd}t||}| jdkr8t||g}nn| jdkrN|| }nX| jdkrh|| d }n>| jdkr~|| }n(| jdu r||g}ntd| j d| j
r| jdu r|| S |g| S |S )zB`Bidirectional.call` implements the same API as the wrapped `RNN`.trainingmaskrX   rP   rD   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   r_   r'   r,   r   r    r)   r   r   r   reverser&   concatenater   )r.   rh   rp   rq   rP   rX   r0   forward_inputsZbackward_inputspivotZforward_stateZbackward_statehalfyZy_revstatesZtime_dimro   r   r   r   rt   _  s    	










zBidirectional.callc                 C   s   | j   | j  d S r4   )r   reset_statesr    r6   r   r   r   r|     s    
zBidirectional.reset_statesc                 C   s~   t | jj | j| W d    n1 s00    Y  t | jj | j| W d    n1 sj0    Y  d| _d S )NT)r   
name_scoper   r#   buildr    built)r.   rM   r   r   r   r~     s
    **zBidirectional.buildc                 C   s   t |tr|d }| jr.| js(||g}q@|}n| js<d d gnd }| jr| jj}dd |D }t |trr||d  S |g|d  S |S )Nr   c                 S   s   g | ]}d qS r4   r   r\   r   r   r   r[     rW   z.Bidirectional.compute_mask.<locals>.<listcomp>r   )r   r_   r   r&   r)   r   r{   )r.   rh   rq   output_maskr{   
state_maskr   r   r   compute_mask  s    


zBidirectional.compute_maskc                 C   s0   i }t | jdr,|| jj || jj |S )Nconstraints)hasattrr   updater   r    )r.   r   r   r   r   r     s
    zBidirectional.constraintsc                    sT   d| j i}| jr| j|d< t| dr.| j|d< t  }tt| t|  S )Nr&   num_constantsr"   r    )	r&   r,   r   r"   r   r=   dictr_   items)r.   rB   base_configr2   r   r   r=     s    




zBidirectional.get_configc                 C   sv   t |}|dd}ddlm} ||d |d|d< |dd }|d ur^|||d}||d< | f i |}||_|S )Nr   r   )deserializer   r<   r    )rL   deepcopypopkeras.layersr   r,   )clsrB   r9   r   deserialize_layerZbackward_layer_configr    r   r   r   r   r?     s    

zBidirectional.from_config)r   NN)F)NN)NNNN)N)rA   
__module____qualname____doc__r   propertyr5   r%   r   r	   shape_type_conversionrG   r`   rt   r|   r~   r   r   r=   classmethodr?   __classcell__r   r   r2   r   r   #   s2   J   I


Z    
`

r   )r   rL   tensorflow.compat.v2compatv2rJ   kerasr   keras.engine.base_layerr   keras.engine.input_specr   keras.layers.rnnr   keras.layers.rnn.base_wrapperr   keras.utilsr   r   r	    tensorflow.python.util.tf_exportr
   r   r   r   r   r   <module>   s   