
    AVh@                        d 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 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      ej*                  ej,                  	 d d                     Z ej0                  d      d        Z ed      ej,                  d!d              Z edddg      ej,                   ej6                  d      d d                     Z ed      ej,                  d!d              Z ej<                  dd       edg      ej,                  d d                     Zy)"zEOperations for clipping (gradient, weight) tensors to min/max values.    N)constant_op)dtypes)indexed_slices)ops)	array_ops)array_ops_stack)gen_array_ops)
gen_nn_ops)math_ops)deprecation)dispatch)collections_abc)	tf_exportclip_by_valuec                 Z   t        j                  |d| ||g      5 }t        j                  t        | t        j
                        r| j                  n| d      }t        j                  ||      }|j                  j                  |j                         t        j                  |||      }|j                  j                  |j                         t        | t        j
                        r+t	        j
                  || j                  | j                        }ddd       |S # 1 sw Y   S xY w)aq	  Clips tensor values to a specified min and max.

  Given a tensor `t`, this operation returns a tensor of the same type and
  shape as `t` with its values clipped to `clip_value_min` and `clip_value_max`.
  Any values less than `clip_value_min` are set to `clip_value_min`. Any values
  greater than `clip_value_max` are set to `clip_value_max`.

  Note: `clip_value_min` needs to be smaller or equal to `clip_value_max` for
  correct results.

  For example:

  Basic usage passes a scalar as the min and max value.

  >>> t = tf.constant([[-10., -1., 0.], [0., 2., 10.]])
  >>> t2 = tf.clip_by_value(t, clip_value_min=-1, clip_value_max=1)
  >>> t2.numpy()
  array([[-1., -1.,  0.],
         [ 0.,  1.,  1.]], dtype=float32)

  The min and max can be the same size as `t`, or broadcastable to that size.

  >>> t = tf.constant([[-1, 0., 10.], [-1, 0, 10]])
  >>> clip_min = [[2],[1]]
  >>> t3 = tf.clip_by_value(t, clip_value_min=clip_min, clip_value_max=100)
  >>> t3.numpy()
  array([[ 2.,  2., 10.],
         [ 1.,  1., 10.]], dtype=float32)

  Broadcasting fails, intentionally, if you would expand the dimensions of `t`

  >>> t = tf.constant([[-1, 0., 10.], [-1, 0, 10]])
  >>> clip_min = [[[2, 1]]] # Has a third axis
  >>> t4 = tf.clip_by_value(t, clip_value_min=clip_min, clip_value_max=100)
  Traceback (most recent call last):
  ...
  InvalidArgumentError: Incompatible shapes: [2,3] vs. [1,1,2]

  It throws a `TypeError` if you try to clip an `int` to a `float` value
  (`tf.cast` the input to `float` first).

  >>> t = tf.constant([[1, 2], [3, 4]], dtype=tf.int32)
  >>> t5 = tf.clip_by_value(t, clip_value_min=-3.1, clip_value_max=3.1)
  Traceback (most recent call last):
  ...
  TypeError: Cannot convert ...


  Args:
    t: A `Tensor` or `IndexedSlices`.
    clip_value_min: The minimum value to clip to. A scalar `Tensor` or one that
      is broadcastable to the shape of `t`.
    clip_value_max: The maximum value to clip to. A scalar `Tensor` or one that
      is broadcastable to the shape of `t`.
    name: A name for the operation (optional).

  Returns:
    A clipped `Tensor` or `IndexedSlices`.

  Raises:
    `tf.errors.InvalidArgumentError`: If the clip tensors would trigger array
      broadcasting that would make the returned tensor larger than the input.
    TypeError: If dtype of the input is `int32` and dtype of
      the `clip_value_min` or `clip_value_max` is `float32`
  r   tnameN)r   
name_scopeconvert_to_tensor
isinstancer   IndexedSlicesvaluesr   minimumshapeassert_is_compatible_withmaximumindicesdense_shape)r   clip_value_minclip_value_maxr   r   t_mint_maxs          N/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/clip_ops.pyr   r   "   s    L ~~dO..9; L>B""q.">">?QF
 V^4E LL**5;;7UN>E
