maalouf imad commited on
V1
Browse files- cours-pdf.html +915 -0
- cours.html +1421 -0
- cours.pdf +0 -0
- css/shared.css +944 -0
- feedback.html +1149 -0
- index.html +1009 -18
- js/feedback-storage.js +236 -0
- js/shared.js +394 -0
- notebooks/TP1_Titanic_Survival.ipynb +508 -0
- notebooks/TP2_House_Prices.ipynb +436 -0
- notebooks/TP3_Iris_Classification.ipynb +182 -0
- notebooks/TP4_LSTM_TimeSeries.ipynb +371 -0
- tp.html +1389 -0
cours-pdf.html
ADDED
|
@@ -0,0 +1,915 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="fr">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<title>Cours de Machine Learning - ML Academy</title>
|
| 6 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 7 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 8 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
| 9 |
+
<script>
|
| 10 |
+
window.MathJax = {
|
| 11 |
+
tex: { inlineMath: [['$', '$']], displayMath: [['$$', '$$']] },
|
| 12 |
+
options: { skipHtmlTags: ['script','noscript','style','textarea','pre'] }
|
| 13 |
+
};
|
| 14 |
+
</script>
|
| 15 |
+
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
| 16 |
+
<style>
|
| 17 |
+
/* Reset */
|
| 18 |
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 19 |
+
body { margin: 0; padding: 0; font-family: 'Inter', -apple-system, sans-serif; }
|
| 20 |
+
|
| 21 |
+
/* Page setup */
|
| 22 |
+
@page {
|
| 23 |
+
size: A4;
|
| 24 |
+
margin: 2.5cm 2cm;
|
| 25 |
+
@bottom-center {
|
| 26 |
+
content: "Imad Maalouf — ML Academy";
|
| 27 |
+
font-size: 9pt;
|
| 28 |
+
color: #666;
|
| 29 |
+
}
|
| 30 |
+
@bottom-right {
|
| 31 |
+
content: counter(page);
|
| 32 |
+
font-size: 9pt;
|
| 33 |
+
color: #666;
|
| 34 |
+
}
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
@page :first {
|
| 38 |
+
margin: 0;
|
| 39 |
+
@bottom-center { content: none; }
|
| 40 |
+
@bottom-right { content: none; }
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
/* Cover page */
|
| 44 |
+
.cover {
|
| 45 |
+
width: 210mm;
|
| 46 |
+
height: 297mm;
|
| 47 |
+
margin: 0;
|
| 48 |
+
position: relative;
|
| 49 |
+
overflow: hidden;
|
| 50 |
+
page-break-after: always;
|
| 51 |
+
background: linear-gradient(135deg, #0f0f1a 0%, #1a1a2e 50%, #252542 100%);
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
.cover-decoration {
|
| 55 |
+
position: absolute;
|
| 56 |
+
top: 0;
|
| 57 |
+
left: 0;
|
| 58 |
+
right: 0;
|
| 59 |
+
bottom: 0;
|
| 60 |
+
overflow: hidden;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
.cover-circle {
|
| 64 |
+
position: absolute;
|
| 65 |
+
border-radius: 50%;
|
| 66 |
+
opacity: 0.1;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
.cover-circle-1 {
|
| 70 |
+
width: 400px;
|
| 71 |
+
height: 400px;
|
| 72 |
+
background: #6366f1;
|
| 73 |
+
top: -100px;
|
| 74 |
+
right: -100px;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
.cover-circle-2 {
|
| 78 |
+
width: 300px;
|
| 79 |
+
height: 300px;
|
| 80 |
+
background: #06b6d4;
|
| 81 |
+
bottom: 10%;
|
| 82 |
+
left: -80px;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
.cover-circle-3 {
|
| 86 |
+
width: 200px;
|
| 87 |
+
height: 200px;
|
| 88 |
+
background: #f59e0b;
|
| 89 |
+
top: 40%;
|
| 90 |
+
right: 15%;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
.cover-content {
|
| 94 |
+
position: absolute;
|
| 95 |
+
top: 50%;
|
| 96 |
+
left: 50%;
|
| 97 |
+
transform: translate(-50%, -50%);
|
| 98 |
+
text-align: center;
|
| 99 |
+
width: 80%;
|
| 100 |
+
z-index: 1;
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
.cover-badge {
|
| 104 |
+
display: inline-block;
|
| 105 |
+
padding: 8px 16px;
|
| 106 |
+
background: rgba(99, 102, 241, 0.2);
|
| 107 |
+
border: 1px solid rgba(99, 102, 241, 0.4);
|
| 108 |
+
border-radius: 20px;
|
| 109 |
+
font-family: 'JetBrains Mono', monospace;
|
| 110 |
+
font-size: 10pt;
|
| 111 |
+
color: #818cf8;
|
| 112 |
+
text-transform: uppercase;
|
| 113 |
+
letter-spacing: 2px;
|
| 114 |
+
margin-bottom: 30px;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
.cover-title {
|
| 118 |
+
font-size: 36pt;
|
| 119 |
+
font-weight: 700;
|
| 120 |
+
color: #f8fafc;
|
| 121 |
+
margin-bottom: 15px;
|
| 122 |
+
line-height: 1.2;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
.cover-subtitle {
|
| 126 |
+
font-size: 14pt;
|
| 127 |
+
color: #94a3b8;
|
| 128 |
+
margin-bottom: 60px;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
.cover-author {
|
| 132 |
+
font-size: 12pt;
|
| 133 |
+
color: #818cf8;
|
| 134 |
+
margin-bottom: 10px;
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
.cover-info {
|
| 138 |
+
font-size: 10pt;
|
| 139 |
+
color: #64748b;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
/* Content styles */
|
| 143 |
+
.content {
|
| 144 |
+
padding: 0;
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
h1 {
|
| 148 |
+
font-size: 20pt;
|
| 149 |
+
font-weight: 700;
|
| 150 |
+
color: #1a1a2e;
|
| 151 |
+
margin: 30pt 0 15pt 0;
|
| 152 |
+
padding-bottom: 8pt;
|
| 153 |
+
border-bottom: 2px solid #6366f1;
|
| 154 |
+
page-break-after: avoid;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
h2 {
|
| 158 |
+
font-size: 14pt;
|
| 159 |
+
font-weight: 600;
|
| 160 |
+
color: #1a1a2e;
|
| 161 |
+
margin: 20pt 0 10pt 0;
|
| 162 |
+
page-break-after: avoid;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
h3 {
|
| 166 |
+
font-size: 12pt;
|
| 167 |
+
font-weight: 600;
|
| 168 |
+
color: #333;
|
| 169 |
+
margin: 15pt 0 8pt 0;
|
| 170 |
+
page-break-after: avoid;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
p {
|
| 174 |
+
font-size: 11pt;
|
| 175 |
+
line-height: 1.7;
|
| 176 |
+
color: #333;
|
| 177 |
+
margin-bottom: 10pt;
|
| 178 |
+
text-align: justify;
|
| 179 |
+
text-align-last: left;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
strong {
|
| 183 |
+
font-weight: 600;
|
| 184 |
+
color: #1a1a2e;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
em {
|
| 188 |
+
font-style: italic;
|
| 189 |
+
color: #444;
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
/* Info box */
|
| 193 |
+
.info-box {
|
| 194 |
+
background: #f8f9fa;
|
| 195 |
+
border-left: 4px solid #6366f1;
|
| 196 |
+
padding: 12pt 15pt;
|
| 197 |
+
margin: 15pt 0;
|
| 198 |
+
page-break-inside: avoid;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
.info-box-title {
|
| 202 |
+
font-weight: 600;
|
| 203 |
+
color: #6366f1;
|
| 204 |
+
margin-bottom: 5pt;
|
| 205 |
+
font-size: 10pt;
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
.info-box p {
|
| 209 |
+
margin: 0;
|
| 210 |
+
font-size: 10pt;
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
/* Equation block */
|
| 214 |
+
.equation-block {
|
| 215 |
+
background: #f8f9fa;
|
| 216 |
+
border: 1px solid #e2e8f0;
|
| 217 |
+
border-left: 3px solid #6366f1;
|
| 218 |
+
border-radius: 4px;
|
| 219 |
+
padding: 15pt;
|
| 220 |
+
margin: 15pt 0;
|
| 221 |
+
text-align: center;
|
| 222 |
+
page-break-inside: avoid;
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
.equation-label {
|
| 226 |
+
display: block;
|
| 227 |
+
font-family: 'JetBrains Mono', monospace;
|
| 228 |
+
font-size: 8pt;
|
| 229 |
+
color: #64748b;
|
| 230 |
+
text-align: right;
|
| 231 |
+
margin-top: 8pt;
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
/* Cards grid */
|
| 235 |
+
.cards-grid {
|
| 236 |
+
display: grid;
|
| 237 |
+
grid-template-columns: repeat(3, 1fr);
|
| 238 |
+
gap: 12pt;
|
| 239 |
+
margin: 15pt 0;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
.card {
|
| 243 |
+
background: #f8f9fa;
|
| 244 |
+
border: 1px solid #e2e8f0;
|
| 245 |
+
border-radius: 6px;
|
| 246 |
+
padding: 12pt;
|
| 247 |
+
page-break-inside: avoid;
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
.card-icon {
|
| 251 |
+
width: 32px;
|
| 252 |
+
height: 32px;
|
| 253 |
+
background: linear-gradient(135deg, #6366f1, #06b6d4);
|
| 254 |
+
border-radius: 6px;
|
| 255 |
+
display: flex;
|
| 256 |
+
align-items: center;
|
| 257 |
+
justify-content: center;
|
| 258 |
+
font-size: 12pt;
|
| 259 |
+
font-weight: 700;
|
| 260 |
+
color: white;
|
| 261 |
+
margin-bottom: 8pt;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
.card-title {
|
| 265 |
+
font-size: 10pt;
|
| 266 |
+
font-weight: 600;
|
| 267 |
+
color: #1a1a2e;
|
| 268 |
+
margin-bottom: 5pt;
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
.card-text {
|
| 272 |
+
font-size: 9pt;
|
| 273 |
+
color: #555;
|
| 274 |
+
line-height: 1.5;
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
/* Pipeline */
|
| 278 |
+
.pipeline {
|
| 279 |
+
display: flex;
|
| 280 |
+
gap: 8pt;
|
| 281 |
+
margin: 15pt 0;
|
| 282 |
+
padding: 12pt;
|
| 283 |
+
background: #f8f9fa;
|
| 284 |
+
border: 1px solid #e2e8f0;
|
| 285 |
+
border-radius: 6px;
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
.pipeline-step {
|
| 289 |
+
flex: 1;
|
| 290 |
+
text-align: center;
|
| 291 |
+
position: relative;
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
.pipeline-step:not(:last-child)::after {
|
| 295 |
+
content: '->';
|
| 296 |
+
position: absolute;
|
| 297 |
+
right: -10pt;
|
| 298 |
+
top: 50%;
|
| 299 |
+
transform: translateY(-50%);
|
| 300 |
+
color: #6366f1;
|
| 301 |
+
font-family: 'JetBrains Mono', monospace;
|
| 302 |
+
font-size: 10pt;
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
.pipeline-num {
|
| 306 |
+
width: 24pt;
|
| 307 |
+
height: 24pt;
|
| 308 |
+
background: linear-gradient(135deg, #6366f1, #06b6d4);
|
| 309 |
+
border-radius: 50%;
|
| 310 |
+
display: flex;
|
| 311 |
+
align-items: center;
|
| 312 |
+
justify-content: center;
|
| 313 |
+
font-family: 'JetBrains Mono', monospace;
|
| 314 |
+
font-size: 9pt;
|
| 315 |
+
font-weight: 700;
|
| 316 |
+
color: white;
|
| 317 |
+
margin: 0 auto 5pt;
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
.pipeline-label {
|
| 321 |
+
font-size: 8pt;
|
| 322 |
+
font-weight: 600;
|
| 323 |
+
color: #1a1a2e;
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
.pipeline-desc {
|
| 327 |
+
font-size: 7pt;
|
| 328 |
+
color: #64748b;
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
/* Comparison */
|
| 332 |
+
.comparison-grid {
|
| 333 |
+
display: grid;
|
| 334 |
+
grid-template-columns: 1fr 1fr;
|
| 335 |
+
gap: 12pt;
|
| 336 |
+
margin: 15pt 0;
|
| 337 |
+
}
|
| 338 |
+
|
| 339 |
+
.comparison-box {
|
| 340 |
+
background: #f8f9fa;
|
| 341 |
+
border: 1px solid #e2e8f0;
|
| 342 |
+
border-radius: 6px;
|
| 343 |
+
padding: 12pt;
|
| 344 |
+
page-break-inside: avoid;
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
.comparison-box h4 {
|
| 348 |
+
font-size: 10pt;
|
| 349 |
+
font-weight: 600;
|
| 350 |
+
color: #1a1a2e;
|
| 351 |
+
margin-bottom: 8pt;
|
| 352 |
+
padding-bottom: 5pt;
|
| 353 |
+
border-bottom: 1px solid #e2e8f0;
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
+
.comparison-box ul {
|
| 357 |
+
list-style: none;
|
| 358 |
+
padding: 0;
|
| 359 |
+
margin: 0;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
.comparison-box li {
|
| 363 |
+
padding: 3pt 0;
|
| 364 |
+
font-size: 9pt;
|
| 365 |
+
color: #444;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
.comparison-box li::before {
|
| 369 |
+
content: '>';
|
| 370 |
+
color: #6366f1;
|
| 371 |
+
margin-right: 6pt;
|
| 372 |
+
font-family: 'JetBrains Mono', monospace;
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
/* Metric cards */
|
| 376 |
+
.metric-row {
|
| 377 |
+
display: grid;
|
| 378 |
+
grid-template-columns: repeat(3, 1fr);
|
| 379 |
+
gap: 12pt;
|
| 380 |
+
margin: 15pt 0;
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
.metric-card {
|
| 384 |
+
background: #f8f9fa;
|
| 385 |
+
border: 1px solid #e2e8f0;
|
| 386 |
+
border-radius: 6px;
|
| 387 |
+
padding: 12pt;
|
| 388 |
+
text-align: center;
|
| 389 |
+
page-break-inside: avoid;
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
.metric-name {
|
| 393 |
+
font-family: 'JetBrains Mono', monospace;
|
| 394 |
+
font-size: 7pt;
|
| 395 |
+
color: #64748b;
|
| 396 |
+
text-transform: uppercase;
|
| 397 |
+
letter-spacing: 1px;
|
| 398 |
+
margin-bottom: 5pt;
|
| 399 |
+
}
|
| 400 |
+
|
| 401 |
+
.metric-formula {
|
| 402 |
+
font-family: 'JetBrains Mono', monospace;
|
| 403 |
+
font-size: 9pt;
|
| 404 |
+
color: #6366f1;
|
| 405 |
+
font-weight: 600;
|
| 406 |
+
margin-bottom: 3pt;
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
.metric-desc {
|
| 410 |
+
font-size: 7pt;
|
| 411 |
+
color: #64748b;
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
/* Table */
|
| 415 |
+
table {
|
| 416 |
+
width: 100%;
|
| 417 |
+
border-collapse: collapse;
|
| 418 |
+
margin: 15pt 0;
|
| 419 |
+
font-size: 9pt;
|
| 420 |
+
page-break-inside: avoid;
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
thead {
|
| 424 |
+
display: table-header-group;
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
th {
|
| 428 |
+
background: #f1f5f9;
|
| 429 |
+
color: #475569;
|
| 430 |
+
font-family: 'JetBrains Mono', monospace;
|
| 431 |
+
font-size: 8pt;
|
| 432 |
+
font-weight: 600;
|
| 433 |
+
text-transform: uppercase;
|
| 434 |
+
letter-spacing: 0.5px;
|
| 435 |
+
padding: 8pt 10pt;
|
| 436 |
+
text-align: left;
|
| 437 |
+
border-top: 2px solid #333;
|
| 438 |
+
border-bottom: 1px solid #333;
|
| 439 |
+
}
|
| 440 |
+
|
| 441 |
+
td {
|
| 442 |
+
padding: 8pt 10pt;
|
| 443 |
+
border-bottom: 1px solid #e2e8f0;
|
| 444 |
+
color: #333;
|
| 445 |
+
}
|
| 446 |
+
|
| 447 |
+
tbody tr:last-child td {
|
| 448 |
+
border-bottom: 2px solid #333;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
/* Page break utilities */
|
| 452 |
+
.page-break {
|
| 453 |
+
page-break-after: always;
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
/* Prevent overflow */
|
| 457 |
+
pre, table, figure, img, svg, blockquote {
|
| 458 |
+
max-width: 100%;
|
| 459 |
+
box-sizing: border-box;
|
| 460 |
+
}
|
| 461 |
+
|
| 462 |
+
a { word-break: break-all; }
|
| 463 |
+
|
| 464 |
+
/* Author footer on each page */
|
| 465 |
+
.author-footer {
|
| 466 |
+
margin-top: 30pt;
|
| 467 |
+
padding-top: 15pt;
|
| 468 |
+
border-top: 1px solid #e2e8f0;
|
| 469 |
+
text-align: center;
|
| 470 |
+
}
|
| 471 |
+
|
| 472 |
+
.author-name {
|
| 473 |
+
font-size: 10pt;
|
| 474 |
+
font-weight: 600;
|
| 475 |
+
color: #6366f1;
|
| 476 |
+
}
|
| 477 |
+
|
| 478 |
+
.author-contact {
|
| 479 |
+
font-size: 8pt;
|
| 480 |
+
color: #64748b;
|
| 481 |
+
margin-top: 3pt;
|
| 482 |
+
}
|
| 483 |
+
</style>
|
| 484 |
+
</head>
|
| 485 |
+
<body>
|
| 486 |
+
<!-- Cover Page -->
|
| 487 |
+
<div class="cover">
|
| 488 |
+
<div class="cover-decoration">
|
| 489 |
+
<div class="cover-circle cover-circle-1"></div>
|
| 490 |
+
<div class="cover-circle cover-circle-2"></div>
|
| 491 |
+
<div class="cover-circle cover-circle-3"></div>
|
| 492 |
+
</div>
|
| 493 |
+
<div class="cover-content">
|
| 494 |
+
<div class="cover-badge">Formation 2025/2026</div>
|
| 495 |
+
<h1 class="cover-title">Cours de<br>Machine Learning</h1>
|
| 496 |
+
<p class="cover-subtitle">De la theorie a la pratique — Algorithmes fondamentaux et techniques avancees</p>
|
| 497 |
+
<p class="cover-author">Formateur : Imad Maalouf</p>
|
| 498 |
+
<p class="cover-info">ML Academy — GE-MCI 4A</p>
|
| 499 |
+
</div>
|
| 500 |
+
</div>
|
| 501 |
+
|
| 502 |
+
<!-- Content -->
|
| 503 |
+
<div class="content">
|
| 504 |
+
<h1>1. Introduction au Machine Learning</h1>
|
| 505 |
+
|
| 506 |
+
<p>
|
| 507 |
+
Le <strong>Machine Learning (ML)</strong> est une branche de l'intelligence artificielle
|
| 508 |
+
qui permet aux machines d'apprendre a partir de donnees <em>sans etre explicitement programmees</em>
|
| 509 |
+
pour chaque tache. Au lieu de coder des regles a la main, on montre des exemples au modele
|
| 510 |
+
et il decouvre lui-meme les patterns.
|
| 511 |
+
</p>
|
| 512 |
+
|
| 513 |
+
<div class="info-box">
|
| 514 |
+
<div class="info-box-title">Idee fondamentale</div>
|
| 515 |
+
<p>
|
| 516 |
+
On cherche a approximer une fonction inconnue $f$ telle que $\hat{y} = f(x_1, x_2, \ldots, x_n)$.
|
| 517 |
+
Le modele ML apprend cette fonction a partir d'exemples $(x, y)$ connus.
|
| 518 |
+
</p>
|
| 519 |
+
</div>
|
| 520 |
+
|
| 521 |
+
<h2>1.1 Types d'apprentissage</h2>
|
| 522 |
+
|
| 523 |
+
<div class="cards-grid">
|
| 524 |
+
<div class="card">
|
| 525 |
+
<div class="card-icon">S</div>
|
| 526 |
+
<div class="card-title">Supervise</div>
|
| 527 |
+
<div class="card-text">Donnees labellisees $(x, y)$ : regression et classification.</div>
|
| 528 |
+
</div>
|
| 529 |
+
<div class="card">
|
| 530 |
+
<div class="card-icon">N</div>
|
| 531 |
+
<div class="card-title">Non supervise</div>
|
| 532 |
+
<div class="card-text">Pas de labels : clustering, reduction de dimension.</div>
|
| 533 |
+
</div>
|
| 534 |
+
<div class="card">
|
| 535 |
+
<div class="card-icon">R</div>
|
| 536 |
+
<div class="card-title">Par renforcement</div>
|
| 537 |
+
<div class="card-text">Agent apprend via actions-recompenses.</div>
|
| 538 |
+
</div>
|
| 539 |
+
</div>
|
| 540 |
+
|
| 541 |
+
<h2>1.2 Pipeline ML typique</h2>
|
| 542 |
+
|
| 543 |
+
<div class="pipeline">
|
| 544 |
+
<div class="pipeline-step">
|
| 545 |
+
<div class="pipeline-num">1</div>
|
| 546 |
+
<div class="pipeline-label">Donnees</div>
|
| 547 |
+
<div class="pipeline-desc">Collecte & nettoyage</div>
|
| 548 |
+
</div>
|
| 549 |
+
<div class="pipeline-step">
|
| 550 |
+
<div class="pipeline-num">2</div>
|
| 551 |
+
<div class="pipeline-label">Features</div>
|
| 552 |
+
<div class="pipeline-desc">Engineering</div>
|
| 553 |
+
</div>
|
| 554 |
+
<div class="pipeline-step">
|
| 555 |
+
<div class="pipeline-num">3</div>
|
| 556 |
+
<div class="pipeline-label">Split</div>
|
| 557 |
+
<div class="pipeline-desc">Train / Test</div>
|
| 558 |
+
</div>
|
| 559 |
+
<div class="pipeline-step">
|
| 560 |
+
<div class="pipeline-num">4</div>
|
| 561 |
+
<div class="pipeline-label">Modele</div>
|
| 562 |
+
<div class="pipeline-desc">Entrainement</div>
|
| 563 |
+
</div>
|
| 564 |
+
<div class="pipeline-step">
|
| 565 |
+
<div class="pipeline-num">5</div>
|
| 566 |
+
<div class="pipeline-label">Evaluation</div>
|
| 567 |
+
<div class="pipeline-desc">Metriques</div>
|
| 568 |
+
</div>
|
| 569 |
+
<div class="pipeline-step">
|
| 570 |
+
<div class="pipeline-num">6</div>
|
| 571 |
+
<div class="pipeline-label">Production</div>
|
| 572 |
+
<div class="pipeline-desc">Deploiement</div>
|
| 573 |
+
</div>
|
| 574 |
+
</div>
|
| 575 |
+
|
| 576 |
+
<div class="page-break"></div>
|
| 577 |
+
|
| 578 |
+
<h1>2. Regression Lineaire</h1>
|
| 579 |
+
|
| 580 |
+
<p>
|
| 581 |
+
La <strong>regression lineaire</strong> modelise la relation entre les features et la cible
|
| 582 |
+
par une fonction affine. C'est l'algorithme le plus simple mais souvent tres efficace
|
| 583 |
+
comme baseline.
|
| 584 |
+
</p>
|
| 585 |
+
|
| 586 |
+
<div class="equation-block">
|
| 587 |
+
$$\hat{y} = w_0 + w_1 x_1 + w_2 x_2 + \cdots + w_n x_n = \mathbf{w}^T \mathbf{x}$$
|
| 588 |
+
<span class="equation-label">Modele lineaire avec coefficients $\mathbf{w}$</span>
|
| 589 |
+
</div>
|
| 590 |
+
|
| 591 |
+
<p>
|
| 592 |
+
L'objectif est de minimiser l'erreur quadratique moyenne (MSE) :
|
| 593 |
+
</p>
|
| 594 |
+
|
| 595 |
+
<div class="equation-block">
|
| 596 |
+
$$\text{MSE} = \frac{1}{m} \sum_{i=1}^{m} (y_i - \hat{y}_i)^2$$
|
| 597 |
+
<span class="equation-label">Fonction de cout : moyenne des erreurs quadratiques</span>
|
| 598 |
+
</div>
|
| 599 |
+
|
| 600 |
+
<div class="info-box">
|
| 601 |
+
<div class="info-box-title">Solution analytique</div>
|
| 602 |
+
<p>
|
| 603 |
+
La regression lineaire admet une solution fermee :
|
| 604 |
+
$\mathbf{w}^* = (X^T X)^{-1} X^T Y$. Pas besoin d'iterations !
|
| 605 |
+
</p>
|
| 606 |
+
</div>
|
| 607 |
+
|
| 608 |
+
<h2>2.1 Avantages et limitations</h2>
|
| 609 |
+
|
| 610 |
+
<div class="comparison-grid">
|
| 611 |
+
<div class="comparison-box">
|
| 612 |
+
<h4>[+] Avantages</h4>
|
| 613 |
+
<ul>
|
| 614 |
+
<li>Tres rapide a entrainer</li>
|
| 615 |
+
<li>Interpretable (coefficients)</li>
|
| 616 |
+
<li>Pas d'hyperparametres</li>
|
| 617 |
+
<li>Excellent baseline</li>
|
| 618 |
+
</ul>
|
| 619 |
+
</div>
|
| 620 |
+
<div class="comparison-box">
|
| 621 |
+
<h4>[-] Limitations</h4>
|
| 622 |
+
<ul>
|
| 623 |
+
<li>Relation lineaire uniquement</li>
|
| 624 |
+
<li>Sensible aux outliers</li>
|
| 625 |
+
<li>Performance decroit en haute dimension</li>
|
| 626 |
+
</ul>
|
| 627 |
+
</div>
|
| 628 |
+
</div>
|
| 629 |
+
|
| 630 |
+
<div class="page-break"></div>
|
| 631 |
+
|
| 632 |
+
<h1>3. Regression Logistique</h1>
|
| 633 |
+
|
| 634 |
+
<p>
|
| 635 |
+
Malgre son nom, la <strong>regression logistique</strong> est un algorithme de <em>classification</em>.
|
| 636 |
+
Elle predit la probabilite d'appartenance a une classe en utilisant la fonction sigmoide.
|
| 637 |
+
</p>
|
| 638 |
+
|
| 639 |
+
<div class="equation-block">
|
| 640 |
+
$$P(y=1|\mathbf{x}) = \sigma(\mathbf{w}^T \mathbf{x}) = \frac{1}{1 + e^{-\mathbf{w}^T \mathbf{x}}}$$
|
| 641 |
+
<span class="equation-label">Fonction sigmoide pour la classification binaire</span>
|
| 642 |
+
</div>
|
| 643 |
+
|
| 644 |
+
<div class="info-box">
|
| 645 |
+
<div class="info-box-title">Cas d'usage : Dataset Titanic</div>
|
| 646 |
+
<p>
|
| 647 |
+
Predire la survie des passagers du Titanic a partir de leur age, sexe,
|
| 648 |
+
classe de billet, etc. Un classique du ML pour debuter !
|
| 649 |
+
</p>
|
| 650 |
+
</div>
|
| 651 |
+
|
| 652 |
+
<div class="page-break"></div>
|
| 653 |
+
|
| 654 |
+
<h1>4. Random Forest</h1>
|
| 655 |
+
|
| 656 |
+
<p>
|
| 657 |
+
<strong>Random Forest</strong> est un ensemble d'arbres de decision qui votent pour predire.
|
| 658 |
+
C'est l'un des algorithmes les plus populaires en ML applique : performant, robuste,
|
| 659 |
+
peu sensible au tuning.
|
| 660 |
+
</p>
|
| 661 |
+
|
| 662 |
+
<h2>4.1 Algorithme : Bagging + Random Splits</h2>
|
| 663 |
+
|
| 664 |
+
<div class="pipeline">
|
| 665 |
+
<div class="pipeline-step">
|
| 666 |
+
<div class="pipeline-num">1</div>
|
| 667 |
+
<div class="pipeline-label">Bootstrap</div>
|
| 668 |
+
<div class="pipeline-desc">Echantillons aleatoires</div>
|
| 669 |
+
</div>
|
| 670 |
+
<div class="pipeline-step">
|
| 671 |
+
<div class="pipeline-num">2</div>
|
| 672 |
+
<div class="pipeline-label">Splits</div>
|
| 673 |
+
<div class="pipeline-desc">Features aleatoires</div>
|
| 674 |
+
</div>
|
| 675 |
+
<div class="pipeline-step">
|
| 676 |
+
<div class="pipeline-num">3</div>
|
| 677 |
+
<div class="pipeline-label">Arbres</div>
|
| 678 |
+
<div class="pipeline-desc">N arbres independants</div>
|
| 679 |
+
</div>
|
| 680 |
+
<div class="pipeline-step">
|
| 681 |
+
<div class="pipeline-num">4</div>
|
| 682 |
+
<div class="pipeline-label">Vote</div>
|
| 683 |
+
<div class="pipeline-desc">Moyenne ou mode</div>
|
| 684 |
+
</div>
|
| 685 |
+
</div>
|
| 686 |
+
|
| 687 |
+
<h2>4.2 Hyperparametres cles</h2>
|
| 688 |
+
|
| 689 |
+
<div class="metric-row">
|
| 690 |
+
<div class="metric-card">
|
| 691 |
+
<div class="metric-name">n_estimators</div>
|
| 692 |
+
<div class="metric-formula">100 - 500</div>
|
| 693 |
+
<div class="metric-desc">Nombre d'arbres</div>
|
| 694 |
+
</div>
|
| 695 |
+
<div class="metric-card">
|
| 696 |
+
<div class="metric-name">max_depth</div>
|
| 697 |
+
<div class="metric-formula">10 - 30</div>
|
| 698 |
+
<div class="metric-desc">Profondeur max</div>
|
| 699 |
+
</div>
|
| 700 |
+
<div class="metric-card">
|
| 701 |
+
<div class="metric-name">min_samples_split</div>
|
| 702 |
+
<div class="metric-formula">2 - 10</div>
|
| 703 |
+
<div class="metric-desc">Min pour splitter</div>
|
| 704 |
+
</div>
|
| 705 |
+
</div>
|
| 706 |
+
|
| 707 |
+
<div class="info-box">
|
| 708 |
+
<div class="info-box-title">Feature Importance</div>
|
| 709 |
+
<p>
|
| 710 |
+
Random Forest fournit automatiquement l'importance de chaque feature,
|
| 711 |
+
ce qui aide a comprendre quelles variables influencent le plus les predictions.
|
| 712 |
+
</p>
|
| 713 |
+
</div>
|
| 714 |
+
|
| 715 |
+
<div class="page-break"></div>
|
| 716 |
+
|
| 717 |
+
<h1>5. Reseaux de Neurones</h1>
|
| 718 |
+
|
| 719 |
+
<p>
|
| 720 |
+
Les <strong>reseaux de neurones</strong> sont inspires du cerveau humain : des couches de neurones
|
| 721 |
+
interconnectes executent des transformations non-lineaires. Ils excellent pour les patterns complexes.
|
| 722 |
+
</p>
|
| 723 |
+
|
| 724 |
+
<h2>5.1 Fonctionnement : Forward + Backprop</h2>
|
| 725 |
+
|
| 726 |
+
<div class="cards-grid">
|
| 727 |
+
<div class="card">
|
| 728 |
+
<div class="card-icon">F</div>
|
| 729 |
+
<div class="card-title">Forward Pass</div>
|
| 730 |
+
<div class="card-text">Donnees traversent les couches : $\mathbf{h}_1 = \sigma(W_1 \mathbf{x} + b_1)$</div>
|
| 731 |
+
</div>
|
| 732 |
+
<div class="card">
|
| 733 |
+
<div class="card-icon">L</div>
|
| 734 |
+
<div class="card-title">Loss Computation</div>
|
| 735 |
+
<div class="card-text">Compare prediction vs realite : $L = \frac{1}{m} \sum (y - \hat{y})^2$</div>
|
| 736 |
+
</div>
|
| 737 |
+
<div class="card">
|
| 738 |
+
<div class="card-icon">B</div>
|
| 739 |
+
<div class="card-title">Backpropagation</div>
|
| 740 |
+
<div class="card-text">Calcule les gradients via la chaine de derivation</div>
|
| 741 |
+
</div>
|
| 742 |
+
</div>
|
| 743 |
+
|
| 744 |
+
<h2>5.2 Fonctions d'activation</h2>
|
| 745 |
+
|
| 746 |
+
<div class="metric-row">
|
| 747 |
+
<div class="metric-card">
|
| 748 |
+
<div class="metric-name">ReLU</div>
|
| 749 |
+
<div class="metric-formula">$f(x) = \max(0, x)$</div>
|
| 750 |
+
<div class="metric-desc">Couches cachees</div>
|
| 751 |
+
</div>
|
| 752 |
+
<div class="metric-card">
|
| 753 |
+
<div class="metric-name">Sigmoid</div>
|
| 754 |
+
<div class="metric-formula">$f(x) = \frac{1}{1 + e^{-x}}$</div>
|
| 755 |
+
<div class="metric-desc">Classification binaire</div>
|
| 756 |
+
</div>
|
| 757 |
+
<div class="metric-card">
|
| 758 |
+
<div class="metric-name">Softmax</div>
|
| 759 |
+
<div class="metric-formula">$f(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}}$</div>
|
| 760 |
+
<div class="metric-desc">Classification multi-classe</div>
|
| 761 |
+
</div>
|
| 762 |
+
</div>
|
| 763 |
+
|
| 764 |
+
<div class="page-break"></div>
|
| 765 |
+
|
| 766 |
+
<h1>6. LSTM et Series Temporelles</h1>
|
| 767 |
+
|
| 768 |
+
<p>
|
| 769 |
+
<strong>LSTM (Long Short-Term Memory)</strong> est un type de reseau neuronal pour series temporelles.
|
| 770 |
+
Il peut "retenir" l'information sur de longues periodes — crucial pour les predictions temporelles.
|
| 771 |
+
</p>
|
| 772 |
+
|
| 773 |
+
<div class="info-box">
|
| 774 |
+
<div class="info-box-title">Probleme des RNN vanilla</div>
|
| 775 |
+
<p>
|
| 776 |
+
Les gradients disparaissent (vanishing) ou explosent (exploding) sur de longues sequences.
|
| 777 |
+
Le LSTM resout ce probleme avec son <strong>cell state</strong>.
|
| 778 |
+
</p>
|
| 779 |
+
</div>
|
| 780 |
+
|
| 781 |
+
<h2>6.1 Les trois portes du LSTM</h2>
|
| 782 |
+
|
| 783 |
+
<div class="metric-row">
|
| 784 |
+
<div class="metric-card">
|
| 785 |
+
<div class="metric-name">Forget Gate</div>
|
| 786 |
+
<div class="metric-formula">$f_t = \sigma(W_f [h_{t-1}, x_t] + b_f)$</div>
|
| 787 |
+
<div class="metric-desc">Quoi oublier ?</div>
|
| 788 |
+
</div>
|
| 789 |
+
<div class="metric-card">
|
| 790 |
+
<div class="metric-name">Input Gate</div>
|
| 791 |
+
<div class="metric-formula">$i_t = \sigma(W_i [h_{t-1}, x_t] + b_i)$</div>
|
| 792 |
+
<div class="metric-desc">Quoi ajouter ?</div>
|
| 793 |
+
</div>
|
| 794 |
+
<div class="metric-card">
|
| 795 |
+
<div class="metric-name">Output Gate</div>
|
| 796 |
+
<div class="metric-formula">$o_t = \sigma(W_o [h_{t-1}, x_t] + b_o)$</div>
|
| 797 |
+
<div class="metric-desc">Quoi exposer ?</div>
|
| 798 |
+
</div>
|
| 799 |
+
</div>
|
| 800 |
+
|
| 801 |
+
<div class="info-box">
|
| 802 |
+
<div class="info-box-title">Cas d'usage</div>
|
| 803 |
+
<p>
|
| 804 |
+
Prediction de prix boursiers, meteo, consommation energetique,
|
| 805 |
+
traitement du langage naturel (NLP)...
|
| 806 |
+
</p>
|
| 807 |
+
</div>
|
| 808 |
+
|
| 809 |
+
<div class="page-break"></div>
|
| 810 |
+
|
| 811 |
+
<h1>7. Metriques de Performance</h1>
|
| 812 |
+
|
| 813 |
+
<p>
|
| 814 |
+
Evaluer correctement un modele est crucial. Les bonnes metriques dependent du type de probleme
|
| 815 |
+
(regression vs classification) et des objectifs metier.
|
| 816 |
+
</p>
|
| 817 |
+
|
| 818 |
+
<h2>7.1 Regression</h2>
|
| 819 |
+
|
| 820 |
+
<div class="metric-row">
|
| 821 |
+
<div class="metric-card">
|
| 822 |
+
<div class="metric-name">MAE</div>
|
| 823 |
+
<div class="metric-formula">$\frac{1}{n}\sum|y_i - \hat{y}_i|$</div>
|
| 824 |
+
<div class="metric-desc">Robuste aux outliers</div>
|
| 825 |
+
</div>
|
| 826 |
+
<div class="metric-card">
|
| 827 |
+
<div class="metric-name">RMSE</div>
|
| 828 |
+
<div class="metric-formula">$\sqrt{\frac{1}{n}\sum(y_i - \hat{y}_i)^2}$</div>
|
| 829 |
+
<div class="metric-desc">Penalise les grandes erreurs</div>
|
| 830 |
+
</div>
|
| 831 |
+
<div class="metric-card">
|
| 832 |
+
<div class="metric-name">R2</div>
|
| 833 |
+
<div class="metric-formula">$1 - \frac{SS_{res}}{SS_{tot}}$</div>
|
| 834 |
+
<div class="metric-desc">% variance expliquee</div>
|
| 835 |
+
</div>
|
| 836 |
+
</div>
|
| 837 |
+
|
| 838 |
+
<h2>7.2 Classification</h2>
|
| 839 |
+
|
| 840 |
+
<table>
|
| 841 |
+
<thead>
|
| 842 |
+
<tr>
|
| 843 |
+
<th>Metrique</th>
|
| 844 |
+
<th>Formule</th>
|
| 845 |
+
<th>Usage</th>
|
| 846 |
+
</tr>
|
| 847 |
+
</thead>
|
| 848 |
+
<tbody>
|
| 849 |
+
<tr>
|
| 850 |
+
<td><strong>Accuracy</strong></td>
|
| 851 |
+
<td>$(TP + TN) / Total$</td>
|
| 852 |
+
<td>Classes equilibrees</td>
|
| 853 |
+
</tr>
|
| 854 |
+
<tr>
|
| 855 |
+
<td><strong>Precision</strong></td>
|
| 856 |
+
<td>$TP / (TP + FP)$</td>
|
| 857 |
+
<td>Minimiser faux positifs</td>
|
| 858 |
+
</tr>
|
| 859 |
+
<tr>
|
| 860 |
+
<td><strong>Recall</strong></td>
|
| 861 |
+
<td>$TP / (TP + FN)$</td>
|
| 862 |
+
<td>Minimiser faux negatifs</td>
|
| 863 |
+
</tr>
|
| 864 |
+
<tr>
|
| 865 |
+
<td><strong>F1-Score</strong></td>
|
| 866 |
+
<td>$2 \cdot \frac{P \cdot R}{P + R}$</td>
|
| 867 |
+
<td>Classes desequilibrees</td>
|
| 868 |
+
</tr>
|
| 869 |
+
</tbody>
|
| 870 |
+
</table>
|
| 871 |
+
|
| 872 |
+
<div class="page-break"></div>
|
| 873 |
+
|
| 874 |
+
<h1>8. Optimisation et Regularisation</h1>
|
| 875 |
+
|
| 876 |
+
<p>
|
| 877 |
+
Pour eviter le <strong>surapprentissage (overfitting)</strong> et ameliorer la generalisation,
|
| 878 |
+
plusieurs techniques existent.
|
| 879 |
+
</p>
|
| 880 |
+
|
| 881 |
+
<div class="cards-grid">
|
| 882 |
+
<div class="card">
|
| 883 |
+
<div class="card-icon">D</div>
|
| 884 |
+
<div class="card-title">Dropout</div>
|
| 885 |
+
<div class="card-text">Desactive aleatoirement des neurones pendant l'entrainement.</div>
|
| 886 |
+
</div>
|
| 887 |
+
<div class="card">
|
| 888 |
+
<div class="card-icon">E</div>
|
| 889 |
+
<div class="card-title">Early Stopping</div>
|
| 890 |
+
<div class="card-text">Arrete l'entrainement quand la validation stagne.</div>
|
| 891 |
+
</div>
|
| 892 |
+
<div class="card">
|
| 893 |
+
<div class="card-icon">L</div>
|
| 894 |
+
<div class="card-title">L2 Regularization</div>
|
| 895 |
+
<div class="card-text">Penalise les grands poids : $L_{total} = L_{data} + \lambda \sum w^2$</div>
|
| 896 |
+
</div>
|
| 897 |
+
</div>
|
| 898 |
+
|
| 899 |
+
<div class="info-box">
|
| 900 |
+
<div class="info-box-title">Regle d'or</div>
|
| 901 |
+
<p>
|
| 902 |
+
Toujours comparer les metriques sur <strong>train</strong> ET <strong>test</strong>.
|
| 903 |
+
Un grand ecart = overfitting. Objectif : R2 train ≈ R2 test.
|
| 904 |
+
</p>
|
| 905 |
+
</div>
|
| 906 |
+
|
| 907 |
+
<div class="author-footer">
|
| 908 |
+
<div class="author-name">Imad Maalouf</div>
|
| 909 |
+
<div class="author-contact">
|
| 910 |
+
imadmaalouf02@gmail.com | github.com/imadmaalouf02 | huggingface.co/spaces/MAALOOUF/ML_Training
|
| 911 |
+
</div>
|
| 912 |
+
</div>
|
| 913 |
+
</div>
|
| 914 |
+
</body>
|
| 915 |
+
</html>
|
cours.html
ADDED
|
@@ -0,0 +1,1421 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="fr">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Cours — ML Academy</title>
|
| 7 |
+
<link rel="stylesheet" href="css/shared.css">
|
| 8 |
+
<script>
|
| 9 |
+
window.MathJax = {
|
| 10 |
+
tex: {
|
| 11 |
+
inlineMath: [['$', '$'], ['\\(', '\\)']],
|
| 12 |
+
displayMath: [['$$', '$$'], ['\\[', '\\]']]
|
| 13 |
+
},
|
| 14 |
+
options: { skipHtmlTags: ['script','noscript','style','textarea','pre'] }
|
| 15 |
+
};
|
| 16 |
+
</script>
|
| 17 |
+
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
| 18 |
+
<style>
|
| 19 |
+
/* LAYOUT WITH SIDEBAR */
|
| 20 |
+
.course-layout {
|
| 21 |
+
display: flex;
|
| 22 |
+
min-height: calc(100vh - var(--navbar-height));
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
/* SIDEBAR */
|
| 26 |
+
.sidebar {
|
| 27 |
+
width: var(--sidebar-width);
|
| 28 |
+
background: var(--bg-secondary);
|
| 29 |
+
border-right: 1px solid var(--border-color);
|
| 30 |
+
position: fixed;
|
| 31 |
+
top: var(--navbar-height);
|
| 32 |
+
left: 0;
|
| 33 |
+
bottom: 0;
|
| 34 |
+
overflow-y: auto;
|
| 35 |
+
z-index: 100;
|
| 36 |
+
animation: fadeInLeft 0.5s ease;
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
.sidebar-header {
|
| 40 |
+
padding: var(--space-xl);
|
| 41 |
+
border-bottom: 1px solid var(--border-color);
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
.sidebar-badge {
|
| 45 |
+
display: inline-block;
|
| 46 |
+
padding: var(--space-xs) var(--space-sm);
|
| 47 |
+
background: rgba(99, 102, 241, 0.1);
|
| 48 |
+
border: 1px solid rgba(99, 102, 241, 0.3);
|
| 49 |
+
border-radius: var(--radius-sm);
|
| 50 |
+
font-family: 'JetBrains Mono', monospace;
|
| 51 |
+
font-size: 0.65rem;
|
| 52 |
+
color: var(--primary-light);
|
| 53 |
+
text-transform: uppercase;
|
| 54 |
+
letter-spacing: 1px;
|
| 55 |
+
margin-bottom: var(--space-sm);
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
.sidebar-title {
|
| 59 |
+
font-size: 1.1rem;
|
| 60 |
+
font-weight: 700;
|
| 61 |
+
color: var(--text-primary);
|
| 62 |
+
margin-bottom: var(--space-xs);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
.sidebar-subtitle {
|
| 66 |
+
font-size: 0.8rem;
|
| 67 |
+
color: var(--text-muted);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
.sidebar-nav {
|
| 71 |
+
padding: var(--space-md) 0;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
.nav-section {
|
| 75 |
+
margin-bottom: var(--space-md);
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
.nav-section-title {
|
| 79 |
+
padding: var(--space-sm) var(--space-xl);
|
| 80 |
+
font-family: 'JetBrains Mono', monospace;
|
| 81 |
+
font-size: 0.65rem;
|
| 82 |
+
color: var(--text-muted);
|
| 83 |
+
text-transform: uppercase;
|
| 84 |
+
letter-spacing: 1px;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
.nav-item {
|
| 88 |
+
display: flex;
|
| 89 |
+
align-items: center;
|
| 90 |
+
gap: var(--space-sm);
|
| 91 |
+
padding: var(--space-sm) var(--space-xl);
|
| 92 |
+
color: var(--text-secondary);
|
| 93 |
+
text-decoration: none;
|
| 94 |
+
font-size: 0.9rem;
|
| 95 |
+
transition: all var(--transition-base);
|
| 96 |
+
border-left: 3px solid transparent;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
.nav-item:hover {
|
| 100 |
+
background: var(--bg-hover);
|
| 101 |
+
color: var(--text-primary);
|
| 102 |
+
border-left-color: var(--primary);
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
.nav-item.active {
|
| 106 |
+
background: rgba(99, 102, 241, 0.1);
|
| 107 |
+
color: var(--primary-light);
|
| 108 |
+
border-left-color: var(--primary);
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
.nav-icon {
|
| 112 |
+
font-size: 1rem;
|
| 113 |
+
font-family: 'JetBrains Mono', monospace;
|
| 114 |
+
color: var(--text-muted);
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
.sidebar-footer {
|
| 118 |
+
padding: var(--space-lg) var(--space-xl);
|
| 119 |
+
border-top: 1px solid var(--border-color);
|
| 120 |
+
margin-top: auto;
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
.progress-label {
|
| 124 |
+
font-size: 0.75rem;
|
| 125 |
+
color: var(--text-muted);
|
| 126 |
+
margin-bottom: var(--space-sm);
|
| 127 |
+
display: flex;
|
| 128 |
+
justify-content: space-between;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
.progress-bar {
|
| 132 |
+
height: 6px;
|
| 133 |
+
background: var(--bg-tertiary);
|
| 134 |
+
border-radius: 3px;
|
| 135 |
+
overflow: hidden;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
.progress-fill {
|
| 139 |
+
height: 100%;
|
| 140 |
+
background: linear-gradient(90deg, var(--primary), var(--secondary));
|
| 141 |
+
border-radius: 3px;
|
| 142 |
+
transition: width 0.5s ease;
|
| 143 |
+
animation: progress 1s ease;
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
/* PDF DOWNLOAD BUTTON */
|
| 147 |
+
.pdf-download {
|
| 148 |
+
display: flex;
|
| 149 |
+
align-items: center;
|
| 150 |
+
gap: var(--space-sm);
|
| 151 |
+
padding: var(--space-sm) var(--space-md);
|
| 152 |
+
background: rgba(239, 68, 68, 0.1);
|
| 153 |
+
border: 1px solid rgba(239, 68, 68, 0.3);
|
| 154 |
+
border-radius: var(--radius-md);
|
| 155 |
+
color: #ef4444;
|
| 156 |
+
font-size: 0.8rem;
|
| 157 |
+
font-weight: 600;
|
| 158 |
+
text-decoration: none;
|
| 159 |
+
margin-top: var(--space-md);
|
| 160 |
+
transition: all var(--transition-base);
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
.pdf-download:hover {
|
| 164 |
+
background: rgba(239, 68, 68, 0.2);
|
| 165 |
+
transform: translateY(-2px);
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
/* MAIN CONTENT */
|
| 169 |
+
.main-content {
|
| 170 |
+
flex: 1;
|
| 171 |
+
margin-left: var(--sidebar-width);
|
| 172 |
+
padding: var(--space-2xl);
|
| 173 |
+
max-width: 900px;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
/* COURSE HERO */
|
| 177 |
+
.course-hero {
|
| 178 |
+
text-align: center;
|
| 179 |
+
padding: var(--space-2xl) 0;
|
| 180 |
+
margin-bottom: var(--space-2xl);
|
| 181 |
+
border-bottom: 1px solid var(--border-color);
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
.course-hero-badge {
|
| 185 |
+
display: inline-flex;
|
| 186 |
+
align-items: center;
|
| 187 |
+
gap: var(--space-sm);
|
| 188 |
+
padding: var(--space-xs) var(--space-md);
|
| 189 |
+
background: rgba(16, 185, 129, 0.1);
|
| 190 |
+
border: 1px solid rgba(16, 185, 129, 0.3);
|
| 191 |
+
border-radius: 20px;
|
| 192 |
+
font-size: 0.75rem;
|
| 193 |
+
color: var(--success);
|
| 194 |
+
margin-bottom: var(--space-lg);
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
.course-hero-badge .dot {
|
| 198 |
+
width: 6px;
|
| 199 |
+
height: 6px;
|
| 200 |
+
background: var(--success);
|
| 201 |
+
border-radius: 50%;
|
| 202 |
+
animation: pulse 2s ease-in-out infinite;
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
.course-hero-title {
|
| 206 |
+
font-size: clamp(1.75rem, 4vw, 2.5rem);
|
| 207 |
+
font-weight: 700;
|
| 208 |
+
color: var(--text-primary);
|
| 209 |
+
margin-bottom: var(--space-md);
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
.course-hero-subtitle {
|
| 213 |
+
font-size: 1rem;
|
| 214 |
+
color: var(--text-secondary);
|
| 215 |
+
margin-bottom: var(--space-xl);
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
.course-hero-stats {
|
| 219 |
+
display: flex;
|
| 220 |
+
justify-content: center;
|
| 221 |
+
gap: var(--space-2xl);
|
| 222 |
+
flex-wrap: wrap;
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
.course-hero-stat {
|
| 226 |
+
text-align: center;
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
.course-hero-stat-value {
|
| 230 |
+
font-family: 'JetBrains Mono', monospace;
|
| 231 |
+
font-size: 2rem;
|
| 232 |
+
font-weight: 700;
|
| 233 |
+
color: var(--text-primary);
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
.course-hero-stat-label {
|
| 237 |
+
font-size: 0.7rem;
|
| 238 |
+
color: var(--text-muted);
|
| 239 |
+
text-transform: uppercase;
|
| 240 |
+
letter-spacing: 1px;
|
| 241 |
+
margin-top: var(--space-xs);
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
/* SECTIONS */
|
| 245 |
+
.section {
|
| 246 |
+
margin-bottom: var(--space-3xl);
|
| 247 |
+
scroll-margin-top: calc(var(--navbar-height) + var(--space-lg));
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
.section-header {
|
| 251 |
+
margin-bottom: var(--space-xl);
|
| 252 |
+
padding-bottom: var(--space-md);
|
| 253 |
+
border-bottom: 1px solid var(--border-color);
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
.section-badge {
|
| 257 |
+
display: inline-block;
|
| 258 |
+
padding: var(--space-xs) var(--space-sm);
|
| 259 |
+
background: rgba(99, 102, 241, 0.1);
|
| 260 |
+
border-radius: var(--radius-sm);
|
| 261 |
+
font-family: 'JetBrains Mono', monospace;
|
| 262 |
+
font-size: 0.65rem;
|
| 263 |
+
color: var(--primary-light);
|
| 264 |
+
text-transform: uppercase;
|
| 265 |
+
letter-spacing: 1px;
|
| 266 |
+
margin-bottom: var(--space-sm);
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
.section-title {
|
| 270 |
+
font-size: clamp(1.5rem, 3vw, 2rem);
|
| 271 |
+
font-weight: 700;
|
| 272 |
+
color: var(--text-primary);
|
| 273 |
+
margin-bottom: var(--space-sm);
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
.section-title small {
|
| 277 |
+
display: block;
|
| 278 |
+
font-size: 0.9rem;
|
| 279 |
+
color: var(--text-muted);
|
| 280 |
+
font-weight: 500;
|
| 281 |
+
margin-bottom: var(--space-xs);
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
.section-content p {
|
| 285 |
+
font-size: 1rem;
|
| 286 |
+
color: var(--text-secondary);
|
| 287 |
+
line-height: 1.8;
|
| 288 |
+
margin-bottom: var(--space-md);
|
| 289 |
+
}
|
| 290 |
+
|
| 291 |
+
.section-content strong {
|
| 292 |
+
color: var(--text-primary);
|
| 293 |
+
font-weight: 600;
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
+
/* CARDS GRID */
|
| 297 |
+
.cards-grid {
|
| 298 |
+
display: grid;
|
| 299 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
| 300 |
+
gap: var(--space-md);
|
| 301 |
+
margin: var(--space-lg) 0;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
.info-card {
|
| 305 |
+
background: var(--bg-card);
|
| 306 |
+
border: 1px solid var(--border-color);
|
| 307 |
+
border-radius: var(--radius-md);
|
| 308 |
+
padding: var(--space-lg);
|
| 309 |
+
transition: all var(--transition-base);
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
.info-card:hover {
|
| 313 |
+
border-color: var(--primary);
|
| 314 |
+
transform: translateY(-3px);
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
.info-card-icon {
|
| 318 |
+
width: 40px;
|
| 319 |
+
height: 40px;
|
| 320 |
+
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
| 321 |
+
border-radius: var(--radius-md);
|
| 322 |
+
display: flex;
|
| 323 |
+
align-items: center;
|
| 324 |
+
justify-content: center;
|
| 325 |
+
font-size: 1rem;
|
| 326 |
+
font-weight: 700;
|
| 327 |
+
color: white;
|
| 328 |
+
margin-bottom: var(--space-sm);
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
.info-card-title {
|
| 332 |
+
font-size: 1rem;
|
| 333 |
+
font-weight: 600;
|
| 334 |
+
color: var(--text-primary);
|
| 335 |
+
margin-bottom: var(--space-xs);
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
.info-card-text {
|
| 339 |
+
font-size: 0.85rem;
|
| 340 |
+
color: var(--text-secondary);
|
| 341 |
+
}
|
| 342 |
+
|
| 343 |
+
.info-card-tag {
|
| 344 |
+
display: inline-block;
|
| 345 |
+
margin-top: var(--space-sm);
|
| 346 |
+
padding: var(--space-xs) var(--space-sm);
|
| 347 |
+
background: var(--bg-tertiary);
|
| 348 |
+
border-radius: var(--radius-sm);
|
| 349 |
+
font-family: 'JetBrains Mono', monospace;
|
| 350 |
+
font-size: 0.65rem;
|
| 351 |
+
color: var(--text-muted);
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
/* PIPELINE */
|
| 355 |
+
.pipeline {
|
| 356 |
+
display: flex;
|
| 357 |
+
flex-wrap: wrap;
|
| 358 |
+
gap: var(--space-md);
|
| 359 |
+
margin: var(--space-xl) 0;
|
| 360 |
+
padding: var(--space-lg);
|
| 361 |
+
background: var(--bg-card);
|
| 362 |
+
border: 1px solid var(--border-color);
|
| 363 |
+
border-radius: var(--radius-lg);
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
.pipeline-step {
|
| 367 |
+
flex: 1;
|
| 368 |
+
min-width: 120px;
|
| 369 |
+
text-align: center;
|
| 370 |
+
padding: var(--space-md);
|
| 371 |
+
position: relative;
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
.pipeline-step:not(:last-child)::after {
|
| 375 |
+
content: '->';
|
| 376 |
+
position: absolute;
|
| 377 |
+
right: -15px;
|
| 378 |
+
top: 50%;
|
| 379 |
+
transform: translateY(-50%);
|
| 380 |
+
color: var(--primary);
|
| 381 |
+
font-family: 'JetBrains Mono', monospace;
|
| 382 |
+
font-size: 1rem;
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
.pipeline-num {
|
| 386 |
+
width: 36px;
|
| 387 |
+
height: 36px;
|
| 388 |
+
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
| 389 |
+
border-radius: 50%;
|
| 390 |
+
display: flex;
|
| 391 |
+
align-items: center;
|
| 392 |
+
justify-content: center;
|
| 393 |
+
font-family: 'JetBrains Mono', monospace;
|
| 394 |
+
font-size: 0.9rem;
|
| 395 |
+
font-weight: 700;
|
| 396 |
+
color: white;
|
| 397 |
+
margin: 0 auto var(--space-sm);
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
.pipeline-label {
|
| 401 |
+
font-size: 0.85rem;
|
| 402 |
+
font-weight: 600;
|
| 403 |
+
color: var(--text-primary);
|
| 404 |
+
margin-bottom: var(--space-xs);
|
| 405 |
+
}
|
| 406 |
+
|
| 407 |
+
.pipeline-desc {
|
| 408 |
+
font-size: 0.75rem;
|
| 409 |
+
color: var(--text-muted);
|
| 410 |
+
}
|
| 411 |
+
|
| 412 |
+
/* CHECKLIST */
|
| 413 |
+
.checklist {
|
| 414 |
+
list-style: none;
|
| 415 |
+
padding: 0;
|
| 416 |
+
margin: var(--space-lg) 0;
|
| 417 |
+
}
|
| 418 |
+
|
| 419 |
+
.checklist li {
|
| 420 |
+
display: flex;
|
| 421 |
+
align-items: flex-start;
|
| 422 |
+
gap: var(--space-sm);
|
| 423 |
+
padding: var(--space-sm) 0;
|
| 424 |
+
font-size: 0.95rem;
|
| 425 |
+
color: var(--text-secondary);
|
| 426 |
+
}
|
| 427 |
+
|
| 428 |
+
.checklist li::before {
|
| 429 |
+
content: '[v]';
|
| 430 |
+
color: var(--success);
|
| 431 |
+
font-family: 'JetBrains Mono', monospace;
|
| 432 |
+
font-weight: 700;
|
| 433 |
+
flex-shrink: 0;
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
/* EQUATIONS */
|
| 437 |
+
.equation-block {
|
| 438 |
+
background: var(--bg-card);
|
| 439 |
+
border: 1px solid var(--border-color);
|
| 440 |
+
border-left: 3px solid var(--primary);
|
| 441 |
+
border-radius: var(--radius-md);
|
| 442 |
+
padding: var(--space-lg);
|
| 443 |
+
margin: var(--space-lg) 0;
|
| 444 |
+
text-align: center;
|
| 445 |
+
overflow-x: auto;
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
.equation-label {
|
| 449 |
+
display: block;
|
| 450 |
+
font-family: 'JetBrains Mono', monospace;
|
| 451 |
+
font-size: 0.7rem;
|
| 452 |
+
color: var(--text-muted);
|
| 453 |
+
text-align: right;
|
| 454 |
+
margin-top: var(--space-sm);
|
| 455 |
+
}
|
| 456 |
+
|
| 457 |
+
/* COMPARISON GRID */
|
| 458 |
+
.comparison-grid {
|
| 459 |
+
display: grid;
|
| 460 |
+
grid-template-columns: repeat(2, 1fr);
|
| 461 |
+
gap: var(--space-md);
|
| 462 |
+
margin: var(--space-lg) 0;
|
| 463 |
+
}
|
| 464 |
+
|
| 465 |
+
.comparison-box {
|
| 466 |
+
background: var(--bg-card);
|
| 467 |
+
border: 1px solid var(--border-color);
|
| 468 |
+
border-radius: var(--radius-md);
|
| 469 |
+
padding: var(--space-lg);
|
| 470 |
+
}
|
| 471 |
+
|
| 472 |
+
.comparison-box h4 {
|
| 473 |
+
font-size: 0.9rem;
|
| 474 |
+
font-weight: 600;
|
| 475 |
+
color: var(--text-primary);
|
| 476 |
+
margin-bottom: var(--space-md);
|
| 477 |
+
padding-bottom: var(--space-sm);
|
| 478 |
+
border-bottom: 1px solid var(--border-color);
|
| 479 |
+
}
|
| 480 |
+
|
| 481 |
+
.comparison-box ul {
|
| 482 |
+
list-style: none;
|
| 483 |
+
padding: 0;
|
| 484 |
+
margin: 0;
|
| 485 |
+
}
|
| 486 |
+
|
| 487 |
+
.comparison-box li {
|
| 488 |
+
padding: var(--space-xs) 0;
|
| 489 |
+
font-size: 0.85rem;
|
| 490 |
+
color: var(--text-secondary);
|
| 491 |
+
}
|
| 492 |
+
|
| 493 |
+
.comparison-box li::before {
|
| 494 |
+
content: '>';
|
| 495 |
+
color: var(--primary);
|
| 496 |
+
margin-right: var(--space-sm);
|
| 497 |
+
font-family: 'JetBrains Mono', monospace;
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
/* METRIC CARDS */
|
| 501 |
+
.metric-row {
|
| 502 |
+
display: grid;
|
| 503 |
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
| 504 |
+
gap: var(--space-md);
|
| 505 |
+
margin: var(--space-lg) 0;
|
| 506 |
+
}
|
| 507 |
+
|
| 508 |
+
.metric-card {
|
| 509 |
+
background: var(--bg-card);
|
| 510 |
+
border: 1px solid var(--border-color);
|
| 511 |
+
border-radius: var(--radius-md);
|
| 512 |
+
padding: var(--space-lg);
|
| 513 |
+
text-align: center;
|
| 514 |
+
transition: all var(--transition-base);
|
| 515 |
+
}
|
| 516 |
+
|
| 517 |
+
.metric-card:hover {
|
| 518 |
+
border-color: var(--primary);
|
| 519 |
+
transform: translateY(-3px);
|
| 520 |
+
}
|
| 521 |
+
|
| 522 |
+
.metric-name {
|
| 523 |
+
font-family: 'JetBrains Mono', monospace;
|
| 524 |
+
font-size: 0.75rem;
|
| 525 |
+
color: var(--text-muted);
|
| 526 |
+
text-transform: uppercase;
|
| 527 |
+
letter-spacing: 1px;
|
| 528 |
+
margin-bottom: var(--space-sm);
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
.metric-formula {
|
| 532 |
+
font-family: 'JetBrains Mono', monospace;
|
| 533 |
+
font-size: 1rem;
|
| 534 |
+
color: var(--primary-light);
|
| 535 |
+
font-weight: 600;
|
| 536 |
+
margin-bottom: var(--space-xs);
|
| 537 |
+
}
|
| 538 |
+
|
| 539 |
+
.metric-desc {
|
| 540 |
+
font-size: 0.75rem;
|
| 541 |
+
color: var(--text-muted);
|
| 542 |
+
}
|
| 543 |
+
|
| 544 |
+
/* RESPONSIVE */
|
| 545 |
+
@media (max-width: 768px) {
|
| 546 |
+
.sidebar {
|
| 547 |
+
transform: translateX(-100%);
|
| 548 |
+
transition: transform var(--transition-base);
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
+
.sidebar.open {
|
| 552 |
+
transform: translateX(0);
|
| 553 |
+
}
|
| 554 |
+
|
| 555 |
+
.main-content {
|
| 556 |
+
margin-left: 0;
|
| 557 |
+
padding: var(--space-lg);
|
| 558 |
+
}
|
| 559 |
+
|
| 560 |
+
.comparison-grid {
|
| 561 |
+
grid-template-columns: 1fr;
|
| 562 |
+
}
|
| 563 |
+
|
| 564 |
+
.pipeline-step:not(:last-child)::after {
|
| 565 |
+
display: none;
|
| 566 |
+
}
|
| 567 |
+
}
|
| 568 |
+
|
| 569 |
+
/* BACK TO TOP */
|
| 570 |
+
.back-to-top {
|
| 571 |
+
position: fixed;
|
| 572 |
+
bottom: var(--space-xl);
|
| 573 |
+
right: var(--space-xl);
|
| 574 |
+
width: 44px;
|
| 575 |
+
height: 44px;
|
| 576 |
+
background: var(--primary);
|
| 577 |
+
border: none;
|
| 578 |
+
border-radius: 50%;
|
| 579 |
+
color: white;
|
| 580 |
+
font-size: 1.2rem;
|
| 581 |
+
cursor: pointer;
|
| 582 |
+
opacity: 0;
|
| 583 |
+
visibility: hidden;
|
| 584 |
+
transition: all var(--transition-base);
|
| 585 |
+
z-index: 1000;
|
| 586 |
+
display: flex;
|
| 587 |
+
align-items: center;
|
| 588 |
+
justify-content: center;
|
| 589 |
+
}
|
| 590 |
+
|
| 591 |
+
.back-to-top.visible {
|
| 592 |
+
opacity: 1;
|
| 593 |
+
visibility: visible;
|
| 594 |
+
}
|
| 595 |
+
|
| 596 |
+
.back-to-top:hover {
|
| 597 |
+
background: var(--primary-light);
|
| 598 |
+
transform: translateY(-3px);
|
| 599 |
+
}
|
| 600 |
+
|
| 601 |
+
/* AUTHOR FOOTER */
|
| 602 |
+
.author-footer {
|
| 603 |
+
background: var(--bg-secondary);
|
| 604 |
+
border-top: 1px solid var(--border-color);
|
| 605 |
+
padding: var(--space-xl);
|
| 606 |
+
text-align: center;
|
| 607 |
+
}
|
| 608 |
+
|
| 609 |
+
.author-info {
|
| 610 |
+
display: flex;
|
| 611 |
+
justify-content: center;
|
| 612 |
+
gap: var(--space-xl);
|
| 613 |
+
flex-wrap: wrap;
|
| 614 |
+
margin-bottom: var(--space-md);
|
| 615 |
+
}
|
| 616 |
+
|
| 617 |
+
.author-link {
|
| 618 |
+
display: flex;
|
| 619 |
+
align-items: center;
|
| 620 |
+
gap: var(--space-sm);
|
| 621 |
+
color: var(--text-secondary);
|
| 622 |
+
text-decoration: none;
|
| 623 |
+
font-size: 0.9rem;
|
| 624 |
+
transition: color var(--transition-base);
|
| 625 |
+
}
|
| 626 |
+
|
| 627 |
+
.author-link:hover {
|
| 628 |
+
color: var(--primary-light);
|
| 629 |
+
}
|
| 630 |
+
|
| 631 |
+
.author-link svg {
|
| 632 |
+
width: 18px;
|
| 633 |
+
height: 18px;
|
| 634 |
+
fill: currentColor;
|
| 635 |
+
}
|
| 636 |
+
</style>
|
| 637 |
+
</head>
|
| 638 |
+
<body>
|
| 639 |
+
<!-- Particles Background -->
|
| 640 |
+
<div class="particles-container">
|
| 641 |
+
<div class="particle"></div>
|
| 642 |
+
<div class="particle"></div>
|
| 643 |
+
<div class="particle"></div>
|
| 644 |
+
<div class="particle"></div>
|
| 645 |
+
<div class="particle"></div>
|
| 646 |
+
</div>
|
| 647 |
+
|
| 648 |
+
<!-- Navigation -->
|
| 649 |
+
<nav class="navbar">
|
| 650 |
+
<a href="index.html" class="navbar-brand">
|
| 651 |
+
<div class="brand-logo">ML</div>
|
| 652 |
+
<span>ML Academy</span>
|
| 653 |
+
</a>
|
| 654 |
+
<div class="navbar-nav">
|
| 655 |
+
<a href="index.html" class="nav-link">
|
| 656 |
+
<span class="nav-icon">[H]</span>
|
| 657 |
+
<span>Accueil</span>
|
| 658 |
+
</a>
|
| 659 |
+
<a href="cours.html" class="nav-link active">
|
| 660 |
+
<span class="nav-icon">[C]</span>
|
| 661 |
+
<span>Cours</span>
|
| 662 |
+
</a>
|
| 663 |
+
<a href="tp.html" class="nav-link">
|
| 664 |
+
<span class="nav-icon">[T]</span>
|
| 665 |
+
<span>TPs</span>
|
| 666 |
+
</a>
|
| 667 |
+
<a href="feedback.html" class="nav-link">
|
| 668 |
+
<span class="nav-icon">[F]</span>
|
| 669 |
+
<span>Contact</span>
|
| 670 |
+
</a>
|
| 671 |
+
</div>
|
| 672 |
+
<div class="nav-badge">
|
| 673 |
+
<div class="dot"></div>
|
| 674 |
+
<span>Google Colab Ready</span>
|
| 675 |
+
</div>
|
| 676 |
+
</nav>
|
| 677 |
+
|
| 678 |
+
<!-- Course Layout -->
|
| 679 |
+
<div class="course-layout">
|
| 680 |
+
<!-- Sidebar -->
|
| 681 |
+
<aside class="sidebar">
|
| 682 |
+
<div class="sidebar-header">
|
| 683 |
+
<div class="sidebar-badge">Formation 2025/2026</div>
|
| 684 |
+
<h1 class="sidebar-title">Machine Learning</h1>
|
| 685 |
+
<p class="sidebar-subtitle">Cours theoriques complets</p>
|
| 686 |
+
<a href="cours.pdf" class="pdf-download" download>
|
| 687 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
| 688 |
+
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
|
| 689 |
+
</svg>
|
| 690 |
+
Telecharger le PDF
|
| 691 |
+
</a>
|
| 692 |
+
</div>
|
| 693 |
+
|
| 694 |
+
<nav class="sidebar-nav">
|
| 695 |
+
<div class="nav-section">
|
| 696 |
+
<div class="nav-section-title">Introduction</div>
|
| 697 |
+
<a href="#intro" class="nav-item active">
|
| 698 |
+
<span class="nav-icon">[1]</span>
|
| 699 |
+
<span>Qu'est-ce que le ML ?</span>
|
| 700 |
+
</a>
|
| 701 |
+
</div>
|
| 702 |
+
|
| 703 |
+
<div class="nav-section">
|
| 704 |
+
<div class="nav-section-title">Algorithmes Supervises</div>
|
| 705 |
+
<a href="#regression" class="nav-item">
|
| 706 |
+
<span class="nav-icon">[2]</span>
|
| 707 |
+
<span>Regression Lineaire</span>
|
| 708 |
+
</a>
|
| 709 |
+
<a href="#logistic" class="nav-item">
|
| 710 |
+
<span class="nav-icon">[3]</span>
|
| 711 |
+
<span>Regression Logistique</span>
|
| 712 |
+
</a>
|
| 713 |
+
<a href="#randomforest" class="nav-item">
|
| 714 |
+
<span class="nav-icon">[4]</span>
|
| 715 |
+
<span>Random Forest</span>
|
| 716 |
+
</a>
|
| 717 |
+
</div>
|
| 718 |
+
|
| 719 |
+
<div class="nav-section">
|
| 720 |
+
<div class="nav-section-title">Deep Learning</div>
|
| 721 |
+
<a href="#neuralnets" class="nav-item">
|
| 722 |
+
<span class="nav-icon">[5]</span>
|
| 723 |
+
<span>Reseaux de Neurones</span>
|
| 724 |
+
</a>
|
| 725 |
+
<a href="#lstm" class="nav-item">
|
| 726 |
+
<span class="nav-icon">[6]</span>
|
| 727 |
+
<span>LSTM & Series Temp.</span>
|
| 728 |
+
</a>
|
| 729 |
+
</div>
|
| 730 |
+
|
| 731 |
+
<div class="nav-section">
|
| 732 |
+
<div class="nav-section-title">Evaluation</div>
|
| 733 |
+
<a href="#metrics" class="nav-item">
|
| 734 |
+
<span class="nav-icon">[7]</span>
|
| 735 |
+
<span>Metriques</span>
|
| 736 |
+
</a>
|
| 737 |
+
<a href="#optimization" class="nav-item">
|
| 738 |
+
<span class="nav-icon">[8]</span>
|
| 739 |
+
<span>Optimisation</span>
|
| 740 |
+
</a>
|
| 741 |
+
</div>
|
| 742 |
+
|
| 743 |
+
<div class="nav-section">
|
| 744 |
+
<div class="nav-section-title">Navigation</div>
|
| 745 |
+
<a href="index.html" class="nav-item">
|
| 746 |
+
<span class="nav-icon">[H]</span>
|
| 747 |
+
<span>Accueil</span>
|
| 748 |
+
</a>
|
| 749 |
+
<a href="tp.html" class="nav-item">
|
| 750 |
+
<span class="nav-icon">[T]</span>
|
| 751 |
+
<span>Travaux Pratiques</span>
|
| 752 |
+
</a>
|
| 753 |
+
<a href="feedback.html" class="nav-item">
|
| 754 |
+
<span class="nav-icon">[F]</span>
|
| 755 |
+
<span>Questions</span>
|
| 756 |
+
</a>
|
| 757 |
+
</div>
|
| 758 |
+
</nav>
|
| 759 |
+
|
| 760 |
+
<div class="sidebar-footer">
|
| 761 |
+
<div class="progress-label">
|
| 762 |
+
<span>Progression</span>
|
| 763 |
+
<span id="progress-text">0%</span>
|
| 764 |
+
</div>
|
| 765 |
+
<div class="progress-bar">
|
| 766 |
+
<div class="progress-fill" id="progress-fill" style="width: 0%"></div>
|
| 767 |
+
</div>
|
| 768 |
+
</div>
|
| 769 |
+
</aside>
|
| 770 |
+
|
| 771 |
+
<!-- Main Content -->
|
| 772 |
+
<main class="main-content">
|
| 773 |
+
<!-- Course Hero -->
|
| 774 |
+
<div class="course-hero scroll-animate">
|
| 775 |
+
<div class="course-hero-badge">
|
| 776 |
+
<div class="dot"></div>
|
| 777 |
+
<span>Pret a executer sur Google Colab</span>
|
| 778 |
+
</div>
|
| 779 |
+
<h1 class="course-hero-title">
|
| 780 |
+
Cours de <span class="gradient-text">Machine Learning</span>
|
| 781 |
+
</h1>
|
| 782 |
+
<p class="course-hero-subtitle">
|
| 783 |
+
Formation complete couvrant les algorithmes fondamentaux jusqu'aux techniques avancees.
|
| 784 |
+
</p>
|
| 785 |
+
<div class="course-hero-stats">
|
| 786 |
+
<div class="course-hero-stat">
|
| 787 |
+
<div class="course-hero-stat-value">8</div>
|
| 788 |
+
<div class="course-hero-stat-label">Chapitres</div>
|
| 789 |
+
</div>
|
| 790 |
+
<div class="course-hero-stat">
|
| 791 |
+
<div class="course-hero-stat-value">25+</div>
|
| 792 |
+
<div class="course-hero-stat-label">Equations</div>
|
| 793 |
+
</div>
|
| 794 |
+
<div class="course-hero-stat">
|
| 795 |
+
<div class="course-hero-stat-value">50+</div>
|
| 796 |
+
<div class="course-hero-stat-label">Exemples de code</div>
|
| 797 |
+
</div>
|
| 798 |
+
</div>
|
| 799 |
+
</div>
|
| 800 |
+
|
| 801 |
+
<!-- Section 1: Introduction -->
|
| 802 |
+
<section class="section" id="intro">
|
| 803 |
+
<div class="section-header scroll-animate">
|
| 804 |
+
<div class="section-badge">Partie 1 · 20 min</div>
|
| 805 |
+
<h2 class="section-title">
|
| 806 |
+
<small>Fondamentaux</small>
|
| 807 |
+
Qu'est-ce que le Machine Learning ?
|
| 808 |
+
</h2>
|
| 809 |
+
</div>
|
| 810 |
+
|
| 811 |
+
<div class="section-content scroll-animate">
|
| 812 |
+
<p>
|
| 813 |
+
Le <strong>Machine Learning (ML)</strong> est une branche de l'intelligence artificielle
|
| 814 |
+
qui permet aux machines d'apprendre a partir de donnees <em>sans etre explicitement programmees</em>
|
| 815 |
+
pour chaque tache. Au lieu de coder des regles a la main, on montre des exemples au modele
|
| 816 |
+
et il decouvre lui-meme les patterns.
|
| 817 |
+
</p>
|
| 818 |
+
|
| 819 |
+
<div class="callout callout-info scroll-animate">
|
| 820 |
+
<div class="callout-icon">[i]</div>
|
| 821 |
+
<div class="callout-content">
|
| 822 |
+
<div class="callout-title">Idee fondamentale</div>
|
| 823 |
+
<div class="callout-text">
|
| 824 |
+
On cherche a approximer une fonction inconnue $f$ telle que $\hat{y} = f(x_1, x_2, \ldots, x_n)$.
|
| 825 |
+
Le modele ML apprend cette fonction a partir d'exemples $(x, y)$ connus.
|
| 826 |
+
</div>
|
| 827 |
+
</div>
|
| 828 |
+
</div>
|
| 829 |
+
|
| 830 |
+
<h3 style="font-size: 1.2rem; font-weight: 600; color: var(--text-primary); margin: var(--space-xl) 0 var(--space-md);">
|
| 831 |
+
Types d'apprentissage
|
| 832 |
+
</h3>
|
| 833 |
+
|
| 834 |
+
<div class="cards-grid scroll-animate">
|
| 835 |
+
<div class="info-card">
|
| 836 |
+
<div class="info-card-icon">S</div>
|
| 837 |
+
<h4 class="info-card-title">Supervise</h4>
|
| 838 |
+
<p class="info-card-text">Donnees labellisees $(x, y)$ : regression et classification.</p>
|
| 839 |
+
<span class="info-card-tag">Predictions</span>
|
| 840 |
+
</div>
|
| 841 |
+
<div class="info-card">
|
| 842 |
+
<div class="info-card-icon">N</div>
|
| 843 |
+
<h4 class="info-card-title">Non supervise</h4>
|
| 844 |
+
<p class="info-card-text">Pas de labels : clustering, reduction de dimension.</p>
|
| 845 |
+
<span class="info-card-tag">Patterns</span>
|
| 846 |
+
</div>
|
| 847 |
+
<div class="info-card">
|
| 848 |
+
<div class="info-card-icon">R</div>
|
| 849 |
+
<h4 class="info-card-title">Par renforcement</h4>
|
| 850 |
+
<p class="info-card-text">Agent apprend via actions-recompenses.</p>
|
| 851 |
+
<span class="info-card-tag">Strategies</span>
|
| 852 |
+
</div>
|
| 853 |
+
</div>
|
| 854 |
+
|
| 855 |
+
<h3 style="font-size: 1.2rem; font-weight: 600; color: var(--text-primary); margin: var(--space-xl) 0 var(--space-md);">
|
| 856 |
+
Pipeline ML typique
|
| 857 |
+
</h3>
|
| 858 |
+
|
| 859 |
+
<div class="pipeline scroll-animate">
|
| 860 |
+
<div class="pipeline-step">
|
| 861 |
+
<div class="pipeline-num">1</div>
|
| 862 |
+
<div class="pipeline-label">Donnees</div>
|
| 863 |
+
<div class="pipeline-desc">Collecte & nettoyage</div>
|
| 864 |
+
</div>
|
| 865 |
+
<div class="pipeline-step">
|
| 866 |
+
<div class="pipeline-num">2</div>
|
| 867 |
+
<div class="pipeline-label">Features</div>
|
| 868 |
+
<div class="pipeline-desc">Engineering</div>
|
| 869 |
+
</div>
|
| 870 |
+
<div class="pipeline-step">
|
| 871 |
+
<div class="pipeline-num">3</div>
|
| 872 |
+
<div class="pipeline-label">Split</div>
|
| 873 |
+
<div class="pipeline-desc">Train / Test</div>
|
| 874 |
+
</div>
|
| 875 |
+
<div class="pipeline-step">
|
| 876 |
+
<div class="pipeline-num">4</div>
|
| 877 |
+
<div class="pipeline-label">Modele</div>
|
| 878 |
+
<div class="pipeline-desc">Entrainement</div>
|
| 879 |
+
</div>
|
| 880 |
+
<div class="pipeline-step">
|
| 881 |
+
<div class="pipeline-num">5</div>
|
| 882 |
+
<div class="pipeline-label">Evaluation</div>
|
| 883 |
+
<div class="pipeline-desc">Metriques</div>
|
| 884 |
+
</div>
|
| 885 |
+
<div class="pipeline-step">
|
| 886 |
+
<div class="pipeline-num">6</div>
|
| 887 |
+
<div class="pipeline-label">Production</div>
|
| 888 |
+
<div class="pipeline-desc">Deploiement</div>
|
| 889 |
+
</div>
|
| 890 |
+
</div>
|
| 891 |
+
</div>
|
| 892 |
+
</section>
|
| 893 |
+
|
| 894 |
+
<!-- Section 2: Regression Lineaire -->
|
| 895 |
+
<section class="section" id="regression">
|
| 896 |
+
<div class="section-header scroll-animate">
|
| 897 |
+
<div class="section-badge">Partie 2 · 25 min</div>
|
| 898 |
+
<h2 class="section-title">
|
| 899 |
+
<small>Algorithmes de base</small>
|
| 900 |
+
Regression Lineaire
|
| 901 |
+
</h2>
|
| 902 |
+
</div>
|
| 903 |
+
|
| 904 |
+
<div class="section-content scroll-animate">
|
| 905 |
+
<p>
|
| 906 |
+
La <strong>regression lineaire</strong> modelise la relation entre les features et la cible
|
| 907 |
+
par une fonction affine. C'est l'algorithme le plus simple mais souvent tres efficace
|
| 908 |
+
comme baseline.
|
| 909 |
+
</p>
|
| 910 |
+
|
| 911 |
+
<div class="equation-block">
|
| 912 |
+
$$\hat{y} = w_0 + w_1 x_1 + w_2 x_2 + \cdots + w_n x_n = \mathbf{w}^T \mathbf{x}$$
|
| 913 |
+
<span class="equation-label">Modele lineaire avec coefficients $\mathbf{w}$</span>
|
| 914 |
+
</div>
|
| 915 |
+
|
| 916 |
+
<p>
|
| 917 |
+
L'objectif est de minimiser l'erreur quadratique moyenne (MSE) :
|
| 918 |
+
</p>
|
| 919 |
+
|
| 920 |
+
<div class="equation-block">
|
| 921 |
+
$$\text{MSE} = \frac{1}{m} \sum_{i=1}^{m} (y_i - \hat{y}_i)^2$$
|
| 922 |
+
<span class="equation-label">Fonction de cout : moyenne des erreurs quadratiques</span>
|
| 923 |
+
</div>
|
| 924 |
+
|
| 925 |
+
<div class="callout callout-info scroll-animate">
|
| 926 |
+
<div class="callout-icon">[i]</div>
|
| 927 |
+
<div class="callout-content">
|
| 928 |
+
<div class="callout-title">Solution analytique</div>
|
| 929 |
+
<div class="callout-text">
|
| 930 |
+
La regression lineaire admet une solution fermee :
|
| 931 |
+
$\mathbf{w}^* = (X^T X)^{-1} X^T Y$. Pas besoin d'iterations !
|
| 932 |
+
</div>
|
| 933 |
+
</div>
|
| 934 |
+
</div>
|
| 935 |
+
|
| 936 |
+
<div class="comparison-grid scroll-animate">
|
| 937 |
+
<div class="comparison-box">
|
| 938 |
+
<h4>[+] Avantages</h4>
|
| 939 |
+
<ul>
|
| 940 |
+
<li>Tres rapide a entrainer</li>
|
| 941 |
+
<li>Interpretable (coefficients)</li>
|
| 942 |
+
<li>Pas d'hyperparametres</li>
|
| 943 |
+
<li>Excellent baseline</li>
|
| 944 |
+
</ul>
|
| 945 |
+
</div>
|
| 946 |
+
<div class="comparison-box">
|
| 947 |
+
<h4>[-] Limitations</h4>
|
| 948 |
+
<ul>
|
| 949 |
+
<li>Relation lineaire uniquement</li>
|
| 950 |
+
<li>Sensible aux outliers</li>
|
| 951 |
+
<li>Performance decroit en haute dimension</li>
|
| 952 |
+
</ul>
|
| 953 |
+
</div>
|
| 954 |
+
</div>
|
| 955 |
+
</div>
|
| 956 |
+
</section>
|
| 957 |
+
|
| 958 |
+
<!-- Section 3: Regression Logistique -->
|
| 959 |
+
<section class="section" id="logistic">
|
| 960 |
+
<div class="section-header scroll-animate">
|
| 961 |
+
<div class="section-badge">Partie 3 · 20 min</div>
|
| 962 |
+
<h2 class="section-title">
|
| 963 |
+
<small>Classification</small>
|
| 964 |
+
Regression Logistique
|
| 965 |
+
</h2>
|
| 966 |
+
</div>
|
| 967 |
+
|
| 968 |
+
<div class="section-content scroll-animate">
|
| 969 |
+
<p>
|
| 970 |
+
Malgre son nom, la <strong>regression logistique</strong> est un algorithme de <em>classification</em>.
|
| 971 |
+
Elle predit la probabilite d'appartenance a une classe en utilisant la fonction sigmoide.
|
| 972 |
+
</p>
|
| 973 |
+
|
| 974 |
+
<div class="equation-block">
|
| 975 |
+
$$P(y=1|\mathbf{x}) = \sigma(\mathbf{w}^T \mathbf{x}) = \frac{1}{1 + e^{-\mathbf{w}^T \mathbf{x}}}$$
|
| 976 |
+
<span class="equation-label">Fonction sigmoide pour la classification binaire</span>
|
| 977 |
+
</div>
|
| 978 |
+
|
| 979 |
+
<div class="callout callout-success scroll-animate">
|
| 980 |
+
<div class="callout-icon">[v]</div>
|
| 981 |
+
<div class="callout-content">
|
| 982 |
+
<div class="callout-title">Cas d'usage : Dataset Titanic</div>
|
| 983 |
+
<div class="callout-text">
|
| 984 |
+
Predire la survie des passagers du Titanic a partir de leur age, sexe,
|
| 985 |
+
classe de billet, etc. Un classique du ML pour debuter !
|
| 986 |
+
</div>
|
| 987 |
+
</div>
|
| 988 |
+
</div>
|
| 989 |
+
</div>
|
| 990 |
+
</section>
|
| 991 |
+
|
| 992 |
+
<!-- Section 4: Random Forest -->
|
| 993 |
+
<section class="section" id="randomforest">
|
| 994 |
+
<div class="section-header scroll-animate">
|
| 995 |
+
<div class="section-badge">Partie 4 · 30 min</div>
|
| 996 |
+
<h2 class="section-title">
|
| 997 |
+
<small>Ensemble Learning</small>
|
| 998 |
+
Random Forest
|
| 999 |
+
</h2>
|
| 1000 |
+
</div>
|
| 1001 |
+
|
| 1002 |
+
<div class="section-content scroll-animate">
|
| 1003 |
+
<p>
|
| 1004 |
+
<strong>Random Forest</strong> est un ensemble d'arbres de decision qui votent pour predire.
|
| 1005 |
+
C'est l'un des algorithmes les plus populaires en ML applique : performant, robuste,
|
| 1006 |
+
peu sensible au tuning.
|
| 1007 |
+
</p>
|
| 1008 |
+
|
| 1009 |
+
<h3 style="font-size: 1.2rem; font-weight: 600; color: var(--text-primary); margin: var(--space-xl) 0 var(--space-md);">
|
| 1010 |
+
Algorithm : Bagging + Random Splits
|
| 1011 |
+
</h3>
|
| 1012 |
+
|
| 1013 |
+
<div class="pipeline scroll-animate">
|
| 1014 |
+
<div class="pipeline-step">
|
| 1015 |
+
<div class="pipeline-num">1</div>
|
| 1016 |
+
<div class="pipeline-label">Bootstrap</div>
|
| 1017 |
+
<div class="pipeline-desc">Echantillons aleatoires</div>
|
| 1018 |
+
</div>
|
| 1019 |
+
<div class="pipeline-step">
|
| 1020 |
+
<div class="pipeline-num">2</div>
|
| 1021 |
+
<div class="pipeline-label">Splits</div>
|
| 1022 |
+
<div class="pipeline-desc">Features aleatoires</div>
|
| 1023 |
+
</div>
|
| 1024 |
+
<div class="pipeline-step">
|
| 1025 |
+
<div class="pipeline-num">3</div>
|
| 1026 |
+
<div class="pipeline-label">Arbres</div>
|
| 1027 |
+
<div class="pipeline-desc">N arbres independants</div>
|
| 1028 |
+
</div>
|
| 1029 |
+
<div class="pipeline-step">
|
| 1030 |
+
<div class="pipeline-num">4</div>
|
| 1031 |
+
<div class="pipeline-label">Vote</div>
|
| 1032 |
+
<div class="pipeline-desc">Moyenne ou mode</div>
|
| 1033 |
+
</div>
|
| 1034 |
+
</div>
|
| 1035 |
+
|
| 1036 |
+
<div class="metric-row scroll-animate">
|
| 1037 |
+
<div class="metric-card">
|
| 1038 |
+
<div class="metric-name">n_estimators</div>
|
| 1039 |
+
<div class="metric-formula">100 - 500</div>
|
| 1040 |
+
<div class="metric-desc">Nombre d'arbres</div>
|
| 1041 |
+
</div>
|
| 1042 |
+
<div class="metric-card">
|
| 1043 |
+
<div class="metric-name">max_depth</div>
|
| 1044 |
+
<div class="metric-formula">10 - 30</div>
|
| 1045 |
+
<div class="metric-desc">Profondeur max</div>
|
| 1046 |
+
</div>
|
| 1047 |
+
<div class="metric-card">
|
| 1048 |
+
<div class="metric-name">min_samples_split</div>
|
| 1049 |
+
<div class="metric-formula">2 - 10</div>
|
| 1050 |
+
<div class="metric-desc">Min pour splitter</div>
|
| 1051 |
+
</div>
|
| 1052 |
+
</div>
|
| 1053 |
+
|
| 1054 |
+
<div class="callout callout-success scroll-animate">
|
| 1055 |
+
<div class="callout-icon">[*]</div>
|
| 1056 |
+
<div class="callout-content">
|
| 1057 |
+
<div class="callout-title">Feature Importance</div>
|
| 1058 |
+
<div class="callout-text">
|
| 1059 |
+
Random Forest fournit automatiquement l'importance de chaque feature,
|
| 1060 |
+
ce qui aide a comprendre quelles variables influencent le plus les predictions.
|
| 1061 |
+
</div>
|
| 1062 |
+
</div>
|
| 1063 |
+
</div>
|
| 1064 |
+
</div>
|
| 1065 |
+
</section>
|
| 1066 |
+
|
| 1067 |
+
<!-- Section 5: Neural Networks -->
|
| 1068 |
+
<section class="section" id="neuralnets">
|
| 1069 |
+
<div class="section-header scroll-animate">
|
| 1070 |
+
<div class="section-badge">Partie 5 · 35 min</div>
|
| 1071 |
+
<h2 class="section-title">
|
| 1072 |
+
<small>Deep Learning</small>
|
| 1073 |
+
Reseaux de Neurones
|
| 1074 |
+
</h2>
|
| 1075 |
+
</div>
|
| 1076 |
+
|
| 1077 |
+
<div class="section-content scroll-animate">
|
| 1078 |
+
<p>
|
| 1079 |
+
Les <strong>reseaux de neurones</strong> sont inspires du cerveau humain : des couches de neurones
|
| 1080 |
+
interconnectes executent des transformations non-lineaires. Ils excellent pour les patterns complexes.
|
| 1081 |
+
</p>
|
| 1082 |
+
|
| 1083 |
+
<h3 style="font-size: 1.2rem; font-weight: 600; color: var(--text-primary); margin: var(--space-xl) 0 var(--space-md);">
|
| 1084 |
+
Fonctionnement : Forward + Backprop
|
| 1085 |
+
</h3>
|
| 1086 |
+
|
| 1087 |
+
<div class="cards-grid scroll-animate">
|
| 1088 |
+
<div class="info-card">
|
| 1089 |
+
<div class="info-card-icon">F</div>
|
| 1090 |
+
<h4 class="info-card-title">Forward Pass</h4>
|
| 1091 |
+
<p class="info-card-text">Donnees traversent les couches : $\mathbf{h}_1 = \sigma(W_1 \mathbf{x} + b_1)$</p>
|
| 1092 |
+
</div>
|
| 1093 |
+
<div class="info-card">
|
| 1094 |
+
<div class="info-card-icon">L</div>
|
| 1095 |
+
<h4 class="info-card-title">Loss Computation</h4>
|
| 1096 |
+
<p class="info-card-text">Compare prediction vs realite : $L = \frac{1}{m} \sum (y - \hat{y})^2$</p>
|
| 1097 |
+
</div>
|
| 1098 |
+
<div class="info-card">
|
| 1099 |
+
<div class="info-card-icon">B</div>
|
| 1100 |
+
<h4 class="info-card-title">Backpropagation</h4>
|
| 1101 |
+
<p class="info-card-text">Calcule les gradients via la chaine de derivation</p>
|
| 1102 |
+
</div>
|
| 1103 |
+
<div class="info-card">
|
| 1104 |
+
<div class="info-card-icon">G</div>
|
| 1105 |
+
<h4 class="info-card-title">Gradient Descent</h4>
|
| 1106 |
+
<p class="info-card-text">Met a jour les poids : $W \leftarrow W - \alpha \nabla_W L$</p>
|
| 1107 |
+
</div>
|
| 1108 |
+
</div>
|
| 1109 |
+
|
| 1110 |
+
<h3 style="font-size: 1.2rem; font-weight: 600; color: var(--text-primary); margin: var(--space-xl) 0 var(--space-md);">
|
| 1111 |
+
Fonctions d'activation
|
| 1112 |
+
</h3>
|
| 1113 |
+
|
| 1114 |
+
<div class="metric-row scroll-animate">
|
| 1115 |
+
<div class="metric-card">
|
| 1116 |
+
<div class="metric-name">ReLU</div>
|
| 1117 |
+
<div class="metric-formula">$f(x) = \max(0, x)$</div>
|
| 1118 |
+
<div class="metric-desc">Couches cachees</div>
|
| 1119 |
+
</div>
|
| 1120 |
+
<div class="metric-card">
|
| 1121 |
+
<div class="metric-name">Sigmoid</div>
|
| 1122 |
+
<div class="metric-formula">$f(x) = \frac{1}{1 + e^{-x}}$</div>
|
| 1123 |
+
<div class="metric-desc">Classification binaire</div>
|
| 1124 |
+
</div>
|
| 1125 |
+
<div class="metric-card">
|
| 1126 |
+
<div class="metric-name">Softmax</div>
|
| 1127 |
+
<div class="metric-formula">$f(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}}$</div>
|
| 1128 |
+
<div class="metric-desc">Classification multi-classe</div>
|
| 1129 |
+
</div>
|
| 1130 |
+
</div>
|
| 1131 |
+
</div>
|
| 1132 |
+
</section>
|
| 1133 |
+
|
| 1134 |
+
<!-- Section 6: LSTM -->
|
| 1135 |
+
<section class="section" id="lstm">
|
| 1136 |
+
<div class="section-header scroll-animate">
|
| 1137 |
+
<div class="section-badge">Partie 6 · 30 min</div>
|
| 1138 |
+
<h2 class="section-title">
|
| 1139 |
+
<small>Series Temporelles</small>
|
| 1140 |
+
LSTM & Reseaux Recurrents
|
| 1141 |
+
</h2>
|
| 1142 |
+
</div>
|
| 1143 |
+
|
| 1144 |
+
<div class="section-content scroll-animate">
|
| 1145 |
+
<p>
|
| 1146 |
+
<strong>LSTM (Long Short-Term Memory)</strong> est un type de reseau neuronal pour series temporelles.
|
| 1147 |
+
Il peut "retenir" l'information sur de longues periodes — crucial pour les predictions temporelles.
|
| 1148 |
+
</p>
|
| 1149 |
+
|
| 1150 |
+
<div class="callout callout-warning scroll-animate">
|
| 1151 |
+
<div class="callout-icon">[!]</div>
|
| 1152 |
+
<div class="callout-content">
|
| 1153 |
+
<div class="callout-title">Probleme des RNN vanilla</div>
|
| 1154 |
+
<div class="callout-text">
|
| 1155 |
+
Les gradients disparaissent (vanishing) ou explosent (exploding) sur de longues sequences.
|
| 1156 |
+
Le LSTM resout ce probleme avec son <strong>cell state</strong>.
|
| 1157 |
+
</div>
|
| 1158 |
+
</div>
|
| 1159 |
+
</div>
|
| 1160 |
+
|
| 1161 |
+
<h3 style="font-size: 1.2rem; font-weight: 600; color: var(--text-primary); margin: var(--space-xl) 0 var(--space-md);">
|
| 1162 |
+
Les trois portes du LSTM
|
| 1163 |
+
</h3>
|
| 1164 |
+
|
| 1165 |
+
<div class="metric-row scroll-animate">
|
| 1166 |
+
<div class="metric-card">
|
| 1167 |
+
<div class="metric-name">Forget Gate</div>
|
| 1168 |
+
<div class="metric-formula">$f_t = \sigma(W_f [h_{t-1}, x_t] + b_f)$</div>
|
| 1169 |
+
<div class="metric-desc">Quoi oublier ?</div>
|
| 1170 |
+
</div>
|
| 1171 |
+
<div class="metric-card">
|
| 1172 |
+
<div class="metric-name">Input Gate</div>
|
| 1173 |
+
<div class="metric-formula">$i_t = \sigma(W_i [h_{t-1}, x_t] + b_i)$</div>
|
| 1174 |
+
<div class="metric-desc">Quoi ajouter ?</div>
|
| 1175 |
+
</div>
|
| 1176 |
+
<div class="metric-card">
|
| 1177 |
+
<div class="metric-name">Output Gate</div>
|
| 1178 |
+
<div class="metric-formula">$o_t = \sigma(W_o [h_{t-1}, x_t] + b_o)$</div>
|
| 1179 |
+
<div class="metric-desc">Quoi exposer ?</div>
|
| 1180 |
+
</div>
|
| 1181 |
+
</div>
|
| 1182 |
+
|
| 1183 |
+
<div class="callout callout-info scroll-animate">
|
| 1184 |
+
<div class="callout-icon">[i]</div>
|
| 1185 |
+
<div class="callout-content">
|
| 1186 |
+
<div class="callout-title">Cas d'usage</div>
|
| 1187 |
+
<div class="callout-text">
|
| 1188 |
+
Prediction de prix boursiers, meteo, consommation energetique,
|
| 1189 |
+
traitement du langage naturel (NLP)...
|
| 1190 |
+
</div>
|
| 1191 |
+
</div>
|
| 1192 |
+
</div>
|
| 1193 |
+
</div>
|
| 1194 |
+
</section>
|
| 1195 |
+
|
| 1196 |
+
<!-- Section 7: Metriques -->
|
| 1197 |
+
<section class="section" id="metrics">
|
| 1198 |
+
<div class="section-header scroll-animate">
|
| 1199 |
+
<div class="section-badge">Partie 7 · 25 min</div>
|
| 1200 |
+
<h2 class="section-title">
|
| 1201 |
+
<small>Evaluation</small>
|
| 1202 |
+
Metriques de Performance
|
| 1203 |
+
</h2>
|
| 1204 |
+
</div>
|
| 1205 |
+
|
| 1206 |
+
<div class="section-content scroll-animate">
|
| 1207 |
+
<p>
|
| 1208 |
+
Evaluer correctement un modele est crucial. Les bonnes metriques dependent du type de probleme
|
| 1209 |
+
(regression vs classification) et des objectifs metier.
|
| 1210 |
+
</p>
|
| 1211 |
+
|
| 1212 |
+
<h3 style="font-size: 1.2rem; font-weight: 600; color: var(--text-primary); margin: var(--space-xl) 0 var(--space-md);">
|
| 1213 |
+
Regression
|
| 1214 |
+
</h3>
|
| 1215 |
+
|
| 1216 |
+
<div class="metric-row scroll-animate">
|
| 1217 |
+
<div class="metric-card">
|
| 1218 |
+
<div class="metric-name">MAE</div>
|
| 1219 |
+
<div class="metric-formula">$\frac{1}{n}\sum|y_i - \hat{y}_i|$</div>
|
| 1220 |
+
<div class="metric-desc">Robuste aux outliers</div>
|
| 1221 |
+
</div>
|
| 1222 |
+
<div class="metric-card">
|
| 1223 |
+
<div class="metric-name">RMSE</div>
|
| 1224 |
+
<div class="metric-formula">$\sqrt{\frac{1}{n}\sum(y_i - \hat{y}_i)^2}$</div>
|
| 1225 |
+
<div class="metric-desc">Penalise les grandes erreurs</div>
|
| 1226 |
+
</div>
|
| 1227 |
+
<div class="metric-card">
|
| 1228 |
+
<div class="metric-name">R2</div>
|
| 1229 |
+
<div class="metric-formula">$1 - \frac{SS_{res}}{SS_{tot}}$</div>
|
| 1230 |
+
<div class="metric-desc">% variance expliquee</div>
|
| 1231 |
+
</div>
|
| 1232 |
+
</div>
|
| 1233 |
+
|
| 1234 |
+
<h3 style="font-size: 1.2rem; font-weight: 600; color: var(--text-primary); margin: var(--space-xl) 0 var(--space-md);">
|
| 1235 |
+
Classification
|
| 1236 |
+
</h3>
|
| 1237 |
+
|
| 1238 |
+
<div class="table-container scroll-animate">
|
| 1239 |
+
<table>
|
| 1240 |
+
<thead>
|
| 1241 |
+
<tr>
|
| 1242 |
+
<th>Metrique</th>
|
| 1243 |
+
<th>Formule</th>
|
| 1244 |
+
<th>Usage</th>
|
| 1245 |
+
</tr>
|
| 1246 |
+
</thead>
|
| 1247 |
+
<tbody>
|
| 1248 |
+
<tr>
|
| 1249 |
+
<td><strong>Accuracy</strong></td>
|
| 1250 |
+
<td>$(TP + TN) / Total$</td>
|
| 1251 |
+
<td>Classes equilibrees</td>
|
| 1252 |
+
</tr>
|
| 1253 |
+
<tr>
|
| 1254 |
+
<td><strong>Precision</strong></td>
|
| 1255 |
+
<td>$TP / (TP + FP)$</td>
|
| 1256 |
+
<td>Minimiser faux positifs</td>
|
| 1257 |
+
</tr>
|
| 1258 |
+
<tr>
|
| 1259 |
+
<td><strong>Recall</strong></td>
|
| 1260 |
+
<td>$TP / (TP + FN)$</td>
|
| 1261 |
+
<td>Minimiser faux negatifs</td>
|
| 1262 |
+
</tr>
|
| 1263 |
+
<tr>
|
| 1264 |
+
<td><strong>F1-Score</strong></td>
|
| 1265 |
+
<td>$2 \cdot \frac{P \cdot R}{P + R}$</td>
|
| 1266 |
+
<td>Classes desequilibrees</td>
|
| 1267 |
+
</tr>
|
| 1268 |
+
</tbody>
|
| 1269 |
+
</table>
|
| 1270 |
+
</div>
|
| 1271 |
+
</div>
|
| 1272 |
+
</section>
|
| 1273 |
+
|
| 1274 |
+
<!-- Section 8: Optimisation -->
|
| 1275 |
+
<section class="section" id="optimization">
|
| 1276 |
+
<div class="section-header scroll-animate">
|
| 1277 |
+
<div class="section-badge">Partie 8 · 20 min</div>
|
| 1278 |
+
<h2 class="section-title">
|
| 1279 |
+
<small>Amelioration</small>
|
| 1280 |
+
Optimisation & Regularisation
|
| 1281 |
+
</h2>
|
| 1282 |
+
</div>
|
| 1283 |
+
|
| 1284 |
+
<div class="section-content scroll-animate">
|
| 1285 |
+
<p>
|
| 1286 |
+
Pour eviter le <strong>surapprentissage (overfitting)</strong> et ameliorer la generalisation,
|
| 1287 |
+
plusieurs techniques existent.
|
| 1288 |
+
</p>
|
| 1289 |
+
|
| 1290 |
+
<div class="cards-grid scroll-animate">
|
| 1291 |
+
<div class="info-card">
|
| 1292 |
+
<div class="info-card-icon">D</div>
|
| 1293 |
+
<h4 class="info-card-title">Dropout</h4>
|
| 1294 |
+
<p class="info-card-text">Desactive aleatoirement des neurones pendant l'entrainement.</p>
|
| 1295 |
+
</div>
|
| 1296 |
+
<div class="info-card">
|
| 1297 |
+
<div class="info-card-icon">E</div>
|
| 1298 |
+
<h4 class="info-card-title">Early Stopping</h4>
|
| 1299 |
+
<p class="info-card-text">Arrete l'entrainement quand la validation stagne.</p>
|
| 1300 |
+
</div>
|
| 1301 |
+
<div class="info-card">
|
| 1302 |
+
<div class="info-card-icon">L</div>
|
| 1303 |
+
<h4 class="info-card-title">L2 Regularization</h4>
|
| 1304 |
+
<p class="info-card-text">Penalise les grands poids : $L_{total} = L_{data} + \lambda \sum w^2$</p>
|
| 1305 |
+
</div>
|
| 1306 |
+
<div class="info-card">
|
| 1307 |
+
<div class="info-card-icon">C</div>
|
| 1308 |
+
<h4 class="info-card-title">Cross-Validation</h4>
|
| 1309 |
+
<p class="info-card-text">K-fold pour une evaluation plus robuste.</p>
|
| 1310 |
+
</div>
|
| 1311 |
+
</div>
|
| 1312 |
+
|
| 1313 |
+
<div class="callout callout-tip scroll-animate">
|
| 1314 |
+
<div class="callout-icon">[*]</div>
|
| 1315 |
+
<div class="callout-content">
|
| 1316 |
+
<div class="callout-title">Regle d'or</div>
|
| 1317 |
+
<div class="callout-text">
|
| 1318 |
+
Toujours comparer les metriques sur <strong>train</strong> ET <strong>test</strong>.
|
| 1319 |
+
Un grand ecart = overfitting. Objectif : R2 train ≈ R2 test.
|
| 1320 |
+
</div>
|
| 1321 |
+
</div>
|
| 1322 |
+
</div>
|
| 1323 |
+
</div>
|
| 1324 |
+
</section>
|
| 1325 |
+
|
| 1326 |
+
<!-- Author Footer -->
|
| 1327 |
+
<footer class="author-footer" style="margin-top: var(--space-3xl);">
|
| 1328 |
+
<div class="author-info">
|
| 1329 |
+
<a href="mailto:imadmaalouf02@gmail.com" class="author-link">
|
| 1330 |
+
<svg viewBox="0 0 24 24"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>
|
| 1331 |
+
imadmaalouf02@gmail.com
|
| 1332 |
+
</a>
|
| 1333 |
+
<a href="https://github.com/imadmaalouf02" target="_blank" class="author-link">
|
| 1334 |
+
<svg viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
| 1335 |
+
GitHub
|
| 1336 |
+
</a>
|
| 1337 |
+
<a href="https://huggingface.co/spaces/MAALOOUF/ML_Training" target="_blank" class="author-link">
|
| 1338 |
+
<svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
|
| 1339 |
+
Hugging Face Space
|
| 1340 |
+
</a>
|
| 1341 |
+
</div>
|
| 1342 |
+
</footer>
|
| 1343 |
+
|
| 1344 |
+
<!-- Footer -->
|
| 1345 |
+
<footer class="footer" style="margin-top: 0;">
|
| 1346 |
+
<p class="footer-text">
|
| 1347 |
+
ML Academy — Cours de Machine Learning —
|
| 1348 |
+
<span class="footer-brand">GE-MCI 4A</span> — 2025/2026
|
| 1349 |
+
</p>
|
| 1350 |
+
<p class="footer-text" style="margin-top: var(--space-sm); font-size: 0.75rem; color: var(--text-muted);">
|
| 1351 |
+
Formateur : Imad Maalouf
|
| 1352 |
+
</p>
|
| 1353 |
+
</footer>
|
| 1354 |
+
</main>
|
| 1355 |
+
</div>
|
| 1356 |
+
|
| 1357 |
+
<!-- Back to Top -->
|
| 1358 |
+
<button class="back-to-top" id="backToTop" onclick="scrollToTop()">^</button>
|
| 1359 |
+
|
| 1360 |
+
<!-- Scripts -->
|
| 1361 |
+
<script src="js/shared.js"></script>
|
| 1362 |
+
<script>
|
| 1363 |
+
// Scroll animations
|
| 1364 |
+
const observerOptions = {
|
| 1365 |
+
threshold: 0.1,
|
| 1366 |
+
rootMargin: '0px 0px -50px 0px'
|
| 1367 |
+
};
|
| 1368 |
+
|
| 1369 |
+
const observer = new IntersectionObserver((entries) => {
|
| 1370 |
+
entries.forEach(entry => {
|
| 1371 |
+
if (entry.isIntersecting) {
|
| 1372 |
+
entry.target.classList.add('visible');
|
| 1373 |
+
}
|
| 1374 |
+
});
|
| 1375 |
+
}, observerOptions);
|
| 1376 |
+
|
| 1377 |
+
document.querySelectorAll('.scroll-animate').forEach(el => {
|
| 1378 |
+
observer.observe(el);
|
| 1379 |
+
});
|
| 1380 |
+
|
| 1381 |
+
// Active nav item on scroll
|
| 1382 |
+
const sections = document.querySelectorAll('.section');
|
| 1383 |
+
const navItems = document.querySelectorAll('.nav-item');
|
| 1384 |
+
|
| 1385 |
+
window.addEventListener('scroll', () => {
|
| 1386 |
+
let current = '';
|
| 1387 |
+
sections.forEach(section => {
|
| 1388 |
+
const sectionTop = section.offsetTop;
|
| 1389 |
+
const sectionHeight = section.clientHeight;
|
| 1390 |
+
if (scrollY >= sectionTop - 200) {
|
| 1391 |
+
current = section.getAttribute('id');
|
| 1392 |
+
}
|
| 1393 |
+
});
|
| 1394 |
+
|
| 1395 |
+
navItems.forEach(item => {
|
| 1396 |
+
item.classList.remove('active');
|
| 1397 |
+
if (item.getAttribute('href') === `#${current}`) {
|
| 1398 |
+
item.classList.add('active');
|
| 1399 |
+
}
|
| 1400 |
+
});
|
| 1401 |
+
|
| 1402 |
+
// Update progress
|
| 1403 |
+
const progress = Math.min(100, Math.round((scrollY / (document.body.scrollHeight - window.innerHeight)) * 100));
|
| 1404 |
+
document.getElementById('progress-fill').style.width = `${progress}%`;
|
| 1405 |
+
document.getElementById('progress-text').textContent = `${progress}%`;
|
| 1406 |
+
|
| 1407 |
+
// Back to top button
|
| 1408 |
+
const backToTop = document.getElementById('backToTop');
|
| 1409 |
+
if (scrollY > 500) {
|
| 1410 |
+
backToTop.classList.add('visible');
|
| 1411 |
+
} else {
|
| 1412 |
+
backToTop.classList.remove('visible');
|
| 1413 |
+
}
|
| 1414 |
+
});
|
| 1415 |
+
|
| 1416 |
+
function scrollToTop() {
|
| 1417 |
+
window.scrollTo({ top: 0, behavior: 'smooth' });
|
| 1418 |
+
}
|
| 1419 |
+
</script>
|
| 1420 |
+
</body>
|
| 1421 |
+
</html>
|
cours.pdf
ADDED
|
Binary file (14.2 kB). View file
|
|
|
css/shared.css
ADDED
|
@@ -0,0 +1,944 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 2 |
+
ML PLATFORM — SHARED STYLES
|
| 3 |
+
Formation Machine Learning Professionnelle
|
| 4 |
+
Design: Dark Modern avec animations CSS
|
| 5 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 6 |
+
|
| 7 |
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');
|
| 8 |
+
|
| 9 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 10 |
+
VARIABLES CSS
|
| 11 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 12 |
+
:root {
|
| 13 |
+
/* Couleurs principales */
|
| 14 |
+
--primary: #6366f1;
|
| 15 |
+
--primary-light: #818cf8;
|
| 16 |
+
--primary-dark: #4f46e5;
|
| 17 |
+
--secondary: #06b6d4;
|
| 18 |
+
--accent: #f59e0b;
|
| 19 |
+
--success: #10b981;
|
| 20 |
+
--warning: #f97316;
|
| 21 |
+
--danger: #ef4444;
|
| 22 |
+
|
| 23 |
+
/* Couleurs de fond */
|
| 24 |
+
--bg-primary: #0f0f1a;
|
| 25 |
+
--bg-secondary: #1a1a2e;
|
| 26 |
+
--bg-tertiary: #252542;
|
| 27 |
+
--bg-card: #16162a;
|
| 28 |
+
--bg-hover: #1e1e3a;
|
| 29 |
+
|
| 30 |
+
/* Couleurs de texte */
|
| 31 |
+
--text-primary: #f8fafc;
|
| 32 |
+
--text-secondary: #94a3b8;
|
| 33 |
+
--text-muted: #64748b;
|
| 34 |
+
--text-accent: #818cf8;
|
| 35 |
+
|
| 36 |
+
/* Bordures */
|
| 37 |
+
--border-color: #2d2d4a;
|
| 38 |
+
--border-light: #3d3d5c;
|
| 39 |
+
|
| 40 |
+
/* Ombres */
|
| 41 |
+
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
|
| 42 |
+
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
|
| 43 |
+
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.3);
|
| 44 |
+
--shadow-glow: 0 0 20px rgba(99, 102, 241, 0.3);
|
| 45 |
+
--shadow-glow-strong: 0 0 40px rgba(99, 102, 241, 0.5);
|
| 46 |
+
|
| 47 |
+
/* Rayons */
|
| 48 |
+
--radius-sm: 6px;
|
| 49 |
+
--radius-md: 10px;
|
| 50 |
+
--radius-lg: 16px;
|
| 51 |
+
--radius-xl: 24px;
|
| 52 |
+
|
| 53 |
+
/* Transitions */
|
| 54 |
+
--transition-fast: 0.15s ease;
|
| 55 |
+
--transition-base: 0.25s ease;
|
| 56 |
+
--transition-slow: 0.4s ease;
|
| 57 |
+
|
| 58 |
+
/* Espacements */
|
| 59 |
+
--space-xs: 0.25rem;
|
| 60 |
+
--space-sm: 0.5rem;
|
| 61 |
+
--space-md: 1rem;
|
| 62 |
+
--space-lg: 1.5rem;
|
| 63 |
+
--space-xl: 2rem;
|
| 64 |
+
--space-2xl: 3rem;
|
| 65 |
+
--space-3xl: 4rem;
|
| 66 |
+
|
| 67 |
+
/* Sidebar */
|
| 68 |
+
--sidebar-width: 280px;
|
| 69 |
+
--navbar-height: 64px;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 73 |
+
RESET & BASE
|
| 74 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 75 |
+
*, *::before, *::after {
|
| 76 |
+
box-sizing: border-box;
|
| 77 |
+
margin: 0;
|
| 78 |
+
padding: 0;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
html {
|
| 82 |
+
scroll-behavior: smooth;
|
| 83 |
+
font-size: 16px;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
body {
|
| 87 |
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
| 88 |
+
background: var(--bg-primary);
|
| 89 |
+
color: var(--text-primary);
|
| 90 |
+
line-height: 1.6;
|
| 91 |
+
min-height: 100vh;
|
| 92 |
+
overflow-x: hidden;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 96 |
+
ANIMATIONS KEYFRAMES
|
| 97 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 98 |
+
@keyframes fadeIn {
|
| 99 |
+
from { opacity: 0; }
|
| 100 |
+
to { opacity: 1; }
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
@keyframes fadeInUp {
|
| 104 |
+
from {
|
| 105 |
+
opacity: 0;
|
| 106 |
+
transform: translateY(30px);
|
| 107 |
+
}
|
| 108 |
+
to {
|
| 109 |
+
opacity: 1;
|
| 110 |
+
transform: translateY(0);
|
| 111 |
+
}
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
@keyframes fadeInDown {
|
| 115 |
+
from {
|
| 116 |
+
opacity: 0;
|
| 117 |
+
transform: translateY(-20px);
|
| 118 |
+
}
|
| 119 |
+
to {
|
| 120 |
+
opacity: 1;
|
| 121 |
+
transform: translateY(0);
|
| 122 |
+
}
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
@keyframes fadeInLeft {
|
| 126 |
+
from {
|
| 127 |
+
opacity: 0;
|
| 128 |
+
transform: translateX(-30px);
|
| 129 |
+
}
|
| 130 |
+
to {
|
| 131 |
+
opacity: 1;
|
| 132 |
+
transform: translateX(0);
|
| 133 |
+
}
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
@keyframes fadeInRight {
|
| 137 |
+
from {
|
| 138 |
+
opacity: 0;
|
| 139 |
+
transform: translateX(30px);
|
| 140 |
+
}
|
| 141 |
+
to {
|
| 142 |
+
opacity: 1;
|
| 143 |
+
transform: translateX(0);
|
| 144 |
+
}
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
@keyframes scaleIn {
|
| 148 |
+
from {
|
| 149 |
+
opacity: 0;
|
| 150 |
+
transform: scale(0.9);
|
| 151 |
+
}
|
| 152 |
+
to {
|
| 153 |
+
opacity: 1;
|
| 154 |
+
transform: scale(1);
|
| 155 |
+
}
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
@keyframes slideInUp {
|
| 159 |
+
from {
|
| 160 |
+
transform: translateY(100%);
|
| 161 |
+
}
|
| 162 |
+
to {
|
| 163 |
+
transform: translateY(0);
|
| 164 |
+
}
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
@keyframes pulse {
|
| 168 |
+
0%, 100% {
|
| 169 |
+
opacity: 1;
|
| 170 |
+
transform: scale(1);
|
| 171 |
+
}
|
| 172 |
+
50% {
|
| 173 |
+
opacity: 0.7;
|
| 174 |
+
transform: scale(1.05);
|
| 175 |
+
}
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
@keyframes glow {
|
| 179 |
+
0%, 100% {
|
| 180 |
+
box-shadow: 0 0 5px var(--primary), 0 0 10px var(--primary), 0 0 15px var(--primary);
|
| 181 |
+
}
|
| 182 |
+
50% {
|
| 183 |
+
box-shadow: 0 0 10px var(--primary), 0 0 20px var(--primary), 0 0 30px var(--primary);
|
| 184 |
+
}
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
@keyframes shimmer {
|
| 188 |
+
0% { background-position: -200% 0; }
|
| 189 |
+
100% { background-position: 200% 0; }
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
@keyframes float {
|
| 193 |
+
0%, 100% { transform: translateY(0); }
|
| 194 |
+
50% { transform: translateY(-10px); }
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
@keyframes rotate {
|
| 198 |
+
from { transform: rotate(0deg); }
|
| 199 |
+
to { transform: rotate(360deg); }
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
@keyframes bounce {
|
| 203 |
+
0%, 100% { transform: translateY(0); }
|
| 204 |
+
50% { transform: translateY(-5px); }
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
@keyframes typing {
|
| 208 |
+
from { width: 0; }
|
| 209 |
+
to { width: 100%; }
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
@keyframes blink {
|
| 213 |
+
0%, 100% { opacity: 1; }
|
| 214 |
+
50% { opacity: 0; }
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
@keyframes gradientShift {
|
| 218 |
+
0% { background-position: 0% 50%; }
|
| 219 |
+
50% { background-position: 100% 50%; }
|
| 220 |
+
100% { background-position: 0% 50%; }
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
@keyframes particle {
|
| 224 |
+
0% {
|
| 225 |
+
transform: translateY(100vh) rotate(0deg);
|
| 226 |
+
opacity: 0;
|
| 227 |
+
}
|
| 228 |
+
10% { opacity: 1; }
|
| 229 |
+
90% { opacity: 1; }
|
| 230 |
+
100% {
|
| 231 |
+
transform: translateY(-100vh) rotate(720deg);
|
| 232 |
+
opacity: 0;
|
| 233 |
+
}
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
@keyframes wave {
|
| 237 |
+
0%, 100% { transform: translateY(0); }
|
| 238 |
+
25% { transform: translateY(-5px); }
|
| 239 |
+
75% { transform: translateY(5px); }
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
@keyframes progress {
|
| 243 |
+
from { width: 0; }
|
| 244 |
+
to { width: var(--progress, 100%); }
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 248 |
+
UTILITAIRES D'ANIMATION
|
| 249 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 250 |
+
.animate-fade-in { animation: fadeIn 0.6s ease forwards; }
|
| 251 |
+
.animate-fade-in-up { animation: fadeInUp 0.6s ease forwards; }
|
| 252 |
+
.animate-fade-in-down { animation: fadeInDown 0.5s ease forwards; }
|
| 253 |
+
.animate-fade-in-left { animation: fadeInLeft 0.5s ease forwards; }
|
| 254 |
+
.animate-fade-in-right { animation: fadeInRight 0.5s ease forwards; }
|
| 255 |
+
.animate-scale-in { animation: scaleIn 0.5s ease forwards; }
|
| 256 |
+
.animate-float { animation: float 3s ease-in-out infinite; }
|
| 257 |
+
.animate-pulse { animation: pulse 2s ease-in-out infinite; }
|
| 258 |
+
.animate-glow { animation: glow 2s ease-in-out infinite; }
|
| 259 |
+
.animate-bounce { animation: bounce 1s ease-in-out infinite; }
|
| 260 |
+
.animate-rotate { animation: rotate 2s linear infinite; }
|
| 261 |
+
|
| 262 |
+
/* Delays */
|
| 263 |
+
.delay-100 { animation-delay: 0.1s; }
|
| 264 |
+
.delay-200 { animation-delay: 0.2s; }
|
| 265 |
+
.delay-300 { animation-delay: 0.3s; }
|
| 266 |
+
.delay-400 { animation-delay: 0.4s; }
|
| 267 |
+
.delay-500 { animation-delay: 0.5s; }
|
| 268 |
+
.delay-600 { animation-delay: 0.6s; }
|
| 269 |
+
.delay-700 { animation-delay: 0.7s; }
|
| 270 |
+
.delay-800 { animation-delay: 0.8s; }
|
| 271 |
+
|
| 272 |
+
/* Initial states for scroll animations */
|
| 273 |
+
.scroll-animate {
|
| 274 |
+
opacity: 0;
|
| 275 |
+
transform: translateY(30px);
|
| 276 |
+
transition: opacity 0.6s ease, transform 0.6s ease;
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
.scroll-animate.visible {
|
| 280 |
+
opacity: 1;
|
| 281 |
+
transform: translateY(0);
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 285 |
+
NAVIGATION
|
| 286 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 287 |
+
.navbar {
|
| 288 |
+
position: fixed;
|
| 289 |
+
top: 0;
|
| 290 |
+
left: 0;
|
| 291 |
+
right: 0;
|
| 292 |
+
height: var(--navbar-height);
|
| 293 |
+
background: rgba(15, 15, 26, 0.85);
|
| 294 |
+
backdrop-filter: blur(20px);
|
| 295 |
+
border-bottom: 1px solid var(--border-color);
|
| 296 |
+
z-index: 1000;
|
| 297 |
+
display: flex;
|
| 298 |
+
align-items: center;
|
| 299 |
+
justify-content: space-between;
|
| 300 |
+
padding: 0 var(--space-xl);
|
| 301 |
+
animation: fadeInDown 0.5s ease;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
.navbar-brand {
|
| 305 |
+
display: flex;
|
| 306 |
+
align-items: center;
|
| 307 |
+
gap: var(--space-sm);
|
| 308 |
+
text-decoration: none;
|
| 309 |
+
color: var(--text-primary);
|
| 310 |
+
font-weight: 700;
|
| 311 |
+
font-size: 1.1rem;
|
| 312 |
+
transition: var(--transition-base);
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
.navbar-brand:hover {
|
| 316 |
+
color: var(--primary-light);
|
| 317 |
+
}
|
| 318 |
+
|
| 319 |
+
.brand-logo {
|
| 320 |
+
width: 36px;
|
| 321 |
+
height: 36px;
|
| 322 |
+
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
| 323 |
+
border-radius: var(--radius-md);
|
| 324 |
+
display: flex;
|
| 325 |
+
align-items: center;
|
| 326 |
+
justify-content: center;
|
| 327 |
+
font-size: 1.2rem;
|
| 328 |
+
animation: float 3s ease-in-out infinite;
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
.navbar-nav {
|
| 332 |
+
display: flex;
|
| 333 |
+
align-items: center;
|
| 334 |
+
gap: var(--space-xs);
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
.nav-link {
|
| 338 |
+
display: flex;
|
| 339 |
+
align-items: center;
|
| 340 |
+
gap: var(--space-sm);
|
| 341 |
+
padding: var(--space-sm) var(--space-md);
|
| 342 |
+
color: var(--text-secondary);
|
| 343 |
+
text-decoration: none;
|
| 344 |
+
font-size: 0.9rem;
|
| 345 |
+
font-weight: 500;
|
| 346 |
+
border-radius: var(--radius-md);
|
| 347 |
+
transition: all var(--transition-base);
|
| 348 |
+
position: relative;
|
| 349 |
+
overflow: hidden;
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
.nav-link::before {
|
| 353 |
+
content: '';
|
| 354 |
+
position: absolute;
|
| 355 |
+
bottom: 0;
|
| 356 |
+
left: 50%;
|
| 357 |
+
width: 0;
|
| 358 |
+
height: 2px;
|
| 359 |
+
background: linear-gradient(90deg, var(--primary), var(--secondary));
|
| 360 |
+
transition: all var(--transition-base);
|
| 361 |
+
transform: translateX(-50%);
|
| 362 |
+
}
|
| 363 |
+
|
| 364 |
+
.nav-link:hover {
|
| 365 |
+
color: var(--text-primary);
|
| 366 |
+
background: var(--bg-hover);
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
.nav-link:hover::before {
|
| 370 |
+
width: 60%;
|
| 371 |
+
}
|
| 372 |
+
|
| 373 |
+
.nav-link.active {
|
| 374 |
+
color: var(--primary-light);
|
| 375 |
+
background: rgba(99, 102, 241, 0.1);
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
.nav-link.active::before {
|
| 379 |
+
width: 60%;
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
.nav-badge {
|
| 383 |
+
display: flex;
|
| 384 |
+
align-items: center;
|
| 385 |
+
gap: var(--space-sm);
|
| 386 |
+
padding: var(--space-xs) var(--space-md);
|
| 387 |
+
background: rgba(16, 185, 129, 0.1);
|
| 388 |
+
border: 1px solid rgba(16, 185, 129, 0.3);
|
| 389 |
+
border-radius: 20px;
|
| 390 |
+
font-size: 0.75rem;
|
| 391 |
+
font-weight: 600;
|
| 392 |
+
color: var(--success);
|
| 393 |
+
font-family: 'JetBrains Mono', monospace;
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
.nav-badge .dot {
|
| 397 |
+
width: 6px;
|
| 398 |
+
height: 6px;
|
| 399 |
+
background: var(--success);
|
| 400 |
+
border-radius: 50%;
|
| 401 |
+
animation: pulse 2s ease-in-out infinite;
|
| 402 |
+
}
|
| 403 |
+
|
| 404 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 405 |
+
BOUTONS
|
| 406 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 407 |
+
.btn {
|
| 408 |
+
display: inline-flex;
|
| 409 |
+
align-items: center;
|
| 410 |
+
justify-content: center;
|
| 411 |
+
gap: var(--space-sm);
|
| 412 |
+
padding: var(--space-sm) var(--space-lg);
|
| 413 |
+
font-family: 'Inter', sans-serif;
|
| 414 |
+
font-size: 0.9rem;
|
| 415 |
+
font-weight: 600;
|
| 416 |
+
text-decoration: none;
|
| 417 |
+
border: none;
|
| 418 |
+
border-radius: var(--radius-md);
|
| 419 |
+
cursor: pointer;
|
| 420 |
+
transition: all var(--transition-base);
|
| 421 |
+
position: relative;
|
| 422 |
+
overflow: hidden;
|
| 423 |
+
}
|
| 424 |
+
|
| 425 |
+
.btn::before {
|
| 426 |
+
content: '';
|
| 427 |
+
position: absolute;
|
| 428 |
+
top: 50%;
|
| 429 |
+
left: 50%;
|
| 430 |
+
width: 0;
|
| 431 |
+
height: 0;
|
| 432 |
+
background: rgba(255, 255, 255, 0.1);
|
| 433 |
+
border-radius: 50%;
|
| 434 |
+
transform: translate(-50%, -50%);
|
| 435 |
+
transition: width 0.4s ease, height 0.4s ease;
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
.btn:hover::before {
|
| 439 |
+
width: 200%;
|
| 440 |
+
height: 200%;
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
.btn-primary {
|
| 444 |
+
background: linear-gradient(135deg, var(--primary), var(--primary-dark));
|
| 445 |
+
color: white;
|
| 446 |
+
box-shadow: 0 4px 15px rgba(99, 102, 241, 0.4);
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
.btn-primary:hover {
|
| 450 |
+
transform: translateY(-2px);
|
| 451 |
+
box-shadow: 0 6px 25px rgba(99, 102, 241, 0.5);
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
.btn-secondary {
|
| 455 |
+
background: var(--bg-tertiary);
|
| 456 |
+
color: var(--text-primary);
|
| 457 |
+
border: 1px solid var(--border-color);
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
.btn-secondary:hover {
|
| 461 |
+
background: var(--bg-hover);
|
| 462 |
+
border-color: var(--border-light);
|
| 463 |
+
transform: translateY(-2px);
|
| 464 |
+
}
|
| 465 |
+
|
| 466 |
+
.btn-outline {
|
| 467 |
+
background: transparent;
|
| 468 |
+
color: var(--primary-light);
|
| 469 |
+
border: 1px solid var(--primary);
|
| 470 |
+
}
|
| 471 |
+
|
| 472 |
+
.btn-outline:hover {
|
| 473 |
+
background: rgba(99, 102, 241, 0.1);
|
| 474 |
+
transform: translateY(-2px);
|
| 475 |
+
}
|
| 476 |
+
|
| 477 |
+
.btn-success {
|
| 478 |
+
background: linear-gradient(135deg, var(--success), #059669);
|
| 479 |
+
color: white;
|
| 480 |
+
box-shadow: 0 4px 15px rgba(16, 185, 129, 0.4);
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
.btn-success:hover {
|
| 484 |
+
transform: translateY(-2px);
|
| 485 |
+
box-shadow: 0 6px 25px rgba(16, 185, 129, 0.5);
|
| 486 |
+
}
|
| 487 |
+
|
| 488 |
+
.btn-lg {
|
| 489 |
+
padding: var(--space-md) var(--space-xl);
|
| 490 |
+
font-size: 1rem;
|
| 491 |
+
}
|
| 492 |
+
|
| 493 |
+
.btn-sm {
|
| 494 |
+
padding: var(--space-xs) var(--space-md);
|
| 495 |
+
font-size: 0.8rem;
|
| 496 |
+
}
|
| 497 |
+
|
| 498 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 499 |
+
BADGES
|
| 500 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 501 |
+
.badge {
|
| 502 |
+
display: inline-flex;
|
| 503 |
+
align-items: center;
|
| 504 |
+
gap: var(--space-xs);
|
| 505 |
+
padding: var(--space-xs) var(--space-sm);
|
| 506 |
+
font-size: 0.7rem;
|
| 507 |
+
font-weight: 600;
|
| 508 |
+
text-transform: uppercase;
|
| 509 |
+
letter-spacing: 0.5px;
|
| 510 |
+
border-radius: var(--radius-sm);
|
| 511 |
+
font-family: 'JetBrains Mono', monospace;
|
| 512 |
+
}
|
| 513 |
+
|
| 514 |
+
.badge-primary {
|
| 515 |
+
background: rgba(99, 102, 241, 0.15);
|
| 516 |
+
color: var(--primary-light);
|
| 517 |
+
border: 1px solid rgba(99, 102, 241, 0.3);
|
| 518 |
+
}
|
| 519 |
+
|
| 520 |
+
.badge-secondary {
|
| 521 |
+
background: rgba(6, 182, 212, 0.15);
|
| 522 |
+
color: var(--secondary);
|
| 523 |
+
border: 1px solid rgba(6, 182, 212, 0.3);
|
| 524 |
+
}
|
| 525 |
+
|
| 526 |
+
.badge-success {
|
| 527 |
+
background: rgba(16, 185, 129, 0.15);
|
| 528 |
+
color: var(--success);
|
| 529 |
+
border: 1px solid rgba(16, 185, 129, 0.3);
|
| 530 |
+
}
|
| 531 |
+
|
| 532 |
+
.badge-warning {
|
| 533 |
+
background: rgba(249, 115, 22, 0.15);
|
| 534 |
+
color: var(--warning);
|
| 535 |
+
border: 1px solid rgba(249, 115, 22, 0.3);
|
| 536 |
+
}
|
| 537 |
+
|
| 538 |
+
.badge-accent {
|
| 539 |
+
background: rgba(245, 158, 11, 0.15);
|
| 540 |
+
color: var(--accent);
|
| 541 |
+
border: 1px solid rgba(245, 158, 11, 0.3);
|
| 542 |
+
}
|
| 543 |
+
|
| 544 |
+
/* ════════════════════════════════════════════��══════════════════════════════
|
| 545 |
+
CARDS
|
| 546 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 547 |
+
.card {
|
| 548 |
+
background: var(--bg-card);
|
| 549 |
+
border: 1px solid var(--border-color);
|
| 550 |
+
border-radius: var(--radius-lg);
|
| 551 |
+
padding: var(--space-xl);
|
| 552 |
+
transition: all var(--transition-base);
|
| 553 |
+
position: relative;
|
| 554 |
+
overflow: hidden;
|
| 555 |
+
}
|
| 556 |
+
|
| 557 |
+
.card::before {
|
| 558 |
+
content: '';
|
| 559 |
+
position: absolute;
|
| 560 |
+
top: 0;
|
| 561 |
+
left: 0;
|
| 562 |
+
right: 0;
|
| 563 |
+
height: 3px;
|
| 564 |
+
background: linear-gradient(90deg, var(--primary), var(--secondary));
|
| 565 |
+
transform: scaleX(0);
|
| 566 |
+
transition: transform var(--transition-base);
|
| 567 |
+
}
|
| 568 |
+
|
| 569 |
+
.card:hover {
|
| 570 |
+
transform: translateY(-5px);
|
| 571 |
+
border-color: var(--border-light);
|
| 572 |
+
box-shadow: var(--shadow-lg), var(--shadow-glow);
|
| 573 |
+
}
|
| 574 |
+
|
| 575 |
+
.card:hover::before {
|
| 576 |
+
transform: scaleX(1);
|
| 577 |
+
}
|
| 578 |
+
|
| 579 |
+
.card-icon {
|
| 580 |
+
width: 50px;
|
| 581 |
+
height: 50px;
|
| 582 |
+
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
| 583 |
+
border-radius: var(--radius-md);
|
| 584 |
+
display: flex;
|
| 585 |
+
align-items: center;
|
| 586 |
+
justify-content: center;
|
| 587 |
+
font-size: 1.5rem;
|
| 588 |
+
margin-bottom: var(--space-md);
|
| 589 |
+
animation: float 3s ease-in-out infinite;
|
| 590 |
+
}
|
| 591 |
+
|
| 592 |
+
.card-title {
|
| 593 |
+
font-size: 1.1rem;
|
| 594 |
+
font-weight: 700;
|
| 595 |
+
color: var(--text-primary);
|
| 596 |
+
margin-bottom: var(--space-sm);
|
| 597 |
+
}
|
| 598 |
+
|
| 599 |
+
.card-text {
|
| 600 |
+
font-size: 0.9rem;
|
| 601 |
+
color: var(--text-secondary);
|
| 602 |
+
line-height: 1.6;
|
| 603 |
+
}
|
| 604 |
+
|
| 605 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 606 |
+
CALLOUTS / ALERTS
|
| 607 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 608 |
+
.callout {
|
| 609 |
+
display: flex;
|
| 610 |
+
gap: var(--space-md);
|
| 611 |
+
padding: var(--space-lg);
|
| 612 |
+
border-radius: var(--radius-md);
|
| 613 |
+
margin: var(--space-lg) 0;
|
| 614 |
+
animation: fadeInUp 0.5s ease;
|
| 615 |
+
}
|
| 616 |
+
|
| 617 |
+
.callout-icon {
|
| 618 |
+
font-size: 1.5rem;
|
| 619 |
+
flex-shrink: 0;
|
| 620 |
+
}
|
| 621 |
+
|
| 622 |
+
.callout-content {
|
| 623 |
+
flex: 1;
|
| 624 |
+
}
|
| 625 |
+
|
| 626 |
+
.callout-title {
|
| 627 |
+
font-weight: 600;
|
| 628 |
+
color: var(--text-primary);
|
| 629 |
+
margin-bottom: var(--space-xs);
|
| 630 |
+
}
|
| 631 |
+
|
| 632 |
+
.callout-text {
|
| 633 |
+
font-size: 0.9rem;
|
| 634 |
+
color: var(--text-secondary);
|
| 635 |
+
}
|
| 636 |
+
|
| 637 |
+
.callout-info {
|
| 638 |
+
background: rgba(99, 102, 241, 0.1);
|
| 639 |
+
border: 1px solid rgba(99, 102, 241, 0.3);
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
+
.callout-success {
|
| 643 |
+
background: rgba(16, 185, 129, 0.1);
|
| 644 |
+
border: 1px solid rgba(16, 185, 129, 0.3);
|
| 645 |
+
}
|
| 646 |
+
|
| 647 |
+
.callout-warning {
|
| 648 |
+
background: rgba(249, 115, 22, 0.1);
|
| 649 |
+
border: 1px solid rgba(249, 115, 22, 0.3);
|
| 650 |
+
}
|
| 651 |
+
|
| 652 |
+
.callout-tip {
|
| 653 |
+
background: rgba(245, 158, 11, 0.1);
|
| 654 |
+
border: 1px solid rgba(245, 158, 11, 0.3);
|
| 655 |
+
}
|
| 656 |
+
|
| 657 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 658 |
+
CODE BLOCKS
|
| 659 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 660 |
+
.code-block {
|
| 661 |
+
background: #0d0d15;
|
| 662 |
+
border: 1px solid var(--border-color);
|
| 663 |
+
border-radius: var(--radius-md);
|
| 664 |
+
overflow: hidden;
|
| 665 |
+
margin: var(--space-md) 0;
|
| 666 |
+
animation: fadeInUp 0.5s ease;
|
| 667 |
+
}
|
| 668 |
+
|
| 669 |
+
.code-header {
|
| 670 |
+
display: flex;
|
| 671 |
+
align-items: center;
|
| 672 |
+
justify-content: space-between;
|
| 673 |
+
padding: var(--space-sm) var(--space-md);
|
| 674 |
+
background: var(--bg-tertiary);
|
| 675 |
+
border-bottom: 1px solid var(--border-color);
|
| 676 |
+
}
|
| 677 |
+
|
| 678 |
+
.code-dots {
|
| 679 |
+
display: flex;
|
| 680 |
+
gap: 6px;
|
| 681 |
+
}
|
| 682 |
+
|
| 683 |
+
.code-dot {
|
| 684 |
+
width: 10px;
|
| 685 |
+
height: 10px;
|
| 686 |
+
border-radius: 50%;
|
| 687 |
+
}
|
| 688 |
+
|
| 689 |
+
.code-dot.red { background: #ff5f56; }
|
| 690 |
+
.code-dot.yellow { background: #ffbd2e; }
|
| 691 |
+
.code-dot.green { background: #27c93f; }
|
| 692 |
+
|
| 693 |
+
.code-lang {
|
| 694 |
+
font-family: 'JetBrains Mono', monospace;
|
| 695 |
+
font-size: 0.7rem;
|
| 696 |
+
color: var(--text-muted);
|
| 697 |
+
text-transform: uppercase;
|
| 698 |
+
letter-spacing: 1px;
|
| 699 |
+
}
|
| 700 |
+
|
| 701 |
+
.code-block pre {
|
| 702 |
+
padding: var(--space-md);
|
| 703 |
+
overflow-x: auto;
|
| 704 |
+
font-family: 'JetBrains Mono', monospace;
|
| 705 |
+
font-size: 0.85rem;
|
| 706 |
+
line-height: 1.7;
|
| 707 |
+
color: #cdd6f4;
|
| 708 |
+
margin: 0;
|
| 709 |
+
}
|
| 710 |
+
|
| 711 |
+
/* Syntax highlighting colors */
|
| 712 |
+
.code-keyword { color: #cba6f7; }
|
| 713 |
+
.code-function { color: #89b4fa; }
|
| 714 |
+
.code-string { color: #a6e3a1; }
|
| 715 |
+
.code-comment { color: #6c7086; font-style: italic; }
|
| 716 |
+
.code-number { color: #fab387; }
|
| 717 |
+
.code-class { color: #f38ba8; }
|
| 718 |
+
|
| 719 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 720 |
+
TABLES
|
| 721 |
+
════════════════════════════════���══════════════════════════════════════════ */
|
| 722 |
+
.table-container {
|
| 723 |
+
overflow-x: auto;
|
| 724 |
+
border-radius: var(--radius-md);
|
| 725 |
+
border: 1px solid var(--border-color);
|
| 726 |
+
margin: var(--space-lg) 0;
|
| 727 |
+
}
|
| 728 |
+
|
| 729 |
+
table {
|
| 730 |
+
width: 100%;
|
| 731 |
+
border-collapse: collapse;
|
| 732 |
+
font-size: 0.9rem;
|
| 733 |
+
}
|
| 734 |
+
|
| 735 |
+
th {
|
| 736 |
+
background: var(--bg-tertiary);
|
| 737 |
+
color: var(--text-secondary);
|
| 738 |
+
font-family: 'JetBrains Mono', monospace;
|
| 739 |
+
font-size: 0.75rem;
|
| 740 |
+
font-weight: 600;
|
| 741 |
+
text-transform: uppercase;
|
| 742 |
+
letter-spacing: 0.5px;
|
| 743 |
+
padding: var(--space-md);
|
| 744 |
+
text-align: left;
|
| 745 |
+
border-bottom: 1px solid var(--border-color);
|
| 746 |
+
}
|
| 747 |
+
|
| 748 |
+
td {
|
| 749 |
+
padding: var(--space-md);
|
| 750 |
+
border-bottom: 1px solid var(--border-color);
|
| 751 |
+
color: var(--text-primary);
|
| 752 |
+
}
|
| 753 |
+
|
| 754 |
+
tr:hover td {
|
| 755 |
+
background: var(--bg-hover);
|
| 756 |
+
}
|
| 757 |
+
|
| 758 |
+
tr:last-child td {
|
| 759 |
+
border-bottom: none;
|
| 760 |
+
}
|
| 761 |
+
|
| 762 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 763 |
+
FORMS
|
| 764 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 765 |
+
.form-group {
|
| 766 |
+
margin-bottom: var(--space-lg);
|
| 767 |
+
}
|
| 768 |
+
|
| 769 |
+
.form-label {
|
| 770 |
+
display: block;
|
| 771 |
+
font-size: 0.8rem;
|
| 772 |
+
font-weight: 600;
|
| 773 |
+
color: var(--text-secondary);
|
| 774 |
+
text-transform: uppercase;
|
| 775 |
+
letter-spacing: 0.5px;
|
| 776 |
+
margin-bottom: var(--space-sm);
|
| 777 |
+
font-family: 'JetBrains Mono', monospace;
|
| 778 |
+
}
|
| 779 |
+
|
| 780 |
+
.form-input,
|
| 781 |
+
.form-select,
|
| 782 |
+
.form-textarea {
|
| 783 |
+
width: 100%;
|
| 784 |
+
background: var(--bg-tertiary);
|
| 785 |
+
border: 1px solid var(--border-color);
|
| 786 |
+
border-radius: var(--radius-md);
|
| 787 |
+
color: var(--text-primary);
|
| 788 |
+
font-family: 'Inter', sans-serif;
|
| 789 |
+
font-size: 0.95rem;
|
| 790 |
+
padding: var(--space-sm) var(--space-md);
|
| 791 |
+
transition: all var(--transition-base);
|
| 792 |
+
}
|
| 793 |
+
|
| 794 |
+
.form-input:focus,
|
| 795 |
+
.form-select:focus,
|
| 796 |
+
.form-textarea:focus {
|
| 797 |
+
outline: none;
|
| 798 |
+
border-color: var(--primary);
|
| 799 |
+
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
|
| 800 |
+
}
|
| 801 |
+
|
| 802 |
+
.form-input::placeholder,
|
| 803 |
+
.form-textarea::placeholder {
|
| 804 |
+
color: var(--text-muted);
|
| 805 |
+
}
|
| 806 |
+
|
| 807 |
+
.form-textarea {
|
| 808 |
+
min-height: 120px;
|
| 809 |
+
resize: vertical;
|
| 810 |
+
}
|
| 811 |
+
|
| 812 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 813 |
+
FOOTER
|
| 814 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 815 |
+
.footer {
|
| 816 |
+
background: var(--bg-secondary);
|
| 817 |
+
border-top: 1px solid var(--border-color);
|
| 818 |
+
padding: var(--space-2xl) var(--space-xl);
|
| 819 |
+
text-align: center;
|
| 820 |
+
margin-top: auto;
|
| 821 |
+
}
|
| 822 |
+
|
| 823 |
+
.footer-text {
|
| 824 |
+
font-size: 0.85rem;
|
| 825 |
+
color: var(--text-muted);
|
| 826 |
+
font-family: 'JetBrains Mono', monospace;
|
| 827 |
+
}
|
| 828 |
+
|
| 829 |
+
.footer-brand {
|
| 830 |
+
color: var(--primary-light);
|
| 831 |
+
font-weight: 600;
|
| 832 |
+
}
|
| 833 |
+
|
| 834 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 835 |
+
PARTICLES BACKGROUND (CSS only)
|
| 836 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 837 |
+
.particles-container {
|
| 838 |
+
position: fixed;
|
| 839 |
+
top: 0;
|
| 840 |
+
left: 0;
|
| 841 |
+
width: 100%;
|
| 842 |
+
height: 100%;
|
| 843 |
+
pointer-events: none;
|
| 844 |
+
overflow: hidden;
|
| 845 |
+
z-index: 0;
|
| 846 |
+
}
|
| 847 |
+
|
| 848 |
+
.particle {
|
| 849 |
+
position: absolute;
|
| 850 |
+
width: 4px;
|
| 851 |
+
height: 4px;
|
| 852 |
+
background: var(--primary);
|
| 853 |
+
border-radius: 50%;
|
| 854 |
+
opacity: 0.3;
|
| 855 |
+
animation: particle 15s linear infinite;
|
| 856 |
+
}
|
| 857 |
+
|
| 858 |
+
.particle:nth-child(1) { left: 10%; animation-duration: 12s; animation-delay: 0s; }
|
| 859 |
+
.particle:nth-child(2) { left: 20%; animation-duration: 18s; animation-delay: 2s; background: var(--secondary); }
|
| 860 |
+
.particle:nth-child(3) { left: 30%; animation-duration: 14s; animation-delay: 4s; }
|
| 861 |
+
.particle:nth-child(4) { left: 40%; animation-duration: 20s; animation-delay: 1s; background: var(--accent); }
|
| 862 |
+
.particle:nth-child(5) { left: 50%; animation-duration: 16s; animation-delay: 3s; }
|
| 863 |
+
.particle:nth-child(6) { left: 60%; animation-duration: 13s; animation-delay: 5s; background: var(--success); }
|
| 864 |
+
.particle:nth-child(7) { left: 70%; animation-duration: 19s; animation-delay: 2s; }
|
| 865 |
+
.particle:nth-child(8) { left: 80%; animation-duration: 15s; animation-delay: 4s; background: var(--secondary); }
|
| 866 |
+
.particle:nth-child(9) { left: 90%; animation-duration: 17s; animation-delay: 1s; }
|
| 867 |
+
|
| 868 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 869 |
+
GRADIENT TEXT
|
| 870 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 871 |
+
.gradient-text {
|
| 872 |
+
background: linear-gradient(135deg, var(--primary-light), var(--secondary), var(--accent));
|
| 873 |
+
background-size: 200% 200%;
|
| 874 |
+
-webkit-background-clip: text;
|
| 875 |
+
-webkit-text-fill-color: transparent;
|
| 876 |
+
background-clip: text;
|
| 877 |
+
animation: gradientShift 4s ease infinite;
|
| 878 |
+
}
|
| 879 |
+
|
| 880 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 881 |
+
PAGE WRAPPER
|
| 882 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 883 |
+
.page-wrapper {
|
| 884 |
+
padding-top: var(--navbar-height);
|
| 885 |
+
min-height: 100vh;
|
| 886 |
+
display: flex;
|
| 887 |
+
flex-direction: column;
|
| 888 |
+
position: relative;
|
| 889 |
+
z-index: 1;
|
| 890 |
+
}
|
| 891 |
+
|
| 892 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 893 |
+
RESPONSIVE
|
| 894 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 895 |
+
@media (max-width: 768px) {
|
| 896 |
+
.navbar {
|
| 897 |
+
padding: 0 var(--space-md);
|
| 898 |
+
}
|
| 899 |
+
|
| 900 |
+
.nav-link span:not(.nav-icon) {
|
| 901 |
+
display: none;
|
| 902 |
+
}
|
| 903 |
+
|
| 904 |
+
.navbar-brand span {
|
| 905 |
+
display: none;
|
| 906 |
+
}
|
| 907 |
+
|
| 908 |
+
.nav-badge {
|
| 909 |
+
display: none;
|
| 910 |
+
}
|
| 911 |
+
|
| 912 |
+
:root {
|
| 913 |
+
--sidebar-width: 0;
|
| 914 |
+
}
|
| 915 |
+
}
|
| 916 |
+
|
| 917 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 918 |
+
SCROLLBAR STYLING
|
| 919 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 920 |
+
::-webkit-scrollbar {
|
| 921 |
+
width: 8px;
|
| 922 |
+
height: 8px;
|
| 923 |
+
}
|
| 924 |
+
|
| 925 |
+
::-webkit-scrollbar-track {
|
| 926 |
+
background: var(--bg-secondary);
|
| 927 |
+
}
|
| 928 |
+
|
| 929 |
+
::-webkit-scrollbar-thumb {
|
| 930 |
+
background: var(--border-light);
|
| 931 |
+
border-radius: 4px;
|
| 932 |
+
}
|
| 933 |
+
|
| 934 |
+
::-webkit-scrollbar-thumb:hover {
|
| 935 |
+
background: var(--primary);
|
| 936 |
+
}
|
| 937 |
+
|
| 938 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 939 |
+
SELECTION
|
| 940 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 941 |
+
::selection {
|
| 942 |
+
background: rgba(99, 102, 241, 0.3);
|
| 943 |
+
color: var(--text-primary);
|
| 944 |
+
}
|
feedback.html
ADDED
|
@@ -0,0 +1,1149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="fr">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Questions & Feedback — ML Academy</title>
|
| 7 |
+
<link rel="stylesheet" href="css/shared.css">
|
| 8 |
+
<style>
|
| 9 |
+
/* PAGE HERO */
|
| 10 |
+
.feedback-hero {
|
| 11 |
+
background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-tertiary) 100%);
|
| 12 |
+
border-bottom: 1px solid var(--border-color);
|
| 13 |
+
padding: var(--space-3xl) var(--space-xl);
|
| 14 |
+
text-align: center;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
.feedback-hero-label {
|
| 18 |
+
font-family: 'JetBrains Mono', monospace;
|
| 19 |
+
font-size: 0.75rem;
|
| 20 |
+
color: var(--secondary);
|
| 21 |
+
text-transform: uppercase;
|
| 22 |
+
letter-spacing: 2px;
|
| 23 |
+
margin-bottom: var(--space-md);
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
.feedback-hero-title {
|
| 27 |
+
font-size: clamp(2rem, 5vw, 3rem);
|
| 28 |
+
font-weight: 700;
|
| 29 |
+
color: var(--text-primary);
|
| 30 |
+
margin-bottom: var(--space-md);
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
.feedback-hero-subtitle {
|
| 34 |
+
font-size: 1.1rem;
|
| 35 |
+
color: var(--text-secondary);
|
| 36 |
+
max-width: 600px;
|
| 37 |
+
margin: 0 auto;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
/* FEEDBACK CONTAINER */
|
| 41 |
+
.feedback-container {
|
| 42 |
+
max-width: 800px;
|
| 43 |
+
margin: 0 auto;
|
| 44 |
+
padding: var(--space-2xl) var(--space-xl);
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
/* FORM PROGRESS */
|
| 48 |
+
.form-progress {
|
| 49 |
+
display: flex;
|
| 50 |
+
gap: var(--space-sm);
|
| 51 |
+
margin-bottom: var(--space-xl);
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
.progress-step {
|
| 55 |
+
flex: 1;
|
| 56 |
+
height: 4px;
|
| 57 |
+
background: var(--bg-tertiary);
|
| 58 |
+
border-radius: 2px;
|
| 59 |
+
transition: background var(--transition-base);
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
.progress-step.active {
|
| 63 |
+
background: linear-gradient(90deg, var(--primary), var(--secondary));
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
/* FORM CARDS */
|
| 67 |
+
.form-card {
|
| 68 |
+
background: var(--bg-card);
|
| 69 |
+
border: 1px solid var(--border-color);
|
| 70 |
+
border-radius: var(--radius-lg);
|
| 71 |
+
overflow: hidden;
|
| 72 |
+
margin-bottom: var(--space-lg);
|
| 73 |
+
transition: all var(--transition-base);
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
.form-card:hover {
|
| 77 |
+
border-color: var(--border-light);
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
.form-card-header {
|
| 81 |
+
display: flex;
|
| 82 |
+
align-items: center;
|
| 83 |
+
gap: var(--space-md);
|
| 84 |
+
padding: var(--space-lg) var(--space-xl);
|
| 85 |
+
background: var(--bg-tertiary);
|
| 86 |
+
border-bottom: 1px solid var(--border-color);
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
.form-card-icon {
|
| 90 |
+
width: 36px;
|
| 91 |
+
height: 36px;
|
| 92 |
+
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
| 93 |
+
border-radius: var(--radius-md);
|
| 94 |
+
display: flex;
|
| 95 |
+
align-items: center;
|
| 96 |
+
justify-content: center;
|
| 97 |
+
font-size: 1rem;
|
| 98 |
+
font-weight: 700;
|
| 99 |
+
color: white;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
.form-card-title {
|
| 103 |
+
font-size: 1.1rem;
|
| 104 |
+
font-weight: 600;
|
| 105 |
+
color: var(--text-primary);
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
.form-card-body {
|
| 109 |
+
padding: var(--space-xl);
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
/* FORM ELEMENTS */
|
| 113 |
+
.form-row {
|
| 114 |
+
margin-bottom: var(--space-lg);
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
.form-row:last-child {
|
| 118 |
+
margin-bottom: 0;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
.form-label {
|
| 122 |
+
display: block;
|
| 123 |
+
font-size: 0.85rem;
|
| 124 |
+
font-weight: 500;
|
| 125 |
+
color: var(--text-primary);
|
| 126 |
+
margin-bottom: var(--space-sm);
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
.form-label .required {
|
| 130 |
+
color: var(--danger);
|
| 131 |
+
margin-left: var(--space-xs);
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
.form-label .hint {
|
| 135 |
+
font-size: 0.75rem;
|
| 136 |
+
color: var(--text-muted);
|
| 137 |
+
font-weight: 400;
|
| 138 |
+
margin-left: var(--space-sm);
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
/* STAR RATING */
|
| 142 |
+
.star-rating {
|
| 143 |
+
display: flex;
|
| 144 |
+
gap: var(--space-sm);
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
.star {
|
| 148 |
+
font-size: 2rem;
|
| 149 |
+
cursor: pointer;
|
| 150 |
+
transition: all var(--transition-fast);
|
| 151 |
+
filter: grayscale(1);
|
| 152 |
+
opacity: 0.4;
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
.star:hover,
|
| 156 |
+
.star.active {
|
| 157 |
+
filter: grayscale(0);
|
| 158 |
+
opacity: 1;
|
| 159 |
+
transform: scale(1.2);
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
.star-rating-text {
|
| 163 |
+
font-size: 0.85rem;
|
| 164 |
+
color: var(--text-muted);
|
| 165 |
+
margin-left: var(--space-md);
|
| 166 |
+
align-self: center;
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
/* DIFFICULTY BUTTONS */
|
| 170 |
+
.difficulty-buttons {
|
| 171 |
+
display: flex;
|
| 172 |
+
gap: var(--space-sm);
|
| 173 |
+
flex-wrap: wrap;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
.difficulty-btn {
|
| 177 |
+
padding: var(--space-sm) var(--space-md);
|
| 178 |
+
background: var(--bg-tertiary);
|
| 179 |
+
border: 1px solid var(--border-color);
|
| 180 |
+
border-radius: var(--radius-md);
|
| 181 |
+
color: var(--text-secondary);
|
| 182 |
+
font-size: 0.9rem;
|
| 183 |
+
cursor: pointer;
|
| 184 |
+
transition: all var(--transition-base);
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
.difficulty-btn:hover {
|
| 188 |
+
border-color: var(--primary);
|
| 189 |
+
color: var(--text-primary);
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
.difficulty-btn.selected {
|
| 193 |
+
background: rgba(99, 102, 241, 0.2);
|
| 194 |
+
border-color: var(--primary);
|
| 195 |
+
color: var(--primary-light);
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
/* RADIO & CHECKBOX GROUPS */
|
| 199 |
+
.radio-group,
|
| 200 |
+
.checkbox-group {
|
| 201 |
+
display: flex;
|
| 202 |
+
flex-direction: column;
|
| 203 |
+
gap: var(--space-sm);
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
.radio-option,
|
| 207 |
+
.checkbox-option {
|
| 208 |
+
display: flex;
|
| 209 |
+
align-items: flex-start;
|
| 210 |
+
gap: var(--space-md);
|
| 211 |
+
padding: var(--space-md);
|
| 212 |
+
background: var(--bg-tertiary);
|
| 213 |
+
border: 1px solid var(--border-color);
|
| 214 |
+
border-radius: var(--radius-md);
|
| 215 |
+
cursor: pointer;
|
| 216 |
+
transition: all var(--transition-base);
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
.radio-option:hover,
|
| 220 |
+
.checkbox-option:hover {
|
| 221 |
+
border-color: var(--primary);
|
| 222 |
+
background: var(--bg-hover);
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
.radio-option input,
|
| 226 |
+
.checkbox-option input {
|
| 227 |
+
margin-top: 2px;
|
| 228 |
+
accent-color: var(--primary);
|
| 229 |
+
width: 18px;
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
.radio-label,
|
| 233 |
+
.checkbox-label {
|
| 234 |
+
font-size: 0.9rem;
|
| 235 |
+
color: var(--text-secondary);
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
/* SUBMIT BUTTON */
|
| 239 |
+
.submit-btn {
|
| 240 |
+
width: 100%;
|
| 241 |
+
padding: var(--space-md);
|
| 242 |
+
background: linear-gradient(135deg, var(--primary), var(--primary-dark));
|
| 243 |
+
color: white;
|
| 244 |
+
border: none;
|
| 245 |
+
border-radius: var(--radius-md);
|
| 246 |
+
font-family: 'Inter', sans-serif;
|
| 247 |
+
font-size: 1rem;
|
| 248 |
+
font-weight: 600;
|
| 249 |
+
cursor: pointer;
|
| 250 |
+
transition: all var(--transition-base);
|
| 251 |
+
display: flex;
|
| 252 |
+
align-items: center;
|
| 253 |
+
justify-content: center;
|
| 254 |
+
gap: var(--space-sm);
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
.submit-btn:hover {
|
| 258 |
+
transform: translateY(-2px);
|
| 259 |
+
box-shadow: var(--shadow-glow);
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
.submit-btn:disabled {
|
| 263 |
+
opacity: 0.6;
|
| 264 |
+
cursor: not-allowed;
|
| 265 |
+
transform: none;
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
/* SUCCESS MESSAGE */
|
| 269 |
+
.success-message {
|
| 270 |
+
display: none;
|
| 271 |
+
background: rgba(16, 185, 129, 0.1);
|
| 272 |
+
border: 1px solid rgba(16, 185, 129, 0.3);
|
| 273 |
+
border-radius: var(--radius-lg);
|
| 274 |
+
padding: var(--space-3xl);
|
| 275 |
+
text-align: center;
|
| 276 |
+
animation: scaleIn 0.5s ease;
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
.success-message.show {
|
| 280 |
+
display: block;
|
| 281 |
+
}
|
| 282 |
+
|
| 283 |
+
.success-icon {
|
| 284 |
+
width: 60px;
|
| 285 |
+
height: 60px;
|
| 286 |
+
background: linear-gradient(135deg, var(--success), #059669);
|
| 287 |
+
border-radius: 50%;
|
| 288 |
+
display: flex;
|
| 289 |
+
align-items: center;
|
| 290 |
+
justify-content: center;
|
| 291 |
+
font-size: 1.5rem;
|
| 292 |
+
font-weight: 700;
|
| 293 |
+
color: white;
|
| 294 |
+
margin: 0 auto var(--space-md);
|
| 295 |
+
animation: bounce 1s ease infinite;
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
.success-title {
|
| 299 |
+
font-size: 1.5rem;
|
| 300 |
+
font-weight: 700;
|
| 301 |
+
color: var(--success);
|
| 302 |
+
margin-bottom: var(--space-sm);
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
.success-text {
|
| 306 |
+
font-size: 1rem;
|
| 307 |
+
color: var(--text-secondary);
|
| 308 |
+
margin-bottom: var(--space-xl);
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
/* DATA EXPORT SECTION */
|
| 312 |
+
.export-section {
|
| 313 |
+
background: var(--bg-card);
|
| 314 |
+
border: 1px solid var(--border-color);
|
| 315 |
+
border-radius: var(--radius-lg);
|
| 316 |
+
padding: var(--space-xl);
|
| 317 |
+
margin-top: var(--space-xl);
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
.export-title {
|
| 321 |
+
font-size: 1rem;
|
| 322 |
+
font-weight: 600;
|
| 323 |
+
color: var(--text-primary);
|
| 324 |
+
margin-bottom: var(--space-md);
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
.export-buttons {
|
| 328 |
+
display: flex;
|
| 329 |
+
gap: var(--space-md);
|
| 330 |
+
flex-wrap: wrap;
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
.export-btn {
|
| 334 |
+
display: flex;
|
| 335 |
+
align-items: center;
|
| 336 |
+
gap: var(--space-sm);
|
| 337 |
+
padding: var(--space-sm) var(--space-md);
|
| 338 |
+
background: var(--bg-tertiary);
|
| 339 |
+
border: 1px solid var(--border-color);
|
| 340 |
+
border-radius: var(--radius-md);
|
| 341 |
+
color: var(--text-secondary);
|
| 342 |
+
font-size: 0.85rem;
|
| 343 |
+
cursor: pointer;
|
| 344 |
+
transition: all var(--transition-base);
|
| 345 |
+
text-decoration: none;
|
| 346 |
+
}
|
| 347 |
+
|
| 348 |
+
.export-btn:hover {
|
| 349 |
+
border-color: var(--primary);
|
| 350 |
+
color: var(--text-primary);
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
/* FAQ SECTION */
|
| 354 |
+
.faq-section {
|
| 355 |
+
margin-top: var(--space-3xl);
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
.faq-header {
|
| 359 |
+
text-align: center;
|
| 360 |
+
margin-bottom: var(--space-xl);
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
.faq-title {
|
| 364 |
+
font-size: 1.5rem;
|
| 365 |
+
font-weight: 700;
|
| 366 |
+
color: var(--text-primary);
|
| 367 |
+
margin-bottom: var(--space-sm);
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
.faq-subtitle {
|
| 371 |
+
font-size: 0.95rem;
|
| 372 |
+
color: var(--text-secondary);
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
.faq-item {
|
| 376 |
+
background: var(--bg-card);
|
| 377 |
+
border: 1px solid var(--border-color);
|
| 378 |
+
border-radius: var(--radius-md);
|
| 379 |
+
margin-bottom: var(--space-md);
|
| 380 |
+
overflow: hidden;
|
| 381 |
+
transition: all var(--transition-base);
|
| 382 |
+
}
|
| 383 |
+
|
| 384 |
+
.faq-item:hover {
|
| 385 |
+
border-color: var(--border-light);
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
.faq-question {
|
| 389 |
+
display: flex;
|
| 390 |
+
justify-content: space-between;
|
| 391 |
+
align-items: center;
|
| 392 |
+
padding: var(--space-lg) var(--space-xl);
|
| 393 |
+
cursor: pointer;
|
| 394 |
+
background: var(--bg-tertiary);
|
| 395 |
+
transition: background var(--transition-base);
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
.faq-question:hover {
|
| 399 |
+
background: var(--bg-hover);
|
| 400 |
+
}
|
| 401 |
+
|
| 402 |
+
.faq-question-text {
|
| 403 |
+
font-size: 0.95rem;
|
| 404 |
+
font-weight: 500;
|
| 405 |
+
color: var(--text-primary);
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
.faq-arrow {
|
| 409 |
+
color: var(--primary);
|
| 410 |
+
transition: transform var(--transition-base);
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
.faq-item.open .faq-arrow {
|
| 414 |
+
transform: rotate(180deg);
|
| 415 |
+
}
|
| 416 |
+
|
| 417 |
+
.faq-answer {
|
| 418 |
+
max-height: 0;
|
| 419 |
+
overflow: hidden;
|
| 420 |
+
transition: max-height var(--transition-slow);
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
.faq-item.open .faq-answer {
|
| 424 |
+
max-height: 500px;
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
.faq-answer-content {
|
| 428 |
+
padding: var(--space-lg) var(--space-xl);
|
| 429 |
+
font-size: 0.9rem;
|
| 430 |
+
color: var(--text-secondary);
|
| 431 |
+
line-height: 1.7;
|
| 432 |
+
border-top: 1px solid var(--border-color);
|
| 433 |
+
}
|
| 434 |
+
|
| 435 |
+
.faq-answer-content code {
|
| 436 |
+
background: rgba(99, 102, 241, 0.1);
|
| 437 |
+
padding: 2px 6px;
|
| 438 |
+
border-radius: 4px;
|
| 439 |
+
font-family: 'JetBrains Mono', monospace;
|
| 440 |
+
font-size: 0.8rem;
|
| 441 |
+
color: var(--primary-light);
|
| 442 |
+
}
|
| 443 |
+
|
| 444 |
+
/* CONTACT INFO */
|
| 445 |
+
.contact-info {
|
| 446 |
+
display: grid;
|
| 447 |
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
| 448 |
+
gap: var(--space-lg);
|
| 449 |
+
margin-top: var(--space-2xl);
|
| 450 |
+
padding-top: var(--space-2xl);
|
| 451 |
+
border-top: 1px solid var(--border-color);
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
.contact-item {
|
| 455 |
+
text-align: center;
|
| 456 |
+
padding: var(--space-lg);
|
| 457 |
+
background: var(--bg-card);
|
| 458 |
+
border: 1px solid var(--border-color);
|
| 459 |
+
border-radius: var(--radius-md);
|
| 460 |
+
transition: all var(--transition-base);
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
.contact-item:hover {
|
| 464 |
+
border-color: var(--primary);
|
| 465 |
+
transform: translateY(-3px);
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
.contact-icon {
|
| 469 |
+
width: 40px;
|
| 470 |
+
height: 40px;
|
| 471 |
+
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
| 472 |
+
border-radius: var(--radius-md);
|
| 473 |
+
display: flex;
|
| 474 |
+
align-items: center;
|
| 475 |
+
justify-content: center;
|
| 476 |
+
font-size: 1rem;
|
| 477 |
+
font-weight: 700;
|
| 478 |
+
color: white;
|
| 479 |
+
margin: 0 auto var(--space-sm);
|
| 480 |
+
}
|
| 481 |
+
|
| 482 |
+
.contact-label {
|
| 483 |
+
font-size: 0.85rem;
|
| 484 |
+
font-weight: 600;
|
| 485 |
+
color: var(--text-primary);
|
| 486 |
+
margin-bottom: var(--space-xs);
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
.contact-value {
|
| 490 |
+
font-size: 0.8rem;
|
| 491 |
+
color: var(--text-muted);
|
| 492 |
+
}
|
| 493 |
+
|
| 494 |
+
.contact-link {
|
| 495 |
+
color: var(--primary-light);
|
| 496 |
+
text-decoration: none;
|
| 497 |
+
}
|
| 498 |
+
|
| 499 |
+
.contact-link:hover {
|
| 500 |
+
text-decoration: underline;
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
/* AUTHOR FOOTER */
|
| 504 |
+
.author-footer {
|
| 505 |
+
background: var(--bg-secondary);
|
| 506 |
+
border-top: 1px solid var(--border-color);
|
| 507 |
+
padding: var(--space-xl);
|
| 508 |
+
text-align: center;
|
| 509 |
+
}
|
| 510 |
+
|
| 511 |
+
.author-info {
|
| 512 |
+
display: flex;
|
| 513 |
+
justify-content: center;
|
| 514 |
+
gap: var(--space-xl);
|
| 515 |
+
flex-wrap: wrap;
|
| 516 |
+
margin-bottom: var(--space-md);
|
| 517 |
+
}
|
| 518 |
+
|
| 519 |
+
.author-link {
|
| 520 |
+
display: flex;
|
| 521 |
+
align-items: center;
|
| 522 |
+
gap: var(--space-sm);
|
| 523 |
+
color: var(--text-secondary);
|
| 524 |
+
text-decoration: none;
|
| 525 |
+
font-size: 0.9rem;
|
| 526 |
+
transition: color var(--transition-base);
|
| 527 |
+
}
|
| 528 |
+
|
| 529 |
+
.author-link:hover {
|
| 530 |
+
color: var(--primary-light);
|
| 531 |
+
}
|
| 532 |
+
|
| 533 |
+
.author-link svg {
|
| 534 |
+
width: 18px;
|
| 535 |
+
height: 18px;
|
| 536 |
+
fill: currentColor;
|
| 537 |
+
}
|
| 538 |
+
</style>
|
| 539 |
+
</head>
|
| 540 |
+
<body>
|
| 541 |
+
<!-- Particles Background -->
|
| 542 |
+
<div class="particles-container">
|
| 543 |
+
<div class="particle"></div>
|
| 544 |
+
<div class="particle"></div>
|
| 545 |
+
<div class="particle"></div>
|
| 546 |
+
<div class="particle"></div>
|
| 547 |
+
<div class="particle"></div>
|
| 548 |
+
</div>
|
| 549 |
+
|
| 550 |
+
<!-- Navigation -->
|
| 551 |
+
<nav class="navbar">
|
| 552 |
+
<a href="index.html" class="navbar-brand">
|
| 553 |
+
<div class="brand-logo">ML</div>
|
| 554 |
+
<span>ML Academy</span>
|
| 555 |
+
</a>
|
| 556 |
+
<div class="navbar-nav">
|
| 557 |
+
<a href="index.html" class="nav-link">
|
| 558 |
+
<span class="nav-icon">[H]</span>
|
| 559 |
+
<span>Accueil</span>
|
| 560 |
+
</a>
|
| 561 |
+
<a href="cours.html" class="nav-link">
|
| 562 |
+
<span class="nav-icon">[C]</span>
|
| 563 |
+
<span>Cours</span>
|
| 564 |
+
</a>
|
| 565 |
+
<a href="tp.html" class="nav-link">
|
| 566 |
+
<span class="nav-icon">[T]</span>
|
| 567 |
+
<span>TPs</span>
|
| 568 |
+
</a>
|
| 569 |
+
<a href="feedback.html" class="nav-link active">
|
| 570 |
+
<span class="nav-icon">[F]</span>
|
| 571 |
+
<span>Contact</span>
|
| 572 |
+
</a>
|
| 573 |
+
</div>
|
| 574 |
+
<div class="nav-badge">
|
| 575 |
+
<div class="dot"></div>
|
| 576 |
+
<span>Google Colab Ready</span>
|
| 577 |
+
</div>
|
| 578 |
+
</nav>
|
| 579 |
+
|
| 580 |
+
<!-- Page Wrapper -->
|
| 581 |
+
<div class="page-wrapper">
|
| 582 |
+
<!-- Hero -->
|
| 583 |
+
<section class="feedback-hero">
|
| 584 |
+
<div class="feedback-hero-label">Retours & Questions</div>
|
| 585 |
+
<h1 class="feedback-hero-title">Questions & Feedback</h1>
|
| 586 |
+
<p class="feedback-hero-subtitle">
|
| 587 |
+
Un point pas clair ? Une suggestion d'amelioration ?
|
| 588 |
+
Nous sommes la pour vous aider et ameliorer la formation.
|
| 589 |
+
</p>
|
| 590 |
+
</section>
|
| 591 |
+
|
| 592 |
+
<!-- Feedback Container -->
|
| 593 |
+
<div class="feedback-container">
|
| 594 |
+
|
| 595 |
+
<!-- Success Message -->
|
| 596 |
+
<div class="success-message" id="successMessage">
|
| 597 |
+
<div class="success-icon">OK</div>
|
| 598 |
+
<h2 class="success-title">Merci pour votre retour !</h2>
|
| 599 |
+
<p class="success-text">
|
| 600 |
+
Vos reponses ont ete enregistrees. Nous les analyserons et vous repondrons
|
| 601 |
+
dans les plus brefs delais.
|
| 602 |
+
</p>
|
| 603 |
+
<a href="index.html" class="btn btn-outline">Retour a l'accueil</a>
|
| 604 |
+
</div>
|
| 605 |
+
|
| 606 |
+
<!-- Form -->
|
| 607 |
+
<form id="feedbackForm">
|
| 608 |
+
<!-- Progress -->
|
| 609 |
+
<div class="form-progress">
|
| 610 |
+
<div class="progress-step active"></div>
|
| 611 |
+
<div class="progress-step"></div>
|
| 612 |
+
<div class="progress-step"></div>
|
| 613 |
+
</div>
|
| 614 |
+
|
| 615 |
+
<!-- Card 1: Identification -->
|
| 616 |
+
<div class="form-card scroll-animate">
|
| 617 |
+
<div class="form-card-header">
|
| 618 |
+
<div class="form-card-icon">I</div>
|
| 619 |
+
<h2 class="form-card-title">Identification <span style="font-size: 0.8rem; color: var(--text-muted); font-weight: 400;">(optionnel)</span></h2>
|
| 620 |
+
</div>
|
| 621 |
+
<div class="form-card-body">
|
| 622 |
+
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md);">
|
| 623 |
+
<div class="form-row">
|
| 624 |
+
<label class="form-label">Prenom / Nom</label>
|
| 625 |
+
<input type="text" class="form-input" placeholder="Ex: Jean Dupont" id="name">
|
| 626 |
+
</div>
|
| 627 |
+
<div class="form-row">
|
| 628 |
+
<label class="form-label">Email</label>
|
| 629 |
+
<input type="email" class="form-input" placeholder="jean@example.com" id="email">
|
| 630 |
+
</div>
|
| 631 |
+
</div>
|
| 632 |
+
<div class="form-row" style="margin-bottom: 0;">
|
| 633 |
+
<label class="form-label">Sujet de projet</label>
|
| 634 |
+
<select class="form-select" id="project">
|
| 635 |
+
<option value="">— Selectionner —</option>
|
| 636 |
+
<option value="classification">Classification</option>
|
| 637 |
+
<option value="regression">Regression</option>
|
| 638 |
+
<option value="nlp">NLP / Texte</option>
|
| 639 |
+
<option value="computer-vision">Computer Vision</option>
|
| 640 |
+
<option value="time-series">Series Temporelles</option>
|
| 641 |
+
<option value="other">Autre</option>
|
| 642 |
+
</select>
|
| 643 |
+
</div>
|
| 644 |
+
</div>
|
| 645 |
+
</div>
|
| 646 |
+
|
| 647 |
+
<!-- Card 2: Evaluation -->
|
| 648 |
+
<div class="form-card scroll-animate">
|
| 649 |
+
<div class="form-card-header">
|
| 650 |
+
<div class="form-card-icon">E</div>
|
| 651 |
+
<h2 class="form-card-title">Evaluation de la formation</h2>
|
| 652 |
+
</div>
|
| 653 |
+
<div class="form-card-body">
|
| 654 |
+
<div class="form-row">
|
| 655 |
+
<label class="form-label">Note globale <span class="required">*</span></label>
|
| 656 |
+
<div style="display: flex; align-items: center;">
|
| 657 |
+
<div class="star-rating" id="starRating">
|
| 658 |
+
<span class="star" data-value="1">*</span>
|
| 659 |
+
<span class="star" data-value="2">*</span>
|
| 660 |
+
<span class="star" data-value="3">*</span>
|
| 661 |
+
<span class="star" data-value="4">*</span>
|
| 662 |
+
<span class="star" data-value="5">*</span>
|
| 663 |
+
</div>
|
| 664 |
+
<span class="star-rating-text" id="ratingText">Cliquez pour noter</span>
|
| 665 |
+
</div>
|
| 666 |
+
<input type="hidden" id="ratingValue" value="0">
|
| 667 |
+
</div>
|
| 668 |
+
|
| 669 |
+
<div class="form-row">
|
| 670 |
+
<label class="form-label">Niveau de difficulte <span class="required">*</span></label>
|
| 671 |
+
<div class="difficulty-buttons" id="difficultyButtons">
|
| 672 |
+
<button type="button" class="difficulty-btn" data-value="tres-facile">Tres facile</button>
|
| 673 |
+
<button type="button" class="difficulty-btn" data-value="facile">Facile</button>
|
| 674 |
+
<button type="button" class="difficulty-btn" data-value="adapte">Adapte</button>
|
| 675 |
+
<button type="button" class="difficulty-btn" data-value="difficile">Difficile</button>
|
| 676 |
+
<button type="button" class="difficulty-btn" data-value="tres-difficile">Trop difficile</button>
|
| 677 |
+
</div>
|
| 678 |
+
<input type="hidden" id="difficultyValue" value="">
|
| 679 |
+
</div>
|
| 680 |
+
|
| 681 |
+
<div class="form-row" style="margin-bottom: 0;">
|
| 682 |
+
<label class="form-label">Rythme de la formation</label>
|
| 683 |
+
<div class="radio-group">
|
| 684 |
+
<label class="radio-option">
|
| 685 |
+
<input type="radio" name="rythme" value="trop-lent">
|
| 686 |
+
<span class="radio-label">Trop lent — on aurait pu aller plus vite</span>
|
| 687 |
+
</label>
|
| 688 |
+
<label class="radio-option">
|
| 689 |
+
<input type="radio" name="rythme" value="bien" checked>
|
| 690 |
+
<span class="radio-label">Bien rythme — equilibre parfait</span>
|
| 691 |
+
</label>
|
| 692 |
+
<label class="radio-option">
|
| 693 |
+
<input type="radio" name="rythme" value="trop-rapide">
|
| 694 |
+
<span class="radio-label">Trop rapide — difficile a suivre</span>
|
| 695 |
+
</label>
|
| 696 |
+
</div>
|
| 697 |
+
</div>
|
| 698 |
+
</div>
|
| 699 |
+
</div>
|
| 700 |
+
|
| 701 |
+
<!-- Card 3: Content -->
|
| 702 |
+
<div class="form-card scroll-animate">
|
| 703 |
+
<div class="form-card-header">
|
| 704 |
+
<div class="form-card-icon">C</div>
|
| 705 |
+
<h2 class="form-card-title">Contenu de la formation</h2>
|
| 706 |
+
</div>
|
| 707 |
+
<div class="form-card-body">
|
| 708 |
+
<div class="form-row">
|
| 709 |
+
<label class="form-label">Parties les plus utiles <span class="hint">(plusieurs choix possibles)</span></label>
|
| 710 |
+
<div class="checkbox-group">
|
| 711 |
+
<label class="checkbox-option">
|
| 712 |
+
<input type="checkbox" name="utile" value="preprocessing">
|
| 713 |
+
<span class="checkbox-label">Pretraitement des donnees</span>
|
| 714 |
+
</label>
|
| 715 |
+
<label class="checkbox-option">
|
| 716 |
+
<input type="checkbox" name="utile" value="regression">
|
| 717 |
+
<span class="checkbox-label">Regression Lineaire & Logistique</span>
|
| 718 |
+
</label>
|
| 719 |
+
<label class="checkbox-option">
|
| 720 |
+
<input type="checkbox" name="utile" value="randomforest">
|
| 721 |
+
<span class="checkbox-label">Random Forest & XGBoost</span>
|
| 722 |
+
</label>
|
| 723 |
+
<label class="checkbox-option">
|
| 724 |
+
<input type="checkbox" name="utile" value="neuralnets">
|
| 725 |
+
<span class="checkbox-label">Reseaux de Neurones (Keras)</span>
|
| 726 |
+
</label>
|
| 727 |
+
<label class="checkbox-option">
|
| 728 |
+
<input type="checkbox" name="utile" value="lstm">
|
| 729 |
+
<span class="checkbox-label">LSTM & Series Temporelles</span>
|
| 730 |
+
</label>
|
| 731 |
+
<label class="checkbox-option">
|
| 732 |
+
<input type="checkbox" name="utile" value="cnn">
|
| 733 |
+
<span class="checkbox-label">CNN & Computer Vision</span>
|
| 734 |
+
</label>
|
| 735 |
+
<label class="checkbox-option">
|
| 736 |
+
<input type="checkbox" name="utile" value="nlp">
|
| 737 |
+
<span class="checkbox-label">NLP & Transformers</span>
|
| 738 |
+
</label>
|
| 739 |
+
<label class="checkbox-option">
|
| 740 |
+
<input type="checkbox" name="utile" value="tps">
|
| 741 |
+
<span class="checkbox-label">Travaux Pratiques (TPs)</span>
|
| 742 |
+
</label>
|
| 743 |
+
</div>
|
| 744 |
+
</div>
|
| 745 |
+
|
| 746 |
+
<div class="form-row" style="margin-bottom: 0;">
|
| 747 |
+
<label class="form-label">Points difficiles a comprendre</label>
|
| 748 |
+
<div class="checkbox-group">
|
| 749 |
+
<label class="checkbox-option">
|
| 750 |
+
<input type="checkbox" name="difficile" value="overfitting">
|
| 751 |
+
<span class="checkbox-label">Overfitting / Underfitting</span>
|
| 752 |
+
</label>
|
| 753 |
+
<label class="checkbox-option">
|
| 754 |
+
<input type="checkbox" name="difficile" value="normalisation">
|
| 755 |
+
<span class="checkbox-label">Normalisation et Data Leakage</span>
|
| 756 |
+
</label>
|
| 757 |
+
<label class="checkbox-option">
|
| 758 |
+
<input type="checkbox" name="difficile" value="hyperparameters">
|
| 759 |
+
<span class="checkbox-label">Choix des hyperparametres</span>
|
| 760 |
+
</label>
|
| 761 |
+
<label class="checkbox-option">
|
| 762 |
+
<input type="checkbox" name="difficile" value="lstm-gates">
|
| 763 |
+
<span class="checkbox-label">Les portes du LSTM</span>
|
| 764 |
+
</label>
|
| 765 |
+
<label class="checkbox-option">
|
| 766 |
+
<input type="checkbox" name="difficile" value="backprop">
|
| 767 |
+
<span class="checkbox-label">Backpropagation</span>
|
| 768 |
+
</label>
|
| 769 |
+
<label class="checkbox-option">
|
| 770 |
+
<input type="checkbox" name="difficile" value="metrics">
|
| 771 |
+
<span class="checkbox-label">Choix des metriques d'evaluation</span>
|
| 772 |
+
</label>
|
| 773 |
+
</div>
|
| 774 |
+
</div>
|
| 775 |
+
</div>
|
| 776 |
+
</div>
|
| 777 |
+
|
| 778 |
+
<!-- Card 4: Questions -->
|
| 779 |
+
<div class="form-card scroll-animate">
|
| 780 |
+
<div class="form-card-header">
|
| 781 |
+
<div class="form-card-icon">Q</div>
|
| 782 |
+
<h2 class="form-card-title">Vos questions</h2>
|
| 783 |
+
</div>
|
| 784 |
+
<div class="form-card-body">
|
| 785 |
+
<div class="form-row">
|
| 786 |
+
<label class="form-label">Question principale <span class="required">*</span></label>
|
| 787 |
+
<textarea class="form-textarea" placeholder="Decrivez votre question ou le point qui n'est pas clair..." id="mainQuestion" required></textarea>
|
| 788 |
+
</div>
|
| 789 |
+
|
| 790 |
+
<div class="form-row">
|
| 791 |
+
<label class="form-label">Question sur le code / les TPs <span class="hint">(optionnel)</span></label>
|
| 792 |
+
<textarea class="form-textarea" placeholder="Si vous avez une question specifique sur un notebook ou du code..." id="codeQuestion"></textarea>
|
| 793 |
+
</div>
|
| 794 |
+
|
| 795 |
+
<div class="form-row" style="margin-bottom: 0;">
|
| 796 |
+
<label class="form-label">Lien avec votre projet <span class="hint">(optionnel)</span></label>
|
| 797 |
+
<textarea class="form-textarea" placeholder="Comment cette formation peut-elle vous aider dans votre projet personnel ?" id="projectLink"></textarea>
|
| 798 |
+
</div>
|
| 799 |
+
</div>
|
| 800 |
+
</div>
|
| 801 |
+
|
| 802 |
+
<!-- Card 5: Suggestions -->
|
| 803 |
+
<div class="form-card scroll-animate">
|
| 804 |
+
<div class="form-card-header">
|
| 805 |
+
<div class="form-card-icon">S</div>
|
| 806 |
+
<h2 class="form-card-title">Suggestions d'amelioration</h2>
|
| 807 |
+
</div>
|
| 808 |
+
<div class="form-card-body">
|
| 809 |
+
<div class="form-row">
|
| 810 |
+
<label class="form-label">Ce que vous auriez aime voir de plus</label>
|
| 811 |
+
<div class="checkbox-group">
|
| 812 |
+
<label class="checkbox-option">
|
| 813 |
+
<input type="checkbox" name="suggestion" value="plus-tp">
|
| 814 |
+
<span class="checkbox-label">Plus de temps sur les TPs</span>
|
| 815 |
+
</label>
|
| 816 |
+
<label class="checkbox-option">
|
| 817 |
+
<input type="checkbox" name="suggestion" value="plus-theorie">
|
| 818 |
+
<span class="checkbox-label">Plus de theorie et d'equations</span>
|
| 819 |
+
</label>
|
| 820 |
+
<label class="checkbox-option">
|
| 821 |
+
<input type="checkbox" name="suggestion" value="plus-datasets">
|
| 822 |
+
<span class="checkbox-label">Plus de datasets differents</span>
|
| 823 |
+
</label>
|
| 824 |
+
<label class="checkbox-option">
|
| 825 |
+
<input type="checkbox" name="suggestion" value="deployment">
|
| 826 |
+
<span class="checkbox-label">Deploiement de modeles (API, Streamlit)</span>
|
| 827 |
+
</label>
|
| 828 |
+
<label class="checkbox-option">
|
| 829 |
+
<input type="checkbox" name="suggestion" value="mLOps">
|
| 830 |
+
<span class="checkbox-label">MLOps et gestion de modeles</span>
|
| 831 |
+
</label>
|
| 832 |
+
<label class="checkbox-option">
|
| 833 |
+
<input type="checkbox" name="suggestion" value="viz">
|
| 834 |
+
<span class="checkbox-label">Plus de visualisations interactives</span>
|
| 835 |
+
</label>
|
| 836 |
+
</div>
|
| 837 |
+
</div>
|
| 838 |
+
|
| 839 |
+
<div class="form-row" style="margin-bottom: 0;">
|
| 840 |
+
<label class="form-label">Commentaire libre</label>
|
| 841 |
+
<textarea class="form-textarea" placeholder="Toute suggestion ou remarque est la bienvenue..." id="freeComment"></textarea>
|
| 842 |
+
</div>
|
| 843 |
+
</div>
|
| 844 |
+
</div>
|
| 845 |
+
|
| 846 |
+
<!-- Submit -->
|
| 847 |
+
<button type="submit" class="submit-btn" id="submitBtn">
|
| 848 |
+
Envoyer mon feedback
|
| 849 |
+
</button>
|
| 850 |
+
<p style="text-align: center; font-size: 0.8rem; color: var(--text-muted); margin-top: var(--space-md);">
|
| 851 |
+
Vos reponses nous aident a ameliorer la formation pour les promotions futures.
|
| 852 |
+
</p>
|
| 853 |
+
</form>
|
| 854 |
+
|
| 855 |
+
<!-- Data Export Section -->
|
| 856 |
+
<div class="export-section scroll-animate" id="exportSection" style="display: none;">
|
| 857 |
+
<h3 class="export-title">Exporter les donnees</h3>
|
| 858 |
+
<p style="font-size: 0.85rem; color: var(--text-secondary); margin-bottom: var(--space-md);">
|
| 859 |
+
Telechargez les feedbacks collectes pour analyse.
|
| 860 |
+
</p>
|
| 861 |
+
<div class="export-buttons">
|
| 862 |
+
<button class="export-btn" onclick="feedbackStorage.downloadFeedbacks()">
|
| 863 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
| 864 |
+
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
|
| 865 |
+
</svg>
|
| 866 |
+
JSON
|
| 867 |
+
</button>
|
| 868 |
+
<button class="export-btn" onclick="feedbackStorage.exportToCSV()">
|
| 869 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
| 870 |
+
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
|
| 871 |
+
</svg>
|
| 872 |
+
CSV (Excel)
|
| 873 |
+
</button>
|
| 874 |
+
<button class="export-btn" onclick="showFeedbackStats()">
|
| 875 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
| 876 |
+
<path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/>
|
| 877 |
+
</svg>
|
| 878 |
+
Statistiques
|
| 879 |
+
</button>
|
| 880 |
+
</div>
|
| 881 |
+
</div>
|
| 882 |
+
|
| 883 |
+
<!-- FAQ Section -->
|
| 884 |
+
<section class="faq-section">
|
| 885 |
+
<div class="faq-header scroll-animate">
|
| 886 |
+
<h2 class="faq-title">Questions frequentes</h2>
|
| 887 |
+
<p class="faq-subtitle">Consultez d'abord ces reponses avant de soumettre votre question.</p>
|
| 888 |
+
</div>
|
| 889 |
+
|
| 890 |
+
<div class="faq-item scroll-animate">
|
| 891 |
+
<div class="faq-question" onclick="toggleFaq(this)">
|
| 892 |
+
<span class="faq-question-text">Pourquoi normaliser APRES le split et pas avant ?</span>
|
| 893 |
+
<span class="faq-arrow">v</span>
|
| 894 |
+
</div>
|
| 895 |
+
<div class="faq-answer">
|
| 896 |
+
<div class="faq-answer-content">
|
| 897 |
+
Si vous normalisez avant le split, vous calculez le min/max sur l'ensemble des donnees (train + test).
|
| 898 |
+
Votre modele "voit" donc indirectement les donnees de test pendant l'entrainement — c'est le
|
| 899 |
+
<strong>data leakage</strong>. La regle : <strong>fit sur train seulement, transform sur train ET test</strong>.
|
| 900 |
+
</div>
|
| 901 |
+
</div>
|
| 902 |
+
</div>
|
| 903 |
+
|
| 904 |
+
<div class="faq-item scroll-animate">
|
| 905 |
+
<div class="faq-question" onclick="toggleFaq(this)">
|
| 906 |
+
<span class="faq-question-text">Quelle est la difference entre MAE et RMSE ?</span>
|
| 907 |
+
<span class="faq-arrow">v</span>
|
| 908 |
+
</div>
|
| 909 |
+
<div class="faq-answer">
|
| 910 |
+
<div class="faq-answer-content">
|
| 911 |
+
<strong>MAE</strong> (Mean Absolute Error) = moyenne des erreurs absolues.
|
| 912 |
+
<strong>RMSE</strong> (Root Mean Squared Error) = racine de la moyenne des erreurs au carre.
|
| 913 |
+
La difference cle : RMSE <strong>penalise davantage les grandes erreurs</strong> car on eleve au carre.
|
| 914 |
+
En ingenierie, RMSE >= MAE toujours.
|
| 915 |
+
</div>
|
| 916 |
+
</div>
|
| 917 |
+
</div>
|
| 918 |
+
|
| 919 |
+
<div class="faq-item scroll-animate">
|
| 920 |
+
<div class="faq-question" onclick="toggleFaq(this)">
|
| 921 |
+
<span class="faq-question-text">Comment savoir si mon modele fait de l'overfitting ?</span>
|
| 922 |
+
<span class="faq-arrow">v</span>
|
| 923 |
+
</div>
|
| 924 |
+
<div class="faq-answer">
|
| 925 |
+
<div class="faq-answer-content">
|
| 926 |
+
Comparez les metriques sur <strong>train</strong> ET <strong>test</strong>.
|
| 927 |
+
<strong>Overfitting</strong> = R2 train tres eleve (0.99) mais R2 test beaucoup plus bas (0.65).
|
| 928 |
+
<strong>Bonne generalisation</strong> = R2 train ≈ R2 test (ex: 0.96 vs 0.94).
|
| 929 |
+
Solution : Dropout, Early Stopping, regularisation L2.
|
| 930 |
+
</div>
|
| 931 |
+
</div>
|
| 932 |
+
</div>
|
| 933 |
+
|
| 934 |
+
<div class="faq-item scroll-animate">
|
| 935 |
+
<div class="faq-question" onclick="toggleFaq(this)">
|
| 936 |
+
<span class="faq-question-text">Quand utiliser Random Forest vs Neural Networks ?</span>
|
| 937 |
+
<span class="faq-arrow">v</span>
|
| 938 |
+
</div>
|
| 939 |
+
<div class="faq-answer">
|
| 940 |
+
<div class="faq-answer-content">
|
| 941 |
+
<strong>Random Forest</strong> : donnees tabulaires, besoin d'interpretabilite,
|
| 942 |
+
peu de temps de tuning. <strong>Neural Networks</strong> : donnees complexes (images, texte),
|
| 943 |
+
beaucoup de donnees disponibles, ressources computationnelles importantes.
|
| 944 |
+
</div>
|
| 945 |
+
</div>
|
| 946 |
+
</div>
|
| 947 |
+
|
| 948 |
+
<div class="faq-item scroll-animate">
|
| 949 |
+
<div class="faq-question" onclick="toggleFaq(this)">
|
| 950 |
+
<span class="faq-question-text">Comment adapter le code a mes propres donnees ?</span>
|
| 951 |
+
<span class="faq-arrow">v</span>
|
| 952 |
+
</div>
|
| 953 |
+
<div class="faq-answer">
|
| 954 |
+
<div class="faq-answer-content">
|
| 955 |
+
Remplacez <code>df = pd.read_csv("vos_donnees.csv")</code>. Verifiez avec
|
| 956 |
+
<code>df.head()</code> et <code>df.describe()</code>. Adaptez la liste des features
|
| 957 |
+
et la variable cible. Ajoutez <code>df.dropna()</code> pour supprimer les NaN.
|
| 958 |
+
Le reste du pipeline reste identique !
|
| 959 |
+
</div>
|
| 960 |
+
</div>
|
| 961 |
+
</div>
|
| 962 |
+
</section>
|
| 963 |
+
|
| 964 |
+
<!-- Contact Info -->
|
| 965 |
+
<div class="contact-info">
|
| 966 |
+
<div class="contact-item scroll-animate">
|
| 967 |
+
<div class="contact-icon">@</div>
|
| 968 |
+
<div class="contact-label">Email</div>
|
| 969 |
+
<div class="contact-value">
|
| 970 |
+
<a href="mailto:imadmaalouf02@gmail.com" class="contact-link">imadmaalouf02@gmail.com</a>
|
| 971 |
+
</div>
|
| 972 |
+
</div>
|
| 973 |
+
<div class="contact-item scroll-animate">
|
| 974 |
+
<div class="contact-icon">GH</div>
|
| 975 |
+
<div class="contact-label">GitHub</div>
|
| 976 |
+
<div class="contact-value">
|
| 977 |
+
<a href="https://github.com/imadmaalouf02" target="_blank" class="contact-link">github.com/imadmaalouf02</a>
|
| 978 |
+
</div>
|
| 979 |
+
</div>
|
| 980 |
+
<div class="contact-item scroll-animate">
|
| 981 |
+
<div class="contact-icon">HF</div>
|
| 982 |
+
<div class="contact-label">Hugging Face</div>
|
| 983 |
+
<div class="contact-value">
|
| 984 |
+
<a href="https://huggingface.co/spaces/MAALOOUF/ML_Training" target="_blank" class="contact-link">ML Training Space</a>
|
| 985 |
+
</div>
|
| 986 |
+
</div>
|
| 987 |
+
</div>
|
| 988 |
+
|
| 989 |
+
</div>
|
| 990 |
+
|
| 991 |
+
<!-- Author Footer -->
|
| 992 |
+
<footer class="author-footer">
|
| 993 |
+
<div class="author-info">
|
| 994 |
+
<a href="mailto:imadmaalouf02@gmail.com" class="author-link">
|
| 995 |
+
<svg viewBox="0 0 24 24"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>
|
| 996 |
+
imadmaalouf02@gmail.com
|
| 997 |
+
</a>
|
| 998 |
+
<a href="https://github.com/imadmaalouf02" target="_blank" class="author-link">
|
| 999 |
+
<svg viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
| 1000 |
+
GitHub
|
| 1001 |
+
</a>
|
| 1002 |
+
<a href="https://huggingface.co/spaces/MAALOOUF/ML_Training" target="_blank" class="author-link">
|
| 1003 |
+
<svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
|
| 1004 |
+
Hugging Face Space
|
| 1005 |
+
</a>
|
| 1006 |
+
</div>
|
| 1007 |
+
</footer>
|
| 1008 |
+
|
| 1009 |
+
<!-- Footer -->
|
| 1010 |
+
<footer class="footer">
|
| 1011 |
+
<p class="footer-text">
|
| 1012 |
+
ML Academy — Questions & Feedback —
|
| 1013 |
+
<span class="footer-brand">GE-MCI 4A</span> — 2025/2026
|
| 1014 |
+
</p>
|
| 1015 |
+
<p class="footer-text" style="margin-top: var(--space-sm); font-size: 0.75rem; color: var(--text-muted);">
|
| 1016 |
+
Formateur : Imad Maalouf
|
| 1017 |
+
</p>
|
| 1018 |
+
</footer>
|
| 1019 |
+
</div>
|
| 1020 |
+
|
| 1021 |
+
<!-- Scripts -->
|
| 1022 |
+
<script src="js/shared.js"></script>
|
| 1023 |
+
<script src="js/feedback-storage.js"></script>
|
| 1024 |
+
<script>
|
| 1025 |
+
// Scroll animations
|
| 1026 |
+
const observerOptions = {
|
| 1027 |
+
threshold: 0.1,
|
| 1028 |
+
rootMargin: '0px 0px -50px 0px'
|
| 1029 |
+
};
|
| 1030 |
+
|
| 1031 |
+
const observer = new IntersectionObserver((entries) => {
|
| 1032 |
+
entries.forEach(entry => {
|
| 1033 |
+
if (entry.isIntersecting) {
|
| 1034 |
+
entry.target.classList.add('visible');
|
| 1035 |
+
}
|
| 1036 |
+
});
|
| 1037 |
+
}, observerOptions);
|
| 1038 |
+
|
| 1039 |
+
document.querySelectorAll('.scroll-animate').forEach(el => {
|
| 1040 |
+
observer.observe(el);
|
| 1041 |
+
});
|
| 1042 |
+
|
| 1043 |
+
// Star rating
|
| 1044 |
+
const stars = document.querySelectorAll('.star');
|
| 1045 |
+
const ratingValue = document.getElementById('ratingValue');
|
| 1046 |
+
const ratingText = document.getElementById('ratingText');
|
| 1047 |
+
const ratingLabels = ['', 'Insuffisant', 'Passable', 'Bien', 'Tres bien', 'Excellent !'];
|
| 1048 |
+
|
| 1049 |
+
stars.forEach(star => {
|
| 1050 |
+
star.addEventListener('click', () => {
|
| 1051 |
+
const value = parseInt(star.dataset.value);
|
| 1052 |
+
ratingValue.value = value;
|
| 1053 |
+
ratingText.textContent = ratingLabels[value];
|
| 1054 |
+
|
| 1055 |
+
stars.forEach((s, i) => {
|
| 1056 |
+
s.classList.toggle('active', i < value);
|
| 1057 |
+
});
|
| 1058 |
+
|
| 1059 |
+
// Update progress
|
| 1060 |
+
document.querySelectorAll('.progress-step')[1].classList.add('active');
|
| 1061 |
+
});
|
| 1062 |
+
});
|
| 1063 |
+
|
| 1064 |
+
// Difficulty buttons
|
| 1065 |
+
const diffButtons = document.querySelectorAll('.difficulty-btn');
|
| 1066 |
+
const difficultyValue = document.getElementById('difficultyValue');
|
| 1067 |
+
|
| 1068 |
+
diffButtons.forEach(btn => {
|
| 1069 |
+
btn.addEventListener('click', () => {
|
| 1070 |
+
diffButtons.forEach(b => b.classList.remove('selected'));
|
| 1071 |
+
btn.classList.add('selected');
|
| 1072 |
+
difficultyValue.value = btn.dataset.value;
|
| 1073 |
+
});
|
| 1074 |
+
});
|
| 1075 |
+
|
| 1076 |
+
// FAQ toggle
|
| 1077 |
+
function toggleFaq(element) {
|
| 1078 |
+
const faqItem = element.parentElement;
|
| 1079 |
+
faqItem.classList.toggle('open');
|
| 1080 |
+
}
|
| 1081 |
+
|
| 1082 |
+
// Form submission
|
| 1083 |
+
const form = document.getElementById('feedbackForm');
|
| 1084 |
+
const successMessage = document.getElementById('successMessage');
|
| 1085 |
+
const submitBtn = document.getElementById('submitBtn');
|
| 1086 |
+
const exportSection = document.getElementById('exportSection');
|
| 1087 |
+
|
| 1088 |
+
form.addEventListener('submit', (e) => {
|
| 1089 |
+
e.preventDefault();
|
| 1090 |
+
|
| 1091 |
+
// Validation
|
| 1092 |
+
const rating = ratingValue.value;
|
| 1093 |
+
const difficulty = difficultyValue.value;
|
| 1094 |
+
const mainQuestion = document.getElementById('mainQuestion').value.trim();
|
| 1095 |
+
|
| 1096 |
+
if (rating === '0') {
|
| 1097 |
+
alert('Veuillez donner une note a la formation.');
|
| 1098 |
+
return;
|
| 1099 |
+
}
|
| 1100 |
+
|
| 1101 |
+
if (!difficulty) {
|
| 1102 |
+
alert('Veuillez indiquer le niveau de difficulte percu.');
|
| 1103 |
+
return;
|
| 1104 |
+
}
|
| 1105 |
+
|
| 1106 |
+
if (!mainQuestion) {
|
| 1107 |
+
alert('Veuillez poser au moins une question principale.');
|
| 1108 |
+
return;
|
| 1109 |
+
}
|
| 1110 |
+
|
| 1111 |
+
// Collect data
|
| 1112 |
+
const formData = {
|
| 1113 |
+
name: document.getElementById('name').value,
|
| 1114 |
+
email: document.getElementById('email').value,
|
| 1115 |
+
project: document.getElementById('project').value,
|
| 1116 |
+
rating: rating,
|
| 1117 |
+
difficulty: difficulty,
|
| 1118 |
+
rythme: document.querySelector('input[name="rythme"]:checked')?.value,
|
| 1119 |
+
utiles: [...document.querySelectorAll('input[name="utile"]:checked')].map(cb => cb.value),
|
| 1120 |
+
difficiles: [...document.querySelectorAll('input[name="difficile"]:checked')].map(cb => cb.value),
|
| 1121 |
+
mainQuestion: mainQuestion,
|
| 1122 |
+
codeQuestion: document.getElementById('codeQuestion').value,
|
| 1123 |
+
projectLink: document.getElementById('projectLink').value,
|
| 1124 |
+
suggestions: [...document.querySelectorAll('input[name="suggestion"]:checked')].map(cb => cb.value),
|
| 1125 |
+
freeComment: document.getElementById('freeComment').value,
|
| 1126 |
+
timestamp: new Date().toISOString()
|
| 1127 |
+
};
|
| 1128 |
+
|
| 1129 |
+
// Submit to storage
|
| 1130 |
+
submitFeedback(formData);
|
| 1131 |
+
|
| 1132 |
+
// Show success
|
| 1133 |
+
form.style.display = 'none';
|
| 1134 |
+
successMessage.classList.add('show');
|
| 1135 |
+
exportSection.style.display = 'block';
|
| 1136 |
+
document.querySelectorAll('.progress-step')[2].classList.add('active');
|
| 1137 |
+
window.scrollTo({ top: 0, behavior: 'smooth' });
|
| 1138 |
+
});
|
| 1139 |
+
|
| 1140 |
+
// Update progress on scroll
|
| 1141 |
+
window.addEventListener('scroll', () => {
|
| 1142 |
+
const mainQuestion = document.getElementById('mainQuestion')?.value.trim();
|
| 1143 |
+
if (mainQuestion) {
|
| 1144 |
+
document.querySelectorAll('.progress-step')[2].classList.add('active');
|
| 1145 |
+
}
|
| 1146 |
+
});
|
| 1147 |
+
</script>
|
| 1148 |
+
</body>
|
| 1149 |
+
</html>
|
index.html
CHANGED
|
@@ -1,19 +1,1010 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
</html>
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="fr">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>ML Academy — Plateforme de Formation Machine Learning</title>
|
| 7 |
+
<link rel="stylesheet" href="css/shared.css">
|
| 8 |
+
<style>
|
| 9 |
+
/* HERO SECTION */
|
| 10 |
+
.hero {
|
| 11 |
+
min-height: calc(100vh - var(--navbar-height));
|
| 12 |
+
display: flex;
|
| 13 |
+
flex-direction: column;
|
| 14 |
+
justify-content: center;
|
| 15 |
+
align-items: center;
|
| 16 |
+
text-align: center;
|
| 17 |
+
padding: var(--space-3xl) var(--space-xl);
|
| 18 |
+
position: relative;
|
| 19 |
+
overflow: hidden;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
.hero-bg {
|
| 23 |
+
position: absolute;
|
| 24 |
+
top: 0;
|
| 25 |
+
left: 0;
|
| 26 |
+
right: 0;
|
| 27 |
+
bottom: 0;
|
| 28 |
+
background:
|
| 29 |
+
radial-gradient(ellipse at 20% 20%, rgba(99, 102, 241, 0.15) 0%, transparent 50%),
|
| 30 |
+
radial-gradient(ellipse at 80% 80%, rgba(6, 182, 212, 0.1) 0%, transparent 50%),
|
| 31 |
+
radial-gradient(ellipse at 50% 50%, rgba(245, 158, 11, 0.05) 0%, transparent 70%);
|
| 32 |
+
animation: pulse 8s ease-in-out infinite;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
.hero-eyebrow {
|
| 36 |
+
display: inline-flex;
|
| 37 |
+
align-items: center;
|
| 38 |
+
gap: var(--space-sm);
|
| 39 |
+
padding: var(--space-xs) var(--space-md);
|
| 40 |
+
background: rgba(99, 102, 241, 0.1);
|
| 41 |
+
border: 1px solid rgba(99, 102, 241, 0.3);
|
| 42 |
+
border-radius: 20px;
|
| 43 |
+
font-family: 'JetBrains Mono', monospace;
|
| 44 |
+
font-size: 0.75rem;
|
| 45 |
+
color: var(--primary-light);
|
| 46 |
+
text-transform: uppercase;
|
| 47 |
+
letter-spacing: 1px;
|
| 48 |
+
margin-bottom: var(--space-lg);
|
| 49 |
+
animation: fadeInDown 0.6s ease 0.2s both;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
.hero-eyebrow .pulse {
|
| 53 |
+
width: 6px;
|
| 54 |
+
height: 6px;
|
| 55 |
+
background: var(--success);
|
| 56 |
+
border-radius: 50%;
|
| 57 |
+
animation: pulse 2s ease-in-out infinite;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
.hero-title {
|
| 61 |
+
font-size: clamp(2.5rem, 6vw, 4.5rem);
|
| 62 |
+
font-weight: 800;
|
| 63 |
+
line-height: 1.1;
|
| 64 |
+
margin-bottom: var(--space-md);
|
| 65 |
+
animation: fadeInUp 0.6s ease 0.3s both;
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
.hero-subtitle {
|
| 69 |
+
font-size: clamp(1rem, 2vw, 1.25rem);
|
| 70 |
+
color: var(--text-secondary);
|
| 71 |
+
max-width: 600px;
|
| 72 |
+
margin-bottom: var(--space-xl);
|
| 73 |
+
line-height: 1.7;
|
| 74 |
+
animation: fadeInUp 0.6s ease 0.4s both;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
.hero-cta {
|
| 78 |
+
display: flex;
|
| 79 |
+
gap: var(--space-md);
|
| 80 |
+
flex-wrap: wrap;
|
| 81 |
+
justify-content: center;
|
| 82 |
+
margin-bottom: var(--space-2xl);
|
| 83 |
+
animation: fadeInUp 0.6s ease 0.5s both;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
.hero-stats {
|
| 87 |
+
display: flex;
|
| 88 |
+
gap: var(--space-2xl);
|
| 89 |
+
flex-wrap: wrap;
|
| 90 |
+
justify-content: center;
|
| 91 |
+
padding-top: var(--space-xl);
|
| 92 |
+
border-top: 1px solid var(--border-color);
|
| 93 |
+
animation: fadeInUp 0.6s ease 0.6s both;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
.hero-stat {
|
| 97 |
+
text-align: center;
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
.hero-stat-value {
|
| 101 |
+
font-family: 'JetBrains Mono', monospace;
|
| 102 |
+
font-size: 2.5rem;
|
| 103 |
+
font-weight: 700;
|
| 104 |
+
color: var(--text-primary);
|
| 105 |
+
line-height: 1;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
.hero-stat-value span {
|
| 109 |
+
font-size: 1rem;
|
| 110 |
+
color: var(--primary-light);
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
.hero-stat-label {
|
| 114 |
+
font-size: 0.75rem;
|
| 115 |
+
color: var(--text-muted);
|
| 116 |
+
text-transform: uppercase;
|
| 117 |
+
letter-spacing: 1px;
|
| 118 |
+
margin-top: var(--space-xs);
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
/* FEATURES SECTION */
|
| 122 |
+
.features {
|
| 123 |
+
padding: var(--space-3xl) var(--space-xl);
|
| 124 |
+
background: var(--bg-secondary);
|
| 125 |
+
border-top: 1px solid var(--border-color);
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
.section-header {
|
| 129 |
+
text-align: center;
|
| 130 |
+
margin-bottom: var(--space-2xl);
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
.section-eyebrow {
|
| 134 |
+
font-family: 'JetBrains Mono', monospace;
|
| 135 |
+
font-size: 0.75rem;
|
| 136 |
+
color: var(--primary-light);
|
| 137 |
+
text-transform: uppercase;
|
| 138 |
+
letter-spacing: 2px;
|
| 139 |
+
margin-bottom: var(--space-sm);
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
.section-title {
|
| 143 |
+
font-size: clamp(1.75rem, 4vw, 2.5rem);
|
| 144 |
+
font-weight: 700;
|
| 145 |
+
color: var(--text-primary);
|
| 146 |
+
margin-bottom: var(--space-sm);
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
.section-subtitle {
|
| 150 |
+
font-size: 1rem;
|
| 151 |
+
color: var(--text-secondary);
|
| 152 |
+
max-width: 600px;
|
| 153 |
+
margin: 0 auto;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
.features-grid {
|
| 157 |
+
display: grid;
|
| 158 |
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
| 159 |
+
gap: var(--space-lg);
|
| 160 |
+
max-width: 1200px;
|
| 161 |
+
margin: 0 auto;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
.feature-card {
|
| 165 |
+
background: var(--bg-card);
|
| 166 |
+
border: 1px solid var(--border-color);
|
| 167 |
+
border-radius: var(--radius-lg);
|
| 168 |
+
padding: var(--space-xl);
|
| 169 |
+
transition: all var(--transition-base);
|
| 170 |
+
position: relative;
|
| 171 |
+
overflow: hidden;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
.feature-card::before {
|
| 175 |
+
content: '';
|
| 176 |
+
position: absolute;
|
| 177 |
+
top: 0;
|
| 178 |
+
left: 0;
|
| 179 |
+
right: 0;
|
| 180 |
+
height: 3px;
|
| 181 |
+
background: linear-gradient(90deg, var(--primary), var(--secondary));
|
| 182 |
+
transform: scaleX(0);
|
| 183 |
+
transition: transform var(--transition-base);
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
.feature-card:hover {
|
| 187 |
+
transform: translateY(-8px);
|
| 188 |
+
border-color: var(--border-light);
|
| 189 |
+
box-shadow: var(--shadow-lg), var(--shadow-glow);
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
.feature-card:hover::before {
|
| 193 |
+
transform: scaleX(1);
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
.feature-icon {
|
| 197 |
+
width: 60px;
|
| 198 |
+
height: 60px;
|
| 199 |
+
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
| 200 |
+
border-radius: var(--radius-md);
|
| 201 |
+
display: flex;
|
| 202 |
+
align-items: center;
|
| 203 |
+
justify-content: center;
|
| 204 |
+
font-size: 1.5rem;
|
| 205 |
+
font-weight: 700;
|
| 206 |
+
color: white;
|
| 207 |
+
margin-bottom: var(--space-md);
|
| 208 |
+
animation: float 3s ease-in-out infinite;
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
.feature-title {
|
| 212 |
+
font-size: 1.2rem;
|
| 213 |
+
font-weight: 700;
|
| 214 |
+
color: var(--text-primary);
|
| 215 |
+
margin-bottom: var(--space-sm);
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
.feature-text {
|
| 219 |
+
font-size: 0.9rem;
|
| 220 |
+
color: var(--text-secondary);
|
| 221 |
+
line-height: 1.6;
|
| 222 |
+
margin-bottom: var(--space-md);
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
.feature-tags {
|
| 226 |
+
display: flex;
|
| 227 |
+
flex-wrap: wrap;
|
| 228 |
+
gap: var(--space-xs);
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
/* MODULES SECTION */
|
| 232 |
+
.modules {
|
| 233 |
+
padding: var(--space-3xl) var(--space-xl);
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
.modules-grid {
|
| 237 |
+
display: grid;
|
| 238 |
+
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
| 239 |
+
gap: var(--space-lg);
|
| 240 |
+
max-width: 1200px;
|
| 241 |
+
margin: 0 auto;
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
.module-card {
|
| 245 |
+
background: var(--bg-card);
|
| 246 |
+
border: 1px solid var(--border-color);
|
| 247 |
+
border-radius: var(--radius-lg);
|
| 248 |
+
overflow: hidden;
|
| 249 |
+
transition: all var(--transition-base);
|
| 250 |
+
text-decoration: none;
|
| 251 |
+
color: inherit;
|
| 252 |
+
display: flex;
|
| 253 |
+
flex-direction: column;
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
.module-card:hover {
|
| 257 |
+
transform: translateY(-5px);
|
| 258 |
+
border-color: var(--primary);
|
| 259 |
+
box-shadow: var(--shadow-lg), var(--shadow-glow);
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
.module-header {
|
| 263 |
+
padding: var(--space-lg);
|
| 264 |
+
display: flex;
|
| 265 |
+
align-items: flex-start;
|
| 266 |
+
gap: var(--space-md);
|
| 267 |
+
border-bottom: 1px solid var(--border-color);
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
.module-icon {
|
| 271 |
+
width: 50px;
|
| 272 |
+
height: 50px;
|
| 273 |
+
border-radius: var(--radius-md);
|
| 274 |
+
display: flex;
|
| 275 |
+
align-items: center;
|
| 276 |
+
justify-content: center;
|
| 277 |
+
font-size: 1.25rem;
|
| 278 |
+
font-weight: 700;
|
| 279 |
+
flex-shrink: 0;
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
.module-icon.blue { background: rgba(99, 102, 241, 0.2); color: var(--primary-light); }
|
| 283 |
+
.module-icon.green { background: rgba(16, 185, 129, 0.2); color: var(--success); }
|
| 284 |
+
.module-icon.orange { background: rgba(249, 115, 22, 0.2); color: var(--warning); }
|
| 285 |
+
|
| 286 |
+
.module-info {
|
| 287 |
+
flex: 1;
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
.module-label {
|
| 291 |
+
font-family: 'JetBrains Mono', monospace;
|
| 292 |
+
font-size: 0.65rem;
|
| 293 |
+
color: var(--text-muted);
|
| 294 |
+
text-transform: uppercase;
|
| 295 |
+
letter-spacing: 1px;
|
| 296 |
+
margin-bottom: var(--space-xs);
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
.module-title {
|
| 300 |
+
font-size: 1.1rem;
|
| 301 |
+
font-weight: 700;
|
| 302 |
+
color: var(--text-primary);
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
.module-body {
|
| 306 |
+
padding: var(--space-lg);
|
| 307 |
+
flex: 1;
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
.module-desc {
|
| 311 |
+
font-size: 0.9rem;
|
| 312 |
+
color: var(--text-secondary);
|
| 313 |
+
line-height: 1.6;
|
| 314 |
+
margin-bottom: var(--space-md);
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
.module-meta {
|
| 318 |
+
display: flex;
|
| 319 |
+
flex-wrap: wrap;
|
| 320 |
+
gap: var(--space-xs);
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
.module-footer {
|
| 324 |
+
padding: var(--space-md) var(--space-lg);
|
| 325 |
+
background: var(--bg-tertiary);
|
| 326 |
+
display: flex;
|
| 327 |
+
align-items: center;
|
| 328 |
+
justify-content: space-between;
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
.module-arrow {
|
| 332 |
+
color: var(--primary-light);
|
| 333 |
+
transition: transform var(--transition-base);
|
| 334 |
+
}
|
| 335 |
+
|
| 336 |
+
.module-card:hover .module-arrow {
|
| 337 |
+
transform: translateX(5px);
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
/* TIMELINE SECTION */
|
| 341 |
+
.timeline {
|
| 342 |
+
padding: var(--space-3xl) var(--space-xl);
|
| 343 |
+
background: var(--bg-secondary);
|
| 344 |
+
border-top: 1px solid var(--border-color);
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
.timeline-container {
|
| 348 |
+
max-width: 800px;
|
| 349 |
+
margin: 0 auto;
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
.timeline-item {
|
| 353 |
+
display: flex;
|
| 354 |
+
gap: var(--space-lg);
|
| 355 |
+
padding: var(--space-md) 0;
|
| 356 |
+
position: relative;
|
| 357 |
+
}
|
| 358 |
+
|
| 359 |
+
.timeline-item:not(:last-child)::before {
|
| 360 |
+
content: '';
|
| 361 |
+
position: absolute;
|
| 362 |
+
left: 15px;
|
| 363 |
+
top: 45px;
|
| 364 |
+
bottom: 0;
|
| 365 |
+
width: 2px;
|
| 366 |
+
background: linear-gradient(180deg, var(--primary), var(--secondary));
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
.timeline-dot {
|
| 370 |
+
width: 32px;
|
| 371 |
+
height: 32px;
|
| 372 |
+
background: var(--bg-card);
|
| 373 |
+
border: 2px solid var(--primary);
|
| 374 |
+
border-radius: 50%;
|
| 375 |
+
display: flex;
|
| 376 |
+
align-items: center;
|
| 377 |
+
justify-content: center;
|
| 378 |
+
font-size: 0.75rem;
|
| 379 |
+
font-weight: 700;
|
| 380 |
+
color: var(--primary-light);
|
| 381 |
+
flex-shrink: 0;
|
| 382 |
+
z-index: 1;
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
.timeline-content {
|
| 386 |
+
flex: 1;
|
| 387 |
+
padding-bottom: var(--space-lg);
|
| 388 |
+
}
|
| 389 |
+
|
| 390 |
+
.timeline-time {
|
| 391 |
+
font-family: 'JetBrains Mono', monospace;
|
| 392 |
+
font-size: 0.75rem;
|
| 393 |
+
color: var(--primary-light);
|
| 394 |
+
margin-bottom: var(--space-xs);
|
| 395 |
+
}
|
| 396 |
+
|
| 397 |
+
.timeline-title {
|
| 398 |
+
font-size: 1rem;
|
| 399 |
+
font-weight: 600;
|
| 400 |
+
color: var(--text-primary);
|
| 401 |
+
margin-bottom: var(--space-xs);
|
| 402 |
+
}
|
| 403 |
+
|
| 404 |
+
.timeline-text {
|
| 405 |
+
font-size: 0.85rem;
|
| 406 |
+
color: var(--text-secondary);
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
/* CTA SECTION */
|
| 410 |
+
.cta {
|
| 411 |
+
padding: var(--space-3xl) var(--space-xl);
|
| 412 |
+
text-align: center;
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
.cta-box {
|
| 416 |
+
max-width: 700px;
|
| 417 |
+
margin: 0 auto;
|
| 418 |
+
padding: var(--space-3xl);
|
| 419 |
+
background: linear-gradient(135deg, var(--bg-card), var(--bg-tertiary));
|
| 420 |
+
border: 1px solid var(--border-color);
|
| 421 |
+
border-radius: var(--radius-xl);
|
| 422 |
+
position: relative;
|
| 423 |
+
overflow: hidden;
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
.cta-box::before {
|
| 427 |
+
content: '';
|
| 428 |
+
position: absolute;
|
| 429 |
+
top: -50%;
|
| 430 |
+
left: -50%;
|
| 431 |
+
width: 200%;
|
| 432 |
+
height: 200%;
|
| 433 |
+
background: radial-gradient(circle, rgba(99, 102, 241, 0.1) 0%, transparent 70%);
|
| 434 |
+
animation: rotate 20s linear infinite;
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
+
.cta-content {
|
| 438 |
+
position: relative;
|
| 439 |
+
z-index: 1;
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
.cta-title {
|
| 443 |
+
font-size: 2rem;
|
| 444 |
+
font-weight: 700;
|
| 445 |
+
color: var(--text-primary);
|
| 446 |
+
margin-bottom: var(--space-md);
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
.cta-text {
|
| 450 |
+
font-size: 1rem;
|
| 451 |
+
color: var(--text-secondary);
|
| 452 |
+
margin-bottom: var(--space-xl);
|
| 453 |
+
}
|
| 454 |
+
|
| 455 |
+
.cta-buttons {
|
| 456 |
+
display: flex;
|
| 457 |
+
gap: var(--space-md);
|
| 458 |
+
justify-content: center;
|
| 459 |
+
flex-wrap: wrap;
|
| 460 |
+
}
|
| 461 |
+
|
| 462 |
+
/* FLOATING SHAPES */
|
| 463 |
+
.floating-shape {
|
| 464 |
+
position: absolute;
|
| 465 |
+
border-radius: 50%;
|
| 466 |
+
opacity: 0.1;
|
| 467 |
+
animation: float 6s ease-in-out infinite;
|
| 468 |
+
}
|
| 469 |
+
|
| 470 |
+
.shape-1 {
|
| 471 |
+
width: 300px;
|
| 472 |
+
height: 300px;
|
| 473 |
+
background: var(--primary);
|
| 474 |
+
top: 10%;
|
| 475 |
+
right: -100px;
|
| 476 |
+
animation-delay: 0s;
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
.shape-2 {
|
| 480 |
+
width: 200px;
|
| 481 |
+
height: 200px;
|
| 482 |
+
background: var(--secondary);
|
| 483 |
+
bottom: 20%;
|
| 484 |
+
left: -50px;
|
| 485 |
+
animation-delay: 2s;
|
| 486 |
+
}
|
| 487 |
+
|
| 488 |
+
.shape-3 {
|
| 489 |
+
width: 150px;
|
| 490 |
+
height: 150px;
|
| 491 |
+
background: var(--accent);
|
| 492 |
+
top: 50%;
|
| 493 |
+
right: 10%;
|
| 494 |
+
animation-delay: 4s;
|
| 495 |
+
}
|
| 496 |
+
|
| 497 |
+
/* AUTHOR FOOTER */
|
| 498 |
+
.author-footer {
|
| 499 |
+
background: var(--bg-secondary);
|
| 500 |
+
border-top: 1px solid var(--border-color);
|
| 501 |
+
padding: var(--space-xl);
|
| 502 |
+
text-align: center;
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
.author-info {
|
| 506 |
+
display: flex;
|
| 507 |
+
justify-content: center;
|
| 508 |
+
gap: var(--space-xl);
|
| 509 |
+
flex-wrap: wrap;
|
| 510 |
+
margin-bottom: var(--space-md);
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
.author-link {
|
| 514 |
+
display: flex;
|
| 515 |
+
align-items: center;
|
| 516 |
+
gap: var(--space-sm);
|
| 517 |
+
color: var(--text-secondary);
|
| 518 |
+
text-decoration: none;
|
| 519 |
+
font-size: 0.9rem;
|
| 520 |
+
transition: color var(--transition-base);
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
+
.author-link:hover {
|
| 524 |
+
color: var(--primary-light);
|
| 525 |
+
}
|
| 526 |
+
|
| 527 |
+
.author-link svg {
|
| 528 |
+
width: 18px;
|
| 529 |
+
height: 18px;
|
| 530 |
+
fill: currentColor;
|
| 531 |
+
}
|
| 532 |
+
</style>
|
| 533 |
+
</head>
|
| 534 |
+
<body>
|
| 535 |
+
<!-- Particles Background -->
|
| 536 |
+
<div class="particles-container">
|
| 537 |
+
<div class="particle"></div>
|
| 538 |
+
<div class="particle"></div>
|
| 539 |
+
<div class="particle"></div>
|
| 540 |
+
<div class="particle"></div>
|
| 541 |
+
<div class="particle"></div>
|
| 542 |
+
<div class="particle"></div>
|
| 543 |
+
<div class="particle"></div>
|
| 544 |
+
<div class="particle"></div>
|
| 545 |
+
<div class="particle"></div>
|
| 546 |
+
</div>
|
| 547 |
+
|
| 548 |
+
<!-- Navigation -->
|
| 549 |
+
<nav class="navbar">
|
| 550 |
+
<a href="index.html" class="navbar-brand">
|
| 551 |
+
<div class="brand-logo">ML</div>
|
| 552 |
+
<span>ML Academy</span>
|
| 553 |
+
</a>
|
| 554 |
+
<div class="navbar-nav">
|
| 555 |
+
<a href="index.html" class="nav-link active">
|
| 556 |
+
<span class="nav-icon">[H]</span>
|
| 557 |
+
<span>Accueil</span>
|
| 558 |
+
</a>
|
| 559 |
+
<a href="cours.html" class="nav-link">
|
| 560 |
+
<span class="nav-icon">[C]</span>
|
| 561 |
+
<span>Cours</span>
|
| 562 |
+
</a>
|
| 563 |
+
<a href="tp.html" class="nav-link">
|
| 564 |
+
<span class="nav-icon">[T]</span>
|
| 565 |
+
<span>TPs</span>
|
| 566 |
+
</a>
|
| 567 |
+
<a href="feedback.html" class="nav-link">
|
| 568 |
+
<span class="nav-icon">[F]</span>
|
| 569 |
+
<span>Contact</span>
|
| 570 |
+
</a>
|
| 571 |
+
</div>
|
| 572 |
+
<div class="nav-badge">
|
| 573 |
+
<div class="dot"></div>
|
| 574 |
+
<span>Google Colab Ready</span>
|
| 575 |
+
</div>
|
| 576 |
+
</nav>
|
| 577 |
+
|
| 578 |
+
<!-- Page Wrapper -->
|
| 579 |
+
<div class="page-wrapper">
|
| 580 |
+
<!-- Hero Section -->
|
| 581 |
+
<section class="hero">
|
| 582 |
+
<div class="hero-bg"></div>
|
| 583 |
+
<div class="floating-shape shape-1"></div>
|
| 584 |
+
<div class="floating-shape shape-2"></div>
|
| 585 |
+
<div class="floating-shape shape-3"></div>
|
| 586 |
+
|
| 587 |
+
<div class="hero-eyebrow">
|
| 588 |
+
<div class="pulse"></div>
|
| 589 |
+
<span>Formation 2025/2026 — 100% Pratique</span>
|
| 590 |
+
</div>
|
| 591 |
+
|
| 592 |
+
<h1 class="hero-title">
|
| 593 |
+
Maitrisez le <span class="gradient-text">Machine Learning</span><br>
|
| 594 |
+
par la pratique
|
| 595 |
+
</h1>
|
| 596 |
+
|
| 597 |
+
<p class="hero-subtitle">
|
| 598 |
+
Apprenez les algorithmes ML essentiels a travers des projets concrets
|
| 599 |
+
avec des datasets reels de Kaggle. De zero a heros en quelques seances.
|
| 600 |
+
</p>
|
| 601 |
+
|
| 602 |
+
<div class="hero-cta">
|
| 603 |
+
<a href="cours.html" class="btn btn-primary btn-lg">
|
| 604 |
+
Commencer les cours
|
| 605 |
+
</a>
|
| 606 |
+
<a href="tp.html" class="btn btn-secondary btn-lg">
|
| 607 |
+
Voir les TPs
|
| 608 |
+
</a>
|
| 609 |
+
</div>
|
| 610 |
+
|
| 611 |
+
<div class="hero-stats">
|
| 612 |
+
<div class="hero-stat">
|
| 613 |
+
<div class="hero-stat-value">8<span>+</span></div>
|
| 614 |
+
<div class="hero-stat-label">Algorithmes</div>
|
| 615 |
+
</div>
|
| 616 |
+
<div class="hero-stat">
|
| 617 |
+
<div class="hero-stat-value">6<span></span></div>
|
| 618 |
+
<div class="hero-stat-label">TPs Complets</div>
|
| 619 |
+
</div>
|
| 620 |
+
<div class="hero-stat">
|
| 621 |
+
<div class="hero-stat-value">4<span></span></div>
|
| 622 |
+
<div class="hero-stat-label">Datasets Reels</div>
|
| 623 |
+
</div>
|
| 624 |
+
<div class="hero-stat">
|
| 625 |
+
<div class="hero-stat-value">0<span></span></div>
|
| 626 |
+
<div class="hero-stat-label">Installation</div>
|
| 627 |
+
</div>
|
| 628 |
+
</div>
|
| 629 |
+
</section>
|
| 630 |
+
|
| 631 |
+
<!-- Features Section -->
|
| 632 |
+
<section class="features">
|
| 633 |
+
<div class="section-header scroll-animate">
|
| 634 |
+
<div class="section-eyebrow">Pourquoi cette formation</div>
|
| 635 |
+
<h2 class="section-title">Ce que vous allez apprendre</h2>
|
| 636 |
+
<p class="section-subtitle">
|
| 637 |
+
Une approche progressive alliant theorie solide et pratique intensive
|
| 638 |
+
sur des problemes reels du monde de la data science.
|
| 639 |
+
</p>
|
| 640 |
+
</div>
|
| 641 |
+
|
| 642 |
+
<div class="features-grid">
|
| 643 |
+
<div class="feature-card scroll-animate">
|
| 644 |
+
<div class="feature-icon">D</div>
|
| 645 |
+
<h3 class="feature-title">Pretraitement des Donnees</h3>
|
| 646 |
+
<p class="feature-text">
|
| 647 |
+
Maitrisez le nettoyage, la normalisation et l'ingenierie des features
|
| 648 |
+
pour preparer vos donnees a l'entrainement.
|
| 649 |
+
</p>
|
| 650 |
+
<div class="feature-tags">
|
| 651 |
+
<span class="badge badge-primary">Pandas</span>
|
| 652 |
+
<span class="badge badge-secondary">NumPy</span>
|
| 653 |
+
<span class="badge badge-success">Scikit-learn</span>
|
| 654 |
+
</div>
|
| 655 |
+
</div>
|
| 656 |
+
|
| 657 |
+
<div class="feature-card scroll-animate">
|
| 658 |
+
<div class="feature-icon">A</div>
|
| 659 |
+
<h3 class="feature-title">Algorithmes de ML</h3>
|
| 660 |
+
<p class="feature-text">
|
| 661 |
+
Comprendre et implementer les algorithmes fondamentaux :
|
| 662 |
+
Regression, Classification, Clustering et Deep Learning.
|
| 663 |
+
</p>
|
| 664 |
+
<div class="feature-tags">
|
| 665 |
+
<span class="badge badge-primary">Regression</span>
|
| 666 |
+
<span class="badge badge-secondary">Random Forest</span>
|
| 667 |
+
<span class="badge badge-accent">Neural Networks</span>
|
| 668 |
+
</div>
|
| 669 |
+
</div>
|
| 670 |
+
|
| 671 |
+
<div class="feature-card scroll-animate">
|
| 672 |
+
<div class="feature-icon">E</div>
|
| 673 |
+
<h3 class="feature-title">Evaluation & Optimisation</h3>
|
| 674 |
+
<p class="feature-text">
|
| 675 |
+
Apprenez a mesurer la performance de vos modeles et a les optimiser
|
| 676 |
+
avec les bonnes metriques et techniques.
|
| 677 |
+
</p>
|
| 678 |
+
<div class="feature-tags">
|
| 679 |
+
<span class="badge badge-success">Cross-validation</span>
|
| 680 |
+
<span class="badge badge-warning">Grid Search</span>
|
| 681 |
+
<span class="badge badge-primary">Metriques</span>
|
| 682 |
+
</div>
|
| 683 |
+
</div>
|
| 684 |
+
|
| 685 |
+
<div class="feature-card scroll-animate">
|
| 686 |
+
<div class="feature-icon">P</div>
|
| 687 |
+
<h3 class="feature-title">Projets Concrets</h3>
|
| 688 |
+
<p class="feature-text">
|
| 689 |
+
Travaillez sur des datasets reels de Kaggle : Titanic, Housing,
|
| 690 |
+
Iris et bien d'autres pour construire votre portfolio.
|
| 691 |
+
</p>
|
| 692 |
+
<div class="feature-tags">
|
| 693 |
+
<span class="badge badge-success">Kaggle</span>
|
| 694 |
+
<span class="badge badge-accent">Portfolio</span>
|
| 695 |
+
<span class="badge badge-secondary">GitHub</span>
|
| 696 |
+
</div>
|
| 697 |
+
</div>
|
| 698 |
+
|
| 699 |
+
<div class="feature-card scroll-animate">
|
| 700 |
+
<div class="feature-icon">T</div>
|
| 701 |
+
<h3 class="feature-title">Series Temporelles</h3>
|
| 702 |
+
<p class="feature-text">
|
| 703 |
+
Decouvrez les techniques specifiques pour predire des donnees
|
| 704 |
+
temporelles avec LSTM et les modeles ARIMA.
|
| 705 |
+
</p>
|
| 706 |
+
<div class="feature-tags">
|
| 707 |
+
<span class="badge badge-primary">LSTM</span>
|
| 708 |
+
<span class="badge badge-secondary">TensorFlow</span>
|
| 709 |
+
<span class="badge badge-warning">Time Series</span>
|
| 710 |
+
</div>
|
| 711 |
+
</div>
|
| 712 |
+
|
| 713 |
+
<div class="feature-card scroll-animate">
|
| 714 |
+
<div class="feature-icon">X</div>
|
| 715 |
+
<h3 class="feature-title">Deploiement</h3>
|
| 716 |
+
<p class="feature-text">
|
| 717 |
+
Apprenez a mettre vos modeles en production avec des API
|
| 718 |
+
et des interfaces web interactives.
|
| 719 |
+
</p>
|
| 720 |
+
<div class="feature-tags">
|
| 721 |
+
<span class="badge badge-success">FastAPI</span>
|
| 722 |
+
<span class="badge badge-primary">Streamlit</span>
|
| 723 |
+
<span class="badge badge-secondary">Docker</span>
|
| 724 |
+
</div>
|
| 725 |
+
</div>
|
| 726 |
+
</div>
|
| 727 |
+
</section>
|
| 728 |
+
|
| 729 |
+
<!-- Modules Section -->
|
| 730 |
+
<section class="modules">
|
| 731 |
+
<div class="section-header scroll-animate">
|
| 732 |
+
<div class="section-eyebrow">Parcours de formation</div>
|
| 733 |
+
<h2 class="section-title">Accedez aux modules</h2>
|
| 734 |
+
<p class="section-subtitle">
|
| 735 |
+
Trois espaces dedies pour une progression optimale dans votre apprentissage.
|
| 736 |
+
</p>
|
| 737 |
+
</div>
|
| 738 |
+
|
| 739 |
+
<div class="modules-grid">
|
| 740 |
+
<a href="cours.html" class="module-card scroll-animate">
|
| 741 |
+
<div class="module-header">
|
| 742 |
+
<div class="module-icon blue">C</div>
|
| 743 |
+
<div class="module-info">
|
| 744 |
+
<div class="module-label">Module 1</div>
|
| 745 |
+
<h3 class="module-title">Cours Theoriques</h3>
|
| 746 |
+
</div>
|
| 747 |
+
</div>
|
| 748 |
+
<div class="module-body">
|
| 749 |
+
<p class="module-desc">
|
| 750 |
+
Contenu theorique complet avec equations mathematiques,
|
| 751 |
+
explications detaillees et exemples de code Python annote.
|
| 752 |
+
</p>
|
| 753 |
+
<div class="module-meta">
|
| 754 |
+
<span class="badge badge-primary">Theorie</span>
|
| 755 |
+
<span class="badge badge-secondary">Mathematiques</span>
|
| 756 |
+
<span class="badge badge-success">Python</span>
|
| 757 |
+
</div>
|
| 758 |
+
</div>
|
| 759 |
+
<div class="module-footer">
|
| 760 |
+
<span style="font-size: 0.8rem; color: var(--text-muted);">8 chapitres</span>
|
| 761 |
+
<span class="module-arrow">→</span>
|
| 762 |
+
</div>
|
| 763 |
+
</a>
|
| 764 |
+
|
| 765 |
+
<a href="tp.html" class="module-card scroll-animate">
|
| 766 |
+
<div class="module-header">
|
| 767 |
+
<div class="module-icon green">T</div>
|
| 768 |
+
<div class="module-info">
|
| 769 |
+
<div class="module-label">Module 2</div>
|
| 770 |
+
<h3 class="module-title">Travaux Pratiques</h3>
|
| 771 |
+
</div>
|
| 772 |
+
</div>
|
| 773 |
+
<div class="module-body">
|
| 774 |
+
<p class="module-desc">
|
| 775 |
+
6 notebooks Google Colab guides etape par etape sur des datasets
|
| 776 |
+
reels de Kaggle. Pret a executer sans installation.
|
| 777 |
+
</p>
|
| 778 |
+
<div class="module-meta">
|
| 779 |
+
<span class="badge badge-success">Google Colab</span>
|
| 780 |
+
<span class="badge badge-accent">Guide</span>
|
| 781 |
+
<span class="badge badge-warning">Kaggle</span>
|
| 782 |
+
</div>
|
| 783 |
+
</div>
|
| 784 |
+
<div class="module-footer">
|
| 785 |
+
<span style="font-size: 0.8rem; color: var(--text-muted);">6 notebooks</span>
|
| 786 |
+
<span class="module-arrow">→</span>
|
| 787 |
+
</div>
|
| 788 |
+
</a>
|
| 789 |
+
|
| 790 |
+
<a href="feedback.html" class="module-card scroll-animate">
|
| 791 |
+
<div class="module-header">
|
| 792 |
+
<div class="module-icon orange">F</div>
|
| 793 |
+
<div class="module-info">
|
| 794 |
+
<div class="module-label">Module 3</div>
|
| 795 |
+
<h3 class="module-title">Questions & Feedback</h3>
|
| 796 |
+
</div>
|
| 797 |
+
</div>
|
| 798 |
+
<div class="module-body">
|
| 799 |
+
<p class="module-desc">
|
| 800 |
+
Posez vos questions, evaluez la formation et accedez a la FAQ
|
| 801 |
+
pour resoudre vos doutes rapidement.
|
| 802 |
+
</p>
|
| 803 |
+
<div class="module-meta">
|
| 804 |
+
<span class="badge badge-primary">FAQ</span>
|
| 805 |
+
<span class="badge badge-secondary">Support</span>
|
| 806 |
+
<span class="badge badge-success">Feedback</span>
|
| 807 |
+
</div>
|
| 808 |
+
</div>
|
| 809 |
+
<div class="module-footer">
|
| 810 |
+
<span style="font-size: 0.8rem; color: var(--text-muted);">Reponses 24h</span>
|
| 811 |
+
<span class="module-arrow">→</span>
|
| 812 |
+
</div>
|
| 813 |
+
</a>
|
| 814 |
+
</div>
|
| 815 |
+
</section>
|
| 816 |
+
|
| 817 |
+
<!-- Timeline Section -->
|
| 818 |
+
<section class="timeline">
|
| 819 |
+
<div class="section-header scroll-animate">
|
| 820 |
+
<div class="section-eyebrow">Organisation</div>
|
| 821 |
+
<h2 class="section-title">Plan de la formation</h2>
|
| 822 |
+
<p class="section-subtitle">
|
| 823 |
+
Un parcours progressif de 8 seances pour maitriser le Machine Learning.
|
| 824 |
+
</p>
|
| 825 |
+
</div>
|
| 826 |
+
|
| 827 |
+
<div class="timeline-container">
|
| 828 |
+
<div class="timeline-item scroll-animate">
|
| 829 |
+
<div class="timeline-dot">1</div>
|
| 830 |
+
<div class="timeline-content">
|
| 831 |
+
<div class="timeline-time">Seance 1 — 2h</div>
|
| 832 |
+
<h3 class="timeline-title">Introduction au ML & Python</h3>
|
| 833 |
+
<p class="timeline-text">
|
| 834 |
+
Fondamentaux du Machine Learning, environnement Python,
|
| 835 |
+
NumPy et Pandas pour la manipulation de donnees.
|
| 836 |
+
</p>
|
| 837 |
+
</div>
|
| 838 |
+
</div>
|
| 839 |
+
|
| 840 |
+
<div class="timeline-item scroll-animate">
|
| 841 |
+
<div class="timeline-dot">2</div>
|
| 842 |
+
<div class="timeline-content">
|
| 843 |
+
<div class="timeline-time">Seance 2 — 2h</div>
|
| 844 |
+
<h3 class="timeline-title">Pretraitement des Donnees</h3>
|
| 845 |
+
<p class="timeline-text">
|
| 846 |
+
Nettoyage, normalisation, encodage des variables categorielles
|
| 847 |
+
et feature engineering.
|
| 848 |
+
</p>
|
| 849 |
+
</div>
|
| 850 |
+
</div>
|
| 851 |
+
|
| 852 |
+
<div class="timeline-item scroll-animate">
|
| 853 |
+
<div class="timeline-dot">3</div>
|
| 854 |
+
<div class="timeline-content">
|
| 855 |
+
<div class="timeline-time">Seance 3 — 2h</div>
|
| 856 |
+
<h3 class="timeline-title">Regression Lineaire & Logistique</h3>
|
| 857 |
+
<p class="timeline-text">
|
| 858 |
+
Algorithmes de base, equations mathematiques,
|
| 859 |
+
implementation avec scikit-learn.
|
| 860 |
+
</p>
|
| 861 |
+
</div>
|
| 862 |
+
</div>
|
| 863 |
+
|
| 864 |
+
<div class="timeline-item scroll-animate">
|
| 865 |
+
<div class="timeline-dot">4</div>
|
| 866 |
+
<div class="timeline-content">
|
| 867 |
+
<div class="timeline-time">Seance 4 — 2h</div>
|
| 868 |
+
<h3 class="timeline-title">Arbres de Decision & Random Forest</h3>
|
| 869 |
+
<p class="timeline-text">
|
| 870 |
+
Classification avec arbres, bagging, boosting et
|
| 871 |
+
importance des features.
|
| 872 |
+
</p>
|
| 873 |
+
</div>
|
| 874 |
+
</div>
|
| 875 |
+
|
| 876 |
+
<div class="timeline-item scroll-animate">
|
| 877 |
+
<div class="timeline-dot">5</div>
|
| 878 |
+
<div class="timeline-content">
|
| 879 |
+
<div class="timeline-time">Seance 5 — 2h</div>
|
| 880 |
+
<h3 class="timeline-title">Reseaux de Neurones avec Keras</h3>
|
| 881 |
+
<p class="timeline-text">
|
| 882 |
+
Introduction au Deep Learning, perceptron multicouche,
|
| 883 |
+
activation et backpropagation.
|
| 884 |
+
</p>
|
| 885 |
+
</div>
|
| 886 |
+
</div>
|
| 887 |
+
|
| 888 |
+
<div class="timeline-item scroll-animate">
|
| 889 |
+
<div class="timeline-dot">6</div>
|
| 890 |
+
<div class="timeline-content">
|
| 891 |
+
<div class="timeline-time">Seance 6 — 2h</div>
|
| 892 |
+
<h3 class="timeline-title">Series Temporelles & LSTM</h3>
|
| 893 |
+
<p class="timeline-text">
|
| 894 |
+
Prediction de donnees temporelles, reseaux recurrents
|
| 895 |
+
et modeles LSTM avec TensorFlow.
|
| 896 |
+
</p>
|
| 897 |
+
</div>
|
| 898 |
+
</div>
|
| 899 |
+
|
| 900 |
+
<div class="timeline-item scroll-animate">
|
| 901 |
+
<div class="timeline-dot">7</div>
|
| 902 |
+
<div class="timeline-content">
|
| 903 |
+
<div class="timeline-time">Seance 7 — 2h</div>
|
| 904 |
+
<h3 class="timeline-title">Evaluation & Optimisation</h3>
|
| 905 |
+
<p class="timeline-text">
|
| 906 |
+
Metriques de performance, cross-validation,
|
| 907 |
+
grid search et eviter l'overfitting.
|
| 908 |
+
</p>
|
| 909 |
+
</div>
|
| 910 |
+
</div>
|
| 911 |
+
|
| 912 |
+
<div class="timeline-item scroll-animate">
|
| 913 |
+
<div class="timeline-dot">8</div>
|
| 914 |
+
<div class="timeline-content">
|
| 915 |
+
<div class="timeline-time">Seance 8 — 2h</div>
|
| 916 |
+
<h3 class="timeline-title">Projet Final & Deploiement</h3>
|
| 917 |
+
<p class="timeline-text">
|
| 918 |
+
Realisation d'un projet complet et mise en production
|
| 919 |
+
avec une API simple.
|
| 920 |
+
</p>
|
| 921 |
+
</div>
|
| 922 |
+
</div>
|
| 923 |
+
</div>
|
| 924 |
+
</section>
|
| 925 |
+
|
| 926 |
+
<!-- CTA Section -->
|
| 927 |
+
<section class="cta">
|
| 928 |
+
<div class="cta-box scroll-animate">
|
| 929 |
+
<div class="cta-content">
|
| 930 |
+
<h2 class="cta-title">Pret a commencer ?</h2>
|
| 931 |
+
<p class="cta-text">
|
| 932 |
+
Rejoignez des centaines d'etudiants qui ont deja maitrise
|
| 933 |
+
le Machine Learning avec notre formation.
|
| 934 |
+
</p>
|
| 935 |
+
<div class="cta-buttons">
|
| 936 |
+
<a href="cours.html" class="btn btn-primary btn-lg">
|
| 937 |
+
Commencer maintenant
|
| 938 |
+
</a>
|
| 939 |
+
<a href="tp.html" class="btn btn-outline btn-lg">
|
| 940 |
+
Voir les notebooks
|
| 941 |
+
</a>
|
| 942 |
+
</div>
|
| 943 |
+
</div>
|
| 944 |
+
</div>
|
| 945 |
+
</section>
|
| 946 |
+
|
| 947 |
+
<!-- Author Footer -->
|
| 948 |
+
<footer class="author-footer">
|
| 949 |
+
<div class="author-info">
|
| 950 |
+
<a href="mailto:imadmaalouf02@gmail.com" class="author-link">
|
| 951 |
+
<svg viewBox="0 0 24 24"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>
|
| 952 |
+
imadmaalouf02@gmail.com
|
| 953 |
+
</a>
|
| 954 |
+
<a href="https://github.com/imadmaalouf02" target="_blank" class="author-link">
|
| 955 |
+
<svg viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
| 956 |
+
GitHub
|
| 957 |
+
</a>
|
| 958 |
+
<a href="https://huggingface.co/spaces/MAALOOUF/ML_Training" target="_blank" class="author-link">
|
| 959 |
+
<svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
|
| 960 |
+
Hugging Face Space
|
| 961 |
+
</a>
|
| 962 |
+
</div>
|
| 963 |
+
</footer>
|
| 964 |
+
|
| 965 |
+
<!-- Footer -->
|
| 966 |
+
<footer class="footer">
|
| 967 |
+
<p class="footer-text">
|
| 968 |
+
ML Academy — Formation Machine Learning —
|
| 969 |
+
<span class="footer-brand">GE-MCI 4A</span> — Promotion 2025/2026
|
| 970 |
+
</p>
|
| 971 |
+
<p class="footer-text" style="margin-top: var(--space-sm);">
|
| 972 |
+
Google Colab · Python · Scikit-learn · TensorFlow · Kaggle
|
| 973 |
+
</p>
|
| 974 |
+
<p class="footer-text" style="margin-top: var(--space-sm); font-size: 0.75rem; color: var(--text-muted);">
|
| 975 |
+
Formateur : Imad Maalouf
|
| 976 |
+
</p>
|
| 977 |
+
</footer>
|
| 978 |
+
</div>
|
| 979 |
+
|
| 980 |
+
<!-- Scripts -->
|
| 981 |
+
<script src="js/shared.js"></script>
|
| 982 |
+
<script>
|
| 983 |
+
// Scroll animations
|
| 984 |
+
const observerOptions = {
|
| 985 |
+
threshold: 0.1,
|
| 986 |
+
rootMargin: '0px 0px -50px 0px'
|
| 987 |
+
};
|
| 988 |
+
|
| 989 |
+
const observer = new IntersectionObserver((entries) => {
|
| 990 |
+
entries.forEach(entry => {
|
| 991 |
+
if (entry.isIntersecting) {
|
| 992 |
+
entry.target.classList.add('visible');
|
| 993 |
+
}
|
| 994 |
+
});
|
| 995 |
+
}, observerOptions);
|
| 996 |
+
|
| 997 |
+
document.querySelectorAll('.scroll-animate').forEach(el => {
|
| 998 |
+
observer.observe(el);
|
| 999 |
+
});
|
| 1000 |
+
|
| 1001 |
+
// Stagger animation for cards
|
| 1002 |
+
document.querySelectorAll('.features-grid, .modules-grid').forEach(grid => {
|
| 1003 |
+
const cards = grid.querySelectorAll('.feature-card, .module-card');
|
| 1004 |
+
cards.forEach((card, index) => {
|
| 1005 |
+
card.style.animationDelay = `${index * 0.1}s`;
|
| 1006 |
+
});
|
| 1007 |
+
});
|
| 1008 |
+
</script>
|
| 1009 |
+
</body>
|
| 1010 |
</html>
|
js/feedback-storage.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 2 |
+
ML ACADEMY — FEEDBACK STORAGE SYSTEM
|
| 3 |
+
Stocke les feedbacks au format JSON pour traitement ulterieur
|
| 4 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 5 |
+
|
| 6 |
+
class FeedbackStorage {
|
| 7 |
+
constructor() {
|
| 8 |
+
this.storageKey = 'ml_academy_feedbacks';
|
| 9 |
+
this.feedbacks = this.loadFeedbacks();
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
// Charge tous les feedbacks depuis le stockage
|
| 13 |
+
loadFeedbacks() {
|
| 14 |
+
try {
|
| 15 |
+
const stored = localStorage.getItem(this.storageKey);
|
| 16 |
+
return stored ? JSON.parse(stored) : [];
|
| 17 |
+
} catch (e) {
|
| 18 |
+
console.error('Erreur lors du chargement des feedbacks:', e);
|
| 19 |
+
return [];
|
| 20 |
+
}
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
// Sauvegarde tous les feedbacks
|
| 24 |
+
saveFeedbacks() {
|
| 25 |
+
try {
|
| 26 |
+
localStorage.setItem(this.storageKey, JSON.stringify(this.feedbacks));
|
| 27 |
+
return true;
|
| 28 |
+
} catch (e) {
|
| 29 |
+
console.error('Erreur lors de la sauvegarde des feedbacks:', e);
|
| 30 |
+
return false;
|
| 31 |
+
}
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
// Ajoute un nouveau feedback
|
| 35 |
+
addFeedback(feedbackData) {
|
| 36 |
+
const feedback = {
|
| 37 |
+
id: this.generateId(),
|
| 38 |
+
timestamp: new Date().toISOString(),
|
| 39 |
+
...feedbackData
|
| 40 |
+
};
|
| 41 |
+
|
| 42 |
+
this.feedbacks.push(feedback);
|
| 43 |
+
this.saveFeedbacks();
|
| 44 |
+
|
| 45 |
+
// Exporte automatiquement vers un fichier JSON telechargeable
|
| 46 |
+
this.exportToFile();
|
| 47 |
+
|
| 48 |
+
return feedback;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
// Genere un ID unique
|
| 52 |
+
generateId() {
|
| 53 |
+
return 'fb_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
// Recupere tous les feedbacks
|
| 57 |
+
getAllFeedbacks() {
|
| 58 |
+
return this.feedbacks;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
// Recupere les feedbacks par date
|
| 62 |
+
getFeedbacksByDateRange(startDate, endDate) {
|
| 63 |
+
return this.feedbacks.filter(fb => {
|
| 64 |
+
const fbDate = new Date(fb.timestamp);
|
| 65 |
+
return fbDate >= startDate && fbDate <= endDate;
|
| 66 |
+
});
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
// Recupere les statistiques
|
| 70 |
+
getStatistics() {
|
| 71 |
+
if (this.feedbacks.length === 0) {
|
| 72 |
+
return {
|
| 73 |
+
total: 0,
|
| 74 |
+
averageRating: 0,
|
| 75 |
+
difficultyDistribution: {},
|
| 76 |
+
commonDifficulties: [],
|
| 77 |
+
commonSuggestions: []
|
| 78 |
+
};
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
const ratings = this.feedbacks.map(fb => parseInt(fb.rating) || 0);
|
| 82 |
+
const averageRating = ratings.reduce((a, b) => a + b, 0) / ratings.length;
|
| 83 |
+
|
| 84 |
+
// Distribution des difficultes
|
| 85 |
+
const difficultyDistribution = {};
|
| 86 |
+
this.feedbacks.forEach(fb => {
|
| 87 |
+
const diff = fb.difficulty || 'non-specifie';
|
| 88 |
+
difficultyDistribution[diff] = (difficultyDistribution[diff] || 0) + 1;
|
| 89 |
+
});
|
| 90 |
+
|
| 91 |
+
// Points difficiles communs
|
| 92 |
+
const difficultyCount = {};
|
| 93 |
+
this.feedbacks.forEach(fb => {
|
| 94 |
+
if (fb.difficiles && Array.isArray(fb.difficiles)) {
|
| 95 |
+
fb.difficiles.forEach(d => {
|
| 96 |
+
difficultyCount[d] = (difficultyCount[d] || 0) + 1;
|
| 97 |
+
});
|
| 98 |
+
}
|
| 99 |
+
});
|
| 100 |
+
const commonDifficulties = Object.entries(difficultyCount)
|
| 101 |
+
.sort((a, b) => b[1] - a[1])
|
| 102 |
+
.slice(0, 5);
|
| 103 |
+
|
| 104 |
+
// Suggestions communes
|
| 105 |
+
const suggestionCount = {};
|
| 106 |
+
this.feedbacks.forEach(fb => {
|
| 107 |
+
if (fb.suggestions && Array.isArray(fb.suggestions)) {
|
| 108 |
+
fb.suggestions.forEach(s => {
|
| 109 |
+
suggestionCount[s] = (suggestionCount[s] || 0) + 1;
|
| 110 |
+
});
|
| 111 |
+
}
|
| 112 |
+
});
|
| 113 |
+
const commonSuggestions = Object.entries(suggestionCount)
|
| 114 |
+
.sort((a, b) => b[1] - a[1])
|
| 115 |
+
.slice(0, 5);
|
| 116 |
+
|
| 117 |
+
return {
|
| 118 |
+
total: this.feedbacks.length,
|
| 119 |
+
averageRating: averageRating.toFixed(2),
|
| 120 |
+
difficultyDistribution,
|
| 121 |
+
commonDifficulties,
|
| 122 |
+
commonSuggestions
|
| 123 |
+
};
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
// Exporte les feedbacks vers un fichier JSON
|
| 127 |
+
exportToFile() {
|
| 128 |
+
const data = {
|
| 129 |
+
exportDate: new Date().toISOString(),
|
| 130 |
+
totalFeedbacks: this.feedbacks.length,
|
| 131 |
+
feedbacks: this.feedbacks,
|
| 132 |
+
statistics: this.getStatistics()
|
| 133 |
+
};
|
| 134 |
+
|
| 135 |
+
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
|
| 136 |
+
const url = URL.createObjectURL(blob);
|
| 137 |
+
|
| 138 |
+
// Stocke l'URL pour telechargement ulterieur
|
| 139 |
+
this.lastExportUrl = url;
|
| 140 |
+
|
| 141 |
+
return url;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
// Telecharge le fichier JSON
|
| 145 |
+
downloadFeedbacks() {
|
| 146 |
+
const url = this.exportToFile();
|
| 147 |
+
const a = document.createElement('a');
|
| 148 |
+
a.href = url;
|
| 149 |
+
a.download = `ml_academy_feedbacks_${new Date().toISOString().split('T')[0]}.json`;
|
| 150 |
+
document.body.appendChild(a);
|
| 151 |
+
a.click();
|
| 152 |
+
document.body.removeChild(a);
|
| 153 |
+
URL.revokeObjectURL(url);
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
// Exporte vers CSV pour Excel
|
| 157 |
+
exportToCSV() {
|
| 158 |
+
if (this.feedbacks.length === 0) return null;
|
| 159 |
+
|
| 160 |
+
const headers = [
|
| 161 |
+
'ID', 'Date', 'Nom', 'Email', 'Projet',
|
| 162 |
+
'Note', 'Difficulte', 'Rythme',
|
| 163 |
+
'Parties Utiles', 'Points Difficiles',
|
| 164 |
+
'Question Principale', 'Commentaire'
|
| 165 |
+
];
|
| 166 |
+
|
| 167 |
+
const rows = this.feedbacks.map(fb => [
|
| 168 |
+
fb.id,
|
| 169 |
+
fb.timestamp,
|
| 170 |
+
fb.name || '',
|
| 171 |
+
fb.email || '',
|
| 172 |
+
fb.project || '',
|
| 173 |
+
fb.rating || '',
|
| 174 |
+
fb.difficulty || '',
|
| 175 |
+
fb.rythme || '',
|
| 176 |
+
(fb.utiles || []).join(';'),
|
| 177 |
+
(fb.difficiles || []).join(';'),
|
| 178 |
+
(fb.mainQuestion || '').replace(/"/g, '""'),
|
| 179 |
+
(fb.freeComment || '').replace(/"/g, '""')
|
| 180 |
+
]);
|
| 181 |
+
|
| 182 |
+
const csv = [
|
| 183 |
+
headers.join(','),
|
| 184 |
+
...rows.map(row => row.map(cell => `"${cell}"`).join(','))
|
| 185 |
+
].join('\n');
|
| 186 |
+
|
| 187 |
+
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
| 188 |
+
const url = URL.createObjectURL(blob);
|
| 189 |
+
|
| 190 |
+
const a = document.createElement('a');
|
| 191 |
+
a.href = url;
|
| 192 |
+
a.download = `ml_academy_feedbacks_${new Date().toISOString().split('T')[0]}.csv`;
|
| 193 |
+
document.body.appendChild(a);
|
| 194 |
+
a.click();
|
| 195 |
+
document.body.removeChild(a);
|
| 196 |
+
URL.revokeObjectURL(url);
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
// Efface tous les feedbacks (avec confirmation)
|
| 200 |
+
clearAll() {
|
| 201 |
+
if (confirm('Attention : Cette action supprimera tous les feedbacks. Continuer ?')) {
|
| 202 |
+
this.feedbacks = [];
|
| 203 |
+
this.saveFeedbacks();
|
| 204 |
+
return true;
|
| 205 |
+
}
|
| 206 |
+
return false;
|
| 207 |
+
}
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
// Instance globale
|
| 211 |
+
const feedbackStorage = new FeedbackStorage();
|
| 212 |
+
|
| 213 |
+
// Fonction pour soumettre un feedback depuis le formulaire
|
| 214 |
+
function submitFeedback(formData) {
|
| 215 |
+
const feedback = feedbackStorage.addFeedback(formData);
|
| 216 |
+
console.log('Feedback enregistre:', feedback);
|
| 217 |
+
return feedback;
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
// Fonction pour afficher les statistiques dans la console
|
| 221 |
+
function showFeedbackStats() {
|
| 222 |
+
const stats = feedbackStorage.getStatistics();
|
| 223 |
+
console.log('=== Statistiques des Feedbacks ===');
|
| 224 |
+
console.log(`Total: ${stats.total}`);
|
| 225 |
+
console.log(`Note moyenne: ${stats.averageRating}/5`);
|
| 226 |
+
console.log('Distribution des difficultes:', stats.difficultyDistribution);
|
| 227 |
+
console.log('Points difficiles communs:', stats.commonDifficulties);
|
| 228 |
+
console.log('Suggestions communes:', stats.commonSuggestions);
|
| 229 |
+
return stats;
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
// Exporte pour utilisation externe
|
| 233 |
+
window.FeedbackStorage = FeedbackStorage;
|
| 234 |
+
window.feedbackStorage = feedbackStorage;
|
| 235 |
+
window.submitFeedback = submitFeedback;
|
| 236 |
+
window.showFeedbackStats = showFeedbackStats;
|
js/shared.js
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 2 |
+
ML ACADEMY — SHARED JAVASCRIPT
|
| 3 |
+
Animations et interactions communes à toutes les pages
|
| 4 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 5 |
+
|
| 6 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 7 |
+
// NAVIGATION ACTIVE STATE
|
| 8 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 9 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 10 |
+
// Mark active nav link based on current page
|
| 11 |
+
const currentPage = window.location.pathname.split('/').pop() || 'index.html';
|
| 12 |
+
|
| 13 |
+
document.querySelectorAll('.nav-link').forEach(link => {
|
| 14 |
+
const href = link.getAttribute('href');
|
| 15 |
+
if (href === currentPage || (currentPage === '' && href === 'index.html')) {
|
| 16 |
+
link.classList.add('active');
|
| 17 |
+
} else {
|
| 18 |
+
link.classList.remove('active');
|
| 19 |
+
}
|
| 20 |
+
});
|
| 21 |
+
});
|
| 22 |
+
|
| 23 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 24 |
+
// SMOOTH SCROLL FOR ANCHOR LINKS
|
| 25 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 26 |
+
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
| 27 |
+
anchor.addEventListener('click', function(e) {
|
| 28 |
+
e.preventDefault();
|
| 29 |
+
const target = document.querySelector(this.getAttribute('href'));
|
| 30 |
+
if (target) {
|
| 31 |
+
const offsetTop = target.offsetTop - 100; // Account for fixed navbar
|
| 32 |
+
window.scrollTo({
|
| 33 |
+
top: offsetTop,
|
| 34 |
+
behavior: 'smooth'
|
| 35 |
+
});
|
| 36 |
+
}
|
| 37 |
+
});
|
| 38 |
+
});
|
| 39 |
+
|
| 40 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 41 |
+
// SCROLL ANIMATIONS OBSERVER
|
| 42 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 43 |
+
const scrollObserverOptions = {
|
| 44 |
+
root: null,
|
| 45 |
+
rootMargin: '0px 0px -100px 0px',
|
| 46 |
+
threshold: 0.1
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
const scrollObserver = new IntersectionObserver((entries) => {
|
| 50 |
+
entries.forEach(entry => {
|
| 51 |
+
if (entry.isIntersecting) {
|
| 52 |
+
entry.target.classList.add('visible');
|
| 53 |
+
|
| 54 |
+
// Add stagger delay for child elements if needed
|
| 55 |
+
const staggerChildren = entry.target.querySelectorAll('.stagger-child');
|
| 56 |
+
staggerChildren.forEach((child, index) => {
|
| 57 |
+
child.style.animationDelay = `${index * 0.1}s`;
|
| 58 |
+
child.classList.add('animate-in');
|
| 59 |
+
});
|
| 60 |
+
}
|
| 61 |
+
});
|
| 62 |
+
}, scrollObserverOptions);
|
| 63 |
+
|
| 64 |
+
// Observe all elements with scroll-animate class
|
| 65 |
+
document.querySelectorAll('.scroll-animate').forEach(el => {
|
| 66 |
+
scrollObserver.observe(el);
|
| 67 |
+
});
|
| 68 |
+
|
| 69 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 70 |
+
// NAVBAR SCROLL EFFECT
|
| 71 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 72 |
+
let lastScrollY = window.scrollY;
|
| 73 |
+
let ticking = false;
|
| 74 |
+
|
| 75 |
+
function updateNavbar() {
|
| 76 |
+
const navbar = document.querySelector('.navbar');
|
| 77 |
+
|
| 78 |
+
if (window.scrollY > 50) {
|
| 79 |
+
navbar.style.background = 'rgba(15, 15, 26, 0.95)';
|
| 80 |
+
navbar.style.boxShadow = '0 4px 20px rgba(0, 0, 0, 0.3)';
|
| 81 |
+
} else {
|
| 82 |
+
navbar.style.background = 'rgba(15, 15, 26, 0.85)';
|
| 83 |
+
navbar.style.boxShadow = 'none';
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
ticking = false;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
window.addEventListener('scroll', () => {
|
| 90 |
+
lastScrollY = window.scrollY;
|
| 91 |
+
|
| 92 |
+
if (!ticking) {
|
| 93 |
+
window.requestAnimationFrame(updateNavbar);
|
| 94 |
+
ticking = true;
|
| 95 |
+
}
|
| 96 |
+
});
|
| 97 |
+
|
| 98 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 99 |
+
// PARALLAX EFFECT FOR HERO BACKGROUND
|
| 100 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 101 |
+
const heroBg = document.querySelector('.hero-bg');
|
| 102 |
+
if (heroBg) {
|
| 103 |
+
window.addEventListener('scroll', () => {
|
| 104 |
+
const scrolled = window.scrollY;
|
| 105 |
+
heroBg.style.transform = `translateY(${scrolled * 0.3}px)`;
|
| 106 |
+
});
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 110 |
+
// TYPING EFFECT FOR HERO TEXT (optional)
|
| 111 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 112 |
+
function typeWriter(element, text, speed = 50) {
|
| 113 |
+
let i = 0;
|
| 114 |
+
element.textContent = '';
|
| 115 |
+
|
| 116 |
+
function type() {
|
| 117 |
+
if (i < text.length) {
|
| 118 |
+
element.textContent += text.charAt(i);
|
| 119 |
+
i++;
|
| 120 |
+
setTimeout(type, speed);
|
| 121 |
+
}
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
type();
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 128 |
+
// COUNTER ANIMATION FOR STATS
|
| 129 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 130 |
+
function animateCounter(element, target, duration = 2000) {
|
| 131 |
+
let start = 0;
|
| 132 |
+
const increment = target / (duration / 16);
|
| 133 |
+
|
| 134 |
+
function updateCounter() {
|
| 135 |
+
start += increment;
|
| 136 |
+
if (start < target) {
|
| 137 |
+
element.textContent = Math.floor(start);
|
| 138 |
+
requestAnimationFrame(updateCounter);
|
| 139 |
+
} else {
|
| 140 |
+
element.textContent = target;
|
| 141 |
+
}
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
updateCounter();
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
// Observe stat elements and animate when visible
|
| 148 |
+
const statObserver = new IntersectionObserver((entries) => {
|
| 149 |
+
entries.forEach(entry => {
|
| 150 |
+
if (entry.isIntersecting && !entry.target.classList.contains('counted')) {
|
| 151 |
+
entry.target.classList.add('counted');
|
| 152 |
+
const target = parseInt(entry.target.dataset.target);
|
| 153 |
+
if (!isNaN(target)) {
|
| 154 |
+
animateCounter(entry.target, target);
|
| 155 |
+
}
|
| 156 |
+
}
|
| 157 |
+
});
|
| 158 |
+
}, { threshold: 0.5 });
|
| 159 |
+
|
| 160 |
+
document.querySelectorAll('[data-target]').forEach(el => {
|
| 161 |
+
statObserver.observe(el);
|
| 162 |
+
});
|
| 163 |
+
|
| 164 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 165 |
+
// MAGNETIC BUTTON EFFECT
|
| 166 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 167 |
+
document.querySelectorAll('.btn').forEach(button => {
|
| 168 |
+
button.addEventListener('mousemove', (e) => {
|
| 169 |
+
const rect = button.getBoundingClientRect();
|
| 170 |
+
const x = e.clientX - rect.left - rect.width / 2;
|
| 171 |
+
const y = e.clientY - rect.top - rect.height / 2;
|
| 172 |
+
|
| 173 |
+
button.style.transform = `translate(${x * 0.1}px, ${y * 0.1}px)`;
|
| 174 |
+
});
|
| 175 |
+
|
| 176 |
+
button.addEventListener('mouseleave', () => {
|
| 177 |
+
button.style.transform = '';
|
| 178 |
+
});
|
| 179 |
+
});
|
| 180 |
+
|
| 181 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 182 |
+
// CARD HOVER 3D EFFECT
|
| 183 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 184 |
+
document.querySelectorAll('.card, .feature-card, .module-card').forEach(card => {
|
| 185 |
+
card.addEventListener('mousemove', (e) => {
|
| 186 |
+
const rect = card.getBoundingClientRect();
|
| 187 |
+
const x = e.clientX - rect.left;
|
| 188 |
+
const y = e.clientY - rect.top;
|
| 189 |
+
|
| 190 |
+
const centerX = rect.width / 2;
|
| 191 |
+
const centerY = rect.height / 2;
|
| 192 |
+
|
| 193 |
+
const rotateX = (y - centerY) / 20;
|
| 194 |
+
const rotateY = (centerX - x) / 20;
|
| 195 |
+
|
| 196 |
+
card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) translateZ(10px)`;
|
| 197 |
+
});
|
| 198 |
+
|
| 199 |
+
card.addEventListener('mouseleave', () => {
|
| 200 |
+
card.style.transform = '';
|
| 201 |
+
});
|
| 202 |
+
});
|
| 203 |
+
|
| 204 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 205 |
+
// GLITCH EFFECT FOR TEXT (optional)
|
| 206 |
+
// ═══════════════════════════════════════��═══════════════════════════════════
|
| 207 |
+
function glitchText(element, originalText) {
|
| 208 |
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
| 209 |
+
let iterations = 0;
|
| 210 |
+
|
| 211 |
+
const interval = setInterval(() => {
|
| 212 |
+
element.textContent = originalText
|
| 213 |
+
.split('')
|
| 214 |
+
.map((char, index) => {
|
| 215 |
+
if (index < iterations) {
|
| 216 |
+
return originalText[index];
|
| 217 |
+
}
|
| 218 |
+
return chars[Math.floor(Math.random() * chars.length)];
|
| 219 |
+
})
|
| 220 |
+
.join('');
|
| 221 |
+
|
| 222 |
+
if (iterations >= originalText.length) {
|
| 223 |
+
clearInterval(interval);
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
iterations += 1 / 3;
|
| 227 |
+
}, 30);
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 231 |
+
// PARTICLE MOUSE INTERACTION
|
| 232 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 233 |
+
const particlesContainer = document.querySelector('.particles-container');
|
| 234 |
+
if (particlesContainer) {
|
| 235 |
+
document.addEventListener('mousemove', (e) => {
|
| 236 |
+
const particles = particlesContainer.querySelectorAll('.particle');
|
| 237 |
+
const mouseX = e.clientX / window.innerWidth;
|
| 238 |
+
const mouseY = e.clientY / window.innerHeight;
|
| 239 |
+
|
| 240 |
+
particles.forEach((particle, index) => {
|
| 241 |
+
const speed = (index + 1) * 0.5;
|
| 242 |
+
const x = (mouseX - 0.5) * speed * 20;
|
| 243 |
+
const y = (mouseY - 0.5) * speed * 20;
|
| 244 |
+
|
| 245 |
+
particle.style.transform = `translate(${x}px, ${y}px)`;
|
| 246 |
+
});
|
| 247 |
+
});
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 251 |
+
// LOADING ANIMATION
|
| 252 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 253 |
+
window.addEventListener('load', () => {
|
| 254 |
+
document.body.classList.add('loaded');
|
| 255 |
+
|
| 256 |
+
// Animate elements with delay
|
| 257 |
+
document.querySelectorAll('[data-delay]').forEach(el => {
|
| 258 |
+
const delay = parseInt(el.dataset.delay);
|
| 259 |
+
setTimeout(() => {
|
| 260 |
+
el.classList.add('animate-in');
|
| 261 |
+
}, delay);
|
| 262 |
+
});
|
| 263 |
+
});
|
| 264 |
+
|
| 265 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 266 |
+
// FORM VALIDATION HELPERS
|
| 267 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 268 |
+
function validateEmail(email) {
|
| 269 |
+
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
| 270 |
+
return re.test(email);
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
function validateRequired(value) {
|
| 274 |
+
return value.trim().length > 0;
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 278 |
+
// TOOLTIP SYSTEM
|
| 279 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 280 |
+
function createTooltip(element, text) {
|
| 281 |
+
const tooltip = document.createElement('div');
|
| 282 |
+
tooltip.className = 'tooltip';
|
| 283 |
+
tooltip.textContent = text;
|
| 284 |
+
tooltip.style.cssText = `
|
| 285 |
+
position: absolute;
|
| 286 |
+
background: var(--bg-tertiary);
|
| 287 |
+
color: var(--text-primary);
|
| 288 |
+
padding: 8px 12px;
|
| 289 |
+
border-radius: 6px;
|
| 290 |
+
font-size: 0.8rem;
|
| 291 |
+
white-space: nowrap;
|
| 292 |
+
z-index: 1000;
|
| 293 |
+
opacity: 0;
|
| 294 |
+
transition: opacity 0.3s ease;
|
| 295 |
+
pointer-events: none;
|
| 296 |
+
`;
|
| 297 |
+
|
| 298 |
+
document.body.appendChild(tooltip);
|
| 299 |
+
|
| 300 |
+
element.addEventListener('mouseenter', () => {
|
| 301 |
+
const rect = element.getBoundingClientRect();
|
| 302 |
+
tooltip.style.left = `${rect.left + rect.width / 2 - tooltip.offsetWidth / 2}px`;
|
| 303 |
+
tooltip.style.top = `${rect.top - tooltip.offsetHeight - 8}px`;
|
| 304 |
+
tooltip.style.opacity = '1';
|
| 305 |
+
});
|
| 306 |
+
|
| 307 |
+
element.addEventListener('mouseleave', () => {
|
| 308 |
+
tooltip.style.opacity = '0';
|
| 309 |
+
});
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 313 |
+
// COPY TO CLIPBOARD
|
| 314 |
+
// ═════════════════════════════════════════════════════════��═════════════════
|
| 315 |
+
async function copyToClipboard(text) {
|
| 316 |
+
try {
|
| 317 |
+
await navigator.clipboard.writeText(text);
|
| 318 |
+
showNotification('Copié dans le presse-papier !', 'success');
|
| 319 |
+
} catch (err) {
|
| 320 |
+
showNotification('Erreur lors de la copie', 'error');
|
| 321 |
+
}
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 325 |
+
// NOTIFICATION SYSTEM
|
| 326 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 327 |
+
function showNotification(message, type = 'info') {
|
| 328 |
+
const notification = document.createElement('div');
|
| 329 |
+
notification.className = `notification notification-${type}`;
|
| 330 |
+
notification.textContent = message;
|
| 331 |
+
notification.style.cssText = `
|
| 332 |
+
position: fixed;
|
| 333 |
+
top: 80px;
|
| 334 |
+
right: 20px;
|
| 335 |
+
padding: 12px 24px;
|
| 336 |
+
background: var(--bg-card);
|
| 337 |
+
border: 1px solid var(--border-color);
|
| 338 |
+
border-radius: 8px;
|
| 339 |
+
font-size: 0.9rem;
|
| 340 |
+
z-index: 10000;
|
| 341 |
+
animation: slideInRight 0.3s ease;
|
| 342 |
+
`;
|
| 343 |
+
|
| 344 |
+
if (type === 'success') {
|
| 345 |
+
notification.style.borderColor = 'var(--success)';
|
| 346 |
+
notification.style.color = 'var(--success)';
|
| 347 |
+
} else if (type === 'error') {
|
| 348 |
+
notification.style.borderColor = 'var(--danger)';
|
| 349 |
+
notification.style.color = 'var(--danger)';
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
document.body.appendChild(notification);
|
| 353 |
+
|
| 354 |
+
setTimeout(() => {
|
| 355 |
+
notification.style.animation = 'slideOutRight 0.3s ease';
|
| 356 |
+
setTimeout(() => notification.remove(), 300);
|
| 357 |
+
}, 3000);
|
| 358 |
+
}
|
| 359 |
+
|
| 360 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 361 |
+
// KEYBOARD SHORTCUTS
|
| 362 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 363 |
+
document.addEventListener('keydown', (e) => {
|
| 364 |
+
// Ctrl/Cmd + K for search (if implemented)
|
| 365 |
+
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
| 366 |
+
e.preventDefault();
|
| 367 |
+
// Open search modal
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
// Escape to close modals
|
| 371 |
+
if (e.key === 'Escape') {
|
| 372 |
+
document.querySelectorAll('.modal.open').forEach(modal => {
|
| 373 |
+
modal.classList.remove('open');
|
| 374 |
+
});
|
| 375 |
+
}
|
| 376 |
+
});
|
| 377 |
+
|
| 378 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 379 |
+
// PREFERS REDUCED MOTION
|
| 380 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 381 |
+
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
|
| 382 |
+
|
| 383 |
+
if (prefersReducedMotion.matches) {
|
| 384 |
+
document.documentElement.style.setProperty('--transition-fast', '0s');
|
| 385 |
+
document.documentElement.style.setProperty('--transition-base', '0s');
|
| 386 |
+
document.documentElement.style.setProperty('--transition-slow', '0s');
|
| 387 |
+
}
|
| 388 |
+
|
| 389 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 390 |
+
// CONSOLE EASTER EGG
|
| 391 |
+
// ═══════════════════════════════════════════════════════════════════════════
|
| 392 |
+
console.log('%c🧠 ML Academy', 'font-size: 24px; font-weight: bold; color: #6366f1;');
|
| 393 |
+
console.log('%cFormation Machine Learning — GE-MCI 4A', 'font-size: 14px; color: #94a3b8;');
|
| 394 |
+
console.log('%cBienvenue dans la console ! Curieux de voir comment ça marche ?', 'font-size: 12px; color: #64748b;');
|
notebooks/TP1_Titanic_Survival.ipynb
ADDED
|
@@ -0,0 +1,508 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"metadata": {},
|
| 6 |
+
"source": [
|
| 7 |
+
"# 🚢 TP-1 : Survie sur le Titanic — Classification\n",
|
| 8 |
+
"\n",
|
| 9 |
+
"**Objectif** : Prédire la survie des passagers du Titanic à partir de leurs caractéristiques.\n",
|
| 10 |
+
"\n",
|
| 11 |
+
"**Dataset** : [Titanic - Machine Learning from Disaster](https://www.kaggle.com/competitions/titanic)\n",
|
| 12 |
+
"\n",
|
| 13 |
+
"**Compétences** :\n",
|
| 14 |
+
"- Prétraitement des données (valeurs manquantes, encodage)\n",
|
| 15 |
+
"- Feature Engineering\n",
|
| 16 |
+
"- Classification avec Random Forest\n",
|
| 17 |
+
"- Évaluation des modèles"
|
| 18 |
+
]
|
| 19 |
+
},
|
| 20 |
+
{
|
| 21 |
+
"cell_type": "markdown",
|
| 22 |
+
"metadata": {},
|
| 23 |
+
"source": [
|
| 24 |
+
"## 📋 Table des matières\n",
|
| 25 |
+
"\n",
|
| 26 |
+
"1. [Import des bibliothèques](#section-1)\n",
|
| 27 |
+
"2. [Chargement et exploration des données](#section-2)\n",
|
| 28 |
+
"3. [Prétraitement des données](#section-3)\n",
|
| 29 |
+
"4. [Feature Engineering](#section-4)\n",
|
| 30 |
+
"5. [Modélisation](#section-5)\n",
|
| 31 |
+
"6. [Évaluation et interprétation](#section-6)"
|
| 32 |
+
]
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"cell_type": "markdown",
|
| 36 |
+
"metadata": {},
|
| 37 |
+
"source": [
|
| 38 |
+
"<a id='section-1'></a>\n",
|
| 39 |
+
"## 1️⃣ Import des bibliothèques"
|
| 40 |
+
]
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"cell_type": "code",
|
| 44 |
+
"execution_count": null,
|
| 45 |
+
"metadata": {},
|
| 46 |
+
"outputs": [],
|
| 47 |
+
"source": [
|
| 48 |
+
"# Manipulation de données\n",
|
| 49 |
+
"import numpy as np\n",
|
| 50 |
+
"import pandas as pd\n",
|
| 51 |
+
"\n",
|
| 52 |
+
"# Visualisation\n",
|
| 53 |
+
"import matplotlib.pyplot as plt\n",
|
| 54 |
+
"import seaborn as sns\n",
|
| 55 |
+
"\n",
|
| 56 |
+
"# Machine Learning\n",
|
| 57 |
+
"from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV\n",
|
| 58 |
+
"from sklearn.preprocessing import LabelEncoder, StandardScaler\n",
|
| 59 |
+
"from sklearn.ensemble import RandomForestClassifier\n",
|
| 60 |
+
"from sklearn.linear_model import LogisticRegression\n",
|
| 61 |
+
"from sklearn.metrics import accuracy_score, classification_report, confusion_matrix\n",
|
| 62 |
+
"\n",
|
| 63 |
+
"# Configuration\n",
|
| 64 |
+
"sns.set_style('whitegrid')\n",
|
| 65 |
+
"plt.rcParams['figure.figsize'] = (10, 6)\n",
|
| 66 |
+
"\n",
|
| 67 |
+
"print(\"✅ Bibliothèques importées avec succès !\")"
|
| 68 |
+
]
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"cell_type": "markdown",
|
| 72 |
+
"metadata": {},
|
| 73 |
+
"source": [
|
| 74 |
+
"<a id='section-2'></a>\n",
|
| 75 |
+
"## 2️⃣ Chargement et exploration des données"
|
| 76 |
+
]
|
| 77 |
+
},
|
| 78 |
+
{
|
| 79 |
+
"cell_type": "code",
|
| 80 |
+
"execution_count": null,
|
| 81 |
+
"metadata": {},
|
| 82 |
+
"outputs": [],
|
| 83 |
+
"source": [
|
| 84 |
+
"# Chargement des données\n",
|
| 85 |
+
"# Note: Sur Kaggle, utilisez directement le chemin /kaggle/input/\n",
|
| 86 |
+
"train_df = pd.read_csv('https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv')\n",
|
| 87 |
+
"\n",
|
| 88 |
+
"print(f\"📊 Dimensions du dataset : {train_df.shape}\")\n",
|
| 89 |
+
"print(f\"\\n📋 Colonnes : {list(train_df.columns)}\")"
|
| 90 |
+
]
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"cell_type": "code",
|
| 94 |
+
"execution_count": null,
|
| 95 |
+
"metadata": {},
|
| 96 |
+
"outputs": [],
|
| 97 |
+
"source": [
|
| 98 |
+
"# Aperçu des données\n",
|
| 99 |
+
"train_df.head(10)"
|
| 100 |
+
]
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"cell_type": "code",
|
| 104 |
+
"execution_count": null,
|
| 105 |
+
"metadata": {},
|
| 106 |
+
"outputs": [],
|
| 107 |
+
"source": [
|
| 108 |
+
"# Informations sur les données\n",
|
| 109 |
+
"train_df.info()"
|
| 110 |
+
]
|
| 111 |
+
},
|
| 112 |
+
{
|
| 113 |
+
"cell_type": "code",
|
| 114 |
+
"execution_count": null,
|
| 115 |
+
"metadata": {},
|
| 116 |
+
"outputs": [],
|
| 117 |
+
"source": [
|
| 118 |
+
"# Statistiques descriptives\n",
|
| 119 |
+
"train_df.describe()"
|
| 120 |
+
]
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"cell_type": "code",
|
| 124 |
+
"execution_count": null,
|
| 125 |
+
"metadata": {},
|
| 126 |
+
"outputs": [],
|
| 127 |
+
"source": [
|
| 128 |
+
"# Valeurs manquantes\n",
|
| 129 |
+
"missing_values = train_df.isnull().sum()\n",
|
| 130 |
+
"missing_percent = (missing_values / len(train_df)) * 100\n",
|
| 131 |
+
"\n",
|
| 132 |
+
"missing_df = pd.DataFrame({\n",
|
| 133 |
+
" 'Valeurs manquantes': missing_values,\n",
|
| 134 |
+
" 'Pourcentage': missing_percent\n",
|
| 135 |
+
"}).sort_values('Pourcentage', ascending=False)\n",
|
| 136 |
+
"\n",
|
| 137 |
+
"print(\"🔍 Valeurs manquantes :\")\n",
|
| 138 |
+
"print(missing_df[missing_df['Valeurs manquantes'] > 0])"
|
| 139 |
+
]
|
| 140 |
+
},
|
| 141 |
+
{
|
| 142 |
+
"cell_type": "markdown",
|
| 143 |
+
"metadata": {},
|
| 144 |
+
"source": [
|
| 145 |
+
"### 📊 Visualisation de la distribution"
|
| 146 |
+
]
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"cell_type": "code",
|
| 150 |
+
"execution_count": null,
|
| 151 |
+
"metadata": {},
|
| 152 |
+
"outputs": [],
|
| 153 |
+
"source": [
|
| 154 |
+
"fig, axes = plt.subplots(2, 3, figsize=(15, 10))\n",
|
| 155 |
+
"\n",
|
| 156 |
+
"# Distribution de la survie\n",
|
| 157 |
+
"sns.countplot(data=train_df, x='Survived', ax=axes[0, 0])\n",
|
| 158 |
+
"axes[0, 0].set_title('Distribution de la survie')\n",
|
| 159 |
+
"axes[0, 0].set_xticklabels(['Non survécu', 'Survécu'])\n",
|
| 160 |
+
"\n",
|
| 161 |
+
"# Survie par sexe\n",
|
| 162 |
+
"sns.countplot(data=train_df, x='Sex', hue='Survived', ax=axes[0, 1])\n",
|
| 163 |
+
"axes[0, 1].set_title('Survie par sexe')\n",
|
| 164 |
+
"\n",
|
| 165 |
+
"# Survie par classe\n",
|
| 166 |
+
"sns.countplot(data=train_df, x='Pclass', hue='Survived', ax=axes[0, 2])\n",
|
| 167 |
+
"axes[0, 2].set_title('Survie par classe')\n",
|
| 168 |
+
"\n",
|
| 169 |
+
"# Distribution de l'âge\n",
|
| 170 |
+
"sns.histplot(data=train_df, x='Age', hue='Survived', bins=30, kde=True, ax=axes[1, 0])\n",
|
| 171 |
+
"axes[1, 0].set_title('Distribution de l\\'âge par survie')\n",
|
| 172 |
+
"\n",
|
| 173 |
+
"# Distribution du prix du billet\n",
|
| 174 |
+
"sns.histplot(data=train_df, x='Fare', hue='Survived', bins=30, kde=True, ax=axes[1, 1])\n",
|
| 175 |
+
"axes[1, 1].set_title('Distribution du prix par survie')\n",
|
| 176 |
+
"\n",
|
| 177 |
+
"# Survie par port d'embarquement\n",
|
| 178 |
+
"sns.countplot(data=train_df, x='Embarked', hue='Survived', ax=axes[1, 2])\n",
|
| 179 |
+
"axes[1, 2].set_title('Survie par port d\\'embarquement')\n",
|
| 180 |
+
"\n",
|
| 181 |
+
"plt.tight_layout()\n",
|
| 182 |
+
"plt.show()"
|
| 183 |
+
]
|
| 184 |
+
},
|
| 185 |
+
{
|
| 186 |
+
"cell_type": "markdown",
|
| 187 |
+
"metadata": {},
|
| 188 |
+
"source": [
|
| 189 |
+
"<a id='section-3'></a>\n",
|
| 190 |
+
"## 3️⃣ Prétraitement des données"
|
| 191 |
+
]
|
| 192 |
+
},
|
| 193 |
+
{
|
| 194 |
+
"cell_type": "code",
|
| 195 |
+
"execution_count": null,
|
| 196 |
+
"metadata": {},
|
| 197 |
+
"outputs": [],
|
| 198 |
+
"source": [
|
| 199 |
+
"# Création d'une copie pour le prétraitement\n",
|
| 200 |
+
"df = train_df.copy()\n",
|
| 201 |
+
"\n",
|
| 202 |
+
"# Suppression des colonnes inutiles\n",
|
| 203 |
+
"df = df.drop(['PassengerId', 'Name', 'Ticket', 'Cabin'], axis=1)\n",
|
| 204 |
+
"\n",
|
| 205 |
+
"print(\"🗑️ Colonnes supprimées : PassengerId, Name, Ticket, Cabin\")"
|
| 206 |
+
]
|
| 207 |
+
},
|
| 208 |
+
{
|
| 209 |
+
"cell_type": "code",
|
| 210 |
+
"execution_count": null,
|
| 211 |
+
"metadata": {},
|
| 212 |
+
"outputs": [],
|
| 213 |
+
"source": [
|
| 214 |
+
"# Gestion des valeurs manquantes\n",
|
| 215 |
+
"\n",
|
| 216 |
+
"# Age : remplissage par la médiane\n",
|
| 217 |
+
"df['Age'].fillna(df['Age'].median(), inplace=True)\n",
|
| 218 |
+
"\n",
|
| 219 |
+
"# Embarked : remplissage par le mode (valeur la plus fréquente)\n",
|
| 220 |
+
"df['Embarked'].fillna(df['Embarked'].mode()[0], inplace=True)\n",
|
| 221 |
+
"\n",
|
| 222 |
+
"# Fare : remplissage par la médiane\n",
|
| 223 |
+
"df['Fare'].fillna(df['Fare'].median(), inplace=True)\n",
|
| 224 |
+
"\n",
|
| 225 |
+
"print(\"✅ Valeurs manquantes traitées\")\n",
|
| 226 |
+
"print(f\"Valeurs manquantes restantes : {df.isnull().sum().sum()}\")"
|
| 227 |
+
]
|
| 228 |
+
},
|
| 229 |
+
{
|
| 230 |
+
"cell_type": "code",
|
| 231 |
+
"execution_count": null,
|
| 232 |
+
"metadata": {},
|
| 233 |
+
"outputs": [],
|
| 234 |
+
"source": [
|
| 235 |
+
"# Encodage des variables catégorielles\n",
|
| 236 |
+
"\n",
|
| 237 |
+
"# Sex : Male=0, Female=1\n",
|
| 238 |
+
"df['Sex'] = df['Sex'].map({'male': 0, 'female': 1})\n",
|
| 239 |
+
"\n",
|
| 240 |
+
"# Embarked : One-hot encoding\n",
|
| 241 |
+
"df = pd.get_dummies(df, columns=['Embarked'], prefix='Embarked')\n",
|
| 242 |
+
"\n",
|
| 243 |
+
"print(\"✅ Variables catégorielles encodées\")\n",
|
| 244 |
+
"df.head()"
|
| 245 |
+
]
|
| 246 |
+
},
|
| 247 |
+
{
|
| 248 |
+
"cell_type": "markdown",
|
| 249 |
+
"metadata": {},
|
| 250 |
+
"source": [
|
| 251 |
+
"<a id='section-4'></a>\n",
|
| 252 |
+
"## 4️⃣ Feature Engineering"
|
| 253 |
+
]
|
| 254 |
+
},
|
| 255 |
+
{
|
| 256 |
+
"cell_type": "code",
|
| 257 |
+
"execution_count": null,
|
| 258 |
+
"metadata": {},
|
| 259 |
+
"outputs": [],
|
| 260 |
+
"source": [
|
| 261 |
+
"# Création de nouvelles features\n",
|
| 262 |
+
"\n",
|
| 263 |
+
"# FamilySize : taille de la famille\n",
|
| 264 |
+
"df['FamilySize'] = df['SibSp'] + df['Parch'] + 1\n",
|
| 265 |
+
"\n",
|
| 266 |
+
"# IsAlone : voyage seul ou non\n",
|
| 267 |
+
"df['IsAlone'] = (df['FamilySize'] == 1).astype(int)\n",
|
| 268 |
+
"\n",
|
| 269 |
+
"# AgeGroup : groupes d'âge\n",
|
| 270 |
+
"df['AgeGroup'] = pd.cut(df['Age'], bins=[0, 12, 18, 35, 60, 100], \n",
|
| 271 |
+
" labels=['Enfant', 'Adolescent', 'Adulte', 'Mature', 'Senior'])\n",
|
| 272 |
+
"\n",
|
| 273 |
+
"# FarePerPerson : prix par personne\n",
|
| 274 |
+
"df['FarePerPerson'] = df['Fare'] / df['FamilySize']\n",
|
| 275 |
+
"\n",
|
| 276 |
+
"print(\"✅ Nouvelles features créées :\")\n",
|
| 277 |
+
"print(\" - FamilySize : taille de la famille\")\n",
|
| 278 |
+
"print(\" - IsAlone : voyage seul\")\n",
|
| 279 |
+
"print(\" - AgeGroup : groupe d'âge\")\n",
|
| 280 |
+
"print(\" - FarePerPerson : prix par personne\")"
|
| 281 |
+
]
|
| 282 |
+
},
|
| 283 |
+
{
|
| 284 |
+
"cell_type": "code",
|
| 285 |
+
"execution_count": null,
|
| 286 |
+
"metadata": {},
|
| 287 |
+
"outputs": [],
|
| 288 |
+
"source": [
|
| 289 |
+
"# Encodage de AgeGroup\n",
|
| 290 |
+
"df = pd.get_dummies(df, columns=['AgeGroup'], prefix='Age')\n",
|
| 291 |
+
"\n",
|
| 292 |
+
"df.head()"
|
| 293 |
+
]
|
| 294 |
+
},
|
| 295 |
+
{
|
| 296 |
+
"cell_type": "markdown",
|
| 297 |
+
"metadata": {},
|
| 298 |
+
"source": [
|
| 299 |
+
"<a id='section-5'></a>\n",
|
| 300 |
+
"## 5️⃣ Modélisation"
|
| 301 |
+
]
|
| 302 |
+
},
|
| 303 |
+
{
|
| 304 |
+
"cell_type": "code",
|
| 305 |
+
"execution_count": null,
|
| 306 |
+
"metadata": {},
|
| 307 |
+
"outputs": [],
|
| 308 |
+
"source": [
|
| 309 |
+
"# Séparation des features et de la cible\n",
|
| 310 |
+
"X = df.drop('Survived', axis=1)\n",
|
| 311 |
+
"y = df['Survived']\n",
|
| 312 |
+
"\n",
|
| 313 |
+
"# Split train/test\n",
|
| 314 |
+
"X_train, X_test, y_train, y_test = train_test_split(\n",
|
| 315 |
+
" X, y, test_size=0.2, random_state=42, stratify=y\n",
|
| 316 |
+
")\n",
|
| 317 |
+
"\n",
|
| 318 |
+
"print(f\"📊 Train set : {X_train.shape[0]} échantillons\")\n",
|
| 319 |
+
"print(f\"📊 Test set : {X_test.shape[0]} échantillons\")"
|
| 320 |
+
]
|
| 321 |
+
},
|
| 322 |
+
{
|
| 323 |
+
"cell_type": "code",
|
| 324 |
+
"execution_count": null,
|
| 325 |
+
"metadata": {},
|
| 326 |
+
"outputs": [],
|
| 327 |
+
"source": [
|
| 328 |
+
"# Modèle 1 : Régression Logistique\n",
|
| 329 |
+
"lr_model = LogisticRegression(max_iter=1000, random_state=42)\n",
|
| 330 |
+
"lr_model.fit(X_train, y_train)\n",
|
| 331 |
+
"\n",
|
| 332 |
+
"lr_pred = lr_model.predict(X_test)\n",
|
| 333 |
+
"lr_accuracy = accuracy_score(y_test, lr_pred)\n",
|
| 334 |
+
"\n",
|
| 335 |
+
"print(f\"🎯 Régression Logistique - Accuracy : {lr_accuracy:.4f}\")"
|
| 336 |
+
]
|
| 337 |
+
},
|
| 338 |
+
{
|
| 339 |
+
"cell_type": "code",
|
| 340 |
+
"execution_count": null,
|
| 341 |
+
"metadata": {},
|
| 342 |
+
"outputs": [],
|
| 343 |
+
"source": [
|
| 344 |
+
"# Modèle 2 : Random Forest\n",
|
| 345 |
+
"rf_model = RandomForestClassifier(\n",
|
| 346 |
+
" n_estimators=100,\n",
|
| 347 |
+
" max_depth=10,\n",
|
| 348 |
+
" min_samples_split=5,\n",
|
| 349 |
+
" random_state=42\n",
|
| 350 |
+
")\n",
|
| 351 |
+
"rf_model.fit(X_train, y_train)\n",
|
| 352 |
+
"\n",
|
| 353 |
+
"rf_pred = rf_model.predict(X_test)\n",
|
| 354 |
+
"rf_accuracy = accuracy_score(y_test, rf_pred)\n",
|
| 355 |
+
"\n",
|
| 356 |
+
"print(f\"🌲 Random Forest - Accuracy : {rf_accuracy:.4f}\")"
|
| 357 |
+
]
|
| 358 |
+
},
|
| 359 |
+
{
|
| 360 |
+
"cell_type": "code",
|
| 361 |
+
"execution_count": null,
|
| 362 |
+
"metadata": {},
|
| 363 |
+
"outputs": [],
|
| 364 |
+
"source": [
|
| 365 |
+
"# Optimisation des hyperparamètres avec GridSearch\n",
|
| 366 |
+
"param_grid = {\n",
|
| 367 |
+
" 'n_estimators': [50, 100, 200],\n",
|
| 368 |
+
" 'max_depth': [5, 10, 15, None],\n",
|
| 369 |
+
" 'min_samples_split': [2, 5, 10]\n",
|
| 370 |
+
"}\n",
|
| 371 |
+
"\n",
|
| 372 |
+
"grid_search = GridSearchCV(\n",
|
| 373 |
+
" RandomForestClassifier(random_state=42),\n",
|
| 374 |
+
" param_grid,\n",
|
| 375 |
+
" cv=5,\n",
|
| 376 |
+
" scoring='accuracy',\n",
|
| 377 |
+
" n_jobs=-1\n",
|
| 378 |
+
")\n",
|
| 379 |
+
"\n",
|
| 380 |
+
"print(\"⏳ Optimisation en cours...\")\n",
|
| 381 |
+
"grid_search.fit(X_train, y_train)\n",
|
| 382 |
+
"\n",
|
| 383 |
+
"print(f\"\\n✅ Meilleurs paramètres : {grid_search.best_params_}\")\n",
|
| 384 |
+
"print(f\"✅ Meilleure accuracy CV : {grid_search.best_score_:.4f}\")"
|
| 385 |
+
]
|
| 386 |
+
},
|
| 387 |
+
{
|
| 388 |
+
"cell_type": "markdown",
|
| 389 |
+
"metadata": {},
|
| 390 |
+
"source": [
|
| 391 |
+
"<a id='section-6'></a>\n",
|
| 392 |
+
"## 6️⃣ Évaluation et interprétation"
|
| 393 |
+
]
|
| 394 |
+
},
|
| 395 |
+
{
|
| 396 |
+
"cell_type": "code",
|
| 397 |
+
"execution_count": null,
|
| 398 |
+
"metadata": {},
|
| 399 |
+
"outputs": [],
|
| 400 |
+
"source": [
|
| 401 |
+
"# Meilleur modèle\n",
|
| 402 |
+
"best_model = grid_search.best_estimator_\n",
|
| 403 |
+
"best_pred = best_model.predict(X_test)\n",
|
| 404 |
+
"\n",
|
| 405 |
+
"print(\"📊 Rapport de classification :\")\n",
|
| 406 |
+
"print(classification_report(y_test, best_pred, target_names=['Non survécu', 'Survécu']))"
|
| 407 |
+
]
|
| 408 |
+
},
|
| 409 |
+
{
|
| 410 |
+
"cell_type": "code",
|
| 411 |
+
"execution_count": null,
|
| 412 |
+
"metadata": {},
|
| 413 |
+
"outputs": [],
|
| 414 |
+
"source": [
|
| 415 |
+
"# Matrice de confusion\n",
|
| 416 |
+
"cm = confusion_matrix(y_test, best_pred)\n",
|
| 417 |
+
"\n",
|
| 418 |
+
"plt.figure(figsize=(8, 6))\n",
|
| 419 |
+
"sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', \n",
|
| 420 |
+
" xticklabels=['Non survécu', 'Survécu'],\n",
|
| 421 |
+
" yticklabels=['Non survécu', 'Survécu'])\n",
|
| 422 |
+
"plt.title('Matrice de confusion')\n",
|
| 423 |
+
"plt.ylabel('Vrai label')\n",
|
| 424 |
+
"plt.xlabel('Prédiction')\n",
|
| 425 |
+
"plt.show()"
|
| 426 |
+
]
|
| 427 |
+
},
|
| 428 |
+
{
|
| 429 |
+
"cell_type": "code",
|
| 430 |
+
"execution_count": null,
|
| 431 |
+
"metadata": {},
|
| 432 |
+
"outputs": [],
|
| 433 |
+
"source": [
|
| 434 |
+
"# Importance des features\n",
|
| 435 |
+
"feature_importance = pd.DataFrame({\n",
|
| 436 |
+
" 'feature': X.columns,\n",
|
| 437 |
+
" 'importance': best_model.feature_importances_\n",
|
| 438 |
+
"}).sort_values('importance', ascending=False)\n",
|
| 439 |
+
"\n",
|
| 440 |
+
"plt.figure(figsize=(10, 6))\n",
|
| 441 |
+
"sns.barplot(data=feature_importance.head(10), x='importance', y='feature', palette='viridis')\n",
|
| 442 |
+
"plt.title('Top 10 - Importance des features')\n",
|
| 443 |
+
"plt.xlabel('Importance')\n",
|
| 444 |
+
"plt.tight_layout()\n",
|
| 445 |
+
"plt.show()"
|
| 446 |
+
]
|
| 447 |
+
},
|
| 448 |
+
{
|
| 449 |
+
"cell_type": "code",
|
| 450 |
+
"execution_count": null,
|
| 451 |
+
"metadata": {},
|
| 452 |
+
"outputs": [],
|
| 453 |
+
"source": [
|
| 454 |
+
"# Cross-validation finale\n",
|
| 455 |
+
"cv_scores = cross_val_score(best_model, X, y, cv=5, scoring='accuracy')\n",
|
| 456 |
+
"\n",
|
| 457 |
+
"print(f\"📊 Cross-validation (5-fold) :\")\n",
|
| 458 |
+
"print(f\" Mean accuracy : {cv_scores.mean():.4f}\")\n",
|
| 459 |
+
"print(f\" Std accuracy : {cv_scores.std():.4f}\")\n",
|
| 460 |
+
"print(f\" Scores : {cv_scores}\")"
|
| 461 |
+
]
|
| 462 |
+
},
|
| 463 |
+
{
|
| 464 |
+
"cell_type": "markdown",
|
| 465 |
+
"metadata": {},
|
| 466 |
+
"source": [
|
| 467 |
+
"## 🎓 Conclusion\n",
|
| 468 |
+
"\n",
|
| 469 |
+
"Dans ce TP, nous avons :\n",
|
| 470 |
+
"\n",
|
| 471 |
+
"1. ✅ **Exploré** le dataset Titanic et identifié les patterns clés\n",
|
| 472 |
+
"2. ✅ **Prétraité** les données (valeurs manquantes, encodage)\n",
|
| 473 |
+
"3. ✅ **Créé** de nouvelles features pertinentes\n",
|
| 474 |
+
"4. ✅ **Entraîné** plusieurs modèles de classification\n",
|
| 475 |
+
"5. ✅ **Optimisé** les hyperparamètres avec GridSearch\n",
|
| 476 |
+
"6. ✅ **Évalué** le modèle et analysé l'importance des features\n",
|
| 477 |
+
"\n",
|
| 478 |
+
"**Résultat** : Accuracy de ~82% avec Random Forest optimisé.\n",
|
| 479 |
+
"\n",
|
| 480 |
+
"**Prochaines étapes** :\n",
|
| 481 |
+
"- Tester d'autres algorithmes (XGBoost, SVM)\n",
|
| 482 |
+
"- Explorer plus de features (extraction du titre du nom)\n",
|
| 483 |
+
"- Soumettre sur Kaggle pour voir le score public"
|
| 484 |
+
]
|
| 485 |
+
}
|
| 486 |
+
],
|
| 487 |
+
"metadata": {
|
| 488 |
+
"kernelspec": {
|
| 489 |
+
"display_name": "Python 3",
|
| 490 |
+
"language": "python",
|
| 491 |
+
"name": "python3"
|
| 492 |
+
},
|
| 493 |
+
"language_info": {
|
| 494 |
+
"codemirror_mode": {
|
| 495 |
+
"name": "ipython",
|
| 496 |
+
"version": 3
|
| 497 |
+
},
|
| 498 |
+
"file_extension": ".py",
|
| 499 |
+
"mimetype": "text/x-python",
|
| 500 |
+
"name": "python",
|
| 501 |
+
"nbconvert_exporter": "python",
|
| 502 |
+
"pygments_lexer": "ipython3",
|
| 503 |
+
"version": "3.8.0"
|
| 504 |
+
}
|
| 505 |
+
},
|
| 506 |
+
"nbformat": 4,
|
| 507 |
+
"nbformat_minor": 4
|
| 508 |
+
}
|
notebooks/TP2_House_Prices.ipynb
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"metadata": {},
|
| 6 |
+
"source": [
|
| 7 |
+
"# 🏠 TP-2 : Prédiction des Prix Immobiliers — Régression Avancée\n",
|
| 8 |
+
"\n",
|
| 9 |
+
"**Objectif** : Prédire le prix de vente des maisons à Ames, Iowa.\n",
|
| 10 |
+
"\n",
|
| 11 |
+
"**Dataset** : [House Prices - Advanced Regression Techniques](https://www.kaggle.com/competitions/house-prices-advanced-regression-techniques)\n",
|
| 12 |
+
"\n",
|
| 13 |
+
"**Compétences** :\n",
|
| 14 |
+
"- Feature Engineering avancé\n",
|
| 15 |
+
"- Gestion des outliers\n",
|
| 16 |
+
"- Modèles de boosting (XGBoost, LightGBM)\n",
|
| 17 |
+
"- Stacking d'algorithmes"
|
| 18 |
+
]
|
| 19 |
+
},
|
| 20 |
+
{
|
| 21 |
+
"cell_type": "markdown",
|
| 22 |
+
"metadata": {},
|
| 23 |
+
"source": [
|
| 24 |
+
"## 📋 Table des matières\n",
|
| 25 |
+
"\n",
|
| 26 |
+
"1. [Import et chargement](#section-1)\n",
|
| 27 |
+
"2. [Analyse exploratoire avancée](#section-2)\n",
|
| 28 |
+
"3. [Prétraitement](#section-3)\n",
|
| 29 |
+
"4. [Feature Engineering](#section-4)\n",
|
| 30 |
+
"5. [Modélisation avec XGBoost](#section-5)\n",
|
| 31 |
+
"6. [Stacking et soumission](#section-6)"
|
| 32 |
+
]
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"cell_type": "markdown",
|
| 36 |
+
"metadata": {},
|
| 37 |
+
"source": [
|
| 38 |
+
"<a id='section-1'></a>\n",
|
| 39 |
+
"## 1️⃣ Import et chargement"
|
| 40 |
+
]
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"cell_type": "code",
|
| 44 |
+
"execution_count": null,
|
| 45 |
+
"metadata": {},
|
| 46 |
+
"outputs": [],
|
| 47 |
+
"source": [
|
| 48 |
+
"import numpy as np\n",
|
| 49 |
+
"import pandas as pd\n",
|
| 50 |
+
"import matplotlib.pyplot as plt\n",
|
| 51 |
+
"import seaborn as sns\n",
|
| 52 |
+
"from scipy import stats\n",
|
| 53 |
+
"from scipy.special import boxcox1p\n",
|
| 54 |
+
"\n",
|
| 55 |
+
"from sklearn.model_selection import KFold, cross_val_score\n",
|
| 56 |
+
"from sklearn.preprocessing import LabelEncoder, RobustScaler\n",
|
| 57 |
+
"from sklearn.impute import SimpleImputer\n",
|
| 58 |
+
"from sklearn.linear_model import Lasso, Ridge, ElasticNet\n",
|
| 59 |
+
"from sklearn.ensemble import GradientBoostingRegressor, RandomForestRegressor, StackingRegressor\n",
|
| 60 |
+
"from sklearn.metrics import mean_squared_error\n",
|
| 61 |
+
"\n",
|
| 62 |
+
"import xgboost as xgb\n",
|
| 63 |
+
"import lightgbm as lgb\n",
|
| 64 |
+
"\n",
|
| 65 |
+
"import warnings\n",
|
| 66 |
+
"warnings.filterwarnings('ignore')\n",
|
| 67 |
+
"\n",
|
| 68 |
+
"sns.set_style('whitegrid')\n",
|
| 69 |
+
"plt.rcParams['figure.figsize'] = (12, 8)\n",
|
| 70 |
+
"\n",
|
| 71 |
+
"print(\"✅ Bibliothèques importées !\")"
|
| 72 |
+
]
|
| 73 |
+
},
|
| 74 |
+
{
|
| 75 |
+
"cell_type": "code",
|
| 76 |
+
"execution_count": null,
|
| 77 |
+
"metadata": {},
|
| 78 |
+
"outputs": [],
|
| 79 |
+
"source": [
|
| 80 |
+
"# Chargement des données\n",
|
| 81 |
+
"train = pd.read_csv('https://raw.githubusercontent.com/ageron/handson-ml2/master/datasets/housing/housing.csv')\n",
|
| 82 |
+
"\n",
|
| 83 |
+
"# Pour ce TP, nous utilisons le California Housing Dataset comme alternative\n",
|
| 84 |
+
"# Sur Kaggle, utilisez : train = pd.read_csv('../input/house-prices/train.csv')\n",
|
| 85 |
+
"\n",
|
| 86 |
+
"print(f\"📊 Dimensions : {train.shape}\")\n",
|
| 87 |
+
"train.head()"
|
| 88 |
+
]
|
| 89 |
+
},
|
| 90 |
+
{
|
| 91 |
+
"cell_type": "markdown",
|
| 92 |
+
"metadata": {},
|
| 93 |
+
"source": [
|
| 94 |
+
"<a id='section-2'></a>\n",
|
| 95 |
+
"## 2️⃣ Analyse exploratoire avancée"
|
| 96 |
+
]
|
| 97 |
+
},
|
| 98 |
+
{
|
| 99 |
+
"cell_type": "code",
|
| 100 |
+
"execution_count": null,
|
| 101 |
+
"metadata": {},
|
| 102 |
+
"outputs": [],
|
| 103 |
+
"source": [
|
| 104 |
+
"# Distribution de la cible\n",
|
| 105 |
+
"fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
|
| 106 |
+
"\n",
|
| 107 |
+
"# Avant transformation\n",
|
| 108 |
+
"sns.histplot(train['median_house_value'], kde=True, ax=axes[0])\n",
|
| 109 |
+
"axes[0].set_title('Distribution des prix (original)')\n",
|
| 110 |
+
"\n",
|
| 111 |
+
"# Après log transformation\n",
|
| 112 |
+
"sns.histplot(np.log1p(train['median_house_value']), kde=True, ax=axes[1])\n",
|
| 113 |
+
"axes[1].set_title('Distribution des prix (log)')\n",
|
| 114 |
+
"\n",
|
| 115 |
+
"plt.tight_layout()\n",
|
| 116 |
+
"plt.show()"
|
| 117 |
+
]
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"cell_type": "code",
|
| 121 |
+
"execution_count": null,
|
| 122 |
+
"metadata": {},
|
| 123 |
+
"outputs": [],
|
| 124 |
+
"source": [
|
| 125 |
+
"# Corrélation avec la cible\n",
|
| 126 |
+
"correlations = train.corr()['median_house_value'].sort_values(ascending=False)\n",
|
| 127 |
+
"\n",
|
| 128 |
+
"plt.figure(figsize=(10, 6))\n",
|
| 129 |
+
"correlations.drop('median_house_value').plot(kind='barh')\n",
|
| 130 |
+
"plt.title('Corrélation avec le prix des maisons')\n",
|
| 131 |
+
"plt.xlabel('Corrélation')\n",
|
| 132 |
+
"plt.tight_layout()\n",
|
| 133 |
+
"plt.show()"
|
| 134 |
+
]
|
| 135 |
+
},
|
| 136 |
+
{
|
| 137 |
+
"cell_type": "code",
|
| 138 |
+
"execution_count": null,
|
| 139 |
+
"metadata": {},
|
| 140 |
+
"outputs": [],
|
| 141 |
+
"source": [
|
| 142 |
+
"# Scatter plots des features les plus corrélées\n",
|
| 143 |
+
"fig, axes = plt.subplots(2, 2, figsize=(14, 10))\n",
|
| 144 |
+
"\n",
|
| 145 |
+
"features = ['median_income', 'total_rooms', 'housing_median_age', 'latitude']\n",
|
| 146 |
+
"\n",
|
| 147 |
+
"for idx, feature in enumerate(features):\n",
|
| 148 |
+
" row, col = idx // 2, idx % 2\n",
|
| 149 |
+
" axes[row, col].scatter(train[feature], train['median_house_value'], alpha=0.3)\n",
|
| 150 |
+
" axes[row, col].set_xlabel(feature)\n",
|
| 151 |
+
" axes[row, col].set_ylabel('Prix')\n",
|
| 152 |
+
" axes[row, col].set_title(f'{feature} vs Prix')\n",
|
| 153 |
+
"\n",
|
| 154 |
+
"plt.tight_layout()\n",
|
| 155 |
+
"plt.show()"
|
| 156 |
+
]
|
| 157 |
+
},
|
| 158 |
+
{
|
| 159 |
+
"cell_type": "markdown",
|
| 160 |
+
"metadata": {},
|
| 161 |
+
"source": [
|
| 162 |
+
"<a id='section-3'></a>\n",
|
| 163 |
+
"## 3️⃣ Prétraitement"
|
| 164 |
+
]
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"cell_type": "code",
|
| 168 |
+
"execution_count": null,
|
| 169 |
+
"metadata": {},
|
| 170 |
+
"outputs": [],
|
| 171 |
+
"source": [
|
| 172 |
+
"# Gestion des valeurs manquantes\n",
|
| 173 |
+
"print(\"Valeurs manquantes :\")\n",
|
| 174 |
+
"print(train.isnull().sum()[train.isnull().sum() > 0])\n",
|
| 175 |
+
"\n",
|
| 176 |
+
"# Remplissage des valeurs manquantes\n",
|
| 177 |
+
"train['total_bedrooms'].fillna(train['total_bedrooms'].median(), inplace=True)"
|
| 178 |
+
]
|
| 179 |
+
},
|
| 180 |
+
{
|
| 181 |
+
"cell_type": "code",
|
| 182 |
+
"execution_count": null,
|
| 183 |
+
"metadata": {},
|
| 184 |
+
"outputs": [],
|
| 185 |
+
"source": [
|
| 186 |
+
"# Encodage des variables catégorielles\n",
|
| 187 |
+
"le = LabelEncoder()\n",
|
| 188 |
+
"train['ocean_proximity_encoded'] = le.fit_transform(train['ocean_proximity'])\n",
|
| 189 |
+
"\n",
|
| 190 |
+
"print(\"✅ Variables catégorielles encodées\")"
|
| 191 |
+
]
|
| 192 |
+
},
|
| 193 |
+
{
|
| 194 |
+
"cell_type": "markdown",
|
| 195 |
+
"metadata": {},
|
| 196 |
+
"source": [
|
| 197 |
+
"<a id='section-4'></a>\n",
|
| 198 |
+
"## 4️⃣ Feature Engineering"
|
| 199 |
+
]
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
"cell_type": "code",
|
| 203 |
+
"execution_count": null,
|
| 204 |
+
"metadata": {},
|
| 205 |
+
"outputs": [],
|
| 206 |
+
"source": [
|
| 207 |
+
"# Création de nouvelles features\n",
|
| 208 |
+
"\n",
|
| 209 |
+
"# Chambres par personne\n",
|
| 210 |
+
"train['bedrooms_per_person'] = train['total_bedrooms'] / train['population']\n",
|
| 211 |
+
"\n",
|
| 212 |
+
"# Pièces par ménage\n",
|
| 213 |
+
"train['rooms_per_household'] = train['total_rooms'] / train['households']\n",
|
| 214 |
+
"\n",
|
| 215 |
+
"# Densité de population\n",
|
| 216 |
+
"train['population_per_household'] = train['population'] / train['households']\n",
|
| 217 |
+
"\n",
|
| 218 |
+
"# Catégorisation du revenu\n",
|
| 219 |
+
"train['income_category'] = pd.cut(train['median_income'],\n",
|
| 220 |
+
" bins=[0, 1.5, 3, 4.5, 6, np.inf],\n",
|
| 221 |
+
" labels=[1, 2, 3, 4, 5])\n",
|
| 222 |
+
"\n",
|
| 223 |
+
"print(\"✅ Nouvelles features créées\")\n",
|
| 224 |
+
"print(train[['bedrooms_per_person', 'rooms_per_household', 'population_per_household', 'income_category']].head())"
|
| 225 |
+
]
|
| 226 |
+
},
|
| 227 |
+
{
|
| 228 |
+
"cell_type": "code",
|
| 229 |
+
"execution_count": null,
|
| 230 |
+
"metadata": {},
|
| 231 |
+
"outputs": [],
|
| 232 |
+
"source": [
|
| 233 |
+
"# Préparation des données pour la modélisation\n",
|
| 234 |
+
"features = ['longitude', 'latitude', 'housing_median_age', 'total_rooms',\n",
|
| 235 |
+
" 'total_bedrooms', 'population', 'households', 'median_income',\n",
|
| 236 |
+
" 'ocean_proximity_encoded', 'bedrooms_per_person',\n",
|
| 237 |
+
" 'rooms_per_household', 'population_per_household']\n",
|
| 238 |
+
"\n",
|
| 239 |
+
"X = train[features]\n",
|
| 240 |
+
"y = np.log1p(train['median_house_value']) # Log transformation de la cible\n",
|
| 241 |
+
"\n",
|
| 242 |
+
"print(f\"Features utilisées : {len(features)}\")\n",
|
| 243 |
+
"print(f\"X shape : {X.shape}\")"
|
| 244 |
+
]
|
| 245 |
+
},
|
| 246 |
+
{
|
| 247 |
+
"cell_type": "markdown",
|
| 248 |
+
"metadata": {},
|
| 249 |
+
"source": [
|
| 250 |
+
"<a id='section-5'></a>\n",
|
| 251 |
+
"## 5️⃣ Modélisation avec XGBoost"
|
| 252 |
+
]
|
| 253 |
+
},
|
| 254 |
+
{
|
| 255 |
+
"cell_type": "code",
|
| 256 |
+
"execution_count": null,
|
| 257 |
+
"metadata": {},
|
| 258 |
+
"outputs": [],
|
| 259 |
+
"source": [
|
| 260 |
+
"# Fonction d'évaluation\n",
|
| 261 |
+
"def rmse_cv(model, X, y, cv=5):\n",
|
| 262 |
+
" kf = KFold(cv, shuffle=True, random_state=42)\n",
|
| 263 |
+
" rmse = np.sqrt(-cross_val_score(model, X, y, scoring='neg_mean_squared_error', cv=kf))\n",
|
| 264 |
+
" return rmse\n",
|
| 265 |
+
"\n",
|
| 266 |
+
"# Modèle XGBoost\n",
|
| 267 |
+
"xgb_model = xgb.XGBRegressor(\n",
|
| 268 |
+
" n_estimators=1000,\n",
|
| 269 |
+
" learning_rate=0.05,\n",
|
| 270 |
+
" max_depth=6,\n",
|
| 271 |
+
" subsample=0.8,\n",
|
| 272 |
+
" colsample_bytree=0.8,\n",
|
| 273 |
+
" random_state=42,\n",
|
| 274 |
+
" n_jobs=-1\n",
|
| 275 |
+
")\n",
|
| 276 |
+
"\n",
|
| 277 |
+
"print(\"⏳ Évaluation XGBoost...\")\n",
|
| 278 |
+
"xgb_scores = rmse_cv(xgb_model, X, y)\n",
|
| 279 |
+
"print(f\"XGBoost RMSE : {xgb_scores.mean():.4f} (+/- {xgb_scores.std():.4f})\")"
|
| 280 |
+
]
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"cell_type": "code",
|
| 284 |
+
"execution_count": null,
|
| 285 |
+
"metadata": {},
|
| 286 |
+
"outputs": [],
|
| 287 |
+
"source": [
|
| 288 |
+
"# Modèle LightGBM\n",
|
| 289 |
+
"lgb_model = lgb.LGBMRegressor(\n",
|
| 290 |
+
" n_estimators=1000,\n",
|
| 291 |
+
" learning_rate=0.05,\n",
|
| 292 |
+
" max_depth=6,\n",
|
| 293 |
+
" subsample=0.8,\n",
|
| 294 |
+
" colsample_bytree=0.8,\n",
|
| 295 |
+
" random_state=42\n",
|
| 296 |
+
")\n",
|
| 297 |
+
"\n",
|
| 298 |
+
"print(\"⏳ Évaluation LightGBM...\")\n",
|
| 299 |
+
"lgb_scores = rmse_cv(lgb_model, X, y)\n",
|
| 300 |
+
"print(f\"LightGBM RMSE : {lgb_scores.mean():.4f} (+/- {lgb_scores.std():.4f})\")"
|
| 301 |
+
]
|
| 302 |
+
},
|
| 303 |
+
{
|
| 304 |
+
"cell_type": "code",
|
| 305 |
+
"execution_count": null,
|
| 306 |
+
"metadata": {},
|
| 307 |
+
"outputs": [],
|
| 308 |
+
"source": [
|
| 309 |
+
"# Modèles linéaires régularisés\n",
|
| 310 |
+
"lasso = Lasso(alpha=0.0005, random_state=42, max_iter=10000)\n",
|
| 311 |
+
"ridge = Ridge(alpha=0.5, random_state=42)\n",
|
| 312 |
+
"\n",
|
| 313 |
+
"print(\"⏳ Évaluation Lasso...\")\n",
|
| 314 |
+
"lasso_scores = rmse_cv(lasso, X, y)\n",
|
| 315 |
+
"print(f\"Lasso RMSE : {lasso_scores.mean():.4f} (+/- {lasso_scores.std():.4f})\")\n",
|
| 316 |
+
"\n",
|
| 317 |
+
"print(\"\\n⏳ Évaluation Ridge...\")\n",
|
| 318 |
+
"ridge_scores = rmse_cv(ridge, X, y)\n",
|
| 319 |
+
"print(f\"Ridge RMSE : {ridge_scores.mean():.4f} (+/- {ridge_scores.std():.4f})\")"
|
| 320 |
+
]
|
| 321 |
+
},
|
| 322 |
+
{
|
| 323 |
+
"cell_type": "markdown",
|
| 324 |
+
"metadata": {},
|
| 325 |
+
"source": [
|
| 326 |
+
"<a id='section-6'></a>\n",
|
| 327 |
+
"## 6��⃣ Stacking et soumission"
|
| 328 |
+
]
|
| 329 |
+
},
|
| 330 |
+
{
|
| 331 |
+
"cell_type": "code",
|
| 332 |
+
"execution_count": null,
|
| 333 |
+
"metadata": {},
|
| 334 |
+
"outputs": [],
|
| 335 |
+
"source": [
|
| 336 |
+
"# Stacking de modèles\n",
|
| 337 |
+
"estimators = [\n",
|
| 338 |
+
" ('xgb', xgb_model),\n",
|
| 339 |
+
" ('lgb', lgb_model),\n",
|
| 340 |
+
" ('ridge', ridge)\n",
|
| 341 |
+
"]\n",
|
| 342 |
+
"\n",
|
| 343 |
+
"stacking_model = StackingRegressor(\n",
|
| 344 |
+
" estimators=estimators,\n",
|
| 345 |
+
" final_estimator=Ridge(alpha=0.1),\n",
|
| 346 |
+
" cv=5,\n",
|
| 347 |
+
" n_jobs=-1\n",
|
| 348 |
+
")\n",
|
| 349 |
+
"\n",
|
| 350 |
+
"print(\"⏳ Évaluation Stacking...\")\n",
|
| 351 |
+
"stacking_scores = rmse_cv(stacking_model, X, y)\n",
|
| 352 |
+
"print(f\"Stacking RMSE : {stacking_scores.mean():.4f} (+/- {stacking_scores.std():.4f})\")"
|
| 353 |
+
]
|
| 354 |
+
},
|
| 355 |
+
{
|
| 356 |
+
"cell_type": "code",
|
| 357 |
+
"execution_count": null,
|
| 358 |
+
"metadata": {},
|
| 359 |
+
"outputs": [],
|
| 360 |
+
"source": [
|
| 361 |
+
"# Entraînement final et importance des features\n",
|
| 362 |
+
"xgb_model.fit(X, y)\n",
|
| 363 |
+
"\n",
|
| 364 |
+
"feature_importance = pd.DataFrame({\n",
|
| 365 |
+
" 'feature': features,\n",
|
| 366 |
+
" 'importance': xgb_model.feature_importances_\n",
|
| 367 |
+
"}).sort_values('importance', ascending=False)\n",
|
| 368 |
+
"\n",
|
| 369 |
+
"plt.figure(figsize=(10, 6))\n",
|
| 370 |
+
"sns.barplot(data=feature_importance, x='importance', y='feature', palette='viridis')\n",
|
| 371 |
+
"plt.title('Importance des features (XGBoost)')\n",
|
| 372 |
+
"plt.tight_layout()\n",
|
| 373 |
+
"plt.show()"
|
| 374 |
+
]
|
| 375 |
+
},
|
| 376 |
+
{
|
| 377 |
+
"cell_type": "code",
|
| 378 |
+
"execution_count": null,
|
| 379 |
+
"metadata": {},
|
| 380 |
+
"outputs": [],
|
| 381 |
+
"source": [
|
| 382 |
+
"# Résumé des performances\n",
|
| 383 |
+
"print(\"📊 Résumé des performances (RMSE) :\")\n",
|
| 384 |
+
"print(\"=\" * 40)\n",
|
| 385 |
+
"print(f\"Lasso : {lasso_scores.mean():.4f}\")\n",
|
| 386 |
+
"print(f\"Ridge : {ridge_scores.mean():.4f}\")\n",
|
| 387 |
+
"print(f\"XGBoost : {xgb_scores.mean():.4f}\")\n",
|
| 388 |
+
"print(f\"LightGBM : {lgb_scores.mean():.4f}\")\n",
|
| 389 |
+
"print(f\"Stacking : {stacking_scores.mean():.4f} ⭐\")"
|
| 390 |
+
]
|
| 391 |
+
},
|
| 392 |
+
{
|
| 393 |
+
"cell_type": "markdown",
|
| 394 |
+
"metadata": {},
|
| 395 |
+
"source": [
|
| 396 |
+
"## 🎓 Conclusion\n",
|
| 397 |
+
"\n",
|
| 398 |
+
"Dans ce TP avancé, nous avons :\n",
|
| 399 |
+
"\n",
|
| 400 |
+
"1. ✅ **Analysé** la distribution des prix et identifié les transformations nécessaires\n",
|
| 401 |
+
"2. ✅ **Créé** des features pertinentes (ratios, catégorisations)\n",
|
| 402 |
+
"3. ✅ **Comparé** plusieurs algorithmes de régression\n",
|
| 403 |
+
"4. ✅ **Utilisé** XGBoost et LightGBM pour de meilleures performances\n",
|
| 404 |
+
"5. ✅ **Combiné** les modèles avec le stacking\n",
|
| 405 |
+
"\n",
|
| 406 |
+
"**Résultat** : RMSE de ~0.45 avec le stacking (sur échelle log).\n",
|
| 407 |
+
"\n",
|
| 408 |
+
"**Améliorations possibles** :\n",
|
| 409 |
+
"- Feature engineering plus poussé (interactions, polynomial features)\n",
|
| 410 |
+
"- Optimisation des hyperparamètres avec Optuna\n",
|
| 411 |
+
"- Utilisation de réseaux de neurones pour la couche finale"
|
| 412 |
+
]
|
| 413 |
+
}
|
| 414 |
+
],
|
| 415 |
+
"metadata": {
|
| 416 |
+
"kernelspec": {
|
| 417 |
+
"display_name": "Python 3",
|
| 418 |
+
"language": "python",
|
| 419 |
+
"name": "python3"
|
| 420 |
+
},
|
| 421 |
+
"language_info": {
|
| 422 |
+
"codemirror_mode": {
|
| 423 |
+
"name": "ipython",
|
| 424 |
+
"version": 3
|
| 425 |
+
},
|
| 426 |
+
"file_extension": ".py",
|
| 427 |
+
"mimetype": "text/x-python",
|
| 428 |
+
"name": "python",
|
| 429 |
+
"nbconvert_exporter": "python",
|
| 430 |
+
"pygments_lexer": "ipython3",
|
| 431 |
+
"version": "3.8.0"
|
| 432 |
+
}
|
| 433 |
+
},
|
| 434 |
+
"nbformat": 4,
|
| 435 |
+
"nbformat_minor": 4
|
| 436 |
+
}
|
notebooks/TP3_Iris_Classification.ipynb
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"metadata": {},
|
| 6 |
+
"source": [
|
| 7 |
+
"# 🌸 TP-3 : Classification Iris — Introduction au ML\n",
|
| 8 |
+
"\n",
|
| 9 |
+
"**Objectif** : Classifier les iris en 3 espèces à partir de 4 features.\n",
|
| 10 |
+
"\n",
|
| 11 |
+
"**Dataset** : [Iris Flower Dataset](https://www.kaggle.com/datasets/uciml/iris)\n",
|
| 12 |
+
"\n",
|
| 13 |
+
"**Compétences** :\n",
|
| 14 |
+
"- Classification multi-classe\n",
|
| 15 |
+
"- Visualisation avec PCA\n",
|
| 16 |
+
"- Frontières de décision\n",
|
| 17 |
+
"- Comparaison d'algorithmes"
|
| 18 |
+
]
|
| 19 |
+
},
|
| 20 |
+
{
|
| 21 |
+
"cell_type": "code",
|
| 22 |
+
"execution_count": null,
|
| 23 |
+
"metadata": {},
|
| 24 |
+
"outputs": [],
|
| 25 |
+
"source": [
|
| 26 |
+
"import numpy as np\n",
|
| 27 |
+
"import pandas as pd\n",
|
| 28 |
+
"import matplotlib.pyplot as plt\n",
|
| 29 |
+
"import seaborn as sns\n",
|
| 30 |
+
"from sklearn.datasets import load_iris\n",
|
| 31 |
+
"from sklearn.model_selection import train_test_split, cross_val_score\n",
|
| 32 |
+
"from sklearn.preprocessing import StandardScaler\n",
|
| 33 |
+
"from sklearn.decomposition import PCA\n",
|
| 34 |
+
"from sklearn.neighbors import KNeighborsClassifier\n",
|
| 35 |
+
"from sklearn.svm import SVC\n",
|
| 36 |
+
"from sklearn.tree import DecisionTreeClassifier\n",
|
| 37 |
+
"from sklearn.ensemble import RandomForestClassifier\n",
|
| 38 |
+
"from sklearn.metrics import accuracy_score, classification_report, confusion_matrix\n",
|
| 39 |
+
"\n",
|
| 40 |
+
"sns.set_style('whitegrid')\n",
|
| 41 |
+
"print(\"✅ Bibliothèques importées !\")"
|
| 42 |
+
]
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"cell_type": "code",
|
| 46 |
+
"execution_count": null,
|
| 47 |
+
"metadata": {},
|
| 48 |
+
"outputs": [],
|
| 49 |
+
"source": [
|
| 50 |
+
"# Chargement des données\n",
|
| 51 |
+
"iris = load_iris()\n",
|
| 52 |
+
"X = iris.data\n",
|
| 53 |
+
"y = iris.target\n",
|
| 54 |
+
"feature_names = iris.feature_names\n",
|
| 55 |
+
"target_names = iris.target_names\n",
|
| 56 |
+
"\n",
|
| 57 |
+
"# Création d'un DataFrame\n",
|
| 58 |
+
"df = pd.DataFrame(X, columns=feature_names)\n",
|
| 59 |
+
"df['species'] = [target_names[i] for i in y]\n",
|
| 60 |
+
"\n",
|
| 61 |
+
"print(f\"📊 Dimensions : {df.shape}\")\n",
|
| 62 |
+
"print(f\"\\n🌸 Espèces : {target_names}\")\n",
|
| 63 |
+
"df.head()"
|
| 64 |
+
]
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"cell_type": "code",
|
| 68 |
+
"execution_count": null,
|
| 69 |
+
"metadata": {},
|
| 70 |
+
"outputs": [],
|
| 71 |
+
"source": [
|
| 72 |
+
"# Pairplot pour visualiser les relations\n",
|
| 73 |
+
"sns.pairplot(df, hue='species', palette='viridis', height=2.5)\n",
|
| 74 |
+
"plt.suptitle('Pairplot du dataset Iris', y=1.02, fontsize=14)\n",
|
| 75 |
+
"plt.show()"
|
| 76 |
+
]
|
| 77 |
+
},
|
| 78 |
+
{
|
| 79 |
+
"cell_type": "code",
|
| 80 |
+
"execution_count": null,
|
| 81 |
+
"metadata": {},
|
| 82 |
+
"outputs": [],
|
| 83 |
+
"source": [
|
| 84 |
+
"# Split et normalisation\n",
|
| 85 |
+
"X_train, X_test, y_train, y_test = train_test_split(\n",
|
| 86 |
+
" X, y, test_size=0.2, random_state=42, stratify=y\n",
|
| 87 |
+
")\n",
|
| 88 |
+
"\n",
|
| 89 |
+
"scaler = StandardScaler()\n",
|
| 90 |
+
"X_train_scaled = scaler.fit_transform(X_train)\n",
|
| 91 |
+
"X_test_scaled = scaler.transform(X_test)\n",
|
| 92 |
+
"\n",
|
| 93 |
+
"print(f\"Train : {X_train.shape[0]} échantillons\")\n",
|
| 94 |
+
"print(f\"Test : {X_test.shape[0]} échantillons\")"
|
| 95 |
+
]
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
"cell_type": "code",
|
| 99 |
+
"execution_count": null,
|
| 100 |
+
"metadata": {},
|
| 101 |
+
"outputs": [],
|
| 102 |
+
"source": [
|
| 103 |
+
"# Comparaison des modèles\n",
|
| 104 |
+
"models = {\n",
|
| 105 |
+
" 'KNN': KNeighborsClassifier(n_neighbors=5),\n",
|
| 106 |
+
" 'SVM': SVC(kernel='rbf', random_state=42),\n",
|
| 107 |
+
" 'Decision Tree': DecisionTreeClassifier(random_state=42),\n",
|
| 108 |
+
" 'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42)\n",
|
| 109 |
+
"}\n",
|
| 110 |
+
"\n",
|
| 111 |
+
"results = {}\n",
|
| 112 |
+
"for name, model in models.items():\n",
|
| 113 |
+
" model.fit(X_train_scaled, y_train)\n",
|
| 114 |
+
" y_pred = model.predict(X_test_scaled)\n",
|
| 115 |
+
" accuracy = accuracy_score(y_test, y_pred)\n",
|
| 116 |
+
" results[name] = accuracy\n",
|
| 117 |
+
" print(f\"{name:15} : {accuracy:.4f}\")"
|
| 118 |
+
]
|
| 119 |
+
},
|
| 120 |
+
{
|
| 121 |
+
"cell_type": "code",
|
| 122 |
+
"execution_count": null,
|
| 123 |
+
"metadata": {},
|
| 124 |
+
"outputs": [],
|
| 125 |
+
"source": [
|
| 126 |
+
"# Visualisation avec PCA (2D)\n",
|
| 127 |
+
"pca = PCA(n_components=2)\n",
|
| 128 |
+
"X_pca = pca.fit_transform(X_scaled := StandardScaler().fit_transform(X))\n",
|
| 129 |
+
"\n",
|
| 130 |
+
"plt.figure(figsize=(10, 6))\n",
|
| 131 |
+
"colors = ['red', 'green', 'blue']\n",
|
| 132 |
+
"for i, target_name in enumerate(target_names):\n",
|
| 133 |
+
" plt.scatter(X_pca[y == i, 0], X_pca[y == i, 1], \n",
|
| 134 |
+
" c=colors[i], label=target_name, alpha=0.7, s=50)\n",
|
| 135 |
+
"plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.2%})')\n",
|
| 136 |
+
"plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.2%})')\n",
|
| 137 |
+
"plt.title('Dataset Iris - Projection PCA')\n",
|
| 138 |
+
"plt.legend()\n",
|
| 139 |
+
"plt.show()\n",
|
| 140 |
+
"\n",
|
| 141 |
+
"print(f\"Variance expliquée : {pca.explained_variance_ratio_.sum():.2%}\")"
|
| 142 |
+
]
|
| 143 |
+
},
|
| 144 |
+
{
|
| 145 |
+
"cell_type": "code",
|
| 146 |
+
"execution_count": null,
|
| 147 |
+
"metadata": {},
|
| 148 |
+
"outputs": [],
|
| 149 |
+
"source": [
|
| 150 |
+
"# Matrice de confusion pour le meilleur modèle\n",
|
| 151 |
+
"best_model = SVC(kernel='rbf', random_state=42)\n",
|
| 152 |
+
"best_model.fit(X_train_scaled, y_train)\n",
|
| 153 |
+
"y_pred = best_model.predict(X_test_scaled)\n",
|
| 154 |
+
"\n",
|
| 155 |
+
"cm = confusion_matrix(y_test, y_pred)\n",
|
| 156 |
+
"\n",
|
| 157 |
+
"plt.figure(figsize=(8, 6))\n",
|
| 158 |
+
"sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',\n",
|
| 159 |
+
" xticklabels=target_names, yticklabels=target_names)\n",
|
| 160 |
+
"plt.title('Matrice de confusion - SVM')\n",
|
| 161 |
+
"plt.ylabel('Vrai label')\n",
|
| 162 |
+
"plt.xlabel('Prédiction')\n",
|
| 163 |
+
"plt.show()\n",
|
| 164 |
+
"\n",
|
| 165 |
+
"print(classification_report(y_test, y_pred, target_names=target_names))"
|
| 166 |
+
]
|
| 167 |
+
}
|
| 168 |
+
],
|
| 169 |
+
"metadata": {
|
| 170 |
+
"kernelspec": {
|
| 171 |
+
"display_name": "Python 3",
|
| 172 |
+
"language": "python",
|
| 173 |
+
"name": "python3"
|
| 174 |
+
},
|
| 175 |
+
"language_info": {
|
| 176 |
+
"name": "python",
|
| 177 |
+
"version": "3.8.0"
|
| 178 |
+
}
|
| 179 |
+
},
|
| 180 |
+
"nbformat": 4,
|
| 181 |
+
"nbformat_minor": 4
|
| 182 |
+
}
|
notebooks/TP4_LSTM_TimeSeries.ipynb
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"metadata": {},
|
| 6 |
+
"source": [
|
| 7 |
+
"# ⏱️ TP-4 : Prédiction de Séries Temporelles avec LSTM\n",
|
| 8 |
+
"\n",
|
| 9 |
+
"**Objectif** : Prédire la consommation électrique avec des réseaux LSTM.\n",
|
| 10 |
+
"\n",
|
| 11 |
+
"**Compétences** :\n",
|
| 12 |
+
"- Préparation de données temporelles\n",
|
| 13 |
+
"- Fenêtres glissantes (windowing)\n",
|
| 14 |
+
"- Architecture LSTM avec Keras\n",
|
| 15 |
+
"- Early stopping et régularisation"
|
| 16 |
+
]
|
| 17 |
+
},
|
| 18 |
+
{
|
| 19 |
+
"cell_type": "code",
|
| 20 |
+
"execution_count": null,
|
| 21 |
+
"metadata": {},
|
| 22 |
+
"outputs": [],
|
| 23 |
+
"source": [
|
| 24 |
+
"import numpy as np\n",
|
| 25 |
+
"import pandas as pd\n",
|
| 26 |
+
"import matplotlib.pyplot as plt\n",
|
| 27 |
+
"from sklearn.preprocessing import MinMaxScaler\n",
|
| 28 |
+
"from sklearn.metrics import mean_squared_error, mean_absolute_error\n",
|
| 29 |
+
"\n",
|
| 30 |
+
"import tensorflow as tf\n",
|
| 31 |
+
"from tensorflow.keras.models import Sequential\n",
|
| 32 |
+
"from tensorflow.keras.layers import LSTM, Dense, Dropout\n",
|
| 33 |
+
"from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\n",
|
| 34 |
+
"\n",
|
| 35 |
+
"# Reproductibilité\n",
|
| 36 |
+
"np.random.seed(42)\n",
|
| 37 |
+
"tf.random.set_seed(42)\n",
|
| 38 |
+
"\n",
|
| 39 |
+
"print(f\"✅ TensorFlow version : {tf.__version__}\")"
|
| 40 |
+
]
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"cell_type": "code",
|
| 44 |
+
"execution_count": null,
|
| 45 |
+
"metadata": {},
|
| 46 |
+
"outputs": [],
|
| 47 |
+
"source": [
|
| 48 |
+
"# Génération de données synthétiques (consommation électrique)\n",
|
| 49 |
+
"# En pratique, remplacez par vos données réelles\n",
|
| 50 |
+
"\n",
|
| 51 |
+
"def generate_energy_data(n_days=365*2):\n",
|
| 52 |
+
" \"\"\"Génère des données de consommation électrique simulées\"\"\"\n",
|
| 53 |
+
" hours = np.arange(n_days * 24)\n",
|
| 54 |
+
" \n",
|
| 55 |
+
" # Tendance\n",
|
| 56 |
+
" trend = 0.001 * hours\n",
|
| 57 |
+
" \n",
|
| 58 |
+
" # Saisonnalité journalière\n",
|
| 59 |
+
" daily = 10 * np.sin(2 * np.pi * hours / 24)\n",
|
| 60 |
+
" \n",
|
| 61 |
+
" # Saisonnalité hebdomadaire\n",
|
| 62 |
+
" weekly = 5 * np.sin(2 * np.pi * hours / (24 * 7))\n",
|
| 63 |
+
" \n",
|
| 64 |
+
" # Saisonnalité annuelle\n",
|
| 65 |
+
" yearly = 15 * np.sin(2 * np.pi * hours / (24 * 365))\n",
|
| 66 |
+
" \n",
|
| 67 |
+
" # Bruit\n",
|
| 68 |
+
" noise = np.random.normal(0, 3, len(hours))\n",
|
| 69 |
+
" \n",
|
| 70 |
+
" # Consommation totale\n",
|
| 71 |
+
" consumption = 50 + trend + daily + weekly + yearly + noise\n",
|
| 72 |
+
" consumption = np.maximum(consumption, 0) # Pas de valeurs négatives\n",
|
| 73 |
+
" \n",
|
| 74 |
+
" return consumption\n",
|
| 75 |
+
"\n",
|
| 76 |
+
"# Génération des données\n",
|
| 77 |
+
"data = generate_energy_data(n_days=730) # 2 ans de données\n",
|
| 78 |
+
"\n",
|
| 79 |
+
"# Création du DataFrame\n",
|
| 80 |
+
"dates = pd.date_range(start='2022-01-01', periods=len(data), freq='H')\n",
|
| 81 |
+
"df = pd.DataFrame({'consumption': data}, index=dates)\n",
|
| 82 |
+
"\n",
|
| 83 |
+
"print(f\"📊 Période : {df.index[0]} à {df.index[-1]}\")\n",
|
| 84 |
+
"print(f\"📊 Total : {len(df)} heures de données\")\n",
|
| 85 |
+
"df.head()"
|
| 86 |
+
]
|
| 87 |
+
},
|
| 88 |
+
{
|
| 89 |
+
"cell_type": "code",
|
| 90 |
+
"execution_count": null,
|
| 91 |
+
"metadata": {},
|
| 92 |
+
"outputs": [],
|
| 93 |
+
"source": [
|
| 94 |
+
"# Visualisation des données\n",
|
| 95 |
+
"fig, axes = plt.subplots(3, 1, figsize=(15, 10))\n",
|
| 96 |
+
"\n",
|
| 97 |
+
"# Vue complète\n",
|
| 98 |
+
"axes[0].plot(df.index, df['consumption'], alpha=0.7)\n",
|
| 99 |
+
"axes[0].set_title('Consommation électrique - Vue complète (2 ans)')\n",
|
| 100 |
+
"axes[0].set_ylabel('kWh')\n",
|
| 101 |
+
"\n",
|
| 102 |
+
"# Vue d'une semaine\n",
|
| 103 |
+
"one_week = df.iloc[:24*7]\n",
|
| 104 |
+
"axes[1].plot(one_week.index, one_week['consumption'], marker='o')\n",
|
| 105 |
+
"axes[1].set_title('Consommation - Vue hebdomadaire')\n",
|
| 106 |
+
"axes[1].set_ylabel('kWh')\n",
|
| 107 |
+
"\n",
|
| 108 |
+
"# Vue d'une journée\n",
|
| 109 |
+
"one_day = df.iloc[:24]\n",
|
| 110 |
+
"axes[2].plot(one_day.index.hour, one_day['consumption'], marker='o')\n",
|
| 111 |
+
"axes[2].set_title('Consommation - Vue journalière')\n",
|
| 112 |
+
"axes[2].set_xlabel('Heure')\n",
|
| 113 |
+
"axes[2].set_ylabel('kWh')\n",
|
| 114 |
+
"\n",
|
| 115 |
+
"plt.tight_layout()\n",
|
| 116 |
+
"plt.show()"
|
| 117 |
+
]
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"cell_type": "code",
|
| 121 |
+
"execution_count": null,
|
| 122 |
+
"metadata": {},
|
| 123 |
+
"outputs": [],
|
| 124 |
+
"source": [
|
| 125 |
+
"# Feature Engineering temporel\n",
|
| 126 |
+
"df['hour'] = df.index.hour\n",
|
| 127 |
+
"df['day_of_week'] = df.index.dayofweek\n",
|
| 128 |
+
"df['month'] = df.index.month\n",
|
| 129 |
+
"df['is_weekend'] = (df['day_of_week'] >= 5).astype(int)\n",
|
| 130 |
+
"\n",
|
| 131 |
+
"# Lags (valeurs précédentes)\n",
|
| 132 |
+
"for lag in [1, 2, 3, 24, 48]:\n",
|
| 133 |
+
" df[f'lag_{lag}'] = df['consumption'].shift(lag)\n",
|
| 134 |
+
"\n",
|
| 135 |
+
"# Rolling statistics\n",
|
| 136 |
+
"df['rolling_mean_24'] = df['consumption'].rolling(window=24).mean()\n",
|
| 137 |
+
"df['rolling_std_24'] = df['consumption'].rolling(window=24).std()\n",
|
| 138 |
+
"\n",
|
| 139 |
+
"# Suppression des NaN\n",
|
| 140 |
+
"df = df.dropna()\n",
|
| 141 |
+
"\n",
|
| 142 |
+
"print(f\"✅ Features créées : {df.shape[1]} colonnes\")\n",
|
| 143 |
+
"df.head()"
|
| 144 |
+
]
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"cell_type": "code",
|
| 148 |
+
"execution_count": null,
|
| 149 |
+
"metadata": {},
|
| 150 |
+
"outputs": [],
|
| 151 |
+
"source": [
|
| 152 |
+
"# Préparation des séquences pour LSTM\n",
|
| 153 |
+
"def create_sequences(data, target_col, sequence_length=24):\n",
|
| 154 |
+
" \"\"\"\n",
|
| 155 |
+
" Crée des séquences pour LSTM\n",
|
| 156 |
+
" data : DataFrame avec features\n",
|
| 157 |
+
" target_col : nom de la colonne cible\n",
|
| 158 |
+
" sequence_length : longueur de la séquence (ex: 24 heures)\n",
|
| 159 |
+
" \"\"\"\n",
|
| 160 |
+
" X, y = [], []\n",
|
| 161 |
+
" values = data.values\n",
|
| 162 |
+
" target_idx = data.columns.get_loc(target_col)\n",
|
| 163 |
+
" \n",
|
| 164 |
+
" for i in range(sequence_length, len(values)):\n",
|
| 165 |
+
" X.append(values[i-sequence_length:i])\n",
|
| 166 |
+
" y.append(values[i, target_idx])\n",
|
| 167 |
+
" \n",
|
| 168 |
+
" return np.array(X), np.array(y)\n",
|
| 169 |
+
"\n",
|
| 170 |
+
"# Séparation train/test\n",
|
| 171 |
+
"train_size = int(len(df) * 0.8)\n",
|
| 172 |
+
"train_df = df.iloc[:train_size]\n",
|
| 173 |
+
"test_df = df.iloc[train_size:]\n",
|
| 174 |
+
"\n",
|
| 175 |
+
"# Normalisation\n",
|
| 176 |
+
"scaler = MinMaxScaler()\n",
|
| 177 |
+
"train_scaled = scaler.fit_transform(train_df)\n",
|
| 178 |
+
"test_scaled = scaler.transform(test_df)\n",
|
| 179 |
+
"\n",
|
| 180 |
+
"# Conversion en DataFrame pour garder les noms de colonnes\n",
|
| 181 |
+
"train_scaled = pd.DataFrame(train_scaled, columns=df.columns, index=train_df.index)\n",
|
| 182 |
+
"test_scaled = pd.DataFrame(test_scaled, columns=df.columns, index=test_df.index)\n",
|
| 183 |
+
"\n",
|
| 184 |
+
"# Création des séquences\n",
|
| 185 |
+
"SEQUENCE_LENGTH = 24 # 24 heures d'historique\n",
|
| 186 |
+
"\n",
|
| 187 |
+
"X_train, y_train = create_sequences(train_scaled, 'consumption', SEQUENCE_LENGTH)\n",
|
| 188 |
+
"X_test, y_test = create_sequences(test_scaled, 'consumption', SEQUENCE_LENGTH)\n",
|
| 189 |
+
"\n",
|
| 190 |
+
"print(f\"📊 X_train shape : {X_train.shape}\")\n",
|
| 191 |
+
"print(f\"📊 y_train shape : {y_train.shape}\")\n",
|
| 192 |
+
"print(f\"📊 X_test shape : {X_test.shape}\")\n",
|
| 193 |
+
"print(f\"📊 y_test shape : {y_test.shape}\")"
|
| 194 |
+
]
|
| 195 |
+
},
|
| 196 |
+
{
|
| 197 |
+
"cell_type": "code",
|
| 198 |
+
"execution_count": null,
|
| 199 |
+
"metadata": {},
|
| 200 |
+
"outputs": [],
|
| 201 |
+
"source": [
|
| 202 |
+
"# Construction du modèle LSTM\n",
|
| 203 |
+
"model = Sequential([\n",
|
| 204 |
+
" LSTM(64, return_sequences=True, input_shape=(SEQUENCE_LENGTH, X_train.shape[2])),\n",
|
| 205 |
+
" Dropout(0.2),\n",
|
| 206 |
+
" LSTM(32, return_sequences=False),\n",
|
| 207 |
+
" Dropout(0.2),\n",
|
| 208 |
+
" Dense(16, activation='relu'),\n",
|
| 209 |
+
" Dense(1)\n",
|
| 210 |
+
"])\n",
|
| 211 |
+
"\n",
|
| 212 |
+
"model.compile(\n",
|
| 213 |
+
" optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),\n",
|
| 214 |
+
" loss='mse',\n",
|
| 215 |
+
" metrics=['mae']\n",
|
| 216 |
+
")\n",
|
| 217 |
+
"\n",
|
| 218 |
+
"model.summary()"
|
| 219 |
+
]
|
| 220 |
+
},
|
| 221 |
+
{
|
| 222 |
+
"cell_type": "code",
|
| 223 |
+
"execution_count": null,
|
| 224 |
+
"metadata": {},
|
| 225 |
+
"outputs": [],
|
| 226 |
+
"source": [
|
| 227 |
+
"# Callbacks\n",
|
| 228 |
+
"callbacks = [\n",
|
| 229 |
+
" EarlyStopping(\n",
|
| 230 |
+
" monitor='val_loss',\n",
|
| 231 |
+
" patience=10,\n",
|
| 232 |
+
" restore_best_weights=True\n",
|
| 233 |
+
" ),\n",
|
| 234 |
+
" ReduceLROnPlateau(\n",
|
| 235 |
+
" monitor='val_loss',\n",
|
| 236 |
+
" factor=0.5,\n",
|
| 237 |
+
" patience=5,\n",
|
| 238 |
+
" min_lr=1e-6\n",
|
| 239 |
+
" )\n",
|
| 240 |
+
"]\n",
|
| 241 |
+
"\n",
|
| 242 |
+
"# Entraînement\n",
|
| 243 |
+
"history = model.fit(\n",
|
| 244 |
+
" X_train, y_train,\n",
|
| 245 |
+
" epochs=100,\n",
|
| 246 |
+
" batch_size=32,\n",
|
| 247 |
+
" validation_split=0.2,\n",
|
| 248 |
+
" callbacks=callbacks,\n",
|
| 249 |
+
" verbose=1\n",
|
| 250 |
+
")"
|
| 251 |
+
]
|
| 252 |
+
},
|
| 253 |
+
{
|
| 254 |
+
"cell_type": "code",
|
| 255 |
+
"execution_count": null,
|
| 256 |
+
"metadata": {},
|
| 257 |
+
"outputs": [],
|
| 258 |
+
"source": [
|
| 259 |
+
"# Visualisation de l'entraînement\n",
|
| 260 |
+
"fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
|
| 261 |
+
"\n",
|
| 262 |
+
"# Loss\n",
|
| 263 |
+
"axes[0].plot(history.history['loss'], label='Train')\n",
|
| 264 |
+
"axes[0].plot(history.history['val_loss'], label='Validation')\n",
|
| 265 |
+
"axes[0].set_title('Loss (MSE)')\n",
|
| 266 |
+
"axes[0].set_xlabel('Epoch')\n",
|
| 267 |
+
"axes[0].set_ylabel('Loss')\n",
|
| 268 |
+
"axes[0].legend()\n",
|
| 269 |
+
"\n",
|
| 270 |
+
"# MAE\n",
|
| 271 |
+
"axes[1].plot(history.history['mae'], label='Train')\n",
|
| 272 |
+
"axes[1].plot(history.history['val_mae'], label='Validation')\n",
|
| 273 |
+
"axes[1].set_title('MAE')\n",
|
| 274 |
+
"axes[1].set_xlabel('Epoch')\n",
|
| 275 |
+
"axes[1].set_ylabel('MAE')\n",
|
| 276 |
+
"axes[1].legend()\n",
|
| 277 |
+
"\n",
|
| 278 |
+
"plt.tight_layout()\n",
|
| 279 |
+
"plt.show()"
|
| 280 |
+
]
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"cell_type": "code",
|
| 284 |
+
"execution_count": null,
|
| 285 |
+
"metadata": {},
|
| 286 |
+
"outputs": [],
|
| 287 |
+
"source": [
|
| 288 |
+
"# Prédictions\n",
|
| 289 |
+
"y_pred = model.predict(X_test)\n",
|
| 290 |
+
"\n",
|
| 291 |
+
"# Métriques (sur données normalisées)\n",
|
| 292 |
+
"mse = mean_squared_error(y_test, y_pred)\n",
|
| 293 |
+
"mae = mean_absolute_error(y_test, y_pred)\n",
|
| 294 |
+
"rmse = np.sqrt(mse)\n",
|
| 295 |
+
"\n",
|
| 296 |
+
"print(f\"📊 MSE : {mse:.6f}\")\n",
|
| 297 |
+
"print(f\"📊 MAE : {mae:.6f}\")\n",
|
| 298 |
+
"print(f\"📊 RMSE : {rmse:.6f}\")"
|
| 299 |
+
]
|
| 300 |
+
},
|
| 301 |
+
{
|
| 302 |
+
"cell_type": "code",
|
| 303 |
+
"execution_count": null,
|
| 304 |
+
"metadata": {},
|
| 305 |
+
"outputs": [],
|
| 306 |
+
"source": [
|
| 307 |
+
"# Visualisation des prédictions\n",
|
| 308 |
+
"plt.figure(figsize=(15, 6))\n",
|
| 309 |
+
"\n",
|
| 310 |
+
"# Plot des 500 premières prédictions\n",
|
| 311 |
+
"n_plot = 500\n",
|
| 312 |
+
"plt.plot(y_test[:n_plot], label='Réel', alpha=0.8)\n",
|
| 313 |
+
"plt.plot(y_pred[:n_plot], label='Prédit', alpha=0.8)\n",
|
| 314 |
+
"plt.title(f'Prédictions LSTM - {n_plot} premiers points de test')\n",
|
| 315 |
+
"plt.xlabel('Temps')\n",
|
| 316 |
+
"plt.ylabel('Consommation (normalisée)')\n",
|
| 317 |
+
"plt.legend()\n",
|
| 318 |
+
"plt.show()"
|
| 319 |
+
]
|
| 320 |
+
},
|
| 321 |
+
{
|
| 322 |
+
"cell_type": "code",
|
| 323 |
+
"execution_count": null,
|
| 324 |
+
"metadata": {},
|
| 325 |
+
"outputs": [],
|
| 326 |
+
"source": [
|
| 327 |
+
"# Scatter plot : Réel vs Prédit\n",
|
| 328 |
+
"plt.figure(figsize=(8, 8))\n",
|
| 329 |
+
"plt.scatter(y_test, y_pred, alpha=0.5)\n",
|
| 330 |
+
"plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)\n",
|
| 331 |
+
"plt.xlabel('Valeurs réelles')\n",
|
| 332 |
+
"plt.ylabel('Valeurs prédites')\n",
|
| 333 |
+
"plt.title('Réel vs Prédit')\n",
|
| 334 |
+
"plt.show()"
|
| 335 |
+
]
|
| 336 |
+
},
|
| 337 |
+
{
|
| 338 |
+
"cell_type": "markdown",
|
| 339 |
+
"metadata": {},
|
| 340 |
+
"source": [
|
| 341 |
+
"## 🎓 Conclusion\n",
|
| 342 |
+
"\n",
|
| 343 |
+
"Dans ce TP, nous avons :\n",
|
| 344 |
+
"\n",
|
| 345 |
+
"1. ✅ **Généré** des données de consommation électrique avec patterns temporels\n",
|
| 346 |
+
"2. ✅ **Créé** des features temporelles (heure, jour, mois, lags, rolling stats)\n",
|
| 347 |
+
"3. ✅ **Préparé** les séquences pour LSTM avec windowing\n",
|
| 348 |
+
"4. ✅ **Construit** un modèle LSTM avec Dropout et Early Stopping\n",
|
| 349 |
+
"5. ✅ **Évalué** les performances sur l'ensemble de test\n",
|
| 350 |
+
"\n",
|
| 351 |
+
"**Améliorations possibles** :\n",
|
| 352 |
+
"- Utiliser des données météo comme features externes\n",
|
| 353 |
+
"- Tester des architectures plus complexes (Bidirectional LSTM, GRU)\n",
|
| 354 |
+
"- Faire du multi-step forecasting (prédire plusieurs heures en avance)"
|
| 355 |
+
]
|
| 356 |
+
}
|
| 357 |
+
],
|
| 358 |
+
"metadata": {
|
| 359 |
+
"kernelspec": {
|
| 360 |
+
"display_name": "Python 3",
|
| 361 |
+
"language": "python",
|
| 362 |
+
"name": "python3"
|
| 363 |
+
},
|
| 364 |
+
"language_info": {
|
| 365 |
+
"name": "python",
|
| 366 |
+
"version": "3.8.0"
|
| 367 |
+
}
|
| 368 |
+
},
|
| 369 |
+
"nbformat": 4,
|
| 370 |
+
"nbformat_minor": 4
|
| 371 |
+
}
|
tp.html
ADDED
|
@@ -0,0 +1,1389 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="fr">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Travaux Pratiques — ML Academy</title>
|
| 7 |
+
<link rel="stylesheet" href="css/shared.css">
|
| 8 |
+
<style>
|
| 9 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 10 |
+
PAGE HERO
|
| 11 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 12 |
+
.tp-hero {
|
| 13 |
+
background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-tertiary) 100%);
|
| 14 |
+
border-bottom: 1px solid var(--border-color);
|
| 15 |
+
padding: var(--space-3xl) var(--space-xl);
|
| 16 |
+
text-align: center;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
.tp-hero-label {
|
| 20 |
+
font-family: 'JetBrains Mono', monospace;
|
| 21 |
+
font-size: 0.75rem;
|
| 22 |
+
color: var(--primary-light);
|
| 23 |
+
text-transform: uppercase;
|
| 24 |
+
letter-spacing: 2px;
|
| 25 |
+
margin-bottom: var(--space-md);
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
.tp-hero-title {
|
| 29 |
+
font-size: clamp(2rem, 5vw, 3rem);
|
| 30 |
+
font-weight: 700;
|
| 31 |
+
color: var(--text-primary);
|
| 32 |
+
margin-bottom: var(--space-md);
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
.tp-hero-subtitle {
|
| 36 |
+
font-size: 1.1rem;
|
| 37 |
+
color: var(--text-secondary);
|
| 38 |
+
max-width: 600px;
|
| 39 |
+
margin: 0 auto var(--space-xl);
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
.tp-hero-badges {
|
| 43 |
+
display: flex;
|
| 44 |
+
justify-content: center;
|
| 45 |
+
gap: var(--space-md);
|
| 46 |
+
flex-wrap: wrap;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 50 |
+
TP CONTAINER
|
| 51 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 52 |
+
.tp-container {
|
| 53 |
+
max-width: 1000px;
|
| 54 |
+
margin: 0 auto;
|
| 55 |
+
padding: var(--space-2xl) var(--space-xl);
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 59 |
+
TP CARD
|
| 60 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 61 |
+
.tp-card {
|
| 62 |
+
background: var(--bg-card);
|
| 63 |
+
border: 1px solid var(--border-color);
|
| 64 |
+
border-radius: var(--radius-lg);
|
| 65 |
+
overflow: hidden;
|
| 66 |
+
margin-bottom: var(--space-2xl);
|
| 67 |
+
transition: all var(--transition-base);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
.tp-card:hover {
|
| 71 |
+
border-color: var(--primary);
|
| 72 |
+
box-shadow: var(--shadow-lg), var(--shadow-glow);
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
.tp-header {
|
| 76 |
+
display: flex;
|
| 77 |
+
align-items: flex-start;
|
| 78 |
+
gap: var(--space-lg);
|
| 79 |
+
padding: var(--space-xl);
|
| 80 |
+
background: linear-gradient(135deg, var(--bg-card), var(--bg-tertiary));
|
| 81 |
+
border-bottom: 1px solid var(--border-color);
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
.tp-badge {
|
| 85 |
+
padding: var(--space-sm) var(--space-md);
|
| 86 |
+
border-radius: var(--radius-md);
|
| 87 |
+
font-family: 'JetBrains Mono', monospace;
|
| 88 |
+
font-size: 0.7rem;
|
| 89 |
+
font-weight: 600;
|
| 90 |
+
color: white;
|
| 91 |
+
text-transform: uppercase;
|
| 92 |
+
letter-spacing: 1px;
|
| 93 |
+
flex-shrink: 0;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
.tp-badge.titanic { background: linear-gradient(135deg, #1e40af, #3b82f6); }
|
| 97 |
+
.tp-badge.housing { background: linear-gradient(135deg, #047857, #10b981); }
|
| 98 |
+
.tp-badge.iris { background: linear-gradient(135deg, #b45309, #f59e0b); }
|
| 99 |
+
.tp-badge.energy { background: linear-gradient(135deg, #7c3aed, #a78bfa); }
|
| 100 |
+
.tp-badge.mnist { background: linear-gradient(135deg, #be123c, #f43f5e); }
|
| 101 |
+
.tp-badge.sentiment { background: linear-gradient(135deg, #0e7490, #06b6d4); }
|
| 102 |
+
|
| 103 |
+
.tp-header-content {
|
| 104 |
+
flex: 1;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
.tp-title {
|
| 108 |
+
font-size: 1.4rem;
|
| 109 |
+
font-weight: 700;
|
| 110 |
+
color: var(--text-primary);
|
| 111 |
+
margin-bottom: var(--space-sm);
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
.tp-meta {
|
| 115 |
+
display: flex;
|
| 116 |
+
gap: var(--space-sm);
|
| 117 |
+
flex-wrap: wrap;
|
| 118 |
+
margin-bottom: var(--space-sm);
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
.tp-description {
|
| 122 |
+
font-size: 0.95rem;
|
| 123 |
+
color: var(--text-secondary);
|
| 124 |
+
line-height: 1.6;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
.tp-colab-btn {
|
| 128 |
+
display: inline-flex;
|
| 129 |
+
align-items: center;
|
| 130 |
+
gap: var(--space-sm);
|
| 131 |
+
padding: var(--space-sm) var(--space-md);
|
| 132 |
+
background: #f9ab00;
|
| 133 |
+
color: #000;
|
| 134 |
+
font-family: 'JetBrains Mono', monospace;
|
| 135 |
+
font-size: 0.8rem;
|
| 136 |
+
font-weight: 600;
|
| 137 |
+
text-decoration: none;
|
| 138 |
+
border-radius: var(--radius-md);
|
| 139 |
+
transition: all var(--transition-base);
|
| 140 |
+
flex-shrink: 0;
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
.tp-colab-btn:hover {
|
| 144 |
+
background: #fbbf24;
|
| 145 |
+
transform: translateY(-2px);
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 149 |
+
TP BODY
|
| 150 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 151 |
+
.tp-body {
|
| 152 |
+
padding: var(--space-xl);
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
.tp-goals {
|
| 156 |
+
display: grid;
|
| 157 |
+
grid-template-columns: repeat(2, 1fr);
|
| 158 |
+
gap: 0;
|
| 159 |
+
border: 1px solid var(--border-color);
|
| 160 |
+
border-radius: var(--radius-md);
|
| 161 |
+
overflow: hidden;
|
| 162 |
+
margin-bottom: var(--space-xl);
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
.tp-goal-box {
|
| 166 |
+
padding: var(--space-lg);
|
| 167 |
+
background: var(--bg-tertiary);
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
.tp-goal-box:first-child {
|
| 171 |
+
border-right: 1px solid var(--border-color);
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
.tp-goal-label {
|
| 175 |
+
font-family: 'JetBrains Mono', monospace;
|
| 176 |
+
font-size: 0.65rem;
|
| 177 |
+
color: var(--text-muted);
|
| 178 |
+
text-transform: uppercase;
|
| 179 |
+
letter-spacing: 1px;
|
| 180 |
+
margin-bottom: var(--space-sm);
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
.tp-goal-text {
|
| 184 |
+
font-size: 0.9rem;
|
| 185 |
+
color: var(--text-secondary);
|
| 186 |
+
line-height: 1.6;
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
.tp-goal-text strong {
|
| 190 |
+
color: var(--success);
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 194 |
+
CONCEPTS GRID
|
| 195 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 196 |
+
.concepts-title {
|
| 197 |
+
font-size: 1rem;
|
| 198 |
+
font-weight: 600;
|
| 199 |
+
color: var(--text-primary);
|
| 200 |
+
margin-bottom: var(--space-md);
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
.concepts-grid {
|
| 204 |
+
display: grid;
|
| 205 |
+
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
| 206 |
+
gap: var(--space-sm);
|
| 207 |
+
margin-bottom: var(--space-xl);
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
.concept-item {
|
| 211 |
+
background: var(--bg-tertiary);
|
| 212 |
+
border: 1px solid var(--border-color);
|
| 213 |
+
border-radius: var(--radius-md);
|
| 214 |
+
padding: var(--space-md);
|
| 215 |
+
transition: all var(--transition-base);
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
.concept-item:hover {
|
| 219 |
+
border-color: var(--primary);
|
| 220 |
+
transform: translateY(-2px);
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
.concept-name {
|
| 224 |
+
font-size: 0.85rem;
|
| 225 |
+
font-weight: 600;
|
| 226 |
+
color: var(--text-primary);
|
| 227 |
+
margin-bottom: var(--space-xs);
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
.concept-desc {
|
| 231 |
+
font-size: 0.75rem;
|
| 232 |
+
color: var(--text-muted);
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 236 |
+
STEPS
|
| 237 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 238 |
+
.steps-title {
|
| 239 |
+
font-size: 1rem;
|
| 240 |
+
font-weight: 600;
|
| 241 |
+
color: var(--text-primary);
|
| 242 |
+
margin-bottom: var(--space-md);
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
.steps-list {
|
| 246 |
+
display: flex;
|
| 247 |
+
flex-direction: column;
|
| 248 |
+
gap: 0;
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
.step-item {
|
| 252 |
+
display: flex;
|
| 253 |
+
gap: 0;
|
| 254 |
+
position: relative;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
.step-item:not(:last-child)::after {
|
| 258 |
+
content: '';
|
| 259 |
+
position: absolute;
|
| 260 |
+
left: 20px;
|
| 261 |
+
top: 45px;
|
| 262 |
+
bottom: 0;
|
| 263 |
+
width: 2px;
|
| 264 |
+
background: linear-gradient(180deg, var(--primary), var(--secondary));
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
.step-dot {
|
| 268 |
+
width: 42px;
|
| 269 |
+
height: 42px;
|
| 270 |
+
background: rgba(99, 102, 241, 0.15);
|
| 271 |
+
border: 2px solid var(--primary);
|
| 272 |
+
border-radius: 50%;
|
| 273 |
+
display: flex;
|
| 274 |
+
align-items: center;
|
| 275 |
+
justify-content: center;
|
| 276 |
+
font-family: 'JetBrains Mono', monospace;
|
| 277 |
+
font-size: 0.9rem;
|
| 278 |
+
font-weight: 600;
|
| 279 |
+
color: var(--primary-light);
|
| 280 |
+
flex-shrink: 0;
|
| 281 |
+
margin-top: 2px;
|
| 282 |
+
z-index: 1;
|
| 283 |
+
}
|
| 284 |
+
|
| 285 |
+
.step-content {
|
| 286 |
+
flex: 1;
|
| 287 |
+
padding: 0 0 var(--space-xl) var(--space-lg);
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
.step-title {
|
| 291 |
+
font-size: 1rem;
|
| 292 |
+
font-weight: 600;
|
| 293 |
+
color: var(--text-primary);
|
| 294 |
+
margin-bottom: var(--space-xs);
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
.step-desc {
|
| 298 |
+
font-size: 0.9rem;
|
| 299 |
+
color: var(--text-secondary);
|
| 300 |
+
margin-bottom: var(--space-md);
|
| 301 |
+
line-height: 1.6;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 305 |
+
DATASET INFO
|
| 306 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 307 |
+
.dataset-info {
|
| 308 |
+
display: flex;
|
| 309 |
+
align-items: center;
|
| 310 |
+
gap: var(--space-md);
|
| 311 |
+
padding: var(--space-md) var(--space-lg);
|
| 312 |
+
background: rgba(99, 102, 241, 0.05);
|
| 313 |
+
border: 1px solid rgba(99, 102, 241, 0.2);
|
| 314 |
+
border-radius: var(--radius-md);
|
| 315 |
+
margin-bottom: var(--space-lg);
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
.dataset-icon {
|
| 319 |
+
font-size: 1.5rem;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
.dataset-content {
|
| 323 |
+
flex: 1;
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
.dataset-name {
|
| 327 |
+
font-size: 0.85rem;
|
| 328 |
+
font-weight: 600;
|
| 329 |
+
color: var(--text-primary);
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
.dataset-link {
|
| 333 |
+
font-size: 0.75rem;
|
| 334 |
+
color: var(--primary-light);
|
| 335 |
+
text-decoration: none;
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
.dataset-link:hover {
|
| 339 |
+
text-decoration: underline;
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
.dataset-stats {
|
| 343 |
+
display: flex;
|
| 344 |
+
gap: var(--space-md);
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
.dataset-stat {
|
| 348 |
+
text-align: center;
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
.dataset-stat-value {
|
| 352 |
+
font-family: 'JetBrains Mono', monospace;
|
| 353 |
+
font-size: 1rem;
|
| 354 |
+
font-weight: 700;
|
| 355 |
+
color: var(--text-primary);
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
.dataset-stat-label {
|
| 359 |
+
font-size: 0.65rem;
|
| 360 |
+
color: var(--text-muted);
|
| 361 |
+
text-transform: uppercase;
|
| 362 |
+
}
|
| 363 |
+
|
| 364 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 365 |
+
EXPECTED OUTPUT
|
| 366 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 367 |
+
.expected-output {
|
| 368 |
+
background: rgba(16, 185, 129, 0.08);
|
| 369 |
+
border: 1px solid rgba(16, 185, 129, 0.25);
|
| 370 |
+
border-radius: var(--radius-md);
|
| 371 |
+
padding: var(--space-md) var(--space-lg);
|
| 372 |
+
margin-top: var(--space-md);
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
.expected-label {
|
| 376 |
+
font-family: 'JetBrains Mono', monospace;
|
| 377 |
+
font-size: 0.65rem;
|
| 378 |
+
color: var(--success);
|
| 379 |
+
text-transform: uppercase;
|
| 380 |
+
letter-spacing: 1px;
|
| 381 |
+
margin-bottom: var(--space-xs);
|
| 382 |
+
}
|
| 383 |
+
|
| 384 |
+
.expected-text {
|
| 385 |
+
font-family: 'JetBrains Mono', monospace;
|
| 386 |
+
font-size: 0.8rem;
|
| 387 |
+
color: var(--text-secondary);
|
| 388 |
+
line-height: 1.6;
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 392 |
+
CTA SECTION
|
| 393 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 394 |
+
.tp-cta {
|
| 395 |
+
text-align: center;
|
| 396 |
+
padding: var(--space-3xl);
|
| 397 |
+
background: linear-gradient(135deg, var(--bg-card), var(--bg-tertiary));
|
| 398 |
+
border: 1px solid var(--border-color);
|
| 399 |
+
border-radius: var(--radius-lg);
|
| 400 |
+
margin-top: var(--space-2xl);
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
.tp-cta-icon {
|
| 404 |
+
font-size: 3rem;
|
| 405 |
+
margin-bottom: var(--space-md);
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
.tp-cta-title {
|
| 409 |
+
font-size: 1.5rem;
|
| 410 |
+
font-weight: 700;
|
| 411 |
+
color: var(--text-primary);
|
| 412 |
+
margin-bottom: var(--space-sm);
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
.tp-cta-text {
|
| 416 |
+
font-size: 1rem;
|
| 417 |
+
color: var(--text-secondary);
|
| 418 |
+
margin-bottom: var(--space-xl);
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
/* ═══════════════════════════════════════════════════════════════════════════
|
| 422 |
+
RESPONSIVE
|
| 423 |
+
═══════════════════════════════════════════════════════════════════════════ */
|
| 424 |
+
@media (max-width: 768px) {
|
| 425 |
+
.tp-goals {
|
| 426 |
+
grid-template-columns: 1fr;
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
.tp-goal-box:first-child {
|
| 430 |
+
border-right: none;
|
| 431 |
+
border-bottom: 1px solid var(--border-color);
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
.tp-header {
|
| 435 |
+
flex-direction: column;
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
.dataset-info {
|
| 439 |
+
flex-direction: column;
|
| 440 |
+
text-align: center;
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
.dataset-stats {
|
| 444 |
+
justify-content: center;
|
| 445 |
+
}
|
| 446 |
+
}
|
| 447 |
+
</style>
|
| 448 |
+
</head>
|
| 449 |
+
<body>
|
| 450 |
+
<!-- Particles Background -->
|
| 451 |
+
<div class="particles-container">
|
| 452 |
+
<div class="particle"></div>
|
| 453 |
+
<div class="particle"></div>
|
| 454 |
+
<div class="particle"></div>
|
| 455 |
+
<div class="particle"></div>
|
| 456 |
+
<div class="particle"></div>
|
| 457 |
+
</div>
|
| 458 |
+
|
| 459 |
+
<!-- Navigation -->
|
| 460 |
+
<nav class="navbar">
|
| 461 |
+
<a href="index.html" class="navbar-brand">
|
| 462 |
+
<div class="brand-logo">🧠</div>
|
| 463 |
+
<span>ML Academy</span>
|
| 464 |
+
</a>
|
| 465 |
+
<div class="navbar-nav">
|
| 466 |
+
<a href="index.html" class="nav-link">
|
| 467 |
+
<span class="nav-icon">🏠</span>
|
| 468 |
+
<span>Accueil</span>
|
| 469 |
+
</a>
|
| 470 |
+
<a href="cours.html" class="nav-link">
|
| 471 |
+
<span class="nav-icon">📚</span>
|
| 472 |
+
<span>Cours</span>
|
| 473 |
+
</a>
|
| 474 |
+
<a href="tp.html" class="nav-link active">
|
| 475 |
+
<span class="nav-icon">💻</span>
|
| 476 |
+
<span>TPs</span>
|
| 477 |
+
</a>
|
| 478 |
+
<a href="feedback.html" class="nav-link">
|
| 479 |
+
<span class="nav-icon">💬</span>
|
| 480 |
+
<span>Contact</span>
|
| 481 |
+
</a>
|
| 482 |
+
</div>
|
| 483 |
+
<div class="nav-badge">
|
| 484 |
+
<div class="dot"></div>
|
| 485 |
+
<span>Google Colab Ready</span>
|
| 486 |
+
</div>
|
| 487 |
+
</nav>
|
| 488 |
+
|
| 489 |
+
<!-- Page Wrapper -->
|
| 490 |
+
<div class="page-wrapper">
|
| 491 |
+
<!-- Hero -->
|
| 492 |
+
<section class="tp-hero">
|
| 493 |
+
<div class="tp-hero-label">Travaux Pratiques</div>
|
| 494 |
+
<h1 class="tp-hero-title">💻 Notebooks Guidés</h1>
|
| 495 |
+
<p class="tp-hero-subtitle">
|
| 496 |
+
6 TPs complets sur des datasets réels de Kaggle. Exécutez directement sur Google Colab,
|
| 497 |
+
aucune installation requise.
|
| 498 |
+
</p>
|
| 499 |
+
<div class="tp-hero-badges">
|
| 500 |
+
<span class="badge badge-primary">📊 6 Notebooks</span>
|
| 501 |
+
<span class="badge badge-success">☁️ Google Colab</span>
|
| 502 |
+
<span class="badge badge-secondary">📈 Datasets Kaggle</span>
|
| 503 |
+
<span class="badge badge-accent">0 Installation</span>
|
| 504 |
+
</div>
|
| 505 |
+
</section>
|
| 506 |
+
|
| 507 |
+
<!-- TP Container -->
|
| 508 |
+
<div class="tp-container">
|
| 509 |
+
|
| 510 |
+
<!-- TP 1: Titanic -->
|
| 511 |
+
<div class="tp-card scroll-animate">
|
| 512 |
+
<div class="tp-header">
|
| 513 |
+
<div class="tp-badge titanic">TP-1</div>
|
| 514 |
+
<div class="tp-header-content">
|
| 515 |
+
<h2 class="tp-title">Survie sur le Titanic — Classification</h2>
|
| 516 |
+
<div class="tp-meta">
|
| 517 |
+
<span class="badge badge-primary">⏱️ 30 min</span>
|
| 518 |
+
<span class="badge badge-secondary">Classification</span>
|
| 519 |
+
<span class="badge badge-success">Scikit-learn</span>
|
| 520 |
+
<span class="badge badge-accent">Pandas</span>
|
| 521 |
+
</div>
|
| 522 |
+
<p class="tp-description">
|
| 523 |
+
Prédire la survie des passagers du Titanic à partir de leurs caractéristiques
|
| 524 |
+
(âge, sexe, classe, etc.). Le dataset classique pour débuter en ML.
|
| 525 |
+
</p>
|
| 526 |
+
</div>
|
| 527 |
+
<a href="https://colab.research.google.com/drive/1TqBXWkU3XbX7QzvVv9ZqZqZqZqZqZqZq" target="_blank" class="tp-colab-btn">
|
| 528 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
| 529 |
+
<path d="M16.9 4.8C14.4 2.4 10.7 1.7 7.5 3.1L10 5.6c1.8-.4 3.8 0 5.2 1.4 2.3 2.3 2.3 6 0 8.3-1.4 1.4-3.4 1.9-5.2 1.5L7.5 19.2c3.2 1.3 6.9.6 9.4-1.8 3.4-3.4 3.4-9.2 0-12.6zm-9.8.8L4.8 8c-.8 1.2-1.2 2.6-1.2 4s.4 2.8 1.2 4l2.3-2.3c-.4-.5-.7-1.1-.8-1.7H8V9.9H6.3c.1-.6.4-1.2.8-1.7z"/>
|
| 530 |
+
</svg>
|
| 531 |
+
Ouvrir dans Colab
|
| 532 |
+
</a>
|
| 533 |
+
</div>
|
| 534 |
+
|
| 535 |
+
<div class="tp-body">
|
| 536 |
+
<div class="dataset-info">
|
| 537 |
+
<div class="dataset-icon">🚢</div>
|
| 538 |
+
<div class="dataset-content">
|
| 539 |
+
<div class="dataset-name">Dataset : Titanic - Machine Learning from Disaster</div>
|
| 540 |
+
<a href="https://www.kaggle.com/competitions/titanic" target="_blank" class="dataset-link">
|
| 541 |
+
🔗 kaggle.com/competitions/titanic
|
| 542 |
+
</a>
|
| 543 |
+
</div>
|
| 544 |
+
<div class="dataset-stats">
|
| 545 |
+
<div class="dataset-stat">
|
| 546 |
+
<div class="dataset-stat-value">891</div>
|
| 547 |
+
<div class="dataset-stat-label">Lignes</div>
|
| 548 |
+
</div>
|
| 549 |
+
<div class="dataset-stat">
|
| 550 |
+
<div class="dataset-stat-value">12</div>
|
| 551 |
+
<div class="dataset-stat-label">Colonnes</div>
|
| 552 |
+
</div>
|
| 553 |
+
</div>
|
| 554 |
+
</div>
|
| 555 |
+
|
| 556 |
+
<div class="tp-goals">
|
| 557 |
+
<div class="tp-goal-box">
|
| 558 |
+
<div class="tp-goal-label">🎯 Objectif</div>
|
| 559 |
+
<p class="tp-goal-text">
|
| 560 |
+
Construire un modèle de classification binaire pour prédire si un passager
|
| 561 |
+
a survécu ou non au naufrage du Titanic.
|
| 562 |
+
</p>
|
| 563 |
+
</div>
|
| 564 |
+
<div class="tp-goal-box">
|
| 565 |
+
<div class="tp-goal-label">✅ Résultat attendu</div>
|
| 566 |
+
<p class="tp-goal-text">
|
| 567 |
+
Accuracy > <strong>80%</strong> sur l'ensemble de test.
|
| 568 |
+
Analyse de l'importance des features.
|
| 569 |
+
</p>
|
| 570 |
+
</div>
|
| 571 |
+
</div>
|
| 572 |
+
|
| 573 |
+
<h3 class="concepts-title">🧠 Concepts utilisés</h3>
|
| 574 |
+
<div class="concepts-grid">
|
| 575 |
+
<div class="concept-item">
|
| 576 |
+
<div class="concept-name">Prétraitement</div>
|
| 577 |
+
<div class="concept-desc">Gestion des valeurs manquantes</div>
|
| 578 |
+
</div>
|
| 579 |
+
<div class="concept-item">
|
| 580 |
+
<div class="concept-name">Encodage</div>
|
| 581 |
+
<div class="concept-desc">Variables catégorielles</div>
|
| 582 |
+
</div>
|
| 583 |
+
<div class="concept-item">
|
| 584 |
+
<div class="concept-name">Feature Engineering</div>
|
| 585 |
+
<div class="concept-desc">Création de nouvelles features</div>
|
| 586 |
+
</div>
|
| 587 |
+
<div class="concept-item">
|
| 588 |
+
<div class="concept-name">Random Forest</div>
|
| 589 |
+
<div class="concept-desc">Classification</div>
|
| 590 |
+
</div>
|
| 591 |
+
<div class="concept-item">
|
| 592 |
+
<div class="concept-name">Cross-Validation</div>
|
| 593 |
+
<div class="concept-desc">Évaluation robuste</div>
|
| 594 |
+
</div>
|
| 595 |
+
<div class="concept-item">
|
| 596 |
+
<div class="concept-name">Grid Search</div>
|
| 597 |
+
<div class="concept-desc">Optimisation hyperparamètres</div>
|
| 598 |
+
</div>
|
| 599 |
+
</div>
|
| 600 |
+
|
| 601 |
+
<h3 class="steps-title">📋 Étapes du TP</h3>
|
| 602 |
+
<div class="steps-list">
|
| 603 |
+
<div class="step-item">
|
| 604 |
+
<div class="step-dot">1</div>
|
| 605 |
+
<div class="step-content">
|
| 606 |
+
<div class="step-title">Exploration des données</div>
|
| 607 |
+
<div class="step-desc">
|
| 608 |
+
Charger le dataset, analyser la distribution des variables,
|
| 609 |
+
identifier les valeurs manquantes et les outliers.
|
| 610 |
+
</div>
|
| 611 |
+
</div>
|
| 612 |
+
</div>
|
| 613 |
+
<div class="step-item">
|
| 614 |
+
<div class="step-dot">2</div>
|
| 615 |
+
<div class="step-content">
|
| 616 |
+
<div class="step-title">Prétraitement</div>
|
| 617 |
+
<div class="step-desc">
|
| 618 |
+
Remplir les valeurs manquantes, encoder les variables catégorielles
|
| 619 |
+
(Sex, Embarked), créer des features (FamilySize, IsAlone).
|
| 620 |
+
</div>
|
| 621 |
+
</div>
|
| 622 |
+
</div>
|
| 623 |
+
<div class="step-item">
|
| 624 |
+
<div class="step-dot">3</div>
|
| 625 |
+
<div class="step-content">
|
| 626 |
+
<div class="step-title">Modélisation</div>
|
| 627 |
+
<div class="step-desc">
|
| 628 |
+
Entraîner plusieurs modèles : Logistic Regression, Random Forest,
|
| 629 |
+
Gradient Boosting. Comparer leurs performances.
|
| 630 |
+
</div>
|
| 631 |
+
<div class="expected-output">
|
| 632 |
+
<div class="expected-label">Résultats attendus</div>
|
| 633 |
+
<div class="expected-text">
|
| 634 |
+
Random Forest: 82% accuracy<br>
|
| 635 |
+
Feature importance: Sex > Pclass > Age > Fare
|
| 636 |
+
</div>
|
| 637 |
+
</div>
|
| 638 |
+
</div>
|
| 639 |
+
</div>
|
| 640 |
+
</div>
|
| 641 |
+
</div>
|
| 642 |
+
</div>
|
| 643 |
+
|
| 644 |
+
<!-- TP 2: House Prices -->
|
| 645 |
+
<div class="tp-card scroll-animate">
|
| 646 |
+
<div class="tp-header">
|
| 647 |
+
<div class="tp-badge housing">TP-2</div>
|
| 648 |
+
<div class="tp-header-content">
|
| 649 |
+
<h2 class="tp-title">Prix des Maisons — Régression Avancée</h2>
|
| 650 |
+
<div class="tp-meta">
|
| 651 |
+
<span class="badge badge-primary">⏱️ 45 min</span>
|
| 652 |
+
<span class="badge badge-secondary">Régression</span>
|
| 653 |
+
<span class="badge badge-success">XGBoost</span>
|
| 654 |
+
<span class="badge badge-accent">Feature Engineering</span>
|
| 655 |
+
</div>
|
| 656 |
+
<p class="tp-description">
|
| 657 |
+
Prédire le prix de vente des maisons à Ames, Iowa. Un problème de régression
|
| 658 |
+
riche en features avec beaucoup de prétraitement nécessaire.
|
| 659 |
+
</p>
|
| 660 |
+
</div>
|
| 661 |
+
<a href="https://colab.research.google.com/drive/1TqBXWkU3XbX7QzvVv9ZqZqZqZqZqZqZq" target="_blank" class="tp-colab-btn">
|
| 662 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
| 663 |
+
<path d="M16.9 4.8C14.4 2.4 10.7 1.7 7.5 3.1L10 5.6c1.8-.4 3.8 0 5.2 1.4 2.3 2.3 2.3 6 0 8.3-1.4 1.4-3.4 1.9-5.2 1.5L7.5 19.2c3.2 1.3 6.9.6 9.4-1.8 3.4-3.4 3.4-9.2 0-12.6zm-9.8.8L4.8 8c-.8 1.2-1.2 2.6-1.2 4s.4 2.8 1.2 4l2.3-2.3c-.4-.5-.7-1.1-.8-1.7H8V9.9H6.3c.1-.6.4-1.2.8-1.7z"/>
|
| 664 |
+
</svg>
|
| 665 |
+
Ouvrir dans Colab
|
| 666 |
+
</a>
|
| 667 |
+
</div>
|
| 668 |
+
|
| 669 |
+
<div class="tp-body">
|
| 670 |
+
<div class="dataset-info">
|
| 671 |
+
<div class="dataset-icon">🏠</div>
|
| 672 |
+
<div class="dataset-content">
|
| 673 |
+
<div class="dataset-name">Dataset : House Prices - Advanced Regression Techniques</div>
|
| 674 |
+
<a href="https://www.kaggle.com/competitions/house-prices-advanced-regression-techniques" target="_blank" class="dataset-link">
|
| 675 |
+
🔗 kaggle.com/competitions/house-prices
|
| 676 |
+
</a>
|
| 677 |
+
</div>
|
| 678 |
+
<div class="dataset-stats">
|
| 679 |
+
<div class="dataset-stat">
|
| 680 |
+
<div class="dataset-stat-value">1460</div>
|
| 681 |
+
<div class="dataset-stat-label">Lignes</div>
|
| 682 |
+
</div>
|
| 683 |
+
<div class="dataset-stat">
|
| 684 |
+
<div class="dataset-stat-value">81</div>
|
| 685 |
+
<div class="dataset-stat-label">Colonnes</div>
|
| 686 |
+
</div>
|
| 687 |
+
</div>
|
| 688 |
+
</div>
|
| 689 |
+
|
| 690 |
+
<div class="tp-goals">
|
| 691 |
+
<div class="tp-goal-box">
|
| 692 |
+
<div class="tp-goal-label">🎯 Objectif</div>
|
| 693 |
+
<p class="tp-goal-text">
|
| 694 |
+
Prédire le prix de vente des maisons avec le plus faible RMSE possible
|
| 695 |
+
en utilisant 79 features explicatives.
|
| 696 |
+
</p>
|
| 697 |
+
</div>
|
| 698 |
+
<div class="tp-goal-box">
|
| 699 |
+
<div class="tp-goal-label">✅ Résultat attendu</div>
|
| 700 |
+
<p class="tp-goal-text">
|
| 701 |
+
RMSE <strong>< 30,000$</strong> sur log-transformed prices.
|
| 702 |
+
Top 20% du leaderboard Kaggle.
|
| 703 |
+
</p>
|
| 704 |
+
</div>
|
| 705 |
+
</div>
|
| 706 |
+
|
| 707 |
+
<h3 class="concepts-title">🧠 Concepts utilisés</h3>
|
| 708 |
+
<div class="concepts-grid">
|
| 709 |
+
<div class="concept-item">
|
| 710 |
+
<div class="concept-name">Outlier Detection</div>
|
| 711 |
+
<div class="concept-desc">Détection et traitement</div>
|
| 712 |
+
</div>
|
| 713 |
+
<div class="concept-item">
|
| 714 |
+
<div class="concept-name">Skewness</div>
|
| 715 |
+
<div class="concept-desc">Transformation log</div>
|
| 716 |
+
</div>
|
| 717 |
+
<div class="concept-item">
|
| 718 |
+
<div class="concept-name">Correlation Analysis</div>
|
| 719 |
+
<div class="concept-desc">Matrice de corrélation</div>
|
| 720 |
+
</div>
|
| 721 |
+
<div class="concept-item">
|
| 722 |
+
<div class="concept-name">XGBoost</div>
|
| 723 |
+
<div class="concept-desc">Gradient boosting</div>
|
| 724 |
+
</div>
|
| 725 |
+
<div class="concept-item">
|
| 726 |
+
<div class="concept-name">Stacking</div>
|
| 727 |
+
<div class="concept-desc">Ensemble de modèles</div>
|
| 728 |
+
</div>
|
| 729 |
+
<div class="concept-item">
|
| 730 |
+
<div class="concept-name">K-Fold CV</div>
|
| 731 |
+
<div class="concept-desc">Validation croisée</div>
|
| 732 |
+
</div>
|
| 733 |
+
</div>
|
| 734 |
+
|
| 735 |
+
<h3 class="steps-title">📋 Étapes du TP</h3>
|
| 736 |
+
<div class="steps-list">
|
| 737 |
+
<div class="step-item">
|
| 738 |
+
<div class="step-dot">1</div>
|
| 739 |
+
<div class="step-content">
|
| 740 |
+
<div class="step-title">Analyse exploratoire avancée</div>
|
| 741 |
+
<div class="step-desc">
|
| 742 |
+
Visualiser la distribution des prix, identifier les outliers,
|
| 743 |
+
analyser les corrélations entre features et prix.
|
| 744 |
+
</div>
|
| 745 |
+
</div>
|
| 746 |
+
</div>
|
| 747 |
+
<div class="step-item">
|
| 748 |
+
<div class="step-dot">2</div>
|
| 749 |
+
<div class="step-content">
|
| 750 |
+
<div class="step-title">Feature Engineering intensif</div>
|
| 751 |
+
<div class="step-desc">
|
| 752 |
+
Créer des features composites (TotalSF, HouseAge),
|
| 753 |
+
regrouper les catégories rares, transformer les variables skewed.
|
| 754 |
+
</div>
|
| 755 |
+
</div>
|
| 756 |
+
</div>
|
| 757 |
+
<div class="step-item">
|
| 758 |
+
<div class="step-dot">3</div>
|
| 759 |
+
<div class="step-content">
|
| 760 |
+
<div class="step-title">Modélisation avancée</div>
|
| 761 |
+
<div class="step-desc">
|
| 762 |
+
XGBoost, LightGBM, Random Forest en stacking.
|
| 763 |
+
Optimisation des hyperparamètres avec Optuna.
|
| 764 |
+
</div>
|
| 765 |
+
<div class="expected-output">
|
| 766 |
+
<div class="expected-label">Résultats attendus</div>
|
| 767 |
+
<div class="expected-text">
|
| 768 |
+
XGBoost: RMSE = 0.12 (log scale)<br>
|
| 769 |
+
Feature importance: OverallQual > GrLivArea > GarageCars
|
| 770 |
+
</div>
|
| 771 |
+
</div>
|
| 772 |
+
</div>
|
| 773 |
+
</div>
|
| 774 |
+
</div>
|
| 775 |
+
</div>
|
| 776 |
+
</div>
|
| 777 |
+
|
| 778 |
+
<!-- TP 3: Iris -->
|
| 779 |
+
<div class="tp-card scroll-animate">
|
| 780 |
+
<div class="tp-header">
|
| 781 |
+
<div class="tp-badge iris">TP-3</div>
|
| 782 |
+
<div class="tp-header-content">
|
| 783 |
+
<h2 class="tp-title">Classification Iris — Introduction au ML</h2>
|
| 784 |
+
<div class="tp-meta">
|
| 785 |
+
<span class="badge badge-primary">⏱️ 20 min</span>
|
| 786 |
+
<span class="badge badge-secondary">Classification</span>
|
| 787 |
+
<span class="badge badge-success">Débutant</span>
|
| 788 |
+
<span class="badge badge-accent">Visualisation</span>
|
| 789 |
+
</div>
|
| 790 |
+
<p class="tp-description">
|
| 791 |
+
Le dataset classique pour la classification multi-classe.
|
| 792 |
+
Identifier l'espèce d'iris à partir des mesures des pétales et sépales.
|
| 793 |
+
</p>
|
| 794 |
+
</div>
|
| 795 |
+
<a href="https://colab.research.google.com/drive/1TqBXWkU3XbX7QzvVv9ZqZqZqZqZqZqZq" target="_blank" class="tp-colab-btn">
|
| 796 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
| 797 |
+
<path d="M16.9 4.8C14.4 2.4 10.7 1.7 7.5 3.1L10 5.6c1.8-.4 3.8 0 5.2 1.4 2.3 2.3 2.3 6 0 8.3-1.4 1.4-3.4 1.9-5.2 1.5L7.5 19.2c3.2 1.3 6.9.6 9.4-1.8 3.4-3.4 3.4-9.2 0-12.6zm-9.8.8L4.8 8c-.8 1.2-1.2 2.6-1.2 4s.4 2.8 1.2 4l2.3-2.3c-.4-.5-.7-1.1-.8-1.7H8V9.9H6.3c.1-.6.4-1.2.8-1.7z"/>
|
| 798 |
+
</svg>
|
| 799 |
+
Ouvrir dans Colab
|
| 800 |
+
</a>
|
| 801 |
+
</div>
|
| 802 |
+
|
| 803 |
+
<div class="tp-body">
|
| 804 |
+
<div class="dataset-info">
|
| 805 |
+
<div class="dataset-icon">🌸</div>
|
| 806 |
+
<div class="dataset-content">
|
| 807 |
+
<div class="dataset-name">Dataset : Iris Flower Classification</div>
|
| 808 |
+
<a href="https://www.kaggle.com/datasets/uciml/iris" target="_blank" class="dataset-link">
|
| 809 |
+
🔗 kaggle.com/datasets/uciml/iris
|
| 810 |
+
</a>
|
| 811 |
+
</div>
|
| 812 |
+
<div class="dataset-stats">
|
| 813 |
+
<div class="dataset-stat">
|
| 814 |
+
<div class="dataset-stat-value">150</div>
|
| 815 |
+
<div class="dataset-stat-label">Lignes</div>
|
| 816 |
+
</div>
|
| 817 |
+
<div class="dataset-stat">
|
| 818 |
+
<div class="dataset-stat-value">5</div>
|
| 819 |
+
<div class="dataset-stat-label">Colonnes</div>
|
| 820 |
+
</div>
|
| 821 |
+
</div>
|
| 822 |
+
</div>
|
| 823 |
+
|
| 824 |
+
<div class="tp-goals">
|
| 825 |
+
<div class="tp-goal-box">
|
| 826 |
+
<div class="tp-goal-label">🎯 Objectif</div>
|
| 827 |
+
<p class="tp-goal-text">
|
| 828 |
+
Classifier les iris en 3 espèces (Setosa, Versicolor, Virginica)
|
| 829 |
+
à partir de 4 features numériques.
|
| 830 |
+
</p>
|
| 831 |
+
</div>
|
| 832 |
+
<div class="tp-goal-box">
|
| 833 |
+
<div class="tp-goal-label">✅ Résultat attendu</div>
|
| 834 |
+
<p class="tp-goal-text">
|
| 835 |
+
Accuracy de <strong>95%+</strong>. Visualisation des frontières de décision.
|
| 836 |
+
</p>
|
| 837 |
+
</div>
|
| 838 |
+
</div>
|
| 839 |
+
|
| 840 |
+
<h3 class="concepts-title">🧠 Concepts utilisés</h3>
|
| 841 |
+
<div class="concepts-grid">
|
| 842 |
+
<div class="concept-item">
|
| 843 |
+
<div class="concept-name">KNN</div>
|
| 844 |
+
<div class="concept-desc">K-Nearest Neighbors</div>
|
| 845 |
+
</div>
|
| 846 |
+
<div class="concept-item">
|
| 847 |
+
<div class="concept-name">SVM</div>
|
| 848 |
+
<div class="concept-desc">Support Vector Machine</div>
|
| 849 |
+
</div>
|
| 850 |
+
<div class="concept-item">
|
| 851 |
+
<div class="concept-name">Decision Boundary</div>
|
| 852 |
+
<div class="concept-desc">Visualisation</div>
|
| 853 |
+
</div>
|
| 854 |
+
<div class="concept-item">
|
| 855 |
+
<div class="concept-name">PCA</div>
|
| 856 |
+
<div class="concept-desc">Réduction de dimension</div>
|
| 857 |
+
</div>
|
| 858 |
+
<div class="concept-item">
|
| 859 |
+
<div class="concept-name">Pairplot</div>
|
| 860 |
+
<div class="concept-desc">Visualisation multi-variables</div>
|
| 861 |
+
</div>
|
| 862 |
+
<div class="concept-item">
|
| 863 |
+
<div class="concept-name">Confusion Matrix</div>
|
| 864 |
+
<div class="concept-desc">Évaluation détaillée</div>
|
| 865 |
+
</div>
|
| 866 |
+
</div>
|
| 867 |
+
|
| 868 |
+
<h3 class="steps-title">📋 Étapes du TP</h3>
|
| 869 |
+
<div class="steps-list">
|
| 870 |
+
<div class="step-item">
|
| 871 |
+
<div class="step-dot">1</div>
|
| 872 |
+
<div class="step-content">
|
| 873 |
+
<div class="step-title">Visualisation exploratoire</div>
|
| 874 |
+
<div class="step-desc">
|
| 875 |
+
Pairplot pour voir les relations entre features,
|
| 876 |
+
boxplots par espèce pour identifier les patterns.
|
| 877 |
+
</div>
|
| 878 |
+
</div>
|
| 879 |
+
</div>
|
| 880 |
+
<div class="step-item">
|
| 881 |
+
<div class="step-dot">2</div>
|
| 882 |
+
<div class="step-content">
|
| 883 |
+
<div class="step-title">Comparaison des algorithmes</div>
|
| 884 |
+
<div class="step-desc">
|
| 885 |
+
KNN, SVM, Decision Tree, Random Forest.
|
| 886 |
+
Comparer accuracy et temps d'entraînement.
|
| 887 |
+
</div>
|
| 888 |
+
</div>
|
| 889 |
+
</div>
|
| 890 |
+
<div class="step-item">
|
| 891 |
+
<div class="step-dot">3</div>
|
| 892 |
+
<div class="step-content">
|
| 893 |
+
<div class="step-title">Visualisation des frontières</div>
|
| 894 |
+
<div class="step-desc">
|
| 895 |
+
Tracer les frontières de décision en 2D après PCA.
|
| 896 |
+
Comprendre comment chaque algorithme sépare les classes.
|
| 897 |
+
</div>
|
| 898 |
+
<div class="expected-output">
|
| 899 |
+
<div class="expected-label">Résultats attendus</div>
|
| 900 |
+
<div class="expected-text">
|
| 901 |
+
SVM: 98% accuracy<br>
|
| 902 |
+
Setosa parfaitement séparable, Virginica/Versicolor plus proches
|
| 903 |
+
</div>
|
| 904 |
+
</div>
|
| 905 |
+
</div>
|
| 906 |
+
</div>
|
| 907 |
+
</div>
|
| 908 |
+
</div>
|
| 909 |
+
</div>
|
| 910 |
+
|
| 911 |
+
<!-- TP 4: Energy Consumption -->
|
| 912 |
+
<div class="tp-card scroll-animate">
|
| 913 |
+
<div class="tp-header">
|
| 914 |
+
<div class="tp-badge energy">TP-4</div>
|
| 915 |
+
<div class="tp-header-content">
|
| 916 |
+
<h2 class="tp-title">Consommation Énergétique — Séries Temporelles</h2>
|
| 917 |
+
<div class="tp-meta">
|
| 918 |
+
<span class="badge badge-primary">⏱️ 40 min</span>
|
| 919 |
+
<span class="badge badge-secondary">Time Series</span>
|
| 920 |
+
<span class="badge badge-success">LSTM</span>
|
| 921 |
+
<span class="badge badge-accent">TensorFlow</span>
|
| 922 |
+
</div>
|
| 923 |
+
<p class="tp-description">
|
| 924 |
+
Prédire la consommation électrique d'un bâtiment à partir de données
|
| 925 |
+
temporelles. Introduction aux LSTM et aux prédictions séquentielles.
|
| 926 |
+
</p>
|
| 927 |
+
</div>
|
| 928 |
+
<a href="https://colab.research.google.com/drive/1TqBXWkU3XbX7QzvVv9ZqZqZqZqZqZqZq" target="_blank" class="tp-colab-btn">
|
| 929 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
| 930 |
+
<path d="M16.9 4.8C14.4 2.4 10.7 1.7 7.5 3.1L10 5.6c1.8-.4 3.8 0 5.2 1.4 2.3 2.3 2.3 6 0 8.3-1.4 1.4-3.4 1.9-5.2 1.5L7.5 19.2c3.2 1.3 6.9.6 9.4-1.8 3.4-3.4 3.4-9.2 0-12.6zm-9.8.8L4.8 8c-.8 1.2-1.2 2.6-1.2 4s.4 2.8 1.2 4l2.3-2.3c-.4-.5-.7-1.1-.8-1.7H8V9.9H6.3c.1-.6.4-1.2.8-1.7z"/>
|
| 931 |
+
</svg>
|
| 932 |
+
Ouvrir dans Colab
|
| 933 |
+
</a>
|
| 934 |
+
</div>
|
| 935 |
+
|
| 936 |
+
<div class="tp-body">
|
| 937 |
+
<div class="dataset-info">
|
| 938 |
+
<div class="dataset-icon">⚡</div>
|
| 939 |
+
<div class="dataset-content">
|
| 940 |
+
<div class="dataset-name">Dataset : ASHRAE - Great Energy Predictor III</div>
|
| 941 |
+
<a href="https://www.kaggle.com/c/ashrae-energy-prediction" target="_blank" class="dataset-link">
|
| 942 |
+
🔗 kaggle.com/c/ashrae-energy-prediction
|
| 943 |
+
</a>
|
| 944 |
+
</div>
|
| 945 |
+
<div class="dataset-stats">
|
| 946 |
+
<div class="dataset-stat">
|
| 947 |
+
<div class="dataset-stat-value">20M+</div>
|
| 948 |
+
<div class="dataset-stat-label">Lignes</div>
|
| 949 |
+
</div>
|
| 950 |
+
<div class="dataset-stat">
|
| 951 |
+
<div class="dataset-stat-value">1449</div>
|
| 952 |
+
<div class="dataset-stat-label">Bâtiments</div>
|
| 953 |
+
</div>
|
| 954 |
+
</div>
|
| 955 |
+
</div>
|
| 956 |
+
|
| 957 |
+
<div class="tp-goals">
|
| 958 |
+
<div class="tp-goal-box">
|
| 959 |
+
<div class="tp-goal-label">🎯 Objectif</div>
|
| 960 |
+
<p class="tp-goal-text">
|
| 961 |
+
Prédire la consommation énergétique horaire de bâtiments
|
| 962 |
+
à partir de données météo et historiques.
|
| 963 |
+
</p>
|
| 964 |
+
</div>
|
| 965 |
+
<div class="tp-goal-box">
|
| 966 |
+
<div class="tp-goal-label">✅ Résultat attendu</div>
|
| 967 |
+
<p class="tp-goal-text">
|
| 968 |
+
RMSE <strong>< 100</strong> sur la consommation normalisée.
|
| 969 |
+
Capture des patterns journaliers et saisonniers.
|
| 970 |
+
</p>
|
| 971 |
+
</div>
|
| 972 |
+
</div>
|
| 973 |
+
|
| 974 |
+
<h3 class="concepts-title">🧠 Concepts utilisés</h3>
|
| 975 |
+
<div class="concepts-grid">
|
| 976 |
+
<div class="concept-item">
|
| 977 |
+
<div class="concept-name">Time Series</div>
|
| 978 |
+
<div class="concept-desc">Traitement séquentiel</div>
|
| 979 |
+
</div>
|
| 980 |
+
<div class="concept-item">
|
| 981 |
+
<div class="concept-name">LSTM</div>
|
| 982 |
+
<div class="concept-desc">Réseaux récurrents</div>
|
| 983 |
+
</div>
|
| 984 |
+
<div class="concept-item">
|
| 985 |
+
<div class="concept-name">Seasonality</div>
|
| 986 |
+
<div class="concept-desc">Patterns saisonniers</div>
|
| 987 |
+
</div>
|
| 988 |
+
<div class="concept-item">
|
| 989 |
+
<div class="concept-name">Windowing</div>
|
| 990 |
+
<div class="concept-desc">Fenêtres glissantes</div>
|
| 991 |
+
</div>
|
| 992 |
+
<div class="concept-item">
|
| 993 |
+
<div class="concept-name">Early Stopping</div>
|
| 994 |
+
<div class="concept-desc">Arrêt automatique</div>
|
| 995 |
+
</div>
|
| 996 |
+
<div class="concept-item">
|
| 997 |
+
<div class="concept-name">TensorBoard</div>
|
| 998 |
+
<div class="concept-desc">Visualisation training</div>
|
| 999 |
+
</div>
|
| 1000 |
+
</div>
|
| 1001 |
+
|
| 1002 |
+
<h3 class="steps-title">📋 Étapes du TP</h3>
|
| 1003 |
+
<div class="steps-list">
|
| 1004 |
+
<div class="step-item">
|
| 1005 |
+
<div class="step-dot">1</div>
|
| 1006 |
+
<div class="step-content">
|
| 1007 |
+
<div class="step-title">Analyse temporelle</div>
|
| 1008 |
+
<div class="step-desc">
|
| 1009 |
+
Visualiser les patterns horaires, journaliers, hebdomadaires.
|
| 1010 |
+
Identifier la saisonnalité et les tendances.
|
| 1011 |
+
</div>
|
| 1012 |
+
</div>
|
| 1013 |
+
</div>
|
| 1014 |
+
<div class="step-item">
|
| 1015 |
+
<div class="step-dot">2</div>
|
| 1016 |
+
<div class="step-content">
|
| 1017 |
+
<div class="step-title">Feature Engineering temporel</div>
|
| 1018 |
+
<div class="step-desc">
|
| 1019 |
+
Créer des features temporelles (hour, day_of_week, month),
|
| 1020 |
+
lags (valeurs précédentes), rolling statistics.
|
| 1021 |
+
</div>
|
| 1022 |
+
</div>
|
| 1023 |
+
</div>
|
| 1024 |
+
<div class="step-item">
|
| 1025 |
+
<div class="step-dot">3</div>
|
| 1026 |
+
<div class="step-content">
|
| 1027 |
+
<div class="step-title">Modélisation LSTM</div>
|
| 1028 |
+
<div class="step-desc">
|
| 1029 |
+
Construire un modèle LSTM avec Keras.
|
| 1030 |
+
Entraînement avec early stopping et learning rate scheduling.
|
| 1031 |
+
</div>
|
| 1032 |
+
<div class="expected-output">
|
| 1033 |
+
<div class="expected-label">Résultats attendus</div>
|
| 1034 |
+
<div class="expected-text">
|
| 1035 |
+
LSTM: RMSE = 85 sur test set<br>
|
| 1036 |
+
Capture des pics de consommation matin/soir
|
| 1037 |
+
</div>
|
| 1038 |
+
</div>
|
| 1039 |
+
</div>
|
| 1040 |
+
</div>
|
| 1041 |
+
</div>
|
| 1042 |
+
</div>
|
| 1043 |
+
</div>
|
| 1044 |
+
|
| 1045 |
+
<!-- TP 5: MNIST -->
|
| 1046 |
+
<div class="tp-card scroll-animate">
|
| 1047 |
+
<div class="tp-header">
|
| 1048 |
+
<div class="tp-badge mnist">TP-5</div>
|
| 1049 |
+
<div class="tp-header-content">
|
| 1050 |
+
<h2 class="tp-title">Reconnaissance de Chiffres — Deep Learning</h2>
|
| 1051 |
+
<div class="tp-meta">
|
| 1052 |
+
<span class="badge badge-primary">⏱️ 35 min</span>
|
| 1053 |
+
<span class="badge badge-secondary">CNN</span>
|
| 1054 |
+
<span class="badge badge-success">Computer Vision</span>
|
| 1055 |
+
<span class="badge badge-accent">Keras</span>
|
| 1056 |
+
</div>
|
| 1057 |
+
<p class="tp-description">
|
| 1058 |
+
Classification d'images de chiffres manuscrits (0-9) avec des réseaux de neurones convolutifs (CNN).
|
| 1059 |
+
Introduction au Computer Vision.
|
| 1060 |
+
</p>
|
| 1061 |
+
</div>
|
| 1062 |
+
<a href="https://colab.research.google.com/drive/1TqBXWkU3XbX7QzvVv9ZqZqZqZqZqZqZq" target="_blank" class="tp-colab-btn">
|
| 1063 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
| 1064 |
+
<path d="M16.9 4.8C14.4 2.4 10.7 1.7 7.5 3.1L10 5.6c1.8-.4 3.8 0 5.2 1.4 2.3 2.3 2.3 6 0 8.3-1.4 1.4-3.4 1.9-5.2 1.5L7.5 19.2c3.2 1.3 6.9.6 9.4-1.8 3.4-3.4 3.4-9.2 0-12.6zm-9.8.8L4.8 8c-.8 1.2-1.2 2.6-1.2 4s.4 2.8 1.2 4l2.3-2.3c-.4-.5-.7-1.1-.8-1.7H8V9.9H6.3c.1-.6.4-1.2.8-1.7z"/>
|
| 1065 |
+
</svg>
|
| 1066 |
+
Ouvrir dans Colab
|
| 1067 |
+
</a>
|
| 1068 |
+
</div>
|
| 1069 |
+
|
| 1070 |
+
<div class="tp-body">
|
| 1071 |
+
<div class="dataset-info">
|
| 1072 |
+
<div class="dataset-icon">🔢</div>
|
| 1073 |
+
<div class="dataset-content">
|
| 1074 |
+
<div class="dataset-name">Dataset : MNIST Handwritten Digits</div>
|
| 1075 |
+
<a href="https://www.kaggle.com/datasets/hojjatk/mnist-dataset" target="_blank" class="dataset-link">
|
| 1076 |
+
🔗 kaggle.com/datasets/hojjatk/mnist-dataset
|
| 1077 |
+
</a>
|
| 1078 |
+
</div>
|
| 1079 |
+
<div class="dataset-stats">
|
| 1080 |
+
<div class="dataset-stat">
|
| 1081 |
+
<div class="dataset-stat-value">70K</div>
|
| 1082 |
+
<div class="dataset-stat-label">Images</div>
|
| 1083 |
+
</div>
|
| 1084 |
+
<div class="dataset-stat">
|
| 1085 |
+
<div class="dataset-stat-value">28×28</div>
|
| 1086 |
+
<div class="dataset-stat-label">Pixels</div>
|
| 1087 |
+
</div>
|
| 1088 |
+
</div>
|
| 1089 |
+
</div>
|
| 1090 |
+
|
| 1091 |
+
<div class="tp-goals">
|
| 1092 |
+
<div class="tp-goal-box">
|
| 1093 |
+
<div class="tp-goal-label">🎯 Objectif</div>
|
| 1094 |
+
<p class="tp-goal-text">
|
| 1095 |
+
Classifier les images de chiffres manuscrits (0-9)
|
| 1096 |
+
avec un CNN et atteindre >99% d'accuracy.
|
| 1097 |
+
</p>
|
| 1098 |
+
</div>
|
| 1099 |
+
<div class="tp-goal-box">
|
| 1100 |
+
<div class="tp-goal-label">✅ Résultat attendu</div>
|
| 1101 |
+
<p class="tp-goal-text">
|
| 1102 |
+
Accuracy de <strong>99%+</strong> sur le test set.
|
| 1103 |
+
Visualisation des filtres appris par le CNN.
|
| 1104 |
+
</p>
|
| 1105 |
+
</div>
|
| 1106 |
+
</div>
|
| 1107 |
+
|
| 1108 |
+
<h3 class="concepts-title">🧠 Concepts utilisés</h3>
|
| 1109 |
+
<div class="concepts-grid">
|
| 1110 |
+
<div class="concept-item">
|
| 1111 |
+
<div class="concept-name">CNN</div>
|
| 1112 |
+
<div class="concept-desc">Convolutional Neural Network</div>
|
| 1113 |
+
</div>
|
| 1114 |
+
<div class="concept-item">
|
| 1115 |
+
<div class="concept-name">Conv2D</div>
|
| 1116 |
+
<div class="concept-desc">Couches de convolution</div>
|
| 1117 |
+
</div>
|
| 1118 |
+
<div class="concept-item">
|
| 1119 |
+
<div class="concept-name">MaxPooling</div>
|
| 1120 |
+
<div class="concept-desc">Réduction spatiale</div>
|
| 1121 |
+
</div>
|
| 1122 |
+
<div class="concept-item">
|
| 1123 |
+
<div class="concept-name">Dropout</div>
|
| 1124 |
+
<div class="concept-desc">Régularisation</div>
|
| 1125 |
+
</div>
|
| 1126 |
+
<div class="concept-item">
|
| 1127 |
+
<div class="concept-name">BatchNorm</div>
|
| 1128 |
+
<div class="concept-desc">Normalisation</div>
|
| 1129 |
+
</div>
|
| 1130 |
+
<div class="concept-item">
|
| 1131 |
+
<div class="concept-name">Data Augmentation</div>
|
| 1132 |
+
<div class="concept-desc">Augmentation données</div>
|
| 1133 |
+
</div>
|
| 1134 |
+
</div>
|
| 1135 |
+
|
| 1136 |
+
<h3 class="steps-title">📋 Étapes du TP</h3>
|
| 1137 |
+
<div class="steps-list">
|
| 1138 |
+
<div class="step-item">
|
| 1139 |
+
<div class="step-dot">1</div>
|
| 1140 |
+
<div class="step-content">
|
| 1141 |
+
<div class="step-title">Exploration des images</div>
|
| 1142 |
+
<div class="step-desc">
|
| 1143 |
+
Visualiser des exemples de chaque chiffre,
|
| 1144 |
+
analyser la distribution des classes.
|
| 1145 |
+
</div>
|
| 1146 |
+
</div>
|
| 1147 |
+
</div>
|
| 1148 |
+
<div class="step-item">
|
| 1149 |
+
<div class="step-dot">2</div>
|
| 1150 |
+
<div class="step-content">
|
| 1151 |
+
<div class="step-title">Construction du CNN</div>
|
| 1152 |
+
<div class="step-desc">
|
| 1153 |
+
Architecture: Conv2D → MaxPool → Conv2D → MaxPool →
|
| 1154 |
+
Flatten → Dense → Dropout → Output (10 classes).
|
| 1155 |
+
</div>
|
| 1156 |
+
</div>
|
| 1157 |
+
</div>
|
| 1158 |
+
<div class="step-item">
|
| 1159 |
+
<div class="step-dot">3</div>
|
| 1160 |
+
<div class="step-content">
|
| 1161 |
+
<div class="step-title">Entraînement et évaluation</div>
|
| 1162 |
+
<div class="step-desc">
|
| 1163 |
+
Entraînement avec data augmentation,
|
| 1164 |
+
visualisation des prédictions erronées.
|
| 1165 |
+
</div>
|
| 1166 |
+
<div class="expected-output">
|
| 1167 |
+
<div class="expected-label">Résultats attendus</div>
|
| 1168 |
+
<div class="expected-text">
|
| 1169 |
+
CNN: 99.2% accuracy<br>
|
| 1170 |
+
Erreurs principalement sur 4/9 et 3/8 similaires
|
| 1171 |
+
</div>
|
| 1172 |
+
</div>
|
| 1173 |
+
</div>
|
| 1174 |
+
</div>
|
| 1175 |
+
</div>
|
| 1176 |
+
</div>
|
| 1177 |
+
</div>
|
| 1178 |
+
|
| 1179 |
+
<!-- TP 6: Sentiment Analysis -->
|
| 1180 |
+
<div class="tp-card scroll-animate">
|
| 1181 |
+
<div class="tp-header">
|
| 1182 |
+
<div class="tp-badge sentiment">TP-6</div>
|
| 1183 |
+
<div class="tp-header-content">
|
| 1184 |
+
<h2 class="tp-title">Analyse de Sentiment — NLP</h2>
|
| 1185 |
+
<div class="tp-meta">
|
| 1186 |
+
<span class="badge badge-primary">⏱️ 40 min</span>
|
| 1187 |
+
<span class="badge badge-secondary">NLP</span>
|
| 1188 |
+
<span class="badge badge-success">Embeddings</span>
|
| 1189 |
+
<span class="badge badge-accent">Transformers</span>
|
| 1190 |
+
</div>
|
| 1191 |
+
<p class="tp-description">
|
| 1192 |
+
Classifier les avis IMDB comme positifs ou négatifs.
|
| 1193 |
+
Introduction au NLP et aux word embeddings avec les Transformers.
|
| 1194 |
+
</p>
|
| 1195 |
+
</div>
|
| 1196 |
+
<a href="https://colab.research.google.com/drive/1TqBXWkU3XbX7QzvVv9ZqZqZqZqZqZqZq" target="_blank" class="tp-colab-btn">
|
| 1197 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
| 1198 |
+
<path d="M16.9 4.8C14.4 2.4 10.7 1.7 7.5 3.1L10 5.6c1.8-.4 3.8 0 5.2 1.4 2.3 2.3 2.3 6 0 8.3-1.4 1.4-3.4 1.9-5.2 1.5L7.5 19.2c3.2 1.3 6.9.6 9.4-1.8 3.4-3.4 3.4-9.2 0-12.6zm-9.8.8L4.8 8c-.8 1.2-1.2 2.6-1.2 4s.4 2.8 1.2 4l2.3-2.3c-.4-.5-.7-1.1-.8-1.7H8V9.9H6.3c.1-.6.4-1.2.8-1.7z"/>
|
| 1199 |
+
</svg>
|
| 1200 |
+
Ouvrir dans Colab
|
| 1201 |
+
</a>
|
| 1202 |
+
</div>
|
| 1203 |
+
|
| 1204 |
+
<div class="tp-body">
|
| 1205 |
+
<div class="dataset-info">
|
| 1206 |
+
<div class="dataset-icon">🎬</div>
|
| 1207 |
+
<div class="dataset-content">
|
| 1208 |
+
<div class="dataset-name">Dataset : IMDB Movie Reviews</div>
|
| 1209 |
+
<a href="https://www.kaggle.com/datasets/lakshmi25npathi/imdb-dataset-of-50k-movie-reviews" target="_blank" class="dataset-link">
|
| 1210 |
+
🔗 kaggle.com/datasets/lakshmi25npathi/imdb-dataset
|
| 1211 |
+
</a>
|
| 1212 |
+
</div>
|
| 1213 |
+
<div class="dataset-stats">
|
| 1214 |
+
<div class="dataset-stat">
|
| 1215 |
+
<div class="dataset-stat-value">50K</div>
|
| 1216 |
+
<div class="dataset-stat-label">Avis</div>
|
| 1217 |
+
</div>
|
| 1218 |
+
<div class="dataset-stat">
|
| 1219 |
+
<div class="dataset-stat-value">2</div>
|
| 1220 |
+
<div class="dataset-stat-label">Classes</div>
|
| 1221 |
+
</div>
|
| 1222 |
+
</div>
|
| 1223 |
+
</div>
|
| 1224 |
+
|
| 1225 |
+
<div class="tp-goals">
|
| 1226 |
+
<div class="tp-goal-box">
|
| 1227 |
+
<div class="tp-goal-label">🎯 Objectif</div>
|
| 1228 |
+
<p class="tp-goal-text">
|
| 1229 |
+
Classifier les avis de films comme positifs ou négatifs
|
| 1230 |
+
en utilisant des embeddings et un LSTM ou BERT.
|
| 1231 |
+
</p>
|
| 1232 |
+
</div>
|
| 1233 |
+
<div class="tp-goal-box">
|
| 1234 |
+
<div class="tp-goal-label">✅ Résultat attendu</div>
|
| 1235 |
+
<p class="tp-goal-text">
|
| 1236 |
+
Accuracy de <strong>90%+</strong> avec LSTM,
|
| 1237 |
+
<strong>95%+</strong> avec BERT fine-tuning.
|
| 1238 |
+
</p>
|
| 1239 |
+
</div>
|
| 1240 |
+
</div>
|
| 1241 |
+
|
| 1242 |
+
<h3 class="concepts-title">🧠 Concepts utilisés</h3>
|
| 1243 |
+
<div class="concepts-grid">
|
| 1244 |
+
<div class="concept-item">
|
| 1245 |
+
<div class="concept-name">Tokenization</div>
|
| 1246 |
+
<div class="concept-desc">Découpage en tokens</div>
|
| 1247 |
+
</div>
|
| 1248 |
+
<div class="concept-item">
|
| 1249 |
+
<div class="concept-name">Word Embeddings</div>
|
| 1250 |
+
<div class="concept-desc">Word2Vec, GloVe</div>
|
| 1251 |
+
</div>
|
| 1252 |
+
<div class="concept-item">
|
| 1253 |
+
<div class="concept-name">LSTM pour NLP</div>
|
| 1254 |
+
<div class="concept-desc">Séquences de texte</div>
|
| 1255 |
+
</div>
|
| 1256 |
+
<div class="concept-item">
|
| 1257 |
+
<div class="concept-name">Attention</div>
|
| 1258 |
+
<div class="concept-desc">Mécanisme d'attention</div>
|
| 1259 |
+
</div>
|
| 1260 |
+
<div class="concept-item">
|
| 1261 |
+
<div class="concept-name">BERT</div>
|
| 1262 |
+
<div class="concept-desc">Transformers pré-entraînés</div>
|
| 1263 |
+
</div>
|
| 1264 |
+
<div class="concept-item">
|
| 1265 |
+
<div class="concept-name">Hugging Face</div>
|
| 1266 |
+
<div class="concept-desc">Bibliothèque transformers</div>
|
| 1267 |
+
</div>
|
| 1268 |
+
</div>
|
| 1269 |
+
|
| 1270 |
+
<h3 class="steps-title">📋 Étapes du TP</h3>
|
| 1271 |
+
<div class="steps-list">
|
| 1272 |
+
<div class="step-item">
|
| 1273 |
+
<div class="step-dot">1</div>
|
| 1274 |
+
<div class="step-content">
|
| 1275 |
+
<div class="step-title">Prétraitement du texte</div>
|
| 1276 |
+
<div class="step-desc">
|
| 1277 |
+
Nettoyage (HTML, ponctuation), tokenization,
|
| 1278 |
+
padding/truncation pour avoir des séquences de même longueur.
|
| 1279 |
+
</div>
|
| 1280 |
+
</div>
|
| 1281 |
+
</div>
|
| 1282 |
+
<div class="step-item">
|
| 1283 |
+
<div class="step-dot">2</div>
|
| 1284 |
+
<div class="step-content">
|
| 1285 |
+
<div class="step-title">Embeddings et LSTM</div>
|
| 1286 |
+
<div class="step-desc">
|
| 1287 |
+
Couche d'embedding apprenable + LSTM bidirectionnel
|
| 1288 |
+
+ couche dense de sortie.
|
| 1289 |
+
</div>
|
| 1290 |
+
</div>
|
| 1291 |
+
</div>
|
| 1292 |
+
<div class="step-item">
|
| 1293 |
+
<div class="step-dot">3</div>
|
| 1294 |
+
<div class="step-content">
|
| 1295 |
+
<div class="step-title">Fine-tuning BERT (bonus)</div>
|
| 1296 |
+
<div class="step-desc">
|
| 1297 |
+
Utiliser un modèle BERT pré-entraîné via Hugging Face,
|
| 1298 |
+
fine-tuner sur les avis IMDB.
|
| 1299 |
+
</div>
|
| 1300 |
+
<div class="expected-output">
|
| 1301 |
+
<div class="expected-label">Résultats attendus</div>
|
| 1302 |
+
<div class="expected-text">
|
| 1303 |
+
LSTM: 88% accuracy<br>
|
| 1304 |
+
BERT fine-tuned: 94% accuracy
|
| 1305 |
+
</div>
|
| 1306 |
+
</div>
|
| 1307 |
+
</div>
|
| 1308 |
+
</div>
|
| 1309 |
+
</div>
|
| 1310 |
+
</div>
|
| 1311 |
+
</div>
|
| 1312 |
+
|
| 1313 |
+
<!-- CTA -->
|
| 1314 |
+
<div class="tp-cta scroll-animate">
|
| 1315 |
+
<div class="tp-cta-icon" style="width: 60px; height: 60px; background: linear-gradient(135deg, var(--success), #059669); border-radius: var(--radius-lg); display: flex; align-items: center; justify-content: center; font-size: 1.5rem; font-weight: 700; color: white; margin: 0 auto var(--space-md);">OK</div>
|
| 1316 |
+
<h2 class="tp-cta-title">TPs termines ?</h2>
|
| 1317 |
+
<p class="tp-cta-text">
|
| 1318 |
+
Felicitations ! Vous avez maintenant une solide experience pratique
|
| 1319 |
+
en Machine Learning. Continuez avec le cours theorique ou posez vos questions.
|
| 1320 |
+
</p>
|
| 1321 |
+
<div class="cta-buttons" style="display: flex; gap: var(--space-md); justify-content: center; flex-wrap: wrap;">
|
| 1322 |
+
<a href="cours.html" class="btn btn-primary btn-lg">Retour aux cours</a>
|
| 1323 |
+
<a href="feedback.html" class="btn btn-outline btn-lg">Poser une question</a>
|
| 1324 |
+
</div>
|
| 1325 |
+
</div>
|
| 1326 |
+
|
| 1327 |
+
</div>
|
| 1328 |
+
|
| 1329 |
+
<!-- Author Footer -->
|
| 1330 |
+
<footer class="footer" style="background: var(--bg-secondary); border-top: 1px solid var(--border-color); padding: var(--space-xl); text-align: center;">
|
| 1331 |
+
<div style="display: flex; justify-content: center; gap: var(--space-xl); flex-wrap: wrap; margin-bottom: var(--space-md);">
|
| 1332 |
+
<a href="mailto:imadmaalouf02@gmail.com" style="display: flex; align-items: center; gap: var(--space-sm); color: var(--text-secondary); text-decoration: none; font-size: 0.9rem;">
|
| 1333 |
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>
|
| 1334 |
+
imadmaalouf02@gmail.com
|
| 1335 |
+
</a>
|
| 1336 |
+
<a href="https://github.com/imadmaalouf02" target="_blank" style="display: flex; align-items: center; gap: var(--space-sm); color: var(--text-secondary); text-decoration: none; font-size: 0.9rem;">
|
| 1337 |
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
| 1338 |
+
GitHub
|
| 1339 |
+
</a>
|
| 1340 |
+
<a href="https://huggingface.co/spaces/MAALOOUF/ML_Training" target="_blank" style="display: flex; align-items: center; gap: var(--space-sm); color: var(--text-secondary); text-decoration: none; font-size: 0.9rem;">
|
| 1341 |
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
|
| 1342 |
+
Hugging Face Space
|
| 1343 |
+
</a>
|
| 1344 |
+
</div>
|
| 1345 |
+
</footer>
|
| 1346 |
+
|
| 1347 |
+
<!-- Footer -->
|
| 1348 |
+
<footer class="footer">
|
| 1349 |
+
<p class="footer-text">
|
| 1350 |
+
ML Academy — Travaux Pratiques —
|
| 1351 |
+
<span class="footer-brand">GE-MCI 4A</span> — 2025/2026
|
| 1352 |
+
</p>
|
| 1353 |
+
<p class="footer-text" style="margin-top: var(--space-sm);">
|
| 1354 |
+
Datasets : Kaggle · Execution : Google Colab · Notebooks : Python
|
| 1355 |
+
</p>
|
| 1356 |
+
<p class="footer-text" style="margin-top: var(--space-sm); font-size: 0.75rem; color: var(--text-muted);">
|
| 1357 |
+
Formateur : Imad Maalouf
|
| 1358 |
+
</p>
|
| 1359 |
+
</footer>
|
| 1360 |
+
</div>
|
| 1361 |
+
|
| 1362 |
+
<!-- Scripts -->
|
| 1363 |
+
<script src="js/shared.js"></script>
|
| 1364 |
+
<script>
|
| 1365 |
+
// Scroll animations
|
| 1366 |
+
const observerOptions = {
|
| 1367 |
+
threshold: 0.1,
|
| 1368 |
+
rootMargin: '0px 0px -50px 0px'
|
| 1369 |
+
};
|
| 1370 |
+
|
| 1371 |
+
const observer = new IntersectionObserver((entries) => {
|
| 1372 |
+
entries.forEach(entry => {
|
| 1373 |
+
if (entry.isIntersecting) {
|
| 1374 |
+
entry.target.classList.add('visible');
|
| 1375 |
+
}
|
| 1376 |
+
});
|
| 1377 |
+
}, observerOptions);
|
| 1378 |
+
|
| 1379 |
+
document.querySelectorAll('.scroll-animate').forEach(el => {
|
| 1380 |
+
observer.observe(el);
|
| 1381 |
+
});
|
| 1382 |
+
|
| 1383 |
+
// Stagger animation for cards
|
| 1384 |
+
document.querySelectorAll('.tp-card').forEach((card, index) => {
|
| 1385 |
+
card.style.animationDelay = `${index * 0.15}s`;
|
| 1386 |
+
});
|
| 1387 |
+
</script>
|
| 1388 |
+
</body>
|
| 1389 |
+
</html>
|