U
    3d                     @   s	  d dl Z d dlZd dlmZmZ d dlZd dlmZ d dlm	Z	m
Z
mZmZ d dlmZ d dlmZmZ d dlmZmZmZmZmZmZmZmZmZmZmZ d dlmZ d d	l m!Z!m"Z" e#e$ Z%d
d e%D Z&e&eddedded deddeddedded deddeddeddg
7 Z&dd Z'dddZ(dd Z)ej*j+de&e'ddd Z,e d d d!d"gej- ej-gfe d d d!d"gej- ej-gfe d d d!d"gej- ej-gfe d!d"gej- d#d$ej-gfe d!d"gej- d#d$d ej-gfed#dd!d"gej- ej-gfed dd!d"gej- ej-gfed%dd!d"gej- d#d$ej-gfeddd!d"gej- d#d$d ej-gfed&dd!d"gej- d#d$d ej-gfed#dd!d"gej- ej-gfed dd#d$d d!d"gej- ej-gfed%dd!d"gej- d#d$ej-gfeddd!d"gej- d#d$d ej-gfed&dd!d"gej- d#d$d ej-gfe d!d'd(gej- d)dej-gfe g ej- d)d*ej-gfgZ.e d gg fed#dd d$d gg fed dd d gg fed%dd gg fed#dd d$d gg fed dd d gg fed%dd gg fe d dgg fe d+d,dgg fg	Z/e g d gfed#dg d#d$d gfed dg d#d$d gfed%dg d gfed#dg d#d$d gfed dd#d$d gg fed%dg d gfe g d dgfe d!d'gd dgfg	Z0ej*+d-e.e/ d.d/ Z1ej*+d0e.e0 d1d2 Z2ej*j+d3e d,d4d5fe d,d4d6fed'dd,d4dfeddd,d4dfeddd4d,d,fe d7e3d6d6de3d6  fe d7e3d6e3d6d' fed&dd7e3d6d8feddd7d9dde3d  feddd7d9e3dd' fed&dd7d9d:fe de3d6e3d;de3d6  fed&d<d+d=d'd>ged=d'd>gd= fed&d<d,d=d'd>ged=d'd>gd' fed&d<d7d=d'd>ged=d'd>gd> fge'dd?d@ Z4ej*+de%ej*+dAdBdCgej*+dDej5ej6gej*+dEej5ej6gej*+dFddgej*+dGddgej*+dHddgej*+dIddgdJdK Z7ej*j+de&e'dej*+dFddLgdMdN Z8ej*j+de&e'dej*+dFddLgdOdP Z9ej*j+de&e'dej*+dFdQdRgdSdT Z:ej*j+de&e'ddUdV Z;ej*j+de&e'dej*+dFddLgdWdX Z<ej*j+de&e'dej*+dFddLgdYdZ Z=ej*+d[d\d]d^d_d`dadbdcddg	e"dedf Z>ej*j+de&e'dej*+dFddLgdgdh Z?ej*+die ej@djfe ejAdjfedddkdl djfe ej@dmfe ej@dnfe ej@dnfe ej@dofgdpdq ZBdrds ZCdtdu ZDej*j+de&e'ddvdw ZEej*+de%ej*+dFddLgej*+dxej5ej6fej*+dydzd{d| ZFej*+de%ej*+d}dxejGid~ejG dfgdd ZHej*+deddieIdfedd ieJdfedd*ieJdfgdd ZKej*j+de&e'ddd ZLej*+ddd dd%dd&gdd ZMdS )    N)assert_allcloseassert_array_equal)approx)minimizeminimize_scalarnewtonLinearConstraint)	logsumexp)_inclusive_low_highIdentityLink)_LOSSESBaseLossAbsoluteErrorHalfBinomialLossHalfGammaLossHalfMultinomialLossHalfPoissonLossHalfSquaredErrorHalfTweedieLossHalfTweedieLossIdentityPinballLoss)assert_all_finite)create_memmap_backed_dataskip_if_32bitc                 C   s   g | ]
}| qS  r   ).0lossr   r   A/tmp/pip-unpacked-wheel-zrfo1fqw/sklearn/_loss/tests/test_loss.py
<listcomp>#   s     r   g      ?)quantileg      power      g      @c                 C   sd   t | trX| }|jj}t|dr6|d|jj d7 }nt|drT|d|jj d7 }|S t| S d S )Nr   z
(quantile=)r!   z(power=)	
isinstancer   	__class____name__hasattrclossr   r!   str)paramr   namer   r   r   loss_instance_name3   s    