LL**5;;7!^112**5!))Q]]Ke!L$ 
,%L$ 
,s   C;D  D*ClipByValuec                 h   | j                   d   }| j                   d   }| j                   d   }|j                  }t        j                  |      }t        j                  |      }t        j                  |      }t        j                  |      }	t        j                  |	|      }
t        j                  ||      }t        j                  ||      }t        j                  ||      \  }}t        j                  ||      \  }}t        j                  t        j                  ||      |
|      }t        j                  |||
      }t        j                  |||
      }t        j                  t        j                  ||      |      }t        j                  t        j                  ||      |      }|||fS )zReturns grad of clip_by_value.r         )inputsdtyper   r   zerosr   lessgreaterr	   broadcast_gradient_argswhere
logical_orreshape
reduce_sum)opgradxyzgdtypesxsysz	gradshaper+   xymaskxzmask_ryrzxgradygradzgradgygzs                        r$   _clip_by_value_gradrG      sW    	iil!iil!iil!::&q"q"q"ood#)
//)V
,%==A&Aq!&

/
/B
7%!R

/
/B
7%!R
//(--ff=ud
K%
//&$
.%
//&$
.%,,UB7<",,UB7<"	B    clip_by_normc                    t        j                  |d| |g      5 }t        j                  t        | t        j
                        r| j                  n| d      }t        j                  |      r|dk  r8d}n5t        j                  t        j                  |d      |j                        }t        j                  ||z  |d      }|dkD  }t        j                  ||t        j                   |            }t        j                  |t        j"                  |      |      }||z  }	|j$                  j'                  |	j$                         t        j(                  |	t        j                  ||      z  |      }
t        | t        j
                        r4t	        j
                  |
| j*                  | j,                        cddd       S |
cddd       S # 1 sw Y   yxY w)	a  Clips tensor values to a maximum L2-norm.

  Given a tensor `t`, and a maximum clip value `clip_norm`, this operation
  normalizes `t` so that its L2-norm is less than or equal to `clip_norm`,
  along the dimensions given in `axes`. Specifically, in the default case
  where all dimensions are used for calculation, if the L2-norm of `t` is
  already less than or equal to `clip_norm`, then `t` is not modified. If
  the L2-norm is greater than `clip_norm`, then this operation returns a
  tensor of the same type and shape as `t` with its values set to:

  `t * clip_norm / l2norm(t)`

  In this case, the L2-norm of the output tensor is `clip_norm`.

  As another example, if `t` is a matrix and `axes == [1]`, then each row
  of the output will have L2-norm less than or equal to `clip_norm`. If
  `axes == [0]` instead, each column of the output will be clipped.

  Code example:

  >>> some_nums = tf.constant([[1, 2, 3, 4, 5]], dtype=tf.float32)
  >>> tf.clip_by_norm(some_nums, 2.0).numpy()
  array([[0.26967996, 0.5393599 , 0.80903983, 1.0787199 , 1.3483998 ]],
        dtype=float32)

  This operation is typically used to clip gradients before applying them with
  an optimizer.  Most gradient data is a collection of different shaped tensors
  for different parts of the model.  Thus, this is a common usage:

  ```
  # Get your gradients after training
  loss_value, grads = grad(model, features, labels)

  # Apply some clipping
  grads = [tf.clip_by_norm(g, norm)
               for g in grads]

  # Continue on with training
  optimizer.apply_gradients(grads)
  ```

  Args:
    t: A `Tensor` or `IndexedSlices`.  This must be a floating point type.
    clip_norm: A 0-D (scalar) `Tensor` > 0. A maximum clipping value, also
      floating point.
      Note: If a negative clip_norm is provided, it will be treated as zero.
    axes: A 1-D (vector) `Tensor` of type int32 containing the dimensions to use
      for computing the L2-norm. If `None` (the default), uses all dimensions.
    name: A name for the operation (optional).

  Returns:
    A clipped `Tensor` or `IndexedSlices`.

  Raises:
    ValueError: If the clip_norm tensor is not a 0-D scalar tensor.
    TypeError: If dtype of the input is not a floating point or
      complex type.
  rI   r   r   r   r*   T)keepdimsN)r   r   r   r   r   r   r   npisscalarr   castr   r*   r2   r   r/   	ones_likesqrtr   r   identityr   r   )r   	clip_normaxesr   r   l2sumpred
