o
    Ne~p                    @   sH  d Z ddlmZ ddlZddlZddlZddlZ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mZmZ dd	lmZmZmZmZ dd
lmZ ddlmZ ddlmZmZ ddlm Z m!Z! ddlZddl	m"Z"m#Z# g dZ$			dLddZ%					dMddZ&				dNddZ'dd Z(						dOdd Z)	!		"		dPd#d$Z*			dQd%d&Z+	'		(		!	dRd)d*Z,						dSd+d,Z-dTd-d.Z.dUd/d0Z/dUd1d2Z0		!		3			dVd4d5Z1dWd7d8Z2						6	6dXd9d:Z3		dYd;d<Z4dTd=d>Z5dZd@dAZ6dTdBdCZ7	d[dDdEZ8	F	G						d\dHdIZ9		d]dJdKZ:dS )^z4
Contrib layers just related to the neural network.
    )print_functionN)LayerHelper)utils   )unique_name)NormalConstantNumpyArrayInitializer)check_variable_and_dtype
check_typecheck_dtypeconvert_dtype)core)	ParamAttr)Variableconvert_np_dtype_to_dtype_)slicereshape)_C_ops_legacy_C_ops)fused_elemwise_activationsequence_topk_avg_poolingvar_conv_2dmatch_matrix_tensor	tree_convfused_embedding_seq_poolmulticlass_nms2search_pyramid_hashshuffle_batchpartial_concatsparse_embeddingpartial_sum	tdm_childrank_attentiontdm_samplerbatch_fc_pull_box_extended_sparsebilateral_slicecorrelationfused_bn_add_actfused_seqpool_cvm        Tc           	   	   C   s   t |tr
|d}t |trt|dkrtdtdi t }|j| j	d}|j| j	d}|j
d| |d||d||||dd	 |S )a<  
    **Fused elementwise_add/mul and activation layers**

    This function computes an elementwise_add/mul cooperated with an activation.

    .. math::

        out = Unary(Binary(x, y))

    or

    .. math::

        out = Binary(x, Unary(y))

    Unary operators can be: `scale`, `relu`, `tanh`. Binary operators can be:
    `elementwise_add`, `elementwise_mul`.

    Args:
        x (Variable): left operation of the binary operator.
        y (Variable): right operator of the binary operator.
        functor_list (list of str): types of operator which will be executed
            by this layer. For example, ['elementwise_add', 'relu']
            (out = elementwise_add(x, relu(y))),
            or ['relu', 'elemmentwise_add'] (out = relu(elementwise_add(x, y))).
        axis (int32, default -1): axis of elementwise op.
        scale (float32, default 0): parameter of scale op.
        save_intermediate_out (bool, default True): whether to save the
            intermediate result, Unary(y) or Binary(x, y).

    Returns:
        Variable: The computation result.
    ,   zAfunctor_list should be a list of str, and the length should be 2.r   dtype)XY)OutZIntermediateOut)axisscalesave_intermediate_outfunctor_listtypeinputsoutputsattrsN)r   )
isinstancestrsplitlistlen
ValueErrorr   locals"create_variable_for_type_inferencer0   	append_op)	xyr7   r4   r5   r6   helperoutZintermediate_out rJ   ND:\Projects\ConvertPro\env\Lib\site-packages\paddle/fluid/contrib/layers/nn.pyr   3   s.   
'
r      float32c                 C   s   t di t }t| j}t|dksJ t|dd}t|dd}t|t||d  |d  g}|j|j	||	d}|
|	}|j
|	dd	}|jd| |||d
||d|||d |d |d |d dd ||S )aL  
    The var_conv_2d layer calculates the output base on the :attr:`input` with variable length,
    row, col, input channel, filter size and strides. Both :attr:`input`, :attr:`row`,
    and :attr:`col` are 1-level LodTensor. The convolution operation is same as conv2d layer with
    padding. Besides, input.dims[1] should be 1.

    .. code-block:: text

            If input_channel is 2 and given row lodTensor and col lodTensor as follows:
                row.lod = [[5, 4]]
                col.lod = [[6, 7]]
            input is a lodTensor:
                input.lod = [[60, 56]]	# where 60 = input_channel * 5 * 6
                input.dims = [116, 1]	# where 116 = 60 + 56

            If set output_channel is 3, filter_size is [3, 3], stride is [1, 1]:
                # where 90 = output_channel * [(5-1)/stride + 1] * [(6-1)/stride + 1]
                output.lod = [[90, 84]]
                output.dims = [174, 1]  # where 174 = 90 + 84

    Args:
        input (Variable): The input should be 1-level LodTensor with dims[1] equals 1.
        row (Variable): The row should be 1-level LodTensor to provide height information.
        col (Variable): The col should be 1-level LodTensor to provide width information.
        input_channel (int): The number of input channel.
        output_channel (int): The number of output channel.
        filter_size (int|tuple|None): The filter size. If filter_size is a tuple,
            it must contain two integers, (filter_size_H, filter_size_W).
            Otherwise, the filter will be a square.
        stride (int|tuple): The stride size. If stride is a tuple, it must
            contain two integers, (stride_H, stride_W). Otherwise, the
            stride_H = stride_W = stride. Default: stride = 1.
        param_attr (ParamAttr|None): The parameter attribute for learnable parameters/weights
            of var_conv2d. If it is set to None or one attribute of ParamAttr, var_conv2d
            will create ParamAttr as param_attr. If the Initializer of the param_attr
            is not set, the parameter is initialized with :math:`Normal(0.0, std)`,
            and the :math:`std` is :math:`(\\frac{2.0 }{filter\_elem\_num})^{
  0.5}`. Default: None.
        act (str): Activation type, if it is set to None, activation is not appended.
            Default: None
        dtype ('float32'): The data type of parameter and output.
        name (str|None): A name for this layer(optional). If set None, the layer
            will be named automatically. Default: None

    Returns:
        Variable: Output variable with LoD specified by this layer.

    Examples:
        .. code-block:: python

            import numpy as np
            from paddle.fluid import layers
            from paddle.fluid import contrib

            x_lod_tensor = layers.data(name='x', shape=[1], lod_level=1)
            row_lod_tensor = layers.data(name='row', shape=[6], lod_level=1)
            col_lod_tensor = layers.data(name='col', shape=[6], lod_level=1)
            out = contrib.var_conv_2d(input=x_lod_tensor,
                                     row=row_lod_tensor,
                                     col=col_lod_tensor,
                                     input_channel=3,
                                     output_channel=5,
                                     filter_size=[3, 3],
                                     stride=1)
    r   r.   filter_sizestrider   rL   attrshaper0   Tstop_gradient)r1   ROWCOLUMNW)r3   ZCol)ZInputChannelZOutputChannelZStrideHZStrideWZKernelHZKernelWr8   N)r   )r   rC   r@   rR   rA   r   Zconvert_to_listintcreate_parameter
param_attrrD   rE   append_activation)inputrowcolZinput_channelZoutput_channelrN   rO   rZ   actr0   namerH   x_shapeZfilter_shapeZfilter_paramZconv_restmp_resrJ   rJ   rK   r   v   sF   L