r-   d      *   c           
      C   sV  t j|}| jrbt || jf}|j|d |d || j d|jdd< t |	t
| j }nt| jtrt| j\}}	t ||d g}t |	|d g}	||	f}|j|d |d |d}t| j\}}	t||d }t|	|d }	|j||	|d}| jjdkr$| jjr$d|dd|d < | jjdkrN| jjrNd|dd|d < ||fS )z9Random generate y_true and raw_prediction in valid range.r   r"   )lowhighsizeNr7      )nprandomRandomStateis_multiclassempty	n_classesuniformflatarangeastypefloatr%   linkr   r
   interval_y_predZamaxZamininterval_y_truemaxminr5   low_inclusiver6   high_inclusive)
r   	n_samplesy_bound	raw_boundseedrngraw_predictiony_truer5   r6   r   r   r   random_y_true_raw_prediction@   s8      rS   c                 C   sh   t j||d}| |d|  }| || }| || }| |d|  }| d|  d|  | d|  S )z2Helper function for numerical (first) derivatives.)
fill_valuer#            (@)r:   	full_like)funcxepshZ
f_minus_2hZ
f_minus_1hZ	f_plus_1hZ	f_plus_2hr   r   r   numerical_derivativee   s    r\   r   )idsc                 C   sJ  | j rtjdddd}nt| j\}}tj||dd}| jjrPtj|| jjf }| jjrjtj|| jj	f }| 
|sxt|jd }t| j\}}| j rt|df}tj|||d|dddf< dd|dddf   |dddf< dd|dddf   |ddd	f< ntj|||d}| |s,t| j|}| j||d
 dS )z4Test interval ranges of y_true and y_pred in losses.r   	   
   numr9   N      ?r"   r#   rR   rQ   )r=   r:   linspacer
   rG   rJ   Zr_r5   rK   r6   in_y_true_rangeAssertionErrorshaperF   r>   in_y_pred_rangerE   r   )r   rR   r5   r6   ny_predrQ   r   r   r   test_loss_boundarys   s(    
$&rk   r/   皙?r0   皙g      ?r9   rb   ?g?              ?z!loss, y_true_success, y_true_failc                 C   sD   |D ]}|  t|gstq|D ]}|  t|gr$tq$dS )z-Test boundaries of y_true for loss functions.N)re   r:   arrayrf   )r   Zy_true_successZy_true_failyr   r   r   test_loss_boundary_y_true   s    ru   z!loss, y_pred_success, y_pred_failc                 C   sD   |D ]}|  t|gstq|D ]}|  t|gr$tq$dS )z-Test boundaries of y_pred for loss functions.N)rh   r:   rs   rf   )r   Zy_pred_successZy_pred_failrt   r   r   r   test_loss_boundary_y_pred   s    rv   z'loss, y_true, raw_prediction, loss_trueg      @rU             @g      ȿg      @g      ?r3   r?   皙?333333?c                 C   s2   | t |gt |gdt|dddks.tdS )zTest losses at specific values.rc   dy=-q=)relabsN)r:   rs   r   rf   )r   rR   rQ   Z	loss_truer   r   r   test_loss_on_specific_values   s    &
 
