
    qWj5                     L   S r SSKrSSKJr  SSKJr  SSKJ	r	  SSK
Jr   " S S5      r " S S	5      r SS
\S\S\R                  S\4S jjrSS/S4S
\S\S\R                  S\\   S\4
S jjrSS\R                  S\R                  S\4S jjrS
\S\R                  S\4S jrg)z
Probability Calibration Module.

Provides calibration methods for probability estimates and reliability diagrams.
Supports both multi-output models (Long/Short) and custom fitting.
    N)IsotonicRegression)LogisticRegression)loggerc                       \ rS rSrSrSS\4S jjrS\S\R                  4S jr
S\S\4S	 jrS\S\R                  4S
 jrS\4S jrSrg)MultiOutputCalibrator   u  
Обертка для калибровки вероятностей multi-output моделей (Long/Short).

Supports:
- Isotonic Regression (non-parametric)
- Platt Scaling (Logistic Regression)

Args:
    method: Calibration method ('isotonic' or 'platt')

Example:
    >>> calibrator = MultiOutputCalibrator(method='isotonic')
    >>> calibrator.fit(raw_probs, y_true)
    >>> calibrated_probs = calibrator.predict_proba(raw_probs)
methodc                 ,    Xl         / U l        SU l        g)u   
Инициализация калибратора.

Args:
    method: Метод калибровки ('isotonic' или 'platt')
FN)r	   calibrators	is_fitted)selfr	   s     3/home/ai/projects/AI_Strategy/models/calibration.py__init__MultiOutputCalibrator.__init__    s         	raw_probsy_truec                    [        U[        5      (       d  [        S5      e[        U5      nX2R                  S   :w  a  [        SU SUR                  S    S35      e/ U l        [        U5       H  nX   SS2S4   nUSS2U4   nU R                  S:X  a  [        SS	SS
9nUR                  XV5        OWU R                  S:X  a.  [        SSSS9nUR                  UR                  SS5      U5        O[        SU R                   S35      eU R
                  R                  U5        M     SU l        [        R                  " SU SU R                   S35        U $ )u  
Обучает калибраторы для каждого выхода.

Args:
    raw_probs: list of arrays (вероятности классов для каждого выхода)
               shape: [(n_samples, 2), (n_samples, 2), ...]
    y_true: массив (n_samples, n_targets)

Returns:
    self: Возвращает себя для удобства (fluent interface)
z"raw_probs must be a list of arrays   zMismatch: raw_probs has z arrays, y_true has z columnsNisotonicclipr   )out_of_boundsy_miny_maxplattg    _Blbfgsi  )Csolvermax_iterz+Method must be 'isotonic' or 'platt', got ''TzCalibrated z targets using .)
isinstancelist
ValueErrorlenshaper   ranger	   r   fitr   reshapeappendr   r   info)r   r   r   	n_targetsip_rawy_tcals           r   r)   MultiOutputCalibrator.fit+   sI    )T**ABB	N	Q'*9+5I&,,WX/IZZbc  y!ALA&EA,C{{j((vQaP#'(4$Ob!,c2 #Nt{{m[\!]^^##C( "  k)ODKK=JKr   returnc                    U R                   (       d  [        S5      e/ n[        U R                  5       H  u  p4X   SS2S4   nU R                  S:X  a  UR                  U5      nO(UR                  UR                  SS5      5      SS2S4   n[        R                  " USS5      nUR                  [        R                  SU-
  U4   5        M     U$ )u   
Применяет калибровку к сырым вероятностям.

Args:
    raw_probs: list of arrays (вероятности классов)

Returns:
    list of arrays: Калиброванные вероятности (n_samples, 2)
z,Calibrator not fitted yet. Call fit() first.Nr   r   r    r   )r   RuntimeError	enumerater   r	   predictpredict_probar*   npr   r+   c_)r   r   
calibratedr.   r1   r/   p1s          r   r8   #MultiOutputCalibrator.predict_probaV   s     ~~MNN
 0 01FALA&E{{j([['&&u}}R';<QTBQ"B beeAFBJ/0 2 r   c                     U R                  U5      n[        R                  " U Vs/ s H  o3SS2S4   S:  PM     sn5      $ s  snf )u  
Предсказывает классы с калиброванными вероятностями.

Args:
    raw_probs: list of arrays (вероятности классов)

Returns:
    np.ndarray: Предсказанные классы (n_samples, n_targets)
Nr         ?)r8   r9   column_stack)r   r   calibrated_probsps       r   r7   MultiOutputCalibrator.predicts   sC      --i88HI8H1!Q$38HIJJIs   A
target_idxc                 p    U[        U R                  5      :  a  [        SU S35      eU R                  U   $ )u   
Получает конкретный калибратор по индексу.

Args:
    target_idx: Индекс таргета (0 = Long, 1 = Short)

Returns:
    Калибратор sklearn
zTarget index z out of range)r&   r   
IndexError)r   rD   s     r   get_calibrator$MultiOutputCalibrator.get_calibrator   s<     T--..}ZLFGG
++r   )r   r   r	   N)r   )__name__
__module____qualname____firstlineno____doc__strr   r$   r9   ndarrayr)   r8   r7   intrG   __static_attributes__ r   r   r   r      sd     	s 	)T )2:: )Vt  :K K"** K, ,r   r   c                       \ rS rSrSrS
S jrS\R                  S\R                  4S jrS\R                  S\	4S jr
S	rg)CalibratedModel   u#  
Обертка для модели с применением калибратора.