r   c                 C   s   t di t }t| j}t|j}	t|dkr&t|	dkr&|d |	d ks(J |d ||	d g}
|j|j|
|dd}||}|j|dd}|jd| ||d||d	d
|id |	||fS )aw
  
    Calculate the semantic matching matrix of two word sequences with variable length.
    Given a query A of length `n` and a title B of length `m`, the input shape are respectively
    [n, h] and [m, h], which h is hidden_size. If :attr:`channel_num` is set to 3,
    it will generate a learnable parameter matrix W with shape [h, 3, h].
    Then the semantic matching matrix of query A and title B is calculated by
    A * W * B.T = [n, h]*[h, 3, h]*[h, m] = [n, 3, m]. The learnable parameter matrix `W`
    is equivalent to a fully connected layer in the calculation process. If :attr:`act` is provided,
    the corresponding activation function will be applied to output matrix.
    The :attr:`x` and :attr:`y` should be LodTensor and only one level LoD is supported.

    .. code-block:: text

            Given a 1-level LoDTensor x:
                x.lod =  [
                    [2,                     3,                               ]]
                x.data = [[0.3, 0.1], [0.2, 0.3], [
                    0.5, 0.6], [0.7, 0.1], [0.3, 0.4]]
                x.dims = [5, 2]
            y is a Tensor:
                y.lod =  [[3,                                 1,       ]]
                y.data = [[0.1, 0.2], [0.3, 0.7], [0.9, 0.2], [0.4, 0.1]]
                y.dims = [4, 2]
            set channel_num 2, then we get a 1-level LoDTensor:
                # where 12 = channel_num * x.lod[0][0] * y.lod[0][0]
                out.lod =  [[12, 6]]
                out.dims = [18, 1]     # where 18 = 12 + 6

    Args:
        x (Variable): Input variable x which should be 1-level LodTensor.
        y (Variable): Input variable y which should be 1-level LodTensor.
        channel_num (int): The channel number of learnable parameter W.
        act (str, default None): Activation to be applied to the output of this layer.
        param_attr (ParamAttr|list of ParamAttr, default None): The parameter attribute for learnable
            parameters/weights of this layer.
        dtype ('float32'): The data type of w data.
        name (str|None): A name for this layer(optional). If set None, the layer will be named automatically. Default: None

    Returns:
        Variable: output with LoD specified by this layer.

    Examples:
        .. code-block:: python

            import numpy as np
            from paddle.fluid import layers
            from paddle.fluid import contrib

            x_lod_tensor = layers.data(name='x', shape=[10], lod_level=1)
            y_lod_tensor = layers.data(name='y', shape=[10], lod_level=1)
            out, out_tmp = contrib.match_matrix_tensor(
                x=x_lod_tensor, y=y_lod_tensor, channel_num=3)
    r   r.   r+   FrQ   rR   r0   is_biasTrS   )r1   r2   rW   )r3   ZTmpZdim_tr8   N)r   )
r   rC   r@   rR   rA   rY   rZ   rD   rE   r[   )rF   rG   channel_numr_   rZ   r0   r`   rH   ra   Zy_shapeZweight_shapewZmm_resrb   rJ   rJ   rK   r      s<   <


r   c                 C   s\   t d
i t }|j| d}|j| dd}|jd| ||d||d||dd |S )aH	  
    The :attr:`topks` is a list with incremental values in this function. For each topk,
    it will average the topk features as an output feature for each channel of every
    input sequence. Both :attr:`row` and :attr:`col` are LodTensor, which provide height
    and width information for :attr:`input` tensor. If feature size of input sequence is less
    than topk, it will padding 0 at the back.

    .. code-block:: text

            If channel_num is 2 and given row LoDTensor and col LoDTensor as follows:
                row.lod = [[5, 4]]
                col.lod = [[6, 7]]

            input is a LoDTensor with input.lod[0][i] = channel_num * row.lod[0][i] * col.lod[0][i]
                input.lod = [[60, 56]]  # where 60 = channel_num * 5 * 6
                input.dims = [116, 1]   # where 116 = 60 + 56

            If topks is [1, 3, 5], then we get a 1-level LoDTensor:
                out.lod =  [[5, 4]] 	# share Lod info with row LodTensor
                out.dims = [9, 6]   	# where 6 = len(topks) * channel_num

    Args:
        input (Variable): The input should be 2D LodTensor with dims[1] equals 1.
        row (Variable): The row should be 1-level LodTensor to provide the height information
                        of the input tensor data.
        col (Variable): The col should be 1-level LodTensor to provide the width information
                        of the input tensor data.
        topks (list): A list of incremental value to average the topk feature.
        channel_num (int): The number of input channel.

    Returns:
        Variable: output LodTensor specified by this layer.

    Examples:

        .. code-block:: python

            import numpy as np
            from paddle.fluid import layers
            from paddle.fluid import contrib

            x_lod_tensor = layers.data(name='x', shape=[1], lod_level=1)
            row_lod_tensor = layers.data(name='row', shape=[6], lod_level=1)
            col_lod_tensor = layers.data(name='col', shape=[6], lod_level=1)
            out = contrib.sequence_topk_avg_pooling(input=x_lod_tensor,
                                                   row=row_lod_tensor,
                                                   col=col_lod_tensor,
                                                   topks=[1, 3, 5],
                                                   channel_num=5)
    r   r/   Tr0   rT   )r1   rU   rV   )r3   pos)topksre   r8   N)r   )r   rC   rD   input_dtyperE   )r\   r]   r^   ri   re   rH   rI   rh   rJ   rJ   rK   r   H  s$   3
r   r.   tanhc	                 C   s   t | dtd t |dtd tdi t }	|	d}
| jd }|d||g}|	j|||
dd}|	j|
d}|	jd| ||d	d
|id|id |	j	rO|	
|}n|}|	|S )a!  
    ${comment}
Args : nodes_vector(${nodes_vector_type}) : $ { nodes_vector_comment }
edge_set(${edge_set_type}) : $ { edge_set_comment }
        output_size(int): output feature width
        num_filters(int): number of filters, Default 1
        max_depth(int): max depth of filters, Default 2
        act(str): activation function, Default tanh
        param_attr(ParamAttr): the parameter attribute for the filters, Default None
        bias_attr(ParamAttr): the parameter attribute for the bias of this layer, Default None
        name(str): a name of this layer(optional). If set None, the layer will be named automatically, Default None

    Returns:
        out(${out_type}): ${
          out_comment
        }

    Examples:
        .. code-block:: python

          import paddle.fluid as fluid

          # 10 for max_node_size of dataset, 5 for vector width
          nodes_vector = fluid.layers.data(
              name='vectors', shape=[10, 5], dtype='float32')
          # 10 for max_node_size of dataset, 2 for every edge has two nodes
          # edges must be directional
          edge_set = fluid.layers.data(name='edge_set', shape=[
                                       10, 2], dtype='float32')
          # the shape of output will be [10, 6, 1],
          # 10 for max_node_size of dataset, 6 for output size, 1 for 1 filter
          out_vector = fluid.layers.tree_conv(nodes_vector, edge_set, 6, 1, 2)
#After reshape, output tensor could be nodes_vector for next tree convolution
          out_vector = fluid.layers.reshape(out_vector, shape=[-1, 10, 6])
          out_vector_2 = fluid.layers.tree_conv(out_vector, edge_set, 3, 4, 2)
#also output tensor could be pooling(the pooling in paper called global pooling)
          pooled = fluid.layers.reduce_max(out_vector, dim=2) # global pooling
    nodes_vectorr   edge_setr.   r   Frc   r/   )ZNodesVectorZEdgeSetFilterr3   	max_depthr8   N)r   )r   r   r   rC   rj   rR   rY   rD   rE   	bias_attrZappend_bias_opr[   )rl   rm   Zoutput_sizeZnum_filtersro   r_   rZ   rp   r`   rH   r0   Zfeature_sizeZW_shaperW   rI   Zpre_activationrJ   rJ   rK   r     s2   /



r   Fsumc           
      C   sz   t di t }|j|j||dd}||}	|du rdn|dkr#|n|d | }|jd| |dd|	i|||d	d
 |	S )a  
    **Embedding Sequence pool**

    This layer is the fusion of lookup table and sequence_pool.

    Args:
        input (Variable): Input is a Tensor<int64> Variable, which contains the IDs' information.
            The value of the input IDs should satisfy :math:`0<= id < size[0]`.
        size (tuple|list): The shape of the lookup_table parameter. It should
            have two elements which indicate the size of the dictionary of
            embedding and the size of each embedding vector respectively.
        is_sparse (bool): The flag indicating whether to use sparse update.
            Default: False.
        padding_idx (int|long|None): It will output all-zero padding data whenever
            lookup encounters :math:`padding\_idx` in Ids. If set :attr:`None`, it makes
            no effect to output. If :math:`padding\_idx < 0`, the :math:`padding\_idx`
            will automatically be converted to :math:`size[0] + padding\_idx` to use.
            Default: None.
        combiner (str): The pooling type of sequence_pool, and only support `sum`.
            Default: sum.
        param_attr (ParamAttr): Parameters for this layer.
        dtype (np.dtype|core.VarDesc.VarType|str): The dtype refers to the data type of output
            tensor. It can be float32, float_16, int etc.
    Returns:
        The sequence pooling variable which is a Tensor.
    Examples:
        .. code-block:: python
            import numpy as np
            import paddle.fluid as fluid

            dict_size = 20
            data_t = fluid.layers.data(
                name='word', shape=[1], dtype='int64', lod_level=1)
            padding_idx = np.random.randint(1, 10)
            out = fluid.contrib.fused_embedding_seq_pool(
                input=data_t,
                size=[dict_size, 32],
                param_attr='w',
                padding_idx=padding_idx,
                is_sparse=False)
    r   Frc   Nr+   r   IdsrW   r3   )	is_sparsecombinerpadding_idxr8   )r   )r   rC   rY   rZ   rD   rE   )