l2sum_safel2normintermediatevalues_clips              r$   rI   rI      s{   z ~~dNQ	N; t""q.">">?QF 
{{9	Q	--


9a
(i
 EE19Dui.A.A%.HIJ__T8==#<eDFI%L LL**<+=+=>$$x''	::GK !^112))+qyy!--P7 : ;  s   F GGGzlinalg.global_normglobal_norm)v1c                 :   t        | t        j                        rt        | t              rt	        dt        |        d      t        |       } t        j                  |d|       5 }t        |       D cg c]I  \  }}|@t        j                  t        |t        j                        r|j                  n|d|z        n|K }}}g }|D ]G  }|t        j                  |      5  |j                  t!        j"                  |             ddd       I t%        j&                  t)        j*                  |            }t%        j,                  |t/        j0                  d|j2                        z  d      }ddd       |S c c}}w # 1 sw Y   xY w# 1 sw Y   S xY w)	aD  Computes the global norm of multiple tensors.

  Given a tuple or list of tensors `t_list`, this operation returns the
  global norm of the elements in all tensors in `t_list`. The global norm is
  computed as:

  `global_norm = sqrt(sum([l2norm(t)**2 for t in t_list]))`

  Any entries in `t_list` that are of type None are ignored.

  Args:
    t_list: A tuple or list of mixed `Tensors`, `IndexedSlices`, or None.
    name: A name for the operation (optional).

  Returns:
    A 0-D (scalar) `Tensor` of type `float`.

  Raises:
    TypeError: If `t_list` is not a sequence.
  3`t_list` should be a sequence of tensors. Received .r[   Nt_%dr   g       @rK   )r   r   Sequencestr	TypeErrortypelistr   r   	enumerater   r   r   r   colocate_withappendr
   l2_lossr   r2   r   stackrQ   r   constantr*   )	t_listr   ir   r   half_squared_normsvhalf_squared_normnorms	            r$   r[   r[      s   0 V_55
6
IF|nA' ( (<&
~~dM62 d
 f%	 Aq !" 	"1n&B&BCAHH!	34	5F   ;	
q! 	;

#
#J$6$6q$9
:	; 	;;
 !++013 ==S(9(?(?@	AD!* 
+)	; 	;* 
+s>   %F4AE>FF$%F	A+F>FF	FFclip_by_global_normc                    t        | t        j                        rt        | t              rt	        dt        |        d      t        |       } |t        | |      }t        j                  |d| |gz         5 }|t        j                  d|z  t        j                  d|j                        |z        z  }|||z
  z   }t        |       D cg c]I  \  }}|@t        j                   t        |t"        j$                        r|j&                  n|d|z        n|K }}}g }	t        |      D ]  \  }}
|
|	j)                  d       t        j*                  |
      5  |	j)                  t-        j.                  |
