o
    ?e)                     @   s   d 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dZedg dejddejdfddZeddgdejedddejddfddZdS )z#Confusion matrix related utilities.    )dtypes)ops)	array_ops)array_ops_stack)	check_ops)cond)control_flow_ops)math_ops)deprecation)dispatch)	tf_exportNc           	         s  t |d g t t    }|j}  }|j}|durd|durd|| }||d krD|jd drDtdgn||d krY|jd drYt dg  fW  d   S t	t	  }|du sz|jd drt

t|d |fddfdd|du s|jd drt

t|d | fdd fd	d  fW  d   S 1 sw   Y  dS )
a$  Squeeze last dim if ranks differ from expected by exactly 1.

  In the common case where we expect shapes to match, `expected_rank_diff`
  defaults to 0, and we squeeze the last dimension of the larger rank if they
  differ by 1.

  But, for example, if `labels` contains class IDs and `predictions` contains 1
  probability per class, we expect `predictions` to have 1 more dimension than
  `labels`, so `expected_rank_diff` would be 1. In this case, we'd squeeze
  `labels` if `rank(predictions) - rank(labels) == 0`, and
  `predictions` if `rank(predictions) - rank(labels) == 2`.

  This will use static shape if available. Otherwise, it will add graph
  operations, which could result in a performance hit.

  Args:
    labels: Label values, a `Tensor` whose dimensions match `predictions`.
    predictions: Predicted values, a `Tensor` of arbitrary dimensions.
    expected_rank_diff: Expected result of `rank(predictions) - rank(labels)`.
    name: Name of the op.

  Returns:
    Tuple of `labels` and `predictions`, possibly with last dim squeezed.
  remove_squeezable_dimensionsN   c                         t  dgS Nr   r   squeeze predictionsr   g/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/ops/confusion_matrix.py<lambda>Q       z.remove_squeezable_dimensions.<locals>.<lambda>c                          S Nr   r   r   r   r   r   R       c                      r   r   r   r   labelsr   r   r   W   r   c                      r   r   r   r   r   r   r   r   X   r   )r   
name_scopeconvert_to_tensor	get_shapeZndimsdimsZis_compatible_withr   r   Zrankr   r	   equal)	r   r   Zexpected_rank_diffnameZpredictions_shapeZpredictions_rankZlabels_shapeZlabels_rankZ	rank_diffr   )r   r   r   r      sP   





$r   zmath.confusion_matrix)v1c           
      C   s  t |d|| ||f}tt j| ddt j|dd\} }t|tj}t| tj} t	t
j| ddg| } t	t
j|ddg|}|du rVtt|t| d	 }n!t|tj}t	t
j| |d
dg| } t	t
j||ddg|}|durt j|dd}| |  t||}t||g}tj| |gd	d}|du rt||n|}	tj||	t|tjdW  d   S 1 sw   Y  dS )a  Computes the confusion matrix from predictions and labels.

  The matrix columns represent the prediction labels and the rows represent the
  real labels. The confusion matrix is always a 2-D array of shape `[n, n]`,
  where `n` is the number of valid labels for a given classification task. Both
  prediction and labels must be 1-D arrays of the same shape in order for this
  function to work.

  If `num_classes` is `None`, then `num_classes` will be set to one plus the
  maximum value in either predictions or labels. Class labels are expected to
  start at 0. For example, if `num_classes` is 3, then the possible labels
  would be `[0, 1, 2]`.

  If `weights` is not `None`, then each prediction contributes its
  corresponding weight to the total value of the confusion matrix cell.

  For example:

  ```python
    tf.math.confusion_matrix([1, 2, 4], [2, 2, 4]) ==>
        [[0 0 0 0 0]
         [0 0 1 0 0]
         [0 0 1 0 0]
         [0 0 0 0 0]
         [0 0 0 0 1]]
  ```

  Note that the possible labels are assumed to be `[0, 1, 2, 3, 4]`,
  resulting in a 5x5 confusion matrix.

  Args:
    labels: 1-D `Tensor` of real labels for the classification task.
    predictions: 1-D `Tensor` of predictions for a given classification.
    num_classes: The possible number of labels the classification task can
                 have. If this value is not provided, it will be calculated
                 using both predictions and labels array.
    weights: An optional `Tensor` whose shape matches `predictions`.
    dtype: Data type of the confusion matrix.
    name: Scope name.

  Returns:
    A `Tensor` of type `dtype` with shape `[n, n]` representing the confusion
    matrix, where `n` is the number of possible labels in the classification
    task.

  Raises:
    ValueError: If both predictions and labels are not 1-D vectors and have
      mismatched shapes, or if `weights` is not `None` and its shape doesn't
      match `predictions`.
  confusion_matrixr   )r$   r   z!`labels` contains negative values)messagez&`predictions` contains negative valuesNr   z`labels` out of boundz`predictions` out of boundweights)Zaxis)indicesZupdatesshape)r   r   r   r    r	   castr   Zint64r   Zwith_dependenciesr   Zassert_non_negativemaximumZ
reduce_maxZassert_lessr!   Zassert_is_compatible_withr   stackr   Z	ones_likeZ
scatter_nd)
r   r   num_classesr(   dtyper$   Znum_classes_int64r*   r)   valuesr   r   r   r&   \   sx   :
$r&   ztrain.confusion_matrixc                 C   s   t | |||||S )a  Computes the confusion matrix from predictions and labels.

  The matrix columns represent the prediction labels and the rows represent the
  real labels. The confusion matrix is always a 2-D array of shape `[n, n]`,
  where `n` is the number of valid labels for a given classification task. Both
  prediction and labels must be 1-D arrays of the same shape in order for this
  function to work.

  If `num_classes` is `None`, then `num_classes` will be set to one plus the
  maximum value in either predictions or labels. Class labels are expected to
  start at 0. For example, if `num_classes` is 3, then the possible labels
  would be `[0, 1, 2]`.

  If `weights` is not `None`, then each prediction contributes its
  corresponding weight to the total value of the confusion matrix cell.

  For example:

  ```python
    tf.math.confusion_matrix([1, 2, 4], [2, 2, 4]) ==>
        [[0 0 0 0 0]
         [0 0 1 0 0]
         [0 0 1 0 0]
         [0 0 0 0 0]
         [0 0 0 0 1]]
  ```

  Note that the possible labels are assumed to be `[0, 1, 2, 3, 4]`,
  resulting in a 5x5 confusion matrix.

  Args:
    labels: 1-D `Tensor` of real labels for the classification task.
    predictions: 1-D `Tensor` of predictions for a given classification.
    num_classes: The possible number of labels the classification task can have.
      If this value is not provided, it will be calculated using both
      predictions and labels array.
    dtype: Data type of the confusion matrix.
    name: Scope name.
    weights: An optional `Tensor` whose shape matches `predictions`.

  Returns:
    A `Tensor` of type `dtype` with shape `[n, n]` representing the confusion
    matrix, where `n` is the number of possible labels in the classification
    task.

  Raises:
    ValueError: If both predictions and labels are not 1-D vectors and have
      mismatched shapes, or if `weights` is not `None` and its shape doesn't
      match `predictions`.
  )r&   )r   r   r.   r/   r$   r(   r   r   r   confusion_matrix_v1   s   ;r1   )r   N)__doc__Ztensorflow.python.frameworkr   r   Ztensorflow.python.opsr   r   r   r   r   r	   Ztensorflow.python.utilr
   r   Z tensorflow.python.util.tf_exportr   r   Zadd_dispatch_supportZint32r&   Zdeprecated_endpointsr1   r   r   r   r   <module>   s:   

>i