r\   sizert   rv   ru   rZ   r0   rH   rf   rI   rJ   rJ   rK   r     s*   0

r   c           	   	      s   t di t | dkrtd| t| dtd t| tr-| D ]
}t|ddgd q"  	 } fddt
t|D }jd||dd	|i| |||d
d |S )aw  
    :api_attr: Static Graph

    This OP is the fusion of sequence_pool and continuous_value_model op.

    **Note:** The Op only receives List of LoDTensor as input, only support SUM pooling now.

    Args:
        input(Variable|list of Variable): Input is List of LoDTensor.
        pool_type(str): pooling type, only support SUM pooling now.
        cvm(Variable): cvm Variable.
        pad_value(float, optional): padding value of sequence pool. Default: 0.0.
        use_cvm(bool, optional): use cvm or not. Default: True.
        cvm_offset(int, optional): cvm offset. Default: 2, which means cvm contains show, click.

    Returns:
        Variable|list of Variable: The tensor variable storing sequence pool and cvm
        of input.

    Examples:
        .. code-block:: python

            import paddle
            import paddle.fluid as fluid
            paddle.enable_static()

            data = paddle.static.data(name='x', shape=[-1, 1], dtype='int64', lod_level=1)
            data2 = paddle.static.data(name='y', shape=[-1, 1], dtype='int64', lod_level=1)
            inputs = [data, data2]
            embs = fluid.layers.nn._pull_box_sparse(input=inputs, size=11, is_distributed=True, is_sparse=True)

            label = paddle.static.data(name="label", shape=[-1, 1], dtype="int64", lod_level=1)
            ones = fluid.layers.fill_constant_batch_size_like(input=label, shape=[-1, 1], dtype="int64", value=1)
            show_clk = paddle.cast(paddle.concat([ones, label], axis=1), dtype='float32')
            show_clk.stop_gradient = True

            cvms = fluid.contrib.layers.fused_seqpool_cvm(embs, 'sum', show_clk)


    r*   ZSUMzBfused_seqpool_cvm only support SUM pooling now, and your type is: r\   rM   c                       g | ]}  qS rJ   rD   .0ir0   rH   rJ   rK   
<listcomp>`      z%fused_seqpool_cvm.<locals>.<listcomp>)r1   ZCVMr3   )Zpooltype	pad_valueuse_cvm
cvm_offsetr8   N)r*   )r   rC   upperrB   r   r@   r=   r
   rj   multiple_inputrangerA   rE   )	r\   Z	pool_typeZcvmr   r   r   _inputr:   outsrJ   r}   rK   r*   #  s<   .


r*   333333?      ?c                 C   st   t d
i t }|j| jd}|jdd}|jd| |d|||||||d||dd d|_d|_|	r8||fS |S )a  
    **Multiclass NMS2**

    This operator is to do multi-class non maximum suppression (NMS) on
    boxes and scores.
    In the NMS step, this operator greedily selects a subset of detection bounding
    boxes that have high scores larger than score_threshold, if providing this
    threshold, then selects the largest nms_top_k confidences scores if nms_top_k
    is larger than -1. Then this operator pruns away boxes that have high IOU
    (intersection over union) overlap with already selected boxes by adaptive
    threshold NMS based on parameters of nms_threshold and nms_eta.
    Aftern NMS step, at most keep_top_k number of total bboxes are to be kept
    per image if keep_top_k is larger than -1.

    Args:
        bboxes (Variable): Two types of bboxes are supported:
                           1. (Tensor) A 3-D Tensor with shape
                           [N, M, 4 or 8 16 24 32] represents the
                           predicted locations of M bounding bboxes,
                           N is the batch size. Each bounding box has four
                           coordinate values and the layout is
                           [xmin, ymin, xmax, ymax], when box size equals to 4.
                           2. (LoDTensor) A 3-D Tensor with shape [M, C, 4]
                           M is the number of bounding boxes, C is the
                           class number
        scores (Variable): Two types of scores are supported:
                           1. (Tensor) A 3-D Tensor with shape [N, C, M]
                           represents the predicted confidence predictions.
                           N is the batch size, C is the class number, M is
                           number of bounding boxes. For each category there
                           are total M scores which corresponding M bounding
                           boxes. Please note, M is equal to the 2nd dimension
                           of BBoxes.
                           2. (LoDTensor) A 2-D LoDTensor with shape [M, C].
                           M is the number of bbox, C is the class number.
                           In this case, input BBoxes should be the second
                           case with shape [M, C, 4].
        background_label (int): The index of background label, the background
                                label will be ignored. If set to -1, then all
                                categories will be considered. Default: 0
        score_threshold (float): Threshold to filter out bounding boxes with
                                 low confidence score. If not provided,
                                 consider all boxes.
        nms_top_k (int): Maximum number of detections to be kept according to
                         the confidences after the filtering detections based
                         on score_threshold.
        nms_threshold (float): The threshold to be used in NMS. Default: 0.3
        nms_eta (float): The threshold to be used in NMS. Default: 1.0
        keep_top_k (int): Number of total bboxes to be kept per image after NMS
                          step. -1 means keeping all bboxes after NMS step.
        normalized (bool): Whether detections are normalized. Default: True
        return_index(bool): Whether return selected index. Default: False
        name(str): Name of the multiclass nms op. Default: None.

    Returns:
        A tuple with two Variables: (Out, Index) if return_index is True,
        otherwise, a tuple with one Variable(Out) is returned.
        Out: A 2-D LoDTensor with shape [No, 6] represents the detections.
        Each row has 6 values: [label, confidence, xmin, ymin, xmax, ymax]
        or A 2-D LoDTensor with shape [No, 10] represents the detections.
        Each row has 10 values: [label, confidence, x1, y1, x2, y2, x3, y3,
        x4, y4]. No is the total number of detections.
        If all images have not detected results, all elements in LoD will be
        0, and output tensor is empty (None).
        Index: Only return when return_index is True. A 2-D LoDTensor with
        shape [No, 1] represents the selected index which type is Integer.
        The index is the absolute value cross batches. No is the same number
        as Out. If the index is used to gather other attribute such as age,
        one needs to reshape the input(N, M, 1) to (N * M, 1) as first, where
        N is the batch size and M is the number of boxes.


    Examples:
        .. code-block:: python


            import paddle.fluid as fluid
            boxes = fluid.layers.data(name='bboxes', shape=[81, 4],
                                      dtype='float32', lod_level=1)
            scores = fluid.layers.data(name='scores', shape=[81],
                                      dtype='float32', lod_level=1)
            out, index = fluid.layers.multiclass_nms2(bboxes=boxes,
                                              scores=scores,
                                              background_label=0,
                                              score_threshold=0.5,
                                              nms_top_k=400,
                                              nms_threshold=0.3,
                                              keep_top_k=200,
                                              normalized=False,
                                              return_index=True)
    r   r/   rX   )ZBBoxesZScores)background_labelscore_threshold	nms_top_knms_threshold
keep_top_knms_eta
normalized)r3   Indexr9   r:   r<   r;   TN)r   )r   rC   rD   r0   rE   rT   )ZbboxesZscoresr   r   r   r   r   r   r   Zreturn_indexr`   rH   outputindexrJ   rJ   rK   r   u  s0   f
r   c                  C   sh  t di t }|| dg}|j|||dd}d|_| |d}|dkr7|dg}|j|||dd}d|_||d< |	dkrO|	dg}|j|||dd}d|_||d	< d
}|rt|tsZJ g }|rd||j |rl||j |rt||j |D ]}||vrtd	|qvd
|}||}||}||}|jd||||d|||||||||	|
||dd |S )aO  
    **Pyramid hash embedding**

    Args:
        input (Variable): LoDTensor<int32> Variable contained the IDs' information.
        num_emb (int): The embedding size of output.
        space_len (int): The length of pyramid hash embedding space.
        pyramid_layer (int): The number of pyramid layers. It should be greater than 2.
        rand_len (int): The minimum length of pyramid hash cell.
        drop_out_percent (float): The probability of dropping out the input token randomly.
            It should satisfy: [0., 1.]
        is_training (bool): Whether in training or testing phrase.
        use_filter(bool): If set True, the white filter and black filter should be given by
            :attr:`param_attr_wl` and :attr:`param_attr_bl` .
        white_list_len(int): If set :math:`white_list_len>0` , white filter with shape [white_list_len, 1]
            should be provided by param_attr_wl.
        black_list_len(int): If set :math:`black_list_len>0` , black filter with shape [black_list_len, 1]
            should be provided by param_attr_bl.
        seed(int): The number of random seed.
        lr(float): The learning rate of weight created by :attr:`param_attr` with shape [space_len+rand_len, 1]
            in this layer.
        param_attr(ParamAttr): To specify the weight parameter property. Default: None, which means the
            default weight parameter property is used. See usage for details in :ref:`api_fluid_ParamAttr` .
        param_attr_wl(ParamAttr): Specified parameters of white filter.
        param_attr_bl(ParamAttr): Specified parameters of black filter.
        distribute_update_vars(list[ParamAttr.name]): Decided which params should be updated in distribute training.
            Used in Distribute Transpiler to create a trainer/server program.
        name(str, optional): The default value is None.  Normally there is no need for user to set this property.
            For more information, please refer to :ref:`api_guide_Name` .
        dtype(str): The data type of output variable, float32.
    Returns:
        Variable: LoDTensor of pyramid hash embedding.
    r   rL   Frc   T)r1   rW   r   Z	WhiteListZ	BlackList z+Pyramid Hash layer didn't have parameter {}r-   Zpyramid_hash)r3   Z