r   readonly_memmapFTdtype_in	dtype_outsample_weightout1out2	n_threadsc                 C   s  |  } d}t | |dddd\}	}
|	|}	|
|}
|dk	rPtjdg| |d}|dk	rftj|	|d}|dk	r|tj|
|d}|rt|	d	d
}	t|
d	d
}
|dk	rt|d	d
}| j|	|
|||d | j|	|
|||d | j|	|
||||d |dk	r
| j	r
tj|
|d}| j
|	|
||||d | |	|
|d | j|	|d | j|	|d t| drb| j|
d t| dr| j|	|
||||d dS )a0  Test acceptance of dtypes, readonly and writeable arrays in loss functions.

    Check that loss accepts if all input arrays are either all float32 or all
    float64, and all output arrays are either all float32 or all float64.

    Also check that input arrays can be readonly, e.g. memory mapped.
    r3   r.   r_   r4   r   rL   rM   rN   rO   Nrx   dtypeT)Zaligned)rR   rQ   r   loss_outr   )rR   rQ   r   gradient_outr   )rR   rQ   r   r   r   r   )rR   rQ   r   r   hessian_outr   rR   rQ   r   rR   r   predict_proba)rQ   gradient_proba)rR   rQ   r   r   	proba_outr   )rS   rC   r:   rs   
empty_liker   r   gradientloss_gradientr=   gradient_hessianfit_intercept_onlyconstant_to_optimal_zeror(   r   r   )r   r   r   r   r   r   r   r   rL   rR   rQ   r   r   r   test_loss_dtype  s    


r   rangec           
      C   sH  t | ddddd\}}|dkr:tjd|jd |jd d	}t|}t|}t|}t|}t|}t|}	t| j||||d
| jj||||d
 t| j||||d| jj||||d | jj	|||||d | jj	|||||d t|| t|| | j
|||||d | jj
|||||	d t|| t||	 dS )z:Test that Python and Cython functions return same results.   r.   r   r4   r   r   r"   r   r`   rR   rQ   r   r   rR   rQ   r   r   rR   rQ   r   r   r   rR   rQ   r   r   r   N)rS   r:   rd   rg   r   r   r   r)   r   r   r   )
r   r   rR   rQ   out_l1out_l2out_g1out_g2Zout_h1Zout_h2r   r   r   test_loss_same_as_C_functionsd  s    









r   c                 C   s  t | ddd|d\}}|dkr:tjd|jd |jd d}t|}t|}t|}t|}t|}	t|}
| j||||d	}| j||||d
}| j|||||d\}}| j||||	|
d\}}t	|| t
|| t||stt
|| t||s
tt	|| t	|| t
|| t||s:tt
|| t||sVtt
||	 t||	srtt| dr| jstt|}t|}| j|||||d\}}t	|| t	|| t	|| t	tj|ddddd dS )zTest that loss and gradient are the same across different functions.

    Also test that output arguments contain correct results.
    r   r.   r   r   r   r"   r   r`   r   r   r   r   r   rR   rQ   r   r   r   Zaxisr|   )rtolN)rS   r:   rd   rg   r   r   r   r   r   r   r   Zshares_memoryrf   r(   r=   r   sum)r   r   global_random_seedrR   rQ   r   r   r   r   Zout_g3Zout_h3l1Zg1l2Zg2Zg3h3Zout_g4Z	out_probaZg4probar   r   r    test_loss_gradients_are_the_same  s    






















r   onesr;   c                 C   sf  d}t | |dd|d\}}|dkr4tj|tjd}n tj|}|j|dtj}t| j	|||d|| j	||d	d  | j
||d	d\}}| j
|||d\}	}
t|| |	 | jst|| |
 nt||d	d	d	f  |
 | j||d	d\}}| j|||d\}
}| js.t|| |
 t|| | n4t||d	d	d	f  |
 t||d	d	d	f  | d	S )
zTest sample weights in loss, gradients and hessians.

    Make sure that passing sample weights to loss, gradient and hessian
    computation methods is equivalent to multiplying by the weights.
    r0   r.   r1   r   r   )rg   r   r8   r   N)rS   r:   r   float64r;   r<   normalrC   r   r   r   r=   r   )r   r   r   rL   rR   rQ   rP   Zlossesr   Z	losses_swZgradient_swhessianZ