Проблема:
    Модель.predict_proba() возвращает "сырые" вероятности, которые могут
    быть смещены (недооценка или переоценка вероятностей).

Решение:
    Используем Calibrator для приведения вероятностей в корректный диапазон.

Args:
    model: Обученная модель (RF, XGBoost, LightGBM)
    calibrator: MultiOutputCalibrator или None

Example:
    >>> calibrator = MultiOutputCalibrator(method='isotonic')
    >>> calibrator.fit(raw_probs, y_true)
    >>> model = CalibratedModel(model, calibrator)
    >>> probs = model.predict_proba(X)
Nc                     Xl         X l        g)u   
Инициализация.

Args:
    model: Обученная модель
    calibrator: MultiOutputCalibrator (по умолчанию None)
N)model
calibrator)r   rW   rX   s      r   r   CalibratedModel.__init__   s     
$r   Xr3   c                     U R                   b6  U R                  R                  U5      nU R                   R                  U5      $ U R                  R                  U5      $ )u   
Предсказывает классы.

Args:
    X: Feature matrix (n_samples, n_features)

Returns:
    np.ndarray: Предсказанные классы (n_samples, n_targets)
)rX   rW   r8   r7   r   rZ   r   s      r   r7   CalibratedModel.predict   sL     ??&

003I??**955::%%a((r   c                 "   U R                   bN  U R                  R                  U5      n[        U[        5      (       d  U/nU R                   R                  U5      $ U R                  R                  U5      n[        U[        5      (       d  U/$ U$ )u   
Предсказывает калиброванные вероятности.

Args:
    X: Feature matrix (n_samples, n_features)

Returns:
    list of arrays: Калиброванные вероятности (n_samples, 2)
)rX   rW   r8   r#   r$   r\   s      r   r8   CalibratedModel.predict_proba   sz     ??&

003Ii..&K	??00;;

003Ii..!{"r   )rX   rW   N)rI   rJ   rK   rL   rM   r   r9   rO   r7   r$   r8   rQ   rR   r   r   rT   rT      s>    *	%) )

 ) rzz d r   rT   r   	cal_probsr   	save_pathc           	         [         R                  " SSSS9u  pESS/n[        S5       H  nXW   nUSS2U4   n	[        XU   SS2S4   5      u  p[        XU   SS2S4   5      u  pUR	                  SS/SS/S	S
S9  UR	                  XSSS9  UR	                  XSSS9  UR                  SSSSSS9  UR                  SXg    35        UR                  S5        UR                  S5        UR                  SS9  UR                  SS5        UR                  SS5        M     [         R                  " 5         U(       a2  [         R                  " USSS9  [        R                  " SU 35        XE4$ [         R                   " 5         XE4$ )u  
Строит график надежности (Reliability Diagram) для сравнения сырых и откалиброванных вероятностей.

График показывает:
- Как хорошо модель предсказывает вероятность (x-axis)
- Какая доля фактических позитивов (y-axis)
- Линия безошибочной калибровки (x=y)
- Красная зона: 0.55 - 0.60 (высокая уверенность)

Args:
    raw_probs: Сырые вероятности (list of arrays, shape [(n_samples, 2), (n_samples, 2)])
    cal_probs: Калиброванные вероятности (list of arrays)
    y_true: True labels (n_samples, n_targets)
    save_path: Путь для сохранения графика (необязательно)

Example:
    >>> from models.calibration import plot_reliability_diagram
    >>> plot_reliability_diagram(raw_probs, cal_probs, y_test, save_path="plot.png")
r      )      figsizeLongShortNr   zk:zPerfectly calibrated)labelzs-z	Raw modelzo-
Calibratedg?g333333?redg?zHigh-conf zone (0.55-0.60))coloralphark   zReliability Diagram: zMean predicted probabilityzFraction of positivesz
upper left)loc   tightdpibbox_incheszReliability diagram saved to )pltsubplotsr(   _calibration_curveplotaxvspan	set_title
set_xlabel
set_ylabellegendset_xlimset_ylimtight_layoutsavefigr   r,   show)r   ra   r   rb   figaxestarget_namesr.   axr0   prob_true_rawprob_pred_rawprob_true_calprob_pred_cals                 r   plot_reliability_diagramr      s   , Q73ICG$L1XWQTl (:#|AqD?Q'R$'9#|AqD?Q'R$
AA,BC
d+F
d,G 	

4U#=Y
Z
,\_,=>?
23
-.
		l	#
Aq
Aq) , I3G<3I;?@ 9 	
9r   ri   rj   r   c           
         [         R                  " SSSS9u  pV[        U5       H  u  pxXg   n	USS2U4   n
U	R                  X   SS2S4   U
S:H     SSS	S
SS9  U	R                  X   SS2S4   U
S:H     SSSSSS9  U	R                  X   SS2S4   U
S:H     SSSSSS9  U	R                  X   SS2S4   U
S:H     SSSSSS9  U	R	                  SU 35        U	R                  S5        U	R                  S5        U	R                  5         U	R                  SS9  M     [         R                  " 5         U(       a2  [         R                  " USSS9  [        R                  " SU 35        XV4$ [         R                  " 5         XV4$ )u{  
Альтернативная визуализация: гистограмма распределения вероятностей.

Сравнивает сырые и калиброванные вероятности, показывая
как Isotonic Regression сдвигает распределение.

Args:
    raw_probs: Сырые вероятности
    cal_probs: Калиброванные вероятности
    y_true: True labels
    target_names: Названия таргетов
    save_path: Путь для сохранения

Example:
    >>> plot_calibration_comparison(raw_probs, cal_probs, y_test)
rd   r   )re      rg   Nr      r?   zRaw (negatives)blueblack)binsro   rk   rn   	edgecolorzRaw (positives)rm   zCalibrated (negatives)cyanzCalibrated (positives)orangezProbability Distribution: ProbabilityCountg333333?)ro   rq   rr   rs   z Calibration comparison saved to )rv   rw   r6   histr{   r|   r}   r~   gridr   r   r   r,   r   )r   ra   r   r   rb   r   r   r.   namer   r0   s              r   plot_calibration_comparisonr     s   . Q73IC\*WQTl 	LAsax(# 	 	
 	LAsax(# 	 	
 	LAsax(* 	 	
 	LAsax(* 	 	
 	1$89
m$
g
		
cY +\ I3G<6ykBC 9 	
9r   y_probn_binsc                    [         R                  " SSUS-   5      nUSS USS -   S-  n[         R                  " U5      n[         R                  " U5      n[        [	        USS USS 5      5       Hs  u  nu  pX:  X:  -  n
U
R                  5       S:  a*  X
   R                  5       XW'   X   R                  5       Xg'   MO  [         R                  XW'   [         R                  Xg'   Mu     [         R                  " U5      ) nX[   Xk   4$ )u  
Кастомная реализация калибровочной кривой.

Args:
    y_true: True labels
    y_prob: Predicted probabilities
    n_bins: Количество бинов

Returns:
    (prob_true, prob_pred): Данные для построения графика
r   r   Nr    rd   )	r9   linspacezerosr6   zipsummeannanisnan)r   r   r   r   bin_centers	prob_true	prob_predr.   lowhighmaskvalids               r   rx   rx   b  s     ;;q!VaZ(D9tABx'1,K I I#CSb	48$<=;C&-088:>!<,,.IL!<,,.IL66IL66IL > XXi  EY---r   r3   c                     SnSn[        [        XR                  5      5       H3  u  nu  pVU[        R                  " USS2S4   U-
  S-  5      -  nUS-  nM5     US:  a  X#-  $ S$ )u  
Вычисляет Brier Score (MSE между предсказанными и истинными вероятностями).

Args:
    raw_probs: Сырые вероятности
    y_true: True labels

Returns:
    Brier Score (чем меньше, тем лучше)
r   Nr   rd   )r6   r   Tr9   r   )r   r   brier_scoretotalr.   r/   r0   s          r   calibration_scorer     sp     KE$SHH%=><Erwwadc 1a788
 ? #(!);22r   r`   )
   )rM   numpyr9   matplotlib.pyplotpyplotrv   sklearn.isotonicr   sklearn.linear_modelr   utils.loggerr   r   rT   r$   rO   rN   r   r   rP   rx   floatr   rR   r   r   <module>r      s      / 3 }, },@D DP LP77 $7.0jj7EH7|  &w/OOO JJO s)	O
 Od.rzz .2:: .s .@3 3rzz 3e 3r   