X_Temp_OutZDropPos)num_emb	space_lenpyramid_layerrand_lendrop_out_percentis_training
use_filterwhite_list_lenblack_list_lenseedlrdistribute_update_varsr8   N)r   )r   rC   rY   rT   r=   r@   appendr`   rB   formatjoinrD   rE   ) r\   r   r   r   r   r   r   r   r   r   r   r   rZ   Zparam_attr_wlZparam_attr_blr`   r   r0   rH   Zw_shaperf   Z
input_varsZwl_shapeZ
white_listZbl_shapeZ
black_listZdistribute_update_vars_strZspecial_name_listparamresZdrop_posZ
x_temp_outrJ   rJ   rK   r     s   3




r   c                 C   s   t di t }|j| jd}|jtjd}|du r$|jjdkr$|jj}|du r/tj	dd}i }t
|trE||d< |jtdd	d
d}|jd| |d|||d|d |S )a  
    This layer shuffle input tensor :attr:`x` . Normally, :attr:`x` is 2-D LoDTensor.

    :attr:`x` is a LoDTensor to be shuffled with shape :math:`[N_1, N_2, ..., N_k, D]` . Note that the last dim of input will not be shuffled.
    :math:`N_1 * N_2 * ... * N_k` numbers of elements with length :math:`D` will be shuffled randomly.

    For Example:

    .. code-block:: text

      Input:
        x.data = [[1, 2], [3, 4], [5, 6], [7, 8]]
        x.dims = [4, 2]

      Attrs:
        seed = 2019

      Output:
        Out.data =[[7, 8], [1, 2], [3, 4], [5, 6]]
        Out.dims = [4, 2]

    Args:
        x (Variable): The input variable. The input variable is a N-D LoDTensor with type int, float32 or float64.
        seed (None|int|Variable): The start up seed. If set, seed will be set as the start up seed of shuffle engine.
                If not set(Default), start up seed of shuffle engine will be generated randomly.

    Returns:
        Variables: The shuffled LoDTensor with the same shape and lod as input.

    Examples:

        .. code-block:: python

            import paddle.fluid as fluid
            x = fluid.layers.data(name="x", shape=[-1, 4])
            out = fluid.contrib.layers.shuffle_batch(x)
    r   r/   Nr   i  i  Zstartup_seedZshuffle_batch_seedint64F)r`   r0   persistable)r1   ZSeed)r3   Z
ShuffleIdxZSeedOutr8   )r   )r   rC   rD   r0   npr   Zmain_programZrandom_seedrandomrandintr=   rX   Zcreate_variabler   generaterE   )rF   r   rH   rI   Zshuffle_idxZop_attrsrJ   rJ   rK   r   t  s4   &
r   c           	      C   s   t | tstdt|   | g} t| D ]\}}t|dt| d g dd qt|dt	d t|dt	d d| i}||d	}t
di t }|j| d
}|jd|d|gi|d |S )a  
    **Partial Concat**
    This OP concatenates the inputs according to the start index and length. This
    OP exists in contrib, which means that it is not shown to the public.
    Only 2-D Tensor or LodTensor input is supported. Slice and concat can only be
    performed along the second dimension.

    .. code-block:: text

        Given:
            x = [[0, 1, 2],
                 [3, 4, 5]]
            y = [[6, 7 ,8],
                 [9, 10, 11]]
            output = partial_concat([x, y], start_index=0, length=2)

          we get:

            output = [[0, 1, 6, 7],
                      [3, 4, 9, 10]]

    Args:
        input(list): List of input Tensors with data type float32, float64, int32,
            int64.
        start_index(int32): The start index of each instance for partial concatenation.
            Default is 0.
        length(int32): The length of each instance for partial concatenation. Default is -1.
            Negative values for all elements after start_index.
    Returns:
        Variable: A Tensor with the same data type as input's.
    Examples:
        .. code-block:: python
            import paddle.fluid as fluid
            x = fluid.data(name="x", shape=[None,3], dtype="float32")
            y = fluid.data(name="y", shape=[None,3], dtype="float32")
            concat = fluid.contrib.layers.partial_concat(
                [x, y], start_index=0, length=2)
    zDThe type of input in partial_concat should be list, but received %s.input[])float16rM   float64int32r   r   start_indexlengthr1   )r   r   r/   r3   r8   N)r   )r=   r@   warningswarnr9   	enumerater
   r>   r   rX   r   rC   rD   rj   rE   	r\   r   r   idrF   r:   r<   rH   rI   rJ   rJ   rK   r     s2   
'
r   c           	      C   s   t | D ]\}}t|dt| d g dd qd| i}i }||d< ||d< tdi t }|j| d}|jd|d	|gi|d
 |S )a  
    **PartialSum**
    This Op can sum the vars by specifying the initial position(start_index) and length(length).
    This Op exists in contrib, which means that it is not shown to the public.
    Only 2-D Tensor or LodTensor input is supported. Slice and concat can only be
    performed along the second dimension.
    .. code-block:: text

        Given:
            x = [[0, 1, 2],
                 [3, 4, 5]]
            y = [[6, 7 ,8],
                 [9, 10, 11]]
            output = partial_sum([x, y], start_index=0, length=2)
          we get:

            output = [[6, 8],
                      [12, 14]]
    Args:
        input(list): List of input Tensors with data type float32, float64, int32,
            int64.
    Returns:
        Variable: A Tensor with the same data type as input's.
    Examples:
        .. code-block:: python
        import paddle.fluid.layers as layers
        import paddle.fluid as fluid
        import numpy as np
        x = fluid.data(name="x", shape=[None, 3], dtype="float32")
        y = fluid.data(name="y", shape=[None, 3], dtype="float32")
        sum = layers.partial_sum([x,y], start_index=0, length=2)
        place = fluid.CPUPlace()
        exe = fluid.Executor(place)
        xx = np.array([1,2,3,4,5,6]).reshape((2,3)).astype("float32")
        yy = np.array([6,5,4,4,5,6]).reshape((2,3)).astype("float32")
        out = exe.run(feed={"x":xx, "y":yy}, fetch_list=[sum])
    r   r   )rM   r   r   r   r!   r1   r   r   r/   r3   r8   N)r!   )r   r
   r>   r   rC   rD   rj   rE   r   rJ   rJ   rK   r!     s"   &r!   MemorySparseTablec	                 C   s   t di t }	t| ddgd t|dddgd |	j|	j|tjjj	|d	d
}
|	
|}|du r2dn|dkr8|n|d | }|dvrFtdd}|durZ|jjdvrVtd| }|dkr`d}|	jd| |
dd|i|ddd||||dd |S )a  
    :api_attr: Static Graph

    The OP is used as the operator of the Embedding Lookup layer in the large-scale 
    sparse training of the parameter server mode, instead of using the paddle.nn.functional.embedding.

    The operator is used to lookup embeddings vector of ids provided by :attr:`input` . 
    It automatically constructs a 2D embedding matrix based on the input :attr:`size` 
    (vocab_size, emb_size) and :attr:`dtype` .

    The shape of output Tensor is generated by appending an emb_size dimension to the
    last dimension of the input Tensor shape.

    **Note:** The id in :attr:`input` must satisfy :math:`0 =< id < size[0]` , otherwise 
    the program will throw an exception and exit.

    .. code-block:: text

        Case 1:

        input is a Tensor. padding_idx = -1
            input.data = [[1, 3], [2, 4], [4, 127]]
            input.shape = [3, 2]
        Given size = [128, 16]
        output is a Tensor:
            out.shape = [3, 2, 16]
            out.data = [[[0.129435295, 0.244512452, ..., 0.436322452],
                        [0.345421456, 0.524563927, ..., 0.144534654]],

                        [[0.345249859, 0.124939536, ..., 0.194353745],
                        [0.945345345, 0.435394634, ..., 0.435345365]],
                        
                        [[0.945345345, 0.435394634, ..., 0.435345365],
                        [0.0,         0.0,         ..., 0.0        ]]]  # padding data
        The input padding_idx is less than 0, it is automatically converted to padding_idx = -1 + 128 = 127
        It will pad all-zero data when ids is 127.
        
        Case 2:

        input is a LoDTensor with 1-level LoD. padding_idx = 0
            input.lod = [[2, 3]]
            input.data = [[1], [3], [2], [4], [0]]
            input.shape = [5, 1]
        Given size = [128, 16]
        output is a LoDTensor:
            out.lod = [[2, 3]]
            out.shape = [5, 1, 16]
            out.data = [[[0.129435295, 0.244512452, ..., 0.436322452]],
                        [[0.345421456, 0.524563927, ..., 0.144534654]],
                        [[0.345249859, 0.124939536, ..., 0.194353745]],
                        [[0.945345345, 0.435394634, ..., 0.435345365]],
                        [[0.0,         0.0,         ..., 0.0        ]]]  # padding data
        It will pad all-zero data when ids is 0.

    Args:
        input(Variable): A Tensor or LoDTensor with type int64, which contains the id 
            information. The value of the input id should satisfy :math:`0<= id < size[0]` .
        size(tuple|list): The shape of lookup table parameter (vocab_size, emb_size). It 
            should have two elements which indicates the size of the dictionary of embeddings 
            and the size of each embedding vector respectively. The initial parameter size 
            is 0 in the large-scale sparse scenario, which will gradually expand with the 
            training. So if vocab_size is temporarily useless, its value can be any integer.
            The emb_size is the dimensional configuration of the word embedding weight parameter.
        padding_idx(int|long|None, optional): padding_idx needs to be in the interval [-vocab_size, vocab_size). 
            If :math:`padding\_idx < 0`, the :math:`padding\_idx` will automatically be converted
            to :math:`vocab\_size + padding\_idx` . It will output all-zero padding data whenever 
            lookup encounters :math:`padding\_idx` in id. And the padding data will not be updated 
            while training. If set None, it makes no efe mfect to output. Default: None.
        is_test(bool, optional): Training or prediction mode. In prediction mode (is_test=False), 
            the output is not initialized and created, and it is filled with 0 and returned. Default: False.
        entry(str, optional): Entry config with parameter server whose value is ProbabilityEntry, 
            CountFilterEntry or None. Default: None.
        table_class(str, optional): The type of the sparse table. The value can be CommonSparseTable 
            or SSDSparseTable. The default is CommonSparseTable.
        param_attr(ParamAttr, optional): To specify the weight parameter property. Default: None, which means the
            default weight parameter property is used. In addition, user-defined or pre-trained word 
            vectors can be loaded with the :attr:`param_attr` parameter. The local word vector needs 
            to be transformed into numpy format, and the shape of local word vector should be consistent 
            with :attr:`size` .
        dtype(str): It refers to the data type of output Tensor. It must be float32 or 
            float64. Default: float32.
            
    Returns:
        Variable: Embedding Tensor or LoDTensor mapped by input. The data type is the same as :attr:`dtype` .
    
    Examples:
        .. code-block:: python

            import paddle
            
            paddle.enable_static()
            sparse_feature_dim = 1024
            embedding_size = 64

            # Only when the feature appear more than 10 times or more will be participated in the training.
            entry = paddle.distributed.CountFilterEntry(10)

            input = paddle.static.data(name='ins', shape=[1], dtype='int64')
        
            emb = paddle.static.nn.sparse_embedding(
                input=input,
                size=[sparse_feature_dim, embedding_size],
                is_test=False,
                entry=entry,
                param_attr=paddle.ParamAttr(name="SparseFeatFactors",
                initializer=paddle.nn.initializer.Uniform()))

    r    r\   r   z%fluid.contrib.layers.sparse_embeddingr0   rM   r   z!paddle.static.nn.sparse_embeddingF)rQ   rR   r9   r0   rd   Nr+   r   )ZCommonSparseTableZSSDSparseTabler   zMtable_class must be in [CommonSparseTable, SSDSparseTable, MemorySparseTable]none)ZProbabilityEntryZCountFilterEntryZShowClickEntryzentry must be instance in [paddle.distributed.ProbabilityEntry, paddle.distributed.CountFilterEntry, paddle.distributed.ShowClickEntry]Zlookup_tablerr   r3   T)rv   rt   Zis_distributedZremote_prefetchis_testentrytable_classslotr8   )r    )r   rC   r
   r   rY   rZ   r   VarDescVarTypeZSELECTED_ROWSrD   rB   	__class____name__Z_to_attrrE   )r\   rw   rv   r   r   r   rZ   r0   r   rH   rf   tmpZ	entry_strrJ   rJ   rK   r    -  s\   v