t        j0                  ||
j                        z  d	||fz               ddd        t3        |	|       D cg c]L  \  }}t        |t"        j$                        r+t#        j$                  ||j4                  |j6                        n|N }}}ddd       ||fS c c}}w # 1 sw Y   xY wc c}}w # 1 sw Y   |fS xY w)
a  Clips values of multiple tensors by the ratio of the sum of their norms.

  Given a tuple or list of tensors `t_list`, and a clipping ratio `clip_norm`,
  this operation returns a list of clipped tensors `list_clipped`
  and the global norm (`global_norm`) of all tensors in `t_list`. Optionally,
  if you've already computed the global norm for `t_list`, you can specify
  the global norm with `use_norm`.

  To perform the clipping, the values `t_list[i]` are set to:

      t_list[i] * clip_norm / max(global_norm, clip_norm)

  where:

      global_norm = sqrt(sum([l2norm(t)**2 for t in t_list]))

  If `clip_norm > global_norm` then the entries in `t_list` remain as they are,
  otherwise they're all shrunk by the global ratio.

  If `global_norm == infinity` then the entries in `t_list` are all set to `NaN`
  to signal that an error occurred.

  Any of the entries of `t_list` that are of type `None` are ignored.

  This is the correct way to perform gradient clipping (Pascanu et al., 2012).

  However, it is slower than `clip_by_norm()` because all the parameters must be
  ready before the clipping operation can be performed.

  Args:
    t_list: A tuple or list of mixed `Tensors`, `IndexedSlices`, or None.
    clip_norm: A 0-D (scalar) `Tensor` > 0. The clipping ratio.
    use_norm: A 0-D (scalar) `Tensor` of type `float` (optional). The global
      norm to use. If not provided, `global_norm()` is used to compute the norm.
    name: A name for the operation (optional).

  Returns:
    list_clipped: A list of `Tensors` of the same type as `list_t`.
    global_norm: A 0-D (scalar) `Tensor` representing the global norm.

  Raises:
    TypeError: If `t_list` is not a sequence.

  References:
    On the difficulty of training Recurrent Neural Networks:
      [Pascanu et al., 2012](http://proceedings.mlr.press/v28/pascanu13.html)
      ([pdf](http://proceedings.mlr.press/v28/pascanu13.pdf))
  r^   r_   Nrr         ?rK   r`   r   z%s_%d)r   r   ra   rb   rc   rd   re   r[   r   r   r   r   r   rk   r*   rf   r   r   r   r   rh   rg   r   rR   rO   zipr   r   )rl   rS   use_normr   scale_for_finitescalerm   r   r   values_clippedro   c_vlist_clippeds                r$   rr   rr   *  sQ   f V_55
6
IF|nA' ( (<&64(H
~~d1	{*, !/3 8#3#3hS7)C$E E
 8 34E f%	 Aq !" 	"1n&B&BCAHH!	34	5F  N&! 	1	
d#q! 	


  hmmE17733'T1I:M	 			 NF3 S! a556 	$$S!))Q]]C<?	@L ;!F 
x	3	 	;!F 
x	sF   7AH8AH?H8AH%&H8?AH2H8H8%H/*H88Izclip_by_average_norm is deprecated in TensorFlow 2.0. Please use clip_by_norm(t, clip_norm * tf.cast(tf.size(t), tf.float32), name) instead.)dateinstructionsclip_by_average_normc                 8   t        j                  |d| |g      5 }t        j                  | d      } t        j                  t        j                  |       t        j                        }t        j                  t        j                  | | z  t        j                  t        j                  |                         }t        j                  | |z  t        j                  ||z  t        j                   d      |z        z  |      }ddd       |S # 1 sw Y   S xY w)a]  Clips tensor values to a maximum average L2-norm.

  Given a tensor `t`, and a maximum clip value `clip_norm`, this operation
  normalizes `t` so that its average L2-norm is less than or equal to
  `clip_norm`. Specifically, if the average L2-norm is already less than or
  equal to `clip_norm`, then `t` is not modified. If the average L2-norm is
  greater than `clip_norm`, then this operation returns a tensor of the same
  type and shape as `t` with its values set to:

  `t * clip_norm / l2norm_avg(t)`

  In this case, the average L2-norm of the output tensor is `clip_norm`.

  This operation is typically used to clip gradients before applying them with
  an optimizer.

  Args:
    t: A `Tensor`.
    clip_norm: A 0-D (scalar) `Tensor` > 0. A maximum clipping value.
    name: A name for the operation (optional).

  Returns:
    A clipped `Tensor`.
  r~   r   r   rt   N)r   r   r   r   rO   r   sizer   float32rsqrtr2   rangerankrR   r   r   rk   )r   rS   r   	n_element
l2norm_invtclips         r$   r~   r~     s    @ ~~d2Q	NC tac*A innQ/@IAE8>>)..2C#DEGJ	I(("K$8$8$=	$IK 	KE 
, 
,s   C+DD)N)NN) __doc__numpyrM   tensorflow.python.frameworkr   r   r   r   tensorflow.python.opsr   r   r	   r
   r   tensorflow.python.utilr   r   tensorflow.python.util.compatr    tensorflow.python.util.tf_exportr   register_unary_elementwise_apiadd_dispatch_supportr   RegisterGradientrG   rI   deprecated_endpointsr[   rr   
deprecatedr~    rH   r$   <module>r      sw   L  3 . 6 + + 1 / , * . + 9 6 ?	((	U  ) Uv m$ %. >	X  Xv %9=$IJ	!!!-0/ 1  K/d  !	\   "\ ~ 	
 %&'	&  (&rH   