U
    3dkJ                  
   @   s  d Z ddlZddlZddlZddlmZ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mZmZ dd	lmZ dd
lmZ ddlmZ edZe ZeejjZej e Z!eje Z"e#e$j%Z&dd Z'dd Z(dd Z)dd Z*dd Z+dd Z,dd Z-ej./dddddgej./dddddgej./d dddgej./d!ddddgd"d# Z0d$d% Z1d&d' Z2ej./d(d)d*d+d,d-gd.d/ Z3d0d1 Z4d2d3 Z5d4d5 Z6d6d7 Z7d8d9 Z8d:d; Z9ej./d<d!e:dfd=e:d>fd?e;d@fgdAdB Z<dCdD Z=dS )EzL
Testing for Neighborhood Component Analysis module (sklearn.neighbors.nca)
    N)assert_array_equalassert_array_almost_equal)
check_grad)clone)ConvergenceWarning)check_random_state)	load_irismake_classification
make_blobs)NeighborhoodComponentsAnalysis)pairwise_distances)LabelEncoderc                  C   s   t ddgddgddgddgg} t ddddg}tdddd}|| | || }tt| dddf t ddddg dS )	zTest on a simple example.

    Puts four points in the input space where the opposite labels points are
    next to each other. After transform the samples from the same class
    should be next to each other.

    r         identity*   )n_componentsinitrandom_stateN   )nparrayr   fit	transformr   r   Zargsort)XyncaX_t r   D/tmp/pip-unpacked-wheel-zrfo1fqw/sklearn/neighbors/tests/test_nca.pytest_simple_example    s    "  
r    c            	      C   s   t jd} d}| d|}t ||jddt jddf g}dddg}G dd	 d	}|||}td|jd
}|	||}t
| t||d  d t|jd dk stdS )a  Test on a toy example of three points that should collapse

    We build a simple example: two points from the same class and a point from
    a different class in the middle of them. On this simple example, the new
    (transformed) points should all collapse into one single point. Indeed, the
    objective is 2/(1 + exp(d/2)), with d the euclidean distance between the
    two samples from the same class. This is maximized for d=0 (because d>=0),
    with an objective equal to 1 (loss=-1.).

    r      r   r   )ZaxisNr   c                   @   s   e Zd Zdd Zdd ZdS )z4test_toy_example_collapse_points.<locals>.LossStorerc                 S   sh   t j| _t | _t j| j_| jj||dd\| _}t 	|}|d d t j
f |t j
d d f k| _d S Nr   )Zensure_min_samples)r   inflossr   fake_ncan_iter__validate_datar   r   fit_transformnewaxissame_class_maskselfr   r   r   r   r   __init__D   s    
z=test_toy_example_collapse_points.<locals>.LossStorer.__init__c                 S   s    | j || j| jd\| _}dS )z*Stores the last value of the loss functiong      N)r%   _loss_grad_lbfgsr   r*   r$   )r,   transformationn_iter_r   r   r   callbackM   s       z=test_toy_example_collapse_points.<locals>.LossStorer.callbackN__name__
__module____qualname__r-   r2   r   r   r   r   
LossStorerC   s   	r7   )r   r2           g|=)r   randomRandomStaterandnZvstackZmeanr)   r   r2   r(   printr   absr$   AssertionError)	rngZ	input_dimZ
two_pointsr   r   r7   Zloss_storerr   r   r   r   r    test_toy_example_collapse_points2   s    $

r@   c                    s   t j| }t| d\ }||d jd d  jd }t d_|ddt j	f |t j	ddf k fdd} fdd}t
||| }|tjd	d
dkstdS )z~Test gradient of loss function

    Assert that the gradient is almost equal to its finite differences
    approximation.
    )r   r   r   Nc                    s    |  d S )Nr   r.   Mr   maskr   r   r   funj   s    z$test_finite_differences.<locals>.func                    s    |  d S )Nr   rA   rB   rD   r   r   gradm   s    z%test_finite_differences.<locals>.gradr8   -C6?)r=   )r   r9   r:   r	   r;   randintshaper   r&   r)   r   ZravelpytestZapproxr>   )Zglobal_random_seedr?   r   rC   rF   rG   Zdiffr   rD   r   test_finite_differences\   s    $$rL   c               	   C   s   t ddd} ddddg}t}t jd}|dd}d|jd	  d
|jd  d}tj	t
t|d ||d| | W 5 Q R X d}d| d| jd  d}tj	t
t|d ||d| | W 5 Q R X d S )N      r   r   r   r   r!   The output dimensionality (r   ]) of the given linear transformation `init` cannot be greater than its input dimensionality ().matchr   
   DThe preferred dimensionality of the projected space `n_components` (8) cannot be greater than the given data dimensionality ()!)r   )r   arangereshaper   r9   r:   randrJ   rK   raises