r    r   c           
      C   s   t di t }t|dddgd t|}|j|j|d| g|tdd}d	|_|j|d
}|j|d
}	|j	d| |d||	d||dd	d ||	fS )an  
    **Tdm Child**
     According to the input node_id on the given tree, return the corresponding child node_id and 
      whether child is a leaf node by leaf_mask value.
    .. code-block:: text

        Given:
            tree[[0], [1, 2], [3, 4], [5, 6]] # A binary tree with seven nodes
            x = [[2], [3]]
            node_nums = 7
            child_nums = 2

          we get:
            child = [[5, 6],
                     [0, 0]]
            leaf_mask = [[1, 1],
                         [0, 0]]
    Args:
        x(Variable): Variable contained the node_id information, dtype support int32/int64.
        node_nums(int): Number of total nodes.
        child_nums(int): Maximum number of child nodes per node.
        param_attr(ParamAttr): To specify the tdm-tree-info parameter property. Default: None, which means the
            default weight parameter property is used. See usage for details in: ref: `api_fluid_ParamAttr`, should
            has shape(node_nums, 3 + child_nums), dtype support int32/int64. 
            The dimension[1] of tdm-tree-info contains the following: 
            1. Item_id(int, shape(1)), if node is a leaf node, give its item_id corresponding to node_id, else give 0.
            2. Layer_id(int, shape(1)), indicates which layer the node is on.
            3. Parent_id(int, shape(1)), node's parent node.
            4. Child_id(int, shape(child_nums)), all child node's node_id of this node should be given. 
            If the number of child nodes is insufficient, padding 0 until child nums equal to child_nums
        dtype(str): The data type of output child and leaf_mask, support int32/int64.

    Returns:
        tuple: A tuple including input node's child(Variable) and leaf_mask(Variable). 
            If child is a leaf node, leaf_mask equal ot 1, otherwise equal to 0.

    Examples:
        .. code-block:: python
        import paddle.fluid as fluid
        import numpy as np
        x = fluid.data(name="x", shape=[None, 1], dtype="int32", lod_level=1)
        tree_info = [[0,0,0,1,2],
                     [0,1,0,3,4],[0,1,0,5,6],
                     [0,2,1,0,0],[1,2,1,0,0],[2,2,2,0,0],[3,2,2,0,0]]
        tree_info_np = np.array(tree_info)
        tree_info_np = np.reshape(tree_info_np, (7,5))
        node_nums = 7
        child_nums = 2
        child, leaf_mask  = fluid.contrib.layers.tdm_child(x, node_nums, child_nums,
                                param_attr=fluid.ParamAttr(
                                    initializer=fluid.initializer.NumpyArrayInitializer(
                                                                            tree_info_np)))
        place = fluid.CPUPlace()
        exe = fluid.Executor(place)
        exe.run(fluid.default_startup_program())
        xx = np.array([[2],[3]]).reshape((2,1)).astype("int32")
        child_res, leaf_mask_res = exe.run(feed={"x":xx}, fetch_list=[child, leaf_mask])
     r"   r0   r   r   zfluid.contrib.layers.tdm_childr   r   rQ   rR   r0   Zdefault_initializerTr/   )r1   ZTreeInfo)ZChildZLeafMask)