hessian_swr   r   r   test_sample_weight_multiplies  sn    




r   c                 C   s   t | ddddd\}}|jdkr|dddf }t| j||d| j||d t| j||d| j||d t| j||d| j||d t| j||d| j||d dS )	z5Test that reshaped raw_prediction gives same results.r   r.   r   r4   r   r"   Nrc   )rS   ndimr   r   r   r   r   )r   rR   rQ   Zraw_prediction_2dr   r   r   test_graceful_squeezingN  s2    

r   c           	      C   s  | j sxtddddddg}t| jtrjd}| jj}| jjsD|| }| jj	}| jj
s\|| }t|||}| j|}nNt| jt}tj| j| jftd td}td|jd	d	| jd
 < |dkrtjd
|jd |jd d}| j|||d}| j||d}t|| ddd d	S )z~Test value of perfect predictions.

    Loss of y_pred = y_true plus constant_to_optimal_zero should sums up to
    zero.
    r   rn   r   rl   r9   r_   绽|=)rg   rT   r   Nr"   r   r`   r   r   +=gV瞯<)atolr   )r=   r:   rs   r%   rE   r   rF   r5   rJ   r6   rK   ZclipinverserB   r?   rC   rD   fullexprA   rd   rg   r   r   r   )	r   r   rQ   rZ   r5   r6   rR   Z
loss_valueZconstant_termr   r   r   test_loss_of_perfect_predictionm  s>    

 r   c           
         s  d}t |dd|d\dkr>tjdjd jd djd	\}}|jjksbt|jjksrtjsއfd
d}t|dd}t||ddd fdd}t|dd}	j	rnt||	ddd nt
jD ]  fdd}t|dd f dd}t|dd f |ddd  fdd}t|dd f dd}	j	rnqt|dd f |	ddd qdS )zTest gradients and hessians with numerical derivatives.

    Gradient should equal the numerical derivatives of the loss function.
    Hessians should equal the numerical derivatives of gradients.
    r   r.   r1   r   r   r"   r   r`   r   c                    s    j | dS Nr   )r   rY   r   r   rR   r   r   	loss_func  s
    z6test_gradients_hessians_numerically.<locals>.loss_funcgư>)rZ   h㈵>r   r   r   c                    s    j | dS r   r   r   r   r   r   	grad_func  s
    z6test_gradients_hessians_numerically.<locals>.grad_funcc                    s(     }| |d d  f< j|dS r   )copyr   rY   rawkr   rQ   r   rR   r   r   r     s    Ngh㈵>c                    s4     }| |d d  f< j|dd d  f S r   )r   r   r   r   r   r   r     s    
)rS   r:   rd   rg   r   rf   r=   r\   r   Zapprox_hessianr   r?   )
r   r   r   rL   gr[   r   Z	g_numericr   Z	h_numericr   r   r   #test_gradients_hessians_numerically  sF    

		r   zloss, x0, y_true)squared_errorg       r4   )r   g     @]@g?)r   rq   rq   )binomial_lossr{   rl   )r   irz   )r      ro   )poisson_lossrV   rr   )r   rq   rx   )r   g      6g      $@c                    s   t   dd tjgtjdtj|gtjd}tjtjd fdd}tjtjd fdd}tjtjd fd	d
}t||||ddd} | }t j	| t||ddd t j
|dddd dS )ac  Test that gradients are zero at the minimum of the loss.

    We check this on a single value/sample using Halley's method with the
    first and second order derivatives computed by the Loss instance.
    Note that methods of Loss instances operate on arrays while the newton
    root finder expects a scalar or a one-element array for this purpose.
    Nr   r   )rY   returnc                    s    j | d jd S )zCompute loss plus constant term.

        The constant term is such that the minimum function value is zero,
        which is required by the Newton method.
        rc   rR   )r   r   r   r   rR   r   r   rX     s     