ValueErrorreescaper   )r   r   ZNCAr?   r   msgr   r   r   r   test_params_validationu   s    ra   c               	   C   s   t ddd} ddddg}t ddgddgg}tt t|d| | W 5 Q R X t ddgddgddgg}tt t|d| | W 5 Q R X t d	dd}t|d| | d S )
NrM   rN   r   r   r   rT   r!      	   )	r   rY   rZ   r   rK   r\   r]   r   r   )r   r   r/   r   r   r   test_transformation_dimensions   s    rd   c               	   C   s  t jd} t ddd}ddddg}| |jd d d}|jd }t||d}d| d	|jd
  d}tj	t
t|d ||| W 5 Q R X |jd d }t||d}d| d|jd  d}tj	t
t|d ||| W 5 Q R X tddd}||| d S )Nr   rM   rN   r   r   r   r   r   rV   V) does not match the output dimensionality of the given linear transformation `init` (r   rX   rR   rW   r   )r   r   )r   r9   r:   rY   rZ   r[   rJ   r   rK   r\   r]   r^   r_   r   )r?   r   r   r   r   r   r`   r   r   r   test_n_components   s$    
rg   c               	   C   s  t jd} tddddd\}}tdd}||| td	d}||| td
d}||| tdd}||| tdd}||| | |jd |jd }t|d}||| | |jd |jd d }t|d}d|jd  d|jd  d}	tj	t
t|	d ||| W 5 Q R X | |jd d |jd }t|d}d|jd  d|jd  d}	tj	t
t|	d ||| W 5 Q R X | |jd |jd }|jd d }
t||
d}d|
 d|jd  d}	tj	t
t|	d ||| W 5 Q R X d S )Nr      rb   r!   r   	n_samplesZcenters
n_featuresr   r   rT   r9   autopcaldar   zThe input dimensionality (zc) of the given linear transformation `init` must match the dimensionality of the given inputs `X` (rQ   rR   rO   rP   r   re   rV   rf   rX   )r   r9   r:   r
   r   r   r[   rJ   rK   r\   r]   r^   r_   )r?   r   r   r   Z
nca_randomZnca_autoZnca_pcaZnca_ldar   r`   r   r   r   r   test_init_transformation   sD    







ro   rj   r   r!         rk   	n_classesr   c           
      C   s   t jd}td|d|d}|| kr&n|| |}t t|| | d d |  }||kr\nt|}||| |t	|d |krt|j
dd}	n0|t	|| k rt|j
dd}	nt|j
dd}	|	|| t|j|	j d S )	Nr   rl   r   )r   r   max_iterr   rn   rT   rm   r   )r   r9   r:   r   r;   Ztileranger   r   minZ
set_paramsr   components_)
rj   rk   rr   r   r?   Znca_baser   r   r   Z	nca_otherr   r   r   test_auto_init  s,        rw   c               	   C   s   t ddddddd\} }tddd}|| | t ddddddd\}}d|jd	  d
|jjd	  d}tjtt	|d ||| W 5 Q R X d S )Nrh   r!   rN   r   )rj   rk   rr   Zn_redundantZn_informativer   T)
warm_startrs   zThe new inputs dimensionality (r   zT) does not match the input dimensionality of the previously learned transformation (rQ   rR   )
r	   r   r   rJ   rv   rK   r\   r]   r^   r_   )r   r   r   ZX_less_featuresr`   r   r   r   test_warm_start_validation)  s,    
	
	ry   c                  C   s   t ddd} | tt | j}d| _| tt | j}t ddd}|tt |j}d|_|tt |j}tt|| }tt|| }|dk st	d||kst	dd S )	NTr   )rx   r   r   Fg      @zVTransformer changed significantly after one iteration even though it was warm-started.zfCold-started transformer changed less significantly than warm-started transformer after one iteration.)
r   r   	iris_datairis_targetrv   rs   r   sumr=   r>   )Znca_warmZtransformation_warmZtransformation_warm_plus_oneZnca_coldZtransformation_coldZtransformation_cold_plus_oneZ	diff_warmZ	diff_coldr   r   r   test_warm_start_effectivenessG  s(    

r}   	init_namerm   rn   r   r9   precomputedc                 C   s^  t jd}tddddd\}}d}d| d	| d
}| dkrX||jd |jd }n| }td|d}||| | \}	}
t	
d|	}| d
krt	||  |d st|dd  }|d dkstdddd}|d d|kst|d ddt| kst|dd D ]}t	d|stqt	d|d sHt|d dksZtd S )Nr   rh   rb   r!   r   ri   z... done in \ *\d+\.\d{2}szFinding principal componentsz&Finding most discriminative components)rm   rn   r   r   )verboser   z
+z [NeighborhoodComponentsAnalysis]z{:>10} {:>20} {:>10}Z	IterationzObjective ValuezTime(s)z#[NeighborhoodComponentsAnalysis] {}r   -r   zH\[NeighborhoodComponentsAnalysis\] *\d+ *\d\.\d{6}e[+|-]\d+\ *\d+\.\d{2}z@\[NeighborhoodComponentsAnalysis\] Training took\ *\d+\.\d{2}s\. )r   r9   r:   r
   r;   rJ   r   r   
readouterrr^   splitrS   r>   formatlen)r~   capsysr?   r   r   Zregexp_initZmsgsr   r   outr1   linesheaderliner   r   r   test_verboseg  s<     
r   c                 C   s.   t  }|tt |  \}}|dks*td S )Nr   )r   r   rz   r{   r   r>   )r   r   r   r1   r   r   r   test_no_verbose  s    r   c                  C   s4  t } t}d}t||k\}d||< |||d < tdd}|| | t|dk\}t|dk\}d||< d||d < d||< d||d < tdd}|| | t|dk\}t|dk\}t|dk\}| |d |d |d g } ||d |d |d g }tddd}|| | t| ||  d S )Nr   r   r   rh   rs   r   )r   rs   )rz   r{   r   wherer   r   r   r   )r   r   Zsingleton_classZind_singletonr   Zind_1Zind_2Zind_0r   r   r   test_singleton_class  s0    

r   c                  C   sL   t tdk } ttdk }td| jd dd}|| | t| ||  d S )Nr   rh   r   r   )rs   r   r   )rz   r{   r   rJ   r   r   r   )r   r   r   r   r   r   test_one_class  s      r   c                    sP   d  fdd}t  |dd}|tt |  \}}d d |ksLtd S )NrU   c                    s4   | j tj d d fkst | }td| d S )Nr   r   {} iterations remaining...)rJ   rz   r>   r<   r   )r/   r0   Zrem_iterr   r   r   my_cb  s    ztest_callback.<locals>.my_cbr   )rs   r2   r   r   )r   r   rz   r{   r   r   r>   )r   r   r   r   r1   r   r   r   test_callback  s    r   c                  C   s\   t } t}G dd d}|| |}|j}td|d}|| | |jj| jd d ksXtdS )z4Test that the transformation has the expected shape.c                   @   s   e Zd Zdd Zdd ZdS )z@test_expected_transformation_shape.<locals>.TransformationStorerc                 S   s`   t  | _tj| j_| jj||dd\| _}t |}|d d tj	f |tj	d d f k| _
d S r"   )r   r%   r   r#   r&   r'   r   r   r(   r)   r*   r+   r   r   r   r-     s
    