child_numsr0   )r9   r:   r;   r<   rT   N)r"   )
r   rC   r   r   rY   rZ   r   rT   rD   rE   )
rF   	node_numsr   rZ   r0   rH   c_dtypeZ	tree_infochildZ	leaf_maskrJ   rJ   rK   r"     s4   ;
r"   c           "   
   C   s  t di t }t|	dddgd t|
dddgd t|
}t|t|kr2tdt|t||dus:J d	d
}d
}d
g}t|D ]'\}}|d7 }||7 }|| || || krltd||| ||| qE||k suJ d||g}|j	|||	t
d
d}|dg}|j	|||	t
d
d}|j|
d}d|_|j|
d}d|_|j|
d}d|_|jd| ||d|||d|||||dd |r@g }g }g }d
}d}|sd
}|D ]a}|| | }t|dg|g|gd}t|dg|g|gd} t|dg|g|gd}!t|d|| dg}d|_t| d|| dg} d| _t|!d|| dg}!d|!_|| ||  ||! |}q|}|}|}|||fS )a  
    **Tdm Sampler**
    According to the input positive samples at leaf node(x), do negative sampling layer by layer on the given tree.
    .. code-block:: text

        Given:
            tree[[0], [1, 2], [3, 4], [5, 6]] # A binary tree with seven nodes
            travel_list = [[1, 3], [1, 4], [2, 5], [2, 6]] # leaf node's travel path (exclude root node)
            layer_list = [[1, 2], [3, 4, 5, 6]] # two layer (exclude root node)

            x = [[0], [1], [2], [3]] # Corresponding to leaf node [[3], [4], [5], [6]]
            neg_samples_num_list = [0, 0] # negative sample nums = 0
            layer_node_num_list = [2, 4]
            leaf_node_num = 4
            output_list = False

          we get:
            out = [[1, 3], [1, 4], [2, 5], [2, 6]]
            labels = [[1, 1], [1, 1], [1, 1], [1, 1]]
            mask = [[1, 1], [1, 1], [1, 1], [1, 1]]

    Args:
        x (Variable): Variable contained the item_id(corresponding to leaf node) information, dtype support int32/int64.
        neg_samples_num_list (list(int)): Number of negative samples per layer.
        layer_node_num_list (list(int)): Number of nodes per layer, must has same shape with neg_samples_num_list.
        leaf_node_num (int): Number of leaf nodes.
        tree_travel_attr (ParamAttr): To specify the tdm-travel parameter property. Default: None, which means the
            default weight parameter property is used. See usage for details in :ref:`api_fluid_ParamAttr`, should 
            has shape (leaf_node_num, len(layer_node_num_list)), dtype support int32/int64.
        tree_layer_attr (ParamAttr): To specify the tdm-layer parameter property. Default: None, which means the
            default weight parameter property is used. See usage for details in :ref:`api_fluid_ParamAttr`, should 
            has shape (node_num, 1), dtype support int32/int64.
        output_positive (bool): Whether to output positive samples (includ label and mask )at the same time.
        output_list (bool): Whether to divide the output into layers and organize it into list format.
        seed (int): The number of random seed.
        tree_dtype(np.dtype|core.VarDesc.VarType|str): The dtype of tdm-travel and tdm-layer, support int32/int64
        dtype(np.dtype|core.VarDesc.VarType|str): The dtype of output(sampling results, labels and masks) 

    Returns:
        tuple: A tuple including sampling results, corresponding labels and masks. if output_positive = True, sampling
            result  will include both positive and negative samples. If sampling reseult is a positive sample, the label is 1, 
            and if it is a negative sample, it is 0. If the tree is unbalanced, in order to ensure the consistency of the 
            sampling result shape, the padding sample's mask = 0, the real sample's mask value = 1. 
            If output_list = True, the result will organize into list format specified by layer information.
            Output variable have same type with tdm-travel and tdm-layer parameter(tree_dtype).

    Examples:
        .. code-block:: python
        import paddle.fluid as fluid
        import numpy as np
        x = fluid.data(name="x", shape=[None, 1], dtype="int32", lod_level=1)
        travel_list = [[1, 3], [1, 4], [2, 5], [2, 6]] # leaf node's travel path, shape(leaf_node_num, layer_num)
        layer_list_flat = [[1], [2], [3], [4], [5], [6]] # shape(node_nums, 1)

        neg_samples_num_list = [0, 0] # negative sample nums = 0
        layer_node_num_list = [2, 4] #two layer (exclude root node)
        leaf_node_num = 4

        travel_array = np.array(travel_list)
        layer_array = np.array(layer_list_flat)

        sample, label, mask = fluid.contrib.layers.tdm_sampler(
            x,
            neg_samples_num_list,
            layer_node_num_list,
            leaf_node_num,
            tree_travel_attr=fluid.ParamAttr(
                initializer=fluid.initializer.NumpyArrayInitializer(
                    travel_array)),
            tree_layer_attr=fluid.ParamAttr(
                initializer=fluid.initializer.NumpyArrayInitializer(
                    layer_array)),
            output_positive=True,
            output_list=True,
            seed=0,
            tree_dtype='int32')

        place = fluid.CPUPlace()
        exe = fluid.Executor(place)
        exe.run(fluid.default_startup_program())
        xx = np.array([[0],[1]]).reshape((2,1)).astype("int32")

        exe.run(feed={"x":xx})

    r$   
