From d7011e73b9cb910d1c71f6afa3afac8de187e57a Mon Sep 17 00:00:00 2001 From: propcgamer20-png Date: Thu, 10 Sep 2026 15:03:02 +0530 Subject: [PATCH] Add reject-option-classification explainer (closes #542) Adds explainers/reject-option-classification.md covering Reject Option Classification (Kamiran, Karim & Zhang, IEEE ICDM 2012), the post-processing method that reassigns labels only inside a low-confidence band around the decision boundary. - Explicit name-collision note distinguishing it from reject-inference.md and a contrast table against this repo's ThresholdOptimizer (S4). - Worked example on the COMPAS baseline logistic regression: sweeps the critical-region half-width theta and shows the fairness gap shrink at +-0.10 (651 of 3,254 predictions flipped, gap halved), then reverse to -70 pp and collapse accuracy at +-0.15. - Detection code: reject_option_classify() plus a sweep_theta() helper. - Limitations: theta has no principled default, needs group membership at prediction time, can invert the disparity, and the individual-fairness objection. Regenerated assets/explainers-data.js, faircode/_explainers/, the HTML page, OG images, sitemap.xml and llms-full.txt; check_explainer_count.py --fix bumped the 60 -> 61 mentions in README/CONTRIBUTORS/METRICS/ROADMAP. --- CONTRIBUTORS.md | 2 +- METRICS.md | 2 +- README.md | 6 +- ROADMAP.md | 2 +- assets/explainers-data.js | 10 + assets/explainers-data.json | 7 + .../og-light/reject-option-classification.png | Bin 0 -> 64528 bytes assets/og/reject-option-classification.png | Bin 0 -> 64808 bytes explainers/reject-option-classification.html | 372 ++++++++++++++++++ explainers/reject-option-classification.md | 228 +++++++++++ faircode/_explainers/data.json | 7 + .../reject-option-classification.md | 228 +++++++++++ llms-full.txt | 235 +++++++++++ sitemap.xml | 4 + 14 files changed, 1097 insertions(+), 6 deletions(-) create mode 100644 assets/og-light/reject-option-classification.png create mode 100644 assets/og/reject-option-classification.png create mode 100644 explainers/reject-option-classification.html create mode 100644 explainers/reject-option-classification.md create mode 100644 faircode/_explainers/reject-option-classification.md diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 052583e..fa0d496 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -55,7 +55,7 @@ the [Git identity map](#git-identity-map) so `git shortlog -sne` can be reconcil | | Who | Role | |:--|-----|------| -| yakew7 | **Yash Kewlani** - [@yakew7](https://github.com/yakew7) | Creator and maintainer. Author of the seven audits, the `faircode` library and benchmark harness, the Open Dataset Profiler, the website, and the bulk of the 60 explainers. Code owner for `faircode/`, `paper/`, every `audit.yaml`, and project policy (`CLAUDE.md`, `CONTRIBUTING.md`); co-owner of `explainers/`. | +| yakew7 | **Yash Kewlani** - [@yakew7](https://github.com/yakew7) | Creator and maintainer. Author of the seven audits, the `faircode` library and benchmark harness, the Open Dataset Profiler, the website, and the bulk of the 61 explainers. Code owner for `faircode/`, `paper/`, every `audit.yaml`, and project policy (`CLAUDE.md`, `CONTRIBUTING.md`); co-owner of `explainers/`. | Contact: [yashkewlani2020@gmail.com](mailto:yashkewlani2020@gmail.com) · [@thefaircodeproject](https://instagram.com/thefaircodeproject) diff --git a/METRICS.md b/METRICS.md index e135893..1b3a1c2 100644 --- a/METRICS.md +++ b/METRICS.md @@ -6,7 +6,7 @@ ![Contributors](https://img.shields.io/badge/Contributors-29-blue?style=flat-square) ![Forks](https://img.shields.io/badge/Forks-33-orange?style=flat-square) ![Watching](https://img.shields.io/badge/Watching-8-yellow?style=flat-square) -![Explainers](https://img.shields.io/badge/Explainers-60-blueviolet?style=flat-square) +![Explainers](https://img.shields.io/badge/Explainers-61-blueviolet?style=flat-square) ![Countries](https://img.shields.io/badge/Countries-20-informational?style=flat-square) ![Updated](https://img.shields.io/badge/Updated-Weekly-lightgrey?style=flat-square) diff --git a/README.md b/README.md index b0fe3b6..2e04b4a 100644 --- a/README.md +++ b/README.md @@ -781,10 +781,10 @@ features = [ ## Explainers -60 short, plain-language write-ups of individual fairness concepts, each with runnable detection code. The healthcare-focused ones are called out above in [Healthcare AI Bias Focus](#healthcare-ai-bias-focus). +61 short, plain-language write-ups of individual fairness concepts, each with runnable detection code. The healthcare-focused ones are called out above in [Healthcare AI Bias Focus](#healthcare-ai-bias-focus).
-Show all 60 explainers → +Show all 61 explainers → | Explainer | What it covers | |-----------|----------------| @@ -1205,7 +1205,7 @@ The full public roadmap - with phases, completion status, and content schedule - | Combined Social Reach (Instagram + LinkedIn) | 30K+ | | Countries Reached (Website Visitors) | 20 | | Code Audits Published | 7 | -| Explainers Published | 60 | +| Explainers Published | 61 | Tracked weekly in [METRICS.md](METRICS.md). diff --git a/ROADMAP.md b/ROADMAP.md index 1359c12..c63f8a8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -44,7 +44,7 @@ Fair Code is an open-source responsible AI platform explaining algorithmic bias, ## Phase 1 - Bias Glossary and Beginner Explainers ✅ -**Status: Foundational library complete - 60 explainers published, expanding toward a 60+ library** +**Status: Foundational library complete - 61 explainers published, expanding toward a 60+ library** Build the foundational vocabulary and explain core fairness concepts clearly enough for a non-technical reader. diff --git a/assets/explainers-data.js b/assets/explainers-data.js index 987f97d..0da1dd9 100644 --- a/assets/explainers-data.js +++ b/assets/explainers-data.js @@ -608,5 +608,15 @@ window.FAIR_CODE_EXPLAINERS = [ "data", "metrics" ] + }, + { + "slug": "reject-option-classification", + "title": "What Is Reject Option Classification?", + "subtitle": "Flip the model's least-confident predictions toward the group history treated worst.", + "summary": "Learn how Reject Option Classification (Kamiran, Karim & Zhang, 2012) post-processes a model by reassigning labels only inside a low-confidence band near the decision boundary, and why the band's width - a free parameter with no principled default - decides whether the fairness gap shrinks, holds, or reverses. Worked on the COMPAS baseline logistic regression: a +-0.10 band flips 651 of 3,254 predictions and halves the gap, while a +-0.15 band overcorrects it to -70 pp and collapses accuracy.", + "tags": [ + "metrics", + "detection" + ] } ]; diff --git a/assets/explainers-data.json b/assets/explainers-data.json index fab4ce2..18b6cee 100644 --- a/assets/explainers-data.json +++ b/assets/explainers-data.json @@ -418,6 +418,13 @@ "subtitle": "The accuracy cost of a privacy guarantee falls hardest on underrepresented groups.", "summary": "Learn how DP-SGD's gradient clipping and noise addition disproportionately degrade accuracy for minority subgroups, so adding a privacy guarantee to a bias-mitigation pipeline is not free. Illustrative example from Bagdasaryan, Poursaeed and Shmatikov (NeurIPS 2019), plus a runnable DP-SGD noise-injection toy; this repo trains no DP model, so no frozen numbers are quoted.", "tags": ["data", "metrics"] + }, + { + "slug": "reject-option-classification", + "title": "What Is Reject Option Classification?", + "subtitle": "Flip the model's least-confident predictions toward the group history treated worst.", + "summary": "Learn how Reject Option Classification (Kamiran, Karim & Zhang, 2012) post-processes a model by reassigning labels only inside a low-confidence band near the decision boundary, and why the band's width - a free parameter with no principled default - decides whether the fairness gap shrinks, holds, or reverses. Worked on the COMPAS baseline logistic regression: a +-0.10 band flips 651 of 3,254 predictions and halves the gap, while a +-0.15 band overcorrects it to -70 pp and collapses accuracy.", + "tags": ["metrics", "detection"] } ] diff --git a/assets/og-light/reject-option-classification.png b/assets/og-light/reject-option-classification.png new file mode 100644 index 0000000000000000000000000000000000000000..ad8fdea52bebedc2df9cbee4acd83972c418c5c8 GIT binary patch literal 64528 zcmdSBbx>CA*EVb+2+|4y0uq9>bc4c0N=P?|bW1nrEl7h%x6+MtgVJ5nDJ|Vy-@^O( zecvDNJTvbf&&>C}dzj%GV()XGd!6e%)^Qwb`@NPCLq{ba6Px`a4F{>F_v-*4Qw z<$!Vve)5BS9qq=Avk?izOGT&g^(jY9+_59hZQNVp_^%Q4@82LHx&ACVtUH{pHq)^m zDb1^O9P!suc|bSny7lm-9M<=*1Fq;#+xJ@CVvJa5q@H};+}iWlAnoEJu(bTN9$$Hs zNFn(um>ezy$8o(Frq;h7-@nKD_X8Hz^(f%DCG_w27cWr${eXgU^WP6Q$^QNR~MqNSB8NUVKX`V2xHv1fn$fOxIY>xMq@tn{*%2iX^l)2UXdfxi zF)}bRGSpYhQO+|P$>(=DWPAR+?_}$XIHiDqfX~&%QA2Y;#lInoLg6Kt70I9>;C^U+ ze!SCVh>jmsyxha@xij~((Wg~5K2x=j9J_sS7e`bS>GEM=VIiDRT3XuuaD6O+*U|10 zPhMU=T`FdG;&_MMY%*m% zIX@WD;W^Rz^y!mQwqj_feh4W)d9sWB+T8B#>q|cg#JXI+b$;R3*54l*beAB4P9$p=@Ga2R3$gVh%T_+S3F3(e>!)=>8N@5d?x>qb?r)#eQ{=MyHN% z56|vkt*g7c+J24W?Si;rG2?$d^#+vL-mRe=6~w~QQu?{960J(GUofLwGU9_QBaR=3 z<#_5I2i%>BLWal1X{oReM*Zb!&hAZiP0c#@v!&I!7jfDWEG6R6Q=96 zZG=xkB7OmW72SmeaGY;q`k^<6_e)YYm#jI zs8i=QR_uCIY}5eFmfPlck!9giUNslFcSPmCUGELsfYD*zQ z<|!5BXYs*0t!e^RBRoSSs{eW*SecKO0|eYp?L4L%_!f<~;YwQ7c7FcB0_%(RN7J=; z(Fp?y_+2JP3&}%$iO?m}26pCKhb%`(R~4rIFXh*3r@4esPoAVO=$< zCqY48{*vGAxTQNzAzenR#JIo8er+(}!w zY}H@&L<`iq9&N6T6c~Nlg3Cn4#u7e$+!ZHMX|XmuIXSt9&j{E5$9Le@K*d#+QEy^+ z_=6c%qgW0LNrXvOmVB1oaITu?`N?uPjRISJDQjIFLa|6+V)}E6;Y69GR>?cvy`^qW z^U1c78tFKW`t#k+x?0!Uw{G33Q;^qrN6yDrqccD`l$gEVPFWWh)W!IlXgnsVXQa z5T`t4XSy-(9~gN5-aWEpsF@qD#vWlEgFGa?Rir?p`QCMG8B zcJ%HoMeZk3($Wdr6INqmV-sZ-depw6BBD5Q4h|fQtbfOU$4k)eMO%1ch_CPQUWlMR zON>ouEu=MXG`vRy1bLdJlCoP@n5&`)QCc4fA52mbZqx8eZzSwm43sD2N8_bqp8QK2 z{KkDx=;-LkUG|pHu`8=89`n6>vsLGg&^I-8IT&ZRNB4MlC9o%q+bp?H*wos}q*dhQ zYuFX7YiinYL2a0@km7?`>XOlchH{lCc-82GNvD!Gmv2&Id&G!6bh#tH`*)boh{R0AC!KbkVrbIzZmm?W^JWLXn zJ5dDx1_kRh5<2W<(u}yF)q3*!{kt z6k{Z9Jw4hL@5rzr)bnf>J1PeLju>|6{S*vLmKZJHOpyS*&WLnG$D)m_tStHJP&Fqj zS~%AbO>`jrWK>0Ubuk@|P7RFlI&UqT@^Eo=C2)qE6(9zSlydwZ(xIB{MKS64wzaoQ z{C4GYp1TwFr36x1$5m|nmxl8<#>UUK6L#^irt3Wg>FK)$2EOon%E>G zz~V5;rD^!@pilxNr$V(9H%V(;4C@N=j9w@D-oJm}bg9`2ut*1m*U{$m#rEuN?1S~O zFvm}D5oTex$*4aoD}{R2Oxksn$u99vItB;B(J^$Eki6U#7r)E-5p*c19lU%>)t*sX zTl?|j$K865^X(752=dUhw6q_N>gC$}n;u&!Vt#+3A{kByBifueK#d~}g z85uV;A%QsTJKKz7c1DIuTo^GmHTCjrqYq;6yKW=I?Ah`0@#%4i*@$IxM?{0L^50pz zVWo1=xKF&8EE1K;7{{4GN z2^+cTSFSdyP;m$I85w^h>Qs3e&Jw*ylt?C>>EYo>_lVHY{;TAyD5e-v9=r8tHDhog z$dcUL+=Rj0u1iuA4jWQZQaCs`(fk;}!5u!=GfYPp;2XWueyiperZcOIY$Bgpttk5R ziF570)sz=~ilFa)G^IT4vx4=hiSjN?h~D|lBObR3$q3pSR(kakUjlo|9-N;p&Nr7K z1#wzUccI~ThSQ`}-sJ02>{?jRw?_s*0Z;cc!Giw0D4LRj6q8nsI3i6l!gQprcFD1W z(NF)Q(NaQ7Ycn&oO7LAj(AHyb5V8# zjN|J1dVFZ;OGH<$V&V-?PYn%?MIrpZV*|V;_J~YMvAimTj)6VG7pAwOm=vEuo$c*H zTW^veZfIVfg&Hp}d6nmucC-J(7``;b100+N{W}JtC=}%6LPA2L3ygrl#U&-llc`8Z z)Y+>Ia+DGKrw3+PirMD{etv$fA;e~r70ksefBv+2>BCr$Hm2ed5-hB&1WgB@b#Ike zB?(BCwg9GKEu6b>JzC$`2nq^{ndDemSurON=6IxC?2z}P!~efh!#CAM$)aL;*1^TA z1r~a_fBfE!@>e@-NJ@!6;(GVSSRBQg_Qm>Cbvc0DCIWH_ataCxBO@d7@$ViN+t?JN zKVOvnMubsGmzY-i_=tIv@4jnR$Cxm-%QW_M%e%n=k)}iiucbo&mT6 z$O7O~C0F&Qp{mk}jG)KybBD=_&wa1SZMt67RY8^yPT;|&R_TVpKZxDw6?{miczhLO zzOeh=VvX_8^vq@oN7ME1@V!!5s&;LzkRr}zkdREAhJw~cs7Y%@5u4c^BJY@=KBL5G zuP(RBQO+r|+L{(d#!TdMmY0Y?JA-O!+GtwbV`ug>&#Y9;l)A{ZJ-CkpB2x;%} zsmJ-T^+7EARs9%~4o;};Vh0BY$G8^V=_$a^L>7Y%K+v)5W-SR}C%=Dw)SI4$ie*y7 z?;|p%$I0&EuMF9V5{u4txcPVvds9oxP5%hGHS68h?^|p?W@btayWIhWO%^tujWXZ9 z{c$~)p8WK55p7Rqrrxt&Z&`+lhrRr}xU_^?wSz@Owh|OMk4Z`EA-^FXZ6zJ<==MH7 z*#DWam*MwkEvU1n_HLwI_CITQf2ZT->=8CDuI*@NzzO&B=ilADQO%cR4Z365_1-4l zynPpd2*kj~Sannk#j1Mo5^R~tDJi@Te_kLuRdRnvBI`$PNKk%ZOyGr(COtS@l4;hz zC4|Y~gG^vCUX~!}d6})0lYVu17SCyhc5M?#s-_8b0~fIP&PXVd?431K!M=C}U1>%g@ihdGn^6oE$N) z9hM(rjnn+ibOI!<^|9jR?gSzNg0YPeoxI%KFJHcNjE--P6=&$Te_4+y#<_}GS4_=N zNlty5|Kji6Gs>ykJaGB;#`Ia_Yw92hui4qz#!nbQ!NE%#Oj=d@EkQ(UoW@^w6){Qp zR4d-R6cTD+0+70#s|Mw3O3k;j7*<0*r|lm-J(hD#ep6MB)XljJ0JL3+9*ut0ZLG9i zwm~a}DxV`$M~5nGW4buQpbAqeF2w!*iIm^N=Qh+ZUn_h>Ez^HjK_a6RrQ5v zBQ__hk09{j_fI9mji-~FGv!h`ASJr>01{->{QiWIv8S;H=I+9O+euCXvPzB z`^eGGE}q9iJ&wadoLM6)BV!r3vxL{~Q=sOAnEpLAmgxWabld+1E%cu$`=6bu{}Gb1Bt3-j zjeFH^-0${z9iA+ubTfuC_Z(O^hxUAI(~IIra>~LT3R*4il1>w?m#Qo}XQPv7S+p6G zyLj%u==-KM>4`%`5M`G=H);D`t2lDJjBjc?|P2S3jq#huFt;vLDD=fI)kii`i|;Kwib0J*6=5U%I@?Z}vv^UfBH<%fY{UQGK>DSN~Q=pj$>Fa&bv=POq^b zv7Xf#F;~rb6>zt>n6xM6)M4f@9P^vJM7rXam~*m)jk=AHC7B2VqZ~dX85eb-uk|yZ z7MVsEPMig)CO(m*nGTVWt65rZ&t7@!&Z_jX_P@!BEwvzGYhNzr@;v3$CaR1f=$9p3 z{Vt5^7W5Y<0q1jt(b~g5ncg+;r|vrSg`ST3{8t+RrmPv=&dKExPrkv+qe zNICLXe_#)+=USB))Q?xh`~HKmVe@BDE0y}0vaHkD=|$)TLSM6`?B{tz`Xa3xkLT&s zhlBxoznPZBJV)ZE$)9nrsP3HNhQd>2ZZ4HU^1-x!&2d8R?m9 z&Bp{+Ogmy$k=UpA>Ro0J4i6Cfn_n}8Gd9T!Rh{(goGh^V%d1D&LzeEH(4#v4=iaeY z$7m$lb+`Q5%5)VB)eUX_oUMm1G{h^It2WfR;}?c9V;f{pW{9~xJZ``=3WkdD5yy0q zr2TD$V%iIzh+Iu+N<5gJ0xC72ORGb7X$bpgjr$wXU~qRr^p`T`|6OU~~%#&Tb{ zzj~!T#Ld@#`jq8nV39ogRLpO(m5b{5{gR}ky=>+=PD5X&^Hn56HYM1{^p2grB_a9M zb(ZSBF=WIENE=g=3)y-oQjSvppCP@|`)<^QnYK1qo;CHJSMK`{{jo8fe4TJf7QeQ> zhJn#xnYNrFoO#;;`Isbh28OWjO<3LTGMajy)ON2dEzGbT1|8i;v;;|Rs-Jr5kO3_d~zrnGRqpM?rbCY4a9f3yrRb0R3p--8YTDlp*pAvYo zx7F?w=Pce5($Xec^fbXg+coLhYb6vl_IAVbuKYWX@1F~yEPs5m)a&IK5S=iSP6It6x}EWL)UwW!oh@JNWudac09h z5U{E6>b^@O;v+L4jEJ`J3lOHBpbEW3E!wL}Tn&whp%zHl3@je57kd zrPPV#J6I%GFz%$2GYm6P4{thTNFtR{-~|E4M|ClMqzDSY}iqpw!4zu6-j zZu_^R(0&fJr-2N=w7i~5>ELN7Rl>#_a1x_M-`Z&(lW<-yU5tvcI`WKaTPC?v44W!l z2|0-EIXmlf_8cDL)H**CYe zG?2iWdN=~noFot}X`Ob}`=3t=<_iP5>RV3g^_QQTc79VRzY<}J>Mbga$C9FbMegsp z=Rb8~J{JF~c48`ynURjUE>+Cest*X%TKQ zDP*oH#2B%Znub^8{r{x}EbOOuky&0%(dSfS8Oh;=`Lb|Q@G~D<{OmEe)bXPUh)Rgv zJ!mnQWwKkHjtYABMd%+$EDbWm5~%mSEG{jjriXv0eTox6XTQDeihm~X8 zbB(Z4Qxp+gf2f=&^q^5uHX^Fkc06^&i$C{ zRJW*sWusk2`X2u!6RU2~>1Sp{YDR&M#rCs$^iID&wMQ?{FzR$81F9CnU3;X{I@LDOk>K?2C1O>utyTDcT4sK2+SJT4A^T%)~Z=YCOd*h>O+YeD@bAs%7& zCLfgh6GirBuV42SXULKQr?GN`F z$0u5wn@v!*CBvV|0rlswF%k7l?jPS(PUGLp%lL$Zv|;Vxn2bu<;bz^j4C*CV0nHoZ zrM#|(=KA`SM~X5%Js5|F=!9%Q8Ej0H3&zEqY)o)YOVHEP!wGi|HzrOGRZ}dzStCpK!d^*X?{k+`@JP-HC@wJ z<0BSC$WF*?qYu1Tv{fol9lVa4>r=(8y}eu8vyG0MlVfG>t`W3KmpQc`sIOIG$QlW+ zUcIUYWu@aG9VN~^$NEa|W}sPk>{s>m^_yHJjE#-!>)cscSu1%}ay7?N#4tm}5%DzI z6k>r8ANOpD%5~>O&CJZEvlz82p4%=-aU^Qi8cM?mcpUz0FLvVFqia{1Dus~nZ~weU z7S=wEjOXMO>5#$s>a|+Pqsb%6v=c05ff}|uQoEMiJ=UdQq zbY|Aq%?*vzc&kBq_n7Hh`~BfIm=@+X%y&AO5)%_E9%Q|+Mey_Um!I!p?j5&-{5!V0 z2u}^<8Q*JbgVXOD*lOzPBz$(6pw(a1VzhU35OSD5I&1pi+w_(>kqc(x$& zwIZ)-Bl!1P*CS=eb5d3#?cZG!^h()-7s#05m_$5wfA)-eX%#bn&#&dMY=7=tWY^L% zV2OcYjD%7Ev6WtfJj=|?46-q|-S%$~8Y`J9Z4R<)YxxCO^4QG#p0KkYT#3;zs5@G1Ykn99 zhr=ZZefiq89p=ips@9;>J)~0}#NwBU;X47Y387f$b`q8$12=rxdU{9pG29%AnrJ|< z*st^&{sXq2F1vSjl+7ZaI$9B;qNlZP5{LjiCS}h14`B`QU2csOkP@NefMO6@Tk8%q z6tzq&!oOG^8~w}StM5*Y^%ti{S35-9dP`F1{ZFvR#>Zh=+lGcB_#4li_nbm7{Xtp& zvfBeR@I30EvZ3J;Xm^$UUtx9#0eIv1A@-JfM@B}dldWdz@-z$Q>PHxWrBj|JXpV`* zybeirFC;@Fqt=NOK85fc;M^vqBh>gY9&}R@sON_gCmj8z`x@* z`9mwm)#1EXSKk(20FNpwAwfotEr*L4Lhj=D^5silznUb@e}Upcn#buB#Ky*E{^X5y zI8c47LpjxsTRrrg5t3>34wz7?_Ej*ar<9-Um zUmYE$z0@85-mf)eog+qZ9ZbpmniVU^{> zZWJ>9jl4CtL5vI`<)y;$13Hs8i}V3x-e=h8BrFK64yVn32s*4Lcb9F>M++g+i{f_f z-4n43yVzZPwP^^e*5ij%V2$W-w$iINo3EEUA~Z@Z-7m)34Otl(H-B7SC}c>}U6wz0 z>52xQfXx*iA)9d@$cdUc>M_8eUYs3``QWb&7vKxfTocbyFT@emeEj8>6NfshEmzyP z*M5(N@P1NqyWx?M$MYs!(L@p~4(p?2q2dtquR)Emr{;zJaemzO3Qh8ba|*kPIF8ixp`NRLCwlt9As>n}BV8jo%*6-fLoW(&P^&z||l$^Gi@ zmusWVy5$=f80hbR`cn+WIS71Q>LPgt9oOa@{a3HC`q$pySeU!2%vbV5?2hEBt&aqY zQ>qu)ncPe!Miy)J^+j1)hG@nh;p3W#T3A?!7xWaEo8WZ6{n4;Hw$Q}igTpWfT_7wPP0h#ECyQ$;=OR~{Bde$OYYmN! zW8EOBZr}AlqBS$?ygZk*CMn`EQ!Ws2JAS^m7rZe6s=CSp2|xc0S(57=U3{{^)+^+ z?H0YQolq!?!wh9Cm8C$ZzRqJq-4ExfN8Iz5jh&90qc0I)VjGSZ+y+T_ z^6fn&BId88Hgdyz%f0oTD7pze_8#Z&zuyQIbYvmHHeq~&A~;@JWw#=~`S<{wch_#Q zHyJE)=YIsFy9jNYg@fHf!8lndZG+&gKE}<`igE(1oXn;0-fF|JyTPd zNTmn$oij5@M59;HChE>XC8ec94iS29-aN6A4O$)A!M{+@%wdT!2aC=mKOiQi?d>Pn z26O_1z9Avh7OM&2Oicxs*p~~}^reJ>e-6gCxAHOIlF3r6(!FpYhiy8#igvGS>I$|& zKVvtKk2f0VutY^gNw{qm4)Zi%pJire&(kQF_PU2_hjXHDWHeLbyw`HD2I3Cv!{niD zfWaW@8^r>jsTEP$N-63uq)LPZ1_fcdI%kXiM4cUs?rriju01Dw1QTK z@0e4QlTP#0tJ4RttCLLDlWw2dyJ>2wtH%OL1z{6_9DtnhQnQQ+%>wTvrqd?{!Q2m@ zNzk~Cc(jZh{rrfWB;YP7Bf|m1d;LuaW)m5mB$r#@9vT|2)AsM$YRCEcc?)y%@e&hO zgN_G#Li$f>-n~-%qycHG&Ur6=rZWo0ucoGkhldv&K|2IKA=h%t9!Xh!|0{JsCzj&k zD2}~-x{au|+>5k#y(HpSzS5p87rwQ4K}wqR`}c3iYmf#&_bya5H!x7DvNPf2EWe9R z!~yB8&0K%VVSc$c>1b=had~sFM4pX_;+ptVX>8&byRsl$10y zfU1(g0T2|&wlZCNjUh{T9+o?U;8gFh#^G`9)V-o>Yhwc#@Ev%XuFa)JM!Y;chnv5Q zwtxQ=Vdj7`_5J(TXmdh=SOE6Q%qBQkSOz91-3I^khtI73OqY%WlUMP!pQw$E4M=w2 z^t)NM@IqO6_`qyrbGowF>}XTeTYLgQ0N6fYP5xZSe-O|N*N=&b`T6&lo}R8gTDP{h zhuvHuUCJ5!eIM_li|Z{3vnnW%f9YHVvs{mo)M%sPL%nK6S=j<1Z`8=h$keqt4=JAn{c%;|I)!fM*Y;mPl zGafyYl{I5i&2D)la&Ce0kQ0O$ZM)mre!H`qaE+e*>4y*seR~i9KAvl5Fs+g#Js$Pb zr{G70uB|usQ9}*FD|??L-@J`%+BQn^;DH@HFY?ok@) zhwEau)f0F!S>tTG6i5Jm1-;h5G1w5BUqwyVI13Yom5z>$5g!~Ha$Xz2EH~60ilGt~ ztF2|%*JqHDTHD%^{RjU#HhbbYw+5O6-WED_jTVCYfI%Vs{;!zjo&=3La{^l{Vj`k5 zP)X}u4osm;5b1AoQODQ>Q(z<~!)x&s?%^zj4COq{n8-+QsdC!==?hH}W&XJUHEZ?T z6B{a_VrWHRzxWondw5k)|FowBe_~RWORWt zRdQ5e-3h!$fdvJ-f=I__V8*W1YYiTE2re%_T2;z{3h`GU$j|mG<3mkNUcTCVo&r#M zg2N<<%i}yEDJd!{YDvx#y}KF^!tvLytCGLU7Hv+_gNVRg!4TD{BvAjS@7u@iWnxJ8 zfb{pZiUYr7U!@Q|dIZifuiYGeRj?+X61M&le^KbQy}kYNHZnMz%Ups8p~7OiI6oxi z`avA#7Z~VvxNmav^k-{phG)Hp6x(Q1(5)-`#3~IIeVh9F)>Qr)%eu9wl3vX6D?B;U_bxB*#X4`zdwubvOS9}5D<&7s#2f@_35*-XQm6j*hanaGy{SsV1mxRUoJjWQT4e#oPgDkUc1EC z?=JXS?REyz>Ml;1p@tjE(Yg8_g&!6~LrJMWkSekIcI6*-+3P@HH5$p+0_#BZ;n`OC z)}-_Hwr;UucSY+l>L#?~03)_PHG(CnXn^=LnTF=NmbDHZlrHrB&QSw}nLt6wSB&Z%*i*Y2)5(NCJ;#p*tJY7(=j0u2ZIAd}_8~T7y73s)*TvKq><`x!td3noS37z~) zDTgzo@Vrn^R$TMQ^hsFv_Ww*Luwh_=M-3l83Ven5hC4*Iw=cjMpUCeDDd|gG?R(C= z@bcJaI#5hb7rOHb>ffxmES=D-}Fl&uou+62Prwb9CKtF?8qtb3+4zAY$G_ z087_i<0?QkfEyMY?{gI*goJKsa6F-*F#);@!De-N&TYFC{;x-qL8EM;ZdgjSCq$^s zYZ=lPF16HWaY`sC!Jz`)6-9xT>FLC{kW|Aw^_eww_x(R|*>glDQ|Z#PvP2IbreR@4 zK6@Ge^9t63IOP{^+vUXice?$_A~ho%T~-W|D?2wq>r6f0DDwIO3A}bK}BnbT)7Jc@2K>yZ)EwqUILs?lFeUK^J z&)1jB^^hK_3Dw?dliJxyp_u6CcU!yo=NCtCk8w^;^jc+soOn%??`c$-t2V$$CflT? zsi|C`mcsZO+Yce?Pk`^0@zd#OlbAEo!OpIWlUIcKj+aOWT zDj}Uu-W#Yveg@I->{H}BZ!a&YL^i+n{QZ&jG0W8y3>waQRxed1Q~;{se8y- z-elTjw%YnAUkjjF0*@mJyXk`?GqFXV=mJL~4toF3`&ZmciPrtQFV@ocX)XTFMY7udfRpalt`Cp`e>&ObUG1rKUrYji3AB zPXN9Z7uy07^qyQRRuhhq?_ZB`cXR7W;DyL6*KNGJsB@%TNTTI@lXEd#h0qo1>25LCZuy)fMP?L-$$3wypw1%}K-#d0TVRd5;6I!)B=KA?D4w`-zMN#ST zfKW;ar4W6GD;`Y3x&%Br&h9v5M(uispcCi5-#>|Y?690dS$pxx$;pFB1uZQs_+5J* zZ-U?XIJ8<#`UP1Ngg+evgT-#D1k5#J5Nes1@n1yN00S@FX=g^)@m_bWF^}#nDVE z*P`|WTA(k+`i$pJ1CoPnOCZ4s9tr?#1JAl2&Us5qK$gT*w;P5_NJ;`d5~)b5RcRVw z6N9TQ`5pD2`a&q_u(0r2!{xef&Ym4@IlG!>)<=W{1n|0_vSGuG%Cwy_+6!v{-~?m^ z4C*wTBs{|y$Uo#ecd(W}xYR{3jB3P;6&n?|Gr-22!o4UAS-~nXdi(w7^4Ls=S(bIQ zBwG!rZ0xNh$wTkdx{5jL-6HI1uhq)Q3V8o{L_AbH+^WbGYDwGW9zZ(jX=%)^z_CQq ztL?UudZL^JL8r@jwGrl-16vI(71a`;-gQGz1)|j)q(c2>sHC2=vd)+J^QL!)yV0*k zzGG1R{@%~K>FrK~HyZm@L?MNuI>VE}jndQ24UOqZnd$h(e`dWG5sK;;zDJ$-OsH5` z(A!}n)-ULGjD?Gv(r9@O&=K?upwB9G>!qk%^SBb*(I?p4iY+E9LeIWj-oCqVmTj}x zX*;83Y@8`{!|nK;p&?a)Gqeu4UTCPPMfCEvCwrsm>FJ#vu8qhjoxawdX5u97=7sbQ zA5BxPkudCa3bDAS-X zVKPe%%KN41qOjBE&k9tshAC*Ajz`)jPwSSa?9^3Nxw6!c(oQ#D7tZ)w-Xs&G3ptIO zf_6HNN0-~PA3q`ATzCHt-g}uM>0LsasLq%nyHpRUEU0YaI4$0;C015elL}f3z4_n+ zZg*$fBOK!inTF#P>H0 zvd=OZfpu;>|CApJ3tyhX3Ie>0-5*`3hm=k>+j8%1VYC{${mNW3cyHkxmQe1e8WNH@ zD!frT_2jTJT%PwsB%kapFY|tC*Kkn;?=4wlBH{rqZes$OiK%HenSc76`itl;iC;{i z;v@oYnT%^8Fxjf~k&nl&AGiST>?rRl%cBdKQRI zC0i)m^hT_MNLZ<6JifoVEp(8iC#RFsal&nn^X@LK4588RdKMoG8(VnXKuc2-!l@S5 zwwYSGraj(!r3HkS=GIog!=swaG@Y+DjLLxfqaY6QHq8BI0fRi4+7$|IM4woC8fny8LO;+zO2--#T{9 zXs@DV5m3wkR(b|Ce{Ukc#OR$KFRwce#ipgEKxE+f>35HpBG@2t+UwDTJh&}nDJdmi z&$b5bY1dDa-`k6)_uU{m zvSG)fqgWZ*HUAN^Qg0k*FN7>y8ninoSvg;pL!I&w8GUuQmbW1J#$wc$eUKQ|iDI&> z{a2u#s0d321ymcTbn@Mu9qfQ+Amx{duY`8K^u-g3Q8VZQZVg~S8LN^eBBLmeeEJF} zw9?!A)5m~)^~LVzl*vHRY_B>z=rZd`wO%S&O~1D-z{2V1IICtW{eabtDyQJaHw#YK zN^$yMq&@vQe%A}QksRgxg-wD?Yc(30$go9AkKa}6`tFju-bj{)N>07;Uwkjpr_dmZ!pg!D?e>k2_DTneFpuMHU2;Np)9@cxWA%#c zI(E>BC>I(EOGK#>%iDKgV4$Kr+Qr4?#PBn9GVmeARtofZve8`3Gg0Dc@*D;_WUL*7 zG(~|dpo&h0^aArCToeh+>>70a>|D)@g+Tv9Zhl!ckjj#hl67bcsD0wv)M5z4=K(}3 znXpe8a2rs}j$blDS~u(_oD1jddz}Dg=X|x=SXbTNIKd=eAfKUf1-9Fah=_;`-=e?N z>mf05x3nqCTWGzi{V7FYZ*M>Jyhtl`WED6PCnRb+7PbeVf6?76(3LU&iH9XWZDa7^ z>CMvB7GThPFi9#ZtLdUhoWB{^3#-)02Ox#Vvsyz{WKp=ZsAv)XQjoU(N) zj9RwhsOW8>>T&IQ&YUE3hlZD0jxvM2L961YfLEaGCE|45^{UF|p3Pv>vHSh?09s{D{-8DBfyrwR0fvar6_S8;Q^-(pq<+>_5^44hK$2jq8kGOui zuuiRwx9=%Up33?832V7#90b^>b{`&-d)CU!MQesoD=>aH_Q}b~QKcV_Z%Tve$P)8= zj2D`xy7noaAtHavb0fAQ5nH`Drr7d^pt`k1==GBFW;Ql z@_0$_f{+C};S6VIrXnqWsw!$c*RLPqG&*PsoNlArvnPfjiW*<)v}^fY4?*F!Tb)!B zHYsgY@4=5~*XMOyf6}AhRyf~s&tw{E^NKj|BH$hm7Zn#fa}Q5>y#KNv2t6X!oVd8S z&?JzvD^9hF^`%c}LKK8D>!1H1_4M=rHx29okcFVdpV|)RDrCq)R|9T8(7G;%e}1Os zJcYgnfY06Ts$Wlp=CmJO*9?0`gZWx#y=uiCa=Dl?h+giHhrXFI2|TOmNUPaT!^>Sh zYuu5Y`dwK>$jFFE%1@XcU6#sKFw`p zg>0xha-@vN*2WgH@stwH9-h_nVmNIqK7*js_IrGrBWMjiuAWDCDjNGzR9pn>>R_#) z-txA+>weN2&nKdekqLfd@=e{}!_vS0^d=R?3 z1NuD>`<$$-MD$-ZxfZ2k=a%l#tK`S4(jN-A0O@K4?FWR~$Ksu1Vn7lvQ=wT**HnHc zG?vc_XLy{k;noj?>83iDn3&jN2LTWG1iv@T3e!ee zYxR5RD$X3x%ra*eM^{tK%L`peoU*o5@&+o5I!nQCj34EC935Uag^Y=jL2lJ3e2a8e za6rWNTX~N0g(!hmsn_mZBFJu|-5j@Q-M-9;ZvmrL?{?8KF~6{o`cdq@f1@?f@2jE< z+Rs|H;pG6>UqYj~gdI{*w-Y7ba_pa-|?dm+TuAZLhIz41; zc8l@-fyK@mZgEg{sHu$r9V0-^A05{O|Bf*{x6v2j&;b&klHFOFYm0lBC?{IZ0KI)=GJb8Q|Ags#9GS5*GNEA*y^a8x@bfarnJyVz zk4J!&wI`hkXz0T4?wB*IB`3FkDrz?rRP#b*&rwERe&Bj{bPaDUVGn?|8B0Pss)P>5 zOu?t@LnE!NeSPmzvooj_`?#-JLll(yR+Mk@FP!$a`4*`=R7=1aOw#r~eH96kXzAxA z;`zxwvjjO&C2|4UQ&cZl#ds$S8I;Mh6r$TUBKigf-O&OG8rlVa2qCLWqnpKp-HOik z%Yo0QPj{i{_=he+a9NSdcp%lULyi#qD)8zYsmz6*iqoXnT6~A8vrf^b_ z+#ZeIe&Wl~){L!f32M!I&(CJ;+RR_&RcK$+m0M0PY?x$ugi?A&rf}TU1&L>?x<^~O znK;2t&&B1`wa1p=_U+r2|!)m3&T!Nb9p*2eM2h3KRpgm6l zqeQo?P2O{QOWTxDKODd+&~@_#WS}*SmYU&Xmzw zdFrJD@seH|maoKZZt3*&p<>%_j7LP7Xk9Bp0L{bR%AY~+sN4rpE&uP7?jJ-2A@-E% zb$W>8PJqxGc>2meCG;fd&p4fooHFAZ@ztC{6A}i$pr8b1y_Wc~;+S=MP>*O;k6BBXxlxUOfRj*LxFjGgXsuW^qLV0q=tuTvgt(c=Hv(oWu(+1*kIB zcEtsV)U9k}Zk~H0aSlXY#q9^Mh92PD0NK@+mB*9_YqtdzV$c8CMs|OKF z$Fi-ggi+T#F#;+NvhTBVS|;?Mt|N}9s5Ut*rTg;gDlJ-fY48H*6f;5JOX7ER02c<@ zaxd#hoS&Zryso4*h*U?NdHsQ1JtKWeprr<&qFY=KN4vYbJG1>I#PJ(Hidg6E(oQ}6 zI^n!IUE3)=Bb4o*v6lM#4h@5cS>JcvP=^%dVhsfag-W#m@iSEBf(VlKp+Tp+5qbw8 zuJmVPGV46JW-Bi5n4!SloDdre@*8JN*s8)*cz+zHrI(kNZ}S{8p%MDMn({~CI-lgH z8<$|pOtep%bBJd9OR}oSZ)#G@#`~&B)v076d5J{IeH!rrCZTA=@I$03y>_{W`<8ZX zg$XM-GJ$?50=!Iani>|SP$xm}+&FSeg=4o$i#FmC1Z7D{R9>w-I6JtjLxEU>0sU$L*~ToN>lKfBg#M9@XyD#O}DM3t|Vj3#HWg&4;;k z6k)4a8ZX8AY)!@q)IlPDO#;XU@31xb@zbO_+jsB3=6p;YAzAq`XB^{Ol3XAkghm{@nX=u~u>e=JG{-AM zaBy&Jls+r_hlBUdN#>0GCFuIEl6tf>(ZWwO5o zP!%az_|lXufM8*GB}?<1L>P70T%+FN`)%N?!773W_6)Wqq^G(B1};aNdE7dgWn-&w zPA8GHz3vyn2!RY)F>Av#`RNo#GPP%Z;^d+4aD{L}T|<$)JiIYb{J`KT3ZjWlxh1jV z@+Wj6DCX0{(gcu zGh0daNOry`BV{EKvXzmtv)6fkyYBnk=bYbt*6(p1kK>Q4>v3J;`}us{pZELqdajp~ z+rnuyDusbXI5+5lKJ>j1_sE$$K|mw|!i(hR?c4)al2KX9aa}qGu}sXP0HBgr51(u4 zU7ayY{mCsgYHr&Ng{i!BPEX-yk^2|j+)C%FUx8v$^!B}mU#BncS25cF3kwbJO&-29MAwMgwx2|1j)#60 z!O=2uL0Vi+;?9pfuF7cmh4;UhJtEr<72V)XW|liMgCt853ar%7MP$ou{V3uIc^9W( zV`}VT4Cr}1XYCd*iFlq?1Q9QA9TlY;aOm+pR( zk&AvFz)?1Mm!$yxm7I)6tag2Ggxy-7UG(}VkM`PItLXMs0Q9z1o0*dD9(fd$TP|2S z)|GjV(LA{9)FyW?>u_Y2@jj{yv0UBjaSv!<2Cnc}P)nTnSTX4SiC)Ne;EjzuVfe+t zX6HQ-%#v=ckY$fZHxHL-Dsn~@f8mop@3t~GlAeBYO8A_88!OK)=OTCG;a|TL14nMR z-@WiNlWCq=ach0W5!pChqIHegFD6@wDN1E=(0qT1r)^T^Jofu@Mfs>9RHN_WUS~;O zbi)oVoTc@B>%-q2Wi9V`gd8gbkxKhpUzjV8l)Lmte8xs=)BEaP0D^upZ7e0!7G9Nk zcrDSf9@FiEPzy4Tjd|M(c$W(I?SWJVYYRt2$l8nwkiYGOFZDxT zE%sXNxQvG&Mfxl6TBR&M4>$G-h4yHwx#Z0U%`u)K@|{1e!YdKJqJ;<-TU%Q$^DS&X zI;#1ZDTU`hO9^rtjXh@WJ$uQYqNqc=~P1$|r ziQCVhmuf%39_QYELrkF{G2-9l8~Eubr2m)qALWfyK)Diu<#w3{0@Z5C^i2?d`;KxP zI&{css?Be%aUsmE_>GlT9<}OyLR*t+Aj9^A_ypmtK!nEtM8qRh=8AL(O6%_F;Z|0> zxvx3jR9xFJU38Z_BRle)9;i{8QSi1$A+tMWO}!bnGi8s@g#+p$|SUFBZiqrgW> zii&GeB+rK#FWw_Dx~I$%sQ}s9)bOyH{>FZjA=*98{nQ4`RZ1`Ct!_8<=++deN_KMb zy$ZGX;+4z&ln?du>o`apRadUa#Jm6O)q97NeYtiT!04!~0F*_VMV1=Wn)_ef=!>3C zas=ZBq_i=TyI#siP*|9)u2xIutm~kyCKyX7F3))T*2jH$E@{|4J<^Ex$=@=NC~bq% zQHMZP)zqXkI+}qshpMSj^q7fV(62EW!|Io*DYxx@2N1(z=I;_V8a{`ak89L!SY>7z*w``pO$=?+qk>Jl!TqMKI;L@Ltwv(RcBjyD?8wKHM^ z-Wt+LwC?1}3%kH>{w%VP z)2tMV!KuV<$I+9@lV2%oBqSurlx{QrnIgVI4+ZBI$CA7=CA5Kr+chL3fh!G{8(tcr z?kQ1CPsz^4rcZDSEgyq=MyP(B;G=Si&h_Uv;Vqw;p-asnGqwYjSBTsByRA@^&Ll&w zH=c356%-OWoM%?6Y-+r;ot2)ArAjN$?ONKKAEJ`!>#xc})hb)jB$%6+6x#GeRTO+w zAuP13%<~|It-rSnI>3qc3}B{&a_^C}1$tgR2(0+L+m1 zjgG}?{9pqUJ^7H*HGE=1==m}|ub*v1ND3JD@V~p?lS+>$Raxkg+ec_s9+O*^mhR#F z^>jKX1pDEW`5CgSC!3{=8#G)u7PJ;^PiWwX=incstJIq!m%+Ify$ff7RldrKJzW%IK zK=V>ujBh+JYCi3slKT2tK$UtWHa{gv-SY5yNY+L zKo#E>e(*l6swn6-d%+tFjEr-}%gEzdURmkLxb{Go=__&+h%^D7NSbEKbHVr z$nwY$oDp_Ac9eO1+jHoP$Lb$W(cD~v7rX2pzXvY|)hW1>7w##<#2b?1w8~McEXXiy zJ3XAX-c^1hYqy4^wQU>g0Mqsib;jkOIc0{e!F$$KC7qd;-+U_G6dT^k@Ss*e;r%XUXq6d4EzVK7ya?OY72hF!}N#Arh zp;q+FX_Me?UHBp|uj5>*`=>1EROBPQpIm=`|**mes~3t65s0%8^wu^yiYyhb~2QRV1yos>hn1N z&Gx#hbuKy7s*O=R-Lv_?7VkM)Fo4|mh|-et4;XDuGQ51=HkzK#U}p4XmL6mCnq{oG zBl}u!3Z#LFPXnZ~qe*g^WfAiB-eMB96%!M48t)2Ss)p68;N0btU$fMILYmw= zbOB15j4!DpTPBxhANmIc1&wZ}-ETnmMJMo+aB^}olq)87b^}Vc5=pUs5v(P6(ZbqV z(yZywP<;rvaOJ#X6&q815>w6jcuSu=XeM|*H>Ke)#OpDMcNE0l-8)O8Q+!!&ho)Jj z!Bt3^{TT-~i-zH9tYnOO&hl%Ocnd~K%G=*pomnQ*gl57(O0>u?KTk`m&)Q#nx2G6P zhS$a_t;3Hi;-mzBpC>sYREG{lCmKpom+2ij$ke#LZZ+iZ?-tzt<;y`a^N;`qZmH;i zz`zFD(^e6#<{;?3Zftou?*=v-!f^Hsm%wY=zBl*hxGC#(uVo&7PJ2rc31bbq9%bHJ zUgZ28U~-^?lqV*sVd1d~@35$I%u(yt{yI*`qmNN?nIFA!kB?x#ai*lb7TRs0u}#&b zP^wUQuex(k0@u(L^NWfO{QUWmJ6hGL@6chIlo`svYcqgE$EH{2A6kI6Z7?ijmT)#c zde79%Y;KoK0T~I>DoAch(5mooS-@(OC!)t zjHcOsF(K#pVF9P~QC5;(aR;K5Wu}y5y1yEbl-${o_I7nOL6eAtgpK;97znXXTn-+N z)EsN>{ho8t6Li_&h5M-1;QSLo_M|MKEU=6rS=`73I31$=MjXlzPUm1I*}o@6iT!)3 zc!lHIA_}J_o>M}*`%^YP#1$14;XA(hoVI%_h^sJ|~7G`966c4H&rCXybD*$_aYG=umJVM?v*7AHVOdL;4C z1@+Cx8K=!h?PrvX?o7$JmYTkQnoqA3S&~(#Y#0t5%GRmS(dYb!xb0kP_f5D{VK;4X z+>hK)(t8u)h*yrBuoJSGh$-sF>}(!6<1*FjK0bIsMD3gR;I?U&Q*E|C$fxr8!}NHG z>PM8>P`FDtjXztjer?+5GU7>lPP2(nSKuGw{7BPzqRv4I`V~U_mW4_MWxp& z79L_|u5g_;fDdMBvIhzp!kvYN{(b}Z)4r~A@bE!qkn-}S--8Ev*ailDNB|Om6lD^% z8KxkeQQ&~WdIg>|*e>4=c-PJh89je4EoAdeXvD*HF0Q2SIrNN`sn z*$>*`NT#gx8+GmvgBEWtl?qv;*_V-&*xwH>ps}UpaZpe>6g*x0H=`e%kS?^CH7?!^ ze2u4AcK7w2W=8h&D>~`Hsgwi&w1{G%F{=ed7lEo z@S0D((v*so2!|fm{A)UW(K+Ka$Ytv4>R<&yrsYGBYr=wpx|PO$Z#r9|`R`xhah&)e z@BDyS$}@V>@!GX7%o47nz)>5B9zj9jTmIcO*aHJB zU=FBOG{w8OhvTpNc+V^zAzU*2=RgtLqd1HWflOb@u|ySd(N>*#WHA;gYK?|oL+@F! zAMcgtXFPcDOQxx!GifE@b-Ygz+$`_w>WXglozcCkK%K8mz%4NN9E8Fm^~e!M1MqiQ zlkvB#Q%aA_p)O7FVjs%wD<>0|;Sv-qxU{yI?|u;e79?ikr-#O}GBn4EXna`Es(3S& zt510L6wmB2ni2M7fWvfiA1fSAz!gFWVLrIo57&(-=huWaFr)qzJC6T(*x)9 zwW+G1DL8PH|KdD<-R&GM(7SC(-s{IB6>y<%7Jf-^@dVyX-oVoP4Mvue9MQg&mJ1VK zx3fnTB%bql-&l1~8dRcT#T{YJE7pk+)W&HRqR)ePMu=WBSLH#Un8}AH^nnLdN}tw8 z<>(4m!7+H1|2Q30j&_-vI1krS-p8+BUDDFh{DsO=)L$5b&aBN~D0dvYdYlh|a=1FJ zjt%gL`klGD54NaKD;W7c@$%t(fwSqve7P&@Rq9w2lXPN?K*pIw8DY;@@MU8J4W#6_ zVE_HMxMReN3oKm7KefwcehNVzqLw2Rk3m@NtZq1*4ZJfe!j}8`gxdN+RWJm|a#o3! z_}$gj1y=d-A*pyK3o7*dAvkyGGq~ncii#E>$Fx6MvzwH3VZ48%_1%5zx&1Lpi_j9- z->ly(a4!Jt%6dwvtvD23AjmS#crMSNko5Z@!7OOD->!KGGGay%i`G{c?%&(73+gd* zJG;Ez7|2K^T&C0+rox5;yK{Pq_j<;`azuAaF`ip%@y{P2HKmdlAW2`}U(uOnkg2)^x7^8}Lk#4|jRr>Yjs2T}S4AO2ke- z`>Eg8kg*S$(JqNt-LUSm^ ze^@6BPFEc`D%B+U3APqsT14456FJ?&F7mDZw`A?LysY@{AFX*EFA;2dG9lvL=6Wvbqg)> z0Z{eNomPuy5VP$S8|g5HwG#<@C%bkMpp%&HEt^MMkrB@_&DGu2e!4^2pIS($=+B*Y#uOK4tlpT%nqR3}sK zj#h;%gv2iCiq3~n8ksLzk7$@gJe_rbQD$**@!~hmP&vl-yiZqdIc~kX@2TiOFQa&p zk8`S5+|g}?>EX2?)6D_ztn$pDAsyO&9%yDv=AH>$u#OQhWu=yfw^4%Z8OW7`99Ous z_chFZuOFyzysZCL4|`O5dwVV6H9R^|i0ot#cQC2kD-)E<1c9Ch*nSTc<6F1NtXCZF zG3W)1V`T=>@tUN%3fRF}bT8rh&0JRv7Nb218m~Ey>fx&jQemcq=_*e zQix9Q3!=;aqA9OE+>oPN+zVR|(*BTGi_PwZY)H$Jmkw9t5wY8EJL|{rR>1gzoOt3( zj!j$WT$!?*Tvw${59IZzaZqu<#Ondmf$aI0R? zzQBhMKX-QWY31r|tS+GS8Ok+1oi}f#!Htfbo=?wh^>=q#$kFidaF`}x6@?%eS|SNV z*`ChU=pG7Y5>^fWoO4`7RjUgwYfRx`ur$l>Zg7vh$J|D z2g=)-r@MrzUy;_LHc*y|u^flUcdA@A-33Mfdp zx(r>j(7bp)Uzq4T=QRFAbLFKn9H)OiguZ%pI$v84s{uv5z2J+#p5FBq0)c=Xr>4;& zuLW=l;6-udUZ#-vY)K%jck|P^tygi#&}e(ozr$x7CYkk}^UEp!j_wj9ivmL*MeKfJ|6Y;-1WGQ&j zey49BzvtcB8RFrNP{w`7#7+k2PPRe-4{Yp>-|2K>QVsskVAWBblUJpzd7s^2_cVlN zf{Kc&_bjk{q6nwnUZ-cq1w!(iU*6Z7r&vBr75)+Hgs7*h9 zR(=6Ov^|aWWanBuKd&A-vXdzN*|Y80|* zwd$YiJ2kMnF!5X&Kb08ck}d+$9FkTRI79#@4Q(D2m2$d$8w~aCH@|j2O-wuj*U;an zN#b|^;1d=WK6UC*pC^VfV9JVztZlfpfK~A znVmIiYl4@2tKtU9>cno0b&$dbmMF2CmukMoq0G*~@xmK_aZ{PDF4XQZJK!k!4H%HZJ4^iT~x*m(NUFR&#(K5~|kk-C~5U@0H3}1~3wP+(0c(OtSF_kmHKH8YeOdQ*FamJ5qFIg6MU1bdsNXX=9GUG8D~dcAnfv*0STo zADk$PF9!bOwyuXLvCoU&{Z`+(bocgcoNRDd5tT@3b_2WQRG@wN`wQ>~7KS{rDkOf9 z5Scf85pUVwFXHVWe*J$HtMl(q`=3bfSyFqBVUUgD)}mlmiw9(k z{9eSdj^kj%UR*nKqu$Fi$3;XmSwbPTN2!wu zCn^re=2%fz7Z+JRyawlw|C{afCM-169u@=oPf5FX?ZWhdmnkWfsu^l8t*xyQdGYIW z;Vqar_mh*8Ch~yqf^83N)?Zb_o#k-^qO+YTb4y80we5Rd*Vq^o00lEXXu<2(UEUpE zz7U;n&?$dbRguQdS#tZ`Kfs~L>)Ug5T}O|4;}7~i;*J2pO#$FO6rOr-oa9+TPm|n7 z>lzxWs-&cZd~uIxkdpzSCvdLYL9aX~3BnmBLu|nzkSpUtnS8Nu;qxHb(31quB4IPp zj<&;PqSqZa19f%F$Bzu>yw)*8pzHxNB3g`U{Kt7)%TNm}PJTml8P`^LnV*b2SrFdO z(JWb3YUl}W0s9#j!iPJi#PD)jh^rJ{aXUM^40Q!*+)qXcTRq$~j4_dyE-Nd8#$Ttz z#m3D|jH>Sa`&|8kQKV&XYvx*i&1P7Vtbfcb@%`5tpqEjpkTi;2BtqB&wygU-(UyV{ z#feA^J|fB%x-!s^En%bc+$I8Njx(IdY{Pt=n779q7Q!x329H?+5I)jBQ zklJh6o}OE^sgrLk!-D7*-10w}k=%F$#kPI1ad8rpO9S@Di5s7h@2ltvltEvUyk(`O zDUl7=|AX@yjw}wkAomAgYl2~X3hF~{#?rqjK{m>?pakF#5fBt?<~fzCU;bWtAwu+iiTw-N-un{HQv^6$ z`b4%JJ$ff3fPHN5-R zB%-Q$Ao%$iQb8UkNN^}cKRb;4n3$OEQSVLcxIQ7Eb~cqE6jHibUVF zmkPB1@j2bs_zVbxviBijRYzERI?ho%dtDNKO) zc&JUE4=tlQS)A+)Df#mDt0E~=W zqLPGbS2Md#svxK54lhe+VUsWJx7a#5eOArj{PMau6{K2M;)Na-G8jgFFDEWiSdcPM zbOIV|G!ZbnW@zY*hq=0{^XRq1SU@J(9=wX!l^Sgs85qh+OP|dP-*$H1FmI$ozz(v- zAW1rXYwpKck0pmr^HHm<%DcVE^WS6#{p{X;0=rkC?&vgR@NjfSjlyM|}0f(8H5gXC!LAr=Y7M6*w z{1;D3&m2EaoHg=0b+p5uc+nV^RV@bH#)4I6*A+#@M&L!aJgA{rZ)iOEeSAE94w$zg zHDvDjS9h2xT%lB3rV;Xa{tv~0?Vrk@9Yga{d@;l9uZY&#YR!{4f^Qqia}}giaYylu zO)&_%WJ3vDJjUP1bf@i!>L?o~L-E36pv9$(RCGIL-R1_lOjrCy}K z)+e-90L2qYWhn6no;Fo~VxwDPW@7S+$N@9NYu&%f{aa7kd0qyAS_4r2q;2*}3Z0jE zQgdHx_kk0>Db3rfQPbY^Re6vJq4~@QRLMxn@b7Ea+f9ofh=f(`8wg*AsQ$;)icR%S zuyEVsGo=lp0)UcdN**IhVA=e{es#~ZCk48(pB7bqfs89Od96IGrM`FejXCgiZNGTZ z2VJFbyi>h&JA5-v#Htn1&q387^f2hcUO@B@?|8-23kK)YZG9={Wiqs7NikmrSLZZ2 z(Si0gY?$Q}1Qt00^_xkwR8;xMD4IF~lnhN2s{3b->Ej3W?7w^zvh78s&(Mdu9Y?G) zA9j((r@Zz{f2O`%mOJAX8Er3vx3!4D)Q!YwNTA{WU9idCbCW3U{;yI?I9Q)?t;EAH>2c%)@mC2{Q7v#7Sg9646Yp5n=Ky2Uh= zB&;{6M{!1=zxcT{XNpQdQ!@$*9~iG7Y@6)QiNo-MfmsCv8XXq0P*FEw&EShs>FG-- zuSZw|1jV9dwxNp#$YO~pFi(N3YMgDNkC#Z8Wnca2w<^5u?}9~J!~Hz^s8Z2hym(yPrz&=GlKbR3*9+8>bq1#ufd70^%Tw>EM4w_2aQd+xnO>o5x0kzG$Q&zUni ztkgg?Ap4NHd>OfY`Mc5ADJ7gKQXZ(3ai#vxsEuN*ktr|Oci?p(4>f^Y@)3hz81+Hu zJ&2YRKJz=NAfX5e2n#~HJ_Vv}i0N53^bewT-~KH8(gOadtJ?!yxvNWiiUiLhNzm06 z^>tNaBqalb_|4Tn#6d0p#-5B;+)aIQY;6%C2Z*kF<ugUV$1bm`Owr8UThS zWU}#LbOyF)iKC@0vrCEpcQF}%p-uGYO~RUXoxPF} z0FR{bIh1)~Mjc?BsKya4!y-soiXng8T)RL7=u2#Y`t>GsShdeAF1{Bc4kA6q8p*j2 zV$;E3>ivgLKO6VzbF5oQUf3sO*!~}R82elQD-Xl&ADkx}J-&OD#M)uCVc&Hu`OL}& zZ;X-%YEeaczKNedHwsJ}o8Wr?!Tn#s7ivmhtC{-RI^;!cd()@95(3s~vcxQJn3{GF z^BFx5Cc39A|EtChVqnKaN5L3w7Amm2U5!@o30s%Axw#Py1|F~O->+G!pf05n=42QC zD9YIGK8>-HpQ8D1LJNo74hSHFp7JiB8hf}ahJ^*=ZlVJxL1!Ubso~?t&qnhm0^LCA zP)=ziOFz6-wdJ+elCb;0Q4y=Jk31et#|ZjuImlhTnt0l1J0D}=>(}21?t;k|aFbB| zse97ek)zy=o5D~?bkn{tqP-$EMIJ(E*kO%k z7eHBukd@`3OGZ@;29>|@D46S3PXf6-fAO9QXP{3u4lqRka7#0!#WF)Gur|(`> zF~jlk!-r*$O-~l0%gKFy3@{dPfEG|M);j5@)gG8+xVA-tc(fJSV{dHU0*2wZ8jU~{ z*ahI>%N6K&f>6w*c%Y7}kF~aQ<1Rh9wo{pvx{NzDoO7bTv7sSW%%~b^o6*g1J;iOU zT<%LUFTuz*SFG3!fh?83#%R#Xy_~($CQ(|KBl4kR2Sb3FkrEC+_J|HBBN)leE`DDq zl`8}Q#F;Ds0fQPsefaCV*Z;M*j;4s%Q7wNi?G~s6_XPdHw zC;{?copG_TQ{5GDPgfp(9H@EyWB(niwS?2Qzq{Z&uy5?ARK@X7@%V7YgIHqg?BnxF zu8&}UpXS;Xa2FAQ4(HX_!>PqvOgrxSa;ylE6Z2a8brq^AJmBYQ+5gcCF|^m(sYnxKWBun;me4 zvMa|%#KtN}BRltyki`@K``9g-ce%wfU2oUgzU07WW7acKyo9iUPt6+=H{U<` zCKsS+pU3(#znyZ8KY7p}(Mpv^$~(;>5S>Fb@+;KvNA})Xm`bqAZtN?3_3E~R3wtmv zRo9{K_y~kL+n-d@SiDJn?yTD0in{|Fy%%+o2sSsUVV^W{EsEiI)2JZHk;`9K*am z$X{NNy3>xyh+515hE5@dOk9VU$cLZxUygdU^~H1^v8K`Y$>5_(JrG{Agj{9B2|FM3 zA+}GHloM?Q1QXiqJKMuf(rIJhAXAIVL+w*7qB6U`CpE_*7~-VeHX~5`vGuV5ulrMVxS@n(EWj;5Nmw2DwX78AM z^5xQxHlrPC*RDO~(|ymY%5>IDsgf_BXnwzWrS3KxCC51xBthE?yt7DrmtNCfetW3; zL`&T@829fTEK@vrHGv$6t#>6JxTmKlG~;e;`!qz9Swc_gzKICfGRrQEhFP9>N%GJ6r$!Wi6f)B#FhZZSD}GpGO5{&bQTTYw|)Ef|41FjV5`rB zKS6V^!w#Qu3h09q*qnzX{EJ%$#XNK6V37#~0uzrB9I6y0H&XiY35U^y_kML93#~z) z)421Ig3I53{LU^jD5GF{W!1@BTx$GF#KyOMs^HZ1umA{C+L`qvwYFzmKd;SQHS+Y$ zLnjiRgwI)EFJ|vaMkqo4H?_tU3#;3&cv2I+ZkZF*3 z+MZ?a2laQOW;CVN*^q7a_H5LL905IYz3-h8t=Ne19Y1k-O#iIeeW16uFCmg$Xl|@~ zpMl$oLR|dGGuG#woc;`XZ<&f-est(~N|Dm(!HJ2?DV9@-+!yrEYp0do`GgN2_ZIEi z>lenMvTfSciRCd-u??H~16AGw&COTbhk0EiGw$8H0AV|%*o)IW;KP^dp`l%q38CFV z6nxSTlHFsjG${6TpI%ShBt9zaGWkpKKTSvtNTvNgoIJt$d>s!4GMW}!m!EAiasoBz zNN-<$@7r`m7-4$$_Cr(GU%T=1f}X6W|12M{T07eZUZVI)uaGEK^s&z;hz#Xsc=$TET^V_UQJIESQ_8ZeY@`K*9oWc zB198}0p4Bylt_Sb{(G6JoW8!kV#LXO=f)^##<2NWM)SR8I&R&Yu1Zo#8Eqm0@ChTO zxhsjG7Eqbne;!2G?<04Er@HIuJp zz>3=243x#)aV%3ZY_EfQ>MqV1JgC3E<031qW>qI3roJJ=mXWHmTI6z9uAD`%WO;_b zg_jBdnT|-^5mMqm(db%69sOLy;5w;jaA->IooRG-5W)5WLRzHVy^=UexPHxED+YyP{CztVHO;~J9{?T)u$Dq9{r~6s^mrdB| zn`wV}*P)fDQ+$sw%Mzg#E?@flr3UnZu&cCrv(WV$S*X8~k5<=_APYLTf|-VBKmOJGpQm@VUfnT846*G%W3 z^#}z>e0%UbxyDhqn)^6BPo7t6ExC73$*;*!r|@kFv5Y~WB1KpH(fx>5_G~l=r{JdC zx5s+%cYkx=Z#L`5&)DkSzq2~~lB&YX43KbaQV($WtF~Sp1Sd~XXmfC=j*IpeD!(In z4!@N(`F<7$bfsNlkBZ4bJRQGUR)^I@FA z_saM6Fp=5q)e-IL2uJ|?42@#^?uOSylZ?D8W|~kbJfXZLO(yjcP_KX z@#!5nmD{QHHg!3U2N#pO!37Ffv^oce z(em1w;|X8DPy0UcRqN(ofAvJRXBVQbU)(t1aPC{=Te37V6_dPe6|T5|sZ_WfG1#DR zHTWp@8mI-Va$AvLqo}Z>Gd4)J5{bVOQeISIWB1>eb!aKcx6Py2GR4<%**d9@KNE4 z+;uW4#r2DJn1L2~sq0eiMH-!FViVC?+y-s>wbUn5#BIMiWBZ+dzgf6^?WiuVBCR{8h1$Qm06AbxR;=i4rC~$Qc}jo zUCY-vmaQv_7p~Wm zSAxymGPsT%7BC4I9Y_w}=Zol4hq7K6yx+YeF|7N$8fVr{w|4RsQ(d$XY?#R;g&L)S zXF0d!<3WyL+JaN~SO6E0n_f~}JURu(?Dgd4_)pbI(!`ra&al@r=cpal_-K%2j}OtB zxqGBgA!Ox}{@!&`Us4^f44Y|A^NpMg(_-5Gt_1Bej%&1sgt$IP^Ew&}~<8sy@5J;& z;gguw;UCQ8{{5n8uHhKly;E)BgaZ^;mCCPaYNxP} z%RT*Qb(rizUWiZ?IT#{WaX{{F)MspkG%c;%H<8sFVK|}lP`Y{}fGjHZ5ZT}9iWu*y zrItUc3mBJbBN-&2?WjBw4z+?yMhSs_((R?HFFd`2KK=Zn8gJYkA^JW!PmGdF?}cn| zs&Z0GPZ_8sTb>6jXCD^3Uw1yzX3^ur7kE<-%-`2VQ83ruOWYS=i{#T{ao~&US5#?Q z&BCFpk-Y#)uHV|ExlB89EC?C4nUJf+dN*FuZ=z>Qek*Dx&7yj9Cy^Q^&YXO$b~x{e zg(1zoU(oggq}CGEsY{U8Mi5GK8Qli${TK-4N6Tq=kf;C!Tf-Weh(?&OIqw=W&K=VoEDCJ zT1YQae{;pYAb2Go4c=_)cz(h6*2eN%ho$^OpV!>irByXXoY?7G4r`TrfOQt$Q8HHn3nC zi3^zoOKvtcQxMBd+6_n&db6>bHK%@dm~~9A=uT1Du*w9WQ91iL-67?R+cjTv@)6em zHSM{5vDcu9KWQO<$A*dWD1H5g))1}0q1^|L2%$q6iw1CK z(i(d%pfc@kMu0q2Et+og0qGE;#(K-h%I*@q^`wES8iuF5>lJ4PzTROL2dPHqxfilP z;@0`mfWOMn$;s)SauFcAGQC`0js1Mas)-Vqu=2*bTVN3@?sQJI545_#1q17bPoQsC z(L0oJc-LWsUgDCKq~QACMXsQ)zpsT@8AxU*q~$lV#S`MCuS4>qu1;hBJ}APm@bJH$ zx(55FS4V^Bo{%#?r!5-tw!AFF}uG}Q(1;NI)@^u}d(GFz_FY%TK!xt4fJlpIqymsPa19=cUB9l+(tgAQQXvS*0d5`QZi@934p1ceup{*(KETR zz7AJJo>6ZRF4xjhA@KTb-=%&kVz>?#5zyX@4$se1E93{LKcA>`Z)xzJ_Tn>yD@@qB zi*g|M-z(%$`S|gnt|iK>f3!a6KHFGZ{AeP;VwucUQwzkhlyo*eKEeIcQSffi2^SR> zn$Ul%<7yfHLih)<@LPW}u8q>sg{LVEvDIoN#xc^;(jGdb{k7#WXGL?ZL(EE@0|L^t z;)COUN^@`=pPYXUWdE!%T12t{buMzxdH?b#r5*`mS07(#hMA%z>724O zk8aWM6dx{E?2B00M}4B{PO)v^U(=nMwdIgU$kQM4%iF8r1Pr3*L*}T6(LbZ|)&B>V z+q?`wqkmm)CEU1TY`_d>WR&x$#-eyJtsP3ELS+hj2%$&KDq`Di1UZma-%%(T1?CJ{ zGqD!XO}xi+o;uV&Z~}M^ridU$2pd%qPKyoR5u+F~dS1+Ag4T#i_0F9$f*E|*&Wj{y z2JU6*_KZ9uzL(a5G`4f7M!KEoiro`mez@>0+fTCAZ3c4ln5J;A>et(QJ0M|zjA-m- z5>FzYE#EQq>tX0~=ds2d&ujbif2WNZl{@(Da=t0ucV0XrL zkGVmi9P4oK&W4dWpe~Rv2+KJCi;*rD4ED84c`qvU2x3ssgAA?D>8d9p?^E;5am#xT z4qhM*BiQDli(EYJ)BCl{&8}!`M+XHp;!{PYDR4a?fu8O}a%yudl`8ya1-nkkf0tt( zX%_!Mp`3p|{*3s;*B~KmrD#VkGJ`9bouALby)k|1Y)H6zQv0LtKf-S{`GY?0uA}uy z@oJcbcrYN{dux-h?S)(J&YUPi2wqV87aDA=LK^jE@+^Q!+wSxCp)9Yz+aPE+ zrPo|@pZehs8+hE6nMiKlAy$&PG1)}p*xN+PxmFy92LP z&(YE{xMS#cTeMH2DBU}NZ7>@=S!@bg75MC*emqPkpsziy%`?9w$zi1$@*_A)UWQZpbw zYcLuO9S!AYusInPT$FU#B>$@$Y+>7fxxuo*zobMb6yYwYH9gI8UwOIo`Gr7Cc28c_ z1YxPx*dEG2xhvN%swI8m3fbGy7$C*d8-3c10lh|w3~CnR-LcEAG)GW>WhljK3;7nNEi$hG7&Wu z=zdSm6kxG#S7mQ#njEcvpW)sQ?4F4morcmvF2A+Smf3{(L|zc~y4|_6FKKOaV=cx- zz>mCZ1vAep4*s#7_rF}KnC9d_9VvgJERLY-`M+~e&BbLSO!L(Z@^q~#scFd-%}($e zz=i0j!1>F%KfE!kx0i4%s{CVcYrx49Cu(|ndU~rb&Igun_x7|lU}FhXIW>{q26V5i z=00qan10i^q`^n~Kp8Q(LiFi3W?n~sRolP$;(uekYK;_=k!HUdt%9T!S#qY9I0;c< zHqwE&xHG6B*6_w0mXJFcsSrbY?;;MBK{W%epw})g6oE3QHtE?(NkfepnWjc7D?IN1 z^N*yYq}ylJ>vbR9R23FZBRHo1(GiRfS4Bdwd^pE7155HLe!9RfWIMKRx7Dkzd`&ZX{cvH z<1dtLf11Lly#wZ|iQ(aDvI@5(GEPl#!y*SZqSzt$u(;Za&u|%aKzM@R+HsT~vwRbte9wO!Kt;mvU{F-yo^4#36$(}up zBsDq77o-Uc1&|dZL4%p!*!N9$CL(kvI!mS@O8^Oq48*HRQfFbxnG)l|jUyiRFOX=A z2!!rtNLlu{J0wL%i$QJZQt&W#me-)n#nuSH&Ql2b>INJ%MQ|r*iF0ex6Q_r9QdI3f zB6JeEWX$ZUc^_AQ}jGP$C;g08Ci#lXf}G`L9JPcEAo{7GHP(mh^ti z#|9(NKThcpj%fL@PjU3r)NSxXQ!t-7S*4u&zm0Xn~8)jnA*I4>UdE_BB_(QS-xTe*W1%e-LPPc;uWk&lp?FEd-jgTIaL4 z3f>dE{H?xz4C-qft-rpMYr!Nb}V{3Q9_P zrMI8^2lhy_hRR`KzD>}}uQ&+%-|(&Yclza`lxA zTERZ$OQ6PxbfaoV4GED7QLS-nxE3jw&@}TH=Ks?k;mWt}`MFx?8P0hELl|razmWL= z!V_%|0`dTt+4h$5yEH|gGixzn@r6h2JdBb0!(; zt8iAuW*O3?E(KWNe*X^G$Oz}?V0KwXrtEGC6$6qQ=6`KPa{?Qz92^JD+r;d2vd<8H z7X7!bq6r04FkE#fH7SieSO4ratiqjEk(9pmQFWZOZFzaCWWdWKRI4J#HAxCbvbwtm zJrk1z*j$4_`>`qgetof;#zre-s84v^LW3j<)lmY%*d)!8bN?EOi;jrSA6R+#Ej z?Ll_stfUYDnoi9g*Wb?wkC^{@hGMnYyh?NOnvBbhi!6J3fDuS7!ucNLHtC zr`P?FZn3RR4m;V0w~K>r&HPui4Wo_@IqZo$Y#R%iCluQ^PWUH}xJqLDjy-X#W!Y>2N5 zV2&M!nj<9Sfa~ewEG)+GH0!@{8j`sWdR(1hd+2+rO!gy3@b^{S?eITt^*3GOh1SKU zr+C(Q+bEBddS+V-d530>!Ik(wBJiKp1-oJMgfQES=p{6Sv)TjEBc=H_x4H?}Ptoz| z5TfZn{QSYn#YsPQgX1W#cBzWKSZG2*bMrcktYfLsE0;?D5%w8^7A`G~L)0Tj0S*NG z`p=Z)MCz=D`|djp(5_HG?uq$FH@g2sGALW+4{>!B|6!TgS>jMeglAC$n7()i;%hlk z{DdSU>q}B!g3dpT7Nxd;O6mEoCl3{I(Z7z3jux`(KRi%@)dU00`g06Vu^y=0=i@n}-}BsL{cD(ip|p`DFVKFuFVD8^i@jn!4A+JSU1tQli%# zr{cv4?Gd#ZzEWG$RULO9*LkzOg2S{vm}yBaV>9rND1@j2S*Cjhi|L)84yK6Huw_WCIKZaus&@6vr3!*=YNpCA3TY!!W z({!+E?05useaA$HzA(ELvFtd1ez_0eFf1r*sK<_CvLa$e!D+UA zxF`D#{BY{=(}=!{zh6Y}$KNlK%+bFU zbx#kSq1>364}AEztK899Gis+k$?Ev_{-tjZPb7w?@$m}_Ubb78K6<_KLF7pz6H}XO zSuQna79^#UFP`0va88!cBM&QU;vy9sJ9Cx`PIsp1@vg1&|F|?>{vm+xqx>xLJJd4N zkuh1@-qe=qw6gDUWY(K+kp+DIX5RI-G%VbTbBoPEd`UIQFDlKTtu!?SP#$$!Kt!~p zklW7ibAOqG2L0Kyv&yrg$*;4%e7TlqAo+7bGtWi;K)&|+O@p3uqcUM}ao-&syt9g{ z7#ZR$7S276kN;hewzcu+c)C@{@ea$w64$k45(p(`qDNN21~eEP^;*+DOAlH+fc^9G*HzGqKmr1;R( zw7fpMkz-|k>HfeU1~DWq4DuVXrCAn?=50y2Zu@!5&)t3S*O;rFzLK({eYSd0m}8OJ zOPk=}D+}cN9bOk8YvkrlmYQ>ZQUuqWY<)k?$v52+>bz~l``)g^9)7meW2F0gk3XA& zn0Ti}drDD8Oj&4t1|T*G-LU9GM-OgH&iUP3)!Hu^Tau;U`MrMYmr8fXUVDCrvh3?Y zkJ)%~yt}N{>IrhT1`EQX1?hT4shWAn=|Ai4-uxpn*?m%7uc5#OV&N5laA8j!#jKJt@or8|c`CzmeHHFQQ#oXl5(^nqYP!p}9)!dk z|M5!s=)gdkedR@&wAEmp_22X#$CQs7NluGzzcHLuxtxx4ixF*wJN=|yc(>_AwrTGYOvA~*-54n8uH)n2SSx*M?&;~2<X_IYx`Z`zh z-N~)r?`e~w#{(7It-UYP;ydCp$uDh6&}ytO>Umr-)mP~>+Ky?dtezHy+4^;!ArF@q zS3Xx*nKndC3*P=6GC!$0xFR5$xB6cC@|&-jd6QNHq^k+@Dz zYkz`z&oiT0oweU+osgK+Ba{vnA5ZLcHzYif-* zzB$K5oj^+9HCaB4*1YKL`0SE$GfN-2)Tr-g-661U@HVo0T| zxK@plwr)RA6c9{2Tlpo!%A5R!w{gB#qexY1D*M12ud5FnO>e$9arJPwsioOx?^ZiD zg+m+deJ8`^^9-e!4>GIf8If`SYWpU2qr$!;&7mWfF>#k>*3c%~dd+;AYZ-}=_IP>g zlHINYN!3BS7$UR2T6Yxp1ZP!FIWxxTYQJ845R%CIw6VL{&hVUmg_BwddDfK9SW6BW zUs9jlkI#&T$M)=bu2O=LpJ&PUdL_h1Jc)_1HL*4}GSYad!&CAtxSd>=jlFhd?d&Qe z(aIvC$Z|ZHT2}V!%La9aOwAH6L6=+m?CBIu%u;bNi#<<6@H)6Kdvw^e#+N^4;hGB? z2zn4YAjQGK1{TMWO!0D><(1fCenGzLK3j3Smd`#8T#tp}9q@m=ny@t2^ym){6J5JiYxb1~ zi77&p@0MyeGrUiInLLpdNYRpKAQh(ISZBQP&)tBDs63iMfe&FOyDHshH}%gO8|%s5 z$&^bmS8aQpT;Z5-=ZgDQ&0y|S*Bg71`5HrSJDRyDY;~(^XQu>jC{=zw)>x#u@gv1I zuCqlwLo>X>SIU?4EWyM1!-tHrGI1}yBbDCtPbiOuM@HTsezhPSJKc;0(UR+R*gNr*S}yNkexy~d#SZ~< zMn^%E&hWNv5o)NLy1Cl?>fjLT=kb9WnY;_{e9lnkEK(ONaeGdTvJ(+pHAJ^=9^9GDnTh zFXMc&R+_P`2{Lie!4+i&9RTVWL6j*9WcxA)H&0lPlWCyR?YV zuZ4={|9DjfC1E>?`!in;Z)OP9Tf>}JR!p<8HwKfTdcSlh{(@LQ8FY>7*0a(fm?tzD zH;juhq1Z`0IHFmu`B+#$@$@?(&xVMake2v!_M{FGamni|1U-fXhWxDNV)92wNQTgL z4Ugw1N57y@F>-2}_vi?FTGtnm)x9&M^!~`Q^jHyDIKou)a zacE@PKhUhH9^ZI*^YZp()u2SpE^$BlX6w#qbDfVfkH`0%ZCNW}qS7YmV#WD+DHmks z+7{kAN9sq&(9EA`U(5lGdOW*^O!<#^Sm0I&v^ezb;{|u&=`^~BD7^)7f^ozjDz9VO zX-3ldW#tswwJZ2LG9{?+5RWtl2AWgjlUpp-X$TjoU=3e|7+lP4%1K-@pUX00WYK1i z8fBz^uUNZZPlFg=x760Dk5uM{y}h^|6dO{nbMie}{F-)eas0hDL@JKKrX)RFl2UOb zVaRGdcV(BIN!5(SABlkqE16;cV+Qh|`4uT4GJ?ltmzEH7Chd{)z)B+OCd9iqXnft@ zv9;crhl_zmpN}MNf3;WJgbAx&eQJ7MK|_TqBEa$ZE~55E4jP8QCcy`ZVblFfg1CvH zVeYcOv8i$IAPc(Zn9&u1j!f~;<;0e$wB&mNA{LLOW=k4o<`cq*rukL1uD`~ObyqJ{}dW&3@n;j*a z-`T5VzHnOsscyE-4I?4SE>UgNXl2F0Oo@-EK3kYh+f2UQ_?3QL6(R{9Yfu;ZiF3XS zMiLCc3m#fFri$u%NMMH^M%9s0x2@SBMP5BApF zRz?%HNsjwr%`h-Qk|WBRe@>24lD6xQQX58j<_1THD;f0Lvmhp4ha|iv_tRKeGmV&3 z?bJoxHDWwIk>TNS*smRb=UXkD<~;`Pf5+b_==$8YR}-Vja%l&ihZ-7Ji7{rCqS2EB zt*XT)rp8Vd=N6SVy6&N}CwHZj=z-_LRhmCKMzkbyv<(ZZi%SDrt zVoX{Ulx*|k%O83h65Hsnq%Ezid33q$*lIyH>^o!DmK&vYuRs&kQg`i-m%605%RAG+ zCPLH!3Q^SxGjqi&td8TbU@@(#gN11!+LXIB@Lb6B0&;7Ye<&o8B>%9qYM$r)AW-X- zVr2A*Chqn|ie6@XgqQ7j$=*chhiZG(LLFYJW=jY{^_w>^sh{7VF0{Hb)3I?;x`yz* z|MaH3wpQzWK@vmBf^W&3;VQL7mc8PGIZVPINX*x>rY{Kg3hVxgk`5FFDDp=xyCJ8m z{k2*O=C?-|R}Ppr1ulG(Gw!WxN4w1~522^mg7M;4v4?jX3@Ux=&<#5u8A!fs$(1~o zN4)!DoB08}qkk@IYmV-LM4({3Iyz>G_ToD6J46r;Fb6;6S|L%>Le)E#SS70igoJZd zJQxIyOkHHSGYgfLfrn-dlj^x5aw!hYB@cIQsS88e;9xRvdDfK0Og=t>hvRR@gSY^H zv7qz(DH6t~J@NR-vs5(u;^K^%a)^e;g8ZB@*lu93_}KfQ*~iH1Ga;$!dTMNZ^3wEt zarnUCZ5A;Zs=SHB!T~K2z=qq0r@o2AMUvhUnn~e4sxg=PAT|D42_W}Rlj$uPzS;r_ z1q=RlRjs42u%u~G>ARpWQO)yXM0BaCeZ$NXW5!+M0M z5L9m;TeA(rVU*JGxaDVD=zMh_${37+8qZQGA{YErri_yyuIq*?vriJdBjL4UWXa!y z_nbhwo=Bx<8&kzGRWOs7D0_19tlO@l`QD-VA}69ArNjb{B1V)3|Ganol=XSQ(r+Hn zG0tXpM!f6l4e*NR68+s-DqA>-U_VKIjv-Y8PZ-q|8j?nu_dqik6ewYAX+EaKk&#}K zc(n5#6$cMDspwIJKj3H1M0S*#4TRvm~d$Eb{VMr00p$V_chF;-!dKA{*@M7*!P3J2;TX z(o~DDu3+N#zCNVkKdi54FGHpw>~w4gW3#jZ8GMwn;g+9I(NHw~R&2OKS_|bv-!ISp zFVC*7kf?@(X}NlExTNvAxl5N*qs3}1v-N(jw)JNBuGQ`CL9506;mnxf$oX{c5pSVU zkgT}D?RKD}d9i(H{#uINbhPNJ`Tp9*(W*q|EF9-N$sOcs3JS`*Pn+&dImCt;WVl9` zU3tN+{=E2OJW0k3X(av}^7i7VUR1vn{)7~xIZQ(K>48kxDmB==Z@RkI5 zI_$5bMY}{d1CA0AqPkdk2!_5(lKSK+eEs+we_6zpKrmHL)KL$KKbnw`WSE@wq0kTN zPEZiFMbJ>~=Fe+IMXsp_Oe{R$y;W8k5K}2rW)-7j;Ak5TMaNB2KUq<<96?!pNZ{ZZ zDav1Js3r?2_kT04yDk@7I@f8ysp5o0O$GJY`vKN>VR@(6Z)b+c5wY~N7RNBTbo3o< ziwECildfnpN2OS_{lMeS4jDbeMHGeYeq&{jn&Q>o0%zR3Dz@(W_RS5ntIN&K8osM5 z^dgn|IIppYQW8I3_EhH(g#Tj%ylJV+`cl5+l+pi5E{9*d9lP^hHkemV_VD(Q^A2>(sS%8GcX zh=M+hq3IIUwPrP_Wv)=HxSh-~HoDZLGhiVnxF2s{WUi6SCOKR09^=@qC)AHWs{B~}rN~YS^hw&hLiQ4ns~9|BwWGXet}DaZ$|p_%>dng0(?Q5tX+Rr zbcTn*Dyaw-k7Y2rLnT{wFP5#cwl*x_2Pi9zUh-F~PAY3zL(iw)jJhor!;UB+wW`3APvP`-eCUT$^0ge(^79X!+E zeOxIXX+_3OGV2e zT+axb}$I;wz(hbCas_ivdYUI4y{EM~BCS?OV|3+lPIe4K ze~@72<)uRcbBHt%mYFefCn-(585TkHE#7;a5{(abMrEzJjg^gsmCePwf6t3`?Xio5 zrv~&mFS~i(;TaB_%GmClag|`|RYJYp<=Cd_r6s42-xovuQfI4URc+}RAH>ik^I7KE zdINO4solYoSzFjx(a!40&3)EpZBZuSdRyDgb|o*>rAU2Kj9?9Di;^m2tf8HRsI)TW z0}a~dJ_ySjFuI+SAs#2RGU7`*Om>nbD7<`9ie>0Upfx=mE3$Q~M~fURUeGt}0IDOw zOumU4Ifu1UFx_i$;KJ4#hGdPw}&{0NAncKFZ#!QJXOCRkj`pF{(ze6*bW-_l| zr*y9AKtne`UfUnOa7XYe_>(ok!KW`E-&BH)ixQ`Pv6E_K^s6g|a^)O7i?-attGVgn zVJFyO!wCo8w!7?ZbZa_9NEUp2ks@F=jcn@pb$bt2rJH~kVvf! zh`%||;FGxdlfcN3->H9A9uR2_y_iGXpD2<3lADgLsima9Xq%1oO@W0vH%eOFFTu;j z$szE~&A=hkD7*+dsAf0FpCxZgwKEahw?AfIPv%H045A|+ridiijX@R~LTJU62S9yq zVQJdna!P5L_6)?(dMCm7lwG$Uj0*t}2p&HZ3AemrCV|h)=wOSFKt!gZc)4X`ZEr{ye`wx~u8$1vfVf}xERYvHI~4Wf)<`Lw zKBlwD&&e(PdUf1bm;~+J=JwHyb*`iulWW6Y(h)u=0PV!tC%pR>>mk+gllJ?bK9yhF z2yZVguP+6X7&RvZRAvjak?BhhB7C2geWm;9t=dD;36oAt`+4vFINnma$<|n%o^1)X z)Wh9!4>o2?_ipE6O0v+kz^Y6~IhaT}WGH47nR=KgO6ZGdS+de^(`PNUK%y4$m}*;s z{Gfi|EhZh{MF&wj>U6{E7#7O1>)w)5_aVXld%cxd5y6o+&rGFFS4USG&=N2WUi=>uv2FxE>r05)F8Y`X%`@q!E^4G4 zG1BL~LP8pL2G)WI`au1zn7r z7#xWjjtWiGlwzDv4{?~3RG0{^?i%XfkXMtJ`vSgjii)7|_MvTZ`>VI+b_Re&{T+m%~GIlLNJfy!hB{2(7Yv zTg)yOtOtaTrUXnDqk(^WF{fQlC#!P$XKS)Fu0*-k^;j(j@vW#zS)HczBJ&M#alwy| zqrbIvZEl%J#l>buk&%#ov~a)R|EarMQ7zkd;+y;xg?mWQ_V_Bh8>$6j+sw`7Zp4Ju zTI1GE`B?$&iR2B)i_K#MaYysgC& z40&qJ3KO@uXrv7J#O4o|mHQ5$(R9DOdE8p6H@ly;14srXMoW_$q!UEg?OX#%Cz@85 z-NMs%?Y#kO?Xx4en1iR#i=BFMlroC?wa#~%Ec3hPgq|xgXjt{!g|g&9aJH?Gy%VpC zY!Pxe(!2Qj%f%kn@HTCp!B%da-eSeVelghld+%L4Ay8^LGqV={l(ksf5+HyH3pOt* zO*rs+lb{OYo%*v<+?RCiFj@ihrTI+ zz6Sy|C}B-aP^tPfO>bG_Vo(>F?dge_OwO;G6%#sGyt@JgE48W(OyyoaKGn^jUe0vA z_d9BRyw*C#ft*Z-;V(_1v5$-WR4u;U+Pe9YFhZqz4^Mxb>Yy$l?>4+k`0@dTYcah# z8?sf+7!+5O;l`J2)85N#kPg>D_;s|LH2(9OjmEnz+#;Rf4LExG`XkK-J^?jHyt?@F zn;v`!2?06v2eRNHYguw3P-vlT`nq##n5MdFKJvT=#iZVBLt`xsET<~r$90W`I&e9l#yl9ch1P$f;+FyWY zurVb(x}fpi_=t}PC4`vq8e3hxe%`U!gpZO!Z3Pb-!l5di1e+bf>_aB1)v zP%_8Cf8SW|jKnXB#~UD~t_`k%zdd+^6#^X9VhXF}^^T>e=nF6iVW)_1PA|^%D`wul zwac~t)k|-8X!HDWxs(kE0Jko6T*t~dfRr=hK@zU#Qs&E3;@J^m8K^!8& z75BRu)(Hj9-@79vizTjpunBs@N%fcR9kJZoBRHJ5*NDiGvWs=80453%B*a6%ytY?5 z{UL;Urs2Bu!RPmGD2Yd;G6&sKlb5JYT(zyswg5q(6lh15s$)s`lwZYIjAsm@9h!%* zmZqFuB2I;xrcfIC7z-PU**@%|;5T1h(UMUG-dyOjCFr96`Y|eVd5FD@hqe$HC~{-hm=pmI96UUCpFo9OXs@=+P2+{**OTY;?zrOAePL%oe&f_;zMNPd2d0s75(s zh4M=%>|PG!#&VylTN!0_2)q;m*x;eLME$b5V!r&Gm}*YkucH#l1o^c?loNp&1JR4Z z<&WkI72695BcW~=eCqA@zfay98cvVOR0}haFJL zribf5BjvISUCEx=PPqOS&!x2Kf}ph~V@IZhpWthG3c!jmRSF|z(Iu~*O~ubdZwY#I z)@@^ft&kTlkX{zDe`MUqWN1(d**izv|D$k=Xuy2^AyjA;8>GOuO{ba)Un0JZ6c*D& zi2^AL69AR0gg5+#T$`F6NcIq1sWi{btaU6@M81bv{z`q|Wieewi5y>xLT6%~WS*L4 zVxEXa-yYCMu2wa-JO)*o^S2tDGbrd=R9H*`2XXX)#STvArFQ51ga-Y6iN`G8 zLF&A%qY8(R40ajeg}T)8)AJwr%eiyr6|NTNM^cE7R{)>8ZoVCv%NmXWku!U|KNEG^ z$}cKE^+j5IvZl;cUU7AKPJ=j2RKX;L5LDFAmebuUa2e1?0`{Sz>=-b(zGT#>v*WWC z-kp~2Ue!IbSZr~MZo2prr|FlO*qewgTiET3>V_8xJO z!2xKGj7KshsHkew5duDQeYDb@rNbcPz<9w->tyv8Ui<*0UiBGCyggW7mY9`zm~DMn ziu5sN$^`TUxLmt9-3TokM*G|8h>RwNKxVglK>_=n7y{>KoP<+!v<>M68 z$nre0GGJcZ*B7vPA*>TTUhF>4K8dFw(PoSqO*K5cc&10gT{_0;tl6ESh7pc7#mvD` zAiEkk^Qq`km~I_TH_9^iu)e|BD6{R@97euS0fad!l^XQwFzsHlXW}AvP0S$kLmses zTE3(6;2}NR%8N0r!Qnjf=kUmel-ZX3UYy4WK|Fa$_ilQTl7nS;Ym!m7oQ#gltR1ag z2o=^t!r9mw0^)k>Ht~thk~#kJuhX#j7l5(;MB+jvyPc1M9}*gRd;7X%u?!CL#R)gJ zDaY^HqnXD`C4A`D{){SSdI1Vqw5kR{xd?67E4@eQhu41lk1(kX=N~21|3mH4NwkSsp8I2*rC4Xj_z6Pn zBl@7W!EiwbYs%(TeqU9B#8s94YhV1t&;BsQWI(DFuVYdTi$MQu5DEy@zya62W_tYi zvoqu8i(l6vFDtZTqeMGBp5XkDR zGIb*(x2f0I*yRR9Y99rPfS_c%}N zQe17?Cb2r_T!NA&Szhsbti3pqZ1CD6v_^n#)w9cp7{E8s=cGRt4A0S&R?v*3MXl-6 zXCMgz0!BQPv`7Zp&%9qp(r(O*$~=$TYWp@a>v%!uXtwA~_mN>ZI#WAKQf5ZWRxH4t zGQeYW%zWlDE3>KUXJxYr5f+Y2FEdvA78__0z||zMf6$OmPe8rP7*~S#h#=)-4!V~1 z(Ae}gj}XE2gEe$4yh=9H?5N6pAK!%bEmT?I=e{PUy2e$yhh>V``Yv*x4z*|VuvBF| z$dp26f5WS8CIh`ho%N>ObW~^@;(e#KZG!yS_VRHB-zbM0B zXpHrIG%$1PZx7xqQAgxhl%aSBDkFu{AAp%~JmNupk0beJ_Ii)gCmc|8YST6jM?9Un zwr0(Q-rmi*tz0;$IOP`WaKkhf7V3!ocfxOsP0gQb*_|CDP!PV}6`R2^tQMVJoK(?J zIos`N9ndW2Av7h%WR2S9AEpO|#-A)ET1#Gz6do$9y+dbN&D)dH%*LdeLj;7NobV_E z_pzKlx{^dCFoPxz^1Q7a=A4Vm{XP6vo@%jluS-MPNk4uJU}tBqW3i{lFTPt%)1;Xc zlqSR_)_-s(4-rH`K!`@$#(%t!dIH2ZT~fK-?S8fzYMN}dcTw6Mi{$b$lDS`3u<94ev-r7Dv<%8gy(D&S|a4W>?9thwV>%DJ*v{wNuY?l)%4$c zErcSVr3dlY!}i?GNl(4sOPpr9Bcg4>hzUp~N^1)nDwIFIJ6^gbJPst;+FYtvzaV3! z(eVKE8mVF2J6~O^pQTwleD?aME#AjFh7&&G%gHvd5(4RSiJDl&3Y*jPl zJan$^I1*on`XDi!$`P4b&Skr60xt0L9&QVv%pFPPuvz&nrLo90I3xo4M-ZJz*JS4QFBlWKUGNpp-mi>fr?^Z zZ3JoDV%h$8WF{}uOq%Uk)Su1?!)f!((Qb>#dWP+Z2yi^$Wlb$=lJ*Dlr9dSJsJ?71 z+>amE(e-(3A^TEb;cQMq(u^zH2j*!xSm=4LyM4H2LImX$BYAnL2R=kZB^3P=i9#rP z<9`V|Y;if(e|U7{oEP_P8^ z_5d4Osk23H5M}L$V;0|JCdv`>IQVtYDT{9QdQ}mlw20+$l8mTLNGs{PVD6Y%E>)SA zwtb*+b@lhzr~<%WxiZsiBelc}xG=~=qf$MdX5qBu^fA=KR}^&D{b3~%imzMxjrBWr zJ(o$EI9j+kxR@XmDTD?`qi^nBHcx@@SyRmv{Fv(3U=rxW=DhR~#nbVOL;nhrsK#$5 z&j+AHhp^BBki~n6;7&=2vajvn&|vG^)a>3`g@=+&=Y^rnzQgTZft?9w_kI8b$6&V z|HD^54CemLir$@9cB0P#W*6@a$I!#NtV+c~%A&*5+7Rq^9sbGwvxa^DJ?Lyuwu$~t zh?bPEH@G6}D#`$%3QW* zdq^#u-B=`h6ghHi&%_zkX6!<0jtR5d+4<(sWp}90U;>F>eUVF^B1WBtx%?T`pt6o7 zFCWCVKDB#UfkFtddFXiVgh^$}$#p(AQ2K)lW~|d*7sO0+ox3`8Do~9p>)1%|V!|CC zyZ-=&ojV{hzA_!N>XyALvK4gOt5sO@vj+3xC_Nb)7YEDi&zUzS6#VTO@5RwwvVaiYFu2q+yxj4@3v9HFMtTBw zLPA)r)=z{3mD}Dfx(QR}ZLLwV#zL>WR4s1Gt4-X| zly7~n)-?y0dO)?{%YTHAq^lRTGn2)A=b6>`mI7<#QRfBK^CciMdOmie z=p^yejI#*H=GPTh1Ic+*82+MKh1uaB^OxQv+&ECgR{S}ZlI*@D8H(mZ6d|$GZwsqr zP!nGagjH7;5Ns033^zPgH4n+UB06sn!mRD=Cc+F}SEEIY!Z#NdCc9B&XqgN<#tQe2a0A-nDf6;`TwQzF7%W_FWpZH zJyTEYADD%Q<{~_s*haGjVDHFc;8FOKlhuP$3gZuc{j_@M6ZQ%JOJ};{%aGaG%8QSP zpzs>+>xGlkG#2c=R=BiR;9le({r$~GAYC?}EKUzS=<|)nKv>JE1iYefM(p9%rr#)Y z0^2%8ewwG1vVfV#(IqZzOUa$GibzXbSX#u=#;XKInUsvC)~#5iLZxt+yD9LAKuB!% zyr#h9yq_82b=p5K74V!d9~Zh=dh0uspB)}=UE6tJVyb9dC3;xa6q4akQF)@QR`^sP z=IJj|8ABDjN|tBQ&CJgW33S1kP|BiHO_3Cpw-~HX#Z|}UYN*$H&B031YVik@RoXi# zqoPIWxmZGjd2e&yQWlx+g|)5f9E>Z{+aRe&!$&{|Qj^1|<$kc&z1XtPj3{Nfp456a z*H|<2&NcBNSijNlFN>IXzOk-G!WEd98b#thcGVXzu4OqrJ1%tR(g=|G7cV;&BFAUV zNJ*l;INAY0$Ff`o1gq2(ff$@s=EfH|iPh2)FP9Ia#I;SzUIQmQxT zrl9SiWT z`Mxx61fTWngt)j5Z%xQqDEMbtm{}+zfdCac=Bz+^IO4@Mz(I^k%S@)F^~>3F4ibIY zjW?pk6X3lq_HUBEVuft|+ULDY)O+m~D8ThF`F(8E@uQD$wk}~3JYrDqjM_(ZgS+UQ zh1VR5qdz%bz48MD1ovQTv-2I#;WN@|RiLXkan>a}DBUFPq(JNZg`#r@G>)LzzfgLU ztYDVN-w)kYG-h-;$5$Luajz$o_x7qrhPlf4Z-qB*3tQcegoi1VISa_XwJ6#BS26Eo zP8*yL=&k#{gdGL?K>^hE1&`F@cbpndU}yqeJR!$iQgGA!WtPTcpaKxuz(bt}mMzYZ zw6iRd0E{1KJxP*2AFuUm#Fz8W%!)c^pl;&QyTCG8;=>SFs5?S=ljCrnc06m%xvvcK z%)Pl1tq&^X^lme=WQ;Z7qdxB7h2)B6Gf|Qb_1n%9dy7~5I7%sP?_F{>k?@jnYv3}D zK4-YwX>4$2<6sE3{CHr7nIyBN&l&Se`%M4K8v@W`0lpJuF-5tfH2*!;0in-HKOPVW zsbp7*>39xN6R;F~&|AWQ`n`ZOxrYUn!E)2=|jfzybNK_@loE%B4!n!{6 zQ(}aC0`_If(R=iFfOLIB5OT?Ui#Uo; zuezd|1|Du)Q7f_?fcc$`ze5CU-E9)&Jy9ZzR<1&9fkZ3np@Gnwosd)4ryg`c>7xgr zJqG&R$vu%=N}!7cDw75Rwf{-12};^;65jyg+56>U(LZGjL)X`Fe;9(2lA|d1pRJ{L zGHoflrEgI~TO6W(jQJ;ubaw@IWz3ZqUL_Bn1x*;I%z{36m-iMKubZE#Ho4CX2t*g`RZzCoTbM}OtcZ2`t$yNd| z^WUL{LO|#4+Q8XbZ*Ae`2yPPJOuiRrbb7X#Y3aZyl=+Uc(KJpnR7)C6j!xw~Cr?`E z;9zvoaFlHrJi)4{p`yE z_ya(Ln6S+6hP|PR*BAkQz#9M!2NoLQX9VAbxZP zQqK)TaUbrWVMOvR)TKhBDg`s&AqL&vH558^5yIY-a9al7c(5Y!3j=Yabs!uVH!7Y6 z^Ytk7z0MR*q^1A3+4AKcU@83{ucuD~;a+&P&*G4RUVm~@rHgWJ7nw$@di3X_qy70z z!}+hSM+IQYJbuTAfzRi|)6_b|_a)=HMxnl-}LPcoN!dV1`Y7S>0)L zb+VkRxgM)ur>4GqLOqr|-r5NTDo@OfNh_SP0sOQhHV*QK_fhm_2jv_?eeq^3J&F`^ z)wjGPB`!Ix2wg8ewlvjANo!}PXEE=rT@iGYt~0vC1Nq`x5BdONMcg3MDTplDQ_Q(F zDG&uVo9csvZJ^D>CBceiFTganH0^)bsu0a)sC&l54PrGcw6CghRo35FG=-`h6jG3G zjc%|w$l_hYlPgUL4-du2#3d*_FkiPxtm}l&7Aa}S#4-WY&A7NSPi^=}m#^!}Z`a8f z;--prfEI)V_a;!)Bqa&WwI6KU1d+HUnmg$&w0%B~iR0OrRz&6QS0K})s)@p$CL}af zknQL1o{=F2%t7hH$~Hi%fEs4yQyM=3VP|NcZoR7$>4+K|E%W$_^D_V-c8R4@(+pBm zlAoL+%mD7JX8s-F;GEDRTiQ#@CM5+KqLp)#!T}(sO2HlKiowP~uGcxoqqS^3P4fBg zC?7uRe~xEemzd(~*Zy%a=%^cusE9$}o|Kei4G<72DyBP$sjRH5qzfn82qJ1rQmpN5 zmoLW<)pM++5qvZ8(V{N;_j#!)`%0;3Q3IhAM2Y>^H}>(HJjR3O;GVC)q^qo0TriZh zN>09Ry_HlE;WJnGE9%uyPOhe~j@00!GbOr$ zj?xvu=ChWo>H6siS*uNCQm^fcR<;X2MWk6aai0SdqW6uUrJS4(K6+ z(qx`g`wp)3i?qhzR(`GZ{s7?3DXIGh9=6VW3hg*J7yvV`<#aQ&5-$ADf3O9vcKiGF z|C$&8{DbW$6_GZ7&p%;^9+xBdkX7EQQgDn~9tUcP*L22PecDNE7Z(;ck5}6g_c0j= z$+PY=D=Bzed9!gZU8c6?%{ZADlkk!`47n6?EWH$8BO!Tc2@`d&mbl>}<2Ac3ht(W% zU?g$?ZqQ3i&_4^xl2CQgwZwJT0A#`CLuMe|-w$ry=#Bix+o9JO)VWYh$sC z+Kgms)VJsfMv1Swv{-rl$v42&6!o_I{6cC``~;p3hcy6n4mk*lcu`uKU0;%Mu?h<4 zGNa$%+0AxQQ*n_Hnoj!k)mZRV7(Zl4Ymt~it0wJJ_T#~Ds&#dI7R`>7%x$#h=I_Xm z!!T&9vk5UX8lM^zyo^@$$}JKdS1+Y5RWUCP0W^p!VvBj!j>n&#N08sN1@v%y8P}7I z5G~c&7caBcH(&D7J86)_+}}7prY5%NZ6+2&Su#&dCv&=A^c+LtRHz4U7}HdUYYjbv zSaYRP=9YCCR1B&^YRELe%cDEYn90bSwOwQ)0`#G}X38&!JuNIWw40PhIlRSZ$Xc;5 z8jwpMEu?weHy)tv0|+Ga__O-pP4dtx5lOD=9TY=?c!E60X3?IHf}@$PYH7SHn}@6r zf16`<8gN@!933yPH$+tq1n|?d{Z^8__}Nh5wA|(h2=%$JL)S}OeqkZkbHHJ7I^ye= zvv-d#kEuHnY`_0MBjgOTB*Vicry|C{?_kH_uFNzsf1cHJvAQng2mncJEOZI>hiKav z)dCX2cR?+Xy)tnUU@S{ZYl-gD>)WgV9)-2`JK`{Wvw7#=hU(I)|5whpePfXtX*T6< znLqZGHu3za@NchxTgFP-suL&{*&6FGvvius;hJ3J-FFwP0lp0|U9ei0j+F&}Kkdc# ztZMTI38|-@aKZiG8NkTs*cN)bUe8w>)a2z(Aafxw4;1n1#w4PlB0FznA_7UB&MH01 z(HH04&p);6{N*k(<*!YI@Bz>VYz*H)508U`b-A#$ z2oEK9?INsf=hA)F?(cZKz%^oj9ULe&+KO%iNF$%D2?f(yfSK-V0@1)=ud4IW{)i0# zp+QLjHN^KH=<%evIAdIVqzCvEV1GP;rdMcMtsfTitbx#TecB1A@ognNkkjIC4;svw z=4LweN(R~OH>RqSPaEB?CL%6^HxtB^=4V4Nl_G#z_doD=gfU~6+x$(6YI#iStqD@T zws)qi2R2rJN(O}lx~co!wty~v3wXCyuzAN@6F&SGgkB2`z=41-D3|i^1TZ*Ij>-+A z!$J?R*&_a^XBVfII_z8{-{D#^KC>7mlK)q*Y<0F!5WrnAkQ(zPOz-huS(Ur z8LUhiGS>n6k)p`?%K9!>SjiNC0!d2J#MXvPQE0>_OBbohn|+@fg$9~}O6mWAysta# z&<&`!ptKo1;`_e~0E-R=ZAg&CO6OEcsd$};ww06ORpRM3H4v2ob-kVSCIHlHh#sPC zVnhpqe~#l$Te`?RM(1qq^v-~XZljk4gq4q%K+^r!Rn@1r9Lr@X^I0Q?c$R-v8`JQp zG%2ZL;!J=fCLRwVF{8G2px0swuE0zwJSW#fCXe>31aS) z#a{iWgBAE%gRLn!6POzNA%@y;<#Gdk8jbO#shO!UI*2RQUIFpiD##LK8^6FZ8~+1( zt3P)AS0|QNa6R@iS=<27NRw63vGgC#j<0dQ&XvR(f=seLcAeFXs%8)5xIe4>@q=2L z^Y+`f@WB@7=lT1uW6sAbx@+BUl`I;34o#|6YeoKdXuO!tiJQLwyJ@%CjodQ+uxy*eh&3=q{KU$f>UMzvNlFltoYQHuY-q@bU~ zjg^Gv2Kw>B6H|Q4hm&o+I6>ty+Q!RVb%SielyZs+fB9QLo=?*qYj>-H>cs~V9^WB{ zjPRGXh1|jaIGkKF|C7VXOd9VMGa4{)!Z))U{zaaJ6pC~mYtva0o5kPrXctYz@r_4-Cn|n zzKiO5ix7n8InUSgFZYj$SVdQnH#70LXNu}uxdD_k5k>fn!Kp^}%BQ1CzjCk^8`I1I zOw2%G28x-9aq0;p!9GVv7#vWekf_^PvQ!xuOv?4c)M!LxDwYn0jg4aW89uMYa5IgYoR(@GTlQr z%2zr#m5-PtK2O3?IggtF{&Zf%o{I~)UWNXA2KOEWD-sStlj;JXSkO|M9H&M_Kp+!B zrHJYOQyQN{ZGc-uo&c0dwjis;H}-Cr%?x1{X`${7I02azAjfH_hZ`O5BIPL@zztv* zXXlr2KYmESA_S!#xICH}4Gk9LMx&TDeiW+LR4X?C)+PThom<4De)!2jn3BV8R;Msvjg|QggG{-hx zHFakEz_6xF%JMXo`jV24O}$Yal$M@Sj)p*!+w zgbaL1xmvI$6hMwLgA>#+syJev%weu7Pi2XnTW&Y>$@Nda>GANX-wPxpRUptM@d@bq zNH~%q^KVPW9Hq!y0Zjxv_N)LEo`cm-H5>Q2jSEg={7-sB^c@`^8LrM!uNGF!53Su} zHwvg_nK$V(#&PX?gflU@(`>~vM{%4Ua)Ib5$}Qa~5iu4`rgzo2H)^&FI1`=%#k%_9 zg2v)PbyyWL0zxtuWO`sbOzO``)$H%Y1O+Mc2S=C{^BOKzd< zv@TAn6T*}7)beDxvl_X|DF{ZmScZd6jV?5H@9>*@B`rTavKH5UUmbd<5 zhOWh1sn4l{ev8Scw_nm*g5BS&{sJ0es5@8E`KgFDrWS9;`KR4MPBhck2P`$q(~Pr; zyD?~Cx%Ha!c?Pe21zth&)) zE67}Q<$A)xhQ>p@^@lPn4Bkpfr3SO>2_A3E7_l0D{=26fgCMUN-VgfU)RG=_fJ2BIu-7#P>ZcP|U*8JP$)&ut)W9&+l|0 zH4|hUyS=J1^Qteq88w7c6cmcALw`@2uo>r?SEKuMA;7zFAwJd^sP**tziNU;LRT>hIlH_0FF*|7LsL+8R?>Y zWe1Hk5Ljq(I5uTx^8hShetzWp5!t&SRW+;v3Ope7H=j8h!++e?>YK5K`@iueyqLMz zD6p3U&I5-Qr=5+!R(GJc1p)}S2k!*&SalL(OVhO&3;-B`|KO)*SM-oIm=dtKsD|N- zTl_BKl*U5c)z$U1On7Fry|h@GJO&i%y5(&4Zkj1S$EIn2j}KV7yhShHd-k=`#>wSu zqtRq@i|-A&^Zf@J>+j$a(^9S97YAErc_1^wjbaZ}{okP4;yk}xNz@o^_sOeYm8w=U z1LaOs53i`Gq@#^>_UM5>)ZMG9l{)JrE(s0gIWYo`HGGcFb;Q z#AYSU+i)#4nF}(d^ziZ-Nr2u47byT64dzzx=Q4F*Nun%$tSTaEt!M)FOL_7boY1IJ z&y!mTS`*HQ^`0O9EnrJeSZ~rLUp@o=?i`}DOioFjS4=_aeE-QY7yv_}$vf|XIf#Oc zt*NN$=ZE7QCuJrM4ltpAZ5=y2rkR9B=R2_6susU}8~8t(JM(a;_r8zQ#&Hr#I8nAD zl9807WJ;ul>`NlD?_^iDI+kK&If!$}6b;F4Le@F9tdWpqFvJ-9kbQ=k=fiWK`~Ks3 zp6j}o>$&dRU#{^pGr!;bzVrQj-=FvU^{w)rkIG4*t1NZv4jIhbwyRL*=(1 z^yV%$f7nrgMKc2CHK=I{gC{;VWXj2Z7fnC%k!TeWd5fEk@L?g%Q0fmo@|vmBQd+TI zR+vl1SrpuB|`$|lu z*(1-v1BC&dp8QNZH6t9Sk;1Z`4{qD{VFO2MF7J57CAio%wOse^D0w@GPZNI;XPBq! z(}ja>E8sH&me&GdF;S-l+q#~!skNMdF?JDpwXr&IY+(tKu|~9(g&xk-{E^rqYlDV~ zwx)4=0EW={|KUz^G|j9?%;xXEWnOz0to|rgv*s2&>AZ#yJ)7k9_Hs~--t_zQ}E<2 z$Xz5n)~-K;=m|dKIX%;k&G|vtpekLR9F3<=c3x4e_NL_f`QR2lXl*d-<(lHWLGlfa zy`+R7_i(K!aBck`^Z70YfYSllV4}XXIABvT_pNd>bQT$Zns2g*$+XC}{Gj*nCluNA1Hq|oVU4jV_=yM%I>;i*<0 ze{LgaF{HJx z-%B4z2s8MI7|)q_h^#Es2XBlrV%-W3Pfv0}@(;3pQ?v6TK0ZoH%<3-+*x8~#yNGac z>;@8O=S3ugfNC&JY3@}QhuEegqgux5A#^c;F9mi<14--%tHJH1aTdrQL)bm~pe?Ls z038Irl?p^$+Z(u9z^*Kt-QU=IMdDPT&LryCd}SL8D2zdf`IM1HaD154=XFtXWgJyk#`=+!1vk-GCJzJ z?H~Xc8apXg+k&89qNkj*7GPqUOo!N9$hjwwL{Ay-0j~^R90!SBY~w?4kU)OznlKj_ z0l-@MyPwb3{KUoYPcZsRk>aytjck0uWyJa;C-o405!<4EI1nw1=`s(f^%Jz(+RFd( zZHwPXld;^1gyv_VA+o8?EVAT{RC6xspA5lQ4uI2R^LY%(IlvE56-kDX3a(4MQ|_3Ol<_nBxPe z1KtE!5cEj))>oNiMKfF|wZ0&4z84(*S;49M7OR5$9AZ4a%(Xrr+VWh=N?Y~8Ai^6Z z@VfSYKioI07yM;YUcSS~C^0wC)d(_)DpD2htL;gc;Eh2Jde{w|c6mbdWeb$Uk2nZ4BQVIN z*4LOz3gr;@BG$M|`!_yvk-NzXDFAQETBCtesqAla!Ko4$FGa4>JX4%1%?>Ca(iyD6 z9_1_Oj9_b71*wbt*yHdi3q;(3uQ=O95p?5;6DPg|V;9GUK}rCmM1Nnm_jc=ad=rBT zZ#)JZ3Db6VqT8tw5);J`BU6x*qLPg05#tl!SszX0O+zjZKn>Q@6=#7Gv_idD_mrYw z@2ER(RT26+&8oe=z+mm`PPvjf=Xv)`&U5Z^3H6=?c|ko<@@8#S>7i@4t1ky)+t9vFhS18~@WEsBRc zBa3n~v|D77+tGGNqwEA&t%QZD+E`!7@RyfR819HRG|+kDkIg+v>~8a|lQGLPB&90C z>a7(2K)VbKL`I=}9C~3#3e|hWZfAwNJo1_`#+rsO$4pn?@^KN5>7S zg5JzD7wXiv_o{91g#dmk$N)e`XNQe8SW_tx809cUzJpD&JnB_p6`(7L&s4Mt`e-T@ z|FzXo6b8`Y3nVR#0VgQ6^<`EUrrpcaVC>eXUz^9UulAaa(5dpRpz(w0T5m6Lg+i|I zpO#+*mzLjLBeEO9P%|;hJ&q3VfHruombhP2>Y`e(zN4oooR=2Ewi=XDD0^KIATiUK zg{g5zn_5&E;<>+a0JX7gZ5vV|Y79COwyUq7yh8P5{G?&%Tvt{6>z;WGigeT4rlo2> zTAV8OiL@+ErB=ZA6(_p!8uJ0B$K`M(H06GGS3k_ja_Ju9=tWwk0~Z9nc#YPjEmDkk zZbJd(<|7saKs=c+@LgRL9t>c_Y;Z4us@v1AedgFPa72Z2&Trp3LgVZH+*yP|sLu98 z#L&q=SEo%LCe>eZqg$$}-N^kxDoaUUC>tfRZ)ZJcOmRJ5a4 zNM6{>JPPBxOGwPEQ z7WN-_5`X+BG=TYAUCa`|MT=lO1QSXTZZP;LaE+ zX`WIEA!DhVEHvtVg9N1&4%Y0`fqY3a!CNO16>At9W7RH~IW{&~G6ME6{V_zEA1C(p zl~;Gd1^KHr}(V%v7l4Gp;C+%TbBTt|rnQGqVnu(ZWf6qXJB zOqh6RbpcG~7#$%lbZ!bqDCg4RXDrSfaHoWFax4xvTV8-P$YCeT0Ov9{Tk@z+sn2`) zPW4Z6er3R2o23pwj0PR0d39_bcu>xYNn^8eaOMcH+#C`>b&~t7Wo?r?eai+_uJ28M z9VAG+dM54Vb70|sVf&sv`QvJPyIEeBy%$1rpy{*O)^UNUUX!;s9EXEC*t?^&tUfN5$#@56vLJ%oybufLaCZQ^#Oq2SJI!-8$QFhP>H-s!;(lfeXmvN@ z%vZdA>~%Cyj~`7jA$RlI@GBPM{DPIYL0N{Mi2 zp84BMCG7LS=S-kmT_7|n^6Us(^2q6F)R$cIFMaR%VY>w=PU>#9ZMtutqQr$ zZx&o3EpX3&f@;%5oLXD$^sv0IiSZ4T2{EkH$xz7s(|q%L^b^4^jc{XJn8gV8Mx|}e zSSdG~P_`_$&RaYiky{9H+lq<`REkmBh5}BqO%N%$VfzaIbfFn~O(r!SAz33Q_hCII zM&y&6a@1{fv(Y&O2nPX*Xc{rrJ9P4cFHKj=S3JH&^CoKb`x-uAER?Pn5=9OPy4pWz znv_-)FmRs#r>izdH7tiBXfPxcjLi+R=?jEyw%njTt$ zZg+XDm1LF|jXIECH?&mX)?X|xEb%Gff2k>x36Vc~QUX0UpSm%!jAK55MB&$J@Bf8+ z&t4`WK3O&yU&x1!$Ln&j@2*pYghDAvH6yMTc7#3chj-NiA-}nO0dDqo;P*`>oss7= zcL!YpepvtJ65ACs;GsX4+5b7K-+$$u{CPJ2&)UTQtr)olHD}GB= LQzc*d{xAOp4-f8W literal 0 HcmV?d00001 diff --git a/assets/og/reject-option-classification.png b/assets/og/reject-option-classification.png new file mode 100644 index 0000000000000000000000000000000000000000..8f571c53e297909f55d49611c499b59f6948aa7c GIT binary patch literal 64808 zcmdSBbySsK*Dh=!h$0OFBHbn3A#A$4L0Ve6L8M!{K}xy>q?Kk<(rg-uO?T&6_~!Gr5PNys}D*Xiv!6HiRoB;x*PZUWDV(zLL&uP{PrBlyD`##Fm**cjH> zxb>&y2i7Kos1(BHShMV5)2kji%8^{z=T|=73#d#f8^-nytSAm^^B$22@d3;a!DoO^ zxfA4b{O9F^N5X&KdLSf(^v??-dPp$UU==N*XQPn3_=xv0yda`N-*`U;`p zoGu-XYr~oJ=%}fGpIbgVKJhqNXS0%MJ=J}>i1jyOiNn!u#pgWsbJcE~d7X(2-vs)% zY>jzUsLxHDq&RMm+p0JoOmnb*(?m(e*ANQNEl>n}v#- z0s)Tt_skgh?;~EK9hR&hYSwPbuLWryB{bim4PL)S!{V_yoTbB!+`ni#BND*AT3lN* z<(scd5@bFoHeG1R@w}aa@mDePHC;F^fPaM>Mme1*`YT+-)tNDT$th zGEuvp38Zx|vs)+x1?#oG{JDX6|H(qHNUqC^H#Gf%1w ziTJkXy0bLEeBw2g3Q!@ww{^qAnmL49=w$Mo?G_#lg-mccc;a?fSj~mj8Okfr8KLE>W7YTVL5R>NU)Ga7FrVL%1TRjaM7--Yn(Sb6y4n$0s;a&P+zNmm$$LetM~>F zOL;}0>f}U1|4-&5E+M%lI^6Ygwb^a0q1d*vHeCJ_vR;S16(Ee>YwUo>?kTjDAd7;6 z@@E+{vFx0TLtv?6i7?&cg#i&nUf$)DDc0S2FDW{s@_lcL8B^|I%lhVKe~LhsOF3g< zp?UQh;|b~u5>k1WI?>i!r5yM1I)lA#`Ha+K_T-g#pY_q==jd}SS8tgm4W>uB<@J#R zga^eC5w8w%g2sxsO7rtmqodtc&SA=CjL{=a>7q2jQZKUt+)@blo@S*UqOk5irVP9U?@7Oqbgbi&EXZuhZ5|E+DxnE2rG&UAzK zanC!`Z&Vry$T(9?N5G<$guQITFE zd-u(=ROm-(tIH*&q`Y{|ljWA0K~T4?c`!3uUrkBJ^LdQddidld_0z3aBc`I^$YjAf zlRX_{27hI~ba$6d!YkRSvdwmsHS*ci46wmEvI!YNeF)?hjV6rF}m4O}| zo%QglZn^6PGc)_{h{O6a6;p7})Ku^g{I1@4qd~CFdb&aULVF9=jESE2El)6(kv(hn zdvA_9efrt{!I3#Du9vJFNjC4<8-a89#+0I8Ghb2hxm>b-FX0?QaOIY{?_tOpT2lcf5zNK7lunkmTIv@H;R>cOuh`my*|9|+=?⪙Xg_ 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ⅆ?akx7-*w82MOW-0mAIN@oV&LS| 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

}he2Z_qUOTB1|ET7r=3 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 Q@dcKXQNB|o{qV`(0cRmi?*IS* literal 0 HcmV?d00001 diff --git a/explainers/reject-option-classification.html b/explainers/reject-option-classification.html new file mode 100644 index 0000000..9e06d5a --- /dev/null +++ b/explainers/reject-option-classification.html @@ -0,0 +1,372 @@ + + + + + +What Is Reject Option Classification? · Fair Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + +
+
Explainer
+

What Is Reject Option Classification?

+

Flip the model's least-confident predictions toward the group history treated worst.

+

Learn how Reject Option Classification (Kamiran, Karim & Zhang, 2012) post-processes a model by reassigning labels only inside a low-confidence band near the decision boundary, and why the band's width - a free parameter with no principled default - decides whether the fairness gap shrinks, holds, or reverses. Worked on the COMPAS baseline logistic regression: a +-0.10 band flips 651 of 3,254 predictions and halves the gap, while a +-0.15 band overcorrects it to -70 pp and collapses accuracy.

+
+ +

What Is Reject Option Classification?

+

When a model is least sure of itself, it has the least evidence to defend its choice. Reject Option Classification takes exactly those borderline cases and hands the favorable outcome to the group history treated worst, on the bet that correcting for bias costs the least where the model was already guessing.

+

The One-Sentence Definition

+

Reject Option Classification (ROC; Kamiran, Karim and Zhang, 2012) is a post-processing bias mitigation that defines a "critical region" of low-confidence predictions near the decision boundary and, only inside that region, assigns the favorable label to instances from the disadvantaged group and the unfavorable label to instances from the advantaged group.

+

Not the same as Reject Inference. That explainer's "reject" is about rejected loan applicants who never entered the training data - a selection-bias problem in credit scoring. This explainer's "reject" is the classifier's reject option: the band of inputs a probabilistic model is too uncertain about to commit to. Same word, unrelated ideas. (The same name-collision warning Counterfactual Explanation carries for its overlap with counterfactual fairness.)

+

Why It Matters

+

This repo's benchmark harness already includes a post-processing mitigation as strategy S4 - Fairlearn's ThresholdOptimizer, which searches for a per-group decision threshold that makes the whole model satisfy a fairness constraint. ROC is a different post-processing mechanism with the same access level (model outputs only, no retraining):

+
ThresholdOptimizer (this repo's S4)Reject Option Classification
What it changesone decision threshold per group, applied to every predictionthe label of individual predictions, only inside a confidence band
Where it actsglobally, across the whole score rangelocally, near p = 0.5
Free parameterthe fairness constraint to satisfythe width of the critical region
Rationalepick thresholds that equalize a chosen rateflip where the model had the least evidence, so accuracy loss is smallest
+

ROC's appeal is the "least evidence" argument: a prediction with p = 0.52 is barely a prediction at all, so overriding it toward the disadvantaged group is a small, defensible correction. Its weakness is that "how wide is the band" has no principled answer - and, as the worked example shows, the answer completely determines whether you fix the gap, do nothing, or overcorrect into a mirror-image disparity.

+

How It Works

+

Let p_i = P(Y = 1 | X_i) be the model's predicted probability of the unfavorable outcome (here: "high risk"), and let Y = 1 be unfavorable, Y = 0 favorable.

+

1. Baseline prediction: y_hat_i = 1 if p_i >= 0.5 else 0. 2. Critical region: pick a half-width theta in (0, 0.5] and define the region as 0.5 - theta <= p_i <= 0.5 + theta. Outside it, keep the baseline prediction. 3. Flip rule inside the region:

+
  • disadvantaged group -> favorable outcome (y_hat_i = 0)
  • advantaged group -> unfavorable outcome (y_hat_i = 1)
+

The flip toward the advantaged group is what keeps ROC from simply lowering everyone's positive rate: it trades favorable outcomes from the advantaged group for favorable outcomes to the disadvantaged group, inside the band, rather than just relabelling one side.

+

theta is the entire design. theta -> 0 recovers the untouched model. theta = 0.5 puts every prediction in the region, so the output becomes "disadvantaged group all-favorable, advantaged group all-unfavorable" regardless of the features.

+

Concrete Example: COMPAS - Audit 01

+

COMPAS/ audits the ProPublica COMPAS raw file, filtered (per audit.yaml) to African-American and Caucasian defendants scored for "Risk of Recidivism" (~16.3k rows). Following the audit's setup, a logistic-regression baseline was trained on Sex_Code_Text, race, CustodyStatus, MaritalStatus (an 80/20 split, random_state=42), and ROC was applied to its test-set probabilities. Favorable outcome = "not high risk"; disadvantaged group = African-American defendants.

+

Baseline model (no ROC):

+
Value
Black defendants flagged high-risk86.1%
White defendants flagged high-risk0.1%
Demographic parity gap+86.0 pp
Test accuracy65.9%
+

The baseline is close to a step function - race dominates the model, so almost every predicted probability sits near 0 or near 1 and very few land near the boundary. That is the setting ROC handles worst, and it shows:

+
Critical region thetaPredictions in region (of 3,254)Predictions flippedNew parity gapTest accuracy
baseline--+86.0 pp65.9%
±0.051717+85.0 pp65.9%
±0.10671651+43.9 pp61.0%
±0.152,6092,566-70.2 pp45.5%
+
  • ±0.05 touches 17 of 3,254 test rows. The gap barely moves and accuracy is unchanged, because the model is almost never uncertain - it committed hard, using race.
  • ±0.10 flips 651 predictions and roughly halves the gap (+86 -> +44 pp), at a ~5-point accuracy cost. This is the band where ROC does what it is supposed to.
  • ±0.15 pulls in 80% of the test set. The "flip rule" now overrides the model on the large majority of cases, the gap reverses to -70 pp (Black defendants now flagged less), and accuracy collapses to 45.5% - worse than predicting the majority class.
+

No value of theta was "correct"; the three rows above are three different fairness outcomes produced by three arbitrary choices of one number. That is the central caveat, made concrete.

+
import numpy as np
+import pandas as pd
+from sklearn.linear_model import LogisticRegression
+from sklearn.model_selection import train_test_split
+from sklearn.preprocessing import StandardScaler
+
+df = pd.read_csv("COMPAS/compas-scores-raw.csv")
+df = df[df["Ethnic_Code_Text"].isin(["African-American", "Caucasian"])]
+df = df[df["DisplayText"] == "Risk of Recidivism"].copy()
+df["high_risk"] = df["ScoreText"].isin(["High", "Medium"]).astype(int)
+df["is_black"] = (df["Ethnic_Code_Text"] == "African-American").astype(int)
+
+X = pd.get_dummies(df[["Sex_Code_Text", "is_black", "CustodyStatus",
+                       "MaritalStatus"]]).astype(float)
+y, g = df["high_risk"].to_numpy(), df["is_black"].to_numpy()
+X_tr, X_te, y_tr, y_te, g_tr, g_te = train_test_split(
+    X, y, g, test_size=0.2, random_state=42, stratify=y)
+
+scaler = StandardScaler().fit(X_tr)
+model = LogisticRegression(max_iter=1000).fit(scaler.transform(X_tr), y_tr)
+p = model.predict_proba(scaler.transform(X_te))[:, 1]
+baseline = (p >= 0.5).astype(int)
+
+for theta in (0.05, 0.10, 0.15):
+    region = np.abs(p - 0.5) <= theta
+    roc = baseline.copy()
+    roc[region & (g_te == 1)] = 0   # disadvantaged -> favorable (not high risk)
+    roc[region & (g_te == 0)] = 1   # advantaged   -> unfavorable
+    gap = roc[g_te == 1].mean() - roc[g_te == 0].mean()
+    print(f"theta=+/-{theta}: {region.sum():4d} in region, "
+          f"{(roc != baseline).sum():4d} flipped, gap {gap:+.3f}, "
+          f"acc {(roc == y_te).mean():.3f}")
+

Detection / Implementation Code

+

A reusable ROC post-processor plus a helper that sweeps theta so the parameter's effect is visible rather than hidden.

+
import numpy as np
+import pandas as pd
+
+
+def reject_option_classify(
+    proba_unfavorable: np.ndarray,
+    group: np.ndarray,
+    disadvantaged_value,
+    theta: float,
+    boundary: float = 0.5,
+) -> np.ndarray:
+    """
+    Apply Reject Option Classification to a probabilistic model's output.
+
+    proba_unfavorable : P(Y = 1) where Y = 1 is the UNfavorable outcome.
+    group             : group membership, aligned to proba_unfavorable.
+    disadvantaged_value : the value in `group` that marks the disadvantaged
+                          group (gets the favorable outcome inside the band).
+    theta             : half-width of the critical region, in (0, boundary].
+    boundary          : decision threshold (default 0.5).
+
+    Returns the post-processed 0/1 predictions (1 = unfavorable).
+    """
+    if not 0 < theta <= boundary:
+        raise ValueError(f"theta must be in (0, {boundary}], got {theta}")
+
+    proba = np.asarray(proba_unfavorable, dtype=float)
+    grp = np.asarray(group)
+    pred = (proba >= boundary).astype(int)
+
+    in_region = np.abs(proba - boundary) <= theta
+    is_disadvantaged = grp == disadvantaged_value
+
+    pred[in_region & is_disadvantaged] = 0    # favorable
+    pred[in_region & ~is_disadvantaged] = 1   # unfavorable
+    return pred
+
+
+def sweep_theta(
+    proba_unfavorable: np.ndarray,
+    group: np.ndarray,
+    y_true: np.ndarray,
+    disadvantaged_value,
+    advantaged_value,
+    thetas=(0.02, 0.05, 0.10, 0.15, 0.20, 0.30),
+    boundary: float = 0.5,
+) -> pd.DataFrame:
+    """Run ROC across a range of theta and report, for each: how many
+    predictions fell in the critical region, how many actually flipped, the
+    resulting demographic-parity gap (disadvantaged - advantaged positive
+    rate on the UNfavorable label), and overall accuracy. There is no
+    'best' row - the point is that the choice is unconstrained."""
+    proba = np.asarray(proba_unfavorable, dtype=float)
+    grp = np.asarray(group)
+    y = np.asarray(y_true, dtype=int)
+    baseline = (proba >= boundary).astype(int)
+
+    def gap(pred):
+        return (pred[grp == disadvantaged_value].mean()
+                - pred[grp == advantaged_value].mean())
+
+    rows = [{
+        "theta": 0.0, "in_region": 0, "flipped": 0,
+        "parity_gap": gap(baseline), "accuracy": (baseline == y).mean(),
+    }]
+    for theta in thetas:
+        pred = reject_option_classify(proba, grp, disadvantaged_value,
+                                      theta, boundary)
+        in_region = int((np.abs(proba - boundary) <= theta).sum())
+        rows.append({
+            "theta": theta,
+            "in_region": in_region,
+            "flipped": int((pred != baseline).sum()),
+            "parity_gap": gap(pred),
+            "accuracy": (pred == y).mean(),
+        })
+    return pd.DataFrame(rows)
+
+
+# Usage (see the COMPAS example above for how p, g_te, y_te are produced):
+# print(sweep_theta(p, g_te, y_te, disadvantaged_value=1, advantaged_value=0))
+

Limitations and Trade-offs

+

1. The critical-region width has no principled default

+

Every number in the worked example - "gap halved", "gap reversed", "accuracy destroyed" - is a consequence of picking theta. The original paper frames the choice through decision theory (a loss ratio between the two error types), which relocates the arbitrariness into choosing that ratio rather than removing it. In practice theta is tuned on a validation set against whatever fairness/accuracy trade-off the deployer already had in mind, which means ROC does not decide the trade-off, it just implements a chosen one.

+

2. It needs group membership at prediction time

+

Like every post-processing method (including this repo's ThresholdOptimizer), the flip rule reads the protected attribute for each individual at inference. In hiring, lending, and housing that is often the exact input a deployer is legally barred from using in the decision, or does not reliably have. A model that must not see race cannot run ROC on race.

+

3. It can invert the disparity instead of removing it

+

Because the flip rule is unconditional inside the band, a wide theta on a confident model (the COMPAS case) does not shrink the gap toward zero - it drags it past zero. ROC has no "stop at parity" mechanism; monitoring the post-processed gap and backing theta off is a manual outer loop.

+

4. It optimizes a rate, not the individuals

+

Two defendants with p = 0.49 and p = 0.51 get opposite treatment based on group, not on any difference between them - the same individual-fairness objection that applies to per-group thresholds. ROC trades group-rate fairness for individual-level consistency in the band.

+ + + +
  • COMPAS/ - the audit used above; its baseline is confident enough that ROC either does almost nothing (theta = 0.05) or overcorrects (theta >= 0.15).
  • German Credit Lending/ - a smaller-gap audit where a model with more mass near the boundary would give ROC a wider useful theta range.
+

Further Reading

+ +
+

Part of The Fair Code Project - exposing and fixing algorithmic bias with real data and open code.

+
+ + + + diff --git a/explainers/reject-option-classification.md b/explainers/reject-option-classification.md new file mode 100644 index 0000000..46e590d --- /dev/null +++ b/explainers/reject-option-classification.md @@ -0,0 +1,228 @@ +# What Is Reject Option Classification? + +> *When a model is least sure of itself, it has the least evidence to defend its choice. Reject Option Classification takes exactly those borderline cases and hands the favorable outcome to the group history treated worst, on the bet that correcting for bias costs the least where the model was already guessing.* + +## The One-Sentence Definition + +**Reject Option Classification** (ROC; Kamiran, Karim and Zhang, 2012) is a post-processing bias mitigation that defines a "critical region" of low-confidence predictions near the decision boundary and, only inside that region, assigns the favorable label to instances from the disadvantaged group and the unfavorable label to instances from the advantaged group. + +> **Not the same as [Reject Inference](reject-inference.md).** That explainer's "reject" is about *rejected loan applicants* who never entered the training data - a selection-bias problem in credit scoring. This explainer's "reject" is the classifier's *reject option*: the band of inputs a probabilistic model is too uncertain about to commit to. Same word, unrelated ideas. (The same name-collision warning [Counterfactual Explanation](counterfactual-explanation.md) carries for its overlap with counterfactual fairness.) + +## Why It Matters + +This repo's benchmark harness already includes a post-processing mitigation as strategy **S4** - Fairlearn's `ThresholdOptimizer`, which searches for a *per-group decision threshold* that makes the whole model satisfy a fairness constraint. ROC is a different post-processing mechanism with the same access level (model outputs only, no retraining): + +| | `ThresholdOptimizer` (this repo's S4) | Reject Option Classification | +|---|---|---| +| What it changes | one decision threshold per group, applied to every prediction | the label of individual predictions, only inside a confidence band | +| Where it acts | globally, across the whole score range | locally, near `p = 0.5` | +| Free parameter | the fairness constraint to satisfy | the width of the critical region | +| Rationale | pick thresholds that equalize a chosen rate | flip where the model had the least evidence, so accuracy loss is smallest | + +ROC's appeal is the "least evidence" argument: a prediction with `p = 0.52` is barely a prediction at all, so overriding it toward the disadvantaged group is a small, defensible correction. Its weakness is that "how wide is the band" has no principled answer - and, as the worked example shows, the answer completely determines whether you fix the gap, do nothing, or overcorrect into a mirror-image disparity. + +## How It Works + +Let `p_i = P(Y = 1 | X_i)` be the model's predicted probability of the *unfavorable* outcome (here: "high risk"), and let `Y = 1` be unfavorable, `Y = 0` favorable. + +1. **Baseline prediction:** `y_hat_i = 1 if p_i >= 0.5 else 0`. +2. **Critical region:** pick a half-width `theta` in `(0, 0.5]` and define the region as `0.5 - theta <= p_i <= 0.5 + theta`. Outside it, keep the baseline prediction. +3. **Flip rule inside the region:** + - disadvantaged group -> favorable outcome (`y_hat_i = 0`) + - advantaged group -> unfavorable outcome (`y_hat_i = 1`) + +The flip toward the advantaged group is what keeps ROC from simply lowering everyone's positive rate: it trades favorable outcomes from the advantaged group for favorable outcomes to the disadvantaged group, inside the band, rather than just relabelling one side. + +`theta` is the entire design. `theta -> 0` recovers the untouched model. `theta = 0.5` puts every prediction in the region, so the output becomes "disadvantaged group all-favorable, advantaged group all-unfavorable" regardless of the features. + +## Concrete Example: COMPAS - Audit 01 + +`COMPAS/` audits the ProPublica COMPAS raw file, filtered (per `audit.yaml`) to African-American and Caucasian defendants scored for "Risk of Recidivism" (~16.3k rows). Following the audit's setup, a logistic-regression baseline was trained on `Sex_Code_Text`, `race`, `CustodyStatus`, `MaritalStatus` (an 80/20 split, `random_state=42`), and ROC was applied to its test-set probabilities. Favorable outcome = "not high risk"; disadvantaged group = African-American defendants. + +**Baseline model (no ROC):** + +| | Value | +|---|---:| +| Black defendants flagged high-risk | 86.1% | +| White defendants flagged high-risk | 0.1% | +| Demographic parity gap | **+86.0 pp** | +| Test accuracy | 65.9% | + +The baseline is close to a step function - `race` dominates the model, so almost every predicted probability sits near 0 or near 1 and very few land near the boundary. That is the setting ROC handles worst, and it shows: + +| Critical region `theta` | Predictions in region (of 3,254) | Predictions flipped | New parity gap | Test accuracy | +|---|---:|---:|---:|---:| +| baseline | - | - | +86.0 pp | 65.9% | +| ±0.05 | 17 | 17 | **+85.0 pp** | 65.9% | +| ±0.10 | 671 | 651 | **+43.9 pp** | 61.0% | +| ±0.15 | 2,609 | 2,566 | **-70.2 pp** | 45.5% | + +- **±0.05** touches 17 of 3,254 test rows. The gap barely moves and accuracy is unchanged, because the model is almost never uncertain - it committed hard, using race. +- **±0.10** flips 651 predictions and roughly halves the gap (+86 -> +44 pp), at a ~5-point accuracy cost. This is the band where ROC does what it is supposed to. +- **±0.15** pulls in 80% of the test set. The "flip rule" now overrides the model on the large majority of cases, the gap **reverses** to -70 pp (Black defendants now flagged *less*), and accuracy collapses to 45.5% - worse than predicting the majority class. + +No value of `theta` was "correct"; the three rows above are three different fairness outcomes produced by three arbitrary choices of one number. That is the central caveat, made concrete. + +```python +import numpy as np +import pandas as pd +from sklearn.linear_model import LogisticRegression +from sklearn.model_selection import train_test_split +from sklearn.preprocessing import StandardScaler + +df = pd.read_csv("COMPAS/compas-scores-raw.csv") +df = df[df["Ethnic_Code_Text"].isin(["African-American", "Caucasian"])] +df = df[df["DisplayText"] == "Risk of Recidivism"].copy() +df["high_risk"] = df["ScoreText"].isin(["High", "Medium"]).astype(int) +df["is_black"] = (df["Ethnic_Code_Text"] == "African-American").astype(int) + +X = pd.get_dummies(df[["Sex_Code_Text", "is_black", "CustodyStatus", + "MaritalStatus"]]).astype(float) +y, g = df["high_risk"].to_numpy(), df["is_black"].to_numpy() +X_tr, X_te, y_tr, y_te, g_tr, g_te = train_test_split( + X, y, g, test_size=0.2, random_state=42, stratify=y) + +scaler = StandardScaler().fit(X_tr) +model = LogisticRegression(max_iter=1000).fit(scaler.transform(X_tr), y_tr) +p = model.predict_proba(scaler.transform(X_te))[:, 1] +baseline = (p >= 0.5).astype(int) + +for theta in (0.05, 0.10, 0.15): + region = np.abs(p - 0.5) <= theta + roc = baseline.copy() + roc[region & (g_te == 1)] = 0 # disadvantaged -> favorable (not high risk) + roc[region & (g_te == 0)] = 1 # advantaged -> unfavorable + gap = roc[g_te == 1].mean() - roc[g_te == 0].mean() + print(f"theta=+/-{theta}: {region.sum():4d} in region, " + f"{(roc != baseline).sum():4d} flipped, gap {gap:+.3f}, " + f"acc {(roc == y_te).mean():.3f}") +``` + +## Detection / Implementation Code + +A reusable ROC post-processor plus a helper that sweeps `theta` so the parameter's effect is visible rather than hidden. + +```python +import numpy as np +import pandas as pd + + +def reject_option_classify( + proba_unfavorable: np.ndarray, + group: np.ndarray, + disadvantaged_value, + theta: float, + boundary: float = 0.5, +) -> np.ndarray: + """ + Apply Reject Option Classification to a probabilistic model's output. + + proba_unfavorable : P(Y = 1) where Y = 1 is the UNfavorable outcome. + group : group membership, aligned to proba_unfavorable. + disadvantaged_value : the value in `group` that marks the disadvantaged + group (gets the favorable outcome inside the band). + theta : half-width of the critical region, in (0, boundary]. + boundary : decision threshold (default 0.5). + + Returns the post-processed 0/1 predictions (1 = unfavorable). + """ + if not 0 < theta <= boundary: + raise ValueError(f"theta must be in (0, {boundary}], got {theta}") + + proba = np.asarray(proba_unfavorable, dtype=float) + grp = np.asarray(group) + pred = (proba >= boundary).astype(int) + + in_region = np.abs(proba - boundary) <= theta + is_disadvantaged = grp == disadvantaged_value + + pred[in_region & is_disadvantaged] = 0 # favorable + pred[in_region & ~is_disadvantaged] = 1 # unfavorable + return pred + + +def sweep_theta( + proba_unfavorable: np.ndarray, + group: np.ndarray, + y_true: np.ndarray, + disadvantaged_value, + advantaged_value, + thetas=(0.02, 0.05, 0.10, 0.15, 0.20, 0.30), + boundary: float = 0.5, +) -> pd.DataFrame: + """Run ROC across a range of theta and report, for each: how many + predictions fell in the critical region, how many actually flipped, the + resulting demographic-parity gap (disadvantaged - advantaged positive + rate on the UNfavorable label), and overall accuracy. There is no + 'best' row - the point is that the choice is unconstrained.""" + proba = np.asarray(proba_unfavorable, dtype=float) + grp = np.asarray(group) + y = np.asarray(y_true, dtype=int) + baseline = (proba >= boundary).astype(int) + + def gap(pred): + return (pred[grp == disadvantaged_value].mean() + - pred[grp == advantaged_value].mean()) + + rows = [{ + "theta": 0.0, "in_region": 0, "flipped": 0, + "parity_gap": gap(baseline), "accuracy": (baseline == y).mean(), + }] + for theta in thetas: + pred = reject_option_classify(proba, grp, disadvantaged_value, + theta, boundary) + in_region = int((np.abs(proba - boundary) <= theta).sum()) + rows.append({ + "theta": theta, + "in_region": in_region, + "flipped": int((pred != baseline).sum()), + "parity_gap": gap(pred), + "accuracy": (pred == y).mean(), + }) + return pd.DataFrame(rows) + + +# Usage (see the COMPAS example above for how p, g_te, y_te are produced): +# print(sweep_theta(p, g_te, y_te, disadvantaged_value=1, advantaged_value=0)) +``` + +## Limitations and Trade-offs + +### 1. The critical-region width has no principled default + +Every number in the worked example - "gap halved", "gap reversed", "accuracy destroyed" - is a consequence of picking `theta`. The original paper frames the choice through decision theory (a loss ratio between the two error types), which relocates the arbitrariness into choosing that ratio rather than removing it. In practice `theta` is tuned on a validation set against whatever fairness/accuracy trade-off the deployer already had in mind, which means ROC does not decide the trade-off, it just implements a chosen one. + +### 2. It needs group membership at prediction time + +Like every post-processing method (including this repo's `ThresholdOptimizer`), the flip rule reads the protected attribute for each individual at inference. In hiring, lending, and housing that is often the exact input a deployer is legally barred from using in the decision, or does not reliably have. A model that must not see race cannot run ROC on race. + +### 3. It can invert the disparity instead of removing it + +Because the flip rule is unconditional inside the band, a wide `theta` on a confident model (the COMPAS case) does not shrink the gap toward zero - it drags it past zero. ROC has no "stop at parity" mechanism; monitoring the post-processed gap and backing `theta` off is a manual outer loop. + +### 4. It optimizes a rate, not the individuals + +Two defendants with `p = 0.49` and `p = 0.51` get opposite treatment based on group, not on any difference between them - the same [individual-fairness](individual-fairness.md) objection that applies to per-group thresholds. ROC trades group-rate fairness for individual-level consistency in the band. + +## Related Concepts + +* [What Are Pre-, In-, and Post-Processing Fairness Mitigations?](mitigation-strategies.md) - where ROC sits among mitigation families, and this repo's own S4 `ThresholdOptimizer` post-processing strategy. +* [What Is Equalized Odds?](equalized-odds.md) and [What Is Equal Opportunity?](equal-opportunity.md) - the error-rate metrics a per-group threshold or a flip band is usually tuned against. +* [What Is Treatment Equality?](treatment-equality.md) - another lens on how a post-processing flip changes the *mix* of errors within each group. +* [What Is Reject Inference?](reject-inference.md) - the unrelated "reject" (missing rejected applicants in training data), kept adjacent here only to mark the name collision. +* [What Is Individual Fairness?](individual-fairness.md) - why treating near-boundary individuals differently by group is contested. + +## Related Projects in This Repo + +* [`COMPAS/`](../COMPAS/) - the audit used above; its baseline is confident enough that ROC either does almost nothing (`theta = 0.05`) or overcorrects (`theta >= 0.15`). +* [`German Credit Lending/`](../German%20Credit%20Lending/) - a smaller-gap audit where a model with more mass near the boundary would give ROC a wider useful `theta` range. + +## Further Reading + +* [Kamiran, F., Karim, A., Zhang, X. (2012): Decision Theory for Discrimination-Aware Classification, *IEEE ICDM 2012*, pp. 924-929](https://doi.org/10.1109/ICDM.2012.45) - the paper that introduces Reject Option based Classification and the disagreement-region variant, and ties both to decision theory. [Author PDF.](https://web.lums.edu.pk/~akarim/pub/decision_theory_icdm2012.pdf) +* [Kamiran, F., Mansha, S., Karim, A., Zhang, X. (2018): Exploiting Reject Option in Classification for Social Discrimination Control, *Information Sciences* 425](https://doi.org/10.1016/j.ins.2017.09.064) - a fuller treatment with more datasets and the multi-attribute case. +* [Hardt, M., Price, E., Srebro, N. (2016): Equality of Opportunity in Supervised Learning, *NeurIPS 2016*](https://arxiv.org/abs/1610.02413) - the per-group-threshold post-processing method this repo's `ThresholdOptimizer` implements, for contrast. + +--- + +*Part of [The Fair Code Project](https://instagram.com/thefaircodeproject) - exposing and fixing algorithmic bias with real data and open code.* diff --git a/faircode/_explainers/data.json b/faircode/_explainers/data.json index fab4ce2..18b6cee 100644 --- a/faircode/_explainers/data.json +++ b/faircode/_explainers/data.json @@ -418,6 +418,13 @@ "subtitle": "The accuracy cost of a privacy guarantee falls hardest on underrepresented groups.", "summary": "Learn how DP-SGD's gradient clipping and noise addition disproportionately degrade accuracy for minority subgroups, so adding a privacy guarantee to a bias-mitigation pipeline is not free. Illustrative example from Bagdasaryan, Poursaeed and Shmatikov (NeurIPS 2019), plus a runnable DP-SGD noise-injection toy; this repo trains no DP model, so no frozen numbers are quoted.", "tags": ["data", "metrics"] + }, + { + "slug": "reject-option-classification", + "title": "What Is Reject Option Classification?", + "subtitle": "Flip the model's least-confident predictions toward the group history treated worst.", + "summary": "Learn how Reject Option Classification (Kamiran, Karim & Zhang, 2012) post-processes a model by reassigning labels only inside a low-confidence band near the decision boundary, and why the band's width - a free parameter with no principled default - decides whether the fairness gap shrinks, holds, or reverses. Worked on the COMPAS baseline logistic regression: a +-0.10 band flips 651 of 3,254 predictions and halves the gap, while a +-0.15 band overcorrects it to -70 pp and collapses accuracy.", + "tags": ["metrics", "detection"] } ] diff --git a/faircode/_explainers/reject-option-classification.md b/faircode/_explainers/reject-option-classification.md new file mode 100644 index 0000000..46e590d --- /dev/null +++ b/faircode/_explainers/reject-option-classification.md @@ -0,0 +1,228 @@ +# What Is Reject Option Classification? + +> *When a model is least sure of itself, it has the least evidence to defend its choice. Reject Option Classification takes exactly those borderline cases and hands the favorable outcome to the group history treated worst, on the bet that correcting for bias costs the least where the model was already guessing.* + +## The One-Sentence Definition + +**Reject Option Classification** (ROC; Kamiran, Karim and Zhang, 2012) is a post-processing bias mitigation that defines a "critical region" of low-confidence predictions near the decision boundary and, only inside that region, assigns the favorable label to instances from the disadvantaged group and the unfavorable label to instances from the advantaged group. + +> **Not the same as [Reject Inference](reject-inference.md).** That explainer's "reject" is about *rejected loan applicants* who never entered the training data - a selection-bias problem in credit scoring. This explainer's "reject" is the classifier's *reject option*: the band of inputs a probabilistic model is too uncertain about to commit to. Same word, unrelated ideas. (The same name-collision warning [Counterfactual Explanation](counterfactual-explanation.md) carries for its overlap with counterfactual fairness.) + +## Why It Matters + +This repo's benchmark harness already includes a post-processing mitigation as strategy **S4** - Fairlearn's `ThresholdOptimizer`, which searches for a *per-group decision threshold* that makes the whole model satisfy a fairness constraint. ROC is a different post-processing mechanism with the same access level (model outputs only, no retraining): + +| | `ThresholdOptimizer` (this repo's S4) | Reject Option Classification | +|---|---|---| +| What it changes | one decision threshold per group, applied to every prediction | the label of individual predictions, only inside a confidence band | +| Where it acts | globally, across the whole score range | locally, near `p = 0.5` | +| Free parameter | the fairness constraint to satisfy | the width of the critical region | +| Rationale | pick thresholds that equalize a chosen rate | flip where the model had the least evidence, so accuracy loss is smallest | + +ROC's appeal is the "least evidence" argument: a prediction with `p = 0.52` is barely a prediction at all, so overriding it toward the disadvantaged group is a small, defensible correction. Its weakness is that "how wide is the band" has no principled answer - and, as the worked example shows, the answer completely determines whether you fix the gap, do nothing, or overcorrect into a mirror-image disparity. + +## How It Works + +Let `p_i = P(Y = 1 | X_i)` be the model's predicted probability of the *unfavorable* outcome (here: "high risk"), and let `Y = 1` be unfavorable, `Y = 0` favorable. + +1. **Baseline prediction:** `y_hat_i = 1 if p_i >= 0.5 else 0`. +2. **Critical region:** pick a half-width `theta` in `(0, 0.5]` and define the region as `0.5 - theta <= p_i <= 0.5 + theta`. Outside it, keep the baseline prediction. +3. **Flip rule inside the region:** + - disadvantaged group -> favorable outcome (`y_hat_i = 0`) + - advantaged group -> unfavorable outcome (`y_hat_i = 1`) + +The flip toward the advantaged group is what keeps ROC from simply lowering everyone's positive rate: it trades favorable outcomes from the advantaged group for favorable outcomes to the disadvantaged group, inside the band, rather than just relabelling one side. + +`theta` is the entire design. `theta -> 0` recovers the untouched model. `theta = 0.5` puts every prediction in the region, so the output becomes "disadvantaged group all-favorable, advantaged group all-unfavorable" regardless of the features. + +## Concrete Example: COMPAS - Audit 01 + +`COMPAS/` audits the ProPublica COMPAS raw file, filtered (per `audit.yaml`) to African-American and Caucasian defendants scored for "Risk of Recidivism" (~16.3k rows). Following the audit's setup, a logistic-regression baseline was trained on `Sex_Code_Text`, `race`, `CustodyStatus`, `MaritalStatus` (an 80/20 split, `random_state=42`), and ROC was applied to its test-set probabilities. Favorable outcome = "not high risk"; disadvantaged group = African-American defendants. + +**Baseline model (no ROC):** + +| | Value | +|---|---:| +| Black defendants flagged high-risk | 86.1% | +| White defendants flagged high-risk | 0.1% | +| Demographic parity gap | **+86.0 pp** | +| Test accuracy | 65.9% | + +The baseline is close to a step function - `race` dominates the model, so almost every predicted probability sits near 0 or near 1 and very few land near the boundary. That is the setting ROC handles worst, and it shows: + +| Critical region `theta` | Predictions in region (of 3,254) | Predictions flipped | New parity gap | Test accuracy | +|---|---:|---:|---:|---:| +| baseline | - | - | +86.0 pp | 65.9% | +| ±0.05 | 17 | 17 | **+85.0 pp** | 65.9% | +| ±0.10 | 671 | 651 | **+43.9 pp** | 61.0% | +| ±0.15 | 2,609 | 2,566 | **-70.2 pp** | 45.5% | + +- **±0.05** touches 17 of 3,254 test rows. The gap barely moves and accuracy is unchanged, because the model is almost never uncertain - it committed hard, using race. +- **±0.10** flips 651 predictions and roughly halves the gap (+86 -> +44 pp), at a ~5-point accuracy cost. This is the band where ROC does what it is supposed to. +- **±0.15** pulls in 80% of the test set. The "flip rule" now overrides the model on the large majority of cases, the gap **reverses** to -70 pp (Black defendants now flagged *less*), and accuracy collapses to 45.5% - worse than predicting the majority class. + +No value of `theta` was "correct"; the three rows above are three different fairness outcomes produced by three arbitrary choices of one number. That is the central caveat, made concrete. + +```python +import numpy as np +import pandas as pd +from sklearn.linear_model import LogisticRegression +from sklearn.model_selection import train_test_split +from sklearn.preprocessing import StandardScaler + +df = pd.read_csv("COMPAS/compas-scores-raw.csv") +df = df[df["Ethnic_Code_Text"].isin(["African-American", "Caucasian"])] +df = df[df["DisplayText"] == "Risk of Recidivism"].copy() +df["high_risk"] = df["ScoreText"].isin(["High", "Medium"]).astype(int) +df["is_black"] = (df["Ethnic_Code_Text"] == "African-American").astype(int) + +X = pd.get_dummies(df[["Sex_Code_Text", "is_black", "CustodyStatus", + "MaritalStatus"]]).astype(float) +y, g = df["high_risk"].to_numpy(), df["is_black"].to_numpy() +X_tr, X_te, y_tr, y_te, g_tr, g_te = train_test_split( + X, y, g, test_size=0.2, random_state=42, stratify=y) + +scaler = StandardScaler().fit(X_tr) +model = LogisticRegression(max_iter=1000).fit(scaler.transform(X_tr), y_tr) +p = model.predict_proba(scaler.transform(X_te))[:, 1] +baseline = (p >= 0.5).astype(int) + +for theta in (0.05, 0.10, 0.15): + region = np.abs(p - 0.5) <= theta + roc = baseline.copy() + roc[region & (g_te == 1)] = 0 # disadvantaged -> favorable (not high risk) + roc[region & (g_te == 0)] = 1 # advantaged -> unfavorable + gap = roc[g_te == 1].mean() - roc[g_te == 0].mean() + print(f"theta=+/-{theta}: {region.sum():4d} in region, " + f"{(roc != baseline).sum():4d} flipped, gap {gap:+.3f}, " + f"acc {(roc == y_te).mean():.3f}") +``` + +## Detection / Implementation Code + +A reusable ROC post-processor plus a helper that sweeps `theta` so the parameter's effect is visible rather than hidden. + +```python +import numpy as np +import pandas as pd + + +def reject_option_classify( + proba_unfavorable: np.ndarray, + group: np.ndarray, + disadvantaged_value, + theta: float, + boundary: float = 0.5, +) -> np.ndarray: + """ + Apply Reject Option Classification to a probabilistic model's output. + + proba_unfavorable : P(Y = 1) where Y = 1 is the UNfavorable outcome. + group : group membership, aligned to proba_unfavorable. + disadvantaged_value : the value in `group` that marks the disadvantaged + group (gets the favorable outcome inside the band). + theta : half-width of the critical region, in (0, boundary]. + boundary : decision threshold (default 0.5). + + Returns the post-processed 0/1 predictions (1 = unfavorable). + """ + if not 0 < theta <= boundary: + raise ValueError(f"theta must be in (0, {boundary}], got {theta}") + + proba = np.asarray(proba_unfavorable, dtype=float) + grp = np.asarray(group) + pred = (proba >= boundary).astype(int) + + in_region = np.abs(proba - boundary) <= theta + is_disadvantaged = grp == disadvantaged_value + + pred[in_region & is_disadvantaged] = 0 # favorable + pred[in_region & ~is_disadvantaged] = 1 # unfavorable + return pred + + +def sweep_theta( + proba_unfavorable: np.ndarray, + group: np.ndarray, + y_true: np.ndarray, + disadvantaged_value, + advantaged_value, + thetas=(0.02, 0.05, 0.10, 0.15, 0.20, 0.30), + boundary: float = 0.5, +) -> pd.DataFrame: + """Run ROC across a range of theta and report, for each: how many + predictions fell in the critical region, how many actually flipped, the + resulting demographic-parity gap (disadvantaged - advantaged positive + rate on the UNfavorable label), and overall accuracy. There is no + 'best' row - the point is that the choice is unconstrained.""" + proba = np.asarray(proba_unfavorable, dtype=float) + grp = np.asarray(group) + y = np.asarray(y_true, dtype=int) + baseline = (proba >= boundary).astype(int) + + def gap(pred): + return (pred[grp == disadvantaged_value].mean() + - pred[grp == advantaged_value].mean()) + + rows = [{ + "theta": 0.0, "in_region": 0, "flipped": 0, + "parity_gap": gap(baseline), "accuracy": (baseline == y).mean(), + }] + for theta in thetas: + pred = reject_option_classify(proba, grp, disadvantaged_value, + theta, boundary) + in_region = int((np.abs(proba - boundary) <= theta).sum()) + rows.append({ + "theta": theta, + "in_region": in_region, + "flipped": int((pred != baseline).sum()), + "parity_gap": gap(pred), + "accuracy": (pred == y).mean(), + }) + return pd.DataFrame(rows) + + +# Usage (see the COMPAS example above for how p, g_te, y_te are produced): +# print(sweep_theta(p, g_te, y_te, disadvantaged_value=1, advantaged_value=0)) +``` + +## Limitations and Trade-offs + +### 1. The critical-region width has no principled default + +Every number in the worked example - "gap halved", "gap reversed", "accuracy destroyed" - is a consequence of picking `theta`. The original paper frames the choice through decision theory (a loss ratio between the two error types), which relocates the arbitrariness into choosing that ratio rather than removing it. In practice `theta` is tuned on a validation set against whatever fairness/accuracy trade-off the deployer already had in mind, which means ROC does not decide the trade-off, it just implements a chosen one. + +### 2. It needs group membership at prediction time + +Like every post-processing method (including this repo's `ThresholdOptimizer`), the flip rule reads the protected attribute for each individual at inference. In hiring, lending, and housing that is often the exact input a deployer is legally barred from using in the decision, or does not reliably have. A model that must not see race cannot run ROC on race. + +### 3. It can invert the disparity instead of removing it + +Because the flip rule is unconditional inside the band, a wide `theta` on a confident model (the COMPAS case) does not shrink the gap toward zero - it drags it past zero. ROC has no "stop at parity" mechanism; monitoring the post-processed gap and backing `theta` off is a manual outer loop. + +### 4. It optimizes a rate, not the individuals + +Two defendants with `p = 0.49` and `p = 0.51` get opposite treatment based on group, not on any difference between them - the same [individual-fairness](individual-fairness.md) objection that applies to per-group thresholds. ROC trades group-rate fairness for individual-level consistency in the band. + +## Related Concepts + +* [What Are Pre-, In-, and Post-Processing Fairness Mitigations?](mitigation-strategies.md) - where ROC sits among mitigation families, and this repo's own S4 `ThresholdOptimizer` post-processing strategy. +* [What Is Equalized Odds?](equalized-odds.md) and [What Is Equal Opportunity?](equal-opportunity.md) - the error-rate metrics a per-group threshold or a flip band is usually tuned against. +* [What Is Treatment Equality?](treatment-equality.md) - another lens on how a post-processing flip changes the *mix* of errors within each group. +* [What Is Reject Inference?](reject-inference.md) - the unrelated "reject" (missing rejected applicants in training data), kept adjacent here only to mark the name collision. +* [What Is Individual Fairness?](individual-fairness.md) - why treating near-boundary individuals differently by group is contested. + +## Related Projects in This Repo + +* [`COMPAS/`](../COMPAS/) - the audit used above; its baseline is confident enough that ROC either does almost nothing (`theta = 0.05`) or overcorrects (`theta >= 0.15`). +* [`German Credit Lending/`](../German%20Credit%20Lending/) - a smaller-gap audit where a model with more mass near the boundary would give ROC a wider useful `theta` range. + +## Further Reading + +* [Kamiran, F., Karim, A., Zhang, X. (2012): Decision Theory for Discrimination-Aware Classification, *IEEE ICDM 2012*, pp. 924-929](https://doi.org/10.1109/ICDM.2012.45) - the paper that introduces Reject Option based Classification and the disagreement-region variant, and ties both to decision theory. [Author PDF.](https://web.lums.edu.pk/~akarim/pub/decision_theory_icdm2012.pdf) +* [Kamiran, F., Mansha, S., Karim, A., Zhang, X. (2018): Exploiting Reject Option in Classification for Social Discrimination Control, *Information Sciences* 425](https://doi.org/10.1016/j.ins.2017.09.064) - a fuller treatment with more datasets and the multi-attribute case. +* [Hardt, M., Price, E., Srebro, N. (2016): Equality of Opportunity in Supervised Learning, *NeurIPS 2016*](https://arxiv.org/abs/1610.02413) - the per-group-threshold post-processing method this repo's `ThresholdOptimizer` implements, for contrast. + +--- + +*Part of [The Fair Code Project](https://instagram.com/thefaircodeproject) - exposing and fixing algorithmic bias with real data and open code.* diff --git a/llms-full.txt b/llms-full.txt index dd42aae..7ea1c87 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -12242,3 +12242,238 @@ The Detection Code has no privacy accountant, so its `sigma` values do not map t *Part of [The Fair Code Project](https://instagram.com/thefaircodeproject) - exposing and fixing algorithmic bias with real data and open code.* +--- + +# What Is Reject Option Classification? +URL: https://www.thefaircode.xyz/explainers/reject-option-classification.html +Summary: Learn how Reject Option Classification (Kamiran, Karim & Zhang, 2012) post-processes a model by reassigning labels only inside a low-confidence band near the decision boundary, and why the band's width - a free parameter with no principled default - decides whether the fairness gap shrinks, holds, or reverses. Worked on the COMPAS baseline logistic regression: a +-0.10 band flips 651 of 3,254 predictions and halves the gap, while a +-0.15 band overcorrects it to -70 pp and collapses accuracy. + +# What Is Reject Option Classification? + +> *When a model is least sure of itself, it has the least evidence to defend its choice. Reject Option Classification takes exactly those borderline cases and hands the favorable outcome to the group history treated worst, on the bet that correcting for bias costs the least where the model was already guessing.* + +## The One-Sentence Definition + +**Reject Option Classification** (ROC; Kamiran, Karim and Zhang, 2012) is a post-processing bias mitigation that defines a "critical region" of low-confidence predictions near the decision boundary and, only inside that region, assigns the favorable label to instances from the disadvantaged group and the unfavorable label to instances from the advantaged group. + +> **Not the same as [Reject Inference](reject-inference.md).** That explainer's "reject" is about *rejected loan applicants* who never entered the training data - a selection-bias problem in credit scoring. This explainer's "reject" is the classifier's *reject option*: the band of inputs a probabilistic model is too uncertain about to commit to. Same word, unrelated ideas. (The same name-collision warning [Counterfactual Explanation](counterfactual-explanation.md) carries for its overlap with counterfactual fairness.) + +## Why It Matters + +This repo's benchmark harness already includes a post-processing mitigation as strategy **S4** - Fairlearn's `ThresholdOptimizer`, which searches for a *per-group decision threshold* that makes the whole model satisfy a fairness constraint. ROC is a different post-processing mechanism with the same access level (model outputs only, no retraining): + +| | `ThresholdOptimizer` (this repo's S4) | Reject Option Classification | +|---|---|---| +| What it changes | one decision threshold per group, applied to every prediction | the label of individual predictions, only inside a confidence band | +| Where it acts | globally, across the whole score range | locally, near `p = 0.5` | +| Free parameter | the fairness constraint to satisfy | the width of the critical region | +| Rationale | pick thresholds that equalize a chosen rate | flip where the model had the least evidence, so accuracy loss is smallest | + +ROC's appeal is the "least evidence" argument: a prediction with `p = 0.52` is barely a prediction at all, so overriding it toward the disadvantaged group is a small, defensible correction. Its weakness is that "how wide is the band" has no principled answer - and, as the worked example shows, the answer completely determines whether you fix the gap, do nothing, or overcorrect into a mirror-image disparity. + +## How It Works + +Let `p_i = P(Y = 1 | X_i)` be the model's predicted probability of the *unfavorable* outcome (here: "high risk"), and let `Y = 1` be unfavorable, `Y = 0` favorable. + +1. **Baseline prediction:** `y_hat_i = 1 if p_i >= 0.5 else 0`. +2. **Critical region:** pick a half-width `theta` in `(0, 0.5]` and define the region as `0.5 - theta <= p_i <= 0.5 + theta`. Outside it, keep the baseline prediction. +3. **Flip rule inside the region:** + - disadvantaged group -> favorable outcome (`y_hat_i = 0`) + - advantaged group -> unfavorable outcome (`y_hat_i = 1`) + +The flip toward the advantaged group is what keeps ROC from simply lowering everyone's positive rate: it trades favorable outcomes from the advantaged group for favorable outcomes to the disadvantaged group, inside the band, rather than just relabelling one side. + +`theta` is the entire design. `theta -> 0` recovers the untouched model. `theta = 0.5` puts every prediction in the region, so the output becomes "disadvantaged group all-favorable, advantaged group all-unfavorable" regardless of the features. + +## Concrete Example: COMPAS - Audit 01 + +`COMPAS/` audits the ProPublica COMPAS raw file, filtered (per `audit.yaml`) to African-American and Caucasian defendants scored for "Risk of Recidivism" (~16.3k rows). Following the audit's setup, a logistic-regression baseline was trained on `Sex_Code_Text`, `race`, `CustodyStatus`, `MaritalStatus` (an 80/20 split, `random_state=42`), and ROC was applied to its test-set probabilities. Favorable outcome = "not high risk"; disadvantaged group = African-American defendants. + +**Baseline model (no ROC):** + +| | Value | +|---|---:| +| Black defendants flagged high-risk | 86.1% | +| White defendants flagged high-risk | 0.1% | +| Demographic parity gap | **+86.0 pp** | +| Test accuracy | 65.9% | + +The baseline is close to a step function - `race` dominates the model, so almost every predicted probability sits near 0 or near 1 and very few land near the boundary. That is the setting ROC handles worst, and it shows: + +| Critical region `theta` | Predictions in region (of 3,254) | Predictions flipped | New parity gap | Test accuracy | +|---|---:|---:|---:|---:| +| baseline | - | - | +86.0 pp | 65.9% | +| ±0.05 | 17 | 17 | **+85.0 pp** | 65.9% | +| ±0.10 | 671 | 651 | **+43.9 pp** | 61.0% | +| ±0.15 | 2,609 | 2,566 | **-70.2 pp** | 45.5% | + +- **±0.05** touches 17 of 3,254 test rows. The gap barely moves and accuracy is unchanged, because the model is almost never uncertain - it committed hard, using race. +- **±0.10** flips 651 predictions and roughly halves the gap (+86 -> +44 pp), at a ~5-point accuracy cost. This is the band where ROC does what it is supposed to. +- **±0.15** pulls in 80% of the test set. The "flip rule" now overrides the model on the large majority of cases, the gap **reverses** to -70 pp (Black defendants now flagged *less*), and accuracy collapses to 45.5% - worse than predicting the majority class. + +No value of `theta` was "correct"; the three rows above are three different fairness outcomes produced by three arbitrary choices of one number. That is the central caveat, made concrete. + +```python +import numpy as np +import pandas as pd +from sklearn.linear_model import LogisticRegression +from sklearn.model_selection import train_test_split +from sklearn.preprocessing import StandardScaler + +df = pd.read_csv("COMPAS/compas-scores-raw.csv") +df = df[df["Ethnic_Code_Text"].isin(["African-American", "Caucasian"])] +df = df[df["DisplayText"] == "Risk of Recidivism"].copy() +df["high_risk"] = df["ScoreText"].isin(["High", "Medium"]).astype(int) +df["is_black"] = (df["Ethnic_Code_Text"] == "African-American").astype(int) + +X = pd.get_dummies(df[["Sex_Code_Text", "is_black", "CustodyStatus", + "MaritalStatus"]]).astype(float) +y, g = df["high_risk"].to_numpy(), df["is_black"].to_numpy() +X_tr, X_te, y_tr, y_te, g_tr, g_te = train_test_split( + X, y, g, test_size=0.2, random_state=42, stratify=y) + +scaler = StandardScaler().fit(X_tr) +model = LogisticRegression(max_iter=1000).fit(scaler.transform(X_tr), y_tr) +p = model.predict_proba(scaler.transform(X_te))[:, 1] +baseline = (p >= 0.5).astype(int) + +for theta in (0.05, 0.10, 0.15): + region = np.abs(p - 0.5) <= theta + roc = baseline.copy() + roc[region & (g_te == 1)] = 0 # disadvantaged -> favorable (not high risk) + roc[region & (g_te == 0)] = 1 # advantaged -> unfavorable + gap = roc[g_te == 1].mean() - roc[g_te == 0].mean() + print(f"theta=+/-{theta}: {region.sum():4d} in region, " + f"{(roc != baseline).sum():4d} flipped, gap {gap:+.3f}, " + f"acc {(roc == y_te).mean():.3f}") +``` + +## Detection / Implementation Code + +A reusable ROC post-processor plus a helper that sweeps `theta` so the parameter's effect is visible rather than hidden. + +```python +import numpy as np +import pandas as pd + + +def reject_option_classify( + proba_unfavorable: np.ndarray, + group: np.ndarray, + disadvantaged_value, + theta: float, + boundary: float = 0.5, +) -> np.ndarray: + """ + Apply Reject Option Classification to a probabilistic model's output. + + proba_unfavorable : P(Y = 1) where Y = 1 is the UNfavorable outcome. + group : group membership, aligned to proba_unfavorable. + disadvantaged_value : the value in `group` that marks the disadvantaged + group (gets the favorable outcome inside the band). + theta : half-width of the critical region, in (0, boundary]. + boundary : decision threshold (default 0.5). + + Returns the post-processed 0/1 predictions (1 = unfavorable). + """ + if not 0 < theta <= boundary: + raise ValueError(f"theta must be in (0, {boundary}], got {theta}") + + proba = np.asarray(proba_unfavorable, dtype=float) + grp = np.asarray(group) + pred = (proba >= boundary).astype(int) + + in_region = np.abs(proba - boundary) <= theta + is_disadvantaged = grp == disadvantaged_value + + pred[in_region & is_disadvantaged] = 0 # favorable + pred[in_region & ~is_disadvantaged] = 1 # unfavorable + return pred + + +def sweep_theta( + proba_unfavorable: np.ndarray, + group: np.ndarray, + y_true: np.ndarray, + disadvantaged_value, + advantaged_value, + thetas=(0.02, 0.05, 0.10, 0.15, 0.20, 0.30), + boundary: float = 0.5, +) -> pd.DataFrame: + """Run ROC across a range of theta and report, for each: how many + predictions fell in the critical region, how many actually flipped, the + resulting demographic-parity gap (disadvantaged - advantaged positive + rate on the UNfavorable label), and overall accuracy. There is no + 'best' row - the point is that the choice is unconstrained.""" + proba = np.asarray(proba_unfavorable, dtype=float) + grp = np.asarray(group) + y = np.asarray(y_true, dtype=int) + baseline = (proba >= boundary).astype(int) + + def gap(pred): + return (pred[grp == disadvantaged_value].mean() + - pred[grp == advantaged_value].mean()) + + rows = [{ + "theta": 0.0, "in_region": 0, "flipped": 0, + "parity_gap": gap(baseline), "accuracy": (baseline == y).mean(), + }] + for theta in thetas: + pred = reject_option_classify(proba, grp, disadvantaged_value, + theta, boundary) + in_region = int((np.abs(proba - boundary) <= theta).sum()) + rows.append({ + "theta": theta, + "in_region": in_region, + "flipped": int((pred != baseline).sum()), + "parity_gap": gap(pred), + "accuracy": (pred == y).mean(), + }) + return pd.DataFrame(rows) + + +# Usage (see the COMPAS example above for how p, g_te, y_te are produced): +# print(sweep_theta(p, g_te, y_te, disadvantaged_value=1, advantaged_value=0)) +``` + +## Limitations and Trade-offs + +### 1. The critical-region width has no principled default + +Every number in the worked example - "gap halved", "gap reversed", "accuracy destroyed" - is a consequence of picking `theta`. The original paper frames the choice through decision theory (a loss ratio between the two error types), which relocates the arbitrariness into choosing that ratio rather than removing it. In practice `theta` is tuned on a validation set against whatever fairness/accuracy trade-off the deployer already had in mind, which means ROC does not decide the trade-off, it just implements a chosen one. + +### 2. It needs group membership at prediction time + +Like every post-processing method (including this repo's `ThresholdOptimizer`), the flip rule reads the protected attribute for each individual at inference. In hiring, lending, and housing that is often the exact input a deployer is legally barred from using in the decision, or does not reliably have. A model that must not see race cannot run ROC on race. + +### 3. It can invert the disparity instead of removing it + +Because the flip rule is unconditional inside the band, a wide `theta` on a confident model (the COMPAS case) does not shrink the gap toward zero - it drags it past zero. ROC has no "stop at parity" mechanism; monitoring the post-processed gap and backing `theta` off is a manual outer loop. + +### 4. It optimizes a rate, not the individuals + +Two defendants with `p = 0.49` and `p = 0.51` get opposite treatment based on group, not on any difference between them - the same [individual-fairness](individual-fairness.md) objection that applies to per-group thresholds. ROC trades group-rate fairness for individual-level consistency in the band. + +## Related Concepts + +* [What Are Pre-, In-, and Post-Processing Fairness Mitigations?](mitigation-strategies.md) - where ROC sits among mitigation families, and this repo's own S4 `ThresholdOptimizer` post-processing strategy. +* [What Is Equalized Odds?](equalized-odds.md) and [What Is Equal Opportunity?](equal-opportunity.md) - the error-rate metrics a per-group threshold or a flip band is usually tuned against. +* [What Is Treatment Equality?](treatment-equality.md) - another lens on how a post-processing flip changes the *mix* of errors within each group. +* [What Is Reject Inference?](reject-inference.md) - the unrelated "reject" (missing rejected applicants in training data), kept adjacent here only to mark the name collision. +* [What Is Individual Fairness?](individual-fairness.md) - why treating near-boundary individuals differently by group is contested. + +## Related Projects in This Repo + +* [`COMPAS/`](../COMPAS/) - the audit used above; its baseline is confident enough that ROC either does almost nothing (`theta = 0.05`) or overcorrects (`theta >= 0.15`). +* [`German Credit Lending/`](../German%20Credit%20Lending/) - a smaller-gap audit where a model with more mass near the boundary would give ROC a wider useful `theta` range. + +## Further Reading + +* [Kamiran, F., Karim, A., Zhang, X. (2012): Decision Theory for Discrimination-Aware Classification, *IEEE ICDM 2012*, pp. 924-929](https://doi.org/10.1109/ICDM.2012.45) - the paper that introduces Reject Option based Classification and the disagreement-region variant, and ties both to decision theory. [Author PDF.](https://web.lums.edu.pk/~akarim/pub/decision_theory_icdm2012.pdf) +* [Kamiran, F., Mansha, S., Karim, A., Zhang, X. (2018): Exploiting Reject Option in Classification for Social Discrimination Control, *Information Sciences* 425](https://doi.org/10.1016/j.ins.2017.09.064) - a fuller treatment with more datasets and the multi-attribute case. +* [Hardt, M., Price, E., Srebro, N. (2016): Equality of Opportunity in Supervised Learning, *NeurIPS 2016*](https://arxiv.org/abs/1610.02413) - the per-group-threshold post-processing method this repo's `ThresholdOptimizer` implements, for contrast. + +--- + +*Part of [The Fair Code Project](https://instagram.com/thefaircodeproject) - exposing and fixing algorithmic bias with real data and open code.* + diff --git a/sitemap.xml b/sitemap.xml index 15b23d8..5bc67fb 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -248,4 +248,8 @@ https://www.thefaircode.xyz/explainers/differential-privacy.html 2026-09-09 + + https://www.thefaircode.xyz/explainers/reject-option-classification.html + 2026-09-10 +