chatgpt is bit worse today. We dont know what it went through. We can only hope for the best.

This commit is contained in:
lda committed 2025-05-06 03:52:30 +07:00
1 parent f744957373
commit c70a62fd69
8 files changed
+641 -9

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
import matplotlib.pyplot as plt
import numpy as np
def plot_cost_function(costs, iterations):
"""Plot the cost function over iterations."""
plt.figure(figsize=(8, 6))
plt.plot(range(iterations), costs, label="Cost Function")
plt.xlabel("Iterations")
plt.ylabel("Cost")
plt.title("Cost Function over Iterations")
plt.legend()
plt.grid(True)
plt.show()
def plot_data_with_regression_line(X, y, theta):
"""Plot the data points and the regression line."""
plt.figure(figsize=(8, 6))
plt.scatter(X[:, 1], y, color="blue", label="Data Points")
regression_line = np.dot(X, theta)
plt.plot(X[:, 1], regression_line, color="red", label="Regression Line")
plt.xlabel("Feature")
plt.ylabel("Target")
plt.title("Data and Regression Line")
plt.legend()
plt.grid(True)
plt.show()
def plot_predictions_vs_actual(y_actual, y_predicted):
"""Plot predicted values against actual values."""
plt.figure(figsize=(8, 6))
plt.scatter(y_actual, y_predicted, color="green", label="Predictions vs Actual")
plt.plot(
[min(y_actual), max(y_actual)],
[min(y_actual), max(y_actual)],
color="red",
label="Ideal Fit",
)
plt.xlabel("Actual Values")
plt.ylabel("Predicted Values")
plt.title("Predictions vs Actual Values")
plt.legend()
plt.grid(True)
plt.show()
def plot_residuals(y_actual, y_predicted):
"""Plot residuals (errors) to evaluate model fit."""
residuals = y_actual - y_predicted
plt.figure(figsize=(8, 6))
plt.scatter(y_predicted, residuals, color="purple", label="Residuals")
plt.axhline(0, color="red", linestyle="--", label="Zero Error Line")
plt.xlabel("Predicted Values")
plt.ylabel("Residuals")
plt.title("Residual Plot")
plt.legend()
plt.grid(True)
plt.show()
def plot_cost_comparison(costs_dict, iterations):
"""Plot cost functions for multiple methods on the same graph."""
plt.figure(figsize=(8, 6))
for method, costs in costs_dict.items():
plt.plot(range(iterations), costs, label=f"{method} Cost")
plt.xlabel("Iterations")
plt.ylabel("Cost")
plt.title("Cost Function Comparison")
plt.legend()
plt.grid(True)
plt.show()
+36
View File
@@ -0,0 +1,36 @@
import pandas as pd
import numpy as np
def load_data(filename, verbose=False, drop_unnamed=True):
try:
# Load the dataset
df = pd.read_csv(
filename, dtype=np.float64
) # Force float64 for higher precision
if verbose:
print("Data loaded successfully.")
print("Data types:\n", df.dtypes)
# Drop unnamed/index columns if specified
if drop_unnamed:
df = df.loc[:, ~df.columns.str.contains("^Unnamed")]
if verbose:
print("Dropped unnamed columns.")
# Features (X) = all but last column, Target (y) = last column
X = df.iloc[:, :-1].values
y = df.iloc[:, -1].values
if verbose:
print("Shape of X:", X.shape)
print("Shape of y:", y.shape)
return X, y
except FileNotFoundError:
print(f"Error: File '{filename}' not found.")
raise
except Exception as e:
print(f"An error occurred: {e}")
raise
+125
View File
@@ -0,0 +1,125 @@
import numpy as np
# Hypothesis function
def hypothesis(X, theta):
"""
Compute the hypothesis (predictions) for the given input and parameters.
"""
result = np.dot(X, theta).reshape(-1, 1)
# print("Shape of X:", X.shape)
# print("Shape of theta:", theta.shape)
# print("Shape of hypothesis output:", result.shape)
return result
# Cost function (Mean Squared Error)
def compute_cost(X, y, theta):
"""
Compute the cost (Mean Squared Error) for the given input, target, and parameters.
"""
m = len(y)
predictions = hypothesis(X, theta)
errors = predictions - y
cost = (1 / (2 * m)) * np.sum(errors**2)
# # print(f"Max error: {np.max(errors):.4f}, Cost: {cost:.4f}") # Debugging
return cost
# Compute gradients
def compute_gradients(theta, X, y):
"""
Compute gradients for gradient descent.
Parameters:
theta (numpy.ndarray): Model parameters (n,).
X (numpy.ndarray): Feature matrix (m, n).
y (numpy.ndarray): Target values (m, 1).
Returns:
numpy.ndarray: Gradients (n,).
"""
# print("Shape of theta, X, y:", theta.shape, X.shape, y.shape)
m = len(y)
errors = hypothesis(X, theta) - y # Compute prediction errors
# print("Shape of errors:", errors.shape) # Debugging
gradients = (1 / m) * np.dot(X.T, errors) # Compute gradients
# print("Shape of gradients:", gradients.shape) # Debugging
return gradients.flatten()
# Gradient Descent function (Batch)
def gradient_descent(X, y, theta, learning_rate, iterations, return_cost: bool = False):
"""
Perform batch gradient descent to optimize theta.
"""
if return_cost:
costs = []
for _i in range(iterations):
# print("Shape of X:", X.shape) # Should be (200, 4)
# print("Shape of y:", y.shape) # Should be (200, 1)
# print("Shape of theta:", theta.shape) # Should be (4,)
gradients = compute_gradients(theta, X, y) # Compute gradients
# print(f"Iteration {i + 1}:")
# print(f" Shape of theta: {theta.shape}")
# print(f" Shape of gradients: {gradients.shape}")
theta -= learning_rate * gradients # Update theta
if return_cost:
cost = compute_cost(X, y, theta)
costs.append(cost) # Track cost
# print(f" Cost: {cost:.4f}")
return (theta, costs) if return_cost else theta
# Mini-batch Gradient Descent function
def mini_batch_gradient_descent(
X, y, theta, learning_rate, iterations, batch_size, return_cost: bool = False
):
"""
Perform mini-batch gradient descent to optimize theta.
"""
m = len(y)
if return_cost:
costs = []
for _i in range(iterations):
shuffle_indices = np.random.permutation(m)
X_shuffled = X[shuffle_indices]
y_shuffled = y[shuffle_indices]
for j in range(0, m, batch_size):
X_batch = X_shuffled[j : j + batch_size]
y_batch = y_shuffled[j : j + batch_size]
gradients = compute_gradients(theta, X_batch, y_batch) # Compute gradients
theta -= learning_rate * gradients # Update theta
if return_cost:
cost = compute_cost(X, y, theta)
costs.append(cost) # Track cost
# print(f"Iteration {i + 1}/{iterations}, Cost: {cost:.4f}") # Debugging
return (theta, costs) if return_cost else theta
# Stochastic Gradient Descent function
def stochastic_gradient_descent(
X, y, theta, learning_rate, iterations, return_cost: bool = False
):
"""
Perform stochastic gradient descent to optimize theta.
"""
m = len(y)
if return_cost:
costs = []
for _i in range(iterations):
for j in range(m):
X_sample = X[j : j + 1]
y_sample = y[j : j + 1]
gradients = compute_gradients(
theta, X_sample, y_sample
) # Compute gradients
theta -= learning_rate * gradients # Update theta
if return_cost:
cost = compute_cost(X, y, theta)
costs.append(cost) # Track cost
# print(f"Iteration {i + 1}/{iterations}, Cost: {cost:.4f}") # Debugging
return (theta, costs) if return_cost else theta
+299
View File
@@ -0,0 +1,299 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "ee8e9389",
"metadata": {},
"source": [
"# no way\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fa275d88",
"metadata": {},
"outputs": [],
"source": [
"import warnings\n",
"\n",
"warnings.filterwarnings(\"error\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0d63f004",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Data loaded successfully.\n",
"Data types:\n",
" Unnamed: 0 float64\n",
"TV float64\n",
"radio float64\n",
"newspaper float64\n",
"sales float64\n",
"dtype: object\n",
"Dropped unnamed columns.\n",
"Shape of X: (200, 3)\n",
"Shape of y: (200,)\n",
"Shape of y before reshaping: (200,)\n",
"Shape of y after reshaping: (200, 1)\n",
"Shape of X after adding bias term: (200, 4)\n"
]
}
],
"source": [
"# Load the data\n",
"import file_reader\n",
"\n",
"filename = \"Advertising.csv\"\n",
"X, y = file_reader.load_data(filename, verbose=True)\n",
"\n",
"# print(\"Shape of X:\", X.shape)\n",
"# print(\"Shape of y:\", y.shape)\n",
"\n",
"print(\"Shape of y before reshaping:\", y.shape)\n",
"y = y.reshape(-1, 1)\n",
"print(\"Shape of y after reshaping:\", y.shape)\n",
"# Add a bias term to X (for the intercept)\n",
"import numpy as np\n",
"\n",
"\n",
"import regulations\n",
"\n",
"X_scaled = regulations.standardize(X)\n",
"## Add bias term (column of 1s)\n",
"# X = np.hstack([np.ones((X_scaled.shape[0], 1)), X_scaled])\n",
"X = np.c_[np.ones(X_scaled.shape[0]), X_scaled]\n",
"\n",
"\n",
"print(\"Shape of X after adding bias term:\", X.shape)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "0fa06674",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Shape of theta: (4,)\n"
]
}
],
"source": [
"# Initialize parameters\n",
"theta = np.zeros(X.shape[1]) # Initialize theta with zeros\n",
"# Reshape theta to ensure proper alignment\n",
"# theta = theta.reshape(-1, 1)\n",
"print(\"Shape of theta:\", theta.shape)\n",
"\n",
"learning_rate = 0.001\n",
"iterations = 1000\n",
"batch_size = 32 # For mini-batch gradient descent"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "8d5bf6a6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Theta batch: [ 1.40204919e+01 3.91562216e+00 2.79885945e+00 -1.09326135e-02]\n",
"Theta (mini_batch): [ 1.40204919e+01 3.91562216e+00 2.79885945e+00 -1.09326135e-02]\n",
"Theta (stochastic): [ 1.40204919e+01 3.91562216e+00 2.79885945e+00 -1.09326135e-02]\n"
]
}
],
"source": [
"# Import gradient functions\n",
"import gradient\n",
"\n",
"# Run batch gradient descent and track costs\n",
"theta_batch, costs_batch = gradient.gradient_descent(\n",
" X, y, theta, learning_rate, iterations, return_cost=True\n",
")\n",
"\n",
"# Run mini-batch gradient descent and track costs\n",
"theta_mini_batch, costs_mini_batch = gradient.mini_batch_gradient_descent(\n",
" X, y, theta, learning_rate, iterations, batch_size, return_cost=True\n",
")\n",
"\n",
"# Run stochastic gradient descent and track costs\n",
"theta_stochastic, costs_stochastic = gradient.stochastic_gradient_descent(\n",
" X, y, theta, learning_rate, iterations, return_cost=True\n",
")\n",
"print(\"Theta batch:\", theta_batch)\n",
"print(\"Theta (mini_batch):\", theta_mini_batch)\n",
"print(\"Theta (stochastic):\", theta_stochastic)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "f9d6d9bf",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Theta (Normal Equation): [[14.0225 ]\n",
" [ 3.91925365]\n",
" [ 2.79206274]\n",
" [-0.02253861]]\n"
]
}
],
"source": [
"# Solve using the improved normal equation\n",
"import normal\n",
"\n",
"theta_normal = normal.normal_equation(X, y)\n",
"print(\"Theta (Normal Equation):\", theta_normal)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "5becf82a",
"metadata": {
"id": "7cf220ac",
"language": "python"
},
"outputs": [
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 800x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAq8AAAIhCAYAAABg21M1AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAYttJREFUeJzt3Xd4VGXe//HPmclk0hMgJCGQQOi9CeICCkhxAVHWtSuibrFgQV0L6iq4q6jPrg+ujdVV8NFF/a2FVddFogI2pDcBKUqHEGoKaZPM/fsjZCSkkMAkZyZ5v64rF8k9Z+Z8M99EP9zc5z6WMcYIAAAACAIOuwsAAAAAaorwCgAAgKBBeAUAAEDQILwCAAAgaBBeAQAAEDQIrwAAAAgahFcAAAAEDcIrAAAAggbhFQAAAEGD8Ao0AmvXrtUNN9ygtLQ0hYWFKSoqSn379tXTTz+tw4cP18k5n3jiCc2dO7fGx1uWVelHfHx8ndRXUxs2bNDUqVO1ffv2Co9df/31atOmTb3XFEyuv/56RUVFlRt78cUXNXv2bHsKqkEd27dvl2VZAVEjgIosbg8LNGyvvPKKbr31VnXq1Em33nqrunbtKo/Ho+XLl+uVV15Rr1699MEHH/j9vFFRUbr00ktrHAAsy9Kll16qe+65p9y4y+XSWWed5ff6aurdd9/VZZddpgULFmjo0KHlHvvxxx+VnZ2tPn362FNcELj++uv17rvvKjc31zfWvXt3xcfHa+HChfYVVk0dhYWFWrVqldq1a6fmzZvbUxyAKoXYXQCAurN48WLdcsstGjlypObOnSu32+17bOTIkbrnnns0b948GyssLzExUeecc47dZdRYu3bt7C4hIOTn5ys8PNzWGowxKigo8Esdbrc7qH4OgcaGZQNAA/bEE0/Isiy9/PLL5YJrmdDQUF100UW+r71er55++ml17txZbrdbCQkJuu6667R79+5yz1u1apUuvPBCJSQkyO12Kzk5WWPHjvUdZ1mWjh07ptdff933z/8nz1rWVlX/RD916lRZllVuzLIs3XbbbXrjjTfUpUsXRUREqFevXvr4448rPP+HH37QVVddpcTERLndbqWmpuq6665TYWGhZs+ercsuu0ySNGzYMN/3UjabXFlNBQUFmjJlitLS0hQaGqqWLVtq0qRJOnr0aLnj2rRpowsvvFDz5s1T3759FR4ers6dO+u1116r0ftx+PBh3XrrrWrZsqVCQ0PVtm1bPfTQQyosLPQd06dPH5177rkVnltSUqKWLVvqkksu8Y0VFRXpz3/+s6/3zZs31w033KADBw5UWvf777+vPn36KCwsTNOmTatRzWXPX79+vRYtWuR7P098D7Ozs/WHP/yh3Ps3efJkHTt2rNzrlPV45syZ6tKli9xut15//XVJ0rRp0zRgwAA1bdpUMTEx6tu3r1599VWd+A+N1dVR1bKBr7/+WsOHD1d0dLQiIiI0cOBA/ec//yl3zOzZs2VZlhYsWKBbbrlF8fHxatasmS655BLt3bu33LFffPGFhg4dqmbNmik8PFypqan69a9/rby8vBq/n0BjxMwr0ECVlJToiy++0FlnnaWUlJQaPeeWW27Ryy+/rNtuu00XXnihtm/frj/+8Y9auHChVq5cqfj4eB07dkwjR45UWlqaXnjhBSUmJiojI0MLFixQTk6OpNIZ3/PPP1/Dhg3TH//4R0lSTEzMKc9vjFFxcXG5MafTWSGc1sR//vMfLVu2TI899piioqL09NNP61e/+pU2bdqktm3bSpLWrFmjwYMHKz4+Xo899pg6dOigffv26cMPP1RRUZHGjh2rJ554Qg8++KBeeOEF9e3bV1LVM67GGI0fP16ff/65pkyZonPPPVdr167Vo48+qsWLF2vx4sXl/hKxZs0a3XPPPXrggQeUmJiof/zjH/rNb36j9u3b67zzzqvyeysoKNCwYcP0448/atq0aerZs6e++uorTZ8+XatXr/YFqhtuuEF33nmntmzZog4dOvieP3/+fO3du1c33HCDpNK/tFx88cX66quvdN9992ngwIHasWOHHn30UQ0dOlTLly8vN6O5cuVKbdy4UQ8//LDS0tIUGRlZ47588MEHuvTSSxUbG6sXX3xRknzvSV5enoYMGaLdu3frwQcfVM+ePbV+/Xo98sgjWrdunT777LNyPwtz587VV199pUceeURJSUlKSEiQVBo+b7rpJqWmpkqSvvvuO91+++3as2ePHnnkkVPWUZlFixZp5MiR6tmzp1599VW53W69+OKLGjdunN566y1dccUV5Y7/7W9/q7Fjx2rOnDnatWuX7r33Xl177bX64osvfDWOHTtW5557rl577TXFxcVpz549mjdvnoqKihQREVHj9xRodAyABikjI8NIMldeeWWNjt+4caORZG699dZy40uWLDGSzIMPPmiMMWb58uVGkpk7d261rxcZGWkmTpxY43olVfrxyiuvGGOMmThxomndunWF5z366KPm5P+USTKJiYkmOzvbN5aRkWEcDoeZPn26b+z88883cXFxJjMzs8q6/vWvfxlJZsGCBRUeO7mmefPmGUnm6aefLnfcO++8YySZl19+2TfWunVrExYWZnbs2OEby8/PN02bNjU33XRTlfUYY8zMmTONJPP//t//Kzf+1FNPGUlm/vz5xhhjDh48aEJDQ329K3P55ZebxMRE4/F4jDHGvPXWW0aSee+998odt2zZMiPJvPjii+XqdjqdZtOmTdXWWGbixIkmMjKy3Fi3bt3MkCFDKhw7ffp043A4zLJly8qNv/vuu0aS+eSTT3xjkkxsbKw5fPhwtecvKSkxHo/HPPbYY6ZZs2bG6/Weso5t27YZSWbWrFm+sXPOOcckJCSYnJwc31hxcbHp3r27adWqle91Z82aVenv0dNPP20kmX379pX7nlavXl1t/QAqYtkAAEnSggULJJX+U/iJzj77bHXp0kWff/65JKl9+/Zq0qSJ7r//fs2cOVMbNmzwWw2XX365li1bVu5j/Pjxp/Vaw4YNU3R0tO/rxMREJSQkaMeOHZJKZ/kWLVqkyy+/3G8X5ZTNqp38Hl522WWKjIz0vYdlevfu7ZsdlKSwsDB17NjRV2N154mMjNSll15abrzsvGXnadasmcaNG6fXX39dXq9XknTkyBH9+9//1nXXXaeQkNJ/fPv4448VFxencePGqbi42PfRu3dvJSUlVbigqWfPnurYseOp35Ba+vjjj9W9e3f17t27XB0XXHCBLMuqUMf555+vJk2aVHidL774QiNGjFBsbKycTqdcLpceeeQRHTp0SJmZmbWu69ixY1qyZIkuvfTScjsnOJ1OTZgwQbt379amTZvKPefE5ThS6Xsmydfb3r17KzQ0VL///e/1+uuv66effqp1XUBjRXgFGqj4+HhFRERo27ZtNTr+0KFDkqQWLVpUeCw5Odn3eGxsrBYtWqTevXvrwQcfVLdu3ZScnKxHH31UHo/njGpu3ry5+vXrV+7jdLfKatasWYUxt9ut/Px8SaUhrqSkRK1atTqjmk906NAhhYSEVAjDlmUpKSnJ9x7WtMbqzpOUlFRhOUVCQoJCQkLKnefGG2/Unj17lJ6eLkl66623VFhYWC5g79+/X0ePHlVoaKhcLle5j4yMDB08eLDceSr7GfGH/fv3a+3atRVqiI6OljGmRnUsXbpUo0aNklS608Y333yjZcuW6aGHHpKkU763lTly5IiMMVX+bkg6ZW/LliSUnb9du3b67LPPlJCQoEmTJqldu3Zq166dnn322VrXBzQ2rHkFGiin06nhw4frv//9r3bv3n3KkFb2P9t9+/ZVOHbv3r3lQmSPHj309ttvyxijtWvXavbs2XrssccUHh6uBx54wP/fjEpnJU+8GKnMyYGmppo2bSqn01nhYrQz0axZMxUXF+vAgQPlAqwxRhkZGerfv7/fzrNkyRIZY8oF2MzMTBUXF5fr1QUXXKDk5GTNmjVLF1xwgWbNmqUBAwaoa9euvmPKLiqqaueJE2ewJZ3WGuSaiI+PV3h4eJUXrZ38F5nK6nj77bflcrn08ccfKywszDdemz2HT9akSRM5HA7t27evwmNlF2Gdzl+yzj33XJ177rkqKSnR8uXL9dxzz2ny5MlKTEzUlVdeedr1Ag0dM69AAzZlyhQZY/S73/1ORUVFFR73eDz66KOPJJX+E6wkvfnmm+WOWbZsmTZu3Kjhw4dXeL5lWerVq5f+93//V3FxcVq5cqXvsZrMINZGmzZtlJmZqf379/vGioqK9Omnn57W64WHh2vIkCH617/+VW0APnnGrDpl79HJ7+F7772nY8eOVfoeno7hw4crNze3QiD7v//7v3J1SD//03bZxU3Lly/XjTfeWO55F154oQ4dOqSSkpIKM9/9+vVTp06d/FJ3map+Ni688EL9+OOPatasWaV11OSGEJZlKSQkRE6n0zeWn5+vN954o8Z1nCwyMlIDBgzQ+++/X+54r9erN998U61atTqjZRROp1MDBgzQCy+8IEnlfo8AVMTMK9CA/eIXv9BLL72kW2+9VWeddZZuueUWdevWTR6PR6tWrdLLL7+s7t27a9y4cerUqZN+//vf67nnnpPD4dDo0aN9uw2kpKTorrvuklS6LvHFF1/U+PHj1bZtWxlj9P777+vo0aMaOXKk79w9evTQwoUL9dFHH6lFixaKjo4+oxB0xRVX6JFHHtGVV16pe++9VwUFBfrb3/6mkpKS037NZ555RoMHD9aAAQP0wAMPqH379tq/f78+/PBD/f3vf1d0dLS6d+8uSXr55ZcVHR2tsLAwpaWlVfpP/iNHjtQFF1yg+++/X9nZ2Ro0aJBvt4E+ffpowoQJp13ria677jq98MILmjhxorZv364ePXro66+/1hNPPKExY8ZoxIgR5Y6/8cYb9dRTT+nqq69WeHh4hSvjr7zySv3zn//UmDFjdOedd+rss8+Line truncated
"text/plain": [
"<Figure size 800x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAtYAAAIhCAYAAABqh/1nAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAYR1JREFUeJzt3Xl8VNX9//H3ZE8gCXtCNEBYFMIiGARBWRQIAlqsIrg04loQFxZbZFOBFlB+llILSPWL4lKFKoLWL19KEKEoEdlFwA0jKCQgi0nYkknm/P6Ic2VIAiG5ZBju6/l45IG5c+aeM/MZ8J2Tc891GWOMAAAAAFRKkL8HAAAAAFwMCNYAAACADQjWAAAAgA0I1gAAAIANCNYAAACADQjWAAAAgA0I1gAAAIANCNYAAACADQjWAAAAgA0I1gD87vPPP9e9996rpKQkRUREqHr16rryyis1ffp0HT58+Lz0OXXqVC1ZsqTc7V0uV6lfderUOS/jK68dO3Zo4sSJ+v7770s8ds8996hRo0ZVPqZAcs8996h69eo+x+bMmaP58+f7Z0DlGMf3338vl8t1QYwRgC8XtzQH4E8vvfSShg0bpssvv1zDhg1TcnKy3G63NmzYoJdeeklXXHGFFi9ebHu/1atX14ABA8odTlwulwYMGKDHH3/c53hoaKhSUlJsH195vfPOO7rtttv00UcfqXv37j6P7dq1S7m5uWrXrp1/BhcA7rnnHr3zzjs6evSodaxVq1aqU6eOVq1a5b+BnWEc+fn52rx5s5o0aaK6dev6Z3AAShXi7wEAcK6MjAw99NBD6tWrl5YsWaLw8HDrsV69eunxxx/XsmXL/DhCX3Fxcbr66qv9PYxya9Kkib+HcEE4ceKEIiMj/ToGY4xOnjxpyzjCw8MD6nMIOAlLQQD4zdSpU+VyufTiiy/6hGqvsLAw/eY3v7G+93g8mj59upo3b67w8HDVq1dPd999t3788Uef523evFk33nij6tWrp/DwcCUkJKhfv35WO5fLpWPHjunVV1+1lnScPtt7rspadjFx4kS5XC6fYy6XS4888ohef/11tWjRQlFRUbriiiv0wQcflHj+l19+qTvuuENxcXEKDw9XgwYNdPfddys/P1/z58/XbbfdJkm67rrrrNfinYUvbUwnT57U2LFjlZSUpLCwMF1yySV6+OGH9fPPP/u0a9SokW688UYtW7ZMV155pSIjI9W8eXO9/PLL5Xo/Dh8+rGHDhumSSy5RWFiYGjdurPHjxys/P99q065dO3Xp0qXEc4uKinTJJZfolltusY4VFBToz3/+s1X7unXr6t5779VPP/1U6rjfffddtWvXThEREZo0aVK5xux9/vbt27V69Wrr/Tz1PczNzdUf/vAHn/dvxIgROnbsmM95vDWeO3euWrRoofDwcL366quSpEmTJqljx46qVauWYmJidOWVV2revHk69RfIZxpHWUtBPv74Y/Xo0UPR0dGKiopS586d9b//+78+bebPny+Xy6WPPvpIDz30kOrUqaPatWvrlltu0b59+3zarly5Ut27d1ft2rUVGRmpBg0a6NZbb9Xx48fL/X4CTsOMNQC/KCoq0sqVK5WSkqLExMRyPeehhx7Siy++qEceeUQ33nijvv/+ez355JNatWqVNm3apDp16ujYsWPq1auXkpKSNHv2bMXFxSk7O1sfffSR8vLyJBXPlF9//fW67rrr9OSTT0qSYmJiztq/MUaFhYU+x4KDg0sE5/L43//9X61fv16TJ09W9erVNX36dP32t7/VV199pcaNG0uStm7dqmuvvVZ16tTR5MmT1axZM2VlZen9999XQUGB+vXrp6lTp2rcuHGaPXu2rrzySkllz1QbY3TzzTfrww8/1NixY9WlSxd9/vnnevrpp5WRkaGMjAyfH3C2bt2qxx9/XGPGjFFcXJz+53/+R/fff7+aNm2qrl27lvnaTp48qeuuu067du3SpEmT1KZNG61Zs0bTpk3Tli1brLB37733avjw4frmm2/UrFkz6/nLly/Xvn37dO+990oq/oGqf//+WrNmjUaPHq3OnTtr9+7devrpp9W9e3dt2LDBZyZ406ZN2rlzpyZMmKCkpCRVq1at3HVZvHixBgwYoNjYWM2ZM0eSrPfk+PHj6tatm3788UeNGzdObdq00fbt2/XUU09p27ZtWrFihc9nYcmSJVqzZo2eeuopxcfHq169epKKg/GQIUPUoEEDSdKnn36qRx99VHv37tVTTz111nGUZvXq1erVq5fatGmjefPmKTw8XHPmzNFNN92kt956S4MGDfJp/8ADD6hfv35688039cMPP+iPf/yjfve732nlypXWGPv166cuXbro5ZdfVo0aNbR3714tW7ZMBQUFioqKKvd7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 truncated
"text/plain": [
"<Figure size 800x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAArcAAAIhCAYAAABUopIpAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAiwZJREFUeJzs3XdcleX/x/HX4bA3iIDIUsGtuM2tKW7LLLWs1IZZtszKMhvar7S0zG+ZmVZqw+xbaeXInZoj98yVCxeIAwXZ4/79QZ5vhAMVOBx4Px+P85Bzz88510HfXue6r9tkGIaBiIiIiEgpYGftAkRERERECovCrYiIiIiUGgq3IiIiIlJqKNyKiIiISKmhcCsiIiIipYbCrYiIiIiUGgq3IiIiIlJqKNyKiIiISKmhcCsiIiIipYbCrYjcsJ07d/LQQw9RqVIlnJ2dcXd3p0GDBowbN47z588XyTnHjBnDTz/9VODtTSbTFR9+fn5FUl9B7dmzh1GjRnH06NF86wYOHEh4eHix13RZYmIib7/9No0aNcLT0xMnJyfCw8N5+OGH2bp1q9XqKi4rV67EZDKxcuVKa5ciIrfApNvvisiNmDZtGkOGDKFatWoMGTKEmjVrkpmZyebNm5k2bRpRUVHMnTu30M/r7u7OPffcw4wZMwq0vclk4p577uH555/Ps9zBwYGGDRsWen0F9cMPP9C7d29+++032rZtm2fdoUOHSExMpH79+sVe16FDh+jYsSPx8fE8/vjjtG3bFnd3d44ePcp///tfFi5cyIULF/Dy8ir22opLYmIie/bsoWbNmnh6elq7HBG5SfbWLkBEbMf69et54okniI6O5qeffsLJycmyLjo6mueff55FixZZscK8AgICuO2226xdRoFVqVLFKufNzs7mrrvu4uzZs6xfv57atWtb1rVp04YBAwbw66+/4uDgYJX6ilpmZiYmkwlPT0+b+ryIyJVpWIKIFNiYMWMwmUxMnTo1T7C9zNHRkTvuuMPyPCcnh3HjxlG9enWcnJzw9/enf//+nDhxIs9+27Zto3v37vj7++Pk5ERQUBDdunWzbGcymUhOTmbmzJmW4QX/7vW8UVcbAjBq1ChMJlOeZSaTiaeeeoqvvvqKGjVq4OrqSlRUFPPnz8+3/759+7jvvvsICAjAycmJ0NBQ+vfvT3p6OjNmzKB3794AtGvXzvJaLvdGX6mmtLQ0RowYQaVKlXB0dKRixYo8+eSTXLhwIc924eHhdO/enUWLFtGgQQNcXFyoXr06X3zxxXXfi59++oldu3YxYsSIPMH2n7p06YKrq6vl+Zo1a2jfvj0eHh64urrSvHlzFixYkGefGTNmYDKZWLFiBYMGDaJcuXJ4enrSv39/kpOTiYuLo0+fPnh7e1OhQgVeeOEFMjMzLfsfPXoUk8nEuHHjePvttwkNDcXZ2ZlGjRqxfPnyPOc6ePAgDz30EJGRkbi6ulKxYkV69OjBrl278mx3eejBV199xfPPP0/FihVxcnLi4MGDVxyWcPjwYe69916CgoJwcnIiICCA9u3bs337dss2Bf2ct23bltq1a7Np0yZatWqFq6srlStX5p133iEnJ+e67SQiBaOeWxEpkOzsbFasWEHDhg0JCQkp0D5PPPEEU6dO5amnnqJ79+4cPXqU1157jZUrV7J161b8/PxITk4mOjqaSpUq8fHHHxMQEEBcXBy//fYbSUlJQG6P8e233067du147bXXAAr0tbFhGGRlZeVZZjab84XXgliwYAGbNm3izTffxN3dnXHjxnHXXXexf/9+KleuDMCOHTto2bIlfn5+vPnmm0RGRhIbG8svv/xCRkYG3bp1Y8yYMbzyyit8/PHHNGjQALh6j61hGPTs2ZPly5czYsQIWrVqxc6dO3njjTdYv34969evz/OfjB07dvD888/z8ssvExAQwGeffcYjjzxCREQErVu3vuprW7JkCQA9e/Ys0HuxatUqoqOjqVu3Lp9//jlOTk5MnjyZHj168O2339K3b9882z/66KP06tWL2bNns23bNl555RWysrLYv38/vXr14rHHHmPZsmW8++67BAUFMWzYsDz7T5o0ibCwMCZOnGgJkl26dGHVqlU0a9YMgFOnTlGuXDneeecdypcvz/nz55k5cyZNmzZl27ZtVKtWLc8xR4wYQbNmzZgyZQp2dnb4+/sTFxeX77V27dqV7Oxsxo0bR2hoKGfPnmXdunV5/nNRkM/5ZXFxcdx///08//zzvPHGG8ydO5cRI0YQFBRE//79C/T+i8h1GCIiBRAXF2cAxr333lug7ffu3WsAxpAhQ/Is37BhgwEYr7zyimEYhrF582YDMH766adrHs/Nzc0YMGBAgesFrviYNm2aYRiGMWDAACMsLCzffm+8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 truncated
"text/plain": [
"<Figure size 800x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 800x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAq8AAAIhCAYAAABg21M1AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAokNJREFUeJzs3Xd4FGXXx/HvJoQUSEBqgIReBEUQG51EioBiNCAlgDQFO0VEfRABX7ALxI5KUwFBCHYpAhEQVKqgILZQJdIJNWV33j/WjSm7yWyyIdnk93kurouZnZ25d4c8ntxz7nMshmEYiIiIiIh4AZ/CHoCIiIiIiFkKXkVERETEayh4FRERERGvoeBVRERERLyGglcRERER8RoKXkVERETEayh4FRERERGvoeBVRERERLyGglcRERER8RoKXkVKiLlz52KxWNL/lCpVirCwMIYMGcLhw4cvyxhq167N4MGD07fj4+OxWCzEx8e7dZ6NGzcyadIkTp8+ne21iIgIIiIi8jXO4mDMmDFYLBZuu+22PJ9j9+7dTJo0iX379nluYDnI+u8jq59++gmLxcITTzzh8pjff/8di8XCI488Yvq6kyZNwmKxuDNUESlECl5FSpg5c+awadMmVq1axb333svChQtp164d58+fv+xjadGiBZs2baJFixZuvW/jxo1MnjzZafD65ptv8uabb3pohN4pNTWVDz/8EIDly5fn+ZeT3bt3M3ny5MsWvOamWbNmXHfddbz//vtYrVanx8yZMweAYcOGXc6hichlpOBVpIS5+uqradmyJZGRkUycOJFx48aRkJDAJ5984vI9Fy5cKJCxhISE0LJlS0JCQjx2ziZNmtCkSROPnc8bffrppxw7doxbb70Vq9XKvHnzCntIHjNs2DCOHDnC119/ne01q9XK+++/z3XXXUezZs0KYXQicjkoeBUp4Vq2bAnA/v37ARg8eDBly5Zl165ddOnSheDgYDp27AhASkoKU6ZM4corr8Tf35/KlSszZMgQjh07lumcqampjBs3jtDQUIKCgmjbti0//vhjtmu7Shv44Ycf6NGjBxUrViQgIIB69eoxatQowP6I97HHHgOgTp066WkQjnM4Sxs4efIkDzzwADVq1KB06dLUrVuX8ePHk5ycnOk4i8XCQw89xAcffEDjxo0JCgqiWbNmfPHFF5mOO3bsGMOHDyc8PDz9e2jTpg3ffPONy+/5k08+wWKxsHr16myvvfXWW1gsFnbu3AnAX3/9Rd++falevTr+/v5UrVqVjh07smPHDpfnz2jWrFmULl2aOXPmEB4ezpw5czAMI9txv/76K/369aNq1ar4+/tTs2ZN7r77bpKTk5k7dy533XUXAJGRkenf89y5cwHXj/izfv+XLl3i0UcfpXnz5pQrV44KFSrQqlUrPv30U1OfJauYmBgCAwPTZ1gzWrlyJYcPH2bo0KEALFq0iC5dulCtWjUCAwNp3LgxTzzxhKmnDBaLhUmTJmXb7+xzJyYmMmLECMLCwihdujR16tRh8uTJpKWlZTrurbfeolmzZpQtW5bg4GCuvPJK/ve//5n/8CICQKnCHoCIFK4//vgDgMqVK6fvS0lJ4fbbb2fEiBE88cQTpKWlYbPZiIqKYv369YwbN47WrVuzf/9+Jk6cSEREBFu2bCEwMBCAe++9l/fff5+xY8fSuXNnfv75Z6Kjozl79myu41mxYgU9evSgcePGTJs2jZo1a7Jv3z5WrlwJwD333MPJkyd57bXXiIuLo1q1agAuZ1svXbpEZGQkf/75J5MnT+aaa65h/fr1PPfcc+zYsYMvv/wy0/Fffvklmzdv5plnnqFs2bK8+OKL3Hnnnezdu5e6desCMHDgQLZt28bUqVNp2LAhp0+fZtu2bZw4ccLl57rtttuoUqUKc+bMSf9lwGHu3Lm0aNGCa665BoDu3btjtVp58cUXqVmzJsePH2fjxo1O0ySyOnToECtXrqRnz55UrlyZQYMGMWXKFNatW0eHDh3Sj/vpp59o27YtlSpV4plnnqFBgwYcOXKEzz77jJSUFG699VaeffZZ/ve///HGG2+kp3bUq1cv1zFklJyczMmTJxk7diw1atQgJSWFb775hujoaObMmcPdd9/t1vnKlStHz549WbRoEceOHcv073bOnDkEBAQQExMD2PNfu3fvzqhRoyhTpgy//vorL7zwAj/++CNr1qxx67quJCYmcuONN+Lj48PTTz9NvXr12LRpE1OmTGHfvn3pQfZHH33EAw88wMMPP8zLL7+Mj48Pf/zxB7t37/bIOERKFENESoQ5c+YYgPH9998bqampxtmzZ40vvvjCqFy5shEcHGwkJiYahmEYgwYNMgBj9uzZmd6/cOFCAzCWLl2aaf/mzZsNwHjzzTcNwzCMPXv2GIAxevToTMfNnz/fAIxBgwal71u7dq0BGGvXrk3fV69ePaNevXrGxYsXXX6Wl156yQCMhISEbK916NDB6NChQ/r222+/bQDG4sWLMx33wgsvGICxcuXK9H2AUbVqVSMpKSl9X2JiouHj42M899xz6fvKli1rjBo1yuX4XBkzZowRGBhonD59On3f7t27DcB47bXXDMMwjOPHjxuAMWPGDLfPbxiG8cwzzxiAsXz5csMwDOOvv/4yLBaLMXDgwEzH3XzzzUb58uWNo0ePujzXxx9/nO3+ONSqVSvTvXTI+v1nlZaWZqSmphrDhg0zrr32WlPnzMrx72batGnp+06cOGH4+/sb/fv3d/oem81mpKamGt9++60BGD/99FP6axMnTjSy/ucQMCZOnJjtPFnHOGLECKNs2bLG/v37Mx338ssvG4Dxyy+/GIZhGA899JBRvnz5XD+biOROaQMiJUzLli3x8/MjODiY2267jdDQUL7++muqVq2a6biePXtm2v7iiy8oX748PXr0IC0tLf1P8+bNCQ0NTX9sv3btWgD69++f6f29e/emVKmcH/b89ttv/PnnnwwbNoyAgIB8flK7NWvWUKZMGXr16pVpv+PRb9bH+JGRkQQHB6dvV61alSpVqqSnVQDceOONzJ07lylTpvD999+TmppqaixDhw7l4sWLLFq0KH3fnDlz8Pf3T58trFChAvXq1eOll15i2rRpbN++HZvNZur8hmGkpwp07twZsKdWREREsHTpUpKSkgB7DvO3335L7969M81cFpSPP/6YNm3aULZsWUqVKoWfnx+zZs1iz549eTpfhw4dqFevXqbUgfnz55OcnJyeMgD29IuYmBhCQ0Px9fXFz88vffY5r9fO6osvviAyMpLq1atn+rno1q0bAN9++y1g/zdz+vRp+vXrx6effsrx48c9cn2RkkjBq0gJ8/7777N582a2b9/O33//zc6dO2nTpk2mY4KCgrItovrnn384ffo0pUuXxs/PL9OfxMTE9P8YOx6dh4aGZnp/qVKlqFixYo5jc+TOhoWF5eszZnTixAlCQ0OzlUKqUqUKpUqVyvao39kY/f39uXjxYvr2okWLGDRoEO+99x6tWrWiQoUK3H333SQmJuY4lquuuoobbrghPeiyWq18+OGHREVFUaFCBYD0vNhbbrmFF198kRYtWlC5cmUeeeSRXNMu1qxZQ0JCAnfddRdJSUmcPn2a06dP07t3by5cuMDChQsBOHXqFFar1aPfsytxcXH07t2bGjVq8OGHH7Jp0yY2b97M0KFDuXTpUp7OabFYGDp0KLt27WLLli2A/ZeAOnXqEBkZCcC5c+do164dP/zwA1OmTCE+Pp7NmzcTFxcHkOl+5sc///zD559/nu1n4qqrrgJI/7kYOHAgs2fPZv/+/fTs2ZMqVapw0003sWrVKo+MQ6QkUc6rSAnTuHFjrr/++hyPcVbzslKlSlSsWJHly5c7fY9jttIR/CUmJlKjRo3019PS0nLMCYX/8m4PHTqU43HuqFixIj/88AOGYWT6XEePHiUtLY1KlSq5fc5KlSoxY8YMZsyYwYEDB/jss8944oknOHr0qMvvx2HIkCE88MAD7Nmzh7/++osjR44wZMiQTMfUqlWLWbNmAfbZ6MWLFzNp0iRSUlJ4++23XZ7b8Z5p06Yxbdo0p6+PGDGCChUq4Ovrm6/vOSAgINuCN7AHaxm/0w8//JA6deqwaNGiTN+/s/e6Y/DgwTz99NPMnj0bPz8/tm/fzv/93/+lX2PNmjX8/fffxMfHZ8r1NZM3DPZfWJyNMeu/4UqVKnHNNdcwdepUp+epXr16+t+HDBnCkCFDOH/+POvWrWPixIncdttt/Pbbb9SqVcvUuEREwauImHTbbbfx0UcfYbVauemmm1we51hpPn/+fK677rr0/YsXL862+jqrhg0bUq9ePWbPns2YMWPw9/d3epxjv5nZs44dO7J48WI++eQT7rzzzvT977//fvrr+VGzZk0eeughVq9ezXfffZfr8f369WPMmDHMnTuXv/76ixo1atClSxeXxzds2JCnnnqKpUuXsm3bNpfHnTp1imXLltGmTRumTJmS7fX33nuP+fPn8/PPP3P11VfToUMHPv74Y6ZOneoygM/pe65du3Z6dQSH3377jb1792Y6n8VioXTp0pkC18TExDxXG3CoXr06Xbt2ZeHChaSlpeHj48OgQYMyXTfjZ3CYOXOmqfM7+3xr1qzh3LlzmfbddtttfPXVV9SrV48rrrjC1LnLlClDt27dSElJ4Y477uCXX35R8CriBgWvImJK3759mT9/Pt27d2fkyJHceOON+Pn5cejQIdauXUtUVBR33nknjRs3ZsCAAcyYMQM/Pz86derEzz//zMsvv2yqnusbb7xBjx49aNmyJaNHj6ZmzZocOHCAFStWMH/+fACaNm0KQGxsLIMGDcLPz49GjRplylV1uPvuu3njjTcYNGgQ+/bto2nTpmzYsIFnn32W7t2706lTJ7e+hzNnzhAZGUlMTAxXXnklwcHBbN68meXLlxMdHZ3r+8uXL8+Line truncated
"text/plain": [
"<Figure size 800x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAArEAAAIhCAYAAABZvOJuAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAehNJREFUeJzt3Xt4E2X6N/Bv0paeA5RCW2hLi0AtUFDABUROylkRrAiC+oIiux5QEM+iS0HERVFBd0F+qIAHWLpQFQQLRaiigAgCopSqQGw5ydGm9ESbzPtHSWjSJJ0kk8xM8v1cF5c2eTJ5MpmZ3HPPPc+jEQRBABERERGRimjl7gARERERkasYxBIRERGR6jCIJSIiIiLVYRBLRERERKrDIJaIiIiIVIdBLBERERGpDoNYIiIiIlIdBrFEREREpDoMYomIiIhIdRjEElFAWb58OTQajeVfcHAwEhIScPfdd+O3337z2vtmZWVBo9GIapuSkoKJEyd6rS+u9MfczvyvUaNGSE1NxdSpU/HXX39Z2pnXq16vd7kvGzduRFZWlsuvI6LAxiCWiALSsmXLsHPnTmzZsgVTpkzBunXrcNNNN+HixYteeb8HH3wQO3fu9MqyfSE3Nxc7d+7Ehg0bMGrUKLzzzjsYNmwYpJi5fOPGjZg1a5YEvSSiQBIsdweIiOTQqVMndO/eHQDQv39/GI1GzJw5E5999hnuv/9+yd8vMTERiYmJki/XV7p164bY2FgAwKBBg3D+/Hl89NFH2LFjB3r37i1z74goEDETS0QEWALaP//80+rxPXv24Pbbb0dMTAzCwsJw/fXXIzs726pNeXk5nnrqKaSmpiIsLAwxMTHo3r07Vq1aZWlj7/J9dXU1nnnmGcTHxyMiIgI33XQTdu/eXa9vji7927uEv3r1agwePBgJCQkIDw9Heno6nnvuOZSVlbm8Tpzp2bMnAOCPP/5w2u6DDz5Aly5dLOvljjvuQEFBgeX5iRMn4j//+Q8AWJUtuFOWQESBhZlYIiIAx44dAwC0b9/e8ti2bdswdOhQ9OjRA++++y4aN26M//73vxg7dizKy8stdavTp0/HRx99hDlz5uD6669HWVkZfv75Z5w/f97pe06ePBkffvghnnrqKQwaNAg///wzMjMzUVpa6vbn+O233zB8+HBMmzYNkZGROHz4MObNm4fdu3dj69atbi/X1u+//w4AaN68ucM2r776Kl544QWMGzcOr776Ks6fP4+srCz06tULP/zwA9q1a4eXXnoJZWVlWLNmjVW5RUJCgmR9JSL/xCCWiAKS0WhETU0NKisr8d1332HOnDno27cvbr/9dkubRx55BB07dsTWrVsRHFx7uBwyZAjOnTuHF154Af/v//0/aLVafPfddxg8eDCeeOIJy2tvvfVWp+9/+PBhrFixAk888QRee+01ALWX6ePi4nDPPfe4/blefPFFy/8LgoDevXsjPT0d/fr1w08//YTOnTu7tVzz+rp06RI2bNiAd999F0lJSejTp4/d9n/99RdefvllDB8+HCtXrrQ83r9/f7Rr1w5ZWVn45JNPcM011yAuLg7A1ewuEZEYLCcgooDUs2dPhISEIDo6GkOHDkXTpk3x+eefW4LV33//HYcPH7YElDU1NZZ/w4cPx6lTp1BYWAgA+Nvf/oYvv/wSzz33HPLz81FRUdHg+2/btg0A6gWsY8aMsfTBHUePHsX48eMRHx+PoKAghISEoF+/fgBgdRnfVfHx8QgJCUHTpk1x7733omvXrsjNzUVYWJjd9jt37kRFRUW9URaSkpJw880346uvvnK7L0READOxRBSgPvzwQ6Snp6O0tBSrV6/GkiVLMG7cOHz55ZcArtbGPvXUU3jqqafsLuPcuXMAgLfffhuJiYlYvXo15s2bh7CwMAwZMgSvv/462rVrZ/e15lKD+Ph4q8eDg4PRrFkztz7TpUuX0KdPH4SFhWHOnDlo3749IiIiUFxcjMzMTFHBtSNbtmxB48aNERISgsTExAb7aP589soCWrZsiby8PLf7QkQEMIglogCVnp5uuZlrwIABMBqNeO+997BmzRqMHj3acif+888/j8zMTLvLSEtLAwBERkZi1qxZmDVrFv78809LVnbEiBE4fPiw3deag8DTp0+jVatWlsdramrq1dKas51VVVUIDQ21PG4Oos22bt2KkydPIj8/35J9BWA1nqu7unTpYlknYpg/36lTp+o9d/LkSZeWRURkD8sJiIgAvPbaa2jatCn++c9/wmQyIS0tDe3atcOBAwfQvXt3u/+io6PrLScuLg4TJ07EuHHjUFhYiPLycrvv179/fwDAJ598YvV4dnY2ampqrB5LSUkBAPz0009Wj69fv97qb/MIBnUDXQBYsmSJ8w/vBb16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 truncated
"text/plain": [
"<Figure size 800x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Import display functions\n",
"import display\n",
"%matplotlib inline\n",
"\n",
"# Plot cost functions for each gradient descent method\n",
"display.plot_cost_function(costs_batch, iterations)\n",
"display.plot_cost_function(costs_mini_batch, iterations)\n",
"display.plot_cost_function(costs_stochastic, iterations)\n",
"\n",
"# Compare cost functions across methods\n",
"costs_dict = {\n",
" 'Batch': costs_batch,\n",
" 'Mini-batch': costs_mini_batch,\n",
" 'Stochastic': costs_stochastic\n",
"}\n",
"display.plot_cost_comparison(costs_dict, iterations)\n",
"\n",
"# Plot data with regression line (Batch Gradient Descent)\n",
"display.plot_data_with_regression_line(X, y, theta_batch)\n",
"\n",
"# Compare predictions vs actual values (Batch Gradient Descent)\n",
"y_pred_batch = np.dot(X, theta_batch).reshape(-1, 1)\n",
"display.plot_predictions_vs_actual(y, y_pred_batch)\n",
"\n",
"# Plot residuals (Batch Gradient Descent)\n",
"display.plot_residuals(y, y_pred_batch)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+12
View File
@@ -0,0 +1,12 @@
import numpy as np
def normal_equation(X, y):
"""
Solve linear regression using the normal equation:
θ = (X^T X)^(-1) X^T y
Efficiently implemented using np.linalg.solve to avoid explicit matrix inversion.
"""
X_transpose = np.transpose(X)
theta = np.linalg.solve(X_transpose @ X, X_transpose @ y)
return theta
+67 -8
View File
@@ -13,29 +13,35 @@
3. Redo exercise 1 with regularization
4. Redo exercise 2 with regularization
## plan
## plan for 1
what the fuck is a Linear regression?
it is to my knowledge: fit a thing to a linear equation, with the Minimal Error.
### the data
lets say the data has m rows. and its linear regression. pretty cool how you can train on all the data at the same time.
this is still basic ml after all
### error function, cost function: the thig we want reduced
this is the cost function, also loss function:
$$
E = \frac{1}{2m} \sum^m_{i = 1}\left(h(x_{(i)})- y_{(i)}\right)^2
E = \frac{1}{2m} \sum^m_{i = 1}\left(h(x^{(i)})- y^{(i)}\right)^2
$$
with $h(x)$ being our model (we are trying to find a and b and make our guess $h(x)$ as close to $y$ as possible)
this comes from the error function here:
$$e = \frac{1}{2}\left(h(x_{(i)})-y_{(i)}\right)^2$$
$$e = \frac{1}{2}\left(h(x^{(i)})-y^{(i)}\right)^2$$
and the cost function from the error function:
$$E = \frac{1}{m}\sum^m_{i=1}e_{(i)}$$
$$E = \frac{1}{m}\sum^m_{i=1}e^{(i)}$$
as were dealing with linear fitting ($h(x) = ax + b$) the thing turns to this:
@@ -64,13 +70,66 @@ however they did the calculations:
for our case $h(x) = ax + b$ we have
$$
\frac{\partial}{\partial a}{E(a, b)}
\text{ or } \\
\frac{\partial E}{\partial a} = \frac{1}{m}\sum^m_{i=1}(ax_{(i)}+b - y_{(i)})\cdot x_{(i)}
\begin{align*}
&\frac{\partial}{\partial a}{E(a, b)} &&= \\
&\frac{\partial E}{\partial a} &&= \frac{1}{m}\sum^m_{i=1}(ax^{(i)}+b - y^{(i)})\cdot x^{(i)}
\end{align*}
$$
yeah also for the case of b:
$$b:= b - \alpha \frac{\partial E}{\partial b}$$
$$\frac{\partial E}{\partial b} = \frac{1}{m}\sum^m_{i=1}(ax_{(i)}+b - y_{(i)})$$
$$\frac{\partial E}{\partial b} = \frac{1}{m}\sum^m_{i=1}(ax^{(i)}+b - y^{(i)})$$
note that that $\alpha$ is important. its called learning rate.
### matrix rep. we go big
but now when the columns are many and the rows are also many, what do we do?
it is very convenient that the linear can be represented by a vector of x times a vector of coefficients (weights):
$$
\theta = \begin{vmatrix}\theta_0 \\ \theta_1 \\ \cdots \\ \theta_n \end{vmatrix} \text{ and }x = \begin{vmatrix}1 \\ x_1 \\ \cdots \\ x_n \end{vmatrix}\\
\implies h(x) = \theta^Tx
$$
cost fucntion here:
$$
E = \frac{1}{2m} \sum^m_{i = 1}\left(\theta^Tx^{(i)}- y^{(i)}\right)^2
$$
and a very generalized gradient descent!!!
$$
\theta_j:= \theta_j - \alpha \frac{\partial E}{\partial \theta_j}\\
\frac{\partial E}{\partial \theta_j} = \frac{1}{m}\sum^m_{i=1}(\theta^Tx^{(i)} - y^{(i)})\cdot x^{(i)}_j
$$
thats insane! also very codable! we already has dot product of 2 vectors `np.dot`, and that is for $\theta^Tx^{(i)}$. the entire table of x across m versions is just a 2d table.
so we could plug this into a
into a chatgpt LMAO aint no way doing this by hand
### ok when are we done?
so its an iterative method where you find a and b and all the other things at the same time using that. and again. and again.
the way we could turn off is jus check if E or e is small enough or we are looping too much
### any way to not ruin our computers?
this does NOT harm your computers. it requires NOTHING to run.
but see this. the m can be anything. it can be one. 64. the whole table.
that is Stochastic, Mini-batch and Batch. crazy. think about it.
## plan for 2
when i calculate $\frac{\partial E}{\partial \theta} = 0$ directly
$$ \theta = (X^T X)^{-1} X^T Y$$
???
+29
View File
@@ -0,0 +1,29 @@
def standardize_df(df):
"""
Standardize the input DataFrame.
Parameters:
df (pandas.DataFrame): The input data.
Returns:
pandas.DataFrame: The standardized data.
"""
return (df - df.mean()) / df.std()
import numpy as np
def standardize(X):
"""
Standardize the input features.
Parameters:
X (numpy.ndarray): The input data matrix (m x n).
Returns:
numpy.ndarray: The standardized data matrix.
"""
mean = np.mean(X, axis=0)
std = np.std(X, axis=0)
return (X - mean) / std
-1
View File
@@ -1,4 +1,3 @@
# ml1
machine learning and data mining 1, lab works