tree_dtyper   r   z fluid.contrib.layers.tdm_samplerr0   zThe shape of negative samples list must match the shape of layers. But received len of neg_samples_num_list: {},and len of layer_node_num_list: {}, please check your input.Nz&leaf_node_num should not be None here.r   rL   zThe number of negative samples must be less than the number of nodes in the layer {}, But received negative nums {}, and num of node at layer {} is {}, please check your input.z0leaf_node_num must be less than total node nums.r   r/   T)r1   ZTravelZLayer)r3   ZLabelsMask)neg_samples_num_listoutput_positiveZlayer_offset_lodr   r0   r8   )ZaxesZstartsZendsr+   )r$   )r   rC   r   r   rA   rB   r   r   r   rY   r   rD   rT   rE   r   r   )"rF   r   Zlayer_node_num_listZleaf_node_numZtree_travel_attrZtree_layer_attrr   Zoutput_listr   r   r0   rH   r   Z
layer_numsr   Ztree_layer_offset_lodZ	layer_idxZlayer_node_numZtravel_shapetravelZlayer_shapelayerrI   labelsmaskZlabels_listZ	mask_listZstart_offsetZpositive_flagZlayer_sample_num
end_offsetZlayer_samplesZlayer_labelsZ
layer_maskrJ   rJ   rK   r$   7  s   `





r$   c                 C   s   t di t }|jdd}| j}|d | | |d ksJ |j|||d}	d|	_||}
|j|dd	}|j|dd	}|jd| ||	d
|
||d||dd |
S )a  
    **Rank Attention layer**
    This Op can calculate rank attention between input and rank_param, and 
    rank_param gives the organization of data. Notice: It currently supports
    GPU device.
    This Op exists in contrib, which means that it is not shown to the public.
    Args:
        input: Tensor with data type float32, float64.
        rank_offset: Tensor with data type int32.
        rank_para_shape: The shape of rank_param.
        rank_param_attr: Attribute initializer of rank_param.
        max_rank: The max rank of input's ranks.
    Returns:
        Variable: A Tensor with the same data type as input's.
    Examples:
        .. code-block:: python
           import paddle.fluid as fluid
           import numpy as np

           input = fluid.data(name="input", shape=[None, 2], dtype="float32")
           rank_offset = fluid.data(name="rank_offset", shape=[None, 7], dtype="int32")
           out = fluid.contrib.layers.rank_attention(input=input,
                                                     rank_offset=rank_offset,
                                                     rank_param_shape=[18,3],
                                                     rank_param_attr=
                                                       fluid.ParamAttr(learning_rate=1.0,
                                                                     name="ubm_rank_param.w_0",
                                                                     initializer=
                                                                     fluid.initializer.Xavier(uniform=False)),
                                                      max_rank=3,
                                                      max_size=0)
    r#   r\   )Zinput_param_namerL   r   rP   FTrg   )r1   Z
RankOffsetZ	RankParam)r3   Z	InputHelpZInsRank)ZMaxRankZMaxSizer8   N)r#   )r   rC   rj   rR   rY   rT   rD   rE   )r\   Zrank_offsetZrank_param_shapeZrank_param_attrZmax_rankmax_sizerH   r0   input_shapeZ
rank_paramr   Z
input_helpZins_rankrJ   rJ   rK   r#     s<   &
r#   c                 C   s   t di t }t| dtd | j}|d |d ksJ |d |d ks&J |d |d ks0J |d |d ks:J | }t|dddgd |j|||dd	}	|j|||dd	}
||}|j	d| |	|
d
d|id |
|S )ah  
    **Batch FC layer**
    This Op can calculate BatchFC. This is similar to matmul op, 
    except that the bias and relu activation layers are added. 
    Notice: It currently supports GPU device.
    This Op exists in contrib, which means that it is not shown to the public.
    Args:
        input: Tensor with data type float32, float64.
        param_size: The size of w.
        param_attr: Attribute initializer of w.
        bias_size: The size of bias.
        bias_attr: Attribute initializer of bias.
        act: Activation to be applied to the output of this layer.

    Returns:
        Variable: A Tensor with the same data type as input's.
    Examples:
        .. code-block:: python
           import paddle.fluid as fluid
           
           input = fluid.data(name="input", shape=[16, 2, 3], dtype="float32")
           out = fluid.contrib.layers.batch_fc(input=input,
                                               param_size=[16, 3, 10],
                                               param_attr=
                                                 fluid.ParamAttr(learning_rate=1.0,
                                                               name="w_0",
                                                               initializer=
                                                               fluid.initializer.Xavier(uniform=False)),
                                               bias_size=[16, 10],
                                               bias_attr=
                                                 fluid.ParamAttr(learning_rate=1.0,
                                                               name="b_0",
                                                               initializer=
                                                               fluid.initializer.Xavier(uniform=False)),
                                                   act="relu")
    r%   r\   r   r.   rL   rM   r   Frc   )ZInputrW   Biasr3   )r9   r:   r;   N)r%   )r   rC   r   r   rR   rj   r   rY   rD   rE   r[   )r\   Z
param_sizerZ   Z	bias_sizerp   r_   rH   r   r0   rf   bZpre_actrJ   rJ   rK   r%   W  s8   &

r%   @   c                    s   t di t    } fddtt|D } fddtt|D }jdd|i||d||dd t|d	krK|d
 |d
 fS ||fS )a  
    **Pull Box Extended Sparse Layer**
    This layer is used to lookup embeddings of IDs, provided by :attr:`input`, in
    BoxPS lookup table. The result of this lookup is the embedding of each ID in the
    :attr:`input`.
    Args:
        input(Variable|list of Variable): Input is a Tensor<int64> Variable, which
            contains the IDs information.
        size(int): The embedding size parameter, which indicates the size of
            each embedding vector respectively.
        extend_size(int): The embedding size parameter in extended dim, 
            which indicates the size of each embedding vector respectively.
        dtype(str): The dtype refers to the data type of output tensor. Only supports
      float32 now.
    Returns:
        Variable|list of Variable: The tensor variable storing the embeddings of the \
                  supplied inputs.
    Examples:
        .. code-block:: python
          import paddle.fluid as fluid
          data = fluid.layers.data(name='sequence', shape=[1], dtype='int64', lod_level=1)
          emb, emb_ex = fluid.contrib.layers._pull_box_extended_sparse(input=data, size=8, extend_size=128)
    pull_box_extended_sparsec                    rx   rJ   ry   rz   r}   rJ   rK   r~     r   z-_pull_box_extended_sparse.<locals>.<listcomp>c                    rx   rJ   ry   rz   r}   rJ   rK   r~     r   rs   )r3   Z	OutExtend)Zemb_sizeZemb_extended_sizer8   rL   r   N)r   )r   rC   rj   r   r   rA   rE   )r\   rw   Zextend_sizer0   r:   r   Zouts_extendrJ   r}   rK   r&     s*   


r&   c           	      C   s   t j rd|f}ttd| ||g|R  S t| dddgd t|dddgd t|dddgd tdi t }|| j	}| ||d}|j
d|d|id	|id
 |S )a  
    :alias_main: paddle.nn.functional.bilateral_slice
	:alias: paddle.nn.functional.bilateral_slice,paddle.nn.functional.vision.bilateral_slice
	:old_api: paddle.fluid.layers.bilateral_slice

    This operation implements bilateral slicing on the input according to the guide map.
    For more information of bilateral slicing, please refer to Deep Bilateral Learning for Real-Time Image Enhancement <https://groups.csail.mit.edu/graphics/hdrnet/data/hdrnet.pdf>_

    Args:
        x(Variable): The input tensor, which is a 4-D tensor with shape
                     [N, C, H, W], N is the batch size, C is the channel
                     number, H and W is the feature height and width.
                     The data type is float32 and float64.
        guide(Variable): Input grid tensor of shape [N, H, W]. The
                        data type is float32 and float64.
        grid(Variable): Input grid tensor of shape [N, C, D, H, W]. The
                        data type is float32 and float64.
        has_offset(bool): Whether to slice with affine offset.
        name(str, optional): For detailed information, please refer
                             to :ref:`api_guide_Name`. Usually name is no need to set and
                             None by default.

    Returns:
        Variable: Output of shape [N, C, H, W]. The data type is same as input tensor.

    Examples:

        .. code-block:: python

            import paddle.fluid as fluid

            x = fluid.data(name='x', shape=[None, 3, 101, 60], dtype='float32')
            guide = fluid.data(name='guide', shape=[None, 101, 60], dtype='float32')
            grid = fluid.data(name='grid', shape=[None, 12, 8, 10, 6], dtype='float32')

            # without offset
            output = fluid.contrib.bilateral_slice(x, guide, grid, has_offset=False)
            
            # has offset
            output = fluid.contrib.bilateral_slice(x, guide, grid, has_offset=True)

    
has_offsetr'   rF   rM   r   guidegrid)r1   ZGuideZGridr3   r   N)r'   )paddlefluid_non_static_modegetattrr   r
   r   rC   rD   r0   rE   )	rF   r   r   r   r`   r<   rH   rI   r:   rJ   rJ   rK   r'     s&   
+r'   c                 C   s   t j r!d|d|d|d|d|d|f}ttd| |g|R  }	|	S tdi t }
|
j| jd}	|
j	d| |d	||||||d
d|	id |	S )a  

    This operation compute correlation of two tensor.
    For more information of correlation, please refer to PWC-Net: 
    CNNs for Optical Flow Using Pyramid, Warping, and Cost Volume 
    <https://arxiv.org/pdf/1709.02371.pdf>_

    Args:
        x(Tensor): The input x is 4-D Tensor with shape [N, C, H, W]. The data type is float32 and float64.
        y(Tensor): The input y is 4-D Tensor with shape [N, C, H, W]. The data type is float32 and float64.
        pad_size(int): Pad size. The data type is int.
        max_displacement(int): Max displacement. The data type is int.
        stride1(int): stride size of x. The data type is int.
        stride2(int): stride size of y. The data type is int.
        corr_type_multiply(int, optional): The type of multiply. The data type is int. Default: 1.

    Returns:
        Tensor: The data type is same as input tensor.

    Examples:

        .. code-block:: python

            import paddle.fluid as fluid

            x1 = fluid.layers.data(name='x1',
                               shape=x_shape,
                               dtype=x_type,
                               append_batch_size=False)
            x2 = fluid.layers.data(name='x2',
                                shape=x_shape,
                                dtype=x_type,
                                append_batch_size=False)


            out = fluid.contrib.correlation(
                            x1,
                            x2,
                            pad_size=4,
                            kernel_size=1,
                            max_displacement=4,
                            stride1=1,
                            stride2=1)

    pad_sizekernel_sizemax_displacementstride1stride2corr_type_multiplyr(   r/   )ZInput1ZInput2)r   r   r   r   r   r   Outputr   N)r(   )