ztest_derivatives.<locals>.funcc                    s    j | dS )Nrc   r   r   r   r   r   fprime"  s    z test_derivatives.<locals>.fprimec                    s    j | dd S )Nrc   r"   )r   r   r   r   r   fprime2%  s    z!test_derivatives.<locals>.fprime2r0   gHj>)x0r   r   maxitertolr   r   r   rc   gƠ>)r   r:   rs   r   Zndarrayr   Zravelr   rE   r   r   )r   r   rR   rX   r   r   Zoptimumr   r   r   test_derivatives  s&    
r   c                    s  d j s$ jtjdddn&ttj j dddd< dkrbtjd	d
d j	d} fdd} j st
|dddid} jt|d}|jt kst|jjkstt| |t|jddk | tdddk nt|t jdddidttd jfddd} jt|dfd}|jjksftt| t||jddd t|jddddd dS )zzTest that fit_intercept_only returns the argmin of the loss.

    Also test that the gradient is zero at the minimum.
    2   rw   r`   r   Nr3   r   rl   r#   r   c                    s>    j stj| d}nttj|  jfd} |dS )N)rg   rT   rg   r   )r=   r:   r   ZascontiguousarrayZbroadcast_tor?   )rY   rQ   r   rL   r   rR   r   r   funN  s    z%test_loss_intercept_only.<locals>.fungHz>r   r0   )r   optionsr   r~   r}   )r   gvIh%<=ZSLSQPr"   )r   r   methodconstraintsr   r   r   r   )r=   rE   r   r:   rd   rB   rC   r   r?   r   r   r   rW   rg   tuplerf   r   r   r   rY   r   r   zerosr   r   Ztiler   )r   r   ar   optgradr   r   r   test_loss_intercept_only:  sL    

r   zloss, func, random_distr   c                 C   s   t j| ddS )N   )q)r:   Z
percentiler   r   r   r   <lambda>      r   ZpoissonZexponentialbinomialc                 C   s   t j|}|dkr&|jdddd}nt||dd}| j|d}t| |t| j||ksft	| j
|t||kst	t| trt| j
|| | jjr|| jj | j|d}t| | jjr|| jj | j|d}t| dS )zTest that fit_intercept_only returns the correct functional.

    We test the functional for specific, meaningful distributions, e.g.
    squared error estimates the expectation of a probability distribution.
    r   r"   rb   r0   r8   r   N)r:   r;   r<   r   getattrr   r   r   rE   rf   r   r%   r   r   rG   rJ   fillr5   rK   r6   )r   rX   Zrandom_distr   rP   y_trainbaseline_predictionr   r   r    test_specific_fit_intercept_only}  s$    
r   c                  C   s  t jd} d}t|d}| jd|d ddt j}|j|d}|j|fksRt	t j
||jd}t|D ]}||k ||< qjt|t |t t |  t|d	d	d	f |j|d	d	d	f  t j
d
dt jd
dfD ]6}|t j}|j|d}|j|jkst	t| qd	S )zATest that fit_intercept_only returns the mean functional for CCE.r   rw   ry   r"   r0   r8   r   r   Nr_   r   )r:   r;   r<   r   randintrC   r   r   rg   rf   r   r   r   meanr   logrE   r   r   )rP   r?   r   r   r   pr   r   r   r   (test_multinomial_loss_fit_intercept_only  s     
 *r   c                 C   s   t j| }d}t }tdd}|jdd|dt j}|j|d}t 	|df}d| |dddf< d| |ddd	f< t
|j||d
|j||d
 dS )zKTest that multinomial loss with n_classes = 2 is the same as binomial loss.r   r#   ry   r   r8   g      Nrb   r"   rc   )r:   r;   r<   r   r   r   rC   r   r   r>   r   r   )r   rP   rL   ZbinomZmultinomr   rQ   Zraw_multinomr   r   r   "test_binomial_and_multinomial_loss  s    
r   c              	   C   s  d}t | |dd|d\}}t| dr`| |}|j|| jfksBttj|ddtddd	ks`tt| d
rddt	|ft	|dft	|t	|ffD ]j\}}| j
||d||d\}}|j|| jfksttj|ddtddd	kstt|| j||ddd qdS )z<Test that predict_proba and gradient_proba work as expected.r   r.   r1   r   r   r"   r   r|   r   r   )NNNr   r   )rS   r(   r   rg   r?   rf   r:   r   r   r   r   r   r   )r   r   rL   rR   rQ   r   r   r   r   r   test_predict_proba  sH    



r   r   order)CFc                 C   s  d}|dkrt |}| |d} | j|||d\}}| jrZ|j|fksJt|jdkstnP| jr|j|| jfkstt|j|| jfkstn |j|fkst|j|fkst|j|kst|j|kst|dkr|j	j
st|j	j
stn|j	jst|j	jstdS )zTest that init_gradient_and_hessian works as expected.

    passing sample_weight to a loss correctly influences the constant_hessian
    attribute, and consequently the shape of the hessian array.
    r3   r   r   )rL   r   r   )r"   r   N)r:   r   init_gradient_and_hessianZconstant_hessianrg   rf   r=   r?   r   flagsc_contiguousf_contiguous)r   r   r   r   rL   r   r   r   r   r   test_init_gradient_and_hessians  s0    



r  zparams, err_msgz+Valid options for 'dtype' are .* Got dtype=z	 instead.c              	   C   s@   |  } t jttf|d | jf ddi|\}}W 5 Q R X dS )zDTest that init_gradient_and_hessian raises errors for invalid input.matchrL   r3   N)pytestraises
ValueError	TypeErrorr   )r   paramserr_msgr   r   r   r   r   %test_init_gradient_and_hessian_raises$  s    r  zloss, params, err_type, err_msgr   z4quantile must be an instance of float, not NoneType.zquantile == 0, must be > 0.zquantile == 1.1, must be < 1.c              	   C   s(   t j||d | f | W 5 Q R X dS )z/Test that loss raises errors for invalid input.r  N)r  r  )r   r  Zerr_typer  r   r   r   #test_loss_init_parameter_validation5  s    r  c                 C   sR   d}t | |dddd\}}t| }t|}| ||dt|||dksNtdS )z Test that losses can be pickled.r   r.   r1   r4   r   rc   N)rS   pickledumpsloadsr   rf   )r   rL   rR   rQ   Zpickled_lossZunpickled_lossr   r   r   test_loss_pickleM  s    



r  r   c                 C   s   t | d}t| d}d}t||dd\}}|j|}|j||d|| }|j||d|| }t|| |j||d\}	}
|j||d\}}t|	||  t|
|| |d |   dS )zCTest for identical losses when only the link function is different.r    r_   r4   )r   rL   rO   rc   r#   N)	r   r   rS   rE   r   r   r   r   r   )r   Zhalf_tweedie_logZhalf_tweedie_identityrL   rR   rQ   rj   Zloss_logZloss_identityZgradient_logZhessian_logZgradient_identityZhessian_identityr   r   r   %test_tweedie_log_identity_consistency_  sF    

  
  

 
 
 r  )r.   r1   r4   )Nr  Znumpyr:   Znumpy.testingr   r   r  r   Zscipy.optimizer   r   r   r   Zscipy.specialr	   Zsklearn._loss.linkr
   r   Zsklearn._loss.lossr   r   r   r   r   r   r   r   r   r   r   Zsklearn.utilsr   Zsklearn.utils._testingr   r   listvaluesZ
ALL_LOSSESZLOSS_INSTANCESr-   rS   r\   markZparametrizerk   infZY_COMMON_PARAMSZY_TRUE_PARAMSZY_PRED_PARAMSru   rv   r   r   Zfloat32r   r   r   r   r   r   r   r   r   r   r   Zmedianr   r   r   r   r  Zint64r  r
  r	  r  r  r  r   r   r   r   <module>   s  4     
%
% """ "" 
 
 & $
TPOE
0Y.A

+$	

