| {% extends "layout.html" %}
|
|
|
| {% block content %}
|
| <script src="https://cdn.tailwindcss.com"></script>
|
| <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
|
| <script id="MathJax-script" async
|
| src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
|
|
| <link rel="stylesheet" href="{{ url_for('static', filename='output.css') }}">
|
| <script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.0/dist/chart.min.js"></script>
|
|
|
| <div class="max-w-3xl mx-auto mt-12 p-8 bg-gray-100 rounded-2xl shadow-xl border border-gray-300 relative overflow-hidden">
|
| <div class="absolute inset-0 bg-gradient-to-br from-gray-200 to-gray-300 opacity-60 rounded-2xl -z-10 animate-pulse-light"></div>
|
|
|
| <h1 class="text-4xl font-extrabold text-gray-900 mb-6 flex items-center">
|
| <span class="mr-3 text-purple-600">⛰️</span> Ridge Regression Predictions
|
| </h1>
|
|
|
| <p class="text-lg text-gray-800 mb-8 leading-relaxed">
|
| Explore the power of <strong>Ridge Regression (L2 Regularization)</strong> for robust predictions.
|
| This technique is excellent for handling multicollinearity and preventing overfitting by shrinking coefficients, while still retaining all features.
|
| </p>
|
|
|
| <div class="bg-gray-200 p-6 rounded-xl shadow-inner border border-gray-300 mt-8">
|
| <h2 class="text-2xl font-bold text-gray-900 mb-4">🎯 Input Features</h2>
|
| <form method="POST" class="space-y-5" id="predictionForm">
|
| {% for field in ['OverallQual', 'GrLivArea', 'GarageCars', 'TotalBsmtSF', 'YearBuilt'] %}
|
| <div class="relative group">
|
| <label for="{{ field }}" class="block text-md font-medium text-gray-800 mb-1">
|
| {{ field | replace('OverallQual', 'Overall Quality') | replace('GrLivArea', 'Above Ground Living Area (sq ft)') | replace('GarageCars', 'Size of Garage (cars)') | replace('TotalBsmtSF', 'Total Basement Area (sq ft)') | replace('YearBuilt', 'Year Built') }}:
|
| </label>
|
| <input type="number" step="any" id="{{ field }}" name="{{ field }}" required
|
| class="w-full border-gray-400 input-glow rounded-md shadow-sm focus:border-purple-500 focus:ring-purple-500 text-lg p-2.5 transition duration-200 ease-in-out hover:border-gray-500"
|
| placeholder="Enter value for {{ field | replace('OverallQual', 'Overall Quality') | replace('GrLivArea', 'sq ft') | replace('GarageCars', 'cars') | replace('TotalBsmtSF', 'sq ft') | replace('YearBuilt', 'year') }}">
|
| <span class="absolute inset-y-0 right-0 flex items-center pr-4 text-gray-500 text-sm pointer-events-none">
|
| {% if field == 'GrLivArea' or field == 'TotalBsmtSF' %} sq ft
|
| {% elif field == 'GarageCars' %} cars
|
| {% elif field == 'YearBuilt' %} year
|
| {% else %}
|
| <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path></svg>
|
| {% endif %}
|
| </span>
|
| </div>
|
| {% endfor %}
|
| <button type="submit" class="w-full bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 text-white font-bold py-3.5 px-4 rounded-lg shadow-lg transition duration-300 ease-in-out transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-opacity-75">
|
| <span class="mr-2">🔍</span> Predict with Ridge
|
| </button>
|
| <div id="loadingSpinner" class="hidden text-center mt-4 text-gray-600">
|
| <span class="loader border-purple-500 border-t-purple-500"></span> Processing...
|
| </div>
|
| </form>
|
| </div>
|
|
|
| {% if prediction %}
|
| <div class="mt-8 bg-gradient-to-r from-purple-400 to-indigo-500 text-white font-extrabold text-3xl p-6 rounded-xl shadow-2xl flex items-center justify-center animate-pulse-purple transform scale-105">
|
| <span class="mr-4 text-4xl">💰</span> Predicted Price: <span class="ml-3 text-shadow">${{ "%.2f" | format(prediction | float) }}</span>
|
| </div>
|
| {% elif error %}
|
| <div class="mt-8 bg-red-500 text-white font-semibold text-lg p-5 rounded-lg shadow-lg flex items-center justify-center animate-shake">
|
| <span class="mr-3">⚠️</span> Error: {{ error }} Please check your inputs.
|
| </div>
|
| {% endif %}
|
| </div>
|
|
|
| <div class="max-w-3xl mx-auto mt-12 p-8 bg-gray-100 rounded-2xl shadow-xl border border-gray-300">
|
| <h2 class="text-3xl font-extrabold text-gray-900 mb-6 flex items-center">
|
| <span class="mr-3 text-purple-600">📚</span> Deep Dive into Ridge Regression (L2 Regularization)
|
| </h2>
|
|
|
| <p class="text-gray-800 mb-4 leading-relaxed">
|
| <strong>Ridge Regression</strong> helps make our prediction models more stable and less prone to errors on new data. It does this by adding a special "penalty" to its calculations. This penalty is called <strong>L2 Regularization</strong>.
|
| </p>
|
|
|
| <div class="bg-gray-200 p-5 rounded-lg mb-6 border border-gray-300">
|
| <h3 class="text-xl font-semibold text-gray-900 mb-3">🎯 How Ridge Calculates (Objective Function):</h3>
|
| <p class="text-gray-800 text-lg mb-2">
|
| Ridge tries to find the best prediction rule by minimizing this formula:
|
| </p>
|
| <strong class="text-gray-900 text-xl bg-gray-300 px-4 py-3 rounded-md font-mono text-center mb-4 block">
|
| $$ J(\theta) = \frac{1}{2n} \sum_{i=1}^{n} \left(h_{\theta}(x^{(i)}) - y^{(i)}\right)^2 + \lambda \sum_{j=1}^{p} \theta_j^2 $$
|
| </strong>
|
| <ul class="list-disc list-inside text-gray-800 mt-4 pl-6 space-y-3">
|
| <li><strong>Prediction Error (First Part):</strong><br>
|
| <strong class="text-gray-900 text-xl bg-gray-300 px-4 py-3 rounded-md font-mono text-center mb-2 inline-block">
|
| $$ \frac{1}{2n} \sum_{i=1}^{n} \left(h_{\theta}(x^{(i)}) - y^{(i)}\right)^2 $$
|
| </strong>
|
| This is the standard part: How well did our model predict? We want our predictions ($h_{\theta}(x^{(i)})$) to be very close to the actual values ($y^{(i)}$).
|
| </li>
|
| <li><strong>Ridge's "Penalty" (Second Part):</strong><br>
|
| <strong class="text-gray-900 text-xl bg-gray-300 px-4 py-3 rounded-md font-mono text-center mb-2 inline-block">
|
| $$ \lambda \sum_{j=1}^{p} \theta_j^2 $$
|
| </strong>
|
| This is the L2 penalty. It adds a cost for making any feature's "importance" (called a coefficient, $\theta_j$) too big. If a coefficient is large, this term gets big, increasing the total cost. To keep the cost low, Ridge *forces* coefficients to be smaller.
|
| </li>
|
| </ul>
|
| <p class="text-gray-800 mt-4">
|
| The symbol $\lambda$ (lambda) is like a <strong>"Volume Knob"</strong> for this penalty.
|
| <br><strong>Big $\lambda$:</strong> Turn up the volume knob, so coefficients are shrunk *a lot*.
|
| <br><strong>Small $\lambda$:</strong> Turn down the volume knob, so coefficients are shrunk *less*.
|
| </p>
|
| </div>
|
|
|
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
|
| <div class="bg-gray-200 p-5 rounded-lg border border-gray-300">
|
| <h3 class="text-xl font-semibold text-gray-900 mb-3 flex items-center">
|
| <span class="mr-2 text-purple-600">✨</span> Why Ridge is Useful
|
| </h3>
|
| <ul class="list-disc list-inside text-gray-800 space-y-2">
|
| <li><strong>Prevents Over-Learning:</strong> Stops the model from memorizing the training data too much, so it performs better on new data.</li>
|
| <li><strong>Handles Similar Features:</strong> If you have features that tell a similar story (e.g., house size and number of rooms), Ridge manages them well without favoring one too much.</li>
|
| <li><strong>Keeps All Information:</strong> All features still contribute to the prediction, even if just a little bit.</li>
|
| </ul>
|
| </div>
|
| <div class="bg-gray-200 p-5 rounded-lg border border-gray-300">
|
| <h3 class="text-xl font-semibold text-gray-900 mb-3 flex items-center">
|
| <span class="mr-2 text-purple-600">🆚</span> Ridge vs. Lasso (The Main Difference)
|
| </h3>
|
| <ul class="list-disc list-inside text-gray-800 space-y-2">
|
| <li><strong>Ridge (L2):</strong> It *shrinks* the importance of features (their coefficients) towards zero. Think of it like a dimmer switch for a light: the light gets very dim, but it's never completely OFF.</li>
|
| <li><strong>Lasso (L1):</strong> It can *force* the importance of some features (their coefficients) to become *exactly zero*. This is like turning some lights completely OFF, effectively ignoring those features.</li>
|
| </ul>
|
| </div>
|
| </div>
|
|
|
|
|
| <div class="bg-purple-50 mt-12 p-8 rounded-2xl shadow-lg border border-purple-300">
|
| <h2 class="text-3xl font-extrabold text-purple-900 mb-6 flex items-center">
|
| <span class="mr-3 text-purple-600">🔄</span> How Ridge Treats Your Data
|
| </h2>
|
|
|
| <p class="text-purple-800 mb-6 leading-relaxed">
|
| Ridge uses <strong>L2 regularization</strong> to <u>shrink all feature weights</u>, but <strong>never drops any feature completely</strong>. This allows it to preserve all information while still controlling model complexity.
|
| </p>
|
|
|
| <div class="grid gap-8 md:grid-cols-5 items-center text-center text-purple-800 font-semibold text-sm">
|
|
|
| <div class="p-4 bg-purple-100 border rounded-lg shadow">
|
| <div class="text-4xl mb-2">📥</div>
|
| <div>Input Features</div>
|
| <div class="text-xs mt-1 text-purple-500">All provided</div>
|
| </div>
|
|
|
|
|
| <div class="text-2xl text-purple-400 hidden md:block">➡️</div>
|
|
|
|
|
| <div class="p-4 bg-purple-100 border rounded-lg shadow">
|
| <div class="text-4xl mb-2">⚙️</div>
|
| <div>Cost Function</div>
|
| <div class="text-xs mt-1 text-purple-500">MSE + λ × ∑θ²</div>
|
| </div>
|
|
|
|
|
| <div class="text-2xl text-purple-400 hidden md:block">➡️</div>
|
|
|
|
|
| <div class="p-4 bg-yellow-100 border rounded-lg shadow">
|
| <div class="text-4xl mb-2">📉</div>
|
| <div>Shrinks All Coeffs</div>
|
| <div class="text-xs mt-1 text-yellow-600">Closer to 0, but ≠ 0</div>
|
| </div>
|
|
|
|
|
| <div class="text-2xl text-purple-400 hidden md:block">➡️</div>
|
|
|
|
|
| <div class="p-4 bg-green-100 border rounded-lg shadow">
|
| <div class="text-4xl mb-2">🎯</div>
|
| <div>Prediction Uses All</div>
|
| <div class="text-xs mt-1 text-green-600">None are ignored</div>
|
| </div>
|
| </div>
|
|
|
| <p class="text-purple-800 mt-6 leading-relaxed text-sm">
|
| Unlike Lasso, <strong>Ridge Regression keeps all your features</strong>—just with smaller, regularized weights. It’s perfect when <u>all features have some predictive power</u>.
|
| </p>
|
| </div>
|
|
|
| </div>
|
| <p class="text-gray-800 mt-6 mb-6 leading-relaxed">
|
| Ridge is a great choice when you believe all your features are somewhat useful and you want to **control how much influence they have** without completely throwing any away.
|
| </p>
|
|
|
| <div class="bg-white mt-12 p-8 rounded-2xl shadow-xl border border-purple-200">
|
| <h2 class="text-3xl font-extrabold text-purple-900 mb-6 flex items-center">
|
| <span class="mr-3">🧠</span> Ridge Regression Made Easy (Story Style)
|
| </h2>
|
|
|
| <p class="text-purple-800 leading-relaxed text-lg mb-6">
|
| Imagine your house price is being predicted by a team of 5 friends (features):<br>
|
| <strong>Quality, Living Area, Garage, Basement, and Year Built.</strong>
|
| Each friend gives their opinion (a number), and we add them up to predict the price.
|
| </p>
|
|
|
| <div class="grid md:grid-cols-3 gap-6 text-center text-purple-800 text-base font-medium">
|
| <div class="bg-purple-50 p-4 rounded-lg border border-purple-200 shadow hover:shadow-lg transition">
|
| <div class="text-4xl mb-2">🔊</div>
|
| <p><strong>Without Ridge</strong><br>Some friends shout too loudly! Their numbers dominate and cause mistakes.</p>
|
| </div>
|
|
|
| <div class="text-4xl text-purple-400 hidden md:block animate-pulse">➡️</div>
|
|
|
| <div class="bg-purple-50 p-4 rounded-lg border border-purple-200 shadow hover:shadow-lg transition">
|
| <div class="text-4xl mb-2">🔇</div>
|
| <p><strong>With Ridge</strong><br>Everyone still speaks, but Ridge adds rules so no one can shout. Voices are balanced.</p>
|
| </div>
|
|
|
| <div class="text-4xl text-purple-400 hidden md:block animate-pulse">➡️</div>
|
|
|
| <div class="bg-green-50 p-4 rounded-lg border border-green-200 shadow hover:shadow-lg transition">
|
| <div class="text-4xl mb-2">📊</div>
|
| <p><strong>Result</strong><br>The prediction is more stable, fair, and doesn’t overreact to any one person.</p>
|
| </div>
|
| </div>
|
|
|
| <p class="mt-6 text-purple-700 leading-relaxed text-base">
|
| ✅ Ridge doesn’t remove anyone (like Lasso does).<br>
|
| ✅ It just turns down their microphone if they’re being too loud.<br>
|
| ✅ That’s how Ridge keeps all your data and prevents wild, unstable predictions.
|
| </p>
|
|
|
| <p class="mt-4 text-sm italic text-purple-500">
|
| (This is especially helpful when features are similar or slightly redundant.)
|
| </p>
|
| </div>
|
|
|
|
|
| <h3 class="text-2xl font-semibold text-gray-900 mt-8 mb-4 flex items-center">
|
| <span class="mr-2 text-purple-600">📊</span> Suggested Visualizations (to see it in action!):
|
| </h3>
|
| <p class="text-gray-800 mb-6">
|
| To really get a feel for how Ridge works, visual examples are best:
|
| </p>
|
| <ul class="list-disc list-inside text-gray-800 space-y-3 pl-4">
|
| <li><strong>Coefficient Shrinkage Graph:</strong> See a graph where all feature "voices" (coefficients) start big and then get smaller as you increase $\lambda$ (the "Volume Knob"). Notice they don't hit zero!</li>
|
| <li><strong>Prediction Quality Chart:</strong> Compare Ridge's predictions against actual values.</li>
|
| <li><strong>Model Stability Over Time:</strong> How the model's performance holds up on different sets of data.</li>
|
| </ul>
|
|
|
| <p class="text-gray-800 mt-4 italic">
|
| (These dynamic visualizations can be powered by Chart.js, D3.js, or by integrating server-side plots from libraries like Matplotlib/Seaborn in your Flask application.)
|
| </p>
|
| </div>
|
|
|
| <style>
|
|
|
| @keyframes fadeIn {
|
| from { opacity: 0; transform: translateY(10px); }
|
| to { opacity: 1; transform: translateY(0); }
|
| }
|
| .animate-fadeIn {
|
| animation: fadeIn 0.5s ease-out forwards;
|
| }
|
|
|
| @keyframes shake {
|
| 0%, 100% { transform: translateX(0); }
|
| 10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
|
| 20%, 40%, 60%, 80% { transform: translateX(5px); }
|
| }
|
| .animate-shake {
|
| animation: shake 0.5s ease-in-out;
|
| }
|
|
|
| .loader {
|
| border: 4px solid rgba(255, 255, 255, 0.3);
|
| border-radius: 50%;
|
| border-top: 4px solid #8B5CF6;
|
| width: 30px;
|
| height: 30px;
|
| animation: spin 1s linear infinite;
|
| display: inline-block;
|
| vertical-align: middle;
|
| margin-right: 8px;
|
| }
|
| @keyframes spin {
|
| 0% { transform: rotate(0deg); }
|
| 100% { transform: rotate(360deg); }
|
| }
|
|
|
|
|
| .input-glow:focus {
|
| box-shadow: 0 0 0 4px rgba(139, 92, 246, 0.4);
|
| }
|
|
|
|
|
| @keyframes pulse-light {
|
| 0% { opacity: 0.6; }
|
| 50% { opacity: 0.8; }
|
| 100% { opacity: 0.6; }
|
| }
|
| .animate-pulse-light {
|
| animation: pulse-light 4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
| }
|
|
|
|
|
| @keyframes pulse-purple {
|
| 0% { transform: scale(1.05); box-shadow: 0 25px 50px -12px rgba(139, 92, 246, 0.25); }
|
| 50% { transform: scale(1.06); box-shadow: 0 25px 50px -12px rgba(139, 92, 246, 0.5); }
|
| 100% { transform: scale(1.05); box-shadow: 0 25px 50px -12px rgba(139, 92, 246, 0.25); } } .animate-pulse-purple { animation: pulse-purple 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } .text-shadow { text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2); } @keyframes pulse-arrow { 0% { transform: translateX(0); opacity: 0.7; } 50% { transform: translateX(5px); opacity: 1; } 100% { transform: translateX(0); opacity: 0.7; } } .animate-pulse { animation: pulse-arrow 1.5s ease-in-out infinite; }
|
| {% endblock %} |