r   r   r   r   r   r   rC   rD   r0   rE   )rF   rG   r   r   r   r   r   r   r<   r   rH   rJ   rJ   rK   r(     s.   
6r(   ?h㈵>c
                 C   sN  t di t }
t| dg dd t|dg dd tjjj}| j}|d }|g}|
j|
j	||t
dd}|
j|
j||dd}|
jt|t
d	d
d||d}d|_|
jt|t
dd
d||d}d|_|}|}|
j|dd}|
j|dd}|
jtjjjdd}|
tjjj}| |||d}||d}||||||d}|
jd|||d |S )a  
    This Op performs batch norm on input x, and adds the result to input y. Then
    it performs activation on the sum. The data format of inputs must be NHWC
    `[batch, in_height, in_width, in_channels]`.

    Args:
        x(Tensor): The rank of input tensor can be 2, 3, 4, 5. The data type
            is float16.
        y(Tensor): The rank of input tensor can be 2, 3, 4, 5. The data type
            is float16.
        momentum(float|Tensor, optional): The value used for the moving_mean and
            moving_var computation. This should be a float number or a tensor with
            shape [1] and data type as float32. The updated formula is:
            :math:`moving\_mean = moving\_mean * momentum + new\_mean * (1. - momentum)`
            :math:`moving\_var = moving\_var * momentum + new\_var * (1. - momentum)`
            Default is 0.9.
        epsilon(float, optional): A value added to the denominator for
            numerical stability. Default is 1e-5.
        param_attr(ParamAttr, optional): The parameter attribute for Parameter `scale`
            of batch_norm. If it is set to None or one attribute of ParamAttr, batch_norm
	        will create ParamAttr as param_attr, the name of scale can be set in ParamAttr.
	        If the Initializer of the param_attr is not set, the parameter is initialized
	        with Xavier. Default: None.
        bias_attr(ParamAttr, optional): The parameter attribute for the bias of batch_norm.
            If it is set to None or one attribute of ParamAttr, batch_norm
	        will create ParamAttr as bias_attr, the name of bias can be set in ParamAttr.
	        If the Initializer of the bias_attr is not set, the bias is initialized zero.
	        Default: None.
        moving_mean_name(str, optional): The name of moving_mean which store the global Mean. If it
            is set to None, batch_norm will save global mean with a random name, otherwise, batch_norm
            will save global mean with the string.
        moving_variance_name(str, optional): The name of the moving_variance which store the global Variance.
            If it is set to None, batch_norm will save global variance with a random name, otherwise, batch_norm
            will save global variance with the string.
        act(string, optional): Activation type, linear|relu|prelu|...
        name(str, optional): For detailed information, please refer to :ref:`api_guide_Name`.
            Usually name is no need to set and None by default.

    Examples:
            .. code-block:: python

            import paddle.fluid as fluid

            def build_program(main_program, startup_program):
                with fluid.program_guard(main_program, startup_program):
                    x = fluid.layers.data(name='x', shape=[1, 28, 28], dtype='float32')
                    y = fluid.layers.data(name="y", shape=[1], dtype='int64')
                    conv1_1 = fluid.layers.conv2d(
                        input=x,
                        filter_size=3,
                        num_filters=32,
                        stride=1,
                        padding=1,
                        act=None,
                        bias_attr=False,
                        data_format='NHWC')
                    conv1_2 = fluid.layers.conv2d(
                        input=x,
                        filter_size=3,
                        num_filters=32,
                        stride=1,
                        padding=1,
                        act=None,
                        bias_attr=False,
                        data_format='NHWC')
                    bn = fluid.layers.batch_norm(
                        input=conv1_1,
                        act=None,
                        data_layout='NHWC')
                    fused_bn_add_act = fluid.contrib.layers.fused_bn_add_act(conv1_2, bn)
                    prediction = fluid.layers.fc(input=fused_bn_add_act, size=10, act='softmax')
                    loss = fluid.layers.cross_entropy(input=prediction, label=y)
                    loss = fluid.layers.mean(loss)
                    sgd = fluid.optimizer.SGD(learning_rate=0.001)
                    sgd = fluid.contrib.mixed_precision.decorate(
                        sgd, use_dynamic_loss_scaling=True, init_loss_scaling=128.0)
                    sgd.minimize(loss)

                return x, y, loss

            iters = 5
            batch_size = 16
            support_gpu = fluid.is_compiled_with_cuda()
            if support_gpu:
                main_program = fluid.Program()
                startup_program = fluid.Program()
                place = fluid.CUDAPlace(0)
                x, y, loss = build_program(main_program, startup_program)
  
                feeder = fluid.DataFeeder(feed_list=[x, y], place=place)
                train_reader = paddle.batch(
                    paddle.dataset.mnist.train(), batch_size=batch_size)
                exe = fluid.Executor(place)
                scope = fluid.Scope()
                with fluid.scope_guard(scope):
                    exe.run(startup_program)
                    for _ in range(iters):
                        data = next(train_reader())
                        loss_v = exe.run(main_program, feed=feeder.feed(data), fetch_list=[loss])
    r)   r\   )r   rM   r   r+   r   r   Trc   r,   F)r`   ZinitializerZ	trainablerP   rg   )r1   ZZScaler   )epsilonmomentum)r2   ZMeanOutZVarianceOutZ	SavedMeanZSavedVarianceZReserveSpaceZfused_bn_add_activationr8   N)r)   )r   rC   r
   r   r   r   ZFP32rR   rY   rZ   r   rp   r   rT   rD   ZFP16rE   )rF   rG   r   r   rZ   rp   Zmoving_mean_nameZmoving_variance_namer_   r`   rH   Zbn_param_dtypera   re   Zparam_shaper5   ZbiasmeanZvarianceZmean_outZvariance_outZ
saved_meanZsaved_varianceZreserve_spaceZbatch_norm_outr:   r<   r;   rJ   rJ   rK   r)   Z  s   n


	r)   c           	   	   C   s   t j r	tdtdi t }|jd|dgd}||tt	||  d |jdddgd}||tdd | |ksAJ d	|j
d||d
||d| |||dd |S )Nz@pow2_decay_with_linear_warmup does not support dygraph mode yet.pow2_decay_with_linear_warmupTrL   )r   r0   rR   )valuer   r   z.warmup_steps cannot be larger than total_steps)ZLearningRateZStep)ZLearningRateOutZStepOut)warmup_stepstotal_stepsbase_lrend_lrr8   )r   )r   r   r   NotImplementedErrorr   rC   Zcreate_global_variableZset_variable_initializerr   floatrE   )	r   r   r   r   r0   r`   rH   r   steprJ   rJ   rK   r     s:   
r   )r+   r,   T)rL   NNrM   N)NNrM   N)rL   r.   rk   NNN)FNrq   NrM   )r,   Tr.   )r   Tr   r   FN)NNNNNrM   )N)r   r+   )NFNr   NrM   N)Nr   )NNTTr   r   r   )r   r   )r   rM   )rL   )r   r   NNNNNN)rM   N);__doc__
__future__r   ossixr   inspectnumpyr   r   Zpaddle.fluid.layer_helperr   Zpaddle.fluid.layersr   r   r   Zpaddle.fluid.initializerr   r   r	   Zpaddle.fluid.data_feederr
   r   r   r   Zpaddle.fluidr   Zpaddle.fluid.param_attrr   Zpaddle.fluid.frameworkr   r   r   r   r   r   __all__r   r   r   r   r   r   r*   r   r   r   r   r!   r    r"   r$   r#   r%   r&   r'   r(   r)   r   rJ   rJ   rJ   rK   <module>   s   
I
{
ZL
N
I
W
 

{
C
>:
 
2]
 ]

H
D
2E
Q
 <