Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
307 changes: 293 additions & 14 deletions MyIA.AI.Notebooks/Probas/Infer/Infer-5-Causal-Inference.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,127 @@
"outputs": [
{
"output_type": "display_data",
"metadata": {},
"data": {
"text/html": [
"\r\n",
"<div>\r\n",
" <div id='dotnet-interactive-this-cell-$CACHE_BUSTER$' style='display: none'>\r\n",
" The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n",
" </div>\r\n",
" <script type='text/javascript'>\r\n",

" function timeout(ms, promise) {\r\n",
" return new Promise(function (resolve, reject) {\r\n",
" setTimeout(function () {\r\n",
" reject(new Error('timeout'))\r\n",
" }, ms)\r\n",
" promise.then(resolve, reject)\r\n",
" })\r\n",
" }\r\n",
"\r\n",


"\r\n",

"\r\n",
" if (!rootUrl.endsWith('/')) {\r\n",
" rootUrl = `${rootUrl}/`;\r\n",
" }\r\n",
"\r\n",
" try {\r\n",
" let response = await timeout(1000, fetch(`${rootUrl}discovery`, {\r\n",
" method: 'POST',\r\n",
" cache: 'no-cache',\r\n",
" mode: 'cors',\r\n",
" timeout: 1000,\r\n",
" headers: {\r\n",
" 'Content-Type': 'text/plain'\r\n",
" },\r\n",

" }));\r\n",
"\r\n",
" if (response.status == 200) {\r\n",
" return rootUrl;\r\n",
" }\r\n",
" }\r\n",
" catch (e) { }\r\n",
" }\r\n",
" }\r\n",
"}\r\n",
"\r\n",


" .then((root) => {\r\n",
" // use probing to find host url and api resources\r\n",
" // load interactive helpers and language services\r\n",
" let dotnetInteractiveRequire = require.config({\r\n",
" context: '40144.Microsoft.DotNet.Interactive.Http.HttpPort',\r\n",
" paths:\r\n",
" {\r\n",
" 'dotnet-interactive': `${root}resources`\r\n",
" }\r\n",
" }) || require;\r\n",
"\r\n",
" window.dotnetInteractiveRequire = dotnetInteractiveRequire;\r\n",
"\r\n",
" window.configureRequireFromExtension = function(extensionName, extensionCacheBuster) {\r\n",
" let paths = {};\r\n",
" paths[extensionName] = `${root}extensions/${extensionName}/resources/`;\r\n",
" \r\n",
" let internalRequire = require.config({\r\n",
" context: extensionCacheBuster,\r\n",
" paths: paths,\r\n",
" urlArgs: `cacheBuster=${extensionCacheBuster}`\r\n",
" }) || require;\r\n",
"\r\n",
" return internalRequire\r\n",
" };\r\n",
" \r\n",
" dotnetInteractiveRequire([\r\n",
" 'dotnet-interactive/dotnet-interactive'\r\n",
" ],\r\n",
" function (dotnet) {\r\n",
" dotnet.init(window);\r\n",
" },\r\n",
" function (error) {\r\n",
" console.log(error);\r\n",
" }\r\n",
" );\r\n",
" })\r\n",
" .catch(error => {console.log(error);});\r\n",
" }\r\n",
"\r\n",
"// ensure `require` is available globally\r\n",
"if ((typeof(require) !== typeof(Function)) || (typeof(require.config) !== typeof(Function))) {\r\n",
" let require_script = document.createElement('script');\r\n",
" require_script.setAttribute('src', 'https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js');\r\n",
" require_script.setAttribute('type', 'text/javascript');\r\n",
" \r\n",
" \r\n",
" require_script.onload = function() {\r\n",

" };\r\n",
"\r\n",
" document.getElementsByTagName('head')[0].appendChild(require_script);\r\n",
"}\r\n",
"else {\r\n",

"}\r\n",
"\r\n",
" </script>\r\n",
"</div>"
]
},
"metadata": {}
},
{
"output_type": "display_data",
"data": {
"text/html": [
"<div><div></div><div><strong>Installing Packages</strong><ul><li><span>Microsoft.ML.Probabilistic</span></li><li><span>Microsoft.ML.Probabilistic.Compiler</span></li></ul></div><div></div></div>"
]
}
},
"metadata": {}
},
{
"output_type": "stream",
Expand Down Expand Up @@ -200,17 +315,16 @@
},
{
"output_type": "display_data",
"metadata": {},
"data": {
"text/html": [
"\n",
"<div style=\"margin: 10px 0; padding: 10px; border: 1px solid #ddd; border-radius: 5px; background: #fafafa;\">\n",
" <div style=\"font-weight: bold; margin-bottom: 8px; color: #333;\">Model_06_29_26_12_25_36_48.svg</div>\n",
" <div style=\"font-weight: bold; margin-bottom: 8px; color: #333;\">Model_09_18_26_05_25_38_96.svg</div>\n",
" <div style=\"max-width: 800px; overflow: auto;\">\n",
" <?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n",
"<!-- Generated by graphviz version 14.1.2 (20260124.0452)\r\n",
"<!-- Generated by graphviz version 16.0.0 (20260814.1018)\r\n",
" -->\r\n",
"<!-- Title: Model Pages: 1 -->\r\n",
"<svg width=\"402pt\" height=\"289pt\"\r\n",
Expand Down Expand Up @@ -381,7 +495,8 @@
" </div>\n",
"</div>"
]
}
},
"metadata": {}
},
{
"output_type": "stream",
Expand Down Expand Up @@ -1445,6 +1560,166 @@
"Console.WriteLine($\" -> part mediee (indirect) ~= TE - CDE(M=0) = {TE - CDE0:F3} (chemin via les competences)\");"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Compiling model..."
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"done.\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"Compiling model..."
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"done.\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"Compiling model..."
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"done.\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"Compiling model..."
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"done.\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"Compiling model..."
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"done.\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"Compiling model..."
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"done.\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"Effets naturels (Pearl 2001) sur le SCM formation -> competences -> promotion :\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
" NDE = 0,280 (effet direct, mediateur naturel sous X=0)\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
" NIE = 0,180 (effet indirect, Y evalue sous X=1)\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
" NDE + NIE = 0,460 vs TE = 0,460 -> ecart |TE - NDE - NIE| = 0,000\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
" Raccourci CDE : NDE =? CDE(0) -> 0,280 vs 0,300 ; part mediee =? TE-CDE(0) -> 0,180 vs 0,160\r\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
" (NDE + NIE = TE : identite algebrique ; ce qui derive, ce sont les raccourcis via CDE)\r\n"
]
}
],
"source": [
"// EFFETS NATURELS (Pearl 2001) : NDE et NIE calcules sur le SCM de mediation ci-dessus.\n",
"// Pas de confondeur M <- U -> Y : la sequential ignorability tient, les quantites\n",
"// \"cross-world\" se calculent par enumeration sur le meme SCM (monde imbrique).\n",
"// P(M=m | do(X=x)) : le mediateur sous intervention (CPT direct du SCM)\n",
"double PM_doX(bool xVal, bool mVal) {\n",
" double pM1 = xVal ? 0.80 : 0.20;\n",
" return mVal ? pM1 : 1.0 - pM1;\n",
"}\n",
"\n",
"// NDE_{0,1} = Somme_m P(m|do(0)) * [P(Y|do(1),do(m)) - P(Y|do(0),do(m))]\n",
"// (mediateur a sa valeur NATURELLE sous X=0, pas figee -- c'est le contrefactuel imbrique)\n",
"double NDE = PM_doX(false, true) * (PY_doX_doM(true, true) - PY_doX_doM(false, true))\n",
" + PM_doX(false, false) * (PY_doX_doM(true, false) - PY_doX_doM(false, false));\n",
"\n",
"// NIE_{1,0} = Somme_m [P(m|do(1)) - P(m|do(0))] * P(Y=1|do(1),do(m))\n",
"// (Y sous X=1, seul le CHANGEMENT du mediateur porte l'effet)\n",
"double NIE = (PM_doX(true, true) - PM_doX(false, true)) * PY_doX_doM(true, true)\n",
" + (PM_doX(true, false) - PM_doX(false, false)) * PY_doX_doM(true, false);\n",
"\n",
"Console.WriteLine(\"Effets naturels (Pearl 2001) sur le SCM formation -> competences -> promotion :\");\n",
"Console.WriteLine($\" NDE = {NDE:F3} (effet direct, mediateur naturel sous X=0)\");\n",
"Console.WriteLine($\" NIE = {NIE:F3} (effet indirect, Y evalue sous X=1)\");\n",
"Console.WriteLine($\" NDE + NIE = {NDE + NIE:F3} vs TE = {TE:F3} -> ecart |TE - NDE - NIE| = {Math.Abs(TE - NDE - NIE):F3}\");\n",
"Console.WriteLine($\" Raccourci CDE : NDE =? CDE(0) -> {NDE:F3} vs {CDE0:F3} ; part mediee =? TE-CDE(0) -> {NIE:F3} vs {TE - CDE0:F3}\");\n",
"Console.WriteLine(\" (NDE + NIE = TE : identite algebrique ; ce qui derive, ce sont les raccourcis via CDE)\");"
]
},
{
"cell_type": "markdown",
"id": "infer22-mediation-interp",
Expand All @@ -1462,10 +1737,14 @@
"- **NIE (Natural Indirect Effect)** = `Y_{1,M_{X=1}} - Y_{1,M_{X=0}}` : effet indirect transmis par le changement \"naturel\" de `M` quand `X` bascule de 0 a 1.\n",
"- **TE = NDE + NIE** (decomposition additive, Pearl 2001, Robins & Greenland 1992).\n",
"\n",
"Dans Infer.NET, le NDE/NIE **necessite une hypothese supplemental** : la **sequential ignorability** (ou *cross-world independence*) sur les contrefactuels `M_{X=x'}` -- c'est-a-dire que la distribution de `M` sous `do(X=x')` reste compatible avec le meme SCM. Sur notre SCM de mediation (`X -> M -> Y`, pas de confondeur `M <- U -> Y`), cette hypothese tient et **NDE = CDE a M=M\\_{X=0}**, **NIE = TE - NDE**. Avec les valeurs mesurees : **NDE = CDE(M=0) = 0,300**, **NIE = TE - NDE = 0,460 - 0,300 = 0,160** -- la part mediee est exactement l'ecart observe. **Verification immediate** :\n",
"Dans Infer.NET, le NDE/NIE **necessite une hypothese supplemental** : la **sequential ignorability** (ou *cross-world independence*) sur les contrefactuels `M_{X=x'}` -- c'est-a-dire que la distribution de `M` sous `do(X=x')` reste compatible avec le meme SCM. Sur notre SCM de mediation (`X -> M -> Y`, pas de confondeur `M <- U -> Y`), cette hypothese tient : les effets naturels sont **calculables par enumeration sur le meme SCM** (cellule suivante). Les valeurs mesurees : **NDE = 0,280**, **NIE = 0,180**, et **NDE + NIE = 0,460 = TE** -- une **identite algebrique** (le telescopage des deux sommes rend la decomposition exacte pour tout SCM discret), pas une coincidence.\n",
"\n",
"Ce que l'interaction X*M casse en revanche, ce sont les **raccourcis via le CDE** : notre monde a CDE(1) = 0,200 != CDE(0) = 0,300, donc **NDE != CDE(0)** (0,280 vs 0,300) et la \"part mediee\" TE - CDE(M=0) = 0,160 sous-estime le vrai NIE = 0,180 :\n",
"\n",
"```\n",
"NDE + NIE = CDE(M=0) + (TE - CDE(M=0)) = TE ✓ (decomposition de Pearl 2001)\n",
"NDE + NIE = TE (exacte, toujours -- identite de telescopage)\n",
"NDE = CDE(m) (faux des que CDE varie en m : interaction)\n",
"part mediee = TE - CDE(M=0) (approximation : 0,160 au lieu de 0,180 ici)\n",
"```\n",
"\n",
"**Quand CDE != NDE** : si un confondeur `U` influence **a la fois** `M` et `Y` (par exemple, le \"motivation\" qui determine a la fois les competences acquises ET la reconnaissance patronale), CDE a `do(M=0)` ne capture pas l'effet direct reel -- il faut le **NDE**, qui requiert des methodes d'inference contrefactuelle specifiques (voir section 10 et la discussion dans Pearl 2001, sec. 4). Infer.NET, comme moteur de message passing determinant sur graphes discrets, rend ce cas plus difficile (les contrefactuels \"cross-world\" sortent du formalisme d'un seul DAG).\n",
Expand Down Expand Up @@ -1514,7 +1793,7 @@
"cell_type": "code",
"id": "7300698aebb9",
"metadata": {},
"execution_count": 11,
"execution_count": 12,
"outputs": [
{
"output_type": "stream",
Expand Down Expand Up @@ -1659,7 +1938,7 @@
"cell_type": "code",
"id": "eb5112fe221d",
"metadata": {},
"execution_count": 12,
"execution_count": 13,
"outputs": [
{
"output_type": "stream",
Expand Down Expand Up @@ -1698,7 +1977,7 @@
"cell_type": "code",
"id": "b1ec24f8fe8a",
"metadata": {},
"execution_count": 13,
"execution_count": 14,
"outputs": [
{
"output_type": "stream",
Expand Down Expand Up @@ -1736,7 +2015,7 @@
"cell_type": "code",
"id": "deeb4d1f5bc6",
"metadata": {},
"execution_count": 14,
"execution_count": 15,
"outputs": [
{
"output_type": "stream",
Expand Down Expand Up @@ -1772,7 +2051,7 @@
"cell_type": "code",
"id": "1f39b5a055ca",
"metadata": {},
"execution_count": 15,
"execution_count": 16,
"outputs": [
{
"output_type": "stream",
Expand Down Expand Up @@ -1890,4 +2169,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}
Loading
Loading