zItest_expected_transformation_shape.<locals>.TransformationStorer.__init__c                 S   s
   || _ dS )zWStores the last value of the transformation taken as input by
            the optimizerN)r/   )r,   r/   r0   r   r   r   r2     s    zItest_expected_transformation_shape.<locals>.TransformationStorer.callbackNr3   r   r   r   r   TransformationStorer  s   	r   r!   )rs   r2   r   r   N)	rz   r{   r2   r   r   r/   sizerJ   r>   )r   r   r   Ztransformation_storercbr   r   r   r   "test_expected_transformation_shape  s    
r   c               	   C   sN   t ddd} | jj}d|}tjtt|d | 	t
t W 5 Q R X d S )Nr   r   )rs   r   z[{}] NCA did not convergerR   )r   	__class__r4   r   rK   Zwarnsr   r^   r_   r   rz   r{   )r   Zcls_namer`   r   r   r   test_convergence_warning  s
    
r   zparam, valuers   d   ZtolrH   c                 C   s&   t f | |i}t}t}||| d S )N)r   rz   r{   r   )paramvaluer   r   r   r   r   r   test_parameters_valid_types  s    r   c                     s`   t } t}t | |}| }|jj  tj	 fddt
|jjd D td}t|| dS )zCCheck `get_feature_names_out` for `NeighborhoodComponentsAnalysis`.c                    s   g | ]}  | qS r   r   ).0iZclass_name_lowerr   r   
<listcomp>   s     z.test_nca_feature_names_out.<locals>.<listcomp>r   )ZdtypeN)rz   r{   r   r   Zget_feature_names_outr   r4   lowerr   r   rt   rv   rJ   objectr   )r   r   ZestZ	names_outZexpected_names_outr   r   r   test_nca_feature_names_out  s    r   )>__doc__rK   r^   Znumpyr   Znumpy.testingr   r   Zscipy.optimizer   Zsklearnr   Zsklearn.exceptionsr   Zsklearn.utilsr   Zsklearn.datasetsr   r	   r
   Zsklearn.neighborsr   Zsklearn.metricsr   Zsklearn.preprocessingr   r?   ZirisZpermutationtargetr   permdatarz   r{   ZfinfofloatZepsZEPSr    r@   rL   ra   rd   rg   ro   markZparametrizerw   ry   r}   r   r   r   r   r   r   r   Zint32Zfloat32r   r   r   r   r   r   <module>   sh   

*#@  
,	$
