U
    fLO                     @   s   d Z ddlZddlmZ zddlZW n ek
r8   Y nX zddlZW n ek
rZ   Y nX G dd dZdd Z	d	d
 Z
dd ZG dd dZdddZdd ZdS )z
This module is a pure python implementation of Tree SHAP.
It is primarily for illustration since it is slower than the 'tree'
module which uses a compiled C++ implmentation.
    N   )	Explainerc                   @   s6   e Zd ZdZdd ZdddZdddZdd
dZdS )TreeExplainerz7 A pure Python (slow) implementation of Tree SHAP.
    c                 K   s(  d| _ tt|dr,dd |jD | _nztt|drRdd |jD | _nTtt|drrd| _ || _n4tt|d	rd
| _ || _ntdtt| | j dkr$tdd | jD d }||d  d }tj	|tj
d| _tj	|tjd| _tj	|tjd| _tj	|tjd| _d S )NZinternalz/sklearn.ensemble.forest.RandomForestRegressor'>c                 S   s   g | ]}t |jqS  TreeZtree_.0er   r   =/tmp/pip-target-lpfmz8o1/lib/python/shap/explainers/pytree.py
<listcomp>   s     z*TreeExplainer.__init__.<locals>.<listcomp>z0sklearn.ensemble.forest.RandomForestClassifier'>c                 S   s   g | ]}t |jd dqS )T)	normalizer   r   r   r   r   r      s     zxgboost.core.Booster'>xgboostzlightgbm.basic.Booster'>lightgbmz+Model type not supported by TreeExplainer: c                 S   s   g | ]
}|j qS r   )	max_depth)r	   tr   r   r   r      s        r   Zdtype)
model_typestrtypeendswithZestimators_trees	Exceptionnpmaxzerosint32feature_indexesfloat64zero_fractionsone_fractionspweights)selfmodelkwargsZmaxdsr   r   r   __init__   s&    zTreeExplainer.__init__c                    sh  | j dkrDtt|ds&t|}|dkr2d}| jj||ddS | j dkr`| jj||ddS tt|d	rz|j}ntt|d
r|j}tt|dst	dtt| t
|jdkst
|jdkst	d| jd jjd }t
|jdkrt|jd d | tj|jd tjd}| jD ]}| |||  q0 t
| j  |dkrp d d df S  fddt|D S nt
|jdkrdt|jd |jd d |f tj|jd tjd}t|jd D ]B}| jD ]4}| |||d d f | |d d d d f  qq܈ t
| j  |dkrN d d d d df S  fddt|D S d S )Nr   xgboost.core.DMatrix'>r(   r   T)ntree_limitZpred_contribsr   )Znum_iterationZpred_contribzpandas.core.series.Series'>zpandas.core.frame.DataFrame'>z'numpy.ndarray'>zUnknown instance type: r   r   z%Instance must have 1 or 2 dimensions!r   c                    s   g | ]} d d |f qS Nr   r	   iphir   r   r      s     z-TreeExplainer.shap_values.<locals>.<listcomp>c                    s"   g | ]} d d d d |f qS r+   r   r,   r.   r   r   r      s     )r   r   r   r   r   DMatrixr   predictvaluesAssertionErrorlenshaper   r   bool	tree_shaprange)r#   X
tree_limitr%   Z	n_outputs	x_missingr   r-   r   r.   r   shap_values   sD    


&$

 
6
zTreeExplainer.shap_valuesc                 K   s\   | j dkrDtt|ds&t|}|dkr2d}| jj||ddS tdtt| d S )Nr   r)   r(   r   T)r*   Zpred_interactionsz5Interaction values not yet supported for model type: )	r   r   r   r   r   r0   r   r1   r   )r#   r9   r:   r%   r   r   r   shap_interaction_values   s    

z%TreeExplainer.shap_interaction_valuesr   c                 C   sz   |dkr.|dd d f  |j dd d f 7  < t|j|j|j|j|j|j |j|||dd| j| j	| j
| jddd||d d S )Nr   r(   r   )r2   tree_shap_recursivechildren_leftchildren_rightchildren_defaultfeatures
thresholdsnode_sample_weightr   r    r!   r"   )r#   treexr;   r/   	conditioncondition_featurer   r   r   r7      s4    &                  zTreeExplainer.tree_shapN)r(   )r(   )r   r   )__name__
__module____qualname____doc__r'   r<   r=   r7   r   r   r   r   r      s
   
3
r   c           	      C   s   || |< |||< |||< |dkr*d||< nd||< t |d ddD ]P}||d   |||  |d  |d  7  < |||  ||  |d  ||< qBd S )Nr         ?        r   r(   r8   )	r   r    r!   r"   unique_depthzero_fractionone_fractionZfeature_indexr-   r   r   r   extend_path  s    
,rS   c                 C   s   || }|| }|| }t |d ddD ]r}	|dkrz||	 }
||d  |	d |  ||	< |
||	 | ||	  |d   }q(||	 |d  |||	   ||	< q(t ||D ]4}	| |	d  | |	< ||	d  ||	< ||	d  ||	< qd S )Nr   r(   rN   rM   rO   )r   r    r!   r"   rP   
path_indexrR   rQ   next_one_portionr-   tmpr   r   r   unwind_path  s    ""rW   c                 C   s   || }|| }|| }d}	t |d ddD ]n}
|dkrz||d  |
d |  }|	|7 }	||
 || ||
 |d    }q,|	||
 | ||
 |d   7 }	q,|	S )Nr   r   r(   rN   rM   rO   )r   r    r!   r"   rP   rT   rR   rQ   rU   totalr-   rV   r   r   r   unwound_path_sum(  s    ""rY   c                   @   s   e Zd ZdddZdS )r   Fc                 C   s   t t|dr|jtj| _|jtj| _| j| _|j	tj| _
|jtj| _|r|jd d dd d f j|jd d dd d f d j| _n|jd d dd d f | _|jtj| _t| j| j| j| jd| _d S )Nz'sklearn.tree._tree.Tree'>r   r   )r   r   r   r?   Zastyper   r   r@   rA   featurerB   	thresholdr   rC   valueTsumr2   Zweighted_n_node_samplesrD   compute_expectationsr   )r#   rE   r   r   r   r   r'   H  s"    >   zTree.__init__N)F)rI   rJ   rK   r'   r   r   r   r   r   9  s   r   c                 C   s   || dkr,||d d f ||d d f< dS | | }|| }t | |||||d }t | |||||d }	|| }
|| }|
||d d f  |||d d f   |
|  }|||d d f< t||	d S d S )Nr(   r   r   )r_   r   )r?   r@   rD   r2   r-   depthZliriZ
depth_leftZdepth_rightZleft_weightZright_weightvr   r   r   r_   ^  s    0r_   c           (      C   s  |dkrd S ||d d  }|d |d  |d |d < ||d d  }|d |d  |d |d < ||d d  }|d |d  |d |d < ||d d  }|d |d  |d |d < |dks||krt |||||||| ||
 }||
 dkrdtd|d D ]X}t||||||}|	|| d d f  ||| ||   ||
d d f  | 7  < qnd}| |
 }||
 }|| dkr||
 }n|| ||
 k r|}n|}||kr|n|} ||
 }|| | }!||  | }"d}#d}$d}%|%|kr||% |krq|%d7 }%q|%|d krJ||% }#||% }$t||||||% |d8 }|}&|}'|dkrt||krtd}'|d8 }n,|dk r||kr|&|!9 }&|'|"9 }'|d8 }t| |||||||||	||d |||||!|# |$||||& t| |||||||||	| |d |||||"|# d||||' d S )NrN   r   r   r(   rM   )rS   r8   rY   rW   r>   )(r?   r@   rA   rB   rC   r2   rD   rF   r;   r/   Z
node_indexrP   Zparent_feature_indexesZparent_zero_fractionsZparent_one_fractionsZparent_pweightsZparent_zero_fractionZparent_one_fractionZparent_feature_indexrG   rH   Zcondition_fractionr   r    r!   r"   Zsplit_indexr-   wZ	hot_indexZcleftZcrightZ
cold_indexZhot_zero_fractionZcold_zero_fractionZincoming_zero_fractionZincoming_one_fractionrT   Zhot_condition_fractionZcold_condition_fractionr   r   r   r>   o  s          H


                                  r>   )r   )rL   numpyr   Z	explainerr   r   ImportErrorr   r   rS   rW   rY   r   r_   r>   r   r   r   r   <module>   s$    n%
