diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml
new file mode 100644
index 00000000..75472f35
--- /dev/null
+++ b/.github/workflows/ruff.yml
@@ -0,0 +1,31 @@
+name: Python Linting
+
+on: [push, pull_request]
+
+jobs:
+ ruff:
+ name: Run Ruff
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: '3.x'
+
+ - name: Install Ruff
+ run: pip install ruff
+
+ - name: Run Ruff (Check)
+ run: ruff check . --exclude "**/problem.py,**/solution.py,**"
+
+ - name: Run Ruff (Format Check)
+ run: ruff format --check . --exclude "**/problem.py,**/solution.py,**"
+
+ - name: Run Ruff (Fix Check)
+ run: ruff check . --fix --exclude "**/problem.py,**/solution.py,**"
+
+ - name: Run Ruff (Fix)
+ run: ruff format . --exclude "**/problem.py,**/solution.py,**"
\ No newline at end of file
diff --git a/old_repo/Problems/100_Softsign/solution.py b/old_repo/Problems/100_Softsign/solution.py
index 7069a041..4f274e7d 100644
--- a/old_repo/Problems/100_Softsign/solution.py
+++ b/old_repo/Problems/100_Softsign/solution.py
@@ -1,31 +1,33 @@
def softsign(x: float) -> float:
"""
Implements the Softsign activation function.
-
+
Args:
x (float): Input value
-
+
Returns:
float: The Softsign of the input, calculated as x/(1 + |x|)
"""
return x / (1 + abs(x))
+
def test_softsign():
# Test case 1: x = 0
assert abs(softsign(0) - 0) < 1e-7, "Test case 1 failed"
-
+
# Test case 2: x = 1
assert abs(softsign(1) - 0.5) < 1e-7, "Test case 2 failed"
-
+
# Test case 3: x = -1
assert abs(softsign(-1) - (-0.5)) < 1e-7, "Test case 3 failed"
-
+
# Test case 4: large positive number
assert abs(softsign(100) - 0.9901) < 1e-4, "Test case 4 failed"
-
+
# Test case 5: large negative number
assert abs(softsign(-100) - (-0.9901)) < 1e-4, "Test case 5 failed"
+
if __name__ == "__main__":
test_softsign()
print("All Softsign tests passed.")
diff --git a/old_repo/Problems/102_Swish/solution.py b/old_repo/Problems/102_Swish/solution.py
index c0c31b72..057002b4 100644
--- a/old_repo/Problems/102_Swish/solution.py
+++ b/old_repo/Problems/102_Swish/solution.py
@@ -1,37 +1,39 @@
import math
+
def swish(x: float) -> float:
"""
Implements the Swish activation function.
-
+
Args:
x: Input value
-
+
Returns:
The Swish activation value
"""
return x * (1 / (1 + math.exp(-x)))
+
def test_swish():
# Test case 1: x = 0
assert abs(swish(0) - 0) < 1e-6, "Test case 1 failed"
-
+
# Test case 2: x = 1
expected = 1 * (1 / (1 + math.exp(-1)))
assert abs(swish(1) - expected) < 1e-6, "Test case 2 failed"
-
+
# Test case 3: x = -1
expected = -1 * (1 / (1 + math.exp(1)))
assert abs(swish(-1) - expected) < 1e-6, "Test case 3 failed"
-
+
# Test case 4: large positive number
x = 10.0
assert abs(swish(x) - x) < 0.01, "Test case 4 failed" # Should be close to x
-
+
# Test case 5: large negative number
assert abs(swish(-10.0)) < 0.01, "Test case 5 failed" # Should be close to 0
+
if __name__ == "__main__":
test_swish()
print("All Swish tests passed.")
-
\ No newline at end of file
diff --git a/old_repo/Problems/103_SELU/solution.py b/old_repo/Problems/103_SELU/solution.py
index 589a8230..6331e319 100644
--- a/old_repo/Problems/103_SELU/solution.py
+++ b/old_repo/Problems/103_SELU/solution.py
@@ -1,39 +1,42 @@
import math
+
def selu(x: float) -> float:
"""
Implements the SELU (Scaled Exponential Linear Unit) activation function.
-
+
Args:
x: Input value
-
+
Returns:
SELU activation value
"""
# Standard SELU parameters
alpha = 1.6732632423543772848170429916717
scale = 1.0507009873554804934193349852946
-
+
if x > 0:
return scale * x
return scale * alpha * (math.exp(x) - 1)
+
def test_selu():
# Test positive input
assert abs(selu(1.0) - 1.0507009873554804) < 1e-7, "Test case 1 failed"
-
+
# Test zero input
assert abs(selu(0.0) - 0.0) < 1e-7, "Test case 2 failed"
-
+
# Test negative input
assert abs(selu(-1.0) - (-1.1113307)) < 1e-6, "Test case 3 failed"
-
+
# Test large positive input
assert abs(selu(5.0) - 5.2535049) < 1e-6, "Test case 4 failed"
-
+
# Test large negative input
assert abs(selu(-5.0) - (-1.7462534)) < 1e-6, "Test case 5 failed"
+
if __name__ == "__main__":
test_selu()
- print("All SELU tests passed.")
\ No newline at end of file
+ print("All SELU tests passed.")
diff --git a/old_repo/Problems/104_logistic_regression/solution.py b/old_repo/Problems/104_logistic_regression/solution.py
index 473320a6..035d950a 100644
--- a/old_repo/Problems/104_logistic_regression/solution.py
+++ b/old_repo/Problems/104_logistic_regression/solution.py
@@ -1,12 +1,13 @@
import numpy as np
-def predict_logistic(X: np.ndarray, weights: np.ndarray, bias: float) -> np.ndarray:
+def predict_logistic(X: np.ndarray, weights: np.ndarray, bias: float) -> np.ndarray:
z = np.dot(X, weights) + bias
z = np.clip(z, -500, 500) # Prevent overflow in exp
probabilities = 1 / (1 + np.exp(-z))
return (probabilities >= 0.5).astype(int)
+
def test_predict_logistic():
# Test case 1: Simple linearly separable case
X1 = np.array([[1, 1], [2, 2], [-1, -1], [-2, -2]])
@@ -29,20 +30,21 @@ def test_predict_logistic():
expected3 = np.array([1, 0, 0])
assert np.array_equal(predict_logistic(X3, w3, b3), expected3), "Test case 3 failed"
-# # Test case 4: Single feature
+ # # Test case 4: Single feature
X4 = np.array([[1], [2], [-1], [-2]]).reshape(-1, 1)
w4 = np.array([2])
b4 = 0
expected4 = np.array([1, 1, 0, 0])
assert np.array_equal(predict_logistic(X4, w4, b4), expected4), "Test case 4 failed"
-# # Test case 5: Numerical stability test with large values
+ # # Test case 5: Numerical stability test with large values
X6 = np.array([[1000, 2000], [-1000, -2000]])
w6 = np.array([0.1, 0.1])
b6 = 0
result6 = predict_logistic(X6, w6, b6)
assert result6[0] == 1 and result6[1] == 0, "Test case 5 failed"
+
if __name__ == "__main__":
test_predict_logistic()
- print("All test cases passed!")
\ No newline at end of file
+ print("All test cases passed!")
diff --git a/old_repo/Problems/105_train_softmaxreg/solution.py b/old_repo/Problems/105_train_softmaxreg/solution.py
index 581a788b..6d41a79c 100644
--- a/old_repo/Problems/105_train_softmaxreg/solution.py
+++ b/old_repo/Problems/105_train_softmaxreg/solution.py
@@ -1,9 +1,10 @@
import numpy as np
-def train_softmaxreg(X: np.ndarray, y: np.ndarray,
- learning_rate: float, iterations: int) -> tuple[list[float], ...]:
- """
+def train_softmaxreg(
+ X: np.ndarray, y: np.ndarray, learning_rate: float, iterations: int
+) -> tuple[list[float], ...]:
+ """
Gradient-descent training algorithm for softmax regression, that collects mean-reduced
CE losses, accuracies.
Returns
@@ -18,14 +19,16 @@ def softmax(z):
return np.exp(z) / np.sum(np.exp(z), axis=1, keepdims=True)
def accuracy(y_pred, y_true):
- return (np.argmax(y_true, axis=1) == np.argmax(y_pred, axis=1)).sum() / len(y_true)
+ return (np.argmax(y_true, axis=1) == np.argmax(y_pred, axis=1)).sum() / len(
+ y_true
+ )
def ce_loss(y_pred, y_true):
true_labels_idx = np.argmax(y_true, axis=1)
- return -np.sum(np.log(y_pred)[list(range(len(y_pred))),true_labels_idx])
-
+ return -np.sum(np.log(y_pred)[list(range(len(y_pred))), true_labels_idx])
+
y = y.astype(int)
- C = y.max()+1 # we assume that classes start from 0
+ C = y.max() + 1 # we assume that classes start from 0
y = np.eye(C)[y]
X = np.hstack((np.ones((X.shape[0], 1)), X))
B = np.zeros((X.shape[1], C))
@@ -42,50 +45,72 @@ def ce_loss(y_pred, y_true):
def test_train_softmaxreg():
# Test 1
- X = np.array([[ 2.52569869, 2.33335813, 1.77303921, 0.41061103, -1.66484491],
- [ 1.51013861, 1.30237106, 1.31989315, 1.36087958, 0.46381252],
- [-2.09699866, -1.35960405, -1.04035503, -2.25481082, -0.32359947],
- [-0.96660088, -0.60680633, -0.72017167, -1.73257187, -1.12811486],
- [-0.38096611, -0.24852455, 0.18789426, 0.52359424, 1.30725962],
- [ 0.54828787, 0.33156614, 0.10676247, 0.30694669, -0.37555384],
- [-3.03393135, -2.01966141, -0.6546858 , -0.90330912, 2.89185791],
- [ 0.28602304, -0.1265 , -0.52209915, 0.28309144, -0.5865882 ],
- [-0.26268117, 0.76017979, 1.84095557, -0.23245038, 1.80716891],
- [ 0.30283562, -0.40231495, -1.29550644, -0.1422727 , -1.78121713]])
+ X = np.array(
+ [
+ [2.52569869, 2.33335813, 1.77303921, 0.41061103, -1.66484491],
+ [1.51013861, 1.30237106, 1.31989315, 1.36087958, 0.46381252],
+ [-2.09699866, -1.35960405, -1.04035503, -2.25481082, -0.32359947],
+ [-0.96660088, -0.60680633, -0.72017167, -1.73257187, -1.12811486],
+ [-0.38096611, -0.24852455, 0.18789426, 0.52359424, 1.30725962],
+ [0.54828787, 0.33156614, 0.10676247, 0.30694669, -0.37555384],
+ [-3.03393135, -2.01966141, -0.6546858, -0.90330912, 2.89185791],
+ [0.28602304, -0.1265, -0.52209915, 0.28309144, -0.5865882],
+ [-0.26268117, 0.76017979, 1.84095557, -0.23245038, 1.80716891],
+ [0.30283562, -0.40231495, -1.29550644, -0.1422727, -1.78121713],
+ ]
+ )
y = np.array([2, 3, 0, 0, 1, 3, 0, 1, 2, 1])
learning_rate = 3e-2
iterations = 10
- expected_b = [[-0.0841, -0.5693, -0.3651, -0.2423, -0.5344, 0.0339],
- [0.2566, 0.0535, -0.2104, -0.4004, 0.2709, -0.1461],
- [-0.1318, 0.2109, 0.3998, 0.523, -0.1001, 0.0545],
- [-0.0407, 0.3049, 0.1757, 0.1197, 0.3637, 0.0576]]
- expected_losses = [13.8629, 10.7201, 9.3163, 8.4942, 7.9132,
- 7.4598, 7.0854, 6.7653, 6.4851, 6.2358]
+ expected_b = [
+ [-0.0841, -0.5693, -0.3651, -0.2423, -0.5344, 0.0339],
+ [0.2566, 0.0535, -0.2104, -0.4004, 0.2709, -0.1461],
+ [-0.1318, 0.2109, 0.3998, 0.523, -0.1001, 0.0545],
+ [-0.0407, 0.3049, 0.1757, 0.1197, 0.3637, 0.0576],
+ ]
+ expected_losses = [
+ 13.8629,
+ 10.7201,
+ 9.3163,
+ 8.4942,
+ 7.9132,
+ 7.4598,
+ 7.0854,
+ 6.7653,
+ 6.4851,
+ 6.2358,
+ ]
b, ce = train_softmaxreg(X, y, learning_rate, iterations)
- assert b == expected_b and ce == expected_losses, 'Test case 1 failed'
+ assert b == expected_b and ce == expected_losses, "Test case 1 failed"
# Test 2
- X = np.array([[-0.55605887, -0.74922526, -0.1913345 , 0.41584056],
- [-1.05481124, -1.13763371, -1.28685937, -1.0710115 ],
- [-1.17111877, -1.46866663, -0.75898143, 0.15915148],
- [-1.21725723, -1.55590285, -0.69318542, 0.3580615 ],
- [-1.90316075, -2.06075824, -2.2952422 , -1.87885386],
- [-0.79089629, -0.98662696, -0.52955027, 0.07329079],
- [ 1.97170638, 2.65609694, 0.6802377 , -1.47090364],
- [ 1.46907396, 1.61396429, 1.69602021, 1.29791351],
- [ 0.03095068, 0.15148081, -0.34698116, -0.74306029],
- [-1.40292946, -1.99308861, -0.1478281 , 1.72332995]])
- y = np.array([1., 0., 0., 1., 0., 1., 0., 1., 0., 1.])
+ X = np.array(
+ [
+ [-0.55605887, -0.74922526, -0.1913345, 0.41584056],
+ [-1.05481124, -1.13763371, -1.28685937, -1.0710115],
+ [-1.17111877, -1.46866663, -0.75898143, 0.15915148],
+ [-1.21725723, -1.55590285, -0.69318542, 0.3580615],
+ [-1.90316075, -2.06075824, -2.2952422, -1.87885386],
+ [-0.79089629, -0.98662696, -0.52955027, 0.07329079],
+ [1.97170638, 2.65609694, 0.6802377, -1.47090364],
+ [1.46907396, 1.61396429, 1.69602021, 1.29791351],
+ [0.03095068, 0.15148081, -0.34698116, -0.74306029],
+ [-1.40292946, -1.99308861, -0.1478281, 1.72332995],
+ ]
+ )
+ y = np.array([1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0])
learning_rate = 1e-2
iterations = 7
- expected_b = [[-0.0052, 0.0148, 0.0562, -0.113, -0.2488],
- [0.0052, -0.0148, -0.0562, 0.113, 0.2488]]
+ expected_b = [
+ [-0.0052, 0.0148, 0.0562, -0.113, -0.2488],
+ [0.0052, -0.0148, -0.0562, 0.113, 0.2488],
+ ]
expected_losses = [6.9315, 6.4544, 6.0487, 5.7025, 5.4055, 5.1493, 4.9269]
b, ce = train_softmaxreg(X, y, learning_rate, iterations)
- assert b == expected_b and ce == expected_losses, 'Test case 2 failed'
+ assert b == expected_b and ce == expected_losses, "Test case 2 failed"
- print('All tests passed')
+ print("All tests passed")
-if __name__ == '__main__':
- test_train_softmaxreg()
\ No newline at end of file
+if __name__ == "__main__":
+ test_train_softmaxreg()
diff --git a/old_repo/Problems/106_train_logreg/solution.py b/old_repo/Problems/106_train_logreg/solution.py
index dc50ff52..efb2970c 100644
--- a/old_repo/Problems/106_train_logreg/solution.py
+++ b/old_repo/Problems/106_train_logreg/solution.py
@@ -1,9 +1,10 @@
import numpy as np
-def train_logreg(X: np.ndarray, y: np.ndarray,
- learning_rate: float, iterations: int) -> tuple[list[float], ...]:
- """
+def train_logreg(
+ X: np.ndarray, y: np.ndarray, learning_rate: float, iterations: int
+) -> tuple[list[float], ...]:
+ """
Gradient-descent training algorithm for logistic regression, that collects sum-reduced
BCE losses, accuracies. Assigns label "0" if the P(x_i)<=0.5 and "1" otherwise.
@@ -20,7 +21,7 @@ def sigmoid(x):
def accuracy(y_pred, y_true):
return (y_true == np.rint(y_pred)).sum() / len(y_true)
-
+
def bce_loss(y_pred, y_true):
return -np.sum(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))
@@ -40,45 +41,71 @@ def bce_loss(y_pred, y_true):
def test_train_logreg():
# Test 1
- X = np.array([[ 0.76743473, -0.23413696, -0.23415337, 1.57921282],
- [-1.4123037 , 0.31424733, -1.01283112, -0.90802408],
- [-0.46572975, 0.54256004, -0.46947439, -0.46341769],
- [-0.56228753, -1.91328024, 0.24196227, -1.72491783],
- [-1.42474819, -0.2257763 , 1.46564877, 0.0675282 ],
- [ 1.85227818, -0.29169375, -0.60063869, -0.60170661],
- [ 0.37569802, 0.11092259, -0.54438272, -1.15099358],
- [ 0.19686124, -1.95967012, 0.2088636 , -1.32818605],
- [ 1.52302986, -0.1382643 , 0.49671415, 0.64768854],
- [-1.22084365, -1.05771093, -0.01349722, 0.82254491]])
- y = np.array([1., 0., 0., 0., 1., 1., 0., 0., 1., 0.])
+ X = np.array(
+ [
+ [0.76743473, -0.23413696, -0.23415337, 1.57921282],
+ [-1.4123037, 0.31424733, -1.01283112, -0.90802408],
+ [-0.46572975, 0.54256004, -0.46947439, -0.46341769],
+ [-0.56228753, -1.91328024, 0.24196227, -1.72491783],
+ [-1.42474819, -0.2257763, 1.46564877, 0.0675282],
+ [1.85227818, -0.29169375, -0.60063869, -0.60170661],
+ [0.37569802, 0.11092259, -0.54438272, -1.15099358],
+ [0.19686124, -1.95967012, 0.2088636, -1.32818605],
+ [1.52302986, -0.1382643, 0.49671415, 0.64768854],
+ [-1.22084365, -1.05771093, -0.01349722, 0.82254491],
+ ]
+ )
+ y = np.array([1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0])
learning_rate = 1e-3
iterations = 10
b, llf = train_logreg(X, y, learning_rate, iterations)
- assert b == [-0.0097, 0.0286, 0.015, 0.0135, 0.0316] and \
- llf == [6.9315, 6.9075, 6.8837, 6.8601, 6.8367, 6.8134, 6.7904, 6.7675, 6.7448, 6.7223], \
- 'Test case 1 failed'
+ assert b == [-0.0097, 0.0286, 0.015, 0.0135, 0.0316] and llf == [
+ 6.9315,
+ 6.9075,
+ 6.8837,
+ 6.8601,
+ 6.8367,
+ 6.8134,
+ 6.7904,
+ 6.7675,
+ 6.7448,
+ 6.7223,
+ ], "Test case 1 failed"
# Test 2
- X = np.array([[ 0.76743473, 1.57921282, -0.46947439],
- [-0.23415337, 1.52302986, -0.23413696],
- [ 0.11092259, -0.54438272, -1.15099358],
- [-0.60063869, 0.37569802, -0.29169375],
- [-1.91328024, 0.24196227, -1.72491783],
- [-1.01283112, -0.56228753, 0.31424733],
- [-0.1382643 , 0.49671415, 0.64768854],
- [-0.46341769, 0.54256004, -0.46572975],
- [-1.4123037 , -0.90802408, 1.46564877],
- [ 0.0675282 , -0.2257763 , -1.42474819]])
- y = np.array([1., 1., 0., 0., 0., 0., 1., 1., 0., 0.])
+ X = np.array(
+ [
+ [0.76743473, 1.57921282, -0.46947439],
+ [-0.23415337, 1.52302986, -0.23413696],
+ [0.11092259, -0.54438272, -1.15099358],
+ [-0.60063869, 0.37569802, -0.29169375],
+ [-1.91328024, 0.24196227, -1.72491783],
+ [-1.01283112, -0.56228753, 0.31424733],
+ [-0.1382643, 0.49671415, 0.64768854],
+ [-0.46341769, 0.54256004, -0.46572975],
+ [-1.4123037, -0.90802408, 1.46564877],
+ [0.0675282, -0.2257763, -1.42474819],
+ ]
+ )
+ y = np.array([1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0])
learning_rate = 1e-1
iterations = 10
b, llf = train_logreg(X, y, learning_rate, iterations)
- assert b == [-0.2509, 0.9325, 1.6218, 0.6336] and \
- llf == [6.9315, 5.5073, 4.6382, 4.0609, 3.6503, 3.3432, 3.1045, 2.9134, 2.7567, 2.6258], \
- 'Test case 2 failed'
+ assert b == [-0.2509, 0.9325, 1.6218, 0.6336] and llf == [
+ 6.9315,
+ 5.5073,
+ 4.6382,
+ 4.0609,
+ 3.6503,
+ 3.3432,
+ 3.1045,
+ 2.9134,
+ 2.7567,
+ 2.6258,
+ ], "Test case 2 failed"
- print('All tests passed')
+ print("All tests passed")
-if __name__ == '__main__':
- test_train_logreg()
\ No newline at end of file
+if __name__ == "__main__":
+ test_train_logreg()
diff --git a/old_repo/Problems/107_masked_attention/solution.py b/old_repo/Problems/107_masked_attention/solution.py
index 0386d639..d5bbab50 100644
--- a/old_repo/Problems/107_masked_attention/solution.py
+++ b/old_repo/Problems/107_masked_attention/solution.py
@@ -1,14 +1,17 @@
import numpy as np
from typing import Tuple
-def compute_qkv(X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
+
+def compute_qkv(
+ X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray
+) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""
Compute the Query (Q), Key (K), and Value (V) matrices.
-
+
Args:
X: numpy array of shape (seq_len, d_model), input sequence
W_q, W_k, W_v: numpy arrays of shape (d_model, d_model), weight matrices for Q, K, and V
-
+
Returns:
Q, K, V: numpy arrays of shape (seq_len, d_model)
"""
@@ -17,28 +20,39 @@ def compute_qkv(X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray
V = np.dot(X, W_v) # Compute the Value matrix V
return Q, K, V
-def masked_attention(Q: np.ndarray, K: np.ndarray, V: np.ndarray, mask: np.ndarray) -> np.ndarray:
+
+def masked_attention(
+ Q: np.ndarray, K: np.ndarray, V: np.ndarray, mask: np.ndarray
+) -> np.ndarray:
"""
Compute self-attention for a single head with a mask applied.
-
+
Args:
Q: numpy array of shape (seq_len, d_k), Query matrix
K: numpy array of shape (seq_len, d_k), Key matrix
V: numpy array of shape (seq_len, d_k), Value matrix
mask: numpy array of shape (seq_len, seq_len), Mask matrix
-
+
Returns:
attention_output: numpy array of shape (seq_len, d_k), output of the masked-attention mechanism
"""
d_k = Q.shape[1] # Get the dimension of the keys
- scores = np.matmul(Q, K.T) / np.sqrt(d_k) # Compute scaled dot-product attention scores
-
+ scores = np.matmul(Q, K.T) / np.sqrt(
+ d_k
+ ) # Compute scaled dot-product attention scores
+
# Apply the mask by adding a large negative value to the masked positions
- scores = scores + mask # This will set the masked positions to a large negative value (-inf)
-
+ scores = (
+ scores + mask
+ ) # This will set the masked positions to a large negative value (-inf)
+
# For numerical stability, compute softmax
- attention_weights = np.exp(scores - np.max(scores, axis=1, keepdims=True)) # Subtract max for numerical stability
- attention_weights = attention_weights / np.sum(attention_weights, axis=1, keepdims=True) # Normalize
+ attention_weights = np.exp(
+ scores - np.max(scores, axis=1, keepdims=True)
+ ) # Subtract max for numerical stability
+ attention_weights = attention_weights / np.sum(
+ attention_weights, axis=1, keepdims=True
+ ) # Normalize
# Compute the final attention output
attention_output = np.matmul(attention_weights, V)
@@ -49,41 +63,54 @@ def test_masked_attention():
# Test case 1: Basic functionality with computed Q, K, V
m, n = 6, 8
np.random.seed(42)
- X = np.arange(m*n).reshape(m,n)
+ X = np.arange(m * n).reshape(m, n)
X = np.random.permutation(X.flatten()).reshape(m, n)
- mask = np.triu(np.ones((m, m))*(-np.inf), k=1)
- W_q = np.random.randint(0,4,size=(n,n))
- W_k = np.random.randint(0,5,size=(n,n))
- W_v = np.random.randint(0,6,size=(n,n))
+ mask = np.triu(np.ones((m, m)) * (-np.inf), k=1)
+ W_q = np.random.randint(0, 4, size=(n, n))
+ W_k = np.random.randint(0, 5, size=(n, n))
+ W_v = np.random.randint(0, 6, size=(n, n))
Q, K, V = compute_qkv(X, W_q, W_k, W_v)
# test masked attention
actual_output = masked_attention(Q, K, V, mask)
- expected_output = np.array([[547., 490., 399., 495., 485., 439., 645., 393.],
- [547., 490., 399., 495., 485., 439., 645., 393.],
- [471., 472., 429., 538., 377., 450., 531., 362.],
- [471., 472., 429., 538., 377., 450., 531., 362.],
- [471., 472., 429., 538., 377., 450., 531., 362.],
- [471., 472., 429., 538., 377., 450., 531., 362.]])
- np.testing.assert_array_almost_equal(actual_output, expected_output, decimal=6, err_msg="Test case 1 failed")
+ expected_output = np.array(
+ [
+ [547.0, 490.0, 399.0, 495.0, 485.0, 439.0, 645.0, 393.0],
+ [547.0, 490.0, 399.0, 495.0, 485.0, 439.0, 645.0, 393.0],
+ [471.0, 472.0, 429.0, 538.0, 377.0, 450.0, 531.0, 362.0],
+ [471.0, 472.0, 429.0, 538.0, 377.0, 450.0, 531.0, 362.0],
+ [471.0, 472.0, 429.0, 538.0, 377.0, 450.0, 531.0, 362.0],
+ [471.0, 472.0, 429.0, 538.0, 377.0, 450.0, 531.0, 362.0],
+ ]
+ )
+ np.testing.assert_array_almost_equal(
+ actual_output, expected_output, decimal=6, err_msg="Test case 1 failed"
+ )
# test different shape
m, n = 4, 4
np.random.seed(42)
- X = np.arange(m*n).reshape(m,n)
+ X = np.arange(m * n).reshape(m, n)
X = np.random.permutation(X.flatten()).reshape(m, n)
- mask = np.triu(np.ones((m, m))*(-np.inf), k=1)
- W_q = np.random.randint(0,4,size=(n,n))
- W_k = np.random.randint(0,5,size=(n,n))
- W_v = np.random.randint(0,6,size=(n,n))
+ mask = np.triu(np.ones((m, m)) * (-np.inf), k=1)
+ W_q = np.random.randint(0, 4, size=(n, n))
+ W_k = np.random.randint(0, 5, size=(n, n))
+ W_v = np.random.randint(0, 6, size=(n, n))
Q, K, V = compute_qkv(X, W_q, W_k, W_v)
actual_output = masked_attention(Q, K, V, mask)
- expected_output = np.array([[ 52., 63., 48., 71.],
- [103., 109., 46., 99.],
- [103., 109., 46., 99.],
- [103., 109., 46., 99.]])
- np.testing.assert_array_almost_equal(actual_output, expected_output, decimal=6, err_msg="Test case 2 failed")
+ expected_output = np.array(
+ [
+ [52.0, 63.0, 48.0, 71.0],
+ [103.0, 109.0, 46.0, 99.0],
+ [103.0, 109.0, 46.0, 99.0],
+ [103.0, 109.0, 46.0, 99.0],
+ ]
+ )
+ np.testing.assert_array_almost_equal(
+ actual_output, expected_output, decimal=6, err_msg="Test case 2 failed"
+ )
+
if __name__ == "__main__":
test_masked_attention()
- print("All masked-attention tests passed.")
\ No newline at end of file
+ print("All masked-attention tests passed.")
diff --git a/old_repo/Problems/10_Calculate_cov_matrix/solution.py b/old_repo/Problems/10_Calculate_cov_matrix/solution.py
index 07e2d602..5edcf58c 100644
--- a/old_repo/Problems/10_Calculate_cov_matrix/solution.py
+++ b/old_repo/Problems/10_Calculate_cov_matrix/solution.py
@@ -7,11 +7,15 @@ def calculate_covariance_matrix(vectors: list[list[float]]) -> list[list[float]]
for i in range(n_features):
for j in range(i, n_features):
- covariance = sum((vectors[i][k] - means[i]) * (vectors[j][k] - means[j]) for k in range(n_observations)) / (n_observations - 1)
+ covariance = sum(
+ (vectors[i][k] - means[i]) * (vectors[j][k] - means[j])
+ for k in range(n_observations)
+ ) / (n_observations - 1)
covariance_matrix[i][j] = covariance_matrix[j][i] = covariance
return covariance_matrix
+
def test_calculate_covariance_matrix() -> None:
# Test cases for calculate_covariance_matrix function
@@ -21,7 +25,12 @@ def test_calculate_covariance_matrix() -> None:
# Test case 2
vectors = [[1, 5, 6], [2, 3, 4], [7, 8, 9]]
- assert calculate_covariance_matrix(vectors) == [[7.0, 2.5, 2.5], [2.5, 1.0, 1.0], [2.5, 1.0, 1.0]]
+ assert calculate_covariance_matrix(vectors) == [
+ [7.0, 2.5, 2.5],
+ [2.5, 1.0, 1.0],
+ [2.5, 1.0, 1.0],
+ ]
+
if __name__ == "__main__":
test_calculate_covariance_matrix()
diff --git a/old_repo/Problems/110_METEOR/solution.py b/old_repo/Problems/110_METEOR/solution.py
index 7ef06506..fe43bf3e 100644
--- a/old_repo/Problems/110_METEOR/solution.py
+++ b/old_repo/Problems/110_METEOR/solution.py
@@ -1,33 +1,37 @@
-import numpy as np
from collections import Counter
+
def meteor_score(reference, candidate, alpha=0.9, beta=3, gamma=0.5):
if not reference or not candidate:
raise ValueError("Reference and candidate cannot be empty")
-
+
# Tokenize and count
ref_tokens = reference.lower().split()
cand_tokens = candidate.lower().split()
- # Counter for unigram for reference and candidate
- ref_counts = Counter(ref_tokens)
+ # Counter for unigram for reference and candidate
+ ref_counts = Counter(ref_tokens)
cand_counts = Counter(cand_tokens)
-
+
# Calculate matches
- num_matches = sum((ref_counts & cand_counts).values()) # Number of matching words in candidate and reference
+ num_matches = sum(
+ (ref_counts & cand_counts).values()
+ ) # Number of matching words in candidate and reference
ref_len = len(ref_tokens)
- cand_len = len(cand_tokens)
+ cand_len = len(cand_tokens)
+
+ # Unigram Precision and Recall
+ precision = (
+ num_matches / cand_len if cand_len > 0 else 0
+ ) # Avoiding Division by zero
+ recall = num_matches / ref_len if ref_len > 0 else 0 # Avoiding Division by zero
- # Unigram Precision and Recall
- precision = num_matches / cand_len if cand_len > 0 else 0 # Avoiding Division by zero
- recall = num_matches / ref_len if ref_len > 0 else 0 # Avoiding Division by zero
-
if num_matches == 0:
return 0.0
-
+
fmean = (precision * recall) / (alpha * precision + (1 - alpha) * recall)
- # Chunk calculation
+ # Chunk calculation
matched_positions = []
ref_positions = {} # Store positions of words in reference
used_positions = set() # Track already used indices
@@ -53,9 +57,10 @@ def meteor_score(reference, candidate, alpha=0.9, beta=3, gamma=0.5):
# Fragmentation penalty
penalty = gamma * ((num_chunks / num_matches) ** beta) if num_matches > 0 else 0
-
+
# Final score
- return round(fmean * (1 - penalty), 3) # Rounding to 3 Decimal places
+ return round(fmean * (1 - penalty), 3) # Rounding to 3 Decimal places
+
def test_meteor_score():
# Test Case 1: Identical translations
@@ -63,38 +68,39 @@ def test_meteor_score():
cand_test1 = "The cat sits on the mat"
expected1 = 1.0
assert meteor_score(ref_test1, cand_test1) == expected1, "Test Case 1 Failed"
-
+
# Test Case 2: Similar translations
ref_test2 = "The quick brown fox jumps over the lazy dog"
cand_test2 = "A quick brown fox jumps over a lazy dog"
expected2 = 0.991
assert meteor_score(ref_test2, cand_test2) == expected2, "Test Case 2 Failed"
-
+
# Test Case 3: Completely different translations
ref_test3 = "The cat sits on the mat"
cand_test3 = "Dogs run in the park"
expected3 = 0.0
assert meteor_score(ref_test3, cand_test3) == expected3, "Test Case 3 Failed"
-
+
# Test Case 4: Partially matching translations
ref_test4 = "Machine learning is an exciting field"
cand_test4 = "Machine learning algorithms are fascinating"
expected4 = 0.667
assert meteor_score(ref_test4, cand_test4) == expected4, "Test Case 4 Failed"
-
+
# Test Case 5: Empty input handling
try:
meteor_score("", "Some text")
assert False, "Test Case 5 Failed"
except ValueError:
pass
-
+
# Test Case 6: Partial match with penalty
ref_test6 = "The cat sits on the mat"
cand_test6 = "The cat on the mat sits"
expected6 = 0.933
assert meteor_score(ref_test6, cand_test6) == expected6, "Test Case 6 Failed"
-
+
+
if __name__ == "__main__":
test_meteor_score()
print("All Test Cases Passed!")
diff --git a/old_repo/Problems/111_PMI/solution.py b/old_repo/Problems/111_PMI/solution.py
index 1a99ad14..2f2e4d7f 100644
--- a/old_repo/Problems/111_PMI/solution.py
+++ b/old_repo/Problems/111_PMI/solution.py
@@ -1,75 +1,98 @@
import numpy as np
+
def compute_pmi(joint_counts, total_counts_x, total_counts_y, total_samples):
-
- if not all(isinstance(x, (int, float)) for x in [joint_counts, total_counts_x, total_counts_y, total_samples]):
+ if not all(
+ isinstance(x, (int, float))
+ for x in [joint_counts, total_counts_x, total_counts_y, total_samples]
+ ):
raise ValueError("All inputs must be numeric")
-
- if any(x < 0 for x in [joint_counts, total_counts_x, total_counts_y, total_samples]):
+
+ if any(
+ x < 0 for x in [joint_counts, total_counts_x, total_counts_y, total_samples]
+ ):
raise ValueError("Counts cannot be negative")
-
+
if total_samples == 0:
raise ValueError("Total samples cannot be zero")
-
+
if joint_counts > min(total_counts_x, total_counts_y):
raise ValueError("Joint counts cannot exceed individual counts")
-
+
if any(x > total_samples for x in [total_counts_x, total_counts_y]):
raise ValueError("Individual counts cannot exceed total samples")
-
+
p_x = total_counts_x / total_samples
p_y = total_counts_y / total_samples
p_xy = joint_counts / total_samples
-
+
# Handle edge cases where probabilities are zero
if p_xy == 0 or p_x == 0 or p_y == 0:
- return float('-inf')
-
+ return float("-inf")
+
pmi = np.log2(p_xy / (p_x * p_y))
-
+
return round(pmi, 3)
+
def test_pmi():
# Test Case 1: Perfect positive association
joint_counts1 = 100
total_counts_x1 = 100
total_counts_y1 = 100
total_samples1 = 100
- expected1 = round(np.log2(1/(1*1)), 3) # Should be 0.0
- assert compute_pmi(joint_counts1, total_counts_x1, total_counts_y1, total_samples1) == expected1, "Test Case 1 Failed"
-
+ expected1 = round(np.log2(1 / (1 * 1)), 3) # Should be 0.0
+ assert (
+ compute_pmi(joint_counts1, total_counts_x1, total_counts_y1, total_samples1)
+ == expected1
+ ), "Test Case 1 Failed"
+
# Test Case 2: Independence
joint_counts2 = 25
total_counts_x2 = 50
total_counts_y2 = 50
total_samples2 = 100
- expected2 = round(np.log2((25/100)/((50/100)*(50/100))), 3) # Should be 0.0
- assert compute_pmi(joint_counts2, total_counts_x2, total_counts_y2, total_samples2) == expected2, "Test Case 2 Failed"
-
+ expected2 = round(
+ np.log2((25 / 100) / ((50 / 100) * (50 / 100))), 3
+ ) # Should be 0.0
+ assert (
+ compute_pmi(joint_counts2, total_counts_x2, total_counts_y2, total_samples2)
+ == expected2
+ ), "Test Case 2 Failed"
+
# Test Case 3: Negative association
joint_counts3 = 10
total_counts_x3 = 50
total_counts_y3 = 50
total_samples3 = 100
- expected3 = round(np.log2((10/100)/((50/100)*(50/100))), 3) # Should be negative
- assert compute_pmi(joint_counts3, total_counts_x3, total_counts_y3, total_samples3) == expected3, "Test Case 3 Failed"
-
+ expected3 = round(
+ np.log2((10 / 100) / ((50 / 100) * (50 / 100))), 3
+ ) # Should be negative
+ assert (
+ compute_pmi(joint_counts3, total_counts_x3, total_counts_y3, total_samples3)
+ == expected3
+ ), "Test Case 3 Failed"
+
# Test Case 4: Zero joint occurrence
joint_counts4 = 0
total_counts_x4 = 50
total_counts_y4 = 50
total_samples4 = 100
- expected4 = float('-inf')
- assert compute_pmi(joint_counts4, total_counts_x4, total_counts_y4, total_samples4) == expected4, "Test Case 4 Failed"
-
+ expected4 = float("-inf")
+ assert (
+ compute_pmi(joint_counts4, total_counts_x4, total_counts_y4, total_samples4)
+ == expected4
+ ), "Test Case 4 Failed"
+
# Test Case 5: Invalid inputs
try:
compute_pmi(-1, 50, 50, 100)
assert False, "Test Case 5 Failed: Should raise ValueError for negative counts"
except ValueError:
pass
-
+
print("All Test Cases Passed!")
+
if __name__ == "__main__":
test_pmi()
diff --git a/old_repo/Problems/112_Min_Max_Normalization/solution.py b/old_repo/Problems/112_Min_Max_Normalization/solution.py
index f2a9617e..44838364 100644
--- a/old_repo/Problems/112_Min_Max_Normalization/solution.py
+++ b/old_repo/Problems/112_Min_Max_Normalization/solution.py
@@ -1,29 +1,30 @@
-def min_max(x:list[int])->list[float]:
+def min_max(x: list[int]) -> list[float]:
+ # trying to modify the input list in-place instead creating a new list
- #trying to modify the input list in-place instead creating a new list
+ largest = max(x) # finding the largest value in the input array
+ smallest = min(x) # finding the minimum value in the input array
- largest=max(x) #finding the largest value in the input array
- smallest=min(x) #finding the minimum value in the input array
-
- if largest==smallest: # if input has identical elements
- return[0.0]*len(x)
+ if largest == smallest: # if input has identical elements
+ return [0.0] * len(x)
for i in range(len(x)):
- #using the formula to normalize the input
- x[i]=round((x[i]-smallest)/(largest-smallest),4)
+ # using the formula to normalize the input
+ x[i] = round((x[i] - smallest) / (largest - smallest), 4)
+
+ return x
- return(x)
def test_min_max():
- #first_test_case:
+ # first_test_case:
- assert min_max([1,2,3,4,5])==[0.0, 0.25, 0.5, 0.75, 1.0],"Test Case 1 failed"
+ assert min_max([1, 2, 3, 4, 5]) == [0.0, 0.25, 0.5, 0.75, 1.0], "Test Case 1 failed"
- assert min_max([30,45,56,70,88])==[0.0, 0.2586, 0.4483, 0.6897, 1.0],"Test Case 2 failed"
+ assert min_max([30, 45, 56, 70, 88]) == [0.0, 0.2586, 0.4483, 0.6897, 1.0], (
+ "Test Case 2 failed"
+ )
- assert min_max([5,5,5,5])==[0.0,0.0,0.0,0.0], "Test Case 3 failed"
+ assert min_max([5, 5, 5, 5]) == [0.0, 0.0, 0.0, 0.0], "Test Case 3 failed"
-if __name__=="__main__":
+if __name__ == "__main__":
test_min_max()
print("All Min Max Normalization test cases passed.")
-
diff --git a/old_repo/Problems/116-polynomial-derivative/solution.py b/old_repo/Problems/116-polynomial-derivative/solution.py
index dde1e97a..b3925fd3 100644
--- a/old_repo/Problems/116-polynomial-derivative/solution.py
+++ b/old_repo/Problems/116-polynomial-derivative/solution.py
@@ -1,29 +1,31 @@
-def polynomial_derivative(x: float,n: float) -> float:
+def polynomial_derivative(x: float, n: float) -> float:
if n == 0.0:
return 0.0
- return round(n*(x**(n-1)),4)
+ return round(n * (x ** (n - 1)), 4)
+
def test_polynomial_derivative():
# Test case 1
- x,n = 10.0,0.0
+ x, n = 10.0, 0.0
expected_output = 0.0
- assert polynomial_derivative(x,n) == expected_output, "Test case 1 failed"
+ assert polynomial_derivative(x, n) == expected_output, "Test case 1 failed"
# Test case 2
- x,n = 6.0,5.0
+ x, n = 6.0, 5.0
expected_output = 6480.0
- assert polynomial_derivative(x,n) == expected_output, "Test case 2 failed"
+ assert polynomial_derivative(x, n) == expected_output, "Test case 2 failed"
# Test case 3
- x,n = 12.0,4.3
+ x, n = 12.0, 4.3
expected_output = 15659.0917
- assert polynomial_derivative(x,n) == expected_output, "Test case 3 failed"
+ assert polynomial_derivative(x, n) == expected_output, "Test case 3 failed"
# Test case 4
- x,n = 14.35,1.0
+ x, n = 14.35, 1.0
expected_output = 1.0
- assert polynomial_derivative(x,n) == expected_output, "Test case 4 failed"
+ assert polynomial_derivative(x, n) == expected_output, "Test case 4 failed"
+
if __name__ == "__main__":
test_polynomial_derivative()
- print("All Polynomial Derivative tests passed.")
\ No newline at end of file
+ print("All Polynomial Derivative tests passed.")
diff --git a/old_repo/Problems/11_Linear_equations_jacobi/solution.py b/old_repo/Problems/11_Linear_equations_jacobi/solution.py
index f3ae3163..70fa52b7 100644
--- a/old_repo/Problems/11_Linear_equations_jacobi/solution.py
+++ b/old_repo/Problems/11_Linear_equations_jacobi/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def solve_jacobi(A: np.ndarray, b: np.ndarray, n: int) -> list:
d_a = np.diag(A)
nda = A - np.diag(d_a)
@@ -7,10 +8,11 @@ def solve_jacobi(A: np.ndarray, b: np.ndarray, n: int) -> list:
x_hold = np.zeros(len(b))
for _ in range(n):
for i in range(len(A)):
- x_hold[i] = (1/d_a[i]) * (b[i] - sum(nda[i]*x))
+ x_hold[i] = (1 / d_a[i]) * (b[i] - sum(nda[i] * x))
x = x_hold.copy()
return np.round(x, 4).tolist()
+
def test_solve_jacobi() -> None:
# Test cases for solve_jacobi function
@@ -29,6 +31,7 @@ def test_solve_jacobi() -> None:
b = np.array([0, 7, 5])
assert solve_jacobi(A, b, 3) == [1.7083, -1.9583, -0.7812]
+
if __name__ == "__main__":
test_solve_jacobi()
print("All solve_jacobi tests passed.")
diff --git a/old_repo/Problems/11_Linear_equations_jacobi/solution_2.py b/old_repo/Problems/11_Linear_equations_jacobi/solution_2.py
index cf49d2ef..b383abab 100644
--- a/old_repo/Problems/11_Linear_equations_jacobi/solution_2.py
+++ b/old_repo/Problems/11_Linear_equations_jacobi/solution_2.py
@@ -6,11 +6,13 @@ def solve_jacobi(A: np.ndarray, b: np.ndarray, n: int) -> list:
x = np.zeros_like(b)
A_diag_vec = np.diag(A)
for epoch in range(n):
- x = 1/A_diag_vec*(b-(A@x-A_diag_vec*x))
+ x = 1 / A_diag_vec * (b - (A @ x - A_diag_vec * x))
return x
+
import numpy as np
+
def test_solve_jacobi() -> None:
def lists_are_close(list1, list2, tol=1e-4):
"""Helper function to check if two lists are element-wise close."""
@@ -21,26 +23,31 @@ def lists_are_close(list1, list2, tol=1e-4):
b = np.array([-1, 2, 3])
result = solve_jacobi(A, b, 2)
expected = [0.146, 0.2032, -0.5175]
- assert lists_are_close(result, expected), f"Test case 1 failed: {result} != {expected}"
+ assert lists_are_close(result, expected), (
+ f"Test case 1 failed: {result} != {expected}"
+ )
# Test case 2
A = np.array([[4, 1, 2], [1, 5, 1], [2, 1, 3]])
b = np.array([4, 6, 7])
result = solve_jacobi(A, b, 5)
expected = [-0.0806, 0.9324, 2.4422]
- assert lists_are_close(result, expected), f"Test case 2 failed: {result} != {expected}"
+ assert lists_are_close(result, expected), (
+ f"Test case 2 failed: {result} != {expected}"
+ )
# Test case 3
A = np.array([[4, 2, -2], [1, -3, -1], [3, -1, 4]])
b = np.array([0, 7, 5])
result = solve_jacobi(A, b, 3)
expected = [1.7083, -1.9583, -0.7812]
- assert lists_are_close(result, expected), f"Test case 3 failed: {result} != {expected}"
+ assert lists_are_close(result, expected), (
+ f"Test case 3 failed: {result} != {expected}"
+ )
print("All test cases passed!")
-
if __name__ == "__main__":
test_solve_jacobi()
- print("All solve_jacobi tests passed.")
\ No newline at end of file
+ print("All solve_jacobi tests passed.")
diff --git a/old_repo/Problems/129_Unigram/solution.py b/old_repo/Problems/129_Unigram/solution.py
index 38a33a00..c35354bf 100644
--- a/old_repo/Problems/129_Unigram/solution.py
+++ b/old_repo/Problems/129_Unigram/solution.py
@@ -1,26 +1,26 @@
-s=''' I am Jack
+s = """ I am Jack
Jack I am
Jack I like
Jack I do like
- do I like Jack '''
+ do I like Jack """
-def unigram_calculation(s,word):
- tokens=s.split()
- total_word_count=len(tokens)
- word_count=tokens.count(word)
- unigram_p=word_count/total_word_count
- return round(unigram_p,4)
-def test():
+def unigram_calculation(s, word):
+ tokens = s.split()
+ total_word_count = len(tokens)
+ word_count = tokens.count(word)
+ unigram_p = word_count / total_word_count
+ return round(unigram_p, 4)
+
- #test case 1 for the word Jack
- assert unigram_calculation(s,"Jack")==0.1852,"Test Case 1 Failed !"
+def test():
+ # test case 1 for the word Jack
+ assert unigram_calculation(s, "Jack") == 0.1852, "Test Case 1 Failed !"
- #test case 2 for the word like
- assert unigram_calculation(s,"like")==0.1111,"Test Case 2 Failed !"
+ # test case 2 for the word like
+ assert unigram_calculation(s, "like") == 0.1111, "Test Case 2 Failed !"
if __name__ == "__main__":
test()
print("All Unigram tests passed.")
-
diff --git a/old_repo/Problems/12_svd_2x2_singular_values/solution.py b/old_repo/Problems/12_svd_2x2_singular_values/solution.py
index 6d5bc68c..9e48e7e1 100644
--- a/old_repo/Problems/12_svd_2x2_singular_values/solution.py
+++ b/old_repo/Problems/12_svd_2x2_singular_values/solution.py
@@ -1,43 +1,38 @@
-import numpy as np
+import numpy as np
def svd_2x2_singular_values(A: np.ndarray) -> tuple:
- # stick to lowercase
- a = A
-
- a_t = np.transpose(a)
- a_2 = a_t @ a
-
- v = np.eye(2)
-
- for _ in range(1):
- # Compute rotation angle for a 2x2 matrix
- if a_2[0,0] == a_2[1,1]:
- theta = np.pi/4
- else:
- theta = 0.5 * np.arctan2(2 * a_2[0,1], a_2[0,0] - a_2[1,1])
-
- # Create rotation matrix
- r = np.array(
- [
- [np.cos(theta), -np.sin(theta)],
- [np.sin(theta), np.cos(theta)]
- ]
- )
-
- # apply rotation
- d = np.transpose(r) @ a_2 @ r
-
- # update a_2
- a_2 = d
-
- # accumulate v
- v = v @ r
-
- # sigma is the diagonal elements squared
- s = np.sqrt([d[0,0], d[1,1]])
- s_inv = np.array([[1/s[0], 0], [0, 1/s[1]]])
-
- u = a @ v @ s_inv
-
- return (u, s, v.T)
+ # stick to lowercase
+ a = A
+
+ a_t = np.transpose(a)
+ a_2 = a_t @ a
+
+ v = np.eye(2)
+
+ for _ in range(1):
+ # Compute rotation angle for a 2x2 matrix
+ if a_2[0, 0] == a_2[1, 1]:
+ theta = np.pi / 4
+ else:
+ theta = 0.5 * np.arctan2(2 * a_2[0, 1], a_2[0, 0] - a_2[1, 1])
+
+ # Create rotation matrix
+ r = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
+
+ # apply rotation
+ d = np.transpose(r) @ a_2 @ r
+
+ # update a_2
+ a_2 = d
+
+ # accumulate v
+ v = v @ r
+
+ # sigma is the diagonal elements squared
+ s = np.sqrt([d[0, 0], d[1, 1]])
+ s_inv = np.array([[1 / s[0], 0], [0, 1 / s[1]]])
+
+ u = a @ v @ s_inv
+
+ return (u, s, v.T)
diff --git a/old_repo/Problems/138_gini_impurity/solution.py b/old_repo/Problems/138_gini_impurity/solution.py
index c12223e9..87768e07 100644
--- a/old_repo/Problems/138_gini_impurity/solution.py
+++ b/old_repo/Problems/138_gini_impurity/solution.py
@@ -1,6 +1,7 @@
import numpy as np
from typing import Tuple
+
def find_best_split(X: np.ndarray, y: np.ndarray) -> Tuple[int, float]:
"""
Find the best feature and threshold to split the dataset based on Gini impurity.
@@ -14,12 +15,12 @@ def gini_impurity(y_subset: np.ndarray) -> float:
if len(y_subset) == 0:
return 0.0
p = np.mean(y_subset == 1)
- return 1.0 - (p ** 2 + (1 - p) ** 2)
+ return 1.0 - (p**2 + (1 - p) ** 2)
n_samples, n_features = X.shape
best_feature = -1
- best_threshold = float('inf')
- best_gini = float('inf')
+ best_threshold = float("inf")
+ best_gini = float("inf")
for feature_index in range(n_features):
thresholds = np.unique(X[:, feature_index])
@@ -39,6 +40,7 @@ def gini_impurity(y_subset: np.ndarray) -> float:
return best_feature, best_threshold
+
def test():
# Test 1: Balanced binary split
X1 = np.array([[2.5], [3.5], [1.0], [4.0]])
@@ -84,5 +86,6 @@ def test():
print("All test cases passed.")
+
if __name__ == "__main__":
test()
diff --git a/old_repo/Problems/13_determinant_4x4/solution.py b/old_repo/Problems/13_determinant_4x4/solution.py
index 6eb09d9b..ad4d3b0a 100644
--- a/old_repo/Problems/13_determinant_4x4/solution.py
+++ b/old_repo/Problems/13_determinant_4x4/solution.py
@@ -1,15 +1,16 @@
-def determinant_4x4(matrix: list[list[int|float]]) -> float:
+def determinant_4x4(matrix: list[list[int | float]]) -> float:
# Base case: If the matrix is 1x1, return its single element
if len(matrix) == 1:
return matrix[0][0]
# Recursive case: Calculate determinant using Laplace's Expansion
det = 0
for c in range(len(matrix)):
- minor = [row[:c] + row[c+1:] for row in matrix[1:]] # Remove column c
- cofactor = ((-1)**c) * determinant_4x4(minor) # Compute cofactor
+ minor = [row[:c] + row[c + 1 :] for row in matrix[1:]] # Remove column c
+ cofactor = ((-1) ** c) * determinant_4x4(minor) # Compute cofactor
det += matrix[0][c] * cofactor # Add to running total
return det
+
def test_determinant_4x4() -> None:
# Test case 1
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
@@ -23,6 +24,7 @@ def test_determinant_4x4() -> None:
matrix = [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]]
assert determinant_4x4(matrix) == 0, "Test case 3 failed"
+
if __name__ == "__main__":
test_determinant_4x4()
print("All determinant_4x4 tests passed.")
diff --git a/old_repo/Problems/14_linear_regression_normal_equation/solution.py b/old_repo/Problems/14_linear_regression_normal_equation/solution.py
index 34faa48b..a25da4df 100644
--- a/old_repo/Problems/14_linear_regression_normal_equation/solution.py
+++ b/old_repo/Problems/14_linear_regression_normal_equation/solution.py
@@ -1,19 +1,23 @@
import numpy as np
-def linear_regression_normal_equation(X: list[list[float]], y: list[float]) -> list[float]:
+
+def linear_regression_normal_equation(
+ X: list[list[float]], y: list[float]
+) -> list[float]:
# Convert the inputs to numpy arrays
X = np.array(X)
y = np.array(y).reshape(-1, 1)
-
+
# Compute the normal equation
X_transpose = X.T
theta = np.linalg.inv(X_transpose.dot(X)).dot(X_transpose).dot(y)
-
+
# Round the result to four decimal places
theta = np.round(theta, 4).flatten().tolist()
-
+
return theta
+
def test_linear_regression_normal_equation() -> None:
# Test case 1
X = [[1, 1], [1, 2], [1, 3]]
@@ -23,7 +27,10 @@ def test_linear_regression_normal_equation() -> None:
# Test case 2
X = [[1, 3, 4], [1, 2, 5], [1, 3, 2]]
y = [1, 2, 1]
- assert linear_regression_normal_equation(X, y) == [4.0, -1.0, -0.0], "Test case 2 failed"
+ assert linear_regression_normal_equation(X, y) == [4.0, -1.0, -0.0], (
+ "Test case 2 failed"
+ )
+
if __name__ == "__main__":
test_linear_regression_normal_equation()
diff --git a/old_repo/Problems/15_linear_regression_gradient_descent/solution.py b/old_repo/Problems/15_linear_regression_gradient_descent/solution.py
index fd77afaf..9dc3c526 100644
--- a/old_repo/Problems/15_linear_regression_gradient_descent/solution.py
+++ b/old_repo/Problems/15_linear_regression_gradient_descent/solution.py
@@ -1,36 +1,45 @@
import numpy as np
-def linear_regression_gradient_descent(X: np.ndarray, y: np.ndarray, alpha: float, iterations: int) -> np.ndarray:
+
+def linear_regression_gradient_descent(
+ X: np.ndarray, y: np.ndarray, alpha: float, iterations: int
+) -> np.ndarray:
# Number of training examples and features
m, n = X.shape
-
+
# Initialize the coefficients (weights) to zeros
theta = np.zeros((n, 1))
-
+
# Perform gradient descent for a given number of iterations
for _ in range(iterations):
# Compute the predictions
predictions = X @ theta
-
+
# Calculate the error (difference between predictions and actual values)
errors = predictions - y.reshape(-1, 1)
-
+
# Calculate the updates for the coefficients
updates = X.T @ errors / m
-
+
# Update the coefficients
theta -= alpha * updates
-
+
# Round the coefficients to four decimal places and return as a 1D array
return np.round(theta.flatten(), 4)
+
def test_linear_regression_gradient_descent() -> None:
# Test case 1
X = np.array([[1, 1], [1, 2], [1, 3]])
y = np.array([1, 2, 3])
alpha = 0.01
iterations = 1000
- assert np.allclose(linear_regression_gradient_descent(X, y, alpha, iterations), np.array([0.1107, 0.9513]), atol=1e-4), "Test case 1 failed"
+ assert np.allclose(
+ linear_regression_gradient_descent(X, y, alpha, iterations),
+ np.array([0.1107, 0.9513]),
+ atol=1e-4,
+ ), "Test case 1 failed"
+
if __name__ == "__main__":
test_linear_regression_gradient_descent()
diff --git a/old_repo/Problems/16_feature_scaling/solution.py b/old_repo/Problems/16_feature_scaling/solution.py
index c0f5b5e6..5e2630cc 100644
--- a/old_repo/Problems/16_feature_scaling/solution.py
+++ b/old_repo/Problems/16_feature_scaling/solution.py
@@ -1,26 +1,33 @@
import numpy as np
+
def feature_scaling(data: np.ndarray) -> (np.ndarray, np.ndarray):
# Standardization
mean = np.mean(data, axis=0)
std = np.std(data, axis=0)
standardized_data = (data - mean) / std
-
+
# Min-Max Normalization
min_val = np.min(data, axis=0)
max_val = np.max(data, axis=0)
normalized_data = (data - min_val) / (max_val - min_val)
-
+
# Rounding to four decimal places and converting to lists
- return np.round(standardized_data, 4).tolist(), np.round(normalized_data, 4).tolist()
+ return np.round(standardized_data, 4).tolist(), np.round(
+ normalized_data, 4
+ ).tolist()
+
def test_feature_scaling() -> None:
# Test case 1
data = np.array([[1, 2], [3, 4], [5, 6]])
standardized, normalized = feature_scaling(data)
- assert standardized == [[-1.2247, -1.2247], [0.0, 0.0], [1.2247, 1.2247]], "Test case 1 failed"
+ assert standardized == [[-1.2247, -1.2247], [0.0, 0.0], [1.2247, 1.2247]], (
+ "Test case 1 failed"
+ )
assert normalized == [[0.0, 0.0], [0.5, 0.5], [1.0, 1.0]], "Test case 1 failed"
+
if __name__ == "__main__":
test_feature_scaling()
print("All feature_scaling tests passed.")
diff --git a/old_repo/Problems/17_k_means_clustering/solution.py b/old_repo/Problems/17_k_means_clustering/solution.py
index 49357bd4..4fa79163 100644
--- a/old_repo/Problems/17_k_means_clustering/solution.py
+++ b/old_repo/Problems/17_k_means_clustering/solution.py
@@ -1,70 +1,116 @@
import numpy as np
+
def euclidean_distance(a, b):
return np.sqrt(((a - b) ** 2).sum(axis=1))
+
def k_means_clustering(points, k, initial_centroids, max_iterations):
points = np.array(points)
centroids = np.array(initial_centroids)
-
+
for iteration in range(max_iterations):
# Assign points to the nearest centroid
- distances = np.array([euclidean_distance(points, centroid) for centroid in centroids])
+ distances = np.array(
+ [euclidean_distance(points, centroid) for centroid in centroids]
+ )
assignments = np.argmin(distances, axis=0)
- new_centroids = np.array([points[assignments == i].mean(axis=0) if len(points[assignments == i]) > 0 else centroids[i] for i in range(k)])
-
+ new_centroids = np.array(
+ [
+ points[assignments == i].mean(axis=0)
+ if len(points[assignments == i]) > 0
+ else centroids[i]
+ for i in range(k)
+ ]
+ )
+
# Check for convergence
if np.all(centroids == new_centroids):
break
centroids = new_centroids
centroids = np.round(centroids, 4)
-
+
return [tuple(centroid) for centroid in centroids]
+
def test_k_means_clustering() -> None:
# Test case 1
points = [(1, 2), (1, 4), (1, 0), (10, 2), (10, 4), (10, 0)]
k = 2
initial_centroids = [(1, 1), (10, 1)]
max_iterations = 10
- assert k_means_clustering(points, k, initial_centroids, max_iterations) == [(1.0, 2.0), (10.0, 2.0)], "Test case 1 failed"
+ assert k_means_clustering(points, k, initial_centroids, max_iterations) == [
+ (1.0, 2.0),
+ (10.0, 2.0),
+ ], "Test case 1 failed"
# Test case 2
points = [(0, 0, 0), (2, 2, 2), (1, 1, 1), (9, 10, 9), (10, 11, 10), (12, 11, 12)]
k = 2
initial_centroids = [(1, 1, 1), (10, 10, 10)]
max_iterations = 10
- assert k_means_clustering(points, k, initial_centroids, max_iterations) == [(1.0, 1.0, 1.0), (10.3333, 10.6667, 10.3333)], "Test case 2 failed"
+ assert k_means_clustering(points, k, initial_centroids, max_iterations) == [
+ (1.0, 1.0, 1.0),
+ (10.3333, 10.6667, 10.3333),
+ ], "Test case 2 failed"
# Test case 3: Single cluster
points = [(1, 1), (2, 2), (3, 3), (4, 4)]
k = 1
initial_centroids = [(0, 0)]
max_iterations = 10
- assert k_means_clustering(points, k, initial_centroids, max_iterations) == [(2.5, 2.5)], "Test case 3 failed"
+ assert k_means_clustering(points, k, initial_centroids, max_iterations) == [
+ (2.5, 2.5)
+ ], "Test case 3 failed"
# Test case 4: Four clusters in 2D space
- points = [(0, 0), (1, 0), (0, 1), (1, 1), (5, 5), (6, 5), (5, 6), (6, 6),
- (0, 5), (1, 5), (0, 6), (1, 6), (5, 0), (6, 0), (5, 1), (6, 1)]
+ points = [
+ (0, 0),
+ (1, 0),
+ (0, 1),
+ (1, 1),
+ (5, 5),
+ (6, 5),
+ (5, 6),
+ (6, 6),
+ (0, 5),
+ (1, 5),
+ (0, 6),
+ (1, 6),
+ (5, 0),
+ (6, 0),
+ (5, 1),
+ (6, 1),
+ ]
k = 4
initial_centroids = [(0, 0), (0, 5), (5, 0), (5, 5)]
max_iterations = 10
result = k_means_clustering(points, k, initial_centroids, max_iterations)
expected = [(0.5, 0.5), (0.5, 5.5), (5.5, 0.5), (5.5, 5.5)]
- assert all(np.allclose(r, e) for r, e in zip(result, expected)), "Test case 4 failed"
+ assert all(np.allclose(r, e) for r, e in zip(result, expected)), (
+ "Test case 4 failed"
+ )
# Test case 5: Clusters with different densities
- points = [(0, 0), (0.5, 0), (0, 0.5), (0.5, 0.5), # Dense cluster
- (4, 4), (6, 6)] # Sparse cluster
+ points = [
+ (0, 0),
+ (0.5, 0),
+ (0, 0.5),
+ (0.5, 0.5), # Dense cluster
+ (4, 4),
+ (6, 6),
+ ] # Sparse cluster
k = 2
initial_centroids = [(0, 0), (5, 5)]
max_iterations = 10
result = k_means_clustering(points, k, initial_centroids, max_iterations)
expected = [(0.25, 0.25), (5.0, 5.0)]
- assert all(np.allclose(r, e) for r, e in zip(result, expected)), "Test case 5 failed"
+ assert all(np.allclose(r, e) for r, e in zip(result, expected)), (
+ "Test case 5 failed"
+ )
+
if __name__ == "__main__":
test_k_means_clustering()
print("All k_means_clustering tests passed.")
-
\ No newline at end of file
diff --git a/old_repo/Problems/18_cross_validation_split/solution.py b/old_repo/Problems/18_cross_validation_split/solution.py
index 637ce8c5..3ca5e8cb 100644
--- a/old_repo/Problems/18_cross_validation_split/solution.py
+++ b/old_repo/Problems/18_cross_validation_split/solution.py
@@ -1,7 +1,9 @@
-
import numpy as np
-def k_fold_cross_validation(X: np.ndarray, y: np.ndarray, k=5, shuffle=True, random_seed=None):
+
+def k_fold_cross_validation(
+ X: np.ndarray, y: np.ndarray, k=5, shuffle=True, random_seed=None
+):
"""
Generate train and test indices for k-fold cross-validation.
@@ -23,43 +25,74 @@ def k_fold_cross_validation(X: np.ndarray, y: np.ndarray, k=5, shuffle=True, ran
np.random.shuffle(indices)
fold_sizes = np.full(k, n_samples // k, dtype=int)
- fold_sizes[:n_samples % k] += 1 # Distribute remainder among the first folds
+ fold_sizes[: n_samples % k] += 1 # Distribute remainder among the first folds
folds = []
current = 0
for fold_size in fold_sizes:
- folds.append(indices[current:current + fold_size])
+ folds.append(indices[current : current + fold_size])
current += fold_size
- return [(np.concatenate(folds[:i] + folds[i+1:]).tolist(), folds[i].tolist()) for i in range(k)]
+ return [
+ (np.concatenate(folds[:i] + folds[i + 1 :]).tolist(), folds[i].tolist())
+ for i in range(k)
+ ]
+
def test_k_fold_cross_validation():
# Test case 1: k=5, shuffle=False
- result = k_fold_cross_validation(np.array([0,1,2,3,4,5,6,7,8,9]), np.array([0,1,2,3,4,5,6,7,8,9]), k=5, shuffle=False)
- expected = [([2, 3, 4, 5, 6, 7, 8, 9], [0, 1]), ([0, 1, 4, 5, 6, 7, 8, 9], [2, 3]),
- ([0, 1, 2, 3, 6, 7, 8, 9], [4, 5]), ([0, 1, 2, 3, 4, 5, 8, 9], [6, 7]),
- ([0, 1, 2, 3, 4, 5, 6, 7], [8, 9])]
+ result = k_fold_cross_validation(
+ np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
+ np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
+ k=5,
+ shuffle=False,
+ )
+ expected = [
+ ([2, 3, 4, 5, 6, 7, 8, 9], [0, 1]),
+ ([0, 1, 4, 5, 6, 7, 8, 9], [2, 3]),
+ ([0, 1, 2, 3, 6, 7, 8, 9], [4, 5]),
+ ([0, 1, 2, 3, 4, 5, 8, 9], [6, 7]),
+ ([0, 1, 2, 3, 4, 5, 6, 7], [8, 9]),
+ ]
assert result == expected, "Test case 1 failed"
-
+
# Test case 2: k=2, shuffle=True, fixed seed
- result = k_fold_cross_validation(np.array([0,1,2,3,4,5,6,7,8,9]), np.array([0,1,2,3,4,5,6,7,8,9]), k=2, shuffle=True, random_seed=42)
+ result = k_fold_cross_validation(
+ np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
+ np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
+ k=2,
+ shuffle=True,
+ random_seed=42,
+ )
expected = [([2, 9, 4, 3, 6], [8, 1, 5, 0, 7]), ([8, 1, 5, 0, 7], [2, 9, 4, 3, 6])]
assert result == expected, "Test case 2 failed"
-
+
# Test case 3: k=3, shuffle=False
- result = k_fold_cross_validation(np.array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]),
- np.array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]), k=3, shuffle=False)
- expected = [([5, 6, 7, 8, 9, 10, 11, 12, 13, 14], [0, 1, 2, 3, 4]),
- ([0, 1, 2, 3, 4, 10, 11, 12, 13, 14], [5, 6, 7, 8, 9]),
- ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14])]
+ result = k_fold_cross_validation(
+ np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]),
+ np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]),
+ k=3,
+ shuffle=False,
+ )
+ expected = [
+ ([5, 6, 7, 8, 9, 10, 11, 12, 13, 14], [0, 1, 2, 3, 4]),
+ ([0, 1, 2, 3, 4, 10, 11, 12, 13, 14], [5, 6, 7, 8, 9]),
+ ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14]),
+ ]
assert result == expected, "Test case 3 failed"
-
+
# Test case 4: k=2, shuffle=False
- result = k_fold_cross_validation(np.array([0,1,2,3,4,5,6,7,8,9]), np.array([0,1,2,3,4,5,6,7,8,9]), k=2, shuffle=False)
+ result = k_fold_cross_validation(
+ np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
+ np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
+ k=2,
+ shuffle=False,
+ )
expected = [([5, 6, 7, 8, 9], [0, 1, 2, 3, 4]), ([0, 1, 2, 3, 4], [5, 6, 7, 8, 9])]
assert result == expected, "Test case 4 failed"
-
+
print("All k-fold cross-validation tests passed.")
+
if __name__ == "__main__":
test_k_fold_cross_validation()
diff --git a/old_repo/Problems/19_PCA/solution.py b/old_repo/Problems/19_PCA/solution.py
index 935f2d93..62d2f085 100644
--- a/old_repo/Problems/19_PCA/solution.py
+++ b/old_repo/Problems/19_PCA/solution.py
@@ -1,25 +1,27 @@
import numpy as np
+
def pca(data, k):
# Standardize the data
data_standardized = (data - np.mean(data, axis=0)) / np.std(data, axis=0)
-
+
# Compute the covariance matrix
covariance_matrix = np.cov(data_standardized, rowvar=False)
-
+
# Eigen decomposition
eigenvalues, eigenvectors = np.linalg.eig(covariance_matrix)
-
+
# Sort the eigenvectors by decreasing eigenvalues
idx = np.argsort(eigenvalues)[::-1]
- eigenvalues_sorted = eigenvalues[idx]
+ eigenvalues[idx]
eigenvectors_sorted = eigenvectors[:, idx]
-
+
# Select the top k eigenvectors (principal components)
principal_components = eigenvectors_sorted[:, :k]
-
+
return np.round(principal_components, 4).tolist()
+
def test_pca():
# Test case 1
data = np.array([[4, 2, 1], [5, 6, 7], [9, 12, 1], [4, 6, 7]])
@@ -33,6 +35,7 @@ def test_pca():
expected_output = [[0.7071], [0.7071]]
assert pca(data, k) == expected_output, "Test case 2 failed"
+
if __name__ == "__main__":
test_pca()
print("All pca tests passed.")
diff --git a/old_repo/Problems/1_matrix_times_vector/Easy_and_simple_solution.py b/old_repo/Problems/1_matrix_times_vector/Easy_and_simple_solution.py
index 88501ca8..d9189f24 100644
--- a/old_repo/Problems/1_matrix_times_vector/Easy_and_simple_solution.py
+++ b/old_repo/Problems/1_matrix_times_vector/Easy_and_simple_solution.py
@@ -1,13 +1,15 @@
-def matrix_dot_vector(a: list[list[int|float]], b: list[int|float]) -> list[int|float]:
- # if the no. of columns of a is not equal to the len of vector b then return -1
- if len(a[0]) != len(b):
- return -1
- # create a vector to store the values
- result = []
- # traverse through the matrix and add do the dot product and append to the result vector
- for i in range(len(a)):
- val = 0
- for j in range(len(b)):
- val += a[i][j] * b[j]
- result.append(val)
- return result
+def matrix_dot_vector(
+ a: list[list[int | float]], b: list[int | float]
+) -> list[int | float]:
+ # if the no. of columns of a is not equal to the len of vector b then return -1
+ if len(a[0]) != len(b):
+ return -1
+ # create a vector to store the values
+ result = []
+ # traverse through the matrix and add do the dot product and append to the result vector
+ for i in range(len(a)):
+ val = 0
+ for j in range(len(b)):
+ val += a[i][j] * b[j]
+ result.append(val)
+ return result
diff --git a/old_repo/Problems/1_matrix_times_vector/solution.py b/old_repo/Problems/1_matrix_times_vector/solution.py
index 4a03ea8c..1d8147ff 100644
--- a/old_repo/Problems/1_matrix_times_vector/solution.py
+++ b/old_repo/Problems/1_matrix_times_vector/solution.py
@@ -28,12 +28,13 @@ def test_matrix_dot_vector() -> None:
a: list[list[int | float]] = [[1, 2], [2, 4]]
b: list[int | float] = [1, 2]
assert matrix_dot_vector(a, b) == [5, 10]
-
- # valid product with rectangular matrix (non-square) -- > if we changed "for j in range(len(a[i]))" to "for j in range(len(a))" previous tests will pass
+
+ # valid product with rectangular matrix (non-square) -- > if we changed "for j in range(len(a[i]))" to "for j in range(len(a))" previous tests will pass
a: list[list[int | float]] = [[1, 2, 3], [2, 4, 6]]
b: list[int | float] = [1, 2, 3]
assert matrix_dot_vector(a, b) == [14, 28]
+
if __name__ == "__main__":
test_matrix_dot_vector()
print("All tests passed.")
diff --git a/old_repo/Problems/1_matrix_times_vector/solution3.py b/old_repo/Problems/1_matrix_times_vector/solution3.py
index 9e293e69..8e3dcb14 100644
--- a/old_repo/Problems/1_matrix_times_vector/solution3.py
+++ b/old_repo/Problems/1_matrix_times_vector/solution3.py
@@ -1,10 +1,14 @@
from numpy import dot as dot_product
-def matrix_dot_vector(a: list[list[int|float]], b: list[int|float]) -> list[int|float]:
+
+def matrix_dot_vector(
+ a: list[list[int | float]], b: list[int | float]
+) -> list[int | float]:
if len(a) != len(b):
return -1
- return dot_product(a,b)
+ return dot_product(a, b)
+
def test_matrix_dot_vector() -> None:
# empty product
@@ -19,12 +23,13 @@ def test_matrix_dot_vector() -> None:
a: list[list[int | float]] = [[1, 2], [2, 4]]
b: list[int | float] = [1, 2]
assert matrix_dot_vector(a, b) == [5, 10]
-
- # valid product with rectangular matrix (non-square) -- > if we changed "for j in range(len(a[i]))" to "for j in range(len(a))" previous tests will pass
+
+ # valid product with rectangular matrix (non-square) -- > if we changed "for j in range(len(a[i]))" to "for j in range(len(a))" previous tests will pass
a: list[list[int | float]] = [[1, 2, 3], [2, 4, 6]]
b: list[int | float] = [1, 2, 3]
assert matrix_dot_vector(a, b) == [14, 28]
+
if __name__ == "__main__":
test_matrix_dot_vector()
print("All tests passed.")
diff --git a/old_repo/Problems/1_matrix_times_vector/solution_2.py b/old_repo/Problems/1_matrix_times_vector/solution_2.py
index 0c44153f..dc2d765c 100644
--- a/old_repo/Problems/1_matrix_times_vector/solution_2.py
+++ b/old_repo/Problems/1_matrix_times_vector/solution_2.py
@@ -4,14 +4,14 @@ def matrix_dot_vector(
) -> list[int | float] | int:
#Check that dimensions match
if len(a[0]) != len(b):
- return -1
-
- c = []
+ return -1
+
+ c = []
#Iterate using a list comprehension
- for s_a in a:
- temp = sum([s_a[i]*b[i] for i in range(len(b))])
- c.append(temp)
- return c
+ for s_a in a:
+ temp = sum([s_a[i]*b[i] for i in range(len(b))])
+ c.append(temp)
+ return c
def test_matrix_dot_vector() -> None:
# empty product
diff --git a/old_repo/Problems/20_decision_tree_learning/solution.py b/old_repo/Problems/20_decision_tree_learning/solution.py
index f2e39156..766d1dad 100644
--- a/old_repo/Problems/20_decision_tree_learning/solution.py
+++ b/old_repo/Problems/20_decision_tree_learning/solution.py
@@ -1,67 +1,83 @@
import math
from collections import Counter
+
def calculate_entropy(labels):
label_counts = Counter(labels)
total_count = len(labels)
- entropy = -sum((count / total_count) * math.log2(count / total_count) for count in label_counts.values())
+ entropy = -sum(
+ (count / total_count) * math.log2(count / total_count)
+ for count in label_counts.values()
+ )
return entropy
+
def calculate_information_gain(examples, attr, target_attr):
total_entropy = calculate_entropy([example[target_attr] for example in examples])
values = set(example[attr] for example in examples)
attr_entropy = 0
for value in values:
- value_subset = [example[target_attr] for example in examples if example[attr] == value]
+ value_subset = [
+ example[target_attr] for example in examples if example[attr] == value
+ ]
value_entropy = calculate_entropy(value_subset)
attr_entropy += (len(value_subset) / len(examples)) * value_entropy
return total_entropy - attr_entropy
+
def majority_class(examples, target_attr):
return Counter([example[target_attr] for example in examples]).most_common(1)[0][0]
+
def learn_decision_tree(examples, attributes, target_attr):
if not examples:
- return 'No examples'
+ return "No examples"
if all(example[target_attr] == examples[0][target_attr] for example in examples):
return examples[0][target_attr]
if not attributes:
return majority_class(examples, target_attr)
-
- gains = {attr: calculate_information_gain(examples, attr, target_attr) for attr in attributes}
+
+ gains = {
+ attr: calculate_information_gain(examples, attr, target_attr)
+ for attr in attributes
+ }
best_attr = max(gains, key=gains.get)
tree = {best_attr: {}}
-
+
for value in set(example[best_attr] for example in examples):
subset = [example for example in examples if example[best_attr] == value]
new_attributes = attributes.copy()
new_attributes.remove(best_attr)
subtree = learn_decision_tree(subset, new_attributes, target_attr)
tree[best_attr][value] = subtree
-
+
return tree
+
def test_learn_decision_tree():
# Test case
examples = [
- {'Outlook': 'Sunny', 'Wind': 'Weak', 'PlayTennis': 'No'},
- {'Outlook': 'Overcast', 'Wind': 'Strong', 'PlayTennis': 'Yes'},
- {'Outlook': 'Rain', 'Wind': 'Weak', 'PlayTennis': 'Yes'},
- {'Outlook': 'Sunny', 'Wind': 'Strong', 'PlayTennis': 'No'},
- {'Outlook': 'Sunny', 'Wind': 'Weak', 'PlayTennis': 'Yes'},
- {'Outlook': 'Overcast', 'Wind': 'Weak', 'PlayTennis': 'Yes'},
- {'Outlook': 'Rain', 'Wind': 'Strong', 'PlayTennis': 'No'},
- {'Outlook': 'Rain', 'Wind': 'Weak', 'PlayTennis': 'Yes'}
+ {"Outlook": "Sunny", "Wind": "Weak", "PlayTennis": "No"},
+ {"Outlook": "Overcast", "Wind": "Strong", "PlayTennis": "Yes"},
+ {"Outlook": "Rain", "Wind": "Weak", "PlayTennis": "Yes"},
+ {"Outlook": "Sunny", "Wind": "Strong", "PlayTennis": "No"},
+ {"Outlook": "Sunny", "Wind": "Weak", "PlayTennis": "Yes"},
+ {"Outlook": "Overcast", "Wind": "Weak", "PlayTennis": "Yes"},
+ {"Outlook": "Rain", "Wind": "Strong", "PlayTennis": "No"},
+ {"Outlook": "Rain", "Wind": "Weak", "PlayTennis": "Yes"},
]
- attributes = ['Outlook', 'Wind']
+ attributes = ["Outlook", "Wind"]
expected_output = {
- 'Outlook': {
- 'Sunny': {'Wind': {'Weak': 'No', 'Strong': 'No'}},
- 'Rain': {'Wind': {'Weak': 'Yes', 'Strong': 'No'}},
- 'Overcast': 'Yes'
+ "Outlook": {
+ "Sunny": {"Wind": {"Weak": "No", "Strong": "No"}},
+ "Rain": {"Wind": {"Weak": "Yes", "Strong": "No"}},
+ "Overcast": "Yes",
}
}
- assert learn_decision_tree(examples, attributes, 'PlayTennis') == expected_output, "Test case failed"
+ assert learn_decision_tree(examples, attributes, "PlayTennis") == expected_output, (
+ "Test case failed"
+ )
+
if __name__ == "__main__":
test_learn_decision_tree()
diff --git a/old_repo/Problems/21_pegasos_kernel_svm/solution.py b/old_repo/Problems/21_pegasos_kernel_svm/solution.py
index 2fd0e4f4..2eade777 100644
--- a/old_repo/Problems/21_pegasos_kernel_svm/solution.py
+++ b/old_repo/Problems/21_pegasos_kernel_svm/solution.py
@@ -1,12 +1,17 @@
import numpy as np
+
def linear_kernel(x, y):
return np.dot(x, y)
+
def rbf_kernel(x, y, sigma=1.0):
- return np.exp(-np.linalg.norm(x-y)**2 / (2 * (sigma ** 2)))
+ return np.exp(-(np.linalg.norm(x - y) ** 2) / (2 * (sigma**2)))
+
-def pegasos_kernel_svm(data, labels, kernel='linear', lambda_val=0.01, iterations=100, sigma=1.0):
+def pegasos_kernel_svm(
+ data, labels, kernel="linear", lambda_val=0.01, iterations=100, sigma=1.0
+):
n_samples = len(data)
alphas = np.zeros(n_samples)
b = 0
@@ -14,12 +19,19 @@ def pegasos_kernel_svm(data, labels, kernel='linear', lambda_val=0.01, iteration
for t in range(1, iterations + 1):
for i in range(n_samples):
eta = 1.0 / (lambda_val * t)
- if kernel == 'linear':
+ if kernel == "linear":
kernel_func = linear_kernel
- elif kernel == 'rbf':
- kernel_func = lambda x, y: rbf_kernel(x, y, sigma)
-
- decision = sum(alphas[j] * labels[j] * kernel_func(data[j], data[i]) for j in range(n_samples)) + b
+ elif kernel == "rbf":
+ def kernel_func(x, y):
+ return rbf_kernel(x, y, sigma)
+
+ decision = (
+ sum(
+ alphas[j] * labels[j] * kernel_func(data[j], data[i])
+ for j in range(n_samples)
+ )
+ + b
+ )
if labels[i] * decision < 1:
alphas[i] += eta * (labels[i] - lambda_val * alphas[i])
b += eta * labels[i]
@@ -32,11 +44,22 @@ def test_pegasos_kernel_svm():
data = np.array([[1, 2], [2, 3], [3, 1], [4, 1]])
labels = np.array([1, 1, -1, -1])
expected_output = ([100.0, 0.0, -100.0, -100.0], -937.4755)
- assert pegasos_kernel_svm(data, labels, kernel='linear', lambda_val=0.01, iterations=100) == expected_output, "Test case 1 failed"
-
+ assert (
+ pegasos_kernel_svm(
+ data, labels, kernel="linear", lambda_val=0.01, iterations=100
+ )
+ == expected_output
+ ), "Test case 1 failed"
+
# Test case 2: RBF kernel
expected_output = ([100.0, 99.0, -100.0, -100.0], -115.0)
- assert pegasos_kernel_svm(data, labels, kernel='rbf', lambda_val=0.01, iterations=100, sigma=0.5) == expected_output, "Test case 2 failed"
+ assert (
+ pegasos_kernel_svm(
+ data, labels, kernel="rbf", lambda_val=0.01, iterations=100, sigma=0.5
+ )
+ == expected_output
+ ), "Test case 2 failed"
+
if __name__ == "__main__":
test_pegasos_kernel_svm()
diff --git a/old_repo/Problems/22_sigmoid/solution.py b/old_repo/Problems/22_sigmoid/solution.py
index 31ad7e0f..269ca97b 100644
--- a/old_repo/Problems/22_sigmoid/solution.py
+++ b/old_repo/Problems/22_sigmoid/solution.py
@@ -1,19 +1,22 @@
import math
+
def sigmoid(z: float) -> float:
result = 1 / (1 + math.exp(-z))
return round(result, 4)
+
def test_sigmoid():
# Test case 1: z = 0
assert sigmoid(0) == 0.5, "Test case 1 failed"
-
+
# Test case 2: z = 1
assert sigmoid(1) == 0.7311, "Test case 2 failed"
-
+
# Test case 3: z = -1
assert sigmoid(-1) == 0.2689, "Test case 3 failed"
+
if __name__ == "__main__":
test_sigmoid()
print("All sigmoid tests passed.")
diff --git a/old_repo/Problems/23_softmax/solution.py b/old_repo/Problems/23_softmax/solution.py
index 3b57b532..4b431a08 100644
--- a/old_repo/Problems/23_softmax/solution.py
+++ b/old_repo/Problems/23_softmax/solution.py
@@ -1,11 +1,13 @@
import numpy as np
+
def softmax(scores):
exp_scores = np.exp(scores)
sum_exp_scores = np.sum(exp_scores)
probabilities = np.round(exp_scores / sum_exp_scores, 4)
return probabilities.tolist()
+
def test_softmax():
# Test case 1
scores = [1, 2, 3]
@@ -22,6 +24,7 @@ def test_softmax():
expected_output = [0.0025, 0.0067, 0.9909]
assert softmax(scores) == expected_output, "Test case 3 failed"
+
if __name__ == "__main__":
test_softmax()
print("All softmax tests passed.")
diff --git a/old_repo/Problems/24_single_neuron/solution.py b/old_repo/Problems/24_single_neuron/solution.py
index 3f8ebee7..f075911b 100644
--- a/old_repo/Problems/24_single_neuron/solution.py
+++ b/old_repo/Problems/24_single_neuron/solution.py
@@ -1,17 +1,24 @@
import math
+
def single_neuron_model(features, labels, weights, bias):
probabilities = []
for feature_vector in features:
- z = sum(weight * feature for weight, feature in zip(weights, feature_vector)) + bias
+ z = (
+ sum(weight * feature for weight, feature in zip(weights, feature_vector))
+ + bias
+ )
prob = 1 / (1 + math.exp(-z))
probabilities.append(round(prob, 4))
-
- mse = sum((prob - label) ** 2 for prob, label in zip(probabilities, labels)) / len(labels)
+
+ mse = sum((prob - label) ** 2 for prob, label in zip(probabilities, labels)) / len(
+ labels
+ )
mse = round(mse, 4)
-
+
return probabilities, mse
+
def test_single_neuron_model():
# Test case 1
features = [[0.5, 1.0], [-1.5, -2.0], [2.0, 1.5]]
@@ -19,15 +26,20 @@ def test_single_neuron_model():
weights = [0.7, -0.4]
bias = -0.1
expected_output = ([0.4626, 0.4134, 0.6682], 0.3349)
- assert single_neuron_model(features, labels, weights, bias) == expected_output, "Test case 1 failed"
-
+ assert single_neuron_model(features, labels, weights, bias) == expected_output, (
+ "Test case 1 failed"
+ )
+
# Test case 2
features = [[1, 2], [2, 3], [3, 1]]
labels = [1, 0, 1]
weights = [0.5, -0.2]
bias = 0
expected_output = ([0.525, 0.5987, 0.7858], 0.21)
- assert single_neuron_model(features, labels, weights, bias) == expected_output, "Test case 2 failed"
+ assert single_neuron_model(features, labels, weights, bias) == expected_output, (
+ "Test case 2 failed"
+ )
+
if __name__ == "__main__":
test_single_neuron_model()
diff --git a/old_repo/Problems/25_Single_Neuron_with_Backpropagation/solution.py b/old_repo/Problems/25_Single_Neuron_with_Backpropagation/solution.py
index 1f9e2cf6..41cdba10 100644
--- a/old_repo/Problems/25_Single_Neuron_with_Backpropagation/solution.py
+++ b/old_repo/Problems/25_Single_Neuron_with_Backpropagation/solution.py
@@ -1,9 +1,13 @@
import numpy as np
+
def sigmoid(x):
return 1 / (1 + np.exp(-x))
-def train_neuron(features, labels, initial_weights, initial_bias, learning_rate, epochs):
+
+def train_neuron(
+ features, labels, initial_weights, initial_bias, learning_rate, epochs
+):
weights = np.array(initial_weights)
bias = initial_bias
features = np.array(features)
@@ -13,15 +17,19 @@ def train_neuron(features, labels, initial_weights, initial_bias, learning_rate,
for _ in range(epochs):
z = np.dot(features, weights) + bias
predictions = sigmoid(z)
-
+
mse = np.mean((predictions - labels) ** 2)
mse_values.append(round(mse, 4))
# Gradient calculation for weights and bias
errors = predictions - labels
- weight_gradients = (2/len(labels)) * np.dot(features.T, errors * predictions * (1 - predictions))
- bias_gradient = (2/len(labels)) * np.mean(errors * predictions * (1 - predictions))
-
+ weight_gradients = (2 / len(labels)) * np.dot(
+ features.T, errors * predictions * (1 - predictions)
+ )
+ bias_gradient = (2 / len(labels)) * np.mean(
+ errors * predictions * (1 - predictions)
+ )
+
# Update weights and bias
weights -= learning_rate * weight_gradients
bias -= learning_rate * bias_gradient
@@ -32,6 +40,7 @@ def train_neuron(features, labels, initial_weights, initial_bias, learning_rate,
return updated_weights.tolist(), updated_bias, mse_values
+
def test_train_neuron():
# Test case 1
features = np.array([[1.0, 2.0], [2.0, 1.0], [-1.0, -2.0]])
@@ -41,8 +50,13 @@ def test_train_neuron():
learning_rate = 0.1
epochs = 2
expected_output = ([0.1035, -0.1426], -0.0056, [0.3033, 0.2947])
- assert train_neuron(features, labels, initial_weights, initial_bias, learning_rate, epochs) == expected_output, "Test case 1 failed"
-
+ assert (
+ train_neuron(
+ features, labels, initial_weights, initial_bias, learning_rate, epochs
+ )
+ == expected_output
+ ), "Test case 1 failed"
+
# Test case 2
features = np.array([[1, 2], [2, 3], [3, 1]])
labels = np.array([1, 0, 1])
@@ -51,7 +65,13 @@ def test_train_neuron():
learning_rate = 0.1
epochs = 3
expected_output = ([0.4893, -0.2301], 0.001, [0.21, 0.2087, 0.2076])
- assert train_neuron(features, labels, initial_weights, initial_bias, learning_rate, epochs) == expected_output, "Test case 2 failed"
+ assert (
+ train_neuron(
+ features, labels, initial_weights, initial_bias, learning_rate, epochs
+ )
+ == expected_output
+ ), "Test case 2 failed"
+
if __name__ == "__main__":
test_train_neuron()
diff --git a/old_repo/Problems/26_Autograd/solution.py b/old_repo/Problems/26_Autograd/solution.py
index 68820fda..f7cc198f 100644
--- a/old_repo/Problems/26_Autograd/solution.py
+++ b/old_repo/Problems/26_Autograd/solution.py
@@ -1,5 +1,5 @@
class Value:
- def __init__(self, data, _children=(), _op=''):
+ def __init__(self, data, _children=(), _op=""):
self.data = data
self.grad = 0
self._backward = lambda: None
@@ -8,29 +8,32 @@ def __init__(self, data, _children=(), _op=''):
def __add__(self, other):
other = other if isinstance(other, Value) else Value(other)
- out = Value(self.data + other.data, (self, other), '+')
+ out = Value(self.data + other.data, (self, other), "+")
def _backward():
self.grad += out.grad
other.grad += out.grad
+
out._backward = _backward
return out
def __mul__(self, other):
other = other if isinstance(other, Value) else Value(other)
- out = Value(self.data * other.data, (self, other), '*')
+ out = Value(self.data * other.data, (self, other), "*")
def _backward():
self.grad += other.data * out.grad
other.grad += self.data * out.grad
+
out._backward = _backward
return out
def relu(self):
- out = Value(0 if self.data < 0 else self.data, (self,), 'ReLU')
+ out = Value(0 if self.data < 0 else self.data, (self,), "ReLU")
def _backward():
self.grad += (out.data > 0) * out.grad
+
out._backward = _backward
return out
@@ -78,9 +81,16 @@ def test_value_operations():
# Actual results
results = [a, b, c, d, e, f, g]
- for i, (result, (expected_data, expected_grad)) in enumerate(zip(results, expected)):
- assert result.data == expected_data, f"Test failed at step {i}: data mismatch ({result.data} != {expected_data})"
- assert result.grad == expected_grad, f"Test failed at step {i}: grad mismatch ({result.grad} != {expected_grad})"
+ for i, (result, (expected_data, expected_grad)) in enumerate(
+ zip(results, expected)
+ ):
+ assert result.data == expected_data, (
+ f"Test failed at step {i}: data mismatch ({result.data} != {expected_data})"
+ )
+ assert result.grad == expected_grad, (
+ f"Test failed at step {i}: grad mismatch ({result.grad} != {expected_grad})"
+ )
+
if __name__ == "__main__":
test_value_operations()
diff --git a/old_repo/Problems/28_svd_2x2_eign/solution.py b/old_repo/Problems/28_svd_2x2_eign/solution.py
index 89f388b1..02e21dcf 100644
--- a/old_repo/Problems/28_svd_2x2_eign/solution.py
+++ b/old_repo/Problems/28_svd_2x2_eign/solution.py
@@ -5,8 +5,8 @@ def svd_2x2(A: np.ndarray) -> tuple:
y1, x1 = (A[1, 0] + A[0, 1]), (A[0, 0] - A[1, 1])
y2, x2 = (A[1, 0] - A[0, 1]), (A[0, 0] + A[1, 1])
- h1 = np.sqrt(y1 ** 2 + x1 ** 2)
- h2 = np.sqrt(y2 ** 2 + x2 ** 2)
+ h1 = np.sqrt(y1**2 + x1**2)
+ h2 = np.sqrt(y2**2 + x2**2)
t1 = x1 / h1
t2 = x2 / h2
@@ -34,7 +34,11 @@ def is_equal(A: np.ndarray, B: np.ndarray, precision=1e-10) -> bool:
# 1. U*S*V.T == A
# 2. U and V are orthogonal matrix -> U*U.T == E, V*V.T == E
result = U @ np.diag(s) @ V
- return is_equal(result, A) and is_equal(U @ U.T, np.eye(U.shape[0])) and is_equal(V @ V.T, np.eye(V.shape[0]))
+ return (
+ is_equal(result, A)
+ and is_equal(U @ U.T, np.eye(U.shape[0]))
+ and is_equal(V @ V.T, np.eye(V.shape[0]))
+ )
def test_svd_2x2():
diff --git a/old_repo/Problems/2_transpose_matrix/solution.py b/old_repo/Problems/2_transpose_matrix/solution.py
index 606fbd46..234112b8 100644
--- a/old_repo/Problems/2_transpose_matrix/solution.py
+++ b/old_repo/Problems/2_transpose_matrix/solution.py
@@ -14,6 +14,7 @@ def test_transpose_matrix() -> None:
a: list[list[int | float]] = [[1, 2, 3], [4, 5, 6]]
assert transpose_matrix(a) == [[1, 4], [2, 5], [3, 6]]
+
if __name__ == "__main__":
test_transpose_matrix()
- print("All tests passed.")
\ No newline at end of file
+ print("All tests passed.")
diff --git a/old_repo/Problems/32_polynomial_features/solution.py b/old_repo/Problems/32_polynomial_features/solution.py
index df0d21f1..1a4788a8 100644
--- a/old_repo/Problems/32_polynomial_features/solution.py
+++ b/old_repo/Problems/32_polynomial_features/solution.py
@@ -1,55 +1,136 @@
import numpy as np
from itertools import combinations_with_replacement
+
def polynomial_features(X, degree):
n_samples, n_features = np.shape(X)
# Generate all combinations of feature indices for polynomial terms
def index_combinations():
- combs = [combinations_with_replacement(range(n_features), i) for i in range(0, degree + 1)]
+ combs = [
+ combinations_with_replacement(range(n_features), i)
+ for i in range(0, degree + 1)
+ ]
flat_combs = [item for sublist in combs for item in sublist]
return flat_combs
-
+
combinations = index_combinations()
n_output_features = len(combinations)
X_new = np.empty((n_samples, n_output_features))
-
+
# Compute polynomial features
- for i, index_combs in enumerate(combinations):
+ for i, index_combs in enumerate(combinations):
X_new[:, i] = np.prod(X[:, index_combs], axis=1)
return X_new
+
def test_polynomial_features():
# Test case 1
X = np.array([[2, 3], [3, 4], [5, 6]])
degree = 2
- expected_output = np.array([
- [ 1., 2., 3., 4., 6., 9.],
- [ 1., 3., 4., 9., 12., 16.],
- [ 1., 5., 6., 25., 30., 36.]
- ])
- assert np.allclose(polynomial_features(X, degree), expected_output), "Test case 1 failed"
-
+ expected_output = np.array(
+ [
+ [1.0, 2.0, 3.0, 4.0, 6.0, 9.0],
+ [1.0, 3.0, 4.0, 9.0, 12.0, 16.0],
+ [1.0, 5.0, 6.0, 25.0, 30.0, 36.0],
+ ]
+ )
+ assert np.allclose(polynomial_features(X, degree), expected_output), (
+ "Test case 1 failed"
+ )
+
# Test case 2
X = np.array([[1, 2], [3, 4], [5, 6]])
degree = 3
- expected_output = np.array([
- [ 1., 1., 2., 1., 2., 4., 1., 2., 4., 8.],
- [ 1., 3., 4., 9., 12., 16., 27., 36., 48., 64.],
- [ 1., 5., 6., 25., 30., 36., 125., 150., 180., 216.]
- ])
- assert np.allclose(polynomial_features(X, degree), expected_output), "Test case 2 failed"
-
+ expected_output = np.array(
+ [
+ [1.0, 1.0, 2.0, 1.0, 2.0, 4.0, 1.0, 2.0, 4.0, 8.0],
+ [1.0, 3.0, 4.0, 9.0, 12.0, 16.0, 27.0, 36.0, 48.0, 64.0],
+ [1.0, 5.0, 6.0, 25.0, 30.0, 36.0, 125.0, 150.0, 180.0, 216.0],
+ ]
+ )
+ assert np.allclose(polynomial_features(X, degree), expected_output), (
+ "Test case 2 failed"
+ )
+
# Test case 3
X = np.array([[1, 2, 3], [3, 4, 5], [5, 6, 9]])
degree = 3
- expected_output = np.array([
- [ 1., 1., 2., 3., 1., 2., 3., 4., 6., 9., 1., 2., 3., 4., 6., 9., 8., 12., 18., 27.],
- [ 1., 3., 4., 5., 9., 12., 15., 16., 20., 25., 27., 36., 45., 48., 60., 75., 64., 80., 100., 125.],
- [ 1., 5., 6., 9., 25., 30., 45., 36., 54., 81., 125., 150., 225., 180., 270., 405., 216., 324., 486., 729.]
- ])
- assert np.allclose(polynomial_features(X, degree), expected_output), "Test case 3 failed"
+ expected_output = np.array(
+ [
+ [
+ 1.0,
+ 1.0,
+ 2.0,
+ 3.0,
+ 1.0,
+ 2.0,
+ 3.0,
+ 4.0,
+ 6.0,
+ 9.0,
+ 1.0,
+ 2.0,
+ 3.0,
+ 4.0,
+ 6.0,
+ 9.0,
+ 8.0,
+ 12.0,
+ 18.0,
+ 27.0,
+ ],
+ [
+ 1.0,
+ 3.0,
+ 4.0,
+ 5.0,
+ 9.0,
+ 12.0,
+ 15.0,
+ 16.0,
+ 20.0,
+ 25.0,
+ 27.0,
+ 36.0,
+ 45.0,
+ 48.0,
+ 60.0,
+ 75.0,
+ 64.0,
+ 80.0,
+ 100.0,
+ 125.0,
+ ],
+ [
+ 1.0,
+ 5.0,
+ 6.0,
+ 9.0,
+ 25.0,
+ 30.0,
+ 45.0,
+ 36.0,
+ 54.0,
+ 81.0,
+ 125.0,
+ 150.0,
+ 225.0,
+ 180.0,
+ 270.0,
+ 405.0,
+ 216.0,
+ 324.0,
+ 486.0,
+ 729.0,
+ ],
+ ]
+ )
+ assert np.allclose(polynomial_features(X, degree), expected_output), (
+ "Test case 3 failed"
+ )
+
if __name__ == "__main__":
test_polynomial_features()
diff --git a/old_repo/Problems/33_random_subsets/solution.py b/old_repo/Problems/33_random_subsets/solution.py
index 850fb041..18f293ed 100644
--- a/old_repo/Problems/33_random_subsets/solution.py
+++ b/old_repo/Problems/33_random_subsets/solution.py
@@ -1,12 +1,18 @@
import numpy as np
+
def get_random_subsets(X, y, n_subsets, replacements=True, seed=42):
np.random.seed(seed)
n, m = X.shape
-
+
subset_size = n if replacements else n // 2
- idx = np.array([np.random.choice(n, subset_size, replace=replacements) for _ in range(n_subsets)])
+ idx = np.array(
+ [
+ np.random.choice(n, subset_size, replace=replacements)
+ for _ in range(n_subsets)
+ ]
+ )
# convert all ndarrays to lists
return [(X[idx][i].tolist(), y[idx][i].tolist()) for i in range(n_subsets)]
@@ -15,15 +21,23 @@ def test_get_random_subsets():
# Test case 1
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
y = np.array([1, 2, 3, 4, 5])
- expected_output = [([[3, 4], [9, 10]], [2, 5]), ([[7, 8], [3, 4]], [4, 2]), ([[3, 4], [1, 2]], [2, 1])]
- assert get_random_subsets(X, y, 3, False, seed=42) == expected_output, "Test case 1 failed"
+ expected_output = [
+ ([[3, 4], [9, 10]], [2, 5]),
+ ([[7, 8], [3, 4]], [4, 2]),
+ ([[3, 4], [1, 2]], [2, 1]),
+ ]
+ assert get_random_subsets(X, y, 3, False, seed=42) == expected_output, (
+ "Test case 1 failed"
+ )
-
# Test case 2
X = np.array([[1, 1], [2, 2], [3, 3], [4, 4]])
y = np.array([10, 20, 30, 40])
expected_output = [([[3, 3], [4, 4], [1, 1], [3, 3]], [30, 40, 10, 30])]
- assert get_random_subsets(X, y, 1, True, seed=42) == expected_output, "Test case 2 failed"
+ assert get_random_subsets(X, y, 1, True, seed=42) == expected_output, (
+ "Test case 2 failed"
+ )
+
if __name__ == "__main__":
test_get_random_subsets()
diff --git a/old_repo/Problems/39_log_softmax/solution.py b/old_repo/Problems/39_log_softmax/solution.py
index b1b5da54..d3b4defa 100644
--- a/old_repo/Problems/39_log_softmax/solution.py
+++ b/old_repo/Problems/39_log_softmax/solution.py
@@ -1,23 +1,26 @@
import numpy as np
+
def log_softmax(scores: np.ndarray) -> np.ndarray:
# Subtract the maximum value for numerical stability
scores = scores - np.max(scores)
return np.round(scores - np.log(np.sum(np.exp(scores))), 4)
+
def test_log_softmax():
# Test case 1
- A = np.array([1,2,3])
+ A = np.array([1, 2, 3])
assert np.allclose(log_softmax(A), [-2.4076, -1.4076, -0.4076])
# Test case 2
- A = np.array([1,1,1])
+ A = np.array([1, 1, 1])
assert np.allclose(log_softmax(A), [-1.0986, -1.0986, -1.0986])
# Test case 3
- A = np.array([1,1,0])
+ A = np.array([1, 1, 0])
assert np.allclose(log_softmax(A), [-0.862, -0.862, -1.862])
+
if __name__ == "__main__":
test_log_softmax()
print("All log softmax tests passed.")
diff --git a/old_repo/Problems/3_reshape_matrix/solution.py b/old_repo/Problems/3_reshape_matrix/solution.py
index 9ced9795..3be1dfbd 100644
--- a/old_repo/Problems/3_reshape_matrix/solution.py
+++ b/old_repo/Problems/3_reshape_matrix/solution.py
@@ -1,13 +1,17 @@
import numpy as np
-def reshape_matrix(a: list[list[int | float]],new_shape: tuple[int, int]) -> list[list[int | float]]:
+
+def reshape_matrix(
+ a: list[list[int | float]], new_shape: tuple[int, int]
+) -> list[list[int | float]]:
# Reshape the matrix using numpy and return it as a list of lists
# Not compatible case
- if len(a)*len(a[0]) != new_shape[0]*new_shape[1]:
+ if len(a) * len(a[0]) != new_shape[0] * new_shape[1]:
return []
# Compatible matches
return np.array(a).reshape(new_shape).tolist()
+
def test_reshape_matrix() -> None:
# Test cases for reshape_matrix function
@@ -32,37 +36,47 @@ def test_reshape_matrix() -> None:
assert reshape_matrix(a, new_shape) == []
# Test case 5
- a = [[1, 2],[3, 4]]
+ a = [[1, 2], [3, 4]]
new_shape = (4, 1)
assert reshape_matrix(a, new_shape) == [[1], [2], [3], [4]]
# Test case 6
- a = [[1, 2, 3],[4, 5, 6]]
- new_shape = (2, 3)
+ a = [[1, 2, 3], [4, 5, 6]]
+ new_shape = (2, 3)
assert reshape_matrix(a, new_shape) == [[1, 2, 3], [4, 5, 6]]
# Test case 7
- a = [[1, 2, 3],[4, 5, 6]]
+ a = [[1, 2, 3], [4, 5, 6]]
new_shape = (6, 1)
assert reshape_matrix(a, new_shape) == [[1], [2], [3], [4], [5], [6]]
# Test case 8
- a = [[1, 2],[3, 4],[5, 6]]
+ a = [[1, 2], [3, 4], [5, 6]]
new_shape = (3, 2) # same as original
assert reshape_matrix(a, new_shape) == [[1, 2], [3, 4], [5, 6]]
# Test case 9
- a = [[1.5, 2.2, 3.1],[4.7, 5.9, 6.3]]
+ a = [[1.5, 2.2, 3.1], [4.7, 5.9, 6.3]]
new_shape = (3, 2)
- assert reshape_matrix(a, new_shape) == [[1.5, 2.2],[3.1, 4.7],[5.9, 6.3]]
+ assert reshape_matrix(a, new_shape) == [[1.5, 2.2], [3.1, 4.7], [5.9, 6.3]]
# Test case 10
- a = [[1.5, 2.2, 3.1],[4.7, 5.9, 6.3],[7.7, 8.8, 9.9]]
+ a = [[1.5, 2.2, 3.1], [4.7, 5.9, 6.3], [7.7, 8.8, 9.9]]
new_shape = (9, 1)
- assert reshape_matrix(a, new_shape) == [[1.5], [2.2], [3.1], [4.7], [5.9], [6.3], [7.7], [8.8], [9.9]]
+ assert reshape_matrix(a, new_shape) == [
+ [1.5],
+ [2.2],
+ [3.1],
+ [4.7],
+ [5.9],
+ [6.3],
+ [7.7],
+ [8.8],
+ [9.9],
+ ]
# Test case 11
- a = [[0, 0],[0, 0]]
+ a = [[0, 0], [0, 0]]
new_shape = (2, 2)
assert reshape_matrix(a, new_shape) == [[0, 0], [0, 0]]
@@ -92,14 +106,14 @@ def test_reshape_matrix() -> None:
assert reshape_matrix(a, new_shape) == [[1, 2, 3, 4, 5]]
# Test case 17
- a = [[-1, -2],[-3, -4]]
+ a = [[-1, -2], [-3, -4]]
new_shape = (1, 4)
assert reshape_matrix(a, new_shape) == [[-1, -2, -3, -4]]
# Test case 18
- a = [[-1, 2],[3, -4],[5, 6],[7, -8]]
+ a = [[-1, 2], [3, -4], [5, 6], [7, -8]]
new_shape = (2, 4)
- assert reshape_matrix(a, new_shape) == [[-1, 2, 3, -4],[5, 6, 7, -8]]
+ assert reshape_matrix(a, new_shape) == [[-1, 2, 3, -4], [5, 6, 7, -8]]
# Test case 19
a = [[1, 2, 3, 4, 5, 6]]
@@ -111,6 +125,7 @@ def test_reshape_matrix() -> None:
new_shape = (2, 3)
assert reshape_matrix(a, new_shape) == [[1, 2, 3], [4, 5, 6]]
+
if __name__ == "__main__":
test_reshape_matrix()
- print("All reshape_matrix tests passed.")
\ No newline at end of file
+ print("All reshape_matrix tests passed.")
diff --git a/old_repo/Problems/3_reshape_matrix/solution_2.py b/old_repo/Problems/3_reshape_matrix/solution_2.py
index fa453d05..fa2a8872 100644
--- a/old_repo/Problems/3_reshape_matrix/solution_2.py
+++ b/old_repo/Problems/3_reshape_matrix/solution_2.py
@@ -1,9 +1,11 @@
-def reshape_matrix(a: list[list[int | float]],new_shape: tuple[int, int]) -> list[list[int | float]]:
+def reshape_matrix(
+ a: list[list[int | float]], new_shape: tuple[int, int]
+) -> list[list[int | float]]:
# Extract dimensions
- rows,cols = len(a),len(a[0])
+ rows, cols = len(a), len(a[0])
new_rows, new_cols = new_shape
# Check if reshaping is feasible
- if rows*cols != new_rows*new_cols:
+ if rows * cols != new_rows * new_cols:
return []
# Flatten matrix
flat_matrix = []
@@ -21,7 +23,7 @@ def reshape_matrix(a: list[list[int | float]],new_shape: tuple[int, int]) -> lis
index += 1
reshaped_matrix.append(new_row)
return reshaped_matrix
-
+
def test_reshape_matrix() -> None:
# Test cases for reshape_matrix function
@@ -47,37 +49,47 @@ def test_reshape_matrix() -> None:
assert reshape_matrix(a, new_shape) == []
# Test case 5
- a = [[1, 2],[3, 4]]
+ a = [[1, 2], [3, 4]]
new_shape = (4, 1)
assert reshape_matrix(a, new_shape) == [[1], [2], [3], [4]]
# Test case 6
- a = [[1, 2, 3],[4, 5, 6]]
- new_shape = (2, 3)
+ a = [[1, 2, 3], [4, 5, 6]]
+ new_shape = (2, 3)
assert reshape_matrix(a, new_shape) == [[1, 2, 3], [4, 5, 6]]
# Test case 7
- a = [[1, 2, 3],[4, 5, 6]]
+ a = [[1, 2, 3], [4, 5, 6]]
new_shape = (6, 1)
assert reshape_matrix(a, new_shape) == [[1], [2], [3], [4], [5], [6]]
# Test case 8
- a = [[1, 2],[3, 4],[5, 6]]
+ a = [[1, 2], [3, 4], [5, 6]]
new_shape = (3, 2) # same as original
assert reshape_matrix(a, new_shape) == [[1, 2], [3, 4], [5, 6]]
# Test case 9
- a = [[1.5, 2.2, 3.1],[4.7, 5.9, 6.3]]
+ a = [[1.5, 2.2, 3.1], [4.7, 5.9, 6.3]]
new_shape = (3, 2)
- assert reshape_matrix(a, new_shape) == [[1.5, 2.2],[3.1, 4.7],[5.9, 6.3]]
+ assert reshape_matrix(a, new_shape) == [[1.5, 2.2], [3.1, 4.7], [5.9, 6.3]]
# Test case 10
- a = [[1.5, 2.2, 3.1],[4.7, 5.9, 6.3],[7.7, 8.8, 9.9]]
+ a = [[1.5, 2.2, 3.1], [4.7, 5.9, 6.3], [7.7, 8.8, 9.9]]
new_shape = (9, 1)
- assert reshape_matrix(a, new_shape) == [[1.5], [2.2], [3.1], [4.7], [5.9], [6.3], [7.7], [8.8], [9.9]]
+ assert reshape_matrix(a, new_shape) == [
+ [1.5],
+ [2.2],
+ [3.1],
+ [4.7],
+ [5.9],
+ [6.3],
+ [7.7],
+ [8.8],
+ [9.9],
+ ]
# Test case 11
- a = [[0, 0],[0, 0]]
+ a = [[0, 0], [0, 0]]
new_shape = (2, 2)
assert reshape_matrix(a, new_shape) == [[0, 0], [0, 0]]
@@ -107,14 +119,14 @@ def test_reshape_matrix() -> None:
assert reshape_matrix(a, new_shape) == [[1, 2, 3, 4, 5]]
# Test case 17
- a = [[-1, -2],[-3, -4]]
+ a = [[-1, -2], [-3, -4]]
new_shape = (1, 4)
assert reshape_matrix(a, new_shape) == [[-1, -2, -3, -4]]
# Test case 18
- a = [[-1, 2],[3, -4],[5, 6],[7, -8]]
+ a = [[-1, 2], [3, -4], [5, 6], [7, -8]]
new_shape = (2, 4)
- assert reshape_matrix(a, new_shape) == [[-1, 2, 3, -4],[5, 6, 7, -8]]
+ assert reshape_matrix(a, new_shape) == [[-1, 2, 3, -4], [5, 6, 7, -8]]
# Test case 19
a = [[1, 2, 3, 4, 5, 6]]
@@ -126,6 +138,7 @@ def test_reshape_matrix() -> None:
new_shape = (2, 3)
assert reshape_matrix(a, new_shape) == [[1, 2, 3], [4, 5, 6]]
+
if __name__ == "__main__":
test_reshape_matrix()
- print("All reshape_matrix tests passed.")
\ No newline at end of file
+ print("All reshape_matrix tests passed.")
diff --git a/old_repo/Problems/41_simple_conv2d_layer/solution.py b/old_repo/Problems/41_simple_conv2d_layer/solution.py
index 72e2212f..19a28908 100644
--- a/old_repo/Problems/41_simple_conv2d_layer/solution.py
+++ b/old_repo/Problems/41_simple_conv2d_layer/solution.py
@@ -1,10 +1,15 @@
import numpy as np
-def simple_conv2d(input_matrix: np.ndarray, kernel: np.ndarray, padding: int, stride: int):
+
+def simple_conv2d(
+ input_matrix: np.ndarray, kernel: np.ndarray, padding: int, stride: int
+):
input_height, input_width = input_matrix.shape
kernel_height, kernel_width = kernel.shape
- padded_input = np.pad(input_matrix, ((padding, padding), (padding, padding)), mode='constant')
+ padded_input = np.pad(
+ input_matrix, ((padding, padding), (padding, padding)), mode="constant"
+ )
input_height_padded, input_width_padded = padded_input.shape
output_height = (input_height_padded - kernel_height) // stride + 1
@@ -14,7 +19,10 @@ def simple_conv2d(input_matrix: np.ndarray, kernel: np.ndarray, padding: int, st
for i in range(output_height):
for j in range(output_width):
- region = padded_input[i*stride:i*stride + kernel_height, j*stride:j*stride + kernel_width]
+ region = padded_input[
+ i * stride : i * stride + kernel_height,
+ j * stride : j * stride + kernel_width,
+ ]
output_matrix[i, j] = np.sum(region * kernel)
return output_matrix
@@ -22,79 +30,115 @@ def simple_conv2d(input_matrix: np.ndarray, kernel: np.ndarray, padding: int, st
def test_simple_conv2d():
# Test case 1
- input_matrix = np.array([
- [1., 2., 3., 4., 5.],
- [6., 7., 8., 9., 10.],
- [11., 12., 13., 14., 15.],
- [16., 17., 18., 19., 20.],
- [21., 22., 23., 24., 25.],
- ])
- kernel = np.array([
- [1., 2.],
- [3., -1.],
- ])
+ input_matrix = np.array(
+ [
+ [1.0, 2.0, 3.0, 4.0, 5.0],
+ [6.0, 7.0, 8.0, 9.0, 10.0],
+ [11.0, 12.0, 13.0, 14.0, 15.0],
+ [16.0, 17.0, 18.0, 19.0, 20.0],
+ [21.0, 22.0, 23.0, 24.0, 25.0],
+ ]
+ )
+ kernel = np.array(
+ [
+ [1.0, 2.0],
+ [3.0, -1.0],
+ ]
+ )
padding, stride = 0, 1
- expected = np.array([
- [ 16., 21., 26., 31.],
- [ 41., 46., 51., 56.],
- [ 66., 71., 76., 81.],
- [ 91., 96., 101., 106.],
- ])
- assert np.array_equal(expected, simple_conv2d(input_matrix, kernel, padding, stride))
+ expected = np.array(
+ [
+ [16.0, 21.0, 26.0, 31.0],
+ [41.0, 46.0, 51.0, 56.0],
+ [66.0, 71.0, 76.0, 81.0],
+ [91.0, 96.0, 101.0, 106.0],
+ ]
+ )
+ assert np.array_equal(
+ expected, simple_conv2d(input_matrix, kernel, padding, stride)
+ )
# Test case 2
padding, stride = 1, 1
- expected = np.array([
- [ -1., 1., 3., 5., 7., 15.],
- [ -4., 16., 21., 26., 31., 35.],
- [ 1., 41., 46., 51., 56., 55.],
- [ 6., 66., 71., 76., 81., 75.],
- [ 11., 91., 96., 101., 106., 95.],
- [ 42., 65., 68., 71., 74., 25.],
- ])
- assert np.array_equal(expected, simple_conv2d(input_matrix, kernel, padding, stride))
+ expected = np.array(
+ [
+ [-1.0, 1.0, 3.0, 5.0, 7.0, 15.0],
+ [-4.0, 16.0, 21.0, 26.0, 31.0, 35.0],
+ [1.0, 41.0, 46.0, 51.0, 56.0, 55.0],
+ [6.0, 66.0, 71.0, 76.0, 81.0, 75.0],
+ [11.0, 91.0, 96.0, 101.0, 106.0, 95.0],
+ [42.0, 65.0, 68.0, 71.0, 74.0, 25.0],
+ ]
+ )
+ assert np.array_equal(
+ expected, simple_conv2d(input_matrix, kernel, padding, stride)
+ )
# Test case 3
- kernel = np.array([
- [1., 2., 3.,],
- [-6., 2., 8.,],
- [5., 2., 3.,],
- ])
+ kernel = np.array(
+ [
+ [
+ 1.0,
+ 2.0,
+ 3.0,
+ ],
+ [
+ -6.0,
+ 2.0,
+ 8.0,
+ ],
+ [
+ 5.0,
+ 2.0,
+ 3.0,
+ ],
+ ]
+ )
padding, stride = 0, 1
- expected = np.array([
- [174., 194., 214.],
- [274., 294., 314.],
- [374., 394., 414.],
- ])
- assert np.array_equal(expected, simple_conv2d(input_matrix, kernel, padding, stride))
+ expected = np.array(
+ [
+ [174.0, 194.0, 214.0],
+ [274.0, 294.0, 314.0],
+ [374.0, 394.0, 414.0],
+ ]
+ )
+ assert np.array_equal(
+ expected, simple_conv2d(input_matrix, kernel, padding, stride)
+ )
# Test case 4
padding, stride = 1, 2
- expected = np.array([
- [51., 104., 51.],
- [234., 294., 110.],
- [301., 216., -35.],
- ])
- assert np.array_equal(expected, simple_conv2d(input_matrix, kernel, padding, stride))
+ expected = np.array(
+ [
+ [51.0, 104.0, 51.0],
+ [234.0, 294.0, 110.0],
+ [301.0, 216.0, -35.0],
+ ]
+ )
+ assert np.array_equal(
+ expected, simple_conv2d(input_matrix, kernel, padding, stride)
+ )
# Test case 5
- input_matrix = np.array([
- [1, 2, 3],
- [1, 2, 3],
- [1, 2, 3],
- ])
- kernel = np.array([
- [1, 2, 3],
- [1, 2, 3],
- [1, 2, 3],
- ])
+ input_matrix = np.array(
+ [
+ [1, 2, 3],
+ [1, 2, 3],
+ [1, 2, 3],
+ ]
+ )
+ kernel = np.array(
+ [
+ [1, 2, 3],
+ [1, 2, 3],
+ [1, 2, 3],
+ ]
+ )
padding, stride = 1, 1
- expected = np.array([
- [16., 28., 16.],
- [24., 42., 24.],
- [16., 28., 16.]
-])
- assert np.array_equal(expected, simple_conv2d(input_matrix, kernel, padding, stride))
+ expected = np.array([[16.0, 28.0, 16.0], [24.0, 42.0, 24.0], [16.0, 28.0, 16.0]])
+ assert np.array_equal(
+ expected, simple_conv2d(input_matrix, kernel, padding, stride)
+ )
if __name__ == "__main__":
diff --git a/old_repo/Problems/42_relu_activation_function/solution.py b/old_repo/Problems/42_relu_activation_function/solution.py
index 8de4562e..9114fcac 100644
--- a/old_repo/Problems/42_relu_activation_function/solution.py
+++ b/old_repo/Problems/42_relu_activation_function/solution.py
@@ -1,16 +1,18 @@
def relu(z: float) -> float:
return max(0, z)
+
def test_relu():
# Test case 1: z = 0
assert relu(0) == 0, "Test case 1 failed"
-
+
# Test case 2: z = 1
assert relu(1) == 1, "Test case 2 failed"
-
+
# Test case 3: z = -1
assert relu(-1) == 0, "Test case 3 failed"
+
if __name__ == "__main__":
test_relu()
- print("All ReLU tests passed.")
\ No newline at end of file
+ print("All ReLU tests passed.")
diff --git a/old_repo/Problems/43_ridge_loss/solution.py b/old_repo/Problems/43_ridge_loss/solution.py
index 71c8e5eb..4a342b6c 100644
--- a/old_repo/Problems/43_ridge_loss/solution.py
+++ b/old_repo/Problems/43_ridge_loss/solution.py
@@ -1,30 +1,28 @@
import numpy as np
+
def ridge_loss(X: np.ndarray, w: np.ndarray, y_true: np.ndarray, alpha):
- loss = np.mean((y_true - X@w)**2) + alpha * np.sum(w**2)
+ loss = np.mean((y_true - X @ w) ** 2) + alpha * np.sum(w**2)
return np.array(loss)
def test_ridge_loss():
# Test case 1
- X = np.array([[1,1],[2,1],[3,1],[4,1]])
- W = np.array([.2,2])
- y = np.array([2,3,4,5])
-
- expected = 2.204
- assert np.array_equal(expected, ridge_loss(X,W,y,.1))
+ X = np.array([[1, 1], [2, 1], [3, 1], [4, 1]])
+ W = np.array([0.2, 2])
+ y = np.array([2, 3, 4, 5])
+ expected = 2.204
+ assert np.array_equal(expected, ridge_loss(X, W, y, 0.1))
# Test case 2
- X = np.array([[1,1,4],[2,1,2],[3,1,.1],[4,1,1.2],[1,2,3]])
- W = np.array([.2,2,5])
- y = np.array([2,3,4,5,2])
-
- expected = 161.7884
- assert np.array_equal(expected, ridge_loss(X,W,y,.1))
+ X = np.array([[1, 1, 4], [2, 1, 2], [3, 1, 0.1], [4, 1, 1.2], [1, 2, 3]])
+ W = np.array([0.2, 2, 5])
+ y = np.array([2, 3, 4, 5, 2])
-
+ expected = 161.7884
+ assert np.array_equal(expected, ridge_loss(X, W, y, 0.1))
if __name__ == "__main__":
diff --git a/old_repo/Problems/45_linear_kernel/solution.py b/old_repo/Problems/45_linear_kernel/solution.py
index d532da00..e8d5a827 100644
--- a/old_repo/Problems/45_linear_kernel/solution.py
+++ b/old_repo/Problems/45_linear_kernel/solution.py
@@ -1,21 +1,24 @@
import numpy as np
+
def kernel_function(x1, x2):
return np.inner(x1, x2)
+
def test_kernel_function():
# Test case 1
x1 = np.array([1, 2, 3])
x2 = np.array([4, 5, 6])
expected_output = 32
assert kernel_function(x1, x2) == expected_output, "Test case 1 failed"
-
+
# Test case 2
x1 = np.array([0, 1, 2])
x2 = np.array([3, 4, 5])
expected_output = 14
assert kernel_function(x1, x2) == expected_output, "Test case 2 failed"
+
if __name__ == "__main__":
test_kernel_function()
print("All kernel_function tests passed.")
diff --git a/old_repo/Problems/46_precision/solution.py b/old_repo/Problems/46_precision/solution.py
index df2136ac..73e4c05b 100644
--- a/old_repo/Problems/46_precision/solution.py
+++ b/old_repo/Problems/46_precision/solution.py
@@ -1,9 +1,15 @@
import numpy as np
+
def precision(y_true, y_pred):
true_positives = np.sum((y_true == 1) & (y_pred == 1))
false_positives = np.sum((y_true == 0) & (y_pred == 1))
- return true_positives / (true_positives + false_positives) if (true_positives + false_positives) > 0 else 0.0
+ return (
+ true_positives / (true_positives + false_positives)
+ if (true_positives + false_positives) > 0
+ else 0.0
+ )
+
def test_precision():
# Test case 1
@@ -11,13 +17,14 @@ def test_precision():
y_pred = np.array([1, 0, 1, 0, 0, 1])
expected_output = 1.0
assert precision(y_true, y_pred) == expected_output, "Test case 1 failed"
-
+
# Test case 2
y_true = np.array([1, 0, 1, 1, 0, 0])
y_pred = np.array([1, 0, 0, 0, 0, 1])
expected_output = 0.5
assert precision(y_true, y_pred) == expected_output, "Test case 2 failed"
+
if __name__ == "__main__":
test_precision()
print("All precision tests passed.")
diff --git a/old_repo/Problems/47_gradient_descent/solution.py b/old_repo/Problems/47_gradient_descent/solution.py
index 1331cdf2..596ff2fb 100644
--- a/old_repo/Problems/47_gradient_descent/solution.py
+++ b/old_repo/Problems/47_gradient_descent/solution.py
@@ -1,36 +1,40 @@
import numpy as np
-def gradient_descent(X, y, weights, learning_rate, n_iterations, batch_size=1, method='batch'):
+
+def gradient_descent(
+ X, y, weights, learning_rate, n_iterations, batch_size=1, method="batch"
+):
m = len(y)
-
+
for _ in range(n_iterations):
- if method == 'batch':
+ if method == "batch":
# Calculate the gradient using all data points
predictions = X.dot(weights)
errors = predictions - y
gradient = 2 * X.T.dot(errors) / m
weights = weights - learning_rate * gradient
-
- elif method == 'stochastic':
+
+ elif method == "stochastic":
# Update weights for each data point individually
for i in range(m):
prediction = X[i].dot(weights)
error = prediction - y[i]
gradient = 2 * X[i].T.dot(error)
weights = weights - learning_rate * gradient
-
- elif method == 'mini_batch':
+
+ elif method == "mini_batch":
# Update weights using sequential batches of data points without shuffling
for i in range(0, m, batch_size):
- X_batch = X[i:i+batch_size]
- y_batch = y[i:i+batch_size]
+ X_batch = X[i : i + batch_size]
+ y_batch = y[i : i + batch_size]
predictions = X_batch.dot(weights)
errors = predictions - y_batch
gradient = 2 * X_batch.T.dot(errors) / batch_size
weights = weights - learning_rate * gradient
-
+
return weights
+
def test_gradient_descent():
# Test case 1: Batch Gradient Descent
X = np.array([[1, 1], [2, 1], [3, 1], [4, 1]])
@@ -39,18 +43,32 @@ def test_gradient_descent():
learning_rate = 0.01
n_iterations = 100
expected_output = np.array([1.14905239, 0.56176776])
- assert np.allclose(gradient_descent(X, y, weights, learning_rate, n_iterations, method='batch'), expected_output), "Test case 1 failed"
-
+ assert np.allclose(
+ gradient_descent(X, y, weights, learning_rate, n_iterations, method="batch"),
+ expected_output,
+ ), "Test case 1 failed"
+
# Test case 2: Stochastic Gradient Descent
weights = np.zeros(X.shape[1])
expected_output = np.array([1.0507814, 0.83659454])
- assert np.allclose(gradient_descent(X, y, weights, learning_rate, n_iterations, method='stochastic'), expected_output), "Test case 2 failed"
-
+ assert np.allclose(
+ gradient_descent(
+ X, y, weights, learning_rate, n_iterations, method="stochastic"
+ ),
+ expected_output,
+ ), "Test case 2 failed"
+
# Test case 3: Mini-Batch Gradient Descent
weights = np.zeros(X.shape[1])
batch_size = 2
expected_output = np.array([1.10334065, 0.68329431])
- assert np.allclose(gradient_descent(X, y, weights, learning_rate, n_iterations, batch_size, method='mini_batch'), expected_output), "Test case 3 failed"
+ assert np.allclose(
+ gradient_descent(
+ X, y, weights, learning_rate, n_iterations, batch_size, method="mini_batch"
+ ),
+ expected_output,
+ ), "Test case 3 failed"
+
if __name__ == "__main__":
test_gradient_descent()
diff --git a/old_repo/Problems/48_rref/solution.py b/old_repo/Problems/48_rref/solution.py
index 06ab6807..bd45a181 100644
--- a/old_repo/Problems/48_rref/solution.py
+++ b/old_repo/Problems/48_rref/solution.py
@@ -1,15 +1,17 @@
import numpy as np
+
def rref(matrix):
# Convert to float for division operations
A = matrix.astype(np.float32)
n, m = A.shape
-
+
for i in range(n):
if A[i, i] == 0:
nonzero_rel_id = np.nonzero(A[i:, i])[0]
- if len(nonzero_rel_id) == 0: continue
-
+ if len(nonzero_rel_id) == 0:
+ continue
+
A[i] = A[i] + A[nonzero_rel_id[0] + i]
A[i] = A[i] / A[i, i]
@@ -19,58 +21,33 @@ def rref(matrix):
return A
+
def test_rref():
# Test case 1
- matrix = np.array([
- [1, 2, -1, -4],
- [2, 3, -1, -11],
- [-2, 0, -3, 22]
- ])
- expected_output = np.array([
- [ 1., 0., 0., -8.],
- [ 0., 1., 0., 1.],
- [-0., -0., 1., -2.]
- ])
+ matrix = np.array([[1, 2, -1, -4], [2, 3, -1, -11], [-2, 0, -3, 22]])
+ expected_output = np.array(
+ [[1.0, 0.0, 0.0, -8.0], [0.0, 1.0, 0.0, 1.0], [-0.0, -0.0, 1.0, -2.0]]
+ )
assert np.allclose(rref(matrix), expected_output), "Test case 1 failed"
-
+
# Test case 2
- matrix = np.array([
- [2, 4, -2],
- [4, 9, -3],
- [-2, -3, 7]
- ])
- expected_output = np.array([
- [ 1., 0., 0.],
- [ 0., 1., 0.],
- [ 0., 0., 1.]
- ])
+ matrix = np.array([[2, 4, -2], [4, 9, -3], [-2, -3, 7]])
+ expected_output = np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
assert np.allclose(rref(matrix), expected_output), "Test case 2 failed"
-
+
# Test case 3
- matrix = np.array([
- [0, 2, -1, -4],
- [2, 0, -1, -11],
- [-2, 0, 0, 22]
- ])
- expected_output = np.array([
- [ 1., 0., 0., -11.],
- [-0., 1., 0., -7.5],
- [-0., -0., 1., -11.]
- ])
+ matrix = np.array([[0, 2, -1, -4], [2, 0, -1, -11], [-2, 0, 0, 22]])
+ expected_output = np.array(
+ [[1.0, 0.0, 0.0, -11.0], [-0.0, 1.0, 0.0, -7.5], [-0.0, -0.0, 1.0, -11.0]]
+ )
assert np.allclose(rref(matrix), expected_output), "Test case 3 failed"
-
- # Test case 4
- matrix = np.array([
- [1, 2, -1],
- [2, 4, -1],
- [-2, -4, -3]])
- expected_output = np.array([
- [ 1., 2., 0.],
- [ 0., 0., 0.],
- [-0., -0., 1.]
- ])
+
+ # Test case 4
+ matrix = np.array([[1, 2, -1], [2, 4, -1], [-2, -4, -3]])
+ expected_output = np.array([[1.0, 2.0, 0.0], [0.0, 0.0, 0.0], [-0.0, -0.0, 1.0]])
assert np.allclose(rref(matrix), expected_output), "Test case 4 failed"
+
if __name__ == "__main__":
test_rref()
print("All rref tests passed.")
diff --git a/old_repo/Problems/4_calculate_mean_by_row_or_column/solution.py b/old_repo/Problems/4_calculate_mean_by_row_or_column/solution.py
index 3bd4eda9..5e9bcfcb 100644
--- a/old_repo/Problems/4_calculate_mean_by_row_or_column/solution.py
+++ b/old_repo/Problems/4_calculate_mean_by_row_or_column/solution.py
@@ -3,34 +3,36 @@ def calculate_matrix_mean(
mode: str,
) -> list[float]:
# Calculate mean by row or column
- if mode == 'column':
+ if mode == "column":
return [sum(col) / len(matrix) for col in zip(*matrix)]
- elif mode == 'row':
+ elif mode == "row":
return [sum(row) / len(row) for row in matrix]
else:
raise ValueError("Mode must be 'row' or 'column'")
+
def test_calculate_matrix_mean() -> None:
# Test cases for calculate_matrix_mean function
# Test case 1
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
- mode = 'column'
+ mode = "column"
assert calculate_matrix_mean(matrix, mode) == [4.0, 5.0, 6.0]
# Test case 2
- mode = 'row'
+ mode = "row"
assert calculate_matrix_mean(matrix, mode) == [2.0, 5.0, 8.0]
# Test case 3
matrix = [[1, 2], [3, 4], [5, 6]]
- mode = 'column'
+ mode = "column"
assert calculate_matrix_mean(matrix, mode) == [3.0, 4.0]
# Test case 4
- mode = 'row'
+ mode = "row"
assert calculate_matrix_mean(matrix, mode) == [1.5, 3.5, 5.5]
+
if __name__ == "__main__":
test_calculate_matrix_mean()
- print("All calculate_matrix_mean tests passed.")
\ No newline at end of file
+ print("All calculate_matrix_mean tests passed.")
diff --git a/old_repo/Problems/4_calculate_mean_by_row_or_column/solution_2.py b/old_repo/Problems/4_calculate_mean_by_row_or_column/solution_2.py
index 343b3a52..587cd2b4 100644
--- a/old_repo/Problems/4_calculate_mean_by_row_or_column/solution_2.py
+++ b/old_repo/Problems/4_calculate_mean_by_row_or_column/solution_2.py
@@ -3,42 +3,44 @@ def calculate_matrix_mean(
mode: str,
) -> list[float]:
# Calculate mean by row or column
- if mode not in ['row','column']:
+ if mode not in ["row", "column"]:
raise ValueError("Mode has to be row or column")
- #Get dimensions and initialize return array
+ # Get dimensions and initialize return array
rows, columns = len(matrix), len(matrix[0])
means = []
- #Row mode
- if mode == 'row':
+ # Row mode
+ if mode == "row":
for r in range(rows):
mean = 0
for c in range(columns):
mean += matrix[r][c]
mean /= columns
means.append(mean)
- #Column mode
+ # Column mode
else:
- for c in range(columns):
+ for c in range(columns):
mean = 0
for r in range(rows):
mean += matrix[r][c]
mean /= rows
- means.append(mean)
- #Return
+ means.append(mean)
+ # Return
return means
+
def test_calculate_matrix_mean() -> None:
# Test cases for calculate_matrix_mean function
# Test case 1
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
- mode = 'column'
+ mode = "column"
assert calculate_matrix_mean(matrix, mode) == [4.0, 5.0, 6.0]
# Test case 2
- mode = 'row'
+ mode = "row"
assert calculate_matrix_mean(matrix, mode) == [2.0, 5.0, 8.0]
+
if __name__ == "__main__":
test_calculate_matrix_mean()
- print("All calculate_matrix_mean tests passed.")
\ No newline at end of file
+ print("All calculate_matrix_mean tests passed.")
diff --git a/old_repo/Problems/50_lasso_regression_gradient_descent/solution.py b/old_repo/Problems/50_lasso_regression_gradient_descent/solution.py
index ecf66fc4..8cf2c512 100644
--- a/old_repo/Problems/50_lasso_regression_gradient_descent/solution.py
+++ b/old_repo/Problems/50_lasso_regression_gradient_descent/solution.py
@@ -1,6 +1,14 @@
import numpy as np
-def l1_regularization_gradient_descent(X:np.array, y:np.array, alpha: float=0.1, learning_rate: float=0.01, max_iter: int=1000, tol: float=1e-4) -> tuple:
+
+def l1_regularization_gradient_descent(
+ X: np.array,
+ y: np.array,
+ alpha: float = 0.1,
+ learning_rate: float = 0.01,
+ max_iter: int = 1000,
+ tol: float = 1e-4,
+) -> tuple:
n_samples, n_features = X.shape
# zero out weights and biases
weights = np.zeros(n_features)
@@ -19,27 +27,32 @@ def l1_regularization_gradient_descent(X:np.array, y:np.array, alpha: float=0.1,
return weights, bias
-def test_l1_regularization_gradient_descent():
- X = np.array([[0,0], [1, 1], [2, 2]])
+def test_l1_regularization_gradient_descent():
+ X = np.array([[0, 0], [1, 1], [2, 2]])
y = np.array([0, 1, 2])
alpha = 0.1
- l1_regularization_gradient_descent(X,y , alpha = 0.1, max_iter = 5000)
+ l1_regularization_gradient_descent(X, y, alpha=0.1, max_iter=5000)
expected_weights = np.array([0.425, 0.425])
expected_bias = 0.15
- weights, bias = l1_regularization_gradient_descent(X, y, alpha=alpha, learning_rate=0.01, max_iter=1000)
+ weights, bias = l1_regularization_gradient_descent(
+ X, y, alpha=alpha, learning_rate=0.01, max_iter=1000
+ )
assert np.allclose(weights, expected_weights, atol=0.01), "Test case 1 failed"
assert np.isclose(bias, expected_bias, atol=0.01), "Test case 1 failed"
-
- X = np.array([[0,1], [1,2], [2,3], [3,4], [4,5]])
+ X = np.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]])
y = np.array([1, 2, 3, 4, 5])
alpha = 0.1
expected_weights = np.array([0.27, 0.68])
- expected_bias = 0.4
- weights, bias = l1_regularization_gradient_descent(X, y, alpha=alpha, learning_rate=0.01, max_iter=1000)
+ expected_bias = 0.4
+ weights, bias = l1_regularization_gradient_descent(
+ X, y, alpha=alpha, learning_rate=0.01, max_iter=1000
+ )
assert np.allclose(weights, expected_weights, atol=0.01), "Test case 2 failed"
assert np.isclose(bias, expected_bias, atol=0.01), "Test case 2 failed"
+
+
if __name__ == "__main__":
test_l1_regularization_gradient_descent()
print("All l1_regularization tests passed.")
diff --git a/old_repo/Problems/51_OSA_distance/solution.py b/old_repo/Problems/51_OSA_distance/solution.py
index dd3f5ea3..7f00f3f0 100644
--- a/old_repo/Problems/51_OSA_distance/solution.py
+++ b/old_repo/Problems/51_OSA_distance/solution.py
@@ -1,42 +1,47 @@
def OSA(source: str, target: str) -> int:
source_len, target_len = len(source), len(target)
-
- osa_matrix = [[0]*(target_len + 1) for _ in range(source_len + 1)]
-
+
+ osa_matrix = [[0] * (target_len + 1) for _ in range(source_len + 1)]
+
for j in range(1, target_len + 1):
osa_matrix[0][j] = j
-
+
for i in range(1, source_len + 1):
osa_matrix[i][0] = i
-
+
for i in range(1, source_len + 1):
for j in range(1, target_len + 1):
osa_matrix[i][j] = min(
osa_matrix[i - 1][j] + 1,
osa_matrix[i][j - 1] + 1,
- osa_matrix[i - 1][j - 1] + (1 if source[i - 1] != target[j - 1] else 0)
+ osa_matrix[i - 1][j - 1] + (1 if source[i - 1] != target[j - 1] else 0),
)
- if i > 1 and j > 1 and source[i - 1] == target[j-2] and source[i-2] == target[j - 1]:
+ if (
+ i > 1
+ and j > 1
+ and source[i - 1] == target[j - 2]
+ and source[i - 2] == target[j - 1]
+ ):
osa_matrix[i][j] = min(osa_matrix[i][j], osa_matrix[i - 2][j - 2] + 1)
return osa_matrix[-1][-1]
-def test_OSA():
+def test_OSA():
input_string_pairs = [
- ("butterfly", "dragonfly"),
- ("london", "paris"),
- ("shower", "grower"),
- ("telescope", "microscope"),
- ("labyrinth", "puzzle"),
- ("silhouette", "shadow"),
- ("whisper", "screaming"),
- ("enigma", "mystery"),
- ("symphony", "cacophony"),
- ("mirage", "oasis"),
- ("asteroid", "meteorite"),
- ("palindrome", "palladium"),
- ("caper", "acer")
+ ("butterfly", "dragonfly"),
+ ("london", "paris"),
+ ("shower", "grower"),
+ ("telescope", "microscope"),
+ ("labyrinth", "puzzle"),
+ ("silhouette", "shadow"),
+ ("whisper", "screaming"),
+ ("enigma", "mystery"),
+ ("symphony", "cacophony"),
+ ("mirage", "oasis"),
+ ("asteroid", "meteorite"),
+ ("palindrome", "palladium"),
+ ("caper", "acer"),
]
expected_output = [6, 6, 2, 5, 9, 8, 9, 7, 4, 6, 5, 5, 2]
@@ -44,6 +49,7 @@ def test_OSA():
for (s1, s2), expected_distance in zip(input_string_pairs, expected_output):
assert OSA(s1, s2) == expected_distance
+
if __name__ == "__main__":
test_OSA()
print("All OSA distance tests passed")
diff --git a/old_repo/Problems/52_recall/solution.py b/old_repo/Problems/52_recall/solution.py
index 0a305ec7..1a079959 100644
--- a/old_repo/Problems/52_recall/solution.py
+++ b/old_repo/Problems/52_recall/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def recall(y_true, y_pred):
tp = np.sum((y_true == 1) & (y_pred == 1))
fn = np.sum((y_true == 1) & (y_pred == 0))
@@ -9,6 +10,7 @@ def recall(y_true, y_pred):
except ZeroDivisionError:
return 0.0
+
def test_recall():
# Test case 1
y_true = np.array([1, 0, 1, 1, 0, 1])
@@ -46,6 +48,7 @@ def test_recall():
expected_output = 0.667
assert recall(y_true, y_pred) == expected_output, "Test case 6 failed"
+
if __name__ == "__main__":
test_recall()
print("All recall tests passed.")
diff --git a/old_repo/Problems/53_self_attention/solution.py b/old_repo/Problems/53_self_attention/solution.py
index 48addfa3..420822f7 100644
--- a/old_repo/Problems/53_self_attention/solution.py
+++ b/old_repo/Problems/53_self_attention/solution.py
@@ -1,13 +1,14 @@
import numpy as np
+
def compute_qkv(X, W_q, W_k, W_v):
"""
Compute Q, K, V matrices from input X and weights.
-
+
Args:
X: numpy array of shape (seq_len, d_model), input sequence
W_q, W_k, W_v: numpy arrays of shape (d_model, d_model), weight matrices for Q, K, V
-
+
Returns:
Q, K, V: numpy arrays of shape (seq_len, d_model)
"""
@@ -16,67 +17,76 @@ def compute_qkv(X, W_q, W_k, W_v):
V = np.dot(X, W_v)
return Q, K, V
+
def self_attention(Q, K, V):
"""
Compute self-attention using the Q, K, V matrices.
-
+
Args:
Q, K, V: numpy arrays of shape (seq_len, d_model)
-
+
Returns:
attention_output: numpy array of shape (seq_len, d_model)
"""
d_k = Q.shape[1]
-
+
# Compute attention scores
scores = np.matmul(Q, K.T) / np.sqrt(d_k)
-
+
# Apply softmax to get attention weights
attention_weights = np.exp(scores) / np.sum(np.exp(scores), axis=1, keepdims=True)
-
+
# Compute attention output
attention_output = np.matmul(attention_weights, V)
return attention_output
+
def test_self_attention():
# Test case 1: Basic functionality with computed Q, K, V
X = np.array([[1, 0], [0, 1]])
W_q = np.array([[1, 0], [0, 1]])
W_k = np.array([[1, 0], [0, 1]])
W_v = np.array([[1, 2], [3, 4]])
-
+
Q, K, V = compute_qkv(X, W_q, W_k, W_v)
expected_output = np.array([[1.660477, 2.660477], [2.339523, 3.339523]])
actual_output = self_attention(Q, K, V)
- np.testing.assert_array_almost_equal(actual_output, expected_output, decimal=6,
- err_msg="Test case 1 failed")
+ np.testing.assert_array_almost_equal(
+ actual_output, expected_output, decimal=6, err_msg="Test case 1 failed"
+ )
# Test case 2: Different input X and weight matrices
X = np.array([[1, 1], [1, 0]])
W_q = np.array([[1, 0], [0, 1]])
W_k = np.array([[1, 0], [0, 1]])
W_v = np.array([[1, 2], [3, 4]])
-
+
Q, K, V = compute_qkv(X, W_q, W_k, W_v)
- expected_output = np.array([[3.00928465, 4.6790462 ],
- [2.5 , 4.]])
+ expected_output = np.array([[3.00928465, 4.6790462], [2.5, 4.0]])
actual_output = self_attention(Q, K, V)
- np.testing.assert_array_almost_equal(actual_output, expected_output, decimal=6,
- err_msg="Test case 2 failed")
+ np.testing.assert_array_almost_equal(
+ actual_output, expected_output, decimal=6, err_msg="Test case 2 failed"
+ )
# Test case 3: Larger input
X = np.array([[1, 0, 1], [0, 1, 1], [1, 1, 0]])
W_q = np.array([[1, 1, 0], [0, 1, 1], [1, 0, 1]])
W_k = np.array([[1, 1, 0], [0, 1, 1], [1, 0, 1]])
W_v = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
-
+
Q, K, V = compute_qkv(X, W_q, W_k, W_v)
- expected_output = np.array([[ 8.,10.,12. ],
- [ 8.61987385, 10.61987385, 12.61987385],
- [ 7.38012615 , 9.38012615, 11.38012615]])
+ expected_output = np.array(
+ [
+ [8.0, 10.0, 12.0],
+ [8.61987385, 10.61987385, 12.61987385],
+ [7.38012615, 9.38012615, 11.38012615],
+ ]
+ )
actual_output = self_attention(Q, K, V)
- np.testing.assert_array_almost_equal(actual_output, expected_output, decimal=6,
- err_msg="Test case 3 failed")
+ np.testing.assert_array_almost_equal(
+ actual_output, expected_output, decimal=6, err_msg="Test case 3 failed"
+ )
+
if __name__ == "__main__":
test_self_attention()
diff --git a/old_repo/Problems/54_RNN_layer/solution.py b/old_repo/Problems/54_RNN_layer/solution.py
index 6156f78d..faed0779 100644
--- a/old_repo/Problems/54_RNN_layer/solution.py
+++ b/old_repo/Problems/54_RNN_layer/solution.py
@@ -1,6 +1,13 @@
import numpy as np
-def rnn_forward(input_sequence: list[list[float]], initial_hidden_state: list[float], Wx: list[list[float]], Wh: list[list[float]], b: list[float]) -> list[float]:
+
+def rnn_forward(
+ input_sequence: list[list[float]],
+ initial_hidden_state: list[float],
+ Wx: list[list[float]],
+ Wh: list[list[float]],
+ b: list[float],
+) -> list[float]:
h = np.array(initial_hidden_state)
Wx = np.array(Wx)
Wh = np.array(Wh)
@@ -11,45 +18,44 @@ def rnn_forward(input_sequence: list[list[float]], initial_hidden_state: list[fl
final_hidden_state = h
return final_hidden_state
+
def test_rnn_forward():
# Test case 1: Single feature inputs
input_sequence_1 = [[1.0], [2.0], [3.0]]
initial_hidden_state_1 = [0.0]
Wx_1 = [[0.5]] # Input to hidden weights
Wh_1 = [[0.8]] # Hidden to hidden weights
- b_1 = [0.0] # Bias
+ b_1 = [0.0] # Bias
expected_output_1 = [0.97588162]
output_1 = rnn_forward(input_sequence_1, initial_hidden_state_1, Wx_1, Wh_1, b_1)
- assert np.allclose(output_1, expected_output_1, atol=0.01), f"Test case 1 failed: expected {expected_output_1}, got {output_1}"
+ assert np.allclose(output_1, expected_output_1, atol=0.01), (
+ f"Test case 1 failed: expected {expected_output_1}, got {output_1}"
+ )
# Test case 2: Single feature inputs with different weights and bias
input_sequence_2 = [[0.5], [0.1], [-0.2]]
initial_hidden_state_2 = [0.0]
Wx_2 = [[1.0]] # Input to hidden weights
- Wh_2 = [[0.5]] # Hidden to hidden weights
- b_2 = [0.1] # Bias
+ Wh_2 = [[0.5]] # Hidden to hidden weights
+ b_2 = [0.1] # Bias
expected_output_2 = [0.118]
output_2 = rnn_forward(input_sequence_2, initial_hidden_state_2, Wx_2, Wh_2, b_2)
- assert np.allclose(output_2, expected_output_2, atol=0.01), f"Test case 2 failed: expected {expected_output_2}, got {output_2}"
+ assert np.allclose(output_2, expected_output_2, atol=0.01), (
+ f"Test case 2 failed: expected {expected_output_2}, got {output_2}"
+ )
# Test case 3: Multiple feature inputs
- input_sequence_3 = [
- [0.1, 0.2, 0.3],
- [0.4, 0.5, 0.6]
- ]
+ input_sequence_3 = [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]
initial_hidden_state_3 = [0.0, 0.0]
- Wx_3 = [
- [0.1, 0.2, 0.3],
- [0.4, 0.5, 0.6]
- ] # Input to hidden weights
- Wh_3 = [
- [0.7, 0.8],
- [0.9, 1.0]
- ] # Hidden to hidden weights
+ Wx_3 = [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]] # Input to hidden weights
+ Wh_3 = [[0.7, 0.8], [0.9, 1.0]] # Hidden to hidden weights
b_3 = [0.1, 0.2] # Bias
expected_output_3 = [0.7474, 0.9302]
output_3 = rnn_forward(input_sequence_3, initial_hidden_state_3, Wx_3, Wh_3, b_3)
- assert np.allclose(output_3, expected_output_3, atol=0.01), f"Test case 3 failed: expected {expected_output_3}, got {output_3}"
+ assert np.allclose(output_3, expected_output_3, atol=0.01), (
+ f"Test case 3 failed: expected {expected_output_3}, got {output_3}"
+ )
+
if __name__ == "__main__":
test_rnn_forward()
diff --git a/old_repo/Problems/55_2D_translation_matrix/solution.py b/old_repo/Problems/55_2D_translation_matrix/solution.py
index 20103f1a..3678ec9f 100644
--- a/old_repo/Problems/55_2D_translation_matrix/solution.py
+++ b/old_repo/Problems/55_2D_translation_matrix/solution.py
@@ -1,48 +1,53 @@
import numpy as np
-def translate_object(points: list[list[float]], tx: float, ty: float) -> list[list[float]]:
+
+def translate_object(
+ points: list[list[float]], tx: float, ty: float
+) -> list[list[float]]:
"""
Translate a set of 2D points by tx and ty.
-
+
:param points: List of [x, y] coordinates representing the object
:param tx: Translation in x-direction
:param ty: Translation in y-direction
:return: List of translated [x, y] coordinates
"""
-
+
# Translation matrix
- translation_matrix = np.array([
- [1, 0, tx],
- [0, 1, ty],
- [0, 0, 1]
- ])
-
+ translation_matrix = np.array([[1, 0, tx], [0, 1, ty], [0, 0, 1]])
+
# Convert points to homogeneous coordinates
homogeneous_points = np.hstack([np.array(points), np.ones((len(points), 1))])
-
+
# Translation
translated_points = np.dot(homogeneous_points, translation_matrix.T)
-
+
# Convert back to 2D coordinates and to list
return translated_points[:, :2].tolist()
+
def test_translate_object() -> None:
# Test cases for translate_object function
-
+
# Test case 1 (triangle)
triangle = [[0, 0], [1, 0], [0.5, 1]]
tx, ty = 2, 3
translated_triangle = translate_object(triangle, tx, ty)
expected_result = [[2.0, 3.0], [3.0, 3.0], [2.5, 4.0]]
- assert translated_triangle == expected_result, f"Expected {expected_result}, but got {translated_triangle}"
-
+ assert translated_triangle == expected_result, (
+ f"Expected {expected_result}, but got {translated_triangle}"
+ )
+
# Test case 2 (square)
square = [[0, 0], [1, 0], [1, 1], [0, 1]]
tx, ty = -1, 2
translated_square = translate_object(square, tx, ty)
expected_result = [[-1.0, 2.0], [0.0, 2.0], [0.0, 3.0], [-1.0, 3.0]]
- assert translated_square == expected_result, f"Expected {expected_result}, but got {translated_square}"
+ assert translated_square == expected_result, (
+ f"Expected {expected_result}, but got {translated_square}"
+ )
+
if __name__ == "__main__":
test_translate_object()
- print("All tests passed.")
\ No newline at end of file
+ print("All tests passed.")
diff --git a/old_repo/Problems/57_gauss_seidel/solution.py b/old_repo/Problems/57_gauss_seidel/solution.py
index 7299211e..b11f8a14 100644
--- a/old_repo/Problems/57_gauss_seidel/solution.py
+++ b/old_repo/Problems/57_gauss_seidel/solution.py
@@ -1,57 +1,61 @@
import numpy as np
-def gauss_seidel_it(A:np.array, b:np.array, x: np.array) -> np.array:
-
+
+def gauss_seidel_it(A: np.array, b: np.array, x: np.array) -> np.array:
rows, cols = A.shape
-
+
for i in range(rows):
x_new = b[i]
for j in range(cols):
if i != j:
- x_new -= A[i,j] * x[j]
- x[i] = x_new/A[i,i]
-
+ x_new -= A[i, j] * x[j]
+ x[i] = x_new / A[i, i]
+
return x
-def gauss_seidel(A:np.array, b:np.array, n: int, x_ini: np.array=None) -> np.array:
-
+
+def gauss_seidel(A: np.array, b: np.array, n: int, x_ini: np.array = None) -> np.array:
x = x_ini or np.zeros_like(b)
-
+
for _ in range(n):
- x = gauss_seidel_it(A,b,x)
-
+ x = gauss_seidel_it(A, b, x)
+
return x
+
def test_gauss_seidel():
-
# Test case 1: basic test
- A_1 = np.array([[4, 1, 2],[3, 5, 1],[1, 1, 3]], dtype=float)
- b_1 = np.array([4,7,3], dtype=float)
+ A_1 = np.array([[4, 1, 2], [3, 5, 1], [1, 1, 3]], dtype=float)
+ b_1 = np.array([4, 7, 3], dtype=float)
n = 5
expected_1 = np.array([0.5008, 0.99968, 0.49984])
output_1 = gauss_seidel(A_1, b_1, n)
- assert np.allclose(output_1, expected_1, atol=0.01), f"Test case 1 failed: expected {expected_1}, got {output_1}"
+ assert np.allclose(output_1, expected_1, atol=0.01), (
+ f"Test case 1 failed: expected {expected_1}, got {output_1}"
+ )
# Test case 2: testing a zero pivot
- A_2 = np.array([[4, -1, 0, 1],
- [-1, 4, -1, 0],
- [0, -1, 4, -1],
- [1, 0, -1, 4]], dtype=float)
+ A_2 = np.array(
+ [[4, -1, 0, 1], [-1, 4, -1, 0], [0, -1, 4, -1], [1, 0, -1, 4]], dtype=float
+ )
b_2 = np.array([15, 10, 10, 15], dtype=float)
n = 1
expected_2 = np.array([3.75, 3.4375, 3.359375, 3.65234375])
output_2 = gauss_seidel(A_2, b_2, n)
- assert np.allclose(output_2, expected_2, atol=0.01), f"Test case 2 failed: expected {expected_2}, got {output_2}"
+ assert np.allclose(output_2, expected_2, atol=0.01), (
+ f"Test case 2 failed: expected {expected_2}, got {output_2}"
+ )
# Test case 3: Multiple feature inputs
- A_3 = np.array([[10, -1, 2],
- [-1, 11, -1],
- [2, -1, 10]], dtype=float)
+ A_3 = np.array([[10, -1, 2], [-1, 11, -1], [2, -1, 10]], dtype=float)
b_3 = np.array([6, 25, -11], dtype=float)
n = 100
expected_3 = np.array([1.04326923, 2.26923077, -1.08173077])
output_3 = gauss_seidel(A_3, b_3, n)
- assert np.allclose(output_3, expected_3, atol=0.01), f"Test case 3 failed: expected {expected_3}, got {output_3}"
+ assert np.allclose(output_3, expected_3, atol=0.01), (
+ f"Test case 3 failed: expected {expected_3}, got {output_3}"
+ )
+
if __name__ == "__main__":
test_gauss_seidel()
diff --git a/old_repo/Problems/58_gaussian_elimination_partial_pivoting/solution.py b/old_repo/Problems/58_gaussian_elimination_partial_pivoting/solution.py
index a233e944..3e055bf5 100644
--- a/old_repo/Problems/58_gaussian_elimination_partial_pivoting/solution.py
+++ b/old_repo/Problems/58_gaussian_elimination_partial_pivoting/solution.py
@@ -1,76 +1,97 @@
import numpy as np
+
def partial_pivoting(A_aug: np.array, row_num: int, col_num: int) -> np.array:
-
rows, cols = A_aug.shape
-
+
max_row = row_num
- max_val = abs(A_aug[row_num,col_num])
-
+ max_val = abs(A_aug[row_num, col_num])
+
for i in range(row_num, rows):
current_val = abs(A_aug[i, col_num])
if current_val > max_val:
max_val = current_val
max_row = i
-
+
if max_row != row_num:
A_aug[[row_num, max_row]] = A_aug[[max_row, row_num]]
-
+
return A_aug
+
def gaussian_elimination(A: np.array, b: np.array) -> np.array:
-
# get original matrix dimensions to avoid overwriting source later in augmented matrix
rows, cols = A.shape
-
+
# create augmented matrix
- A_aug = np.hstack((A,b.reshape(-1,1)))
-
+ A_aug = np.hstack((A, b.reshape(-1, 1)))
+
# Elimination
# loop over rows
- for i in range(rows-1):
+ for i in range(rows - 1):
A_aug = partial_pivoting(A_aug, i, i)
# apply elimination to all rows below the current row
- for j in range(i+1, rows):
- A_aug[j, i:] -= (A_aug[j,i] / A_aug[i,i]) * A_aug[i, i:]
+ for j in range(i + 1, rows):
+ A_aug[j, i:] -= (A_aug[j, i] / A_aug[i, i]) * A_aug[i, i:]
x = np.zeros_like(b, dtype=float)
-
+
# Backsubtitution
- for i in range(rows-1,-1,-1):
- x[i] = (A_aug[i,-1] - np.dot(A_aug[i,i+1:cols],x[i+1:]))/A_aug[i,i]
-
+ for i in range(rows - 1, -1, -1):
+ x[i] = (A_aug[i, -1] - np.dot(A_aug[i, i + 1 : cols], x[i + 1 :])) / A_aug[i, i]
+
return x
+
def test_gaussian_elimination():
# Test case 1: basic test
- A_1 = np.array([[2,8,4],[2,5,1],[4,10,-1]], dtype=float)
- b_1 = np.array([2,5,1], dtype=float)
- expected_1 = np.array([11., -4., 3.])
+ A_1 = np.array([[2, 8, 4], [2, 5, 1], [4, 10, -1]], dtype=float)
+ b_1 = np.array([2, 5, 1], dtype=float)
+ expected_1 = np.array([11.0, -4.0, 3.0])
output_1 = gaussian_elimination(A_1, b_1)
- assert np.allclose(output_1, expected_1, atol=0.01), f"Test case 1 failed: expected {expected_1}, got {output_1}"
+ assert np.allclose(output_1, expected_1, atol=0.01), (
+ f"Test case 1 failed: expected {expected_1}, got {output_1}"
+ )
# Test case 2: testing a zero pivot
- A_2 = np.array([
- [0, 2, 1, 0, 0, 0, 0],
- [2, 6, 2, 1, 0, 0, 0],
- [1, 2, 7, 2, 1, 0, 0],
- [0, 1, 2, 8, 2, 1, 0],
- [0, 0, 1, 2, 9, 2, 1],
- [0, 0, 0, 1, 2, 10, 2],
- [0, 0, 0, 0, 1, 2, 11]
- ], dtype=float)
+ A_2 = np.array(
+ [
+ [0, 2, 1, 0, 0, 0, 0],
+ [2, 6, 2, 1, 0, 0, 0],
+ [1, 2, 7, 2, 1, 0, 0],
+ [0, 1, 2, 8, 2, 1, 0],
+ [0, 0, 1, 2, 9, 2, 1],
+ [0, 0, 0, 1, 2, 10, 2],
+ [0, 0, 0, 0, 1, 2, 11],
+ ],
+ dtype=float,
+ )
b_2 = np.array([1, 2, 3, 4, 5, 6, 7], dtype=float)
- expected_2 = np.array([-0.4894027, 0.36169985, 0.2766003, 0.25540569, 0.31898951, 0.40387497, 0.53393278])
+ expected_2 = np.array(
+ [
+ -0.4894027,
+ 0.36169985,
+ 0.2766003,
+ 0.25540569,
+ 0.31898951,
+ 0.40387497,
+ 0.53393278,
+ ]
+ )
output_2 = gaussian_elimination(A_2, b_2)
- assert np.allclose(output_2, expected_2, atol=0.01), f"Test case 2 failed: expected {expected_2}, got {output_2}"
+ assert np.allclose(output_2, expected_2, atol=0.01), (
+ f"Test case 2 failed: expected {expected_2}, got {output_2}"
+ )
# Test case 3: Multiple feature inputs
A_3 = np.array([[2, 1, -1], [-3, -1, 2], [-2, 1, 2]], dtype=float)
b_3 = np.array([8, -11, -3], dtype=float)
- expected_3 = np.array([2., 3., -1.])
+ expected_3 = np.array([2.0, 3.0, -1.0])
output_3 = gaussian_elimination(A_3, b_3)
- assert np.allclose(output_3, expected_3, atol=0.01), f"Test case 3 failed: expected {expected_3}, got {output_3}"
+ assert np.allclose(output_3, expected_3, atol=0.01), (
+ f"Test case 3 failed: expected {expected_3}, got {output_3}"
+ )
+
if __name__ == "__main__":
test_gaussian_elimination()
diff --git a/old_repo/Problems/5_scalar_multiplication_of_a_matrix/solution.py b/old_repo/Problems/5_scalar_multiplication_of_a_matrix/solution.py
index efb4b4ba..64bdba66 100644
--- a/old_repo/Problems/5_scalar_multiplication_of_a_matrix/solution.py
+++ b/old_repo/Problems/5_scalar_multiplication_of_a_matrix/solution.py
@@ -5,6 +5,7 @@ def scalar_multiply(
# Multiply each element by the scalar
return [[element * scalar for element in row] for row in matrix]
+
def test_scalar_multiply() -> None:
# Test cases for scalar_multiply function
@@ -18,6 +19,7 @@ def test_scalar_multiply() -> None:
scalar = -1
assert scalar_multiply(matrix, scalar) == [[0, 1], [-1, 0]]
+
if __name__ == "__main__":
test_scalar_multiply()
- print("All scalar_multiply tests passed.")
\ No newline at end of file
+ print("All scalar_multiply tests passed.")
diff --git a/old_repo/Problems/60_TF-IDF/solution.py b/old_repo/Problems/60_TF-IDF/solution.py
index 497f78ce..789c5a1f 100644
--- a/old_repo/Problems/60_TF-IDF/solution.py
+++ b/old_repo/Problems/60_TF-IDF/solution.py
@@ -1,10 +1,11 @@
import numpy as np
+
def compute_tf_idf(corpus, query):
"""
Compute TF-IDF scores for a query against a corpus of documents using only NumPy.
The output TF-IDF scores retain five decimal places.
-
+
:param corpus: List of documents, where each document is a list of words
:param query: List of words in the query
:return: List of lists containing TF-IDF scores for the query words in each document,
@@ -13,10 +14,10 @@ def compute_tf_idf(corpus, query):
# Build the vocabulary from the corpus and include query terms
vocab = sorted(set(word for document in corpus for word in document).union(query))
word_to_index = {word: idx for idx, word in enumerate(vocab)}
-
+
# Initialize term-frequency (TF) matrix
tf = np.zeros((len(corpus), len(vocab)))
-
+
# Compute term frequencies
for doc_idx, document in enumerate(corpus):
for word in document:
@@ -24,69 +25,76 @@ def compute_tf_idf(corpus, query):
tf[doc_idx, word_idx] += 1
# Normalize TF values by the document length
tf[doc_idx, :] /= len(document)
-
+
# Compute document frequency (DF) for each term
df = np.count_nonzero(tf > 0, axis=0)
-
+
# Compute inverse document frequency (IDF) with smoothing
num_docs = len(corpus)
- idf = np.log((num_docs + 1) / (df + 1)) + 1 # Add 1 to numerator and denominator to prevent division by zero
-
+ idf = (
+ np.log((num_docs + 1) / (df + 1)) + 1
+ ) # Add 1 to numerator and denominator to prevent division by zero
+
# Compute TF-IDF matrix
tf_idf = tf * idf
-
+
# Extract TF-IDF scores for the query words
query_indices = [word_to_index[word] for word in query]
tf_idf_scores = tf_idf[:, query_indices]
-
+
# Round the TF-IDF scores to five decimal places
tf_idf_scores = np.round(tf_idf_scores, 5)
-
+
# Convert the TF-IDF scores to a list of lists
tf_idf_scores_list = tf_idf_scores.tolist()
-
+
return tf_idf_scores_list
+
def test_tf_idf():
# Test case 1: Simple corpus with single-word query
corpus_1 = [
["the", "cat", "sat", "on", "the", "mat"],
["the", "dog", "chased", "the", "cat"],
- ["the", "bird", "flew", "over", "the", "mat"]
+ ["the", "bird", "flew", "over", "the", "mat"],
]
query_1 = ["cat"]
expected_output_1 = [[0.21461], [0.25754], [0.0]]
output_1 = compute_tf_idf(corpus_1, query_1)
- assert np.allclose(output_1, expected_output_1, atol=1e-5), \
+ assert np.allclose(output_1, expected_output_1, atol=1e-5), (
f"Test case 1 failed: expected {expected_output_1}, got {output_1}"
-
+ )
+
# Test case 2: Simple corpus with multi-word query
corpus_2 = corpus_1 # Reuse the corpus from test case 1
query_2 = ["cat", "mat"]
expected_output_2 = [[0.21461, 0.21461], [0.25754, 0.0], [0.0, 0.21461]]
output_2 = compute_tf_idf(corpus_2, query_2)
- assert np.allclose(output_2, expected_output_2, atol=1e-5), \
+ assert np.allclose(output_2, expected_output_2, atol=1e-5), (
f"Test case 2 failed: expected {expected_output_2}, got {output_2}"
-
+ )
+
# Test case 3: Larger corpus with multi-word query
corpus_3 = [
["this", "is", "a", "sample"],
["this", "is", "another", "example"],
["yet", "another", "sample", "document"],
- ["one", "more", "document", "for", "testing"]
+ ["one", "more", "document", "for", "testing"],
]
query_3 = ["sample", "document", "test"]
expected_output_3 = [
[0.37771, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.37771, 0.37771, 0.0],
- [0.0, 0.30217, 0.0]
+ [0.0, 0.30217, 0.0],
]
output_3 = compute_tf_idf(corpus_3, query_3)
- assert np.allclose(output_3, expected_output_3, atol=1e-5), \
+ assert np.allclose(output_3, expected_output_3, atol=1e-5), (
f"Test case 3 failed: expected {expected_output_3}, got {output_3}"
-
+ )
+
print("All TF-IDF tests passed.")
+
if __name__ == "__main__":
test_tf_idf()
diff --git a/old_repo/Problems/61_f_score/solution.py b/old_repo/Problems/61_f_score/solution.py
index 030b0b08..931afec7 100644
--- a/old_repo/Problems/61_f_score/solution.py
+++ b/old_repo/Problems/61_f_score/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def f_score(y_true, y_pred, beta):
tp = np.sum((y_true == 1) & (y_pred == 1))
fn = np.sum((y_true == 1) & (y_pred == 0))
@@ -14,9 +15,10 @@ def f_score(y_true, y_pred, beta):
if div == 0 or op == 0:
return 0
- score = op/div * (1 + (beta ** 2))
+ score = op / div * (1 + (beta**2))
return round(score, 3)
+
def test_f_score():
# Test case 1
y_true = np.array([1, 0, 1, 1, 0, 1])
@@ -74,6 +76,7 @@ def test_f_score():
expected_output = 0.667
assert f_score(y_true, y_pred, beta) == expected_output, "Test case 8 failed"
+
if __name__ == "__main__":
test_f_score()
print("All F-score tests passed.")
diff --git a/old_repo/Problems/63_conjugate_gradient/solution.py b/old_repo/Problems/63_conjugate_gradient/solution.py
index ee60ffad..656d68c6 100644
--- a/old_repo/Problems/63_conjugate_gradient/solution.py
+++ b/old_repo/Problems/63_conjugate_gradient/solution.py
@@ -1,22 +1,23 @@
import numpy as np
-def conjugate_gradient(A: np.array, b: np.array, n: int, x0: np.array=None, tol=1e-8) -> np.array:
-
+
+def conjugate_gradient(
+ A: np.array, b: np.array, n: int, x0: np.array = None, tol=1e-8
+) -> np.array:
# calculate initial residual vector
x = np.zeros_like(b)
- r = residual(A, b, x) # residual vector
+ r = residual(A, b, x) # residual vector
rPlus1 = r
- p = r # search direction vector
+ p = r # search direction vector
for i in range(n):
-
# line search step value - this minimizes the error along the current search direction
alp = alpha(A, r, p)
# new x and r based on current p (the search direction vector)
x = x + alp * p
- rPlus1 = r - alp * (A@p)
-
+ rPlus1 = r - alp * (A @ p)
+
# calculate beta - this ensures that all vectors are A-orthogonal to each other
bet = beta(r, rPlus1)
@@ -28,64 +29,72 @@ def conjugate_gradient(A: np.array, b: np.array, n: int, x0: np.array=None, tol=
r = rPlus1
# break if less than tolerance
- if np.linalg.norm(residual(A,b,x)) < tol:
+ if np.linalg.norm(residual(A, b, x)) < tol:
break
return x
+
def residual(A: np.array, b: np.array, x: np.array) -> np.array:
# calculate linear system residuals
return b - A @ x
-def alpha(A: np.array, r: np.array, p: np.array) -> float:
+def alpha(A: np.array, r: np.array, p: np.array) -> float:
# calculate step size
alpha_num = np.dot(r, r)
alpha_den = np.dot(p @ A, p)
- return alpha_num/alpha_den
+ return alpha_num / alpha_den
+
def beta(r: np.array, r_plus1: np.array) -> float:
-
# calculate direction scaling
beta_num = np.dot(r_plus1, r_plus1)
beta_den = np.dot(r, r)
- return beta_num/beta_den
+ return beta_num / beta_den
-def test_conjugate_gradient() -> None:
- A_1 = A_1 = np.array([[4, 1],
- [1, 3]])
+def test_conjugate_gradient() -> None:
+ A_1 = A_1 = np.array([[4, 1], [1, 3]])
b_1 = np.array([1, 2])
n = 5
expected_1 = np.array([0.09090909, 0.63636364])
output_1 = conjugate_gradient(A_1, b_1, n)
- assert np.allclose(output_1, expected_1, atol=0.01), f"Test case 1 failed: expected {expected_1}, got {output_1}"
+ assert np.allclose(output_1, expected_1, atol=0.01), (
+ f"Test case 1 failed: expected {expected_1}, got {output_1}"
+ )
- A_2 = np.array([[4, 1, 2],
- [1, 3, 0],
- [2, 0, 5]])
+ A_2 = np.array([[4, 1, 2], [1, 3, 0], [2, 0, 5]])
b_2 = np.array([7, 8, 5])
n = 1
expected_2 = np.array([1.2627451, 1.44313725, 0.90196078])
output_2 = conjugate_gradient(A_2, b_2, n)
- assert np.allclose(output_2, expected_2, atol=0.01), f"Test case 2 failed: expected {expected_2}, got {output_2}"
+ assert np.allclose(output_2, expected_2, atol=0.01), (
+ f"Test case 2 failed: expected {expected_2}, got {output_2}"
+ )
# 5x5 positive definite
- A_3 = np.array([[6, 2, 1, 1, 0],
- [2, 5, 2, 1, 1],
- [1, 2, 6, 1, 2],
- [1, 1, 1, 7, 1],
- [0, 1, 2, 1, 8]])
+ A_3 = np.array(
+ [
+ [6, 2, 1, 1, 0],
+ [2, 5, 2, 1, 1],
+ [1, 2, 6, 1, 2],
+ [1, 1, 1, 7, 1],
+ [0, 1, 2, 1, 8],
+ ]
+ )
b_3 = np.array([1, 2, 3, 4, 5])
n = 100
expected_3 = np.array([0.01666667, 0.11666667, 0.21666667, 0.45, 0.5])
output_3 = conjugate_gradient(A_3, b_3, n)
- assert np.allclose(output_3, expected_3, atol=0.01), f"Test case 3 failed: expected {expected_3}, got {output_3}"
+ assert np.allclose(output_3, expected_3, atol=0.01), (
+ f"Test case 3 failed: expected {expected_3}, got {output_3}"
+ )
if __name__ == "__main__":
test_conjugate_gradient()
- print("All Conjugate Gradient tests passed.")
\ No newline at end of file
+ print("All Conjugate Gradient tests passed.")
diff --git a/old_repo/Problems/64_gini_impurity/solution.py b/old_repo/Problems/64_gini_impurity/solution.py
index 1bac5ade..1bc76bfe 100644
--- a/old_repo/Problems/64_gini_impurity/solution.py
+++ b/old_repo/Problems/64_gini_impurity/solution.py
@@ -1,29 +1,29 @@
import numpy as np
-def gini_impurity(y: list[int]) -> float:
+def gini_impurity(y: list[int]) -> float:
classes = set(y)
n = len(y)
gini_impurity = 0
for cls in classes:
- gini_impurity += (y.count(cls)/n)**2
+ gini_impurity += (y.count(cls) / n) ** 2
- return np.round(1-gini_impurity,3)
+ return np.round(1 - gini_impurity, 3)
def test_gini_impurity() -> None:
-
- classes_1 = [0,0,0,0,1,1,1,1]
+ classes_1 = [0, 0, 0, 0, 1, 1, 1, 1]
assert gini_impurity(classes_1) == 0.5
- classes_2 = [0,0,0,0,0,1]
+ classes_2 = [0, 0, 0, 0, 0, 1]
assert gini_impurity(classes_2) == 0.278
- classes_3 = [0,1,2,2,2,1,2]
+ classes_3 = [0, 1, 2, 2, 2, 1, 2]
assert gini_impurity(classes_3) == 0.571
+
if __name__ == "__main__":
test_gini_impurity()
print("All Gini Impurity tests passed.")
diff --git a/old_repo/Problems/65_compressed_row_sparse_matrix/solution.py b/old_repo/Problems/65_compressed_row_sparse_matrix/solution.py
index 45624436..f2cefbfe 100644
--- a/old_repo/Problems/65_compressed_row_sparse_matrix/solution.py
+++ b/old_repo/Problems/65_compressed_row_sparse_matrix/solution.py
@@ -1,8 +1,6 @@
-import numpy as np
-from scipy.sparse import csr_matrix
-
-def compressed_row_sparse_matrix(dense_matrix: list[list[float]]) -> tuple[list[float], list[int], list[int]]:
-
+def compressed_row_sparse_matrix(
+ dense_matrix: list[list[float]],
+) -> tuple[list[float], list[int], list[int]]:
vals = []
col_idx = []
row_ptr = [0]
@@ -13,35 +11,26 @@ def compressed_row_sparse_matrix(dense_matrix: list[list[float]]) -> tuple[list[
continue
vals.append(val)
col_idx.append(j)
- row_ptr.append(len(vals))
+ row_ptr.append(len(vals))
return vals, col_idx, row_ptr
-
-def test_compressed_row():
+def test_compressed_row():
# Test case 1
- dense_matrix = [
- [0, 0, 0],
- [0, 0, 0],
- [0, 0, 0]
- ]
+ dense_matrix = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
vals, col_idx, row_ptr = compressed_row_sparse_matrix(dense_matrix)
-
+
assert vals == [], "Test case 1 failed: vals should be an empty list"
assert col_idx == [], "Test case 1 failed: col_idx should be an empty list"
assert row_ptr == [0, 0, 0, 0], "Test case 1 failed: row_ptr should be [0, 0, 0, 0]"
# Test case 2
- dense_matrix = [
- [0, 0, 0],
- [1, 2, 0],
- [0, 3, 4]
- ]
+ dense_matrix = [[0, 0, 0], [1, 2, 0], [0, 3, 4]]
vals, col_idx, row_ptr = compressed_row_sparse_matrix(dense_matrix)
-
+
assert vals == [1, 2, 3, 4], "Test case 2 failed: vals should be [1, 2, 3, 4]"
assert col_idx == [0, 1, 1, 2], "Test case 2 failed: col_idx should be [0, 1, 1, 2]"
assert row_ptr == [0, 0, 2, 4], "Test case 2 failed: row_ptr should be [0, 0, 2, 4]"
@@ -52,14 +41,21 @@ def test_compressed_row():
[0, 4, 0, 0, 0], # One non-zero element
[5, 0, 0, 6, 0], # Two non-zero elements
[0, 0, 0, 0, 0], # All zeros
- [0, 7, 0, 0, 8] # Two non-zero elements
+ [0, 7, 0, 0, 8], # Two non-zero elements
]
vals, col_idx, row_ptr = compressed_row_sparse_matrix(dense_matrix)
- assert vals == [3, 4, 5, 6, 7, 8], "Test case failed: vals should be [3, 4, 5, 6, 7, 8]"
- assert col_idx == [2, 1, 0, 3, 1, 4], "Test case failed: col_idx should be [2, 1, 0, 3, 1, 4]"
- assert row_ptr == [0, 1, 2, 4, 4, 6], "Test case failed: row_ptr should be [0, 1, 2, 4, 4, 6]"
+ assert vals == [3, 4, 5, 6, 7, 8], (
+ "Test case failed: vals should be [3, 4, 5, 6, 7, 8]"
+ )
+ assert col_idx == [2, 1, 0, 3, 1, 4], (
+ "Test case failed: col_idx should be [2, 1, 0, 3, 1, 4]"
+ )
+ assert row_ptr == [0, 1, 2, 4, 4, 6], (
+ "Test case failed: row_ptr should be [0, 1, 2, 4, 4, 6]"
+ )
+
if __name__ == "__main__":
test_compressed_row()
diff --git a/old_repo/Problems/66_orthogonal_projection/solution.py b/old_repo/Problems/66_orthogonal_projection/solution.py
index 76913bf5..e15bc03a 100644
--- a/old_repo/Problems/66_orthogonal_projection/solution.py
+++ b/old_repo/Problems/66_orthogonal_projection/solution.py
@@ -1,45 +1,51 @@
-def dot(v1:list[float], v2:list[float]) -> float:
-
+def dot(v1: list[float], v2: list[float]) -> float:
if len(v1) != len(v2):
raise Exception("Vectors are not of the same dimensions.")
-
- return sum([ax1*ax2 for ax1,ax2 in zip(v1,v2)])
-def scalar_mult(scalar:float, v:list[float]) -> list[float]:
+ return sum([ax1 * ax2 for ax1, ax2 in zip(v1, v2)])
+
+def scalar_mult(scalar: float, v: list[float]) -> list[float]:
+ return [scalar * ax for ax in v]
- return [scalar*ax for ax in v]
-def orthogonal_projection(v:list[float], L: list[float]) -> list[list[float]]:
-
+def orthogonal_projection(v: list[float], L: list[float]) -> list[list[float]]:
# calculate the orthogonal projection of v onto L
# calculate the unit vector of L
- L_mag = sum([ax**2 for ax in L])**0.5
- u = [ax/L_mag for ax in L]
+ L_mag = sum([ax**2 for ax in L]) ** 0.5
+ u = [ax / L_mag for ax in L]
# calculate orthogonal projection
proj_v = scalar_mult(dot(v, u), u)
return proj_v
+
def test_orthogonal_projection() -> None:
# Test case 1: 2D vectors
v1 = [3, 4]
L1 = [1, 0]
expected_proj1 = [3, 0] # Projection of v1 onto L1 should lie along the x-axis
- assert orthogonal_projection(v1, L1) == expected_proj1, f"Test case 1 failed: {orthogonal_projection(v1, L1)} != {expected_proj1}"
+ assert orthogonal_projection(v1, L1) == expected_proj1, (
+ f"Test case 1 failed: {orthogonal_projection(v1, L1)} != {expected_proj1}"
+ )
# Test case 2: 3D vectors
v2 = [1, 2, 3]
L2 = [0, 0, 1]
expected_proj2 = [0, 0, 3] # Projection of v2 onto L2 should be along the z-axis
- assert orthogonal_projection(v2, L2) == expected_proj2, f"Test case 2 failed: {orthogonal_projection(v2, L2)} != {expected_proj2}"
+ assert orthogonal_projection(v2, L2) == expected_proj2, (
+ f"Test case 2 failed: {orthogonal_projection(v2, L2)} != {expected_proj2}"
+ )
# Test case 3: Arbitrary 3D vectors
v3 = [5, 6, 7]
L3 = [2, 0, 0] # Projection should align with the x-axis
expected_proj3 = [5, 0, 0]
- assert orthogonal_projection(v3, L3) == expected_proj3, f"Test case 3 failed: {orthogonal_projection(v3, L3)} != {expected_proj3}"
+ assert orthogonal_projection(v3, L3) == expected_proj3, (
+ f"Test case 3 failed: {orthogonal_projection(v3, L3)} != {expected_proj3}"
+ )
+
if __name__ == "__main__":
test_orthogonal_projection()
diff --git a/old_repo/Problems/67_compressed_column_sparse_matrix/solution.py b/old_repo/Problems/67_compressed_column_sparse_matrix/solution.py
index e6fa6eab..805ffacb 100644
--- a/old_repo/Problems/67_compressed_column_sparse_matrix/solution.py
+++ b/old_repo/Problems/67_compressed_column_sparse_matrix/solution.py
@@ -1,8 +1,6 @@
-import numpy as np
-from scipy.sparse import csc_matrix
-
-def compressed_col_sparse_matrix(dense_matrix: list[list[float]]) -> tuple[list[float], list[int], list[int]]:
-
+def compressed_col_sparse_matrix(
+ dense_matrix: list[list[float]],
+) -> tuple[list[float], list[int], list[int]]:
vals = []
row_idx = []
col_ptr = [0]
@@ -16,35 +14,26 @@ def compressed_col_sparse_matrix(dense_matrix: list[list[float]]) -> tuple[list[
continue
vals.append(val)
row_idx.append(j)
- col_ptr.append(len(vals))
+ col_ptr.append(len(vals))
return vals, row_idx, col_ptr
-
-def test_compressed_col():
+def test_compressed_col():
# Test case 1
- dense_matrix = [
- [0, 0, 0],
- [0, 0, 0],
- [0, 0, 0]
- ]
+ dense_matrix = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
vals, row_idx, col_ptr = compressed_col_sparse_matrix(dense_matrix)
-
+
assert vals == [], "Test case 1 failed: vals should be an empty list"
assert row_idx == [], "Test case 1 failed: row_idx should be an empty list"
assert col_ptr == [0, 0, 0, 0], "Test case 1 failed: col_ptr should be [0, 0, 0, 0]"
# Test case 2
- dense_matrix = [
- [0, 0, 0],
- [1, 2, 0],
- [0, 3, 4]
- ]
+ dense_matrix = [[0, 0, 0], [1, 2, 0], [0, 3, 4]]
vals, row_idx, col_ptr = compressed_col_sparse_matrix(dense_matrix)
-
+
assert vals == [1, 2, 3, 4], "Test case 2 failed: vals should be [1, 2, 3, 4]"
assert row_idx == [1, 1, 2, 2], "Test case 2 failed: row_idx should be [1, 1, 2, 2]"
assert col_ptr == [0, 1, 3, 4], "Test case 2 failed: col_ptr should be [0, 1, 3, 4]"
@@ -52,17 +41,24 @@ def test_compressed_col():
# Test case 3
dense_matrix = [
[0, 0, 3, 0, 0],
- [0, 4, 0, 0, 0],
+ [0, 4, 0, 0, 0],
[5, 0, 0, 6, 0],
- [0, 0, 0, 0, 0],
- [0, 7, 0, 0, 8]
+ [0, 0, 0, 0, 0],
+ [0, 7, 0, 0, 8],
]
vals, row_idx, col_ptr = compressed_col_sparse_matrix(dense_matrix)
- assert vals == [5, 4, 7, 3, 6, 8], "Test case failed: vals should be [5, 4, 7, 3, 6, 8]"
- assert row_idx == [2, 1, 4, 0, 2, 4], "Test case failed: row_idx should be [2, 1, 4, 0, 2, 4]"
- assert col_ptr == [0, 1, 3, 4, 5, 6], "Test case failed: col_ptr should be [0, 1, 3, 4, 5, 6]"
+ assert vals == [5, 4, 7, 3, 6, 8], (
+ "Test case failed: vals should be [5, 4, 7, 3, 6, 8]"
+ )
+ assert row_idx == [2, 1, 4, 0, 2, 4], (
+ "Test case failed: row_idx should be [2, 1, 4, 0, 2, 4]"
+ )
+ assert col_ptr == [0, 1, 3, 4, 5, 6], (
+ "Test case failed: col_ptr should be [0, 1, 3, 4, 5, 6]"
+ )
+
if __name__ == "__main__":
test_compressed_row()
diff --git a/old_repo/Problems/69_r-squared/solution.py b/old_repo/Problems/69_r-squared/solution.py
index 199c73a1..563f2c3f 100644
--- a/old_repo/Problems/69_r-squared/solution.py
+++ b/old_repo/Problems/69_r-squared/solution.py
@@ -1,25 +1,26 @@
import numpy as np
+
def r_squared(y_true, y_pred):
"""
Calculate the R-squared (R²) coefficient of determination.
-
+
Args:
y_true (numpy.ndarray): Array of true values
y_pred (numpy.ndarray): Array of predicted values
-
+
Returns:
float: R-squared value rounded to 3 decimal places
"""
if np.array_equal(y_true, y_pred):
return 1.0
-
+
# Calculate mean of true values
y_mean = np.mean(y_true)
-
+
# Calculate Sum of Squared Residuals (SSR)
ssr = np.sum((y_true - y_pred) ** 2)
-
+
# Calculate Total Sum of Squares (SST)
sst = np.sum((y_true - y_mean) ** 2)
@@ -32,6 +33,7 @@ def r_squared(y_true, y_pred):
except ZeroDivisionError:
return 0.0
+
def test_r_squared():
# Test case 1: Perfect prediction
y_true = np.array([1, 2, 3, 4, 5])
@@ -49,7 +51,7 @@ def test_r_squared():
y_true = np.array([1, 2, 3, 4, 5])
y_pred = np.array([2, 1, 4, 3, 5])
expected_output = 0.600
- output = r_squared(y_true, y_pred)
+ r_squared(y_true, y_pred)
assert r_squared(y_true, y_pred) == expected_output, "Test case 3 failed"
# Test case 4: Worst possible prediction (predicting mean)
@@ -57,7 +59,7 @@ def test_r_squared():
y_pred = np.array([3, 3, 3, 3, 3])
expected_output = 0.000
assert r_squared(y_true, y_pred) == expected_output, "Test case 4 failed"
-
+
# Test case 5
y_true = np.array([3, 3, 3, 3, 3])
y_pred = np.array([1, 2, 3, 4, 5])
@@ -70,18 +72,19 @@ def test_r_squared():
expected_output = -3.000
assert r_squared(y_true, y_pred) == expected_output, "Test case 6 failed"
- # Test case 7: All zeros
+ # Test case 7: All zeros
y_true = np.array([0, 0, 0, 0, 0])
y_pred = np.array([0, 0, 0, 0, 0])
expected_output = 1.000
assert r_squared(y_true, y_pred) == expected_output, "Test case 7 failed"
-
+
# Test case 8 : output = -inf
y_true = np.array([-2, -2, -2])
y_pred = np.array([-2, -2, -2 + 1e-8])
expected_output = 0.000
assert r_squared(y_true, y_pred) == expected_output, "Test case 8 failed"
+
if __name__ == "__main__":
test_r_squared()
- print("All R-squared tests passed.")
\ No newline at end of file
+ print("All R-squared tests passed.")
diff --git a/old_repo/Problems/6_calculate_eigenvalues/solution.py b/old_repo/Problems/6_calculate_eigenvalues/solution.py
index b661fb1f..951cfb7d 100644
--- a/old_repo/Problems/6_calculate_eigenvalues/solution.py
+++ b/old_repo/Problems/6_calculate_eigenvalues/solution.py
@@ -12,6 +12,7 @@ def calculate_eigenvalues(
lambda_2 = (trace - discriminant**0.5) / 2
return [lambda_1, lambda_2]
+
def test_calculate_eigenvalues() -> None:
# Test cases for calculate_eigenvalues function
@@ -23,6 +24,7 @@ def test_calculate_eigenvalues() -> None:
matrix = [[4, -2], [1, 1]]
assert calculate_eigenvalues(matrix) == [3.0, 2.0]
+
if __name__ == "__main__":
test_calculate_eigenvalues()
- print("All calculate_eigenvalues tests passed.")
\ No newline at end of file
+ print("All calculate_eigenvalues tests passed.")
diff --git a/old_repo/Problems/70_image_brightness_calculator/solution.py b/old_repo/Problems/70_image_brightness_calculator/solution.py
index ef1c4ce8..3f624d95 100644
--- a/old_repo/Problems/70_image_brightness_calculator/solution.py
+++ b/old_repo/Problems/70_image_brightness_calculator/solution.py
@@ -4,9 +4,9 @@ def calculate_brightness(
# Check if image is empty or has no columns
if not img or not img[0]:
return -1
-
+
rows, cols = len(img), len(img[0])
-
+
# Check if all rows have same length and values are valid
for row in img:
if len(row) != cols:
@@ -14,7 +14,7 @@ def calculate_brightness(
for pixel in row:
if not 0 <= pixel <= 255:
return -1
-
+
# Calculate average brightness
total = sum(sum(row) for row in img)
return round(total / (rows * cols), 2)
@@ -23,18 +23,19 @@ def calculate_brightness(
def test_calculate_brightness() -> None:
# Test empty image
assert calculate_brightness([]) == -1
-
+
# Test invalid dimensions
assert calculate_brightness([[100, 200], [150]]) == -1
-
+
# Test invalid pixel values
assert calculate_brightness([[100, 300]]) == -1
assert calculate_brightness([[100, -1]]) == -1
-
+
# Test valid cases
assert calculate_brightness([[128]]) == 128.0
assert calculate_brightness([[100, 200], [50, 150]]) == 125.0
-
+
+
if __name__ == "__main__":
test_calculate_brightness()
- print("All tests passed.")
\ No newline at end of file
+ print("All tests passed.")
diff --git a/old_repo/Problems/71_Room_Mean_Square_Error/solution.py b/old_repo/Problems/71_Room_Mean_Square_Error/solution.py
index 2e7d2ab2..b8e6482f 100644
--- a/old_repo/Problems/71_Room_Mean_Square_Error/solution.py
+++ b/old_repo/Problems/71_Room_Mean_Square_Error/solution.py
@@ -1,31 +1,34 @@
import numpy as np
-def rmse(y_true,y_pred):
+
+def rmse(y_true, y_pred):
if y_true.shape != y_pred.shape:
raise ValueError("Arrays must have the same shape")
if y_true.size == 0:
raise ValueError("Arrays cannot be empty")
-
- return round(np.sqrt(np.mean((y_true - y_pred) ** 2)),3)
+
+ return round(np.sqrt(np.mean((y_true - y_pred) ** 2)), 3)
+
+
def test_rmse():
-# Test Case 1: Normal Case
+ # Test Case 1: Normal Case
y_true1 = np.array([3, -0.5, 2, 7])
y_pred1 = np.array([2.5, 0.0, 2, 8])
expected1 = 0.612
assert abs(rmse(y_true1, y_pred1)) == expected1, "Test Case Failed"
-# Test Case 2: 2D Array
+ # Test Case 2: 2D Array
y_true2 = np.array([[0.5, 1], [-1, 1], [7, -6]])
y_pred2 = np.array([[0, 2], [-1, 2], [8, -5]])
expected2 = 0.842
- assert rmse(y_true2, y_pred2)==expected2, "Test Case Failed"
+ assert rmse(y_true2, y_pred2) == expected2, "Test Case Failed"
-# Test Case 3: Perfect predictions
+ # Test Case 3: Perfect predictions
y_true3 = np.array([[1, 2], [3, 4]])
y_pred3 = np.array([[1, 2], [3, 4]])
assert rmse(y_true3, y_pred3) == 0.0, "Test Case Failed"
-# Test Case 4: Different shapes
+ # Test Case 4: Different shapes
y_true4 = np.array([[1, 2], [3, 4]])
y_pred4 = np.array([1, 2, 3, 4])
try:
@@ -34,7 +37,7 @@ def test_rmse():
except ValueError:
pass
-# Test Case 5: Empty arrays
+ # Test Case 5: Empty arrays
y_true5 = np.array([])
y_pred5 = np.array([])
try:
@@ -43,6 +46,7 @@ def test_rmse():
except ValueError:
pass
+
if __name__ == "__main__":
test_rmse()
print("All Test Cases Passed !")
diff --git a/old_repo/Problems/73_Dice_Score/solution.py b/old_repo/Problems/73_Dice_Score/solution.py
index 939e231a..a1f0c622 100644
--- a/old_repo/Problems/73_Dice_Score/solution.py
+++ b/old_repo/Problems/73_Dice_Score/solution.py
@@ -1,13 +1,14 @@
import numpy as np
+
def dice_score(y_true, y_pred):
"""
Calculate the Dice coefficient (also known as F1-score or Sørensen–Dice coefficient).
-
+
Args:
y_true (numpy.ndarray): Array of true values (ground truth)
y_pred (numpy.ndarray): Array of predicted values
-
+
Returns:
float: Dice score value rounded to 3 decimal places
"""
@@ -15,65 +16,66 @@ def dice_score(y_true, y_pred):
intersection = np.logical_and(y_true, y_pred).sum()
true_sum = y_true.sum()
pred_sum = y_pred.sum()
-
- # Handle edge cases
+
+ # Handle edge cases
if true_sum == 0 or pred_sum == 0:
return 0.0
-
+
# Calculate Dice coefficient
dice = (2.0 * intersection) / (true_sum + pred_sum)
return round(float(dice), 3)
+
def test_dice_score():
# Test case 1: Perfect overlap
y_true = np.array([1, 1, 0, 0])
y_pred = np.array([1, 1, 0, 0])
expected_output = 1.000
assert dice_score(y_true, y_pred) == expected_output, "Test case 1 failed"
-
+
# Test case 2: No overlap
y_true = np.array([1, 1, 0, 0])
y_pred = np.array([0, 0, 1, 1])
expected_output = 0.000
assert dice_score(y_true, y_pred) == expected_output, "Test case 2 failed"
-
+
# Test case 3: Partial overlap
y_true = np.array([1, 1, 0, 0])
y_pred = np.array([1, 0, 0, 0])
expected_output = 0.667
assert dice_score(y_true, y_pred) == expected_output, "Test case 3 failed"
-
+
# Test case 4: All zeros
y_true = np.array([0, 0, 0, 0])
y_pred = np.array([0, 0, 0, 0])
expected_output = 0.000
assert dice_score(y_true, y_pred) == expected_output, "Test case 4 failed"
-
+
# Test case 5: All ones
y_true = np.array([1, 1, 1, 1])
y_pred = np.array([1, 1, 1, 1])
expected_output = 1.000
assert dice_score(y_true, y_pred) == expected_output, "Test case 5 failed"
-
+
# Test case 6: One empty, one full
y_true = np.array([0, 0, 0, 0])
y_pred = np.array([1, 1, 1, 1])
expected_output = 0.000
assert dice_score(y_true, y_pred) == expected_output, "Test case 6 failed"
-
+
# Test case 7: Single element arrays
y_true = np.array([1])
y_pred = np.array([1])
expected_output = 1.000
assert dice_score(y_true, y_pred) == expected_output, "Test case 7 failed"
-
+
# Test case 8: Different data types
y_true = np.array([True, True, False, False])
y_pred = np.array([1, 1, 0, 0])
expected_output = 1.000
assert dice_score(y_true, y_pred) == expected_output, "Test case 8 failed"
-
+
if __name__ == "__main__":
test_dice_score()
- print("All Dice score test cases passed.")
\ No newline at end of file
+ print("All Dice score test cases passed.")
diff --git a/old_repo/Problems/74_hdc_bundling_binding/solution.py b/old_repo/Problems/74_hdc_bundling_binding/solution.py
index cb762b6f..06864589 100644
--- a/old_repo/Problems/74_hdc_bundling_binding/solution.py
+++ b/old_repo/Problems/74_hdc_bundling_binding/solution.py
@@ -1,24 +1,30 @@
import numpy as np
+
def create_hv(dim):
return np.random.choice([-1, 1], dim)
+
def create_col_hvs(dim, seed):
np.random.seed(seed)
return create_hv(dim), create_hv(dim)
+
def bind(hv1, hv2):
- return hv1*hv2
+ return hv1 * hv2
+
def bundle(hvs, dim):
bundled = np.sum(list(hvs.values()), axis=0)
return sign(bundled)
+
def sign(vector, threshold=0.01):
return np.array([1 if v >= 0 else -1 for v in vector])
-def create_row_hv(row:dict[str,str], dim:int, random_seeds:dict[str,int]):
- row_hvs = {col:bind(*create_col_hvs(dim, random_seeds[col])) for col in row.keys()}
+
+def create_row_hv(row: dict[str, str], dim: int, random_seeds: dict[str, int]):
+ row_hvs = {col: bind(*create_col_hvs(dim, random_seeds[col])) for col in row.keys()}
return bundle(row_hvs, dim)
@@ -30,26 +36,33 @@ def test_create_row_hv():
# Test case 1
dim = 5
hv = create_row_hv(row, dim, seed_dict)
- result_hv = np.array([1,-1,1,1,1])
+ result_hv = np.array([1, -1, 1, 1, 1])
assert len(hv) == dim, "Test case 1 failed: Incorrect dimension"
- assert np.all(np.isin(hv, [-1, 1])), "Test case 1 failed: Non-bipolar values present"
- assert np.array_equal(hv,result_hv)
+ assert np.all(np.isin(hv, [-1, 1])), (
+ "Test case 1 failed: Non-bipolar values present"
+ )
+ assert np.array_equal(hv, result_hv)
# Test case 2
dim = 10
hv = create_row_hv(row, dim, seed_dict)
- result_hv = np.array([1,-1,1,1,-1,-1,-1,-1,-1,-1])
+ result_hv = np.array([1, -1, 1, 1, -1, -1, -1, -1, -1, -1])
assert len(hv) == dim, "Test case 2 failed: Incorrect dimension"
- assert np.all(np.isin(hv, [-1, 1])), "Test case 2 failed: Non-bipolar values present"
- assert np.array_equal(hv,result_hv)
+ assert np.all(np.isin(hv, [-1, 1])), (
+ "Test case 2 failed: Non-bipolar values present"
+ )
+ assert np.array_equal(hv, result_hv)
# Test case 3
dim = 15
hv = create_row_hv(row, dim, seed_dict)
- result_hv = np.array([1,1,-1,-1,1,1,1,1,-1,1,1,1,-1,-1,1])
+ result_hv = np.array([1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1])
assert len(hv) == dim, "Test case 3 failed: Incorrect dimension"
- assert np.all(np.isin(hv, [-1, 1])), "Test case 3 failed: Non-bipolar values present"
- assert np.array_equal(hv,result_hv)
+ assert np.all(np.isin(hv, [-1, 1])), (
+ "Test case 3 failed: Non-bipolar values present"
+ )
+ assert np.array_equal(hv, result_hv)
+
if __name__ == "__main__":
test_create_row_hv()
diff --git a/old_repo/Problems/75_classification_performance_metrics/solution.py b/old_repo/Problems/75_classification_performance_metrics/solution.py
index b8d1f47e..bf5d4b4d 100644
--- a/old_repo/Problems/75_classification_performance_metrics/solution.py
+++ b/old_repo/Problems/75_classification_performance_metrics/solution.py
@@ -1,42 +1,78 @@
from collections import Counter
-def performance_metrics(actual: list[int],predicted: list[int]) -> tuple:
- #Merge lists into one
- data = list(zip(actual,predicted))
- #Count all occurrences
+
+def performance_metrics(actual: list[int], predicted: list[int]) -> tuple:
+ # Merge lists into one
+ data = list(zip(actual, predicted))
+ # Count all occurrences
counts = Counter(tuple(pair) for pair in data)
- #Get metrics
- TP, FN, FP, TN = counts[(1,1)],counts[(1,0)],counts[(0,1)],counts[(0,0)]
- #Define confusin matrix
- confusion_matrix = [[TP,FN],[FP,TN]]
- #Get accuracy
- accuracy = (TP+TN)/(TP+TN+FP+FN)
- #Get precision
- precision = TP/(TP+FP)
- #Get recall
- recall = TP/(TP + FN)
- #Get F1 score
- f1 = 2*precision*recall/(precision+recall)
- #Get negative predictive value
- negativePredictive = TN/(TN+FN)
- #Get specificiy
- specificity = TN/(TN+FP)
- #Return
- return confusion_matrix, round(accuracy,3),round(f1,3), round(specificity,3), round(negativePredictive,3),
+ # Get metrics
+ TP, FN, FP, TN = counts[(1, 1)], counts[(1, 0)], counts[(0, 1)], counts[(0, 0)]
+ # Define confusin matrix
+ confusion_matrix = [[TP, FN], [FP, TN]]
+ # Get accuracy
+ accuracy = (TP + TN) / (TP + TN + FP + FN)
+ # Get precision
+ precision = TP / (TP + FP)
+ # Get recall
+ recall = TP / (TP + FN)
+ # Get F1 score
+ f1 = 2 * precision * recall / (precision + recall)
+ # Get negative predictive value
+ negativePredictive = TN / (TN + FN)
+ # Get specificiy
+ specificity = TN / (TN + FP)
+ # Return
+ return (
+ confusion_matrix,
+ round(accuracy, 3),
+ round(f1, 3),
+ round(specificity, 3),
+ round(negativePredictive, 3),
+ )
+
def test_confusion_matrix() -> None:
# Test case 1
- y_actual, y_pred = [1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1], [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0]
- assert performance_metrics(y_actual,y_pred) == ([[6, 4], [2, 7]],0.684, 0.667, 0.778, 0.636), "Test case 1 failed"
+ y_actual, y_pred = (
+ [1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1],
+ [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0],
+ )
+ assert performance_metrics(y_actual, y_pred) == (
+ [[6, 4], [2, 7]],
+ 0.684,
+ 0.667,
+ 0.778,
+ 0.636,
+ ), "Test case 1 failed"
# Test case 2
- y_actual, y_pred = [0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0],[1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1]
- assert performance_metrics(y_actual,y_pred) == ([[4, 4], [5, 2]], 0.4, 0.471, 0.286, 0.333), "Test case 1 failed"
+ y_actual, y_pred = (
+ [0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0],
+ [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1],
+ )
+ assert performance_metrics(y_actual, y_pred) == (
+ [[4, 4], [5, 2]],
+ 0.4,
+ 0.471,
+ 0.286,
+ 0.333,
+ ), "Test case 1 failed"
# Test case 3
- y_actual, y_pred = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1],[0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0]
- assert performance_metrics(y_actual,y_pred) == ([[4, 5], [4, 2]], 0.4, 0.471, 0.333, 0.286), "Test case 1 failed"
+ y_actual, y_pred = (
+ [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1],
+ [0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0],
+ )
+ assert performance_metrics(y_actual, y_pred) == (
+ [[4, 5], [4, 2]],
+ 0.4,
+ 0.471,
+ 0.333,
+ 0.286,
+ ), "Test case 1 failed"
+
if __name__ == "__main__":
test_confusion_matrix()
- print("All performance metrics tests passed.")
\ No newline at end of file
+ print("All performance metrics tests passed.")
diff --git a/old_repo/Problems/76_Cosine_Similarity/solution.py b/old_repo/Problems/76_Cosine_Similarity/solution.py
index 16ff3ba4..0f68a543 100644
--- a/old_repo/Problems/76_Cosine_Similarity/solution.py
+++ b/old_repo/Problems/76_Cosine_Similarity/solution.py
@@ -1,47 +1,49 @@
import numpy as np
+
def cosine_similarity(v1, v2):
if v1.shape != v2.shape:
raise ValueError("Arrays must have the same shape")
-
+
if v1.size == 0:
raise ValueError("Arrays cannot be empty")
-
+
# Flatten arrays in case of 2D
v1_flat = v1.flatten()
v2_flat = v2.flatten()
-
+
dot_product = np.dot(v1_flat, v2_flat)
magnitude1 = np.sqrt(np.sum(v1_flat**2))
magnitude2 = np.sqrt(np.sum(v2_flat**2))
-
+
if magnitude1 == 0 or magnitude2 == 0:
raise ValueError("Vectors cannot have zero magnitude")
-
+
return round(dot_product / (magnitude1 * magnitude2), 3)
+
def test_cosine_similarity():
v1_test1 = np.array([1, 2, 3])
v2_test1 = np.array([2, 4, 6])
- expected1 = 1.0
+ expected1 = 1.0
assert cosine_similarity(v1_test1, v2_test1) == expected1, "Test Case Failed"
-
+
v1_test2 = np.array([[1, 2], [3, 4]])
v2_test2 = np.array([[2, 4], [6, 8]])
expected2 = 1.0
assert cosine_similarity(v1_test2, v2_test2) == expected2, "Test Case Failed"
-
+
v1_test3 = np.array([1, 2, 3])
v2_test3 = np.array([-1, -2, -3])
expected3 = -1.0
assert cosine_similarity(v1_test3, v2_test3) == expected3, "Test Case Failed"
-
+
# Test Case : Orthogonal vectors
v1_test4 = np.array([1, 0])
v2_test4 = np.array([0, 1])
expected4 = 0.0
assert cosine_similarity(v1_test4, v2_test4) == expected4, "Test Case Failed"
-
+
# Test Case : Different shapes
v1_test5 = np.array([1, 2, 3])
v2_test5 = np.array([1, 2])
@@ -50,7 +52,7 @@ def test_cosine_similarity():
assert False, "Test Case Failed"
except ValueError:
pass
-
+
# Test Case : Zero magnitude vector
v1_test7 = np.array([0, 0, 0])
v2_test7 = np.array([1, 2, 3])
@@ -60,6 +62,7 @@ def test_cosine_similarity():
except ValueError:
pass
+
if __name__ == "__main__":
test_cosine_similarity()
print("All Test Cases Passed!")
diff --git a/old_repo/Problems/77_classification_performance_metrics/solution.py b/old_repo/Problems/77_classification_performance_metrics/solution.py
index 239a057d..10352662 100644
--- a/old_repo/Problems/77_classification_performance_metrics/solution.py
+++ b/old_repo/Problems/77_classification_performance_metrics/solution.py
@@ -1,45 +1,81 @@
from collections import Counter
-def performance_metrics(actual: list[int],predicted: list[int]) -> tuple:
- #Ensure lists are of the same length
+
+def performance_metrics(actual: list[int], predicted: list[int]) -> tuple:
+ # Ensure lists are of the same length
if len(actual) != len(predicted):
raise ValueError("Lists must be of the same length")
- #Merge lists into one
- data = list(zip(actual,predicted))
- #Count all occurrences
+ # Merge lists into one
+ data = list(zip(actual, predicted))
+ # Count all occurrences
counts = Counter(tuple(pair) for pair in data)
- #Get metrics
- TP, FN, FP, TN = counts[(1,1)],counts[(1,0)],counts[(0,1)],counts[(0,0)]
- #Define confusin matrix
- confusion_matrix = [[TP,FN],[FP,TN]]
- #Get accuracy
- accuracy = (TP+TN)/(TP+TN+FP+FN)
- #Get precision
- precision = TP/(TP+FP)
- #Get recall
- recall = TP/(TP + FN)
- #Get F1 score
- f1 = 2*precision*recall/(precision+recall)
- #Get negative predictive value
- negativePredictive = TN/(TN+FN)
- #Get specificiy
- specificity = TN/(TN+FP)
- #Return
- return confusion_matrix, round(accuracy,3),round(f1,3), round(specificity,3), round(negativePredictive,3),
+ # Get metrics
+ TP, FN, FP, TN = counts[(1, 1)], counts[(1, 0)], counts[(0, 1)], counts[(0, 0)]
+ # Define confusin matrix
+ confusion_matrix = [[TP, FN], [FP, TN]]
+ # Get accuracy
+ accuracy = (TP + TN) / (TP + TN + FP + FN)
+ # Get precision
+ precision = TP / (TP + FP)
+ # Get recall
+ recall = TP / (TP + FN)
+ # Get F1 score
+ f1 = 2 * precision * recall / (precision + recall)
+ # Get negative predictive value
+ negativePredictive = TN / (TN + FN)
+ # Get specificiy
+ specificity = TN / (TN + FP)
+ # Return
+ return (
+ confusion_matrix,
+ round(accuracy, 3),
+ round(f1, 3),
+ round(specificity, 3),
+ round(negativePredictive, 3),
+ )
+
def test_confusion_matrix() -> None:
# Test case 1
- y_actual, y_pred = [1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1], [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0]
- assert performance_metrics(y_actual,y_pred) == ([[6, 4], [2, 7]],0.684, 0.667, 0.778, 0.636), "Test case 1 failed"
+ y_actual, y_pred = (
+ [1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1],
+ [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0],
+ )
+ assert performance_metrics(y_actual, y_pred) == (
+ [[6, 4], [2, 7]],
+ 0.684,
+ 0.667,
+ 0.778,
+ 0.636,
+ ), "Test case 1 failed"
# Test case 2
- y_actual, y_pred = [0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0],[1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1]
- assert performance_metrics(y_actual,y_pred) == ([[4, 4], [5, 2]], 0.4, 0.471, 0.286, 0.333), "Test case 1 failed"
+ y_actual, y_pred = (
+ [0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0],
+ [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1],
+ )
+ assert performance_metrics(y_actual, y_pred) == (
+ [[4, 4], [5, 2]],
+ 0.4,
+ 0.471,
+ 0.286,
+ 0.333,
+ ), "Test case 1 failed"
# Test case 3
- y_actual, y_pred = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1],[0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0]
- assert performance_metrics(y_actual,y_pred) == ([[4, 5], [4, 2]], 0.4, 0.471, 0.333, 0.286), "Test case 1 failed"
+ y_actual, y_pred = (
+ [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1],
+ [0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0],
+ )
+ assert performance_metrics(y_actual, y_pred) == (
+ [[4, 5], [4, 2]],
+ 0.4,
+ 0.471,
+ 0.333,
+ 0.286,
+ ), "Test case 1 failed"
+
if __name__ == "__main__":
test_confusion_matrix()
- print("All performance metrics tests passed.")
\ No newline at end of file
+ print("All performance metrics tests passed.")
diff --git a/old_repo/Problems/78_binomial_distribution/solution.py b/old_repo/Problems/78_binomial_distribution/solution.py
index ad7ace5f..91dcaaa2 100644
--- a/old_repo/Problems/78_binomial_distribution/solution.py
+++ b/old_repo/Problems/78_binomial_distribution/solution.py
@@ -1,5 +1,6 @@
import math
+
def binomial_probability(n, k, p):
"""
Calculate the probability of achieving exactly k successes in n independent Bernoulli trials,
@@ -13,47 +14,54 @@ def binomial_probability(n, k, p):
# Calculate binomial coefficient (n choose k)
binomial_coeff = math.comb(n, k)
# Calculate the probability using the binomial formula
- probability = binomial_coeff * (p ** k) * ((1 - p) ** (n - k))
+ probability = binomial_coeff * (p**k) * ((1 - p) ** (n - k))
# Return the probability, rounded to five decimal places
return round(probability, 5)
+
def test_binomial_probability():
# Test case 1: Basic binomial calculation
n1, k1, p1 = 6, 2, 0.5
expected_output_1 = 0.23438
output_1 = binomial_probability(n1, k1, p1)
- assert output_1 == expected_output_1, \
+ assert output_1 == expected_output_1, (
f"Test case 1 failed: expected {expected_output_1}, got {output_1}"
+ )
# Test case 2: Higher success probability
n2, k2, p2 = 6, 4, 0.7
expected_output_2 = 0.32413
output_2 = binomial_probability(n2, k2, p2)
- assert output_2 == expected_output_2, \
+ assert output_2 == expected_output_2, (
f"Test case 2 failed: expected {expected_output_2}, got {output_2}"
+ )
# Test case 3: All trials succeed
n3, k3, p3 = 3, 3, 0.9
expected_output_3 = 0.729
output_3 = binomial_probability(n3, k3, p3)
- assert output_3 == expected_output_3, \
+ assert output_3 == expected_output_3, (
f"Test case 3 failed: expected {expected_output_3}, got {output_3}"
+ )
# Test case 4: All trials fail
n4, k4, p4 = 5, 0, 0.3
expected_output_4 = 0.16807
output_4 = binomial_probability(n4, k4, p4)
- assert output_4 == expected_output_4, \
+ assert output_4 == expected_output_4, (
f"Test case 4 failed: expected {expected_output_4}, got {output_4}"
+ )
# Test case 5: Low probability of success
n5, k5, p5 = 7, 2, 0.1
expected_output_5 = 0.12106
output_5 = binomial_probability(n5, k5, p5)
- assert output_5 == expected_output_5, \
+ assert output_5 == expected_output_5, (
f"Test case 5 failed: expected {expected_output_5}, got {output_5}"
+ )
print("All Binomial distribution tests passed.")
+
if __name__ == "__main__":
test_binomial_probability()
diff --git a/old_repo/Problems/78_descriptive_stats/solution.py b/old_repo/Problems/78_descriptive_stats/solution.py
index 84dcdd0e..5dbdde43 100644
--- a/old_repo/Problems/78_descriptive_stats/solution.py
+++ b/old_repo/Problems/78_descriptive_stats/solution.py
@@ -44,7 +44,7 @@ def descriptive_statistics(data):
"25th_percentile": percentiles[0],
"50th_percentile": percentiles[1],
"75th_percentile": percentiles[2],
- "interquartile_range": iqr
+ "interquartile_range": iqr,
}
return stats_dict
@@ -62,11 +62,13 @@ def test_descriptive_statistics():
"25th_percentile": 20.0,
"50th_percentile": 30.0,
"75th_percentile": 40.0,
- "interquartile_range": 20.0
+ "interquartile_range": 20.0,
}
output_1 = descriptive_statistics(data_1)
- assert all(np.isclose(output_1[key], value, atol=1e-5) for key, value in expected_output_1.items()), \
- f"Test case 1 failed: expected {expected_output_1}, got {output_1}"
+ assert all(
+ np.isclose(output_1[key], value, atol=1e-5)
+ for key, value in expected_output_1.items()
+ ), f"Test case 1 failed: expected {expected_output_1}, got {output_1}"
# Test case 2: Dataset with repeated elements
data_2 = [1, 2, 2, 3, 4, 4, 4, 5]
@@ -79,11 +81,13 @@ def test_descriptive_statistics():
"25th_percentile": 2.0,
"50th_percentile": 3.5,
"75th_percentile": 4.0,
- "interquartile_range": 2.0
+ "interquartile_range": 2.0,
}
output_2 = descriptive_statistics(data_2)
- assert all(np.isclose(output_2[key], value, atol=1e-5) for key, value in expected_output_2.items()), \
- f"Test case 2 failed: expected {expected_output_2}, got {output_2}"
+ assert all(
+ np.isclose(output_2[key], value, atol=1e-5)
+ for key, value in expected_output_2.items()
+ ), f"Test case 2 failed: expected {expected_output_2}, got {output_2}"
# Test case 3: Single-element dataset
data_3 = [100]
@@ -96,11 +100,13 @@ def test_descriptive_statistics():
"25th_percentile": 100.0,
"50th_percentile": 100.0,
"75th_percentile": 100.0,
- "interquartile_range": 0.0
+ "interquartile_range": 0.0,
}
output_3 = descriptive_statistics(data_3)
- assert all(np.isclose(output_3[key], value, atol=1e-5) for key, value in expected_output_3.items()), \
- f"Test case 3 failed: expected {expected_output_3}, got {output_3}"
+ assert all(
+ np.isclose(output_3[key], value, atol=1e-5)
+ for key, value in expected_output_3.items()
+ ), f"Test case 3 failed: expected {expected_output_3}, got {output_3}"
print("All descriptive statistics tests passed.")
diff --git a/old_repo/Problems/7_transform_matrix/solution.py b/old_repo/Problems/7_transform_matrix/solution.py
index e7312a4f..7b0e73a9 100644
--- a/old_repo/Problems/7_transform_matrix/solution.py
+++ b/old_repo/Problems/7_transform_matrix/solution.py
@@ -1,29 +1,30 @@
import numpy as np
+
def transform_matrix(
A: list[list[int | float]],
T: list[list[int | float]],
S: list[list[int | float]],
) -> list[list[int | float]]:
-
# Convert to numpy arrays for easier manipulation
A = np.array(A, dtype=float)
T = np.array(T, dtype=float)
S = np.array(S, dtype=float)
-
+
# Check if the matrices T and S are invertible
if np.linalg.det(T) == 0 or np.linalg.det(S) == 0:
# raise ValueError("The matrices T and/or S are not invertible.")
return -1
-
+
# Compute the inverse of T
T_inv = np.linalg.inv(T)
-
+
# Perform the matrix transformation; use @ for better readability
transformed_matrix = np.round(T_inv @ A @ S, 3)
-
+
return transformed_matrix.tolist()
+
def test_transform_matrix() -> None:
# Test cases for transform_matrix function
# Test case 1
@@ -31,19 +32,19 @@ def test_transform_matrix() -> None:
T = [[2, 0], [0, 2]]
S = [[1, 1], [0, 1]]
assert transform_matrix(A, T, S) == [[0.5, 1.5], [1.5, 3.5]]
-
+
# Test case 2
A = [[1, 0], [0, 1]]
T = [[1, 2], [3, 4]]
S = [[2, 0], [0, 2]]
assert transform_matrix(A, T, S) == [[-4.0, 2.0], [3.0, -1.0]]
-
+
# Test case 3
A = [[2, 3], [1, 4]]
T = [[3, 0], [0, 3]]
S = [[1, 1], [0, 1]]
assert transform_matrix(A, T, S) == [[0.667, 1.667], [0.333, 1.667]]
-
+
# Test case 4
A = [[2, 3], [1, 4]]
T = [[3, 0], [0, 3]]
@@ -51,16 +52,21 @@ def test_transform_matrix() -> None:
assert transform_matrix(A, T, S) == -1
# Test case 5
- A = [[1, 2, 3],[0, 1, 4],[5, 6, 0]]
- T = [[2, 0, 0],[0, 2, 0],[0, 0, 2]]
- S = [[0, 1, 0],[0, 0, 1],[1, 0, 0]]
- assert transform_matrix(A, T, S) == [[1.5, 0.5, 1.0], [2.0, 0.0, 0.5], [0.0, 2.5, 3.0]]
+ A = [[1, 2, 3], [0, 1, 4], [5, 6, 0]]
+ T = [[2, 0, 0], [0, 2, 0], [0, 0, 2]]
+ S = [[0, 1, 0], [0, 0, 1], [1, 0, 0]]
+ assert transform_matrix(A, T, S) == [
+ [1.5, 0.5, 1.0],
+ [2.0, 0.0, 0.5],
+ [0.0, 2.5, 3.0],
+ ]
# try:
# transform_matrix(A, T, S)
# assert False, "ValueError not raised"
# except ValueError as e:
# assert str(e) == "The matrices T and/or S are not invertible."
+
if __name__ == "__main__":
test_transform_matrix()
- print("All transform_matrix tests passed.")
\ No newline at end of file
+ print("All transform_matrix tests passed.")
diff --git a/old_repo/Problems/80_normal_distribution/solution.py b/old_repo/Problems/80_normal_distribution/solution.py
index f5c5b34a..47a933d5 100644
--- a/old_repo/Problems/80_normal_distribution/solution.py
+++ b/old_repo/Problems/80_normal_distribution/solution.py
@@ -1,5 +1,6 @@
import math
+
def normal_pdf(x, mean, std_dev):
"""
Calculate the probability density function (PDF) of the normal distribution.
@@ -10,9 +11,10 @@ def normal_pdf(x, mean, std_dev):
:return: The PDF value for the given x.
"""
coefficient = 1 / (math.sqrt(2 * math.pi) * std_dev)
- exponent = math.exp(-((x - mean) ** 2) / (2 * std_dev ** 2))
+ exponent = math.exp(-((x - mean) ** 2) / (2 * std_dev**2))
return round(coefficient * exponent, 5)
+
def test_normal_pdf():
"""
Test cases for the normal_pdf function.
@@ -21,25 +23,29 @@ def test_normal_pdf():
x1, mean1, std_dev1 = 0, 0, 1
expected_output_1 = 0.39894
output_1 = normal_pdf(x1, mean1, std_dev1)
- assert output_1 == expected_output_1, \
+ assert output_1 == expected_output_1, (
f"Test case 1 failed: expected {expected_output_1}, got {output_1}"
+ )
# Test case 2: Normal distribution with non-zero mean
x2, mean2, std_dev2 = 16, 15, 2.04
expected_output_2 = 0.17603
output_2 = normal_pdf(x2, mean2, std_dev2)
- assert output_2 == expected_output_2, \
+ assert output_2 == expected_output_2, (
f"Test case 2 failed: expected {expected_output_2}, got {output_2}"
+ )
# Test case 3: Low standard deviation
x3, mean3, std_dev3 = 1, 0, 0.5
expected_output_3 = 0.10798
output_3 = normal_pdf(x3, mean3, std_dev3)
- assert output_3 == expected_output_3, \
+ assert output_3 == expected_output_3, (
f"Test case 3 failed: expected {expected_output_3}, got {output_3}"
+ )
print("All Normal Distribution tests passed.")
+
if __name__ == "__main__":
# Run the test cases
- test_normal_pdf()
\ No newline at end of file
+ test_normal_pdf()
diff --git a/old_repo/Problems/81_poisson_distribution/solution.py b/old_repo/Problems/81_poisson_distribution/solution.py
index d939282e..c08a2c73 100644
--- a/old_repo/Problems/81_poisson_distribution/solution.py
+++ b/old_repo/Problems/81_poisson_distribution/solution.py
@@ -1,5 +1,6 @@
import math
+
def poisson_probability(k, lam):
"""
Calculate the probability of observing exactly k events in a fixed interval,
@@ -10,47 +11,54 @@ def poisson_probability(k, lam):
:return: Probability of k events occurring
"""
# Calculate the Poisson probability using the formula
- probability = (lam ** k) * math.exp(-lam) / math.factorial(k)
+ probability = (lam**k) * math.exp(-lam) / math.factorial(k)
# Return the probability, rounded to five decimal places
return round(probability, 5)
+
def test_poisson_probability():
# Test case 1: Basic Poisson distribution calculation
k1, lam1 = 3, 5
expected_output_1 = 0.14037
output_1 = poisson_probability(k1, lam1)
- assert output_1 == expected_output_1, \
+ assert output_1 == expected_output_1, (
f"Test case 1 failed: expected {expected_output_1}, got {output_1}"
+ )
# Test case 2: Calculate probability for k = 0
k2, lam2 = 0, 5
expected_output_2 = 0.00674
output_2 = poisson_probability(k2, lam2)
- assert output_2 == expected_output_2, \
+ assert output_2 == expected_output_2, (
f"Test case 2 failed: expected {expected_output_2}, got {output_2}"
+ )
# Test case 3: Larger lambda (mean rate)
k3, lam3 = 2, 10
expected_output_3 = 0.00045
output_3 = poisson_probability(k3, lam3)
- assert output_3 == expected_output_3, \
+ assert output_3 == expected_output_3, (
f"Test case 3 failed: expected {expected_output_3}, got {output_3}"
+ )
# Test case 4: Small k with small lambda
k4, lam4 = 1, 1
expected_output_4 = 0.36788
output_4 = poisson_probability(k4, lam4)
- assert output_4 == expected_output_4, \
+ assert output_4 == expected_output_4, (
f"Test case 4 failed: expected {expected_output_4}, got {output_4}"
+ )
# Test case 5: Larger k with large lambda
k5, lam5 = 20, 20
expected_output_5 = 0.08505
output_5 = poisson_probability(k5, lam5)
- assert output_5 == expected_output_5, \
+ assert output_5 == expected_output_5, (
f"Test case 5 failed: expected {expected_output_5}, got {output_5}"
+ )
print("All Poisson distribution tests passed.")
+
if __name__ == "__main__":
test_poisson_probability()
diff --git a/old_repo/Problems/82_image_basic_contrast_calculator/solution.py b/old_repo/Problems/82_image_basic_contrast_calculator/solution.py
index 1f09250b..11272d2f 100644
--- a/old_repo/Problems/82_image_basic_contrast_calculator/solution.py
+++ b/old_repo/Problems/82_image_basic_contrast_calculator/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def calculate_contrast(img):
"""
Calculate the contrast of a grayscale image.
@@ -10,42 +11,44 @@ def calculate_contrast(img):
Returns:
float: Contrast value rounded to 3 decimal places.
"""
-
+
# Find the maximum and minimum pixel values
max_pixel = np.max(img)
min_pixel = np.min(img)
-
+
# Calculate contrast
contrast = max_pixel - min_pixel
-
+
return round(float(contrast), 3)
+
def test_calculate_contrast():
# Test case 1: Simple gradient
img1 = np.array([[0, 50], [200, 255]])
expected_output1 = 255
assert calculate_contrast(img1) == expected_output1, "Test case 1 failed"
-
+
# Test case 2: Uniform image (all pixels same)
img2 = np.array([[128, 128], [128, 128]])
expected_output2 = 0
assert calculate_contrast(img2) == expected_output2, "Test case 2 failed"
-
+
# Test case 3: All black
img3 = np.zeros((10, 10), dtype=np.uint8)
expected_output3 = 0
assert calculate_contrast(img3) == expected_output3, "Test case 3 failed"
-
+
# Test case 4: All white
img4 = np.ones((10, 10), dtype=np.uint8) * 255
expected_output4 = 0
assert calculate_contrast(img4) == expected_output4, "Test case 4 failed"
-
+
# Test case 5: Random values
img5 = np.array([[10, 20, 30], [40, 50, 60]])
expected_output5 = 50
assert calculate_contrast(img5) == expected_output5, "Test case 5 failed"
+
if __name__ == "__main__":
test_calculate_contrast()
- print("All contrast test cases passed.")
\ No newline at end of file
+ print("All contrast test cases passed.")
diff --git a/old_repo/Problems/83_vector_dot_product/solution.py b/old_repo/Problems/83_vector_dot_product/solution.py
index 8203f86f..68b7fad0 100644
--- a/old_repo/Problems/83_vector_dot_product/solution.py
+++ b/old_repo/Problems/83_vector_dot_product/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def calculate_dot_product(vec1, vec2):
"""
Calculate the dot product of two vectors.
@@ -13,37 +14,39 @@ def calculate_dot_product(vec1, vec2):
"""
return np.dot(vec1, vec2)
+
def test_calculate_dot_product():
# Test case 1: Positive numbers
vec1 = np.array([1, 2, 3])
vec2 = np.array([4, 5, 6])
expected_output1 = 32
assert calculate_dot_product(vec1, vec2) == expected_output1, "Test case 1 failed"
-
+
# Test case 2: Include negative numbers
vec1 = np.array([-1, 2, 3])
vec2 = np.array([4, -5, 6])
expected_output2 = 4
assert calculate_dot_product(vec1, vec2) == expected_output2, "Test case 2 failed"
-
+
# Test case 3: Orthogonal vectors
vec1 = np.array([1, 0])
vec2 = np.array([0, 1])
expected_output3 = 0
assert calculate_dot_product(vec1, vec2) == expected_output3, "Test case 3 failed"
-
+
# Test case 4: All zeros
vec1 = np.array([0, 0, 0])
vec2 = np.array([0, 0, 0])
expected_output4 = 0
assert calculate_dot_product(vec1, vec2) == expected_output4, "Test case 4 failed"
-
+
# Test case 5: Scalars (single-element vectors)
vec1 = np.array([7])
vec2 = np.array([3])
expected_output5 = 21
assert calculate_dot_product(vec1, vec2) == expected_output5, "Test case 5 failed"
+
if __name__ == "__main__":
test_calculate_dot_product()
print("All dot product test cases passed.")
diff --git a/old_repo/Problems/84_phi_transformation/solution.py b/old_repo/Problems/84_phi_transformation/solution.py
index 5df869da..d6bfe4b2 100644
--- a/old_repo/Problems/84_phi_transformation/solution.py
+++ b/old_repo/Problems/84_phi_transformation/solution.py
@@ -1,36 +1,40 @@
import numpy as np
-def phi_transform(data: list[float], degree: int,) -> list[list[float]]:
+
+def phi_transform(
+ data: list[float],
+ degree: int,
+) -> list[list[float]]:
if degree < 0 or not data:
return []
- return np.array([[x ** i for i in range(degree + 1)] for x in data]).tolist()
+ return np.array([[x**i for i in range(degree + 1)] for x in data]).tolist()
+
def test_phi_transform() -> None:
- assert phi_transform([], 2) == [], 'Test Case 1 Failed.'
+ assert phi_transform([], 2) == [], "Test Case 1 Failed."
- assert phi_transform([1.0, 2.0], -1) == [], 'Test Case 2 Failed.'
+ assert phi_transform([1.0, 2.0], -1) == [], "Test Case 2 Failed."
data: list[float] = [1.0, 2.0]
degree: int = 2
assert phi_transform(data, degree) == [
[1.0, 1.0, 1.0],
[1.0, 2.0, 4.0],
- ], 'Test Case 3 Failed.'
+ ], "Test Case 3 Failed."
data: list[float] = [1.0, 3.0]
degree: int = 3
assert phi_transform(data, degree) == [
[1.0, 1.0, 1.0, 1.0],
[1.0, 3.0, 9.0, 27.0],
- ], 'Test Case 4 Failed.'
+ ], "Test Case 4 Failed."
data: list[float] = [2.0]
degree: int = 4
- assert phi_transform(data, degree) == [
- [1.0, 2.0, 4.0, 8.0, 16.0]
- ], 'Test Case 5 Failed.'
+ assert phi_transform(data, degree) == [[1.0, 2.0, 4.0, 8.0, 16.0]], (
+ "Test Case 5 Failed."
+ )
-
if __name__ == "__main__":
test_phi_transform()
diff --git a/old_repo/Problems/85_Positional_encoding/solution.py b/old_repo/Problems/85_Positional_encoding/solution.py
index e2aabfc5..258ad841 100644
--- a/old_repo/Problems/85_Positional_encoding/solution.py
+++ b/old_repo/Problems/85_Positional_encoding/solution.py
@@ -1,14 +1,14 @@
import numpy as np
-def pos_encoding(position:int, dmodel:int):
-
- if position == 0 or dmodel == 0: return -1
+
+def pos_encoding(position: int, dmodel: int):
+ if position == 0 or dmodel == 0:
+ return -1
pos = np.array(np.arange(position), np.float16)
ind = np.array(np.arange(dmodel), np.float16)
- pos = pos.reshape(position,1)
- ind = ind.reshape(1,dmodel)
-
+ pos = pos.reshape(position, 1)
+ ind = ind.reshape(1, dmodel)
def get_angles(pos, i):
angles = 1 / np.power(10000, (2 * (i // 2)) / np.float16(dmodel))
@@ -19,53 +19,145 @@ def get_angles(pos, i):
sine = np.sin(angle1[:, 0::2])
cosine = np.cos(angle1[:, 1::2])
- pos_encoding = np.concatenate([sine, cosine], axis = -1)
+ pos_encoding = np.concatenate([sine, cosine], axis=-1)
pos_encoding = pos_encoding[np.newaxis, :]
pos_encoding = np.float16(pos_encoding)
return pos_encoding
+
def test_pos_encoding() -> None:
# Test case 1:
- ans1 = np.array([[[0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0],
- [0.8413, 0.0998, 0.01, 0.001, 0.5405, 0.995, 1.0, 1.0]]], dtype=np.float16)
+ ans1 = np.array(
+ [
+ [
+ [0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0],
+ [0.8413, 0.0998, 0.01, 0.001, 0.5405, 0.995, 1.0, 1.0],
+ ]
+ ],
+ dtype=np.float16,
+ )
result1 = pos_encoding(2, 8)
- assert np.allclose(result1, ans1, atol=1e-3), f"Test case 1 failed: {result1} != {ans1}"
-
+ assert np.allclose(result1, ans1, atol=1e-3), (
+ f"Test case 1 failed: {result1} != {ans1}"
+ )
# Test case 2:
ans2 = np.array(
- [[[ 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
- 0.000e+00, 0.000e+00, 1.000e+00, 1.000e+00, 1.000e+00, 1.000e+00,
- 1.000e+00, 1.000e+00, 1.000e+00, 1.000e+00],
- [ 8.413e-01, 3.110e-01, 9.985e-02, 3.162e-02, 1.000e-02, 3.162e-03,
- 1.000e-03, 3.161e-04, 5.405e-01, 9.502e-01, 9.951e-01, 9.995e-01,
- 1.000e+00, 1.000e+00, 1.000e+00, 1.000e+00],
- [ 9.092e-01, 5.913e-01, 1.986e-01, 6.323e-02, 2.000e-02, 6.325e-03,
- 2.001e-03, 6.323e-04, -4.163e-01, 8.066e-01, 9.800e-01, 9.980e-01,
- 1.000e+00, 1.000e+00, 1.000e+00, 1.000e+00],
- [ 1.411e-01, 8.125e-01, 2.954e-01, 9.473e-02, 3.000e-02, 9.483e-03,
- 3.000e-03, 9.489e-04, -9.902e-01, 5.825e-01, 9.556e-01, 9.956e-01,
- 9.995e-01, 1.000e+00, 1.000e+00, 1.000e+00],
- [-7.568e-01, 9.536e-01, 3.894e-01, 1.261e-01, 3.998e-02, 1.265e-02,
- 4.002e-03, 1.265e-03, -6.538e-01, 3.010e-01, 9.209e-01, 9.922e-01,
- 9.990e-01, 1.000e+00, 1.000e+00, 1.000e+00]]],
- dtype=np.float16)
+ [
+ [
+ [
+ 0.000e00,
+ 0.000e00,
+ 0.000e00,
+ 0.000e00,
+ 0.000e00,
+ 0.000e00,
+ 0.000e00,
+ 0.000e00,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ ],
+ [
+ 8.413e-01,
+ 3.110e-01,
+ 9.985e-02,
+ 3.162e-02,
+ 1.000e-02,
+ 3.162e-03,
+ 1.000e-03,
+ 3.161e-04,
+ 5.405e-01,
+ 9.502e-01,
+ 9.951e-01,
+ 9.995e-01,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ ],
+ [
+ 9.092e-01,
+ 5.913e-01,
+ 1.986e-01,
+ 6.323e-02,
+ 2.000e-02,
+ 6.325e-03,
+ 2.001e-03,
+ 6.323e-04,
+ -4.163e-01,
+ 8.066e-01,
+ 9.800e-01,
+ 9.980e-01,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ ],
+ [
+ 1.411e-01,
+ 8.125e-01,
+ 2.954e-01,
+ 9.473e-02,
+ 3.000e-02,
+ 9.483e-03,
+ 3.000e-03,
+ 9.489e-04,
+ -9.902e-01,
+ 5.825e-01,
+ 9.556e-01,
+ 9.956e-01,
+ 9.995e-01,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ ],
+ [
+ -7.568e-01,
+ 9.536e-01,
+ 3.894e-01,
+ 1.261e-01,
+ 3.998e-02,
+ 1.265e-02,
+ 4.002e-03,
+ 1.265e-03,
+ -6.538e-01,
+ 3.010e-01,
+ 9.209e-01,
+ 9.922e-01,
+ 9.990e-01,
+ 1.000e00,
+ 1.000e00,
+ 1.000e00,
+ ],
+ ]
+ ],
+ dtype=np.float16,
+ )
result2 = pos_encoding(5, 16)
- assert np.allclose(result2, ans2, atol=1e-3), f"Test case 2 failed: {result2} != {ans2}"
-
+ assert np.allclose(result2, ans2, atol=1e-3), (
+ f"Test case 2 failed: {result2} != {ans2}"
+ )
# Test case 3:
ans3 = np.array([])
- assert np.allclose(pos_encoding(0,0), ans3, atol=1e-3), f"Test case 3 failed: {pos_encoding(0,0)} != {ans3}"
-
+ assert np.allclose(pos_encoding(0, 0), ans3, atol=1e-3), (
+ f"Test case 3 failed: {pos_encoding(0, 0)} != {ans3}"
+ )
# Test case 4:
ans4 = -1
- assert np.allclose(pos_encoding(2,-1), ans4, atol=1e-3), f"Test case 4 failed: {pos_encoding(2,-1)} != {ans4}"
-
+ assert np.allclose(pos_encoding(2, -1), ans4, atol=1e-3), (
+ f"Test case 4 failed: {pos_encoding(2, -1)} != {ans4}"
+ )
if __name__ == "__main__":
test_pos_encoding()
- print("All tests passed.")
\ No newline at end of file
+ print("All tests passed.")
diff --git a/old_repo/Problems/86_overfitting_underfitting/solution.py b/old_repo/Problems/86_overfitting_underfitting/solution.py
index 0b47ad1e..f3fc92c1 100644
--- a/old_repo/Problems/86_overfitting_underfitting/solution.py
+++ b/old_repo/Problems/86_overfitting_underfitting/solution.py
@@ -12,6 +12,7 @@ def model_fit_quality(training_accuracy: float, test_accuracy: float) -> int:
else:
return 0
+
def test_model_fit_quality() -> None:
# Test case 1: Overfitting
result1 = model_fit_quality(0.9, 0.6)
@@ -33,6 +34,7 @@ def test_model_fit_quality() -> None:
result5 = model_fit_quality(0.9, 0.7)
assert result5 == 0, f"Test case 5 failed: {result5} != 0"
+
if __name__ == "__main__":
test_model_fit_quality()
print("All tests passed.")
diff --git a/old_repo/Problems/87_adam_optimizer/solution.py b/old_repo/Problems/87_adam_optimizer/solution.py
index 2825378a..ff723988 100644
--- a/old_repo/Problems/87_adam_optimizer/solution.py
+++ b/old_repo/Problems/87_adam_optimizer/solution.py
@@ -1,6 +1,9 @@
import numpy as np
-def adam_optimizer(parameter, grad, m, v, t, learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8):
+
+def adam_optimizer(
+ parameter, grad, m, v, t, learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8
+):
"""
Update parameters using the Adam optimizer.
Adjusts the learning rate based on the moving averages of the gradient and squared gradient.
@@ -37,6 +40,7 @@ def adam_optimizer(parameter, grad, m, v, t, learning_rate=0.001, beta1=0.9, bet
return parameter, m, v
+
def test_adam_optimizer():
"""Test cases for the Adam optimizer implementation."""
# Test case 1: Scalar inputs
@@ -62,11 +66,14 @@ def test_adam_optimizer():
expected_m = np.array([0.01, 0.02])
expected_v = np.array([0.0001, 0.0004])
- assert np.allclose(new_param, expected_param), f"Unexpected parameter values: {new_param}"
+ assert np.allclose(new_param, expected_param), (
+ f"Unexpected parameter values: {new_param}"
+ )
assert np.allclose(new_m, expected_m), f"Unexpected m values: {new_m}"
assert np.allclose(new_v, expected_v), f"Unexpected v values: {new_v}"
print("All tests passed!")
+
if __name__ == "__main__":
test_adam_optimizer()
diff --git a/old_repo/Problems/88_GPT_2/solution.py b/old_repo/Problems/88_GPT_2/solution.py
index 6a77ca04..72ff7e3f 100644
--- a/old_repo/Problems/88_GPT_2/solution.py
+++ b/old_repo/Problems/88_GPT_2/solution.py
@@ -1,51 +1,66 @@
import numpy as np
+
np.random.seed(42)
+
+
def gelu(x):
return 0.5 * x * (1 + np.tanh(np.sqrt(2 / np.pi) * (x + 0.044715 * x**3)))
+
def softmax(x):
exp_x = np.exp(x - np.max(x, axis=-1, keepdims=True))
return exp_x / np.sum(exp_x, axis=-1, keepdims=True)
+
def layer_norm(x, g, b, eps=1e-5):
mean = np.mean(x, axis=-1, keepdims=True)
variance = np.var(x, axis=-1, keepdims=True)
return g * (x - mean) / np.sqrt(variance + eps) + b
+
def linear(x, w, b):
return x @ w + b
+
def ffn(x, c_fc, c_proj):
return linear(gelu(linear(x, **c_fc)), **c_proj)
+
def attention(q, k, v, mask):
return softmax(q @ k.T / np.sqrt(q.shape[-1]) + mask) @ v
+
def mha(x, c_attn, c_proj, n_head):
x = linear(x, **c_attn)
- qkv_heads = list(map(lambda x: np.split(x, n_head, axis=-1), np.split(x, 3, axis=-1)))
+ qkv_heads = list(
+ map(lambda x: np.split(x, n_head, axis=-1), np.split(x, 3, axis=-1))
+ )
causal_mask = (1 - np.tri(x.shape[0], dtype=x.dtype)) * -1e10
out_heads = [attention(q, k, v, causal_mask) for q, k, v in zip(*qkv_heads)]
x = linear(np.hstack(out_heads), **c_proj)
return x
+
def transformer_block(x, mlp, attn, ln_1, ln_2, n_head):
x = x + mha(layer_norm(x, **ln_1), **attn, n_head=n_head)
x = x + ffn(layer_norm(x, **ln_2), **mlp)
return x
+
def gpt2(inputs, wte, wpe, blocks, ln_f, n_head):
x = wte[inputs] + wpe[range(len(inputs))]
for block in blocks:
x = transformer_block(x, **block, n_head=n_head)
return layer_norm(x, **ln_f) @ wte.T
+
def generate(inputs, params, n_head, n_tokens_to_generate):
for _ in range(n_tokens_to_generate):
logits = gpt2(inputs, **params, n_head=n_head)
next_id = np.argmax(logits[-1])
inputs.append(int(next_id))
- return inputs[len(inputs) - n_tokens_to_generate:]
+ return inputs[len(inputs) - n_tokens_to_generate :]
+
def gen_text(prompt: str, n_tokens_to_generate: int = 40):
np.random.seed(42) # Set the random seed for reproducibility
@@ -56,23 +71,28 @@ def gen_text(prompt: str, n_tokens_to_generate: int = 40):
output_text = encoder.decode(output_ids)
return output_text
-def load_encoder_hparams_and_params(model_size: str = "124M", models_dir: str = "models"):
+
+def load_encoder_hparams_and_params(
+ model_size: str = "124M", models_dir: str = "models"
+):
class DummyBPE:
def __init__(self):
self.encoder_dict = {"hello": 1, "world": 2, "": 0}
def encode(self, text: str):
tokens = text.strip().split()
- return [self.encoder_dict.get(token, self.encoder_dict[""]) for token in tokens]
+ return [
+ self.encoder_dict.get(token, self.encoder_dict[""])
+ for token in tokens
+ ]
def decode(self, token_ids: list):
reversed_dict = {v: k for k, v in self.encoder_dict.items()}
- return " ".join([reversed_dict.get(tok_id, "") for tok_id in token_ids])
+ return " ".join(
+ [reversed_dict.get(tok_id, "") for tok_id in token_ids]
+ )
- hparams = {
- "n_ctx": 1024,
- "n_head": 12
- }
+ hparams = {"n_ctx": 1024, "n_head": 12}
params = {
"wte": np.random.rand(3, 10),
@@ -81,12 +101,13 @@ def decode(self, token_ids: list):
"ln_f": {
"g": np.ones(10),
"b": np.zeros(10),
- }
+ },
}
encoder = DummyBPE()
return encoder, hparams, params
+
def test_gen_text() -> None:
# Test case 1
result1 = gen_text("hello", n_tokens_to_generate=5)
@@ -103,6 +124,7 @@ def test_gen_text() -> None:
expected3 = "world world world"
assert result3 == expected3, f"Test case 3 failed: {result3} != {expected3}"
+
if __name__ == "__main__":
test_gen_text()
print("All tests passed.")
diff --git a/old_repo/Problems/8_Calculate_2x2_Matrix_Inverse/solution.py b/old_repo/Problems/8_Calculate_2x2_Matrix_Inverse/solution.py
index be97f0a8..5b7c3a16 100644
--- a/old_repo/Problems/8_Calculate_2x2_Matrix_Inverse/solution.py
+++ b/old_repo/Problems/8_Calculate_2x2_Matrix_Inverse/solution.py
@@ -3,9 +3,10 @@ def inverse_2x2(matrix: list[list[float]]) -> list[list[float]]:
determinant = a * d - b * c
if determinant == 0:
return None
- inverse = [[d/determinant, -b/determinant], [-c/determinant, a/determinant]]
+ inverse = [[d / determinant, -b / determinant], [-c / determinant, a / determinant]]
return inverse
+
def test_inverse_2x2() -> None:
# Test cases for inverse_2x2 function
@@ -17,6 +18,7 @@ def test_inverse_2x2() -> None:
matrix = [[2, 1], [6, 2]]
assert inverse_2x2(matrix) == [[-1.0, 0.5], [3.0, -1.0]]
+
if __name__ == "__main__":
test_inverse_2x2()
print("All inverse_2x2 tests passed.")
diff --git a/old_repo/Problems/8_Calculate_2x2_Matrix_Inverse/solution_2.py b/old_repo/Problems/8_Calculate_2x2_Matrix_Inverse/solution_2.py
index f8c78d01..c6e7227e 100644
--- a/old_repo/Problems/8_Calculate_2x2_Matrix_Inverse/solution_2.py
+++ b/old_repo/Problems/8_Calculate_2x2_Matrix_Inverse/solution_2.py
@@ -1,4 +1,5 @@
import numpy as np
+
def inverse_2x2(matrix: list[list[float]]) -> list[list[float]]:
- return np.linalg.inv(np.array(matrix))
\ No newline at end of file
+ return np.linalg.inv(np.array(matrix))
diff --git a/old_repo/Problems/94_multi_head_attention/solution.py b/old_repo/Problems/94_multi_head_attention/solution.py
index 454c6b6c..86d47598 100644
--- a/old_repo/Problems/94_multi_head_attention/solution.py
+++ b/old_repo/Problems/94_multi_head_attention/solution.py
@@ -1,14 +1,17 @@
import numpy as np
from typing import Tuple, List
-def compute_qkv(X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
+
+def compute_qkv(
+ X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray
+) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""
Compute the Query (Q), Key (K), and Value (V) matrices.
-
+
Args:
X: numpy array of shape (seq_len, d_model), input sequence
W_q, W_k, W_v: numpy arrays of shape (d_model, d_model), weight matrices for Q, K, and V
-
+
Returns:
Q, K, V: numpy arrays of shape (seq_len, d_model)
"""
@@ -17,106 +20,143 @@ def compute_qkv(X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray
V = np.dot(X, W_v) # Compute the Value matrix V
return Q, K, V
+
def self_attention(Q: np.ndarray, K: np.ndarray, V: np.ndarray) -> np.ndarray:
"""
Compute self-attention for a single head.
-
+
Args:
Q: numpy array of shape (seq_len, d_k), Query matrix
K: numpy array of shape (seq_len, d_k), Key matrix
V: numpy array of shape (seq_len, d_k), Value matrix
-
+
Returns:
attention_output: numpy array of shape (seq_len, d_k), output of the self-attention mechanism
"""
d_k = Q.shape[1] # Get the dimension of the keys
- scores = np.matmul(Q, K.T) / np.sqrt(d_k) # Compute scaled dot-product attention scores
- score_max = np.max(scores, axis=1, keepdims=True) # Find the maximum score for numerical stability
- attention_weights = np.exp(scores - score_max) / np.sum(np.exp(scores - score_max), axis=1, keepdims=True) # Compute softmax to get attention weights
- attention_output = np.matmul(attention_weights, V) # Compute the final attention output
+ scores = np.matmul(Q, K.T) / np.sqrt(
+ d_k
+ ) # Compute scaled dot-product attention scores
+ score_max = np.max(
+ scores, axis=1, keepdims=True
+ ) # Find the maximum score for numerical stability
+ attention_weights = np.exp(scores - score_max) / np.sum(
+ np.exp(scores - score_max), axis=1, keepdims=True
+ ) # Compute softmax to get attention weights
+ attention_output = np.matmul(
+ attention_weights, V
+ ) # Compute the final attention output
return attention_output
-def multi_head_attention(Q: np.ndarray, K: np.ndarray, V: np.ndarray, n_heads: int) -> Tuple[np.ndarray, List[np.ndarray]]:
+
+def multi_head_attention(
+ Q: np.ndarray, K: np.ndarray, V: np.ndarray, n_heads: int
+) -> Tuple[np.ndarray, List[np.ndarray]]:
"""
Compute multi-head attention.
-
+
Args:
Q, K, V: numpy arrays of shape (seq_len, d_model), Query, Key, and Value matrices
n_heads: int, number of attention heads
-
+
Returns:
attention_output: numpy array of shape (seq_len, d_model), final attention output
"""
d_model = Q.shape[1] # Get the model dimension
assert d_model % n_heads == 0 # Ensure d_model is divisible by n_heads
d_k = d_model // n_heads # Dimension for each head
-
+
# Reshape Q, K, V to separate heads
- Q_reshaped = Q.reshape(Q.shape[0], n_heads, d_k).transpose(1, 0, 2) # Reshape and transpose to (n_heads, seq_len, d_k)
- K_reshaped = K.reshape(K.shape[0], n_heads, d_k).transpose(1, 0, 2) # Reshape and transpose to (n_heads, seq_len, d_k)
- V_reshaped = V.reshape(V.shape[0], n_heads, d_k).transpose(1, 0, 2) # Reshape and transpose to (n_heads, seq_len, d_k)
+ Q_reshaped = Q.reshape(Q.shape[0], n_heads, d_k).transpose(
+ 1, 0, 2
+ ) # Reshape and transpose to (n_heads, seq_len, d_k)
+ K_reshaped = K.reshape(K.shape[0], n_heads, d_k).transpose(
+ 1, 0, 2
+ ) # Reshape and transpose to (n_heads, seq_len, d_k)
+ V_reshaped = V.reshape(V.shape[0], n_heads, d_k).transpose(
+ 1, 0, 2
+ ) # Reshape and transpose to (n_heads, seq_len, d_k)
# Compute attention scores for each head
attentions = [] # Store attention outputs for each head
for i in range(n_heads):
- attn = self_attention(Q_reshaped[i], K_reshaped[i], V_reshaped[i]) # Compute attention for the i-th head
+ attn = self_attention(
+ Q_reshaped[i], K_reshaped[i], V_reshaped[i]
+ ) # Compute attention for the i-th head
attentions.append(attn) # Collect attention output
-
+
# Concatenate all head outputs
- attention_output = np.concatenate(attentions, axis=-1) # Concatenate along the last axis (columns)
+ attention_output = np.concatenate(
+ attentions, axis=-1
+ ) # Concatenate along the last axis (columns)
return attention_output # Return the final attention output
+
def test_multi_head_attention():
# Test case 1: Basic functionality with computed Q, K, V
m, n = 6, 8
n_heads = 4
np.random.seed(42)
- X = np.arange(m*n).reshape(m,n)
+ X = np.arange(m * n).reshape(m, n)
X = np.random.permutation(X.flatten()).reshape(m, n)
- W_q = np.random.randint(0,4,size=(n,n))
- W_k = np.random.randint(0,5,size=(n,n))
- W_v = np.random.randint(0,6,size=(n,n))
+ W_q = np.random.randint(0, 4, size=(n, n))
+ W_k = np.random.randint(0, 5, size=(n, n))
+ W_v = np.random.randint(0, 6, size=(n, n))
Q, K, V = compute_qkv(X, W_q, W_k, W_v)
# test multi-head attention
actual_output = multi_head_attention(Q, K, V, n_heads)
- expected_output = np.array([[500, 463, 399, 495, 377, 450, 531, 362],
- [500, 463, 399, 495, 377, 450, 531, 362],
- [500, 463, 399, 495, 377, 450, 531, 362],
- [500, 463, 399, 495, 377, 450, 531, 362],
- [500, 463, 399, 495, 377, 450, 531, 362],
- [500, 463, 399, 495, 377, 450, 531, 362]])
- np.testing.assert_array_almost_equal(actual_output, expected_output, decimal=6, err_msg="Test case 1 failed")
+ expected_output = np.array(
+ [
+ [500, 463, 399, 495, 377, 450, 531, 362],
+ [500, 463, 399, 495, 377, 450, 531, 362],
+ [500, 463, 399, 495, 377, 450, 531, 362],
+ [500, 463, 399, 495, 377, 450, 531, 362],
+ [500, 463, 399, 495, 377, 450, 531, 362],
+ [500, 463, 399, 495, 377, 450, 531, 362],
+ ]
+ )
+ np.testing.assert_array_almost_equal(
+ actual_output, expected_output, decimal=6, err_msg="Test case 1 failed"
+ )
# test less number of heads
n_heads = 2
actual_output = multi_head_attention(Q, K, V, n_heads)
- expected_output = np.array([[547, 490, 399, 495, 377, 450, 531, 362],
- [547, 490, 399, 495, 377, 450, 531, 362],
- [547, 490, 399, 495, 377, 450, 531, 362],
- [547, 490, 399, 495, 377, 450, 531, 362],
- [547, 490, 399, 495, 377, 450, 531, 362],
- [547, 490, 399, 495, 377, 450, 531, 362]])
- np.testing.assert_array_almost_equal(actual_output, expected_output, decimal=6, err_msg="Test case 2 failed")
+ expected_output = np.array(
+ [
+ [547, 490, 399, 495, 377, 450, 531, 362],
+ [547, 490, 399, 495, 377, 450, 531, 362],
+ [547, 490, 399, 495, 377, 450, 531, 362],
+ [547, 490, 399, 495, 377, 450, 531, 362],
+ [547, 490, 399, 495, 377, 450, 531, 362],
+ [547, 490, 399, 495, 377, 450, 531, 362],
+ ]
+ )
+ np.testing.assert_array_almost_equal(
+ actual_output, expected_output, decimal=6, err_msg="Test case 2 failed"
+ )
# test small size input
m, n = 4, 4
n_heads = 2
np.random.seed(42)
- X = np.arange(m*n).reshape(m,n)
+ X = np.arange(m * n).reshape(m, n)
X = np.random.permutation(X.flatten()).reshape(m, n)
- W_q = np.random.randint(0,4,size=(n,n))
- W_k = np.random.randint(0,5,size=(n,n))
- W_v = np.random.randint(0,6,size=(n,n))
+ W_q = np.random.randint(0, 4, size=(n, n))
+ W_k = np.random.randint(0, 5, size=(n, n))
+ W_v = np.random.randint(0, 6, size=(n, n))
Q, K, V = compute_qkv(X, W_q, W_k, W_v)
actual_output = multi_head_attention(Q, K, V, n_heads)
- expected_output = np.array([[103, 109, 46, 99],
- [103, 109, 46, 99],
- [103, 109, 46, 99],
- [103, 109, 46, 99]])
- np.testing.assert_array_almost_equal(actual_output, expected_output, decimal=6, err_msg="Test case 3 failed")
+ expected_output = np.array(
+ [[103, 109, 46, 99], [103, 109, 46, 99], [103, 109, 46, 99], [103, 109, 46, 99]]
+ )
+ np.testing.assert_array_almost_equal(
+ actual_output, expected_output, decimal=6, err_msg="Test case 3 failed"
+ )
+
if __name__ == "__main__":
test_multi_head_attention()
- print("All multi-head-attention tests passed.")
\ No newline at end of file
+ print("All multi-head-attention tests passed.")
diff --git a/old_repo/Problems/95_phi_correlation_coefficient/solution.py b/old_repo/Problems/95_phi_correlation_coefficient/solution.py
index 6d536b6d..05f50708 100644
--- a/old_repo/Problems/95_phi_correlation_coefficient/solution.py
+++ b/old_repo/Problems/95_phi_correlation_coefficient/solution.py
@@ -1,33 +1,35 @@
-def phi_corr(x:list[int],y:list[int]):
- x1y1=0
- x1y0=0
- x0y1=0
- x0y0=0
+def phi_corr(x: list[int], y: list[int]):
+ x1y1 = 0
+ x1y0 = 0
+ x0y1 = 0
+ x0y0 = 0
for i in range(len(x)):
- if x[i]==1:
- if y[i]==1:
- x1y1+=1
+ if x[i] == 1:
+ if y[i] == 1:
+ x1y1 += 1
else:
- x1y0+=1
- if x[i]==0:
- if y[i]==1:
- x0y1+=1
+ x1y0 += 1
+ if x[i] == 0:
+ if y[i] == 1:
+ x0y1 += 1
else:
- x0y0+=1
+ x0y0 += 1
- dr=((x0y0+x0y1)*(x1y0+x1y1)*(x0y0+x1y0)*(x0y1+x1y1))**0.5
- nr=(x0y0*x1y1)-(x0y1*x1y0)
- phi=round(nr/dr,4)
+ dr = ((x0y0 + x0y1) * (x1y0 + x1y1) * (x0y0 + x1y0) * (x0y1 + x1y1)) ** 0.5
+ nr = (x0y0 * x1y1) - (x0y1 * x1y0)
+ phi = round(nr / dr, 4)
return phi
+
def test_phi_corr():
# Test case 1: z = 0
- assert phi_corr([1,1,0,0],[0,0,1,1]) == -1, "Test case 1 failed"
-
+ assert phi_corr([1, 1, 0, 0], [0, 0, 1, 1]) == -1, "Test case 1 failed"
+
# Test case 2: z = 1
- assert phi_corr([1,1,0,0],[1,0,1,1]) == -0.5774, "Test case 2 failed"
+ assert phi_corr([1, 1, 0, 0], [1, 0, 1, 1]) == -0.5774, "Test case 2 failed"
+
if __name__ == "__main__":
test_phi_corr()
diff --git a/old_repo/Problems/96_Hard_Sigmoid/solution.py b/old_repo/Problems/96_Hard_Sigmoid/solution.py
index 1c4ef36a..cbe8c756 100644
--- a/old_repo/Problems/96_Hard_Sigmoid/solution.py
+++ b/old_repo/Problems/96_Hard_Sigmoid/solution.py
@@ -1,10 +1,10 @@
def hard_sigmoid(x: float) -> float:
"""
Implements the Hard Sigmoid activation function.
-
+
Args:
x (float): Input value
-
+
Returns:
float: The Hard Sigmoid of the input
"""
@@ -15,22 +15,24 @@ def hard_sigmoid(x: float) -> float:
else:
return 0.2 * x + 0.5
+
def test_hard_sigmoid():
# Test case 1: x <= -2.5
assert hard_sigmoid(-3.0) == 0.0, "Test case 1 failed"
-
+
# Test case 2: x >= 2.5
assert hard_sigmoid(3.0) == 1.0, "Test case 2 failed"
-
+
# Test case 3: -2.5 < x < 2.5
assert abs(hard_sigmoid(0.0) - 0.5) < 1e-6, "Test case 3 failed"
assert abs(hard_sigmoid(1.0) - 0.7) < 1e-6, "Test case 4 failed"
assert abs(hard_sigmoid(-1.0) - 0.3) < 1e-6, "Test case 5 failed"
-
+
# Test boundary cases
assert abs(hard_sigmoid(2.5) - 1.0) < 1e-6, "Test case 6 failed"
assert abs(hard_sigmoid(-2.5) - 0.0) < 1e-6, "Test case 7 failed"
+
if __name__ == "__main__":
test_hard_sigmoid()
- print("All Hard Sigmoid tests passed.")
\ No newline at end of file
+ print("All Hard Sigmoid tests passed.")
diff --git a/old_repo/Problems/97_ELU/solution.py b/old_repo/Problems/97_ELU/solution.py
index 731ee693..bf3df24f 100644
--- a/old_repo/Problems/97_ELU/solution.py
+++ b/old_repo/Problems/97_ELU/solution.py
@@ -1,37 +1,40 @@
import math
+
def elu(x: float, alpha: float = 1.0) -> float:
"""
Compute the ELU activation function.
-
+
Args:
x (float): Input value
alpha (float): ELU parameter for negative values (default: 1.0)
-
+
Returns:
float: ELU activation value
"""
return x if x > 0 else alpha * (math.exp(x) - 1)
+
def test_elu():
# Test case 1: x = 0
assert abs(elu(0)) < 1e-10, "Test case 1 failed"
-
+
# Test case 2: positive input
assert abs(elu(1) - 1) < 1e-10, "Test case 2 failed"
-
+
# Test case 3: negative input
assert abs(elu(-1) - (-0.6321205588285577)) < 1e-10, "Test case 3 failed"
-
+
# Test case 4: different alpha value
assert abs(elu(-1, alpha=2.0) - (-1.2642411176571154)) < 1e-10, "Test case 4 failed"
-
+
# Test case 5: large positive input
assert abs(elu(5) - 5) < 1e-10, "Test case 5 failed"
-
+
# Test case 6: large negative input
assert abs(elu(-5) - (-0.9932620530009145)) < 1e-10, "Test case 6 failed"
+
if __name__ == "__main__":
test_elu()
- print("All ELU tests passed.")
\ No newline at end of file
+ print("All ELU tests passed.")
diff --git a/old_repo/Problems/98_PReLU/solution.py b/old_repo/Problems/98_PReLU/solution.py
index c9b30ece..9650f69d 100644
--- a/old_repo/Problems/98_PReLU/solution.py
+++ b/old_repo/Problems/98_PReLU/solution.py
@@ -1,35 +1,39 @@
def prelu(x: float, alpha: float = 0.25) -> float:
"""
Implements the PReLU (Parametric ReLU) activation function.
-
+
Args:
x: Input value
alpha: Slope parameter for negative values (default: 0.25)
-
+
Returns:
float: PReLU activation value
"""
return x if x > 0 else alpha * x
+
def test_prelu() -> None:
# Test positive input (should behave like regular ReLU)
assert prelu(2.0) == 2.0, "Test failed for positive input"
-
+
# Test zero input
assert prelu(0.0) == 0.0, "Test failed for zero input"
-
+
# Test negative input with default alpha
assert prelu(-2.0) == -0.5, "Test failed for negative input with default alpha"
-
+
# Test negative input with custom alpha
- assert prelu(-2.0, alpha=0.1) == -0.2, "Test failed for negative input with custom alpha"
-
+ assert prelu(-2.0, alpha=0.1) == -0.2, (
+ "Test failed for negative input with custom alpha"
+ )
+
# Test with alpha = 0 (behaves like ReLU)
assert prelu(-2.0, alpha=0.0) == 0.0, "Test failed for ReLU behavior"
-
+
# Test with alpha = 1 (behaves like linear function)
assert prelu(-2.0, alpha=1.0) == -2.0, "Test failed for linear behavior"
+
if __name__ == "__main__":
test_prelu()
print("All PReLU tests passed.")
diff --git a/old_repo/Problems/99_Softplus/solution.py b/old_repo/Problems/99_Softplus/solution.py
index 01ae35ad..38b92a14 100644
--- a/old_repo/Problems/99_Softplus/solution.py
+++ b/old_repo/Problems/99_Softplus/solution.py
@@ -1,12 +1,13 @@
import math
+
def softplus(x: float) -> float:
"""
Compute the softplus activation function.
-
+
Args:
x: Input value
-
+
Returns:
The softplus value: log(1 + e^x)
"""
@@ -16,25 +17,27 @@ def softplus(x: float) -> float:
# To prevent underflow for large negative values
if x < -100:
return 0.0
-
+
return math.log(1.0 + math.exp(x))
+
def test_softplus():
# Test case 1: x = 0
assert abs(softplus(0) - math.log(2)) < 1e-6, "Test case 1 failed"
-
+
# Test case 2: large positive number
assert abs(softplus(100) - 100) < 1e-6, "Test case 2 failed"
-
+
# Test case 3: large negative number
assert abs(softplus(-100)) < 1e-6, "Test case 3 failed"
-
+
# Test case 4: positive number
assert abs(softplus(2) - 2.1269280110429727) < 1e-6, "Test case 4 failed"
-
+
# Test case 5: negative number
assert abs(softplus(-2) - 0.12692801104297272) < 1e-6, "Test case 5 failed"
+
if __name__ == "__main__":
test_softplus()
- print("All Softplus tests passed.")
\ No newline at end of file
+ print("All Softplus tests passed.")
diff --git a/old_repo/Problems/9_matrixmul/solution.py b/old_repo/Problems/9_matrixmul/solution.py
index 0df31c2a..6e682e4e 100644
--- a/old_repo/Problems/9_matrixmul/solution.py
+++ b/old_repo/Problems/9_matrixmul/solution.py
@@ -1,7 +1,9 @@
-def matrixmul(a: list[list[int | float]], b: list[list[int | float]]) -> list[list[int | float]]:
+def matrixmul(
+ a: list[list[int | float]], b: list[list[int | float]]
+) -> list[list[int | float]]:
if len(a[0]) != len(b):
return -1
-
+
vals = []
for i in range(len(a)):
hold = []
@@ -9,12 +11,13 @@ def matrixmul(a: list[list[int | float]], b: list[list[int | float]]) -> list[li
val = 0
for k in range(len(b)):
val += a[i][k] * b[k][j]
-
+
hold.append(val)
vals.append(hold)
return vals
+
def test_matrixmul() -> None:
# Test cases for matrixmul function
@@ -33,6 +36,7 @@ def test_matrixmul() -> None:
b = [[0, 0, 1], [2, 4, 1], [1, 2, 3]]
assert matrixmul(a, b) == -1
+
if __name__ == "__main__":
test_matrixmul()
print("All matrixmul tests passed.")
diff --git a/old_repo/Problems/BM25/solution.py b/old_repo/Problems/BM25/solution.py
index 1ad78176..e2d9fd0e 100644
--- a/old_repo/Problems/BM25/solution.py
+++ b/old_repo/Problems/BM25/solution.py
@@ -1,89 +1,79 @@
import numpy as np
from collections import Counter
+
def calculate_bm25_scores(corpus, query, k1=1.5, b=0.75):
if not corpus or not query:
raise ValueError("Corpus and query cannot be empty")
-
+
doc_lengths = [len(doc) for doc in corpus]
avg_doc_length = np.mean(doc_lengths)
doc_term_counts = [Counter(doc) for doc in corpus]
doc_freqs = Counter()
for doc in corpus:
doc_freqs.update(set(doc))
-
+
scores = np.zeros(len(corpus))
N = len(corpus)
-
+
for term in query:
df = doc_freqs.get(term, 0) + 1
idf = np.log((N + 1) / df)
-
+
for idx, term_counts in enumerate(doc_term_counts):
if term not in term_counts:
continue
-
+
tf = term_counts[term]
doc_len_norm = 1 - b + b * (doc_lengths[idx] / avg_doc_length)
term_score = (tf * (k1 + 1)) / (tf + k1 * doc_len_norm)
scores[idx] += idf * term_score
-
+
return np.round(scores, 3)
+
def test_bm25_scores():
# Test case 1
- corpus = [
- ["the", "cat", "sat"],
- ["the", "dog", "ran"],
- ["the", "bird", "flew"]
- ]
+ corpus = [["the", "cat", "sat"], ["the", "dog", "ran"], ["the", "bird", "flew"]]
query = ["the", "cat"]
scores = calculate_bm25_scores(corpus, query)
expected_scores = np.array([2.283, 1.386, 1.386])
np.testing.assert_array_almost_equal(scores, expected_scores, decimal=3)
-
+
# Test case 2
try:
calculate_bm25_scores([], ["test"])
assert False, "Should raise error for empty corpus"
except ValueError:
pass
-
+
try:
calculate_bm25_scores([["test"]], [])
assert False, "Should raise error for empty query"
except ValueError:
pass
-
+
# Test case 3
- corpus = [
- ["the"] * 10,
- ["the"]
- ]
+ corpus = [["the"] * 10, ["the"]]
query = ["the"]
scores = calculate_bm25_scores(corpus, query)
assert scores[1] > scores[0], "Shorter document should score higher for same term"
-
+
# Test case 4
- corpus = [
- ["term"] * 10,
- ["term"] * 2
- ]
+ corpus = [["term"] * 10, ["term"] * 2]
query = ["term"]
scores = calculate_bm25_scores(corpus, query, k1=1.0)
expected_scores = np.array([0.579, 0.763])
np.testing.assert_array_almost_equal(scores, expected_scores, decimal=3)
-
+
# Test case 5
- corpus = [
- ["the"] * 10,
- ["the"]
- ]
+ corpus = [["the"] * 10, ["the"]]
query = ["the"]
scores = calculate_bm25_scores(corpus, query)
expected_scores = np.array([0.446, 0.893])
np.testing.assert_array_almost_equal(scores, expected_scores, decimal=3)
-
+
+
if __name__ == "__main__":
test_bm25_scores()
print("All test cases passed!")
diff --git a/old_repo/Problems/MAE/solution.py b/old_repo/Problems/MAE/solution.py
index d9bbfcf6..1baff5f1 100644
--- a/old_repo/Problems/MAE/solution.py
+++ b/old_repo/Problems/MAE/solution.py
@@ -1,13 +1,14 @@
import numpy as np
+
def mae(y_true, y_pred):
"""
Calculate Mean Absolute Error between two arrays.
-
+
Parameters:
y_true (numpy.ndarray): Array of true values
y_pred (numpy.ndarray): Array of predicted values
-
+
Returns:
float: Mean Absolute Error rounded to 3 decimal places
"""
@@ -15,9 +16,10 @@ def mae(y_true, y_pred):
raise ValueError("Arrays must have the same shape")
if y_true.size == 0:
raise ValueError("Arrays cannot be empty")
-
+
return round(np.mean(np.abs(y_true - y_pred)), 3)
+
def test_mae():
# Test Case 1: Normal Case
y_true1 = np.array([3, -0.5, 2, 7])
@@ -66,6 +68,7 @@ def test_mae():
expected7 = 1.333
assert mae(y_true7, y_pred7) == expected7, "Test Case 7 Failed"
+
if __name__ == "__main__":
test_mae()
- print("All Test Cases Passed!")
\ No newline at end of file
+ print("All Test Cases Passed!")
diff --git a/old_repo/Problems/interactive_learn/problem-10/notebook.py b/old_repo/Problems/interactive_learn/problem-10/notebook.py
index f3d70298..df3ac6db 100644
--- a/old_repo/Problems/interactive_learn/problem-10/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-10/notebook.py
@@ -79,9 +79,9 @@ def _(insights):
def _(mo):
# Key concepts accordion
-
- insights = mo.accordion({
- "🎯 Understanding Covariance": mo.md("""
+ insights = mo.accordion(
+ {
+ "🎯 Understanding Covariance": mo.md("""
**Key Concepts:**
1. **Variance**: Measures spread of a single variable
@@ -92,8 +92,7 @@ def _(mo):
4. **Interpretation**: Direction and strength of relationships
"""),
-
- "📊 Matrix Properties": mo.md("""
+ "📊 Matrix Properties": mo.md("""
The covariance matrix has important properties:
1. **Symmetry**: cov(X,Y) = cov(Y,X)
@@ -103,8 +102,9 @@ def _(mo):
3. **Off-diagonal Elements**: Show relationships
4. **Positive Semi-definite**: All eigenvalues ≥ 0
- """)
- })
+ """),
+ }
+ )
return (insights,)
@@ -128,11 +128,13 @@ def _(Matrix, mo):
matrix=[[1, 2, 3], [4, 5, 6]], # default example data
rows=2,
cols=3,
- step=0.1
+ step=0.1,
+ )
+ input_controls = mo.hstack(
+ [
+ data_matrix,
+ ]
)
- input_controls = mo.hstack([
- data_matrix,
- ])
return data_matrix, input_controls
@@ -158,48 +160,43 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
cov_matrix = np.cov(data)
# 3. visualization with covariance matrix
- df = pd.DataFrame({
- 'x': data[0],
- 'y': data[1]
- })
+ df = pd.DataFrame({"x": data[0], "y": data[1]})
scatter_fig = px.scatter(
df,
- x='x',
- y='y',
+ x="x",
+ y="y",
title="Variable Relationship Pattern",
- labels={'x': 'Variable 1', 'y': 'Variable 2'}
- ).update_layout(
- width=400,
- height=400,
- showlegend=False
- )
+ labels={"x": "Variable 1", "y": "Variable 2"},
+ ).update_layout(width=400, height=400, showlegend=False)
# appropriate trendline
coeffs = np.polyfit(data[0], data[1], 1)
x_range = np.linspace(min(data[0]), max(data[0]), 100)
scatter_fig.add_trace(
dict(
- type='scatter',
+ type="scatter",
x=x_range,
y=coeffs[0] * x_range + coeffs[1],
- mode='lines',
- line=dict(color='red', dash='dash'),
- name='Trend'
+ mode="lines",
+ line=dict(color="red", dash="dash"),
+ name="Trend",
)
)
# 4. results with relevant explanations
- results = mo.vstack([
- mo.md("## Understanding Your Data's Covariance"),
-
- # First row: Plot and Matrix
- mo.hstack([
- # scatter plot
- mo.vstack([scatter_fig]),
-
- # covariance matrix
- mo.vstack([
- mo.md(r"""
+ results = mo.vstack(
+ [
+ mo.md("## Understanding Your Data's Covariance"),
+ # First row: Plot and Matrix
+ mo.hstack(
+ [
+ # scatter plot
+ mo.vstack([scatter_fig]),
+ # covariance matrix
+ mo.vstack(
+ [
+ mo.md(
+ r"""
**Covariance Matrix:**
$$
@@ -208,18 +205,24 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
%.2f & %.2f
\end{pmatrix}
$$
- """ % (
- cov_matrix[0,0], cov_matrix[0,1],
- cov_matrix[1,0], cov_matrix[1,1]
- ))
- ])
- ]),
-
- # interpretation and insights side by side
- mo.hstack([
- # Left: Pattern Interpretation
- mo.callout(
- mo.md("""
+ """
+ % (
+ cov_matrix[0, 0],
+ cov_matrix[0, 1],
+ cov_matrix[1, 0],
+ cov_matrix[1, 1],
+ )
+ )
+ ]
+ ),
+ ]
+ ),
+ # interpretation and insights side by side
+ mo.hstack(
+ [
+ # Left: Pattern Interpretation
+ mo.callout(
+ mo.md("""
**Pattern Interpretation:**
@@ -235,20 +238,19 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
- Off-diagonal: Show relationship strength
"""),
- kind="info"
- ),
-
- # Right: Key Insights
- mo.callout(
- mo.md(f"""
+ kind="info",
+ ),
+ # Right: Key Insights
+ mo.callout(
+ mo.md(f"""
**Key Insights:**
- 1. Relationship: {"Positive" if cov_matrix[0,1] > 0 else "Negative" if cov_matrix[0,1] < 0 else "No"} covariance
+ 1. Relationship: {"Positive" if cov_matrix[0, 1] > 0 else "Negative" if cov_matrix[0, 1] < 0 else "No"} covariance
- 2. Strength: {"Strong" if abs(cov_matrix[0,1]) > 1 else "Moderate" if abs(cov_matrix[0,1]) > 0.5 else "Weak"}
+ 2. Strength: {"Strong" if abs(cov_matrix[0, 1]) > 1 else "Moderate" if abs(cov_matrix[0, 1]) > 0.5 else "Weak"}
- 3. Variances: ({cov_matrix[0,0]:.2f}, {cov_matrix[1,1]:.2f})
+ 3. Variances: ({cov_matrix[0, 0]:.2f}, {cov_matrix[1, 1]:.2f})
**Centered Data:**
```python
@@ -258,10 +260,13 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
Var2: {np.round(centered_data[1], 2)}
```
"""),
- kind="neutral"
- )
- ])
- ], justify='center')
+ kind="neutral",
+ ),
+ ]
+ ),
+ ],
+ justify="center",
+ )
except Exception as e:
results = mo.md(f"⚠️ Error: {str(e)}").callout(kind="danger")
@@ -289,9 +294,9 @@ def _(exercises):
def _(mo):
# Practice exercises
- exercises = mo.accordion({
-
- "🎯 Practice Exercises": mo.md("""
+ exercises = mo.accordion(
+ {
+ "🎯 Practice Exercises": mo.md("""
Try these examples to understand covariance better:
@@ -304,9 +309,7 @@ def _(mo):
What do you notice about the covariance matrices?
"""),
-
-
- "💡 Tips for Interpretation": mo.md("""
+ "💡 Tips for Interpretation": mo.md("""
- Large positive values: Strong positive relationship
@@ -316,9 +319,9 @@ def _(mo):
- Diagonal values: Spread of individual variables
- """)
-
- })
+ """),
+ }
+ )
return (exercises,)
@@ -331,9 +334,10 @@ def _(conclusion):
@app.cell(hide_code=True)
def _(mo):
# Conclusion
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've mastered the key concepts of covariance matrices:
@@ -344,12 +348,11 @@ def _(mo):
- The importance of centered data
"""),
- kind="success"
- ),
-
- mo.accordion({
-
- "🚀 Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "🚀 Next Steps": mo.md("""
1. Explore correlation matrices (normalized covariance)
2. Apply to real-world datasets
@@ -357,14 +360,17 @@ def _(mo):
4. Implement in machine learning projects
""")
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _():
import marimo as mo
+
return (mo,)
@@ -374,6 +380,7 @@ def _():
import plotly.express as px
from wigglystuff import Matrix
import pandas as pd
+
return Matrix, np, pd, px
diff --git a/old_repo/Problems/interactive_learn/problem-17/notebook.py b/old_repo/Problems/interactive_learn/problem-17/notebook.py
index 917799a6..6db4cc65 100644
--- a/old_repo/Problems/interactive_learn/problem-17/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-17/notebook.py
@@ -13,18 +13,20 @@
import marimo
__generated_with = "0.10.12"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
def _(mo):
mo.md(
- f"""# Understanding K-means Clustering
+ """# Understanding K-means Clustering
## Overview
K-means clustering is an [unsupervised learning algorithm](https://en.wikipedia.org/wiki/Unsupervised_learning) that partitions data into k distinct clusters. Each cluster is characterized by its centroid - the mean position of all points in that cluster.
"""
- )
+ )
return
@@ -36,8 +38,9 @@ def _(intro):
@app.cell(hide_code=True)
def _(mo):
- intro = mo.accordion({
- "🔄 Algorithm Steps": mo.md("""
+ intro = mo.accordion(
+ {
+ "🔄 Algorithm Steps": mo.md("""
1. **Initialization**: Randomly place k centroids in the feature space
2. **Assignment**: Assign each point to the nearest centroid using Euclidean distance (or a suitable distance metric like Manhattan (City Block distance), Minkowski distance, etc.):
@@ -48,7 +51,7 @@ def _(mo):
3. **Update**: Recompute centroids as the mean of assigned points
4. **Repeat**: Steps 2-3 until convergence
"""),
- "📐 Mathematical Formulation": mo.md("""
+ "📐 Mathematical Formulation": mo.md("""
The objective function (inertia) that K-means minimizes:
\\[
@@ -58,15 +61,16 @@ def _(mo):
where:
- $x_i$ is the i-th data point
- $\\mu_j$ is the centroid of cluster $j$
- """)
- })
+ """),
+ }
+ )
return (intro,)
@app.cell(hide_code=True)
def _(mo):
- mo.md(f"""
+ mo.md("""
## Implementation Details
This implementation uses:
@@ -86,7 +90,8 @@ def _(implementation):
@app.cell(hide_code=True)
def _(mo):
- implementation = mo.accordion({
+ implementation = mo.accordion(
+ {
"⚙️ Key Parameters": mo.md("""
- **n_clusters**: Number of clusters (k)
- **init**: Initialization method ('k-means++' or 'random')
@@ -94,16 +99,15 @@ def _(mo):
- **tol**: Tolerance for declaring convergence (default=1e-4)
- **n_init**: Number of initializations to try (default=10)
""")
- })
+ }
+ )
return (implementation,)
@app.cell
def _(mo):
method = mo.ui.dropdown(
- options=["Random", "Manual"],
- value="Random",
- label="Generation Method"
+ options=["Random", "Manual"], value="Random", label="Generation Method"
)
return (method,)
@@ -161,7 +165,6 @@ def _(mo):
def _(np, random, random_button):
random_button
-
def _generate_data():
n_clusters = random.randint(2, 10)
np.random.randn()
@@ -174,7 +177,6 @@ def _generate_data():
)
return np.vstack(points)
-
generated_points = _generate_data()
return (generated_points,)
@@ -479,6 +481,7 @@ def _(callout):
@app.cell
def _():
import marimo as mo
+
return (mo,)
@@ -491,6 +494,7 @@ def _():
from sklearn.cluster import KMeans
import plotly.express as px
from drawdata import ScatterWidget
+
return KMeans, ScatterWidget, np, pd, px, random
diff --git a/old_repo/Problems/interactive_learn/problem-22/notebook.py b/old_repo/Problems/interactive_learn/problem-22/notebook.py
index 5b05fef4..dbde9e0b 100644
--- a/old_repo/Problems/interactive_learn/problem-22/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-22/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.10"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -44,18 +46,14 @@ def _(mo):
- Differentiable everywhere
""")
- mo.accordion({"### Mathematical Definition" : value})
+ mo.accordion({"### Mathematical Definition": value})
return (value,)
@app.cell
def _(mo):
steepness = mo.ui.slider(
- start=0.1,
- stop=5.0,
- value=1.0,
- step=0.1,
- label="Steepness Factor (β)"
+ start=0.1, stop=5.0, value=1.0, step=0.1, label="Steepness Factor (β)"
)
_callout = mo.callout(
@@ -70,62 +68,62 @@ def _(mo):
- This affects how quickly the function transitions from 0 to 1
"""),
- kind="info"
+ kind="info",
)
x_range = mo.ui.range_slider(
- start=-10,
- stop=10,
- step=0.5,
- value=[-5, 5],
- label="X-axis Range"
+ start=-10, stop=10, step=0.5, value=[-5, 5], label="X-axis Range"
)
- controls = mo.vstack([
- mo.md("### Adjust Parameters"),
- mo.hstack([
- mo.vstack([
- steepness,
- mo.accordion({
- "About Steepness": _callout
- })
- ]),
- mo.vstack([
- x_range,
- mo.accordion({
- "About Range": "Adjust to see different regions of the S-shaped curve."
- })
- ])
- ])
- ])
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ mo.hstack(
+ [
+ mo.vstack([steepness, mo.accordion({"About Steepness": _callout})]),
+ mo.vstack(
+ [
+ x_range,
+ mo.accordion(
+ {
+ "About Range": "Adjust to see different regions of the S-shaped curve."
+ }
+ ),
+ ]
+ ),
+ ]
+ ),
+ ]
+ )
return controls, steepness, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-10,
- stop=10,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-10, stop=10, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their Sigmoid outputs (always between 0 and 1)."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {
+ "About Testing": "Enter specific values to see their Sigmoid outputs (always between 0 and 1)."
+ }
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(mo, steepness):
- formula_display = mo.vstack([
- mo.md(
- f"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ f"""
### Current Sigmoid Configuration
With steepness parameter $\\beta = {steepness.value:.2f}$, the current Sigmoid function is:
@@ -142,8 +140,9 @@ def _(mo, steepness):
- As z → -∞, σ(z) → 0
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -158,7 +157,9 @@ def _(mo, np, plt, steepness, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_sigmoid():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
y = 1 / (1 + np.exp(-steepness.value * x))
@@ -166,42 +167,56 @@ def plot_sigmoid():
plt.figure(figsize=(12, 7))
# Plot main sigmoid curve
- plt.plot(x, y,
- label=f'Sigmoid (β = {steepness.value:.2f})',
- color='blue',
- linewidth=2)
+ plt.plot(
+ x,
+ y,
+ label=f"Sigmoid (β = {steepness.value:.2f})",
+ color="blue",
+ linewidth=2,
+ )
# Plot horizontal asymptotes
- plt.axhline(y=1, color='gray', linestyle='--', alpha=0.5, label='Upper Asymptote (y=1)')
- plt.axhline(y=0, color='gray', linestyle='--', alpha=0.5, label='Lower Asymptote (y=0)')
+ plt.axhline(
+ y=1, color="gray", linestyle="--", alpha=0.5, label="Upper Asymptote (y=1)"
+ )
+ plt.axhline(
+ y=0, color="gray", linestyle="--", alpha=0.5, label="Lower Asymptote (y=0)"
+ )
# Plot midpoint
- plt.plot([0], [0.5], 'ro', label='Midpoint (0, 0.5)')
+ plt.plot([0], [0.5], "ro", label="Midpoint (0, 0.5)")
# Plot test point if within range
if x_range.value[0] <= test_input.value <= x_range.value[1]:
test_output = 1 / (1 + np.exp(-steepness.value * test_input.value))
- plt.scatter([test_input.value], [test_output],
- color='green', s=100,
- label=f'Test point: σ({test_input.value:.2f}) = {test_output:.4f}')
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="green",
+ s=100,
+ label=f"Test point: σ({test_input.value:.2f}) = {test_output:.4f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title(f'Sigmoid Function (β = {steepness.value:.2f})')
- plt.xlabel('Input (z)')
- plt.ylabel('Output (σ(z))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title(f"Sigmoid Function (β = {steepness.value:.2f})")
+ plt.xlabel("Input (z)")
+ plt.ylabel("Output (σ(z))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add vertical zero line
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
# Set y-axis limits with some padding
plt.ylim(-0.1, 1.1)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_sigmoid,)
@@ -225,9 +240,10 @@ def _(plot_sigmoid):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the Sigmoid function interactively. You've learned:
@@ -236,30 +252,33 @@ def _(mo):
- Why it's useful for binary classification
- Its symmetric properties around the midpoint
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Implementation:** Try implementing Sigmoid from scratch
2. **Compare:** Explore how it differs from tanh and softmax
3. **Practice:** Use it in a binary classification task
4. **Advanced:** Learn about vanishing gradient problems
"""),
- "🎯 Common Applications": mo.md("""
+ "🎯 Common Applications": mo.md("""
- Binary classification output layers
- Logistic regression
- Neural network hidden layers (historically)
- Probability estimation
- Feature scaling between 0 and 1
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the Sigmoid activation function. Hope this helps in your deep learning journey!
""")
return
@@ -274,6 +293,7 @@ def _(conclusion):
@app.cell
def _():
import marimo as mo
+
return (mo,)
@@ -281,6 +301,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-23/notebook.py b/old_repo/Problems/interactive_learn/problem-23/notebook.py
index ffc4d120..d83c5097 100644
--- a/old_repo/Problems/interactive_learn/problem-23/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-23/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.9"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -38,7 +40,7 @@ def _(mo):
where $i$ ranges from 1 to $n$, and each output $\text{softmax}(z_i)$ represents the probability of class $i$.
""")
- mo.accordion({"### Mathematical Definition" : value})
+ mo.accordion({"### Mathematical Definition": value})
return (value,)
@@ -46,19 +48,11 @@ def _(mo):
def _(mo):
# Interactive elements for formula exploration
temperature = mo.ui.slider(
- start=0.5,
- stop=5.0,
- value=1.0,
- step=0.1,
- label="Temperature (τ)"
+ start=0.5, stop=5.0, value=1.0, step=0.1, label="Temperature (τ)"
)
vector_size = mo.ui.slider(
- start=2,
- stop=5,
- value=3,
- step=1,
- label="Vector Size (n)"
+ start=2, stop=5, value=3, step=1, label="Vector Size (n)"
)
_callout = mo.callout(
@@ -71,47 +65,64 @@ def _(mo):
- Lower temperature amplifies differences between inputs
"""),
- kind="info"
+ kind="info",
+ )
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ mo.hstack(
+ [
+ mo.vstack(
+ [temperature, mo.accordion({"About Temperature": _callout})]
+ ),
+ mo.vstack(
+ [
+ vector_size,
+ mo.accordion(
+ {
+ "About Vector Size": "Change to see how Softmax handles different input dimensions."
+ }
+ ),
+ ]
+ ),
+ ]
+ ),
+ ]
)
- controls = mo.vstack([
- mo.md("### Adjust Parameters"),
- mo.hstack([
- mo.vstack([
- temperature,
- mo.accordion({
- "About Temperature": _callout
- })
- ]),
- mo.vstack([
- vector_size,
- mo.accordion({
- "About Vector Size": "Change to see how Softmax handles different input dimensions."
- })
- ])
- ])
- ])
return controls, temperature, vector_size
@app.cell
def _(array_nums, mo, x_range):
- input_controls = mo.vstack([
- mo.md("### Input Values"),
- mo.hstack([
- mo.vstack([
- x_range,
- mo.accordion({
- "About Range": "Adjust the range of input values shown in the plot."
- })
- ]),
- mo.vstack([
- array_nums,
- mo.accordion({
- "About Inputs": "Set specific input values to see their Softmax probabilities."
- })
- ])
- ])
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Input Values"),
+ mo.hstack(
+ [
+ mo.vstack(
+ [
+ x_range,
+ mo.accordion(
+ {
+ "About Range": "Adjust the range of input values shown in the plot."
+ }
+ ),
+ ]
+ ),
+ mo.vstack(
+ [
+ array_nums,
+ mo.accordion(
+ {
+ "About Inputs": "Set specific input values to see their Softmax probabilities."
+ }
+ ),
+ ]
+ ),
+ ]
+ ),
+ ]
+ )
return (input_controls,)
@@ -123,9 +134,10 @@ def _(formula_display):
@app.cell
def _(mo, temperature, vector_size):
- formula_display = mo.vstack([
- mo.md(
- f"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ f"""
### Temperature-Scaled Softmax
With temperature parameter $\\tau = {temperature.value:.1f}$ and vector size $n = {vector_size.value}$,
@@ -139,8 +151,9 @@ def _(mo, temperature, vector_size):
- Lower temperature ($\\tau < 1$) makes the distribution more peaked
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -148,22 +161,12 @@ def _(mo, temperature, vector_size):
def _(mo, vector_size):
# Input range control
x_range = mo.ui.range_slider(
- start=-10,
- stop=10,
- step=0.5,
- value=[-5, 5],
- label="X-axis Range"
+ start=-10, stop=10, step=0.5, value=[-5, 5], label="X-axis Range"
)
# Array of number inputs dynamically based on vector_size
input_numbers = [
- mo.ui.number(
- value=1.0,
- start=-10,
- stop=10,
- step=0.1,
- label=f"Value {i+1}"
- )
+ mo.ui.number(value=1.0, start=-10, stop=10, step=0.1, label=f"Value {i + 1}")
for i in range(vector_size.value)
]
@@ -175,7 +178,7 @@ def _(mo, vector_size):
### Sample Input Values
Current vector: {inputs}
"""),
- {"inputs": array_nums}
+ {"inputs": array_nums},
)
return array_nums, input_numbers, input_values, x_range
@@ -193,7 +196,9 @@ def _(array_nums, mo, np, plt, temperature, vector_size, x_range):
def plot_softmax():
# Validate x_range
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
scores = np.vstack([x] + [np.zeros_like(x)] * (vector_size.value - 1))
@@ -205,33 +210,36 @@ def plot_softmax():
plt.figure(figsize=(12, 7))
for i in range(vector_size.value):
- plt.plot(x, softmax_values[i],
- label=f'Class {i+1}',
- linewidth=2)
+ plt.plot(x, softmax_values[i], label=f"Class {i + 1}", linewidth=2)
# Plot current input values
input_array = np.array([num.value for num in array_nums.elements])
if len(input_array) >= vector_size.value:
- exp_inputs = np.exp(input_array[:vector_size.value] / temperature.value)
+ exp_inputs = np.exp(input_array[: vector_size.value] / temperature.value)
softmax_inputs = exp_inputs / np.sum(exp_inputs)
- plt.scatter(input_array[:vector_size.value],
- softmax_inputs,
- c='red',
- s=100,
- label='Current inputs')
+ plt.scatter(
+ input_array[: vector_size.value],
+ softmax_inputs,
+ c="red",
+ s=100,
+ label="Current inputs",
+ )
plt.grid(True, alpha=0.3)
- plt.title(f'Softmax Function (τ = {temperature.value:.1f})')
- plt.xlabel('Input values (z)')
- plt.ylabel('Softmax probabilities')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title(f"Softmax Function (τ = {temperature.value:.1f})")
+ plt.xlabel("Input values (z)")
+ plt.ylabel("Softmax probabilities")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
plt.ylim(-0.1, 1.1)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_softmax,)
@@ -255,9 +263,10 @@ def _(plot_softmax):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the Softmax function interactively. You've learned:
@@ -267,30 +276,33 @@ def _(mo):
- How different input values affect the output distribution
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Problem solving:** Head over to the Problem Decsription tab and start solving the problem!
2. **Apply**: Think about where you might use Softmax in your own projects
3. **Explore**: Learn about variants like Sparsemax and Gumbel-Softmax
4. **Practice**: Implement Softmax from scratch in your preferred framework
"""),
- " 🎯 Common Applications": mo.md("""
+ " 🎯 Common Applications": mo.md("""
- Classification layers in neural networks
- Attention mechanisms in transformers
- Policy networks in reinforcement learning
- Knowledge distillation
- Temperature scaling for model calibration
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the Softmax activation function. Hope this resource proves valuable in your exploration of this important topic.
""")
return
@@ -307,6 +319,7 @@ def _():
import marimo as mo
import numpy as np
import matplotlib.pyplot as plt
+
return mo, np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-24/notebook.py b/old_repo/Problems/interactive_learn/problem-24/notebook.py
index afd62677..cc0b4a9f 100644
--- a/old_repo/Problems/interactive_learn/problem-24/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-24/notebook.py
@@ -65,8 +65,9 @@ def _(insights):
@app.cell(hide_code=True)
def _(mo):
# insights accordion
- insights = mo.accordion({
- "🧠 Understanding the Components": mo.md("""
+ insights = mo.accordion(
+ {
+ "🧠 Understanding the Components": mo.md("""
**Key Concepts:**
1. **Input Features**: Multiple numerical values representing different aspects of the data
@@ -74,16 +75,16 @@ def _(mo):
3. **Bias**: Offset term that helps the model fit the data better
4. **Sigmoid Function**: Squashes input to probability between 0 and 1
"""),
-
- "📊 Model Behavior": mo.md("""
+ "📊 Model Behavior": mo.md("""
The neuron's behavior is influenced by:
1. **Feature Values**: Input data characteristics
2. **Weight Magnitudes**: Control feature influence
3. **Bias Term**: Shifts the decision boundary
4. **Sigmoid Activation**: Creates non-linear output
- """)
- })
+ """),
+ }
+ )
return (insights,)
@@ -96,38 +97,39 @@ def _(feature_inputs):
@app.cell(hide_code=True)
def _(mo):
# input controls: features
- features_1 = mo.ui.array([
- mo.ui.number(value=0.5, label="Feature 1", step=0.1),
- mo.ui.number(value=1.0, label="Feature 2", step=0.1)
- ])
-
- features_2 = mo.ui.array([
- mo.ui.number(value=-1.5, label="Feature 1", step=0.1),
- mo.ui.number(value=-2.0, label="Feature 2", step=0.1)
- ])
-
- features_3 = mo.ui.array([
- mo.ui.number(value=2.0, label="Feature 1", step=0.1),
- mo.ui.number(value=1.5, label="Feature 2", step=0.1)
- ])
-
- feature_inputs = mo.vstack([
- mo.md("### Input Features"),
- mo.hstack([
- mo.vstack([
- mo.md("**Example 1**"),
- features_1
- ]),
- mo.vstack([
- mo.md("**Example 2**"),
- features_2
- ]),
- mo.vstack([
- mo.md("**Example 3**"),
- features_3
- ])
- ])
- ])
+ features_1 = mo.ui.array(
+ [
+ mo.ui.number(value=0.5, label="Feature 1", step=0.1),
+ mo.ui.number(value=1.0, label="Feature 2", step=0.1),
+ ]
+ )
+
+ features_2 = mo.ui.array(
+ [
+ mo.ui.number(value=-1.5, label="Feature 1", step=0.1),
+ mo.ui.number(value=-2.0, label="Feature 2", step=0.1),
+ ]
+ )
+
+ features_3 = mo.ui.array(
+ [
+ mo.ui.number(value=2.0, label="Feature 1", step=0.1),
+ mo.ui.number(value=1.5, label="Feature 2", step=0.1),
+ ]
+ )
+
+ feature_inputs = mo.vstack(
+ [
+ mo.md("### Input Features"),
+ mo.hstack(
+ [
+ mo.vstack([mo.md("**Example 1**"), features_1]),
+ mo.vstack([mo.md("**Example 2**"), features_2]),
+ mo.vstack([mo.md("**Example 3**"), features_3]),
+ ]
+ ),
+ ]
+ )
return feature_inputs, features_1, features_2, features_3
@@ -140,29 +142,18 @@ def _(weight_controls):
@app.cell(hide_code=True)
def _(mo):
# Weight and bias (wandb) controls
- w1 = mo.ui.number(
- value=0.7,
- label="Weight 1",
- step=0.1
- )
+ w1 = mo.ui.number(value=0.7, label="Weight 1", step=0.1)
- w2 = mo.ui.number(
- value=-0.4,
- label="Weight 2",
- step=0.1
- )
+ w2 = mo.ui.number(value=-0.4, label="Weight 2", step=0.1)
- bias = mo.ui.number(
- value=-0.1,
- label="Bias",
- step=0.1
- )
+ bias = mo.ui.number(value=-0.1, label="Bias", step=0.1)
- weight_controls = mo.vstack([
- mo.md("### Model Parameters"),
- mo.hstack([w1, w2, bias]),
- mo.callout(
- mo.md("""
+ weight_controls = mo.vstack(
+ [
+ mo.md("### Model Parameters"),
+ mo.hstack([w1, w2, bias]),
+ mo.callout(
+ mo.md("""
Adjust weights and bias to see how they affect the neuron's output:
- Positive weights increase output for positive features
@@ -171,9 +162,10 @@ def _(mo):
- Bias shifts the decision boundary
"""),
- kind="info"
- )
- ])
+ kind="info",
+ ),
+ ]
+ )
return bias, w1, w2, weight_controls
@@ -208,7 +200,7 @@ def _(
w2,
):
def sigmoid(z):
- return 1 / (1 + np.exp(-z))
+ return 1 / (1 + np.exp(-z))
def compute_neuron_output(features, weights, bias):
z = np.dot(features, weights) + bias
@@ -226,7 +218,7 @@ def compute_neuron_output(features, weights, bias):
feature_vectors = [
[f.value for f in features_1.elements],
[f.value for f in features_2.elements],
- [f.value for f in features_3.elements]
+ [f.value for f in features_3.elements],
]
predictions = []
@@ -238,18 +230,22 @@ def compute_neuron_output(features, weights, bias):
mse = round(np.mean((np.array(predictions) - true_labels) ** 2), 4)
results = predictions
- results_display = mo.vstack([
- mo.md(f"### Results"),
- mo.md(f"**Predictions:** {results}"),
- mo.md(f"**Mean Squared Error:** {mse}"),
- mo.accordion({
- "🔍 Understanding the Results": mo.md(f"""
+ results_display = mo.vstack(
+ [
+ mo.md("### Results"),
+ mo.md(f"**Predictions:** {results}"),
+ mo.md(f"**Mean Squared Error:** {mse}"),
+ mo.accordion(
+ {
+ "🔍 Understanding the Results": mo.md("""
- Predictions close to 0 indicate class 0
- Predictions close to 1 indicate class 1
- Lower MSE means better model performance
""")
- })
- ])
+ }
+ ),
+ ]
+ )
return (
compute_neuron_output,
feature_vectors,
@@ -289,49 +285,43 @@ def plot_decision_boundary():
# Z values calculated using the neuron model
Z = 1 / (1 + np.exp(-(w1.value * X + w2.value * Y + bias.value)))
- df = pd.DataFrame({
- 'x': X.flatten(),
- 'y': Y.flatten(),
- 'z': Z.flatten()
- })
+ df = pd.DataFrame({"x": X.flatten(), "y": Y.flatten(), "z": Z.flatten()})
# Plot decision boundary using density contour
fig = px.density_contour(
- df, x='x', y='y', z='z',
- title='Decision Boundary Visualization',
- labels={'x': 'Feature 1', 'y': 'Feature 2', 'z': 'Probability'}
+ df,
+ x="x",
+ y="y",
+ z="z",
+ title="Decision Boundary Visualization",
+ labels={"x": "Feature 1", "y": "Feature 2", "z": "Probability"},
)
# Add scatter points for input examples
- feature_points = pd.DataFrame({
- 'Feature 1': [
- features_1.elements[0].value,
- features_2.elements[0].value,
- features_3.elements[0].value
- ],
- 'Feature 2': [
- features_1.elements[1].value,
- features_2.elements[1].value,
- features_3.elements[1].value
- ],
- 'Label': ['Example 1', 'Example 2', 'Example 3']
- })
-
- scatter = px.scatter(
- feature_points,
- x='Feature 1',
- y='Feature 2',
- text='Label'
+ feature_points = pd.DataFrame(
+ {
+ "Feature 1": [
+ features_1.elements[0].value,
+ features_2.elements[0].value,
+ features_3.elements[0].value,
+ ],
+ "Feature 2": [
+ features_1.elements[1].value,
+ features_2.elements[1].value,
+ features_3.elements[1].value,
+ ],
+ "Label": ["Example 1", "Example 2", "Example 3"],
+ }
)
+ scatter = px.scatter(feature_points, x="Feature 1", y="Feature 2", text="Label")
+
for trace in scatter.data:
fig.add_trace(trace)
- fig.update_layout(
- width=800,
- height=600
- )
+ fig.update_layout(width=800, height=600)
return fig
+
return (plot_decision_boundary,)
@@ -353,9 +343,10 @@ def _(conclusion):
@app.cell(hide_code=True)
def _(mo):
# Conclusion and next steps
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the single neuron model with sigmoid activation. You've learned:
@@ -363,29 +354,33 @@ def _(mo):
- How sigmoid activation converts linear combinations to probabilities
- How to evaluate performance using MSE
"""),
- kind="success"
- ),
- mo.accordion({
- "🎯 Applications": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "🎯 Applications": mo.md("""
- Binary classification tasks
- Feature importance analysis
- Basic pattern recognition
- Building blocks for larger neural networks
"""),
- "🚀 Next Steps": mo.md("""
+ "🚀 Next Steps": mo.md("""
1. Implement the neuron in a real project
2. Explore other activation functions
3. Add more features to handle complex patterns
4. Learn about gradient descent for training
- """)
- })
- ])
+ """),
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _():
import marimo as mo
+
return (mo,)
@@ -394,6 +389,7 @@ def _():
import numpy as np
import pandas as pd
import plotly.express as px
+
return np, pd, px
diff --git a/old_repo/Problems/interactive_learn/problem-4/notebook.py b/old_repo/Problems/interactive_learn/problem-4/notebook.py
index f5742f6c..2d622504 100644
--- a/old_repo/Problems/interactive_learn/problem-4/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-4/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.9"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -43,7 +45,7 @@ def _(column_content, mo, row_content):
@app.cell(hide_code=True)
def _(mo):
row_content = mo.md(
- r'''
+ r"""
For a row \(i\), the sum is:
\[
@@ -55,11 +57,11 @@ def _(mo):
\[
\overline{R}_i = \frac{R_i}{n}
\]
- '''
+ """
)
column_content = mo.md(
- r'''
+ r"""
For a column \(j\), the sum is:
\[
@@ -71,7 +73,7 @@ def _(mo):
\[
\overline{C}_j = \frac{C_j}{m}
\]
- '''
+ """
)
return column_content, row_content
@@ -110,17 +112,13 @@ def calculate_stats(matrix, dimension):
if dimension == "row":
sums = np.sum(arr, axis=1)
means = np.mean(arr, axis=1)
- labels = [f"Row {i+1}" for i in range(arr.shape[0])]
+ labels = [f"Row {i + 1}" for i in range(arr.shape[0])]
else:
sums = np.sum(arr, axis=0)
means = np.mean(arr, axis=0)
- labels = [f"Column {i+1}" for i in range(arr.shape[1])]
+ labels = [f"Column {i + 1}" for i in range(arr.shape[1])]
- return {
- "Dimension": labels,
- "Sum": list(sums),
- "Mean": list(means)
- }
+ return {"Dimension": labels, "Sum": list(sums), "Mean": list(means)}
# Calculate both row and column statistics
row_stats = calculate_stats(matrix.matrix, "row")
@@ -132,7 +130,6 @@ def calculate_stats(matrix, dimension):
def step_by_step_display(col_stats, matrix, mo, np, row_stats):
arr = np.array(matrix.matrix)
-
def generate_row_steps():
steps = ""
for i in range(arr.shape[0]):
@@ -143,12 +140,11 @@ def generate_row_steps():
steps += rf"""
\[
- \text{{Row {i+1}}}: {sum_expr} = {sum_val:.1f} \text{{ (sum)}}, \frac{{{sum_val:.1f}}}{{{len(row)}}} = {mean_val:.1f} \text{{ (mean)}}
+ \text{{Row {i + 1}}}: {sum_expr} = {sum_val:.1f} \text{{ (sum)}}, \frac{{{sum_val:.1f}}}{{{len(row)}}} = {mean_val:.1f} \text{{ (mean)}}
\]
"""
return mo.md(steps)
-
def generate_column_steps():
steps = ""
for j in range(arr.shape[1]):
@@ -159,12 +155,11 @@ def generate_column_steps():
steps += rf"""
\[
- \text{{Column {j+1}}}: {sum_expr} = {sum_val:.1f} \text{{ (sum)}}, \frac{{{sum_val:.1f}}}{{{len(col)}}} = {mean_val:.1f} \text{{ (mean)}}
+ \text{{Column {j + 1}}}: {sum_expr} = {sum_val:.1f} \text{{ (sum)}}, \frac{{{sum_val:.1f}}}{{{len(col)}}} = {mean_val:.1f} \text{{ (mean)}}
\]
"""
return mo.md(steps)
-
# Create tabs for row and column calculations
tabs_content = {
"📊 Row Operations": mo.vstack(
@@ -207,6 +202,7 @@ def _(mo):
@app.cell
def _():
import marimo as mo
+
return (mo,)
@@ -214,6 +210,7 @@ def _():
def _():
import numpy as np
from wigglystuff import Matrix
+
return Matrix, np
diff --git a/old_repo/Problems/interactive_learn/problem-42/notebook.py b/old_repo/Problems/interactive_learn/problem-42/notebook.py
index 823308f2..91219224 100644
--- a/old_repo/Problems/interactive_learn/problem-42/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-42/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.12"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -46,11 +48,7 @@ def _(mo):
@app.cell
def _(mo):
x_range = mo.ui.range_slider(
- start=-10,
- stop=10,
- step=0.5,
- value=[-5, 5],
- label="X-axis Range"
+ start=-10, stop=10, step=0.5, value=[-5, 5], label="X-axis Range"
)
_callout = mo.callout(
@@ -63,65 +61,60 @@ def _(mo):
- Positive inputs remain unchanged
- This creates non-linearity in neural networks
"""),
- kind="info"
+ kind="info",
)
- controls = mo.vstack([
- mo.md("### Adjust Parameters"),
- mo.hstack([
- mo.vstack([
- x_range,
- mo.accordion({
- "About Range": _callout
- })
- ])
- ])
- ])
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ mo.hstack([mo.vstack([x_range, mo.accordion({"About Range": _callout})])]),
+ ]
+ )
return controls, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-10,
- stop=10,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-10, stop=10, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their ReLU outputs."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {"About Testing": "Enter specific values to see their ReLU outputs."}
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(mo):
- formula_display = mo.vstack([
- mo.md(
- f"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ """
### Current ReLU Configuration
The ReLU function is defined as:
\[
- f(z) = \max(0, z) = \\begin{{cases}}
- z & \\text{{if }} z > 0 \\\\
- 0 & \\text{{if }} z \\leq 0
- \\end{{cases}}
+ f(z) = \max(0, z) = \\begin{cases}
+ z & \\text{if } z > 0 \\\\
+ 0 & \\text{if } z \\leq 0
+ \\end{cases}
\]
- For positive inputs: output = input
- For negative inputs: output = 0
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -136,7 +129,9 @@ def _(mo, np, plt, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_relu():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
y = np.maximum(0, x)
@@ -145,40 +140,53 @@ def plot_relu():
# Plot -ve region
mask_neg = x <= 0
- plt.plot(x[mask_neg], y[mask_neg],
- label='Zero region (ReLU = 0)',
- color='red',
- linewidth=2)
+ plt.plot(
+ x[mask_neg],
+ y[mask_neg],
+ label="Zero region (ReLU = 0)",
+ color="red",
+ linewidth=2,
+ )
# Plot +ve region
mask_pos = x > 0
- plt.plot(x[mask_pos], y[mask_pos],
- label='Linear region (ReLU = x)',
- color='blue',
- linewidth=2)
+ plt.plot(
+ x[mask_pos],
+ y[mask_pos],
+ label="Linear region (ReLU = x)",
+ color="blue",
+ linewidth=2,
+ )
# Plot test point if within range (expand slider if it doesn't appear)
if x_range.value[0] <= test_input.value <= x_range.value[1]:
test_output = max(0, test_input.value)
- plt.scatter([test_input.value], [test_output],
- color='green', s=100,
- label=f'Test point: ReLU({test_input.value:.2f}) = {test_output:.2f}')
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="green",
+ s=100,
+ label=f"Test point: ReLU({test_input.value:.2f}) = {test_output:.2f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title('ReLU Function')
- plt.xlabel('Input (z)')
- plt.ylabel('Output (ReLU(z))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title("ReLU Function")
+ plt.xlabel("Input (z)")
+ plt.ylabel("Output (ReLU(z))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add zero lines
- plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
+ plt.axhline(y=0, color="k", linestyle="--", alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_relu,)
@@ -202,9 +210,10 @@ def _(plot_relu):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the ReLU function interactively. You've learned:
@@ -213,30 +222,33 @@ def _(mo):
- The relationship between input values and their corresponding outputs
- How to test specific input values and observe their ReLU transformations
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Implementation:** Try implementing ReLU from scratch
2. **Compare:** Explore how it differs from other activation functions
3. **Experiment:** Test ReLU in a simple neural network
4. **Advanced:** Learn about variants like Leaky ReLU and ELU
"""),
- "🎯 Common Applications": mo.md("""
+ "🎯 Common Applications": mo.md("""
- Deep neural networks
- Convolutional neural networks (CNNs)
- Hidden layers in deep learning
- Feature extraction
- Modern computer vision models
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the ReLU activation function. Hope this helps in your deep learning journey!
""")
return
@@ -251,6 +263,7 @@ def _(conclusion):
@app.cell(hide_code=True)
def _():
import marimo as mo
+
return (mo,)
@@ -258,6 +271,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-43/notebook.py b/old_repo/Problems/interactive_learn/problem-43/notebook.py
index 0eab24c7..5b875dd1 100644
--- a/old_repo/Problems/interactive_learn/problem-43/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-43/notebook.py
@@ -56,8 +56,9 @@ def _(mo):
@app.cell(hide_code=True)
def _(mo):
- insights = mo.accordion({
- "🔍 Key Components": mo.md("""
+ insights = mo.accordion(
+ {
+ "🔍 Key Components": mo.md("""
**1. Mean Squared Error (MSE)**
- Measures prediction accuracy
- Penalizes larger errors more heavily
@@ -68,53 +69,38 @@ def _(mo):
- Prevents coefficient values from becoming too large
- Helps prevent overfitting
"""),
-
- "⚙️ Role of Alpha (λ)": mo.md("""
+ "⚙️ Role of Alpha (λ)": mo.md("""
The regularization parameter α controls:
1. α = 0: Equivalent to standard linear regression
2. Small α: Slight regularization effect
3. Large α: Strong regularization, coefficients approach zero
"""),
-
- "🧮 Coefficient Shrinkage": mo.md("""
+ "🧮 Coefficient Shrinkage": mo.md("""
Ridge regression shrinks coefficients by adding a penalty proportional to their squared magnitude:
- Larger coefficients incur higher penalties
- The penalty applies to all coefficients equally
- Unlike Lasso, Ridge typically keeps all features but with reduced magnitudes
- Mathematically, Ridge finds the minimum of: ||y - Xβ||² + λ||β||²
- """)
- })
+ """),
+ }
+ )
return (insights,)
@app.cell(hide_code=True)
def _(mo):
# controls for sample data
- sample_size = mo.ui.slider(
- start=4,
- stop=20,
- value=10,
- step=1,
- label="Sample Size"
- )
+ sample_size = mo.ui.slider(start=4, stop=20, value=10, step=1, label="Sample Size")
alpha = mo.ui.number(
- value=0.1,
- start=0,
- stop=10,
- step=0.1,
- label="Regularization Parameter (α)"
+ value=0.1, start=0, stop=10, step=0.1, label="Regularization Parameter (α)"
)
- controls = mo.hstack([
- mo.vstack([
- mo.md("### Data Parameters"),
- sample_size,
- alpha
- ])
- ])
+ controls = mo.hstack(
+ [mo.vstack([mo.md("### Data Parameters"), sample_size, alpha])]
+ )
return alpha, controls, sample_size
@@ -132,18 +118,23 @@ def _(mo):
@app.cell
def _(mo):
- coefficient_inputs = mo.ui.array([
- mo.ui.number(value=0.2, label="Coefficient 1", step=0.1),
- mo.ui.number(value=2.0, label="Coefficient 2", step=0.1)
- ], label="Model Coefficients")
-
- coefficient_section = mo.hstack([
- coefficient_inputs,
- mo.callout(
- mo.md("Adjust coefficients to see how they affect the loss value."),
- kind="warn"
- )
- ])
+ coefficient_inputs = mo.ui.array(
+ [
+ mo.ui.number(value=0.2, label="Coefficient 1", step=0.1),
+ mo.ui.number(value=2.0, label="Coefficient 2", step=0.1),
+ ],
+ label="Model Coefficients",
+ )
+
+ coefficient_section = mo.hstack(
+ [
+ coefficient_inputs,
+ mo.callout(
+ mo.md("Adjust coefficients to see how they affect the loss value."),
+ kind="warn",
+ ),
+ ]
+ )
return coefficient_inputs, coefficient_section
@@ -167,16 +158,19 @@ def ridge_loss(X, w, y_true, alpha):
Returns:
float: Ridge loss value
"""
- n_samples = X.shape[0]
+ X.shape[0]
# Check dimension compatibility
if X.shape[1] != len(w):
- raise ValueError(f"Coefficient count ({len(w)}) must match feature count ({X.shape[1]})")
+ raise ValueError(
+ f"Coefficient count ({len(w)}) must match feature count ({X.shape[1]})"
+ )
y_pred = X @ w
mse = np.mean((y_true - y_pred) ** 2)
- regularization = alpha * np.sum(w ** 2)
+ regularization = alpha * np.sum(w**2)
return mse + regularization
+
return (ridge_loss,)
@@ -189,10 +183,9 @@ def _(mo):
@app.cell
def _(alpha, coefficient_inputs, mo, np, ridge_loss, sample_size):
# Generate sample data
- X = np.column_stack([
- np.arange(1, sample_size.value + 1),
- np.ones(sample_size.value)
- ])
+ X = np.column_stack(
+ [np.arange(1, sample_size.value + 1), np.ones(sample_size.value)]
+ )
y_true = np.arange(2, sample_size.value + 2)
w = np.array(coefficient_inputs.value)
@@ -202,26 +195,26 @@ def _(alpha, coefficient_inputs, mo, np, ridge_loss, sample_size):
# Calculate components for display
mse_component = np.mean((y_true - X @ w) ** 2)
- reg_component = alpha.value * np.sum(w ** 2)
+ reg_component = alpha.value * np.sum(w**2)
# Display results
- result_display = mo.vstack([
- mo.md("### Current Loss Value"),
- mo.callout(
- mo.md(f"Ridge Loss: **{current_loss:.4f}**\n\n"
- f"- MSE Component: {mse_component:.4f}\n"
- f"- Regularization Component: {reg_component:.4f}"),
- kind="info"
- )
- ])
+ result_display = mo.vstack(
+ [
+ mo.md("### Current Loss Value"),
+ mo.callout(
+ mo.md(
+ f"Ridge Loss: **{current_loss:.4f}**\n\n"
+ f"- MSE Component: {mse_component:.4f}\n"
+ f"- Regularization Component: {reg_component:.4f}"
+ ),
+ kind="info",
+ ),
+ ]
+ )
except Exception as e:
- result_display = mo.vstack([
- mo.md("### Error"),
- mo.callout(
- mo.md(f"Error: {str(e)}"),
- kind="danger"
- )
- ])
+ result_display = mo.vstack(
+ [mo.md("### Error"), mo.callout(mo.md(f"Error: {str(e)}"), kind="danger")]
+ )
current_loss = None
return (
X,
@@ -246,28 +239,39 @@ def plot_predictions(X, w, y_true):
y_pred = X @ w
# Use pandas DataFrame for better compatibility with plotly
- df = pd.DataFrame({
- 'x': X[:, 0],
- 'True Values': y_true,
- 'Predictions': y_pred
- })
+ df = pd.DataFrame({"x": X[:, 0], "True Values": y_true, "Predictions": y_pred})
# Prepare data for plotting
- plot_df = pd.melt(df, id_vars=['x'], value_vars=['True Values', 'Predictions'],
- var_name='Type', value_name='Value')
+ plot_df = pd.melt(
+ df,
+ id_vars=["x"],
+ value_vars=["True Values", "Predictions"],
+ var_name="Type",
+ value_name="Value",
+ )
- fig = px.scatter(plot_df, x='x', y='Value', color='Type',
- title='True Values vs Predictions',
- labels={'Value': 'Value', 'x': 'Sample Index'})
+ fig = px.scatter(
+ plot_df,
+ x="x",
+ y="Value",
+ color="Type",
+ title="True Values vs Predictions",
+ labels={"Value": "Value", "x": "Sample Index"},
+ )
# Add lines connecting points
- for series_name in ['True Values', 'Predictions']:
- series_data = df[['x', series_name]].sort_values('x')
- fig.add_scatter(x=series_data['x'], y=series_data[series_name],
- mode='lines', name=f'{series_name} (line)',
- line=dict(dash='dash'))
+ for series_name in ["True Values", "Predictions"]:
+ series_data = df[["x", series_name]].sort_values("x")
+ fig.add_scatter(
+ x=series_data["x"],
+ y=series_data[series_name],
+ mode="lines",
+ name=f"{series_name} (line)",
+ line=dict(dash="dash"),
+ )
return fig
+
return (plot_predictions,)
@@ -284,16 +288,19 @@ def _(X, mo, plot_predictions, visualize_button, w, y_true):
try:
plot_results = plot_predictions(X, w, y_true)
except Exception as e:
- plot_results = mo.md(f"Error generating plot: {str(e)}").callout(kind="danger")
+ plot_results = mo.md(f"Error generating plot: {str(e)}").callout(
+ kind="danger"
+ )
plot_results
return (plot_results,)
@app.cell(hide_code=True)
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the Ridge Regression loss function interactively. Key takeaways:
@@ -302,23 +309,26 @@ def _(mo):
- How coefficients affect predictions and loss
- How Ridge regression shrinks coefficients toward zero
"""),
- kind="success"
- ),
- mo.accordion({
- "🎯 Applications": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "🎯 Applications": mo.md("""
- High-dimensional data analysis
- Feature selection
- Preventing overfitting in linear models
- Multicollinearity handling
"""),
- "🚀 Next Steps": mo.md("""
+ "🚀 Next Steps": mo.md("""
1. Implement gradient descent optimization
2. Compare with Lasso regression
3. Explore cross-validation for α selection
4. Apply to real-world datasets
- """)
- })
- ])
+ """),
+ }
+ ),
+ ]
+ )
return (conclusion,)
@@ -331,6 +341,7 @@ def _(conclusion):
@app.cell
def _():
import marimo as mo
+
return (mo,)
@@ -339,6 +350,7 @@ def _():
import numpy as np
import plotly.express as px
import pandas as pd
+
return np, pd, px
diff --git a/old_repo/Problems/interactive_learn/problem-44/notebook.py b/old_repo/Problems/interactive_learn/problem-44/notebook.py
index 2a935df2..fb44c687 100644
--- a/old_repo/Problems/interactive_learn/problem-44/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-44/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.10"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -39,19 +41,13 @@ def _(mo):
where $\alpha$ is typically a small positive value (default is 0.01) that determines the slope for negative inputs.
""")
- mo.accordion({"### Mathematical Definition" : value})
+ mo.accordion({"### Mathematical Definition": value})
return (value,)
@app.cell
def _(mo):
- alpha = mo.ui.slider(
- start=0.01,
- stop=0.5,
- value=0.01,
- step=0.01,
- label="Alpha (α)"
- )
+ alpha = mo.ui.slider(start=0.01, stop=0.5, value=0.01, step=0.01, label="Alpha (α)")
_callout = mo.callout(
mo.md("""
@@ -63,62 +59,62 @@ def _(mo):
- Lower alpha values make the function more similar to regular ReLU
"""),
- kind="info"
+ kind="info",
)
x_range = mo.ui.range_slider(
- start=-10,
- stop=10,
- step=0.5,
- value=[-5, 5],
- label="X-axis Range"
+ start=-10, stop=10, step=0.5, value=[-5, 5], label="X-axis Range"
)
- controls = mo.vstack([
- mo.md("### Adjust Parameters"),
- mo.hstack([
- mo.vstack([
- alpha,
- mo.accordion({
- "About Alpha": _callout
- })
- ]),
- mo.vstack([
- x_range,
- mo.accordion({
- "About Range": "Adjust to see different regions of the function."
- })
- ])
- ])
- ])
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ mo.hstack(
+ [
+ mo.vstack([alpha, mo.accordion({"About Alpha": _callout})]),
+ mo.vstack(
+ [
+ x_range,
+ mo.accordion(
+ {
+ "About Range": "Adjust to see different regions of the function."
+ }
+ ),
+ ]
+ ),
+ ]
+ ),
+ ]
+ )
return alpha, controls, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-10,
- stop=10,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-10, stop=10, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their Leaky ReLU outputs."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {
+ "About Testing": "Enter specific values to see their Leaky ReLU outputs."
+ }
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(alpha, mo):
- formula_display = mo.vstack([
- mo.md(
- f"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ f"""
### Current Leaky ReLU Configuration
With alpha parameter $\\alpha = {alpha.value:.3f}$, the current Leaky ReLU function is:
@@ -134,8 +130,9 @@ def _(alpha, mo):
- For negative inputs: output = {alpha.value:.3f} × input
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -150,7 +147,9 @@ def _(alpha, mo, np, plt, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_leaky_relu():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
y = np.where(x > 0, x, alpha.value * x)
@@ -159,40 +158,57 @@ def plot_leaky_relu():
# Plot negative region
mask_neg = x <= 0
- plt.plot(x[mask_neg], y[mask_neg],
- label=f'Negative region (slope = {alpha.value:.3f})',
- color='red',
- linewidth=2)
+ plt.plot(
+ x[mask_neg],
+ y[mask_neg],
+ label=f"Negative region (slope = {alpha.value:.3f})",
+ color="red",
+ linewidth=2,
+ )
# Plot positive region
mask_pos = x > 0
- plt.plot(x[mask_pos], y[mask_pos],
- label='Positive region (slope = 1.0)',
- color='blue',
- linewidth=2)
+ plt.plot(
+ x[mask_pos],
+ y[mask_pos],
+ label="Positive region (slope = 1.0)",
+ color="blue",
+ linewidth=2,
+ )
# Plot test point if within range
if x_range.value[0] <= test_input.value <= x_range.value[1]:
- test_output = test_input.value if test_input.value > 0 else alpha.value * test_input.value
- plt.scatter([test_input.value], [test_output],
- color='green', s=100,
- label=f'Test point: f({test_input.value:.2f}) = {test_output:.2f}')
+ test_output = (
+ test_input.value
+ if test_input.value > 0
+ else alpha.value * test_input.value
+ )
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="green",
+ s=100,
+ label=f"Test point: f({test_input.value:.2f}) = {test_output:.2f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title(f'Leaky ReLU Function (α = {alpha.value:.3f})')
- plt.xlabel('Input (z)')
- plt.ylabel('Output (LeakyReLU(z))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title(f"Leaky ReLU Function (α = {alpha.value:.3f})")
+ plt.xlabel("Input (z)")
+ plt.ylabel("Output (LeakyReLU(z))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add zero lines
- plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
+ plt.axhline(y=0, color="k", linestyle="--", alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_leaky_relu,)
@@ -216,9 +232,10 @@ def _(plot_leaky_relu):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the Leaky ReLU function interactively. You've learned:
@@ -226,30 +243,33 @@ def _(mo):
- The effect of the alpha parameter
- Why this helps prevent the "dying ReLU" problem
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Implementation:** Try implementing Leaky ReLU from scratch
2. **Compare:** Explore how it differs from other ReLU variants
3. **Experiment:** Test different alpha values in a neural network
4. **Advanced:** Learn about other solutions to the dying ReLU problem
"""),
- "🎯 Common Applications": mo.md("""
+ "🎯 Common Applications": mo.md("""
- Deep neural networks
- Convolutional neural networks (CNNs)
- Feature extraction layers
- When regular ReLU causes dead neurons
- Training very deep networks
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the Leaky ReLU activation function. Hope this helps in your deep learning journey!
""")
return
@@ -264,6 +284,7 @@ def _(conclusion):
@app.cell(hide_code=True)
def _():
import marimo as mo
+
return (mo,)
@@ -271,6 +292,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-75/notebook.py b/old_repo/Problems/interactive_learn/problem-75/notebook.py
index c191ccf6..0a2348c9 100644
--- a/old_repo/Problems/interactive_learn/problem-75/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-75/notebook.py
@@ -95,14 +95,18 @@ def _(data_controls):
def _(mo):
# Create number inputs for 12 individuals
n_samples = 12
- actual_inputs = mo.ui.array([
- mo.ui.number(value=0, start=0, stop=1, label=f"Actual {i+1}")
- for i in range(n_samples)
- ])
- predicted_inputs = mo.ui.array([
- mo.ui.number(value=0, start=0, stop=1, label=f"Predicted {i+1}")
- for i in range(n_samples)
- ])
+ actual_inputs = mo.ui.array(
+ [
+ mo.ui.number(value=0, start=0, stop=1, label=f"Actual {i + 1}")
+ for i in range(n_samples)
+ ]
+ )
+ predicted_inputs = mo.ui.array(
+ [
+ mo.ui.number(value=0, start=0, stop=1, label=f"Predicted {i + 1}")
+ for i in range(n_samples)
+ ]
+ )
# Create data table using markdown with LaTeX
data_table = mo.md(r"""
@@ -120,20 +124,23 @@ def _(mo):
""")
# Stack inputs horizontally and data table below
- data_controls = mo.vstack([
- mo.hstack([
- mo.vstack([
- mo.md("**Actual Classifications:**"),
- actual_inputs
- ]),
- mo.vstack([
- mo.md("**Predicted Classifications:**"),
- predicted_inputs
- ])
- ], justify="start", align="start"),
- mo.md("### Data Table:"),
- data_table
- ], gap=2) # Added gap for better spacing
+ data_controls = mo.vstack(
+ [
+ mo.hstack(
+ [
+ mo.vstack([mo.md("**Actual Classifications:**"), actual_inputs]),
+ mo.vstack(
+ [mo.md("**Predicted Classifications:**"), predicted_inputs]
+ ),
+ ],
+ justify="start",
+ align="start",
+ ),
+ mo.md("### Data Table:"),
+ data_table,
+ ],
+ gap=2,
+ ) # Added gap for better spacing
return (
actual_inputs,
data_controls,
@@ -197,49 +204,58 @@ def _(
accuracy = (tp + tn) / total if total > 0 else 0
precision = tp / (tp + fp) if (tp + fp) > 0 else 0
recall = tp / (tp + fn) if (tp + fn) > 0 else 0
- f1 = 2 * (precision * recall) / (precision + recall) if (precision + recall) > 0 else 0
+ f1 = (
+ 2 * (precision * recall) / (precision + recall)
+ if (precision + recall) > 0
+ else 0
+ )
# results table using markdown with LaTeX
- results_table = mo.md(r"""
+ results_table = mo.md(
+ r"""
$$
\begin{array}{|c|c|c|c|c|c|c|c|c|c|c|c|c|}
\hline
\text{Individual} & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 \\
\hline
- \text{Actual} & """ + " & ".join(str(v) for v in actual_values) + r""" \\
+ \text{Actual} & """
+ + " & ".join(str(v) for v in actual_values)
+ + r""" \\
\hline
- \text{Predicted} & """ + " & ".join(str(v) for v in predicted_values) + r""" \\
+ \text{Predicted} & """
+ + " & ".join(str(v) for v in predicted_values)
+ + r""" \\
\hline
- \text{Result} & """ + " & ".join(results_array) + r""" \\
+ \text{Result} & """
+ + " & ".join(results_array)
+ + r""" \\
\hline
\end{array}
$$
- """)
+ """
+ )
# Create confusion matrix visualization
fig = px.imshow(
conf_matrix,
labels=dict(x="Predicted", y="Actual"),
- x=['Positive', 'Negative'],
- y=['Positive', 'Negative'],
+ x=["Positive", "Negative"],
+ y=["Positive", "Negative"],
aspect="auto",
title="Confusion Matrix Heatmap",
color_continuous_scale="RdBu",
width=500,
height=500,
- text_auto=True
+ text_auto=True,
)
fig.update_traces(
texttemplate="%{z}",
textfont={"size": 20},
hoverongaps=False,
- hovertemplate="
".join([
- "Actual: %{y}",
- "Predicted: %{x}",
- "Count: %{z}",
- ""
- ])
+ hovertemplate="
".join(
+ ["Actual: %{y}", "Predicted: %{x}", "Count: %{z}", ""]
+ ),
)
# matrix interpretation
@@ -265,18 +281,16 @@ def _(
- F1 Score: {f1:.2f}
""")
- results = mo.vstack([
- mo.md("### Results"),
- results_table,
- # confusion matrix and interpretation side-by-side
- mo.hstack([
- fig,
- matrix_interpretation
- ], justify="start", align="start"),
- explanation,
- # final callout
- mo.callout(
- mo.md("""
+ results = mo.vstack(
+ [
+ mo.md("### Results"),
+ results_table,
+ # confusion matrix and interpretation side-by-side
+ mo.hstack([fig, matrix_interpretation], justify="start", align="start"),
+ explanation,
+ # final callout
+ mo.callout(
+ mo.md("""
🎉 Congratulations! You've successfully:
- Understood how confusion matrices work in binary classification
@@ -287,9 +301,10 @@ def _(
- Gained hands-on experience with interactive confusion matrix analysis
"""),
- kind="success"
- )
- ])
+ kind="success",
+ ),
+ ]
+ )
results
return (
accuracy,
@@ -317,8 +332,9 @@ def _(
@app.cell(hide_code=True)
def _(mo):
- explanation = mo.accordion({
- "🎯 Understanding the Results": mo.md("""
+ explanation = mo.accordion(
+ {
+ "🎯 Understanding the Results": mo.md("""
**Interpreting the Confusion Matrix:**
1. **Top-left (TP)**: Correctly identified positive cases
@@ -326,27 +342,27 @@ def _(mo):
3. **Bottom-left (FP)**: False alarms
4. **Bottom-right (TN)**: Correctly identified negative cases
"""),
-
- "📊 Derived Metrics": mo.md("""
+ "📊 Derived Metrics": mo.md("""
- **Accuracy**: Overall correctness (TP + TN) / Total
- **Precision**: Positive predictive value TP / (TP + FP)
- **Recall**: True positive rate TP / (TP + FN)
- **F1 Score**: Harmonic mean of precision and recall
"""),
-
- "💡 Best Practices": mo.md("""
+ "💡 Best Practices": mo.md("""
1. Consider class imbalance
2. Look at all metrics, not just accuracy
3. Choose metrics based on your problem context
4. Use confusion matrix for model debugging
- """)
- })
+ """),
+ }
+ )
return (explanation,)
@app.cell
def _():
import marimo as mo
+
return (mo,)
@@ -354,6 +370,7 @@ def _():
def _():
import numpy as np
import plotly.express as px
+
return np, px
diff --git a/old_repo/Problems/interactive_learn/problem-82/notebook.py b/old_repo/Problems/interactive_learn/problem-82/notebook.py
index ec2a6703..a2c9c5f9 100644
--- a/old_repo/Problems/interactive_learn/problem-82/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-82/notebook.py
@@ -11,7 +11,9 @@
import marimo
__generated_with = "0.10.11"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -130,7 +132,6 @@ def compress_image(img, max_size=(400, 400)):
img.thumbnail(max_size, Image.Resampling.LANCZOS)
return img
-
@mo.cache
def process_image(image_data=None, use_sample=False):
# TODO: Image path needs to be fixed for sample image; rerun when new version is rolled out
@@ -152,7 +153,6 @@ def process_image(image_data=None, use_sample=False):
return img_array, img_display
-
def calculate_contrast(img_array, method):
if img_array is None:
return 0
@@ -165,6 +165,7 @@ def calculate_contrast(img_array, method):
else: # Michelson Contrast
Imax, Imin = np.max(img_array), np.min(img_array)
return (Imax - Imin) / (Imax + Imin + 1e-6)
+
return calculate_contrast, compress_image, process_image
@@ -260,7 +261,6 @@ def _(calculate_contrast, img_array, io, mo, np, plt):
]
)
-
michelson_tab = mo.vstack(
[
mo.md(rf"""
@@ -323,7 +323,7 @@ def _(display):
@app.cell
def _(mo):
- conclusion = mo.md(f"""
+ conclusion = mo.md("""
**Congratulations!**
You've explored the Grayscale Image Contrast Calculator interactively.
@@ -342,8 +342,9 @@ def _(mo):
@app.cell
def _(mo):
- mo.accordion({
- "🌟 Applications and Relevance": mo.md(r"""
+ mo.accordion(
+ {
+ "🌟 Applications and Relevance": mo.md(r"""
### Relevance in Signal and Image Processing
Contrast calculations play a vital role in enhancing image quality for better visualization and analysis. They are used in:
@@ -354,7 +355,8 @@ def _(mo):
Contrast is a cornerstone of image and signal processing, enabling improved functionality across diverse fields from healthcare to autonomous systems.
"""),
- })
+ }
+ )
return
@@ -374,6 +376,7 @@ def _(callout, img_data, mo, source_selector):
@app.cell
def _():
import marimo as mo
+
return (mo,)
@@ -383,6 +386,7 @@ def _():
from PIL import Image
import matplotlib.pyplot as plt
import io
+
return Image, io, np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-96/notebook.py b/old_repo/Problems/interactive_learn/problem-96/notebook.py
index 2b748e42..34702859 100644
--- a/old_repo/Problems/interactive_learn/problem-96/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-96/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.12"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -40,18 +42,14 @@ def _(mo):
This piece-wise linear function approximates the smooth sigmoid curve with straight lines.
""")
- mo.accordion({"### Mathematical Definition" : value})
+ mo.accordion({"### Mathematical Definition": value})
return (value,)
@app.cell
def _(mo):
x_range = mo.ui.range_slider(
- start=-5,
- stop=5,
- step=0.5,
- value=[-3, 3],
- label="X-axis Range"
+ start=-5, stop=5, step=0.5, value=[-3, 3], label="X-axis Range"
)
_callout = mo.callout(
@@ -62,48 +60,50 @@ def _(mo):
- Between -2.5 and 2.5: Linear interpolation (0.2x + 0.5)
- Above 2.5: Output is 1
"""),
- kind="info"
+ kind="info",
)
- controls = mo.vstack([
- mo.md("### Adjust Parameters"),
- mo.hstack([
- mo.vstack([
- x_range,
- mo.accordion({
- "About Function Regions": _callout
- })
- ])
- ])
- ])
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ mo.hstack(
+ [
+ mo.vstack(
+ [x_range, mo.accordion({"About Function Regions": _callout})]
+ )
+ ]
+ ),
+ ]
+ )
return controls, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-5,
- stop=5,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-5, stop=5, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their Hard Sigmoid outputs."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {
+ "About Testing": "Enter specific values to see their Hard Sigmoid outputs."
+ }
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(mo):
- formula_display = mo.vstack([
- mo.md(
- r"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ r"""
### Current Hard Sigmoid Configuration
The Hard Sigmoid function is defined piece-wise:
@@ -120,8 +120,9 @@ def _(mo):
- For -2.5 < x < 2.5: output = 0.2x + 0.5
- For x ≥ 2.5: output = 1
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -136,7 +137,9 @@ def _(mo, np, plt, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_hard_sigmoid():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
y = np.clip(0.2 * x + 0.5, 0, 1)
@@ -148,41 +151,57 @@ def plot_hard_sigmoid():
mask_middle = (x > -2.5) & (x < 2.5)
mask_right = x >= 2.5
- plt.plot(x[mask_left], y[mask_left],
- label='Lower saturation (y = 0)',
- color='red',
- linewidth=2)
- plt.plot(x[mask_middle], y[mask_middle],
- label='Linear region (y = 0.2x + 0.5)',
- color='blue',
- linewidth=2)
- plt.plot(x[mask_right], y[mask_right],
- label='Upper saturation (y = 1)',
- color='green',
- linewidth=2)
+ plt.plot(
+ x[mask_left],
+ y[mask_left],
+ label="Lower saturation (y = 0)",
+ color="red",
+ linewidth=2,
+ )
+ plt.plot(
+ x[mask_middle],
+ y[mask_middle],
+ label="Linear region (y = 0.2x + 0.5)",
+ color="blue",
+ linewidth=2,
+ )
+ plt.plot(
+ x[mask_right],
+ y[mask_right],
+ label="Upper saturation (y = 1)",
+ color="green",
+ linewidth=2,
+ )
# Plot test point if within range (extend slider range accordingly)
if x_range.value[0] <= test_input.value <= x_range.value[1]:
test_output = np.clip(0.2 * test_input.value + 0.5, 0, 1)
- plt.scatter([test_input.value], [test_output],
- color='purple', s=100,
- label=f'Test point: f({test_input.value:.2f}) = {test_output:.2f}')
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="purple",
+ s=100,
+ label=f"Test point: f({test_input.value:.2f}) = {test_output:.2f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title('Hard Sigmoid Function')
- plt.xlabel('Input (x)')
- plt.ylabel('Output (HardSigmoid(x))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title("Hard Sigmoid Function")
+ plt.xlabel("Input (x)")
+ plt.ylabel("Output (HardSigmoid(x))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add zero lines
- plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
+ plt.axhline(y=0, color="k", linestyle="--", alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_hard_sigmoid,)
@@ -206,9 +225,10 @@ def _(plot_hard_sigmoid):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the Hard Sigmoid function interactively. You've learned:
@@ -216,30 +236,33 @@ def _(mo):
- The three distinct regions of the function
- The simplicity of the function -> only requires basic arithmetic operations -> making it computationally cheaper
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Implementation:** Try implementing Hard Sigmoid from scratch
2. **Compare:** Explore how it differs from regular sigmoid
3. **Experiment:** Test performance benefits in a neural network
4. **Advanced:** Learn about other sigmoid approximations
"""),
- "🎯 Common Applications": mo.md("""
+ "🎯 Common Applications": mo.md("""
- Neural networks requiring fast computation
- Embedded systems with limited resources
- Mobile applications
- Real-time inference systems
- Hardware implementations of neural networks
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the Hard Sigmoid activation function. Hope this helps in your deep learning journey!
""")
return
@@ -254,6 +277,7 @@ def _(conclusion):
@app.cell(hide_code=True)
def _():
import marimo as mo
+
return (mo,)
@@ -261,6 +285,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-97/notebook.py b/old_repo/Problems/interactive_learn/problem-97/notebook.py
index e87c8500..58362b3a 100644
--- a/old_repo/Problems/interactive_learn/problem-97/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-97/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.12"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -45,13 +47,7 @@ def _(mo):
@app.cell
def _(mo):
- alpha = mo.ui.slider(
- start=0.1,
- stop=3.0,
- value=1.0,
- step=0.1,
- label="Alpha (α)"
- )
+ alpha = mo.ui.slider(start=0.1, stop=3.0, value=1.0, step=0.1, label="Alpha (α)")
_callout = mo.callout(
mo.md("""
@@ -63,62 +59,60 @@ def _(mo):
- The function smoothly transitions at z = 0
- Negative values are bounded by -α
"""),
- kind="info"
+ kind="info",
)
x_range = mo.ui.range_slider(
- start=-10,
- stop=10,
- step=0.5,
- value=[-5, 5],
- label="X-axis Range"
+ start=-10, stop=10, step=0.5, value=[-5, 5], label="X-axis Range"
)
- controls = mo.vstack([
- mo.md("### Adjust Parameters"),
- mo.hstack([
- mo.vstack([
- alpha,
- mo.accordion({
- "About Alpha": _callout
- })
- ]),
- mo.vstack([
- x_range,
- mo.accordion({
- "About Range": "Adjust to see different regions of the function."
- })
- ])
- ])
- ])
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ mo.hstack(
+ [
+ mo.vstack([alpha, mo.accordion({"About Alpha": _callout})]),
+ mo.vstack(
+ [
+ x_range,
+ mo.accordion(
+ {
+ "About Range": "Adjust to see different regions of the function."
+ }
+ ),
+ ]
+ ),
+ ]
+ ),
+ ]
+ )
return alpha, controls, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-10,
- stop=10,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-10, stop=10, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their ELU outputs."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {"About Testing": "Enter specific values to see their ELU outputs."}
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(alpha, mo):
- formula_display = mo.vstack([
- mo.md(
- f"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ f"""
### Current ELU Configuration
With alpha parameter $\\alpha = {alpha.value:.3f}$, the current ELU function is:
@@ -134,8 +128,9 @@ def _(alpha, mo):
- For negative inputs: output = {alpha.value:.3f}(e^z - 1)
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -150,7 +145,9 @@ def _(alpha, mo, np, plt, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_elu():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
y = np.where(x > 0, x, alpha.value * (np.exp(x) - 1))
@@ -159,41 +156,58 @@ def plot_elu():
# Plot -ve region
mask_neg = x <= 0
- plt.plot(x[mask_neg], y[mask_neg],
- label=f'Negative region (exponential decay)',
- color='red',
- linewidth=2)
+ plt.plot(
+ x[mask_neg],
+ y[mask_neg],
+ label="Negative region (exponential decay)",
+ color="red",
+ linewidth=2,
+ )
# Plot +ve region
mask_pos = x > 0
- plt.plot(x[mask_pos], y[mask_pos],
- label='Positive region (linear)',
- color='blue',
- linewidth=2)
+ plt.plot(
+ x[mask_pos],
+ y[mask_pos],
+ label="Positive region (linear)",
+ color="blue",
+ linewidth=2,
+ )
# Plot test point if within range (expand x slider range to show test point)
if x_range.value[0] <= test_input.value <= x_range.value[1]:
- test_output = test_input.value if test_input.value > 0 else alpha.value * (np.exp(test_input.value) - 1)
- plt.scatter([test_input.value], [test_output],
- color='green', s=100,
- label=f'Test point: ELU({test_input.value:.2f}) = {test_output:.2f}')
+ test_output = (
+ test_input.value
+ if test_input.value > 0
+ else alpha.value * (np.exp(test_input.value) - 1)
+ )
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="green",
+ s=100,
+ label=f"Test point: ELU({test_input.value:.2f}) = {test_output:.2f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title(f'ELU Function (α = {alpha.value:.3f})')
- plt.xlabel('Input (z)')
- plt.ylabel('Output (ELU(z))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title(f"ELU Function (α = {alpha.value:.3f})")
+ plt.xlabel("Input (z)")
+ plt.ylabel("Output (ELU(z))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add zero lines
- plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
+ plt.axhline(y=0, color="k", linestyle="--", alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_elu,)
@@ -217,9 +231,10 @@ def _(plot_elu):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the ELU function interactively. You've learned:
@@ -228,30 +243,33 @@ def _(mo):
- Why it can help with mean unit activations
- How it combines the benefits of ReLU with negative values
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Implementation:** Try implementing ELU from scratch
2. **Compare:** Explore how it differs from ReLU and Leaky ReLU
3. **Experiment:** Test different alpha values in a neural network
4. **Advanced:** Learn about variants like SELU
"""),
- "🎯 Common Applications": mo.md("""
+ "🎯 Common Applications": mo.md("""
- Deep neural networks
- When faster learning is desired
- When negative values are important
- When dealing with vanishing gradients
- When mean activations closer to zero are beneficial
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the ELU activation function. Hope this helps in your deep learning journey!
""")
return
@@ -266,6 +284,7 @@ def _(conclusion):
@app.cell(hide_code=True)
def _():
import marimo as mo
+
return (mo,)
@@ -273,6 +292,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-98/notebook.py b/old_repo/Problems/interactive_learn/problem-98/notebook.py
index a8adbcbf..102dcffa 100644
--- a/old_repo/Problems/interactive_learn/problem-98/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-98/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.12"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -39,19 +41,13 @@ def _(mo):
where $\alpha$ is a learnable parameter that can be optimized during training, unlike Leaky ReLU where it's fixed.
""")
- mo.accordion({"### Mathematical Definition" : value})
+ mo.accordion({"### Mathematical Definition": value})
return (value,)
@app.cell
def _(mo):
- alpha = mo.ui.slider(
- start=0.01,
- stop=1.0,
- value=0.25,
- step=0.01,
- label="Alpha (α)"
- )
+ alpha = mo.ui.slider(start=0.01, stop=1.0, value=0.25, step=0.01, label="Alpha (α)")
_callout = mo.callout(
mo.md("""
@@ -63,62 +59,60 @@ def _(mo):
- Can adapt to the data distribution
- May have different values for different channels
"""),
- kind="info"
+ kind="info",
)
x_range = mo.ui.range_slider(
- start=-10,
- stop=10,
- step=0.5,
- value=[-5, 5],
- label="X-axis Range"
+ start=-10, stop=10, step=0.5, value=[-5, 5], label="X-axis Range"
)
- controls = mo.vstack([
- mo.md("### Adjust Parameters"),
- mo.hstack([
- mo.vstack([
- alpha,
- mo.accordion({
- "About Alpha": _callout
- })
- ]),
- mo.vstack([
- x_range,
- mo.accordion({
- "About Range": "Adjust to see different regions of the function."
- })
- ])
- ])
- ])
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ mo.hstack(
+ [
+ mo.vstack([alpha, mo.accordion({"About Alpha": _callout})]),
+ mo.vstack(
+ [
+ x_range,
+ mo.accordion(
+ {
+ "About Range": "Adjust to see different regions of the function."
+ }
+ ),
+ ]
+ ),
+ ]
+ ),
+ ]
+ )
return alpha, controls, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-10,
- stop=10,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-10, stop=10, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their PReLU outputs."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {"About Testing": "Enter specific values to see their PReLU outputs."}
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(alpha, mo):
- formula_display = mo.vstack([
- mo.md(
- f"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ f"""
### Current PReLU Configuration
With learnable parameter $\\alpha = {alpha.value:.3f}$, the current PReLU function is:
@@ -134,8 +128,9 @@ def _(alpha, mo):
- For negative inputs: output = {alpha.value:.3f} × input (learnable)
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -150,7 +145,9 @@ def _(alpha, mo, np, plt, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_prelu():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
y = np.where(x > 0, x, alpha.value * x)
@@ -159,40 +156,57 @@ def plot_prelu():
# Plot -ve region
mask_neg = x <= 0
- plt.plot(x[mask_neg], y[mask_neg],
- label=f'Negative region (learned slope = {alpha.value:.3f})',
- color='purple',
- linewidth=2)
+ plt.plot(
+ x[mask_neg],
+ y[mask_neg],
+ label=f"Negative region (learned slope = {alpha.value:.3f})",
+ color="purple",
+ linewidth=2,
+ )
# Plot +ve region
mask_pos = x > 0
- plt.plot(x[mask_pos], y[mask_pos],
- label='Positive region (slope = 1.0)',
- color='green',
- linewidth=2)
+ plt.plot(
+ x[mask_pos],
+ y[mask_pos],
+ label="Positive region (slope = 1.0)",
+ color="green",
+ linewidth=2,
+ )
# Plot test point if within range (modify x range slider accordingly)
if x_range.value[0] <= test_input.value <= x_range.value[1]:
- test_output = test_input.value if test_input.value > 0 else alpha.value * test_input.value
- plt.scatter([test_input.value], [test_output],
- color='orange', s=100,
- label=f'Test point: f({test_input.value:.2f}) = {test_output:.2f}')
+ test_output = (
+ test_input.value
+ if test_input.value > 0
+ else alpha.value * test_input.value
+ )
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="orange",
+ s=100,
+ label=f"Test point: f({test_input.value:.2f}) = {test_output:.2f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title(f'PReLU Function (learned α = {alpha.value:.3f})')
- plt.xlabel('Input (z)')
- plt.ylabel('Output (PReLU(z))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title(f"PReLU Function (learned α = {alpha.value:.3f})")
+ plt.xlabel("Input (z)")
+ plt.ylabel("Output (PReLU(z))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add zero lines
- plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
+ plt.axhline(y=0, color="k", linestyle="--", alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_prelu,)
@@ -216,9 +230,10 @@ def _(plot_prelu):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the PReLU activation function interactively. You've learned:
@@ -226,30 +241,33 @@ def _(mo):
- The effect of adaptive alpha parameters
- Why this helps improve model performance
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Implementation:** Try implementing PReLU in a neural network
2. **Compare:** Test against ReLU and Leaky ReLU
3. **Experiment:** Observe learned alpha values after training
4. **Advanced:** Implement channel-wise PReLU parameters
"""),
- "🎯 Common Applications": mo.md("""
+ "🎯 Common Applications": mo.md("""
- Deep Convolutional Neural Networks
- Image Classification Tasks
- Feature Extraction Networks
- When adaptive negative slopes are beneficial
- Performance-critical deep learning models
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the PReLU activation function. Hope this helps in your deep learning journey!
""")
return
@@ -264,6 +282,7 @@ def _(conclusion):
@app.cell(hide_code=True)
def _():
import marimo as mo
+
return (mo,)
@@ -271,6 +290,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-99/notebook.py b/old_repo/Problems/interactive_learn/problem-99/notebook.py
index 29a98f11..deedb4a9 100644
--- a/old_repo/Problems/interactive_learn/problem-99/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-99/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.12"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -36,18 +38,14 @@ def _(mo):
where $\log$ is the natural logarithm. This function provides a smooth, differentiable alternative to ReLU.
""")
- mo.accordion({"### Mathematical Definition" : value})
+ mo.accordion({"### Mathematical Definition": value})
return (value,)
@app.cell
def _(mo):
x_range = mo.ui.range_slider(
- start=-5,
- stop=5,
- step=0.5,
- value=[-3, 3],
- label="X-axis Range"
+ start=-5, stop=5, step=0.5, value=[-3, 3], label="X-axis Range"
)
_callout = mo.callout(
@@ -58,48 +56,46 @@ def _(mo):
- Around 0: Smooth transition
- For large positive values: Approaches linear (similar to ReLU)
"""),
- kind="info"
+ kind="info",
)
- controls = mo.vstack([
- mo.md("### Adjust Range"),
- mo.hstack([
- mo.vstack([
- x_range,
- mo.accordion({
- "About Function": _callout
- })
- ])
- ])
- ])
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Range"),
+ mo.hstack(
+ [mo.vstack([x_range, mo.accordion({"About Function": _callout})])]
+ ),
+ ]
+ )
return controls, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-5,
- stop=5,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-5, stop=5, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their Softplus outputs and compare with ReLU."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {
+ "About Testing": "Enter specific values to see their Softplus outputs and compare with ReLU."
+ }
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(mo):
- formula_display = mo.vstack([
- mo.md(
- r"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ r"""
### Softplus Function Properties
The Softplus function $f(x) = \log(1 + e^x)$ has these key properties:
@@ -108,8 +104,9 @@ def _(mo):
- Smooth and differentiable everywhere
- Derivative is the logistic sigmoid function: $f'(x) = \frac{1}{1 + e^{-x}}$
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -124,7 +121,9 @@ def _(mo, np, plt, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_softplus():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
y_softplus = np.log1p(np.exp(x)) # numerically stable version
@@ -133,41 +132,48 @@ def plot_softplus():
plt.figure(figsize=(12, 7))
# Plot Softplus
- plt.plot(x, y_softplus,
- label='Softplus',
- color='blue',
- linewidth=2)
+ plt.plot(x, y_softplus, label="Softplus", color="blue", linewidth=2)
# Plot ReLU for comparison (to see the smooth approximation)
- plt.plot(x, y_relu,
- label='ReLU (for comparison)',
- color='red',
- linestyle='--',
- alpha=0.5,
- linewidth=2)
+ plt.plot(
+ x,
+ y_relu,
+ label="ReLU (for comparison)",
+ color="red",
+ linestyle="--",
+ alpha=0.5,
+ linewidth=2,
+ )
# Plot test point if within range (adjust slider value accordingly)
if x_range.value[0] <= test_input.value <= x_range.value[1]:
test_output = np.log1p(np.exp(test_input.value))
- plt.scatter([test_input.value], [test_output],
- color='green', s=100,
- label=f'Test point: f({test_input.value:.2f}) = {test_output:.2f}')
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="green",
+ s=100,
+ label=f"Test point: f({test_input.value:.2f}) = {test_output:.2f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title('Softplus Function vs ReLU')
- plt.xlabel('Input (x)')
- plt.ylabel('Output (Softplus(x))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title("Softplus Function vs ReLU")
+ plt.xlabel("Input (x)")
+ plt.ylabel("Output (Softplus(x))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add zero lines
- plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
+ plt.axhline(y=0, color="k", linestyle="--", alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_softplus,)
@@ -191,9 +197,10 @@ def _(plot_softplus):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the Softplus activation function interactively. You've learned:
@@ -202,23 +209,26 @@ def _(mo):
- How it compares to ReLU visually
- Its behavior in different input regions
"""),
- kind="success"
- ),
- mo.accordion({
- "Key Takeaways": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Key Takeaways": mo.md("""
- Softplus is always positive
- Provides smooth transitions (differentiable everywhere)
- Approaches ReLU for large positive values
- More computationally expensive than ReLU
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the Softplus activation function. Hope this helps in your deep learning journey!
""")
return
@@ -233,6 +243,7 @@ def _(conclusion):
@app.cell(hide_code=True)
def _():
import marimo as mo
+
return (mo,)
@@ -240,6 +251,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-Mish/notebook.py b/old_repo/Problems/interactive_learn/problem-Mish/notebook.py
index 848762ef..69187ad9 100644
--- a/old_repo/Problems/interactive_learn/problem-Mish/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-Mish/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.12"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -36,18 +38,14 @@ def _(mo):
It combines the characteristics of the softplus function ($\ln(1 + e^x)$) with hyperbolic tangent, creating a smooth and non-monotonic activation function.
""")
- mo.accordion({"### Mathematical Definition" : value})
+ mo.accordion({"### Mathematical Definition": value})
return (value,)
@app.cell
def _(mo):
x_range = mo.ui.range_slider(
- start=-5,
- stop=5,
- step=0.5,
- value=[-3, 3],
- label="X-axis Range"
+ start=-5, stop=5, step=0.5, value=[-3, 3], label="X-axis Range"
)
_callout = mo.callout(
@@ -62,62 +60,60 @@ def _(mo):
- Preserves small negative gradients
- Smoother than ReLU and its variants
"""),
- kind="info"
+ kind="info",
)
smoothing = mo.ui.slider(
- start=0.1,
- stop=2.0,
- value=1.0,
- step=0.1,
- label="Smoothing Factor"
+ start=0.1, stop=2.0, value=1.0, step=0.1, label="Smoothing Factor"
)
- controls = mo.vstack([
- mo.md("### Adjust Parameters"),
- mo.hstack([
- mo.vstack([
- smoothing,
- mo.accordion({
- "About Smoothing": _callout
- })
- ]),
- mo.vstack([
- x_range,
- mo.accordion({
- "About Range": "Adjust to see different regions of the function."
- })
- ])
- ])
- ])
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ mo.hstack(
+ [
+ mo.vstack([smoothing, mo.accordion({"About Smoothing": _callout})]),
+ mo.vstack(
+ [
+ x_range,
+ mo.accordion(
+ {
+ "About Range": "Adjust to see different regions of the function."
+ }
+ ),
+ ]
+ ),
+ ]
+ ),
+ ]
+ )
return controls, smoothing, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-5,
- stop=5,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-5, stop=5, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their Mish outputs."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {"About Testing": "Enter specific values to see their Mish outputs."}
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(mo, smoothing):
- formula_display = mo.vstack([
- mo.md(
- f"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ f"""
### Current Mish Configuration
With smoothing factor $\\beta = {smoothing.value:.3f}$, the current Mish function is:
@@ -131,8 +127,9 @@ def _(mo, smoothing):
- Non-monotonic near x = 0
- Preserves small negative gradients
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -147,7 +144,9 @@ def _(mo, np, plt, smoothing, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_mish():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
softplus = np.log1p(np.exp(x))
@@ -156,34 +155,40 @@ def plot_mish():
plt.figure(figsize=(12, 7))
# Main function
- plt.plot(x, y,
- label=f'Mish (β={smoothing.value:.2f})',
- color='purple',
- linewidth=2)
+ plt.plot(
+ x, y, label=f"Mish (β={smoothing.value:.2f})", color="purple", linewidth=2
+ )
# Plot test point if within range (vary slider accordingly)
if x_range.value[0] <= test_input.value <= x_range.value[1]:
test_softplus = np.log1p(np.exp(test_input.value))
test_output = test_input.value * np.tanh(smoothing.value * test_softplus)
- plt.scatter([test_input.value], [test_output],
- color='orange', s=100,
- label=f'Test point: f({test_input.value:.2f}) = {test_output:.2f}')
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="orange",
+ s=100,
+ label=f"Test point: f({test_input.value:.2f}) = {test_output:.2f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title(f'Mish Function (β = {smoothing.value:.2f})')
- plt.xlabel('Input (x)')
- plt.ylabel('Output (Mish(x))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title(f"Mish Function (β = {smoothing.value:.2f})")
+ plt.xlabel("Input (x)")
+ plt.ylabel("Output (Mish(x))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add zero lines
- plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
+ plt.axhline(y=0, color="k", linestyle="--", alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_mish,)
@@ -207,9 +212,10 @@ def _(plot_mish):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the Mish activation function interactively. You've learned:
@@ -217,30 +223,33 @@ def _(mo):
- Its smooth, non-monotonic behavior
- Why it's effective in deep networks
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Implementation:** Try implementing Mish in a neural network
2. **Compare:** Test against ReLU and other modern activations
3. **Experiment:** Observe training stability improvements
4. **Advanced:** Study the gradients and their behavior
"""),
- "🎯 Common Applications": mo.md("""
+ "🎯 Common Applications": mo.md("""
- Deep Neural Networks
- Computer Vision Tasks
- Classification Problems
- When smooth gradients are crucial
- Problems requiring self-regularization
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the Mish activation function. Hope this helps in your deep learning journey!
""")
return
@@ -255,6 +264,7 @@ def _(conclusion):
@app.cell(hide_code=True)
def _():
import marimo as mo
+
return (mo,)
@@ -262,6 +272,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-SELU/notebook.py b/old_repo/Problems/interactive_learn/problem-SELU/notebook.py
index 80a2722a..cfedc044 100644
--- a/old_repo/Problems/interactive_learn/problem-SELU/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-SELU/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.12"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -39,7 +41,7 @@ def _(mo):
where $\lambda \approx 1.0507$ is a scaling parameter and $\alpha \approx 1.6733$ is the default shape parameter for self-normalization.
""")
- mo.accordion({"### Mathematical Definition" : value})
+ mo.accordion({"### Mathematical Definition": value})
return (value,)
@@ -50,7 +52,7 @@ def _(mo):
stop=3.0,
value=1.6732632423543772, # Default SELU alpha
step=0.01,
- label="Alpha (α)"
+ label="Alpha (α)",
)
_callout = mo.callout(
@@ -64,62 +66,60 @@ def _(mo):
- Experiment with different α values to understand impact
- Standard SELU uses fixed parameters for optimal performance
"""),
- kind="info"
+ kind="info",
)
x_range = mo.ui.range_slider(
- start=-5,
- stop=5,
- step=0.5,
- value=[-3, 3],
- label="X-axis Range"
+ start=-5, stop=5, step=0.5, value=[-3, 3], label="X-axis Range"
)
- controls = mo.vstack([
- mo.md("### Adjust Parameters"),
- mo.hstack([
- mo.vstack([
- alpha,
- mo.accordion({
- "About Alpha": _callout
- })
- ]),
- mo.vstack([
- x_range,
- mo.accordion({
- "About Range": "Adjust to see different regions of the function."
- })
- ])
- ])
- ])
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ mo.hstack(
+ [
+ mo.vstack([alpha, mo.accordion({"About Alpha": _callout})]),
+ mo.vstack(
+ [
+ x_range,
+ mo.accordion(
+ {
+ "About Range": "Adjust to see different regions of the function."
+ }
+ ),
+ ]
+ ),
+ ]
+ ),
+ ]
+ )
return alpha, controls, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-5,
- stop=5,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-5, stop=5, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their SELU outputs."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {"About Testing": "Enter specific values to see their SELU outputs."}
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(alpha, mo):
- formula_display = mo.vstack([
- mo.md(
- f"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ f"""
### Current SELU Configuration
With parameter $\\alpha = {alpha.value:.3f}$ and fixed $\\lambda = 1.0507$, the current SELU function is:
@@ -134,8 +134,9 @@ def _(alpha, mo):
- For positive inputs: output = 1.0507 × input
- For negative inputs: output = 1.0507 × {alpha.value:.3f} × (e^input - 1)
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -150,7 +151,9 @@ def _(alpha, mo, np, plt, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_selu():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
scale = 1.0507009873554804
@@ -161,17 +164,23 @@ def plot_selu():
# Plot -ve region
mask_neg = x <= 0
- plt.plot(x[mask_neg], y[mask_neg],
- label=f'Negative region (α={alpha.value:.3f})',
- color='darkred',
- linewidth=2)
+ plt.plot(
+ x[mask_neg],
+ y[mask_neg],
+ label=f"Negative region (α={alpha.value:.3f})",
+ color="darkred",
+ linewidth=2,
+ )
# Plot +ve region
mask_pos = x > 0
- plt.plot(x[mask_pos], y[mask_pos],
- label='Positive region (λx)',
- color='darkgreen',
- linewidth=2)
+ plt.plot(
+ x[mask_pos],
+ y[mask_pos],
+ label="Positive region (λx)",
+ color="darkgreen",
+ linewidth=2,
+ )
# Plot test point if within range (extend range to show point if needed)
if x_range.value[0] <= test_input.value <= x_range.value[1]:
@@ -179,25 +188,32 @@ def plot_selu():
test_output = scale * test_input.value
else:
test_output = scale * alpha.value * (np.exp(test_input.value) - 1)
- plt.scatter([test_input.value], [test_output],
- color='orange', s=100,
- label=f'Test point: f({test_input.value:.2f}) = {test_output:.2f}')
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="orange",
+ s=100,
+ label=f"Test point: f({test_input.value:.2f}) = {test_output:.2f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title(f'SELU Function (α = {alpha.value:.3f})')
- plt.xlabel('Input (z)')
- plt.ylabel('Output (SELU(z))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title(f"SELU Function (α = {alpha.value:.3f})")
+ plt.xlabel("Input (z)")
+ plt.ylabel("Output (SELU(z))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add zero lines
- plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
+ plt.axhline(y=0, color="k", linestyle="--", alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_selu,)
@@ -221,9 +237,10 @@ def _(plot_selu):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the SELU activation function interactively. You've learned:
@@ -231,30 +248,33 @@ def _(mo):
- The role of λ and α parameters
- Why specific parameter values are chosen
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Implementation:** Try implementing SELU in a neural network
2. **Compare:** Test against other activation functions
3. **Experiment:** Observe self-normalizing properties
4. **Advanced:** Learn about proper initialization with SELU
"""),
- "🎯 Common Applications": mo.md("""
+ "🎯 Common Applications": mo.md("""
- Deep Neural Networks
- Self-Normalizing Neural Networks (SNNs)
- Networks requiring stable training
- Deep architectures sensitive to normalization
- Cases where batch normalization is impractical
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the SELU activation function. Hope this helps in your deep learning journey!
""")
return
@@ -269,6 +289,7 @@ def _(conclusion):
@app.cell(hide_code=True)
def _():
import marimo as mo
+
return (mo,)
@@ -276,6 +297,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-softsign/notebook.py b/old_repo/Problems/interactive_learn/problem-softsign/notebook.py
index 5e0753c1..48cb92d6 100644
--- a/old_repo/Problems/interactive_learn/problem-softsign/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-softsign/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.12"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -44,18 +46,14 @@ def _(mo):
While both functions map inputs to the range (-1, 1), Softsign approaches its asymptotes more slowly than tanh,
which can help maintain better gradient flow during training.
""")
- mo.accordion({"### Mathematical Definition" : value})
+ mo.accordion({"### Mathematical Definition": value})
return (value,)
@app.cell
def _(mo):
x_range = mo.ui.range_slider(
- start=-10,
- stop=10,
- step=0.5,
- value=[-5, 5],
- label="X-axis Range"
+ start=-10, stop=10, step=0.5, value=[-5, 5], label="X-axis Range"
)
_callout = mo.callout(
@@ -70,46 +68,54 @@ def _(mo):
- Shows slower saturation than tanh
"""),
- kind="info"
+ kind="info",
)
- controls = mo.hstack([
- mo.vstack([
- mo.md("### Adjust Parameters"),
- x_range,
- mo.accordion({
- "About Range": "Adjust to see different regions of the function and how it approaches its asymptotes.",
- })
- ]), _callout.right()
- ])
+ controls = mo.hstack(
+ [
+ mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ x_range,
+ mo.accordion(
+ {
+ "About Range": "Adjust to see different regions of the function and how it approaches its asymptotes.",
+ }
+ ),
+ ]
+ ),
+ _callout.right(),
+ ]
+ )
return controls, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-10,
- stop=10,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-10, stop=10, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their Softsign outputs."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {
+ "About Testing": "Enter specific values to see their Softsign outputs."
+ }
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(mo):
- formula_display = mo.vstack([
- mo.md(
- r"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ r"""
### Current Softsign Configuration
The Softsign function is defined as:
@@ -119,8 +125,9 @@ def _(mo):
\]
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -135,7 +142,9 @@ def _(mo, np, plt, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_softsign():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
y_softsign = x / (1 + np.abs(x))
@@ -144,43 +153,48 @@ def plot_softsign():
plt.figure(figsize=(12, 7))
# Plot tanh first (as reference)
- plt.plot(x, y_tanh,
- label='tanh',
- color='red',
- linewidth=2,
- linestyle='--',
- alpha=0.6)
+ plt.plot(
+ x, y_tanh, label="tanh", color="red", linewidth=2, linestyle="--", alpha=0.6
+ )
# Plot Softsign
- plt.plot(x, y_softsign,
- label='Softsign',
- color='blue',
- linewidth=2)
+ plt.plot(x, y_softsign, label="Softsign", color="blue", linewidth=2)
# Plot test point if within range (adjust sliders accordingly)
if x_range.value[0] <= test_input.value <= x_range.value[1]:
test_output = test_input.value / (1 + abs(test_input.value))
- plt.scatter([test_input.value], [test_output],
- color='green', s=100,
- label=f'Test point: f({test_input.value:.2f}) = {test_output:.2f}')
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="green",
+ s=100,
+ label=f"Test point: f({test_input.value:.2f}) = {test_output:.2f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title('Softsign Activation Function')
- plt.xlabel('Input (x)')
- plt.ylabel('Output (Softsign(x))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title("Softsign Activation Function")
+ plt.xlabel("Input (x)")
+ plt.ylabel("Output (Softsign(x))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add zero lines and asymptotes
- plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
- plt.axhline(y=1, color='r', linestyle=':', alpha=0.3, label='Upper asymptote (y=1)')
- plt.axhline(y=-1, color='r', linestyle=':', alpha=0.3, label='Lower asymptote (y=-1)')
-
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plt.axhline(y=0, color="k", linestyle="--", alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
+ plt.axhline(
+ y=1, color="r", linestyle=":", alpha=0.3, label="Upper asymptote (y=1)"
+ )
+ plt.axhline(
+ y=-1, color="r", linestyle=":", alpha=0.3, label="Lower asymptote (y=-1)"
+ )
+
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_softsign,)
@@ -204,9 +218,10 @@ def _(plot_softsign):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've explored the Softsign activation function interactively. You've learned:
@@ -214,30 +229,33 @@ def _(mo):
- Its smooth behavior and slower saturation
- Why it can be an alternative to tanh
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Implementation:** Try implementing Softsign from scratch
2. **Compare:** Explore how it differs from tanh
3. **Experiment:** Test it in a neural network
4. **Advanced:** Learn about other bounded activation functions
"""),
- "🎯 Common Applications": mo.md("""
+ "🎯 Common Applications": mo.md("""
- Deep neural networks
- When smooth gradients are important
- Situations where bounded outputs are needed
- Alternative to tanh activation
- When slower saturation is beneficial
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the Softsign activation function. Hope this helps in your deep learning journey!
""")
return
@@ -252,6 +270,7 @@ def _(conclusion):
@app.cell(hide_code=True)
def _():
import marimo as mo
+
return (mo,)
@@ -259,6 +278,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/Problems/interactive_learn/problem-tanh/notebook.py b/old_repo/Problems/interactive_learn/problem-tanh/notebook.py
index 80c56048..0173ce47 100644
--- a/old_repo/Problems/interactive_learn/problem-tanh/notebook.py
+++ b/old_repo/Problems/interactive_learn/problem-tanh/notebook.py
@@ -10,7 +10,9 @@
import marimo
__generated_with = "0.10.12"
-app = marimo.App(css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css")
+app = marimo.App(
+ css_file="/Users/adityakhalkar/Library/Application Support/mtheme/themes/deepml.css"
+)
@app.cell(hide_code=True)
@@ -42,18 +44,14 @@ def _(mo):
where $\sigma(x)$ is the sigmoid function. This creates a smooth, S-shaped function that maps inputs to the range [-1, 1].
""")
- mo.accordion({"### Mathematical Definition" : value})
+ mo.accordion({"### Mathematical Definition": value})
return (value,)
@app.cell
def _(mo):
steepness = mo.ui.slider(
- start=0.1,
- stop=2.0,
- value=1.0,
- step=0.1,
- label="Steepness"
+ start=0.1, stop=2.0, value=1.0, step=0.1, label="Steepness"
)
_callout = mo.callout(
@@ -66,62 +64,60 @@ def _(mo):
- Lower values make the transition more gradual
- Default value of 1.0 gives the standard tanh
"""),
- kind="info"
+ kind="info",
)
x_range = mo.ui.range_slider(
- start=-10,
- stop=10,
- step=0.5,
- value=[-5, 5],
- label="X-axis Range"
+ start=-10, stop=10, step=0.5, value=[-5, 5], label="X-axis Range"
)
- controls = mo.vstack([
- mo.md("### Adjust Parameters"),
- mo.hstack([
- mo.vstack([
- steepness,
- mo.accordion({
- "About Steepness": _callout
- })
- ]),
- mo.vstack([
- x_range,
- mo.accordion({
- "About Range": "Adjust to see different regions of the function."
- })
- ])
- ])
- ])
+ controls = mo.vstack(
+ [
+ mo.md("### Adjust Parameters"),
+ mo.hstack(
+ [
+ mo.vstack([steepness, mo.accordion({"About Steepness": _callout})]),
+ mo.vstack(
+ [
+ x_range,
+ mo.accordion(
+ {
+ "About Range": "Adjust to see different regions of the function."
+ }
+ ),
+ ]
+ ),
+ ]
+ ),
+ ]
+ )
return controls, steepness, x_range
@app.cell
def _(mo):
test_input = mo.ui.number(
- value=0.0,
- start=-10,
- stop=10,
- step=0.1,
- label="Test Input Value"
+ value=0.0, start=-10, stop=10, step=0.1, label="Test Input Value"
)
- input_controls = mo.vstack([
- mo.md("### Test Specific Values"),
- test_input,
- mo.accordion({
- "About Testing": "Enter specific values to see their tanh outputs."
- })
- ])
+ input_controls = mo.vstack(
+ [
+ mo.md("### Test Specific Values"),
+ test_input,
+ mo.accordion(
+ {"About Testing": "Enter specific values to see their tanh outputs."}
+ ),
+ ]
+ )
return input_controls, test_input
@app.cell
def _(mo, steepness):
- formula_display = mo.vstack([
- mo.md(
- f"""
+ formula_display = mo.vstack(
+ [
+ mo.md(
+ f"""
### Current Tanh Configuration
With steepness parameter $s = {steepness.value:.1f}$, the current tanh function is:
@@ -136,8 +132,9 @@ def _(mo, steepness):
- Steeper gradient near origin compared to sigmoid
- Outputs centered around zero
"""
- ),
- ])
+ ),
+ ]
+ )
return (formula_display,)
@@ -152,7 +149,9 @@ def _(mo, np, plt, steepness, test_input, x_range):
@mo.cache(pin_modules=True)
def plot_tanh():
if x_range.value[0] >= x_range.value[1]:
- raise ValueError("Invalid x_range: start value must be less than stop value.")
+ raise ValueError(
+ "Invalid x_range: start value must be less than stop value."
+ )
x = np.linspace(x_range.value[0], x_range.value[1], 1000)
y = np.tanh(steepness.value * x)
@@ -160,44 +159,46 @@ def plot_tanh():
plt.figure(figsize=(12, 7))
# Plot main function
- plt.plot(x, y,
- label='tanh function',
- color='blue',
- linewidth=2)
+ plt.plot(x, y, label="tanh function", color="blue", linewidth=2)
# Plot derivative (serves as a reference)
derivative = steepness.value * (1 - y**2)
- plt.plot(x, derivative,
- label='Derivative',
- color='red',
- linestyle='--',
- alpha=0.5)
+ plt.plot(
+ x, derivative, label="Derivative", color="red", linestyle="--", alpha=0.5
+ )
# Plot test point if within range (adjust if needed accordingly)
if x_range.value[0] <= test_input.value <= x_range.value[1]:
test_output = np.tanh(steepness.value * test_input.value)
- plt.scatter([test_input.value], [test_output],
- color='green', s=100,
- label=f'Test point: f({test_input.value:.2f}) = {test_output:.2f}')
+ plt.scatter(
+ [test_input.value],
+ [test_output],
+ color="green",
+ s=100,
+ label=f"Test point: f({test_input.value:.2f}) = {test_output:.2f}",
+ )
plt.grid(True, alpha=0.3)
- plt.title(f'Tanh Function (steepness = {steepness.value:.1f})')
- plt.xlabel('Input (x)')
- plt.ylabel('Output (tanh(x))')
- plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
+ plt.title(f"Tanh Function (steepness = {steepness.value:.1f})")
+ plt.xlabel("Input (x)")
+ plt.ylabel("Output (tanh(x))")
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
# Add horizontal bounds at -1 and 1
- plt.axhline(y=-1, color='gray', linestyle=':', alpha=0.5)
- plt.axhline(y=1, color='gray', linestyle=':', alpha=0.5)
+ plt.axhline(y=-1, color="gray", linestyle=":", alpha=0.5)
+ plt.axhline(y=1, color="gray", linestyle=":", alpha=0.5)
# Add zero lines
- plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
- plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)
+ plt.axhline(y=0, color="k", linestyle="--", alpha=0.3)
+ plt.axvline(x=0, color="k", linestyle="--", alpha=0.3)
- plot_display = mo.vstack([
- mo.as_html(plt.gca()),
- ])
+ plot_display = mo.vstack(
+ [
+ mo.as_html(plt.gca()),
+ ]
+ )
return plot_display
+
return (plot_tanh,)
@@ -221,9 +222,10 @@ def _(plot_tanh):
@app.cell
def _(mo):
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Key Takeaways!**
Through this interactive exploration of the tanh function, you've learned:
@@ -231,30 +233,33 @@ def _(mo):
- The effect of steepness on the function's shape
- The symmetric nature of the function
"""),
- kind="success"
- ),
- mo.accordion({
- "Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "Next Steps": mo.md("""
1. **Implementation:** Try using tanh in your neural networks
2. **Compare:** Analyze performance vs sigmoid and other activations
3. **Experiment:** Study the vanishing gradient problem
4. **Advanced:** Explore tanh in RNNs and LSTMs
"""),
- "🎯 Common Applications": mo.md("""
+ "🎯 Common Applications": mo.md("""
- Recurrent Neural Networks (RNNs)
- Long Short-Term Memory (LSTM) networks
- Binary classification tasks
- When zero-centered outputs are needed
- Financial time series prediction
"""),
- })
- ])
+ }
+ ),
+ ]
+ )
return (conclusion,)
@app.cell
def _(mo):
- mo.md(f"""
+ mo.md("""
This interactive learning experience was designed to help you understand the hyperbolic tangent (tanh) activation function. Hope this helps in your deep learning journey!
""")
return
@@ -269,6 +274,7 @@ def _(conclusion):
@app.cell(hide_code=True)
def _():
import marimo as mo
+
return (mo,)
@@ -276,6 +282,7 @@ def _():
def _():
import numpy as np
import matplotlib.pyplot as plt
+
return np, plt
diff --git a/old_repo/app.py b/old_repo/app.py
index 2c86cbd7..40114c7d 100644
--- a/old_repo/app.py
+++ b/old_repo/app.py
@@ -4,13 +4,14 @@
import os
import re
+
def render_learn_section(learn_section):
# Replace LaTeX delimiters with the appropriate format for MathJax
- learn_section = re.sub(r'\\\(', r'$', learn_section)
- learn_section = re.sub(r'\\\)', r'$', learn_section)
- learn_section = re.sub(r'\\\[', r'$$', learn_section)
- learn_section = re.sub(r'\\\]', r'$$', learn_section)
-
+ learn_section = re.sub(r"\\\(", r"$", learn_section)
+ learn_section = re.sub(r"\\\)", r"$", learn_section)
+ learn_section = re.sub(r"\\\[", r"$$", learn_section)
+ learn_section = re.sub(r"\\\]", r"$$", learn_section)
+
st.subheader("Learn Section Preview")
components.html(
f"""
@@ -36,24 +37,28 @@ def render_learn_section(learn_section):
height=1000,
)
+
# Define the directory containing the learn.html files
LEARN_HTML_DIR = "Problems"
+
def load_file(file_path):
try:
- with open(file_path, 'r', encoding='utf-8') as file:
+ with open(file_path, "r", encoding="utf-8") as file:
return file.read()
except Exception as e:
st.error(f"Error loading file {file_path}: {e}")
return ""
+
def save_file(file_path, content):
try:
- with open(file_path, 'w', encoding='utf-8') as file:
+ with open(file_path, "w", encoding="utf-8") as file:
file.write(content)
except Exception as e:
st.error(f"Error saving file {file_path}: {e}")
+
# Streamlit app
st.title("Learn Section Editor")
@@ -68,7 +73,9 @@ def save_file(file_path, content):
st.warning("No learn.html files found.")
else:
# File selector
- selected_file = st.selectbox("Select an HTML file to edit", html_files, key="file_selector")
+ selected_file = st.selectbox(
+ "Select an HTML file to edit", html_files, key="file_selector"
+ )
if selected_file:
# Load the content of the selected file
@@ -79,7 +86,9 @@ def save_file(file_path, content):
editor_key = f"editor_{selected_file}"
# Display the editor with the current file content
- edited_content = st_ace(value=content, language='html', theme='monokai', key=editor_key)
+ edited_content = st_ace(
+ value=content, language="html", theme="monokai", key=editor_key
+ )
if st.button("RENDER"):
st.session_state["rendered_html"] = edited_content
diff --git a/old_repo/example_problem/solution.py b/old_repo/example_problem/solution.py
index 4a03ea8c..1d8147ff 100644
--- a/old_repo/example_problem/solution.py
+++ b/old_repo/example_problem/solution.py
@@ -28,12 +28,13 @@ def test_matrix_dot_vector() -> None:
a: list[list[int | float]] = [[1, 2], [2, 4]]
b: list[int | float] = [1, 2]
assert matrix_dot_vector(a, b) == [5, 10]
-
- # valid product with rectangular matrix (non-square) -- > if we changed "for j in range(len(a[i]))" to "for j in range(len(a))" previous tests will pass
+
+ # valid product with rectangular matrix (non-square) -- > if we changed "for j in range(len(a[i]))" to "for j in range(len(a))" previous tests will pass
a: list[list[int | float]] = [[1, 2, 3], [2, 4, 6]]
b: list[int | float] = [1, 2, 3]
assert matrix_dot_vector(a, b) == [14, 28]
+
if __name__ == "__main__":
test_matrix_dot_vector()
print("All tests passed.")
diff --git a/old_repo/notebook.py b/old_repo/notebook.py
index e05ac49c..27a68299 100644
--- a/old_repo/notebook.py
+++ b/old_repo/notebook.py
@@ -14,13 +14,14 @@
__generated_with = "0.11.31"
app = marimo.App(width="medium")
+
@app.cell(hide_code=True)
def _(mo):
# Key concepts accordion
-
- insights = mo.accordion({
- "🎯 Understanding Covariance": mo.md("""
+ insights = mo.accordion(
+ {
+ "🎯 Understanding Covariance": mo.md("""
**Key Concepts:**
1. **Variance**: Measures spread of a single variable
@@ -31,8 +32,7 @@ def _(mo):
4. **Interpretation**: Direction and strength of relationships
"""),
-
- "📊 Matrix Properties": mo.md("""
+ "📊 Matrix Properties": mo.md("""
The covariance matrix has important properties:
1. **Symmetry**: cov(X,Y) = cov(Y,X)
@@ -43,8 +43,7 @@ def _(mo):
4. **Positive Semi-definite**: All eigenvalues ≥ 0
"""),
-
- "🔄 Covariance vs. Correlation": mo.md("""
+ "🔄 Covariance vs. Correlation": mo.md("""
**Important Distinction:**
1. **Covariance**: Depends on the scale of the variables
@@ -56,17 +55,19 @@ def _(mo):
- Always ranges from -1 to 1
- Easier to interpret: 1 (perfect positive), -1 (perfect negative), 0 (no relationship)
- Formula: $corr(X,Y) = \\frac{cov(X,Y)}{\\sigma_X \\sigma_Y}$
- """)
- })
+ """),
+ }
+ )
return (insights,)
+
@app.cell(hide_code=True)
def _(mo):
# Practice exercises
- exercises = mo.accordion({
-
- "🎯 Practice Exercises": mo.md("""
+ exercises = mo.accordion(
+ {
+ "🎯 Practice Exercises": mo.md("""
Try these examples to understand covariance better:
@@ -85,9 +86,7 @@ def _(mo):
What do you notice about the covariance vs correlation matrices?
"""),
-
-
- "💡 Tips for Interpretation": mo.md("""
+ "💡 Tips for Interpretation": mo.md("""
- Large positive values: Strong positive relationship
@@ -101,11 +100,12 @@ def _(mo):
- Correlation is easier to interpret consistently (-1 to 1)
- Covariance magnitude depends on your variable units
- """)
-
- })
+ """),
+ }
+ )
return (exercises,)
+
@app.cell
def _(calculate_button, data_matrix, mo, np, pd, px):
results = None
@@ -115,7 +115,7 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
data = np.array(data_matrix.matrix, dtype=float)
if data.shape[0] != 2:
raise ValueError("Data must have exactly 2 rows (variables)")
-
+
# Check if we have enough data points
if data.shape[1] < 2:
raise ValueError("Need at least 2 data points for analysis")
@@ -126,22 +126,15 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
cov_matrix = np.cov(data)
# 3. visualization with covariance matrix
- df = pd.DataFrame({
- 'x': data[0],
- 'y': data[1]
- })
+ df = pd.DataFrame({"x": data[0], "y": data[1]})
scatter_fig = px.scatter(
df,
- x='x',
- y='y',
+ x="x",
+ y="y",
title="Variable Relationship Pattern",
- labels={'x': 'Variable 1', 'y': 'Variable 2'}
- ).update_layout(
- width=400,
- height=400,
- showlegend=False
- )
+ labels={"x": "Variable 1", "y": "Variable 2"},
+ ).update_layout(width=400, height=400, showlegend=False)
# appropriate trendline - with error handling for edge cases
try:
@@ -150,36 +143,42 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
x_range = np.linspace(min(data[0]), max(data[0]), 100)
scatter_fig.add_trace(
dict(
- type='scatter',
+ type="scatter",
x=x_range,
y=coeffs[0] * x_range + coeffs[1],
- mode='lines',
- line=dict(color='red', dash='dash'),
- name='Trend'
+ mode="lines",
+ line=dict(color="red", dash="dash"),
+ name="Trend",
)
)
else:
coeffs = (0, 0) # Default no slope
- x_range = np.array([min(data[0]), max(data[0])]) if len(data[0]) > 0 else np.array([0, 1])
- except Exception as trend_error:
+ x_range = (
+ np.array([min(data[0]), max(data[0])])
+ if len(data[0]) > 0
+ else np.array([0, 1])
+ )
+ except Exception:
coeffs = (0, 0) # Default fallback
x_range = np.array([0, 1])
-
+
# Calculate correlation coefficient
corr_matrix = np.corrcoef(data)
# 4. results with relevant explanations
- results = mo.vstack([
- mo.md("## Understanding Your Data's Covariance"),
-
- # First row: Plot and Matrix
- mo.hstack([
- # scatter plot
- mo.vstack([scatter_fig]),
-
- # covariance matrix
- mo.vstack([
- mo.md(r"""
+ results = mo.vstack(
+ [
+ mo.md("## Understanding Your Data's Covariance"),
+ # First row: Plot and Matrix
+ mo.hstack(
+ [
+ # scatter plot
+ mo.vstack([scatter_fig]),
+ # covariance matrix
+ mo.vstack(
+ [
+ mo.md(
+ r"""
**Covariance Matrix:**
$$
@@ -188,12 +187,16 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
%.2f & %.2f
\end{pmatrix}
$$
- """ % (
- cov_matrix[0,0], cov_matrix[0,1],
- cov_matrix[1,0], cov_matrix[1,1]
- )),
-
- mo.md(r"""
+ """
+ % (
+ cov_matrix[0, 0],
+ cov_matrix[0, 1],
+ cov_matrix[1, 0],
+ cov_matrix[1, 1],
+ )
+ ),
+ mo.md(
+ r"""
**Correlation Matrix:**
$$
@@ -202,18 +205,24 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
%.2f & %.2f
\end{pmatrix}
$$
- """ % (
- corr_matrix[0,0], corr_matrix[0,1],
- corr_matrix[1,0], corr_matrix[1,1]
- ))
- ])
- ]),
-
- # interpretation and insights side by side
- mo.hstack([
- # Left: Pattern Interpretation
- mo.callout(
- mo.md("""
+ """
+ % (
+ corr_matrix[0, 0],
+ corr_matrix[0, 1],
+ corr_matrix[1, 0],
+ corr_matrix[1, 1],
+ )
+ ),
+ ]
+ ),
+ ]
+ ),
+ # interpretation and insights side by side
+ mo.hstack(
+ [
+ # Left: Pattern Interpretation
+ mo.callout(
+ mo.md("""
**Pattern Interpretation:**
@@ -229,20 +238,19 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
- Off-diagonal: Show relationship strength
"""),
- kind="info"
- ),
-
- # Right: Key Insights
- mo.callout(
- mo.md(f"""
+ kind="info",
+ ),
+ # Right: Key Insights
+ mo.callout(
+ mo.md(f"""
**Key Insights:**
- 1. Relationship: {"Positive" if cov_matrix[0,1] > 0 else "Negative" if cov_matrix[0,1] < 0 else "No"} covariance
+ 1. Relationship: {"Positive" if cov_matrix[0, 1] > 0 else "Negative" if cov_matrix[0, 1] < 0 else "No"} covariance
- 2. Strength: {"Strong" if abs(corr_matrix[0,1]) > 0.7 else "Moderate" if abs(corr_matrix[0,1]) > 0.3 else "Weak"} correlation ({corr_matrix[0,1]:.2f})
+ 2. Strength: {"Strong" if abs(corr_matrix[0, 1]) > 0.7 else "Moderate" if abs(corr_matrix[0, 1]) > 0.3 else "Weak"} correlation ({corr_matrix[0, 1]:.2f})
- 3. Variances: ({cov_matrix[0,0]:.2f}, {cov_matrix[1,1]:.2f})
+ 3. Variances: ({cov_matrix[0, 0]:.2f}, {cov_matrix[1, 1]:.2f})
**Centered Data:**
```python
@@ -252,15 +260,20 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
Var2: {np.round(centered_data[1], 2)}
```
"""),
- kind="neutral"
- )
- ])
- ], justify='center')
+ kind="neutral",
+ ),
+ ]
+ ),
+ ],
+ justify="center",
+ )
except Exception as e:
results = mo.md(f"⚠️ Error: {str(e)}").callout(kind="danger")
# Initialize variables to None to avoid reference errors in case of exception
- centered_data = coeffs = cov_matrix = data = df = means = scatter_fig = x_range = corr_matrix = None
+ centered_data = coeffs = cov_matrix = data = df = means = scatter_fig = (
+ x_range
+ ) = corr_matrix = None
results
return (
centered_data,
@@ -275,12 +288,14 @@ def _(calculate_button, data_matrix, mo, np, pd, px):
x_range,
)
+
@app.cell(hide_code=True)
def _(mo):
# Conclusion
- conclusion = mo.vstack([
- mo.callout(
- mo.md("""
+ conclusion = mo.vstack(
+ [
+ mo.callout(
+ mo.md("""
**Congratulations!**
You've mastered the key concepts of covariance matrices:
@@ -292,12 +307,11 @@ def _(mo):
- The importance of centered data
"""),
- kind="success"
- ),
-
- mo.accordion({
-
- "🚀 Next Steps": mo.md("""
+ kind="success",
+ ),
+ mo.accordion(
+ {
+ "🚀 Next Steps": mo.md("""
1. Work with multivariate datasets (3+ variables)
2. Apply to real-world datasets with different scales
@@ -305,6 +319,8 @@ def _(mo):
4. Implement in machine learning projects
""")
- })
- ])
- return (conclusion,)
\ No newline at end of file
+ }
+ ),
+ ]
+ )
+ return (conclusion,)
diff --git a/questions/100_implement-the-softsign-activation-function/starter_code.py b/questions/100_implement-the-softsign-activation-function/starter_code.py
index 28ec96a5..694a0b70 100644
--- a/questions/100_implement-the-softsign-activation-function/starter_code.py
+++ b/questions/100_implement-the-softsign-activation-function/starter_code.py
@@ -1,12 +1,12 @@
def softsign(x: float) -> float:
- """
- Implements the Softsign activation function.
+ """
+ Implements the Softsign activation function.
- Args:
- x (float): Input value
+ Args:
+ x (float): Input value
- Returns:
- float: The Softsign of the input """
- # Your code here
- pass
- return round(val,4)
+ Returns:
+ float: The Softsign of the input"""
+ # Your code here
+ pass
+ return round(val, 4)
diff --git a/questions/101_implement-the-grpo-objective-function/solution.py b/questions/101_implement-the-grpo-objective-function/solution.py
index 32d5432b..9747d201 100644
--- a/questions/101_implement-the-grpo-objective-function/solution.py
+++ b/questions/101_implement-the-grpo-objective-function/solution.py
@@ -1,6 +1,9 @@
import numpy as np
-def grpo_objective(rhos, A, pi_theta_old, pi_theta_ref, epsilon=0.2, beta=0.01) -> float:
+
+def grpo_objective(
+ rhos, A, pi_theta_old, pi_theta_ref, epsilon=0.2, beta=0.01
+) -> float:
"""
Compute the GRPO objective function.
@@ -18,27 +21,29 @@ def grpo_objective(rhos, A, pi_theta_old, pi_theta_ref, epsilon=0.2, beta=0.01)
G = len(rhos)
if not (len(A) == len(pi_theta_old) == len(pi_theta_ref) == G):
raise ValueError("All input lists must have the same length.")
-
+
# Compute clipped likelihood ratios
clipped_rhos = np.clip(rhos, 1 - epsilon, 1 + epsilon)
-
+
# Compute the minimum terms for the objective
unclipped = np.array(rhos) * np.array(A)
clipped = clipped_rhos * np.array(A)
min_terms = np.minimum(unclipped, clipped)
average_min = np.mean(min_terms)
-
+
# Compute pi_theta from rhos and pi_theta_old
pi_theta = np.array(rhos) * np.array(pi_theta_old)
-
+
# Normalize pi_theta and pi_theta_ref to ensure they are valid probability distributions
pi_theta /= np.sum(pi_theta)
pi_theta_ref /= np.sum(pi_theta_ref)
-
+
# Compute KL divergence D_KL(pi_theta || pi_theta_ref)
- kl_divergence = np.sum(pi_theta * np.log(pi_theta / pi_theta_ref + 1e-10)) # Added epsilon to avoid log(0)
-
+ kl_divergence = np.sum(
+ pi_theta * np.log(pi_theta / pi_theta_ref + 1e-10)
+ ) # Added epsilon to avoid log(0)
+
# Compute the final objective
objective = average_min - beta * kl_divergence
-
+
return objective
diff --git a/questions/101_implement-the-grpo-objective-function/starter_code.py b/questions/101_implement-the-grpo-objective-function/starter_code.py
index ccde54a2..311c92a4 100644
--- a/questions/101_implement-the-grpo-objective-function/starter_code.py
+++ b/questions/101_implement-the-grpo-objective-function/starter_code.py
@@ -1,19 +1,19 @@
-import numpy as np
+def grpo_objective(
+ rhos, A, pi_theta_old, pi_theta_ref, epsilon=0.2, beta=0.01
+) -> float:
+ """
+ Compute the GRPO objective function.
-def grpo_objective(rhos, A, pi_theta_old, pi_theta_ref, epsilon=0.2, beta=0.01) -> float:
- """
- Compute the GRPO objective function.
+ Args:
+ rhos: List of likelihood ratios (p_i) = pi_theta(o_i | q) / pi_theta_old(o_i | q).
+ A: List of advantage estimates (A_i).
+ pi_theta_old: List representing the old policy probabilities pi_theta_old(o_i | q).
+ pi_theta_ref: List representing the reference policy probabilities pi_ref(o_i | q).
+ epsilon: Clipping parameter (eps).
+ beta: KL divergence penalty coefficient (beta).
- Args:
- rhos: List of likelihood ratios (p_i) = pi_theta(o_i | q) / pi_theta_old(o_i | q).
- A: List of advantage estimates (A_i).
- pi_theta_old: List representing the old policy probabilities pi_theta_old(o_i | q).
- pi_theta_ref: List representing the reference policy probabilities pi_ref(o_i | q).
- epsilon: Clipping parameter (eps).
- beta: KL divergence penalty coefficient (beta).
-
- Returns:
- The computed GRPO objective value.
- """
- # Your code here
- pass
+ Returns:
+ The computed GRPO objective value.
+ """
+ # Your code here
+ pass
diff --git a/questions/102_implement-the-swish-activation-function/solution.py b/questions/102_implement-the-swish-activation-function/solution.py
index e510aac8..be3e93fe 100644
--- a/questions/102_implement-the-swish-activation-function/solution.py
+++ b/questions/102_implement-the-swish-activation-function/solution.py
@@ -1,5 +1,6 @@
import math
+
def swish(x: float) -> float:
"""
Implements the Swish activation function.
diff --git a/questions/102_implement-the-swish-activation-function/starter_code.py b/questions/102_implement-the-swish-activation-function/starter_code.py
index a198140f..86949b83 100644
--- a/questions/102_implement-the-swish-activation-function/starter_code.py
+++ b/questions/102_implement-the-swish-activation-function/starter_code.py
@@ -1,12 +1,12 @@
def swish(x: float) -> float:
- """
- Implements the Swish activation function.
+ """
+ Implements the Swish activation function.
- Args:
- x: Input value
+ Args:
+ x: Input value
- Returns:
- The Swish activation value
- """
- # Your code here
- pass
+ Returns:
+ The Swish activation value
+ """
+ # Your code here
+ pass
diff --git a/questions/103_implement-the-selu-activation-function/solution.py b/questions/103_implement-the-selu-activation-function/solution.py
index 41caa2c8..37552ea9 100644
--- a/questions/103_implement-the-selu-activation-function/solution.py
+++ b/questions/103_implement-the-selu-activation-function/solution.py
@@ -1,5 +1,6 @@
import math
+
def selu(x: float) -> float:
"""
Implements the SELU (Scaled Exponential Linear Unit) activation function.
diff --git a/questions/103_implement-the-selu-activation-function/starter_code.py b/questions/103_implement-the-selu-activation-function/starter_code.py
index 5827c91b..38c25950 100644
--- a/questions/103_implement-the-selu-activation-function/starter_code.py
+++ b/questions/103_implement-the-selu-activation-function/starter_code.py
@@ -1,14 +1,12 @@
def selu(x: float) -> float:
- """
- Implements the SELU (Scaled Exponential Linear Unit) activation function.
+ """
+ Implements the SELU (Scaled Exponential Linear Unit) activation function.
- Args:
- x: Input value
+ Args:
+ x: Input value
- Returns:
- SELU activation value
- """
- alpha = 1.6732632423543772
- scale = 1.0507009873554804
- # Your code here
- pass
+ Returns:
+ SELU activation value
+ """
+ # Your code here
+ pass
diff --git a/questions/104_binary-classification-with-logistic-regression/solution.py b/questions/104_binary-classification-with-logistic-regression/solution.py
index ed5de9a2..030c45ae 100644
--- a/questions/104_binary-classification-with-logistic-regression/solution.py
+++ b/questions/104_binary-classification-with-logistic-regression/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def predict_logistic(X: np.ndarray, weights: np.ndarray, bias: float) -> np.ndarray:
"""
Implements binary classification prediction using Logistic Regression.
diff --git a/questions/104_binary-classification-with-logistic-regression/starter_code.py b/questions/104_binary-classification-with-logistic-regression/starter_code.py
index 7af3a008..720e9aef 100644
--- a/questions/104_binary-classification-with-logistic-regression/starter_code.py
+++ b/questions/104_binary-classification-with-logistic-regression/starter_code.py
@@ -1,16 +1,17 @@
import numpy as np
+
def predict_logistic(X: np.ndarray, weights: np.ndarray, bias: float) -> np.ndarray:
- """
- Implements binary classification prediction using Logistic Regression.
+ """
+ Implements binary classification prediction using Logistic Regression.
- Args:
- X: Input feature matrix (shape: N x D)
- weights: Model weights (shape: D)
- bias: Model bias
+ Args:
+ X: Input feature matrix (shape: N x D)
+ weights: Model weights (shape: D)
+ bias: Model bias
- Returns:
- Binary predictions (0 or 1)
- """
- # Your code here
- pass
+ Returns:
+ Binary predictions (0 or 1)
+ """
+ # Your code here
+ pass
diff --git a/questions/105_train-softmax-regression-with-gradient-descent/solution.py b/questions/105_train-softmax-regression-with-gradient-descent/solution.py
index 55b2ea21..2f886ec7 100644
--- a/questions/105_train-softmax-regression-with-gradient-descent/solution.py
+++ b/questions/105_train-softmax-regression-with-gradient-descent/solution.py
@@ -1,9 +1,10 @@
import numpy as np
-def train_softmaxreg(X: np.ndarray, y: np.ndarray,
- learning_rate: float, iterations: int) -> tuple[list[float], ...]:
- '''
+def train_softmaxreg(
+ X: np.ndarray, y: np.ndarray, learning_rate: float, iterations: int
+) -> tuple[list[float], ...]:
+ """
Gradient-descent training algorithm for softmax regression, that collects mean-reduced
CE losses, accuracies.
Returns
@@ -12,20 +13,22 @@ def train_softmaxreg(X: np.ndarray, y: np.ndarray,
CxM updated parameter vector rounded to 4 floating points
losses : list[float]
collected values of a Cross Entropy rounded to 4 floating points
- '''
+ """
def softmax(z):
return np.exp(z) / np.sum(np.exp(z), axis=1, keepdims=True)
def accuracy(y_pred, y_true):
- return (np.argmax(y_true, axis=1) == np.argmax(y_pred, axis=1)).sum() / len(y_true)
+ return (np.argmax(y_true, axis=1) == np.argmax(y_pred, axis=1)).sum() / len(
+ y_true
+ )
def ce_loss(y_pred, y_true):
true_labels_idx = np.argmax(y_true, axis=1)
- return -np.sum(np.log(y_pred)[list(range(len(y_pred))),true_labels_idx])
+ return -np.sum(np.log(y_pred)[list(range(len(y_pred))), true_labels_idx])
y = y.astype(int)
- C = y.max()+1 # we assume that classes start from 0
+ C = y.max() + 1 # we assume that classes start from 0
y = np.eye(C)[y]
X = np.hstack((np.ones((X.shape[0], 1)), X))
B = np.zeros((X.shape[1], C))
diff --git a/questions/105_train-softmax-regression-with-gradient-descent/starter_code.py b/questions/105_train-softmax-regression-with-gradient-descent/starter_code.py
index 0e93e504..3f984a8d 100644
--- a/questions/105_train-softmax-regression-with-gradient-descent/starter_code.py
+++ b/questions/105_train-softmax-regression-with-gradient-descent/starter_code.py
@@ -1,8 +1,11 @@
import numpy as np
-def train_softmaxreg(X: np.ndarray, y: np.ndarray, learning_rate: float, iterations: int) -> tuple[list[float], ...]:
- """
- Gradient-descent training algorithm for Softmax regression, optimizing parameters with Cross Entropy loss.
- """
- # Your code here
- pass
+
+def train_softmaxreg(
+ X: np.ndarray, y: np.ndarray, learning_rate: float, iterations: int
+) -> tuple[list[float], ...]:
+ """
+ Gradient-descent training algorithm for Softmax regression, optimizing parameters with Cross Entropy loss.
+ """
+ # Your code here
+ pass
diff --git a/questions/106_train-logistic-regression-with-gradient-descent/solution.py b/questions/106_train-logistic-regression-with-gradient-descent/solution.py
index 8db5fae1..742283a7 100644
--- a/questions/106_train-logistic-regression-with-gradient-descent/solution.py
+++ b/questions/106_train-logistic-regression-with-gradient-descent/solution.py
@@ -1,9 +1,13 @@
import numpy as np
-def train_logreg(X: np.ndarray, y: np.ndarray, learning_rate: float, iterations: int) -> tuple[list[float], ...]:
+
+def train_logreg(
+ X: np.ndarray, y: np.ndarray, learning_rate: float, iterations: int
+) -> tuple[list[float], ...]:
"""
Gradient-descent training algorithm for logistic regression, optimizing parameters with Binary Cross Entropy loss.
"""
+
def sigmoid(x):
return 1 / (1 + np.exp(-x))
diff --git a/questions/106_train-logistic-regression-with-gradient-descent/starter_code.py b/questions/106_train-logistic-regression-with-gradient-descent/starter_code.py
index 29bd086c..71eb660f 100644
--- a/questions/106_train-logistic-regression-with-gradient-descent/starter_code.py
+++ b/questions/106_train-logistic-regression-with-gradient-descent/starter_code.py
@@ -1,8 +1,11 @@
import numpy as np
-def train_logreg(X: np.ndarray, y: np.ndarray, learning_rate: float, iterations: int) -> tuple[list[float], ...]:
- """
- Gradient-descent training algorithm for logistic regression, optimizing parameters with Binary Cross Entropy loss.
- """
- # Your code here
- pass
+
+def train_logreg(
+ X: np.ndarray, y: np.ndarray, learning_rate: float, iterations: int
+) -> tuple[list[float], ...]:
+ """
+ Gradient-descent training algorithm for logistic regression, optimizing parameters with Binary Cross Entropy loss.
+ """
+ # Your code here
+ pass
diff --git a/questions/107_implement-masked-self-attention/solution.py b/questions/107_implement-masked-self-attention/solution.py
index c78be60f..291bbf5f 100644
--- a/questions/107_implement-masked-self-attention/solution.py
+++ b/questions/107_implement-masked-self-attention/solution.py
@@ -1,15 +1,21 @@
import numpy as np
+
def compute_qkv(X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray):
Q = np.dot(X, W_q)
K = np.dot(X, W_k)
V = np.dot(X, W_v)
return Q, K, V
-def masked_attention(Q: np.ndarray, K: np.ndarray, V: np.ndarray, mask: np.ndarray) -> np.ndarray:
+
+def masked_attention(
+ Q: np.ndarray, K: np.ndarray, V: np.ndarray, mask: np.ndarray
+) -> np.ndarray:
d_k = Q.shape[1]
scores = np.matmul(Q, K.T) / np.sqrt(d_k)
scores = scores + mask # Apply mask
attention_weights = np.exp(scores - np.max(scores, axis=1, keepdims=True))
- attention_weights = attention_weights / np.sum(attention_weights, axis=1, keepdims=True)
+ attention_weights = attention_weights / np.sum(
+ attention_weights, axis=1, keepdims=True
+ )
return np.matmul(attention_weights, V)
diff --git a/questions/107_implement-masked-self-attention/starter_code.py b/questions/107_implement-masked-self-attention/starter_code.py
index 48a14241..2f5aeabe 100644
--- a/questions/107_implement-masked-self-attention/starter_code.py
+++ b/questions/107_implement-masked-self-attention/starter_code.py
@@ -1,14 +1,18 @@
import numpy as np
+
def compute_qkv(X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray):
- """
- Compute Query (Q), Key (K), and Value (V) matrices.
- """
- return np.dot(X, W_q), np.dot(X, W_k), np.dot(X, W_v)
-
-def masked_attention(Q: np.ndarray, K: np.ndarray, V: np.ndarray, mask: np.ndarray) -> np.ndarray:
- """
- Compute masked self-attention.
- """
- # Your code here
- pass
+ """
+ Compute Query (Q), Key (K), and Value (V) matrices.
+ """
+ return np.dot(X, W_q), np.dot(X, W_k), np.dot(X, W_v)
+
+
+def masked_attention(
+ Q: np.ndarray, K: np.ndarray, V: np.ndarray, mask: np.ndarray
+) -> np.ndarray:
+ """
+ Compute masked self-attention.
+ """
+ # Your code here
+ pass
diff --git a/questions/108_measure-disorder-in-apple-colors/starter_code.py b/questions/108_measure-disorder-in-apple-colors/starter_code.py
index 8c8f45cc..f7ea83ec 100644
--- a/questions/108_measure-disorder-in-apple-colors/starter_code.py
+++ b/questions/108_measure-disorder-in-apple-colors/starter_code.py
@@ -1,6 +1,6 @@
def disorder(apples: list) -> float:
- """
- Compute the disorder in a basket of apples.
- """
- # Your code here
- pass
+ """
+ Compute the disorder in a basket of apples.
+ """
+ # Your code here
+ pass
diff --git a/questions/109_implement-layer-normalization-for-sequence-data/solution.py b/questions/109_implement-layer-normalization-for-sequence-data/solution.py
index 7e7c8afb..6cb956f6 100644
--- a/questions/109_implement-layer-normalization-for-sequence-data/solution.py
+++ b/questions/109_implement-layer-normalization-for-sequence-data/solution.py
@@ -1,6 +1,9 @@
import numpy as np
-def layer_normalization(X: np.ndarray, gamma: np.ndarray, beta: np.ndarray, epsilon: float = 1e-5) -> np.ndarray:
+
+def layer_normalization(
+ X: np.ndarray, gamma: np.ndarray, beta: np.ndarray, epsilon: float = 1e-5
+) -> np.ndarray:
"""
Perform Layer Normalization.
"""
diff --git a/questions/109_implement-layer-normalization-for-sequence-data/starter_code.py b/questions/109_implement-layer-normalization-for-sequence-data/starter_code.py
index 113b2986..b2de3d93 100644
--- a/questions/109_implement-layer-normalization-for-sequence-data/starter_code.py
+++ b/questions/109_implement-layer-normalization-for-sequence-data/starter_code.py
@@ -1,8 +1,11 @@
import numpy as np
-def layer_normalization(X: np.ndarray, gamma: np.ndarray, beta: np.ndarray, epsilon: float = 1e-5) -> np.ndarray:
- """
- Perform Layer Normalization.
- """
- # Your code here
- pass
+
+def layer_normalization(
+ X: np.ndarray, gamma: np.ndarray, beta: np.ndarray, epsilon: float = 1e-5
+) -> np.ndarray:
+ """
+ Perform Layer Normalization.
+ """
+ # Your code here
+ pass
diff --git a/questions/10_calculate-covariance-matrix/pytorch/solution.py b/questions/10_calculate-covariance-matrix/pytorch/solution.py
index d21cbe1d..1b89a196 100644
--- a/questions/10_calculate-covariance-matrix/pytorch/solution.py
+++ b/questions/10_calculate-covariance-matrix/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def calculate_covariance_matrix(vectors) -> torch.Tensor:
"""
Calculate the covariance matrix for given feature vectors using PyTorch.
diff --git a/questions/10_calculate-covariance-matrix/pytorch/starter_code.py b/questions/10_calculate-covariance-matrix/pytorch/starter_code.py
index a0a8e878..a5f6e66c 100644
--- a/questions/10_calculate-covariance-matrix/pytorch/starter_code.py
+++ b/questions/10_calculate-covariance-matrix/pytorch/starter_code.py
@@ -1,11 +1,12 @@
import torch
+
def calculate_covariance_matrix(vectors) -> torch.Tensor:
"""
Calculate the covariance matrix for given feature vectors using PyTorch.
Input: 2D array-like of shape (n_features, n_observations).
Returns a tensor of shape (n_features, n_features).
"""
- v_t = torch.as_tensor(vectors, dtype=torch.float)
+ torch.as_tensor(vectors, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/10_calculate-covariance-matrix/solution.py b/questions/10_calculate-covariance-matrix/solution.py
index 3a7d9b92..24ce4d52 100644
--- a/questions/10_calculate-covariance-matrix/solution.py
+++ b/questions/10_calculate-covariance-matrix/solution.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def calculate_covariance_matrix(vectors: list[list[float]]) -> list[list[float]]:
n_observations = len(vectors)
n_features = len(vectors[0])
diff --git a/questions/10_calculate-covariance-matrix/starter_code.py b/questions/10_calculate-covariance-matrix/starter_code.py
index d19a47d4..3e1585ae 100644
--- a/questions/10_calculate-covariance-matrix/starter_code.py
+++ b/questions/10_calculate-covariance-matrix/starter_code.py
@@ -1,3 +1,3 @@
def calculate_covariance_matrix(vectors: list[list[float]]) -> list[list[float]]:
- # Your code here
- return []
+ # Your code here
+ return []
diff --git a/questions/10_calculate-covariance-matrix/tinygrad/solution.py b/questions/10_calculate-covariance-matrix/tinygrad/solution.py
index 17fd97bd..0f20a93e 100644
--- a/questions/10_calculate-covariance-matrix/tinygrad/solution.py
+++ b/questions/10_calculate-covariance-matrix/tinygrad/solution.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def calculate_covariance_matrix_tg(vectors) -> Tensor:
"""
Calculate the covariance matrix for given feature vectors using tinygrad.
@@ -9,7 +10,7 @@ def calculate_covariance_matrix_tg(vectors) -> Tensor:
v_t = Tensor(vectors).float()
n_features, n_obs = v_t.shape
# compute feature means
- means = v_t.sum(axis=1).reshape(n_features,1) / n_obs
+ means = v_t.sum(axis=1).reshape(n_features, 1) / n_obs
centered = v_t - means
- cov = centered.matmul(centered.transpose(0,1)) / (n_obs - 1)
+ cov = centered.matmul(centered.transpose(0, 1)) / (n_obs - 1)
return cov
diff --git a/questions/10_calculate-covariance-matrix/tinygrad/starter_code.py b/questions/10_calculate-covariance-matrix/tinygrad/starter_code.py
index ce185fba..66baf0c8 100644
--- a/questions/10_calculate-covariance-matrix/tinygrad/starter_code.py
+++ b/questions/10_calculate-covariance-matrix/tinygrad/starter_code.py
@@ -1,11 +1,12 @@
from tinygrad.tensor import Tensor
+
def calculate_covariance_matrix_tg(vectors) -> Tensor:
"""
Calculate the covariance matrix for given feature vectors using tinygrad.
Input: 2D array-like of shape (n_features, n_observations).
Returns a Tensor of shape (n_features, n_features).
"""
- v_t = Tensor(vectors).float()
+ Tensor(vectors).float()
# Your implementation here
pass
diff --git a/questions/110_evaluate-translation-quality-with-meteor-score/starter_code.py b/questions/110_evaluate-translation-quality-with-meteor-score/starter_code.py
index e92f6c7d..e425a96e 100644
--- a/questions/110_evaluate-translation-quality-with-meteor-score/starter_code.py
+++ b/questions/110_evaluate-translation-quality-with-meteor-score/starter_code.py
@@ -1,6 +1,3 @@
-import numpy as np
-from collections import Counter
-
def meteor_score(reference, candidate, alpha=0.9, beta=3, gamma=0.5):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/111_compute-pointwise-mutual-information/solution.py b/questions/111_compute-pointwise-mutual-information/solution.py
index c8d947fb..4c6f0435 100644
--- a/questions/111_compute-pointwise-mutual-information/solution.py
+++ b/questions/111_compute-pointwise-mutual-information/solution.py
@@ -1,8 +1,11 @@
import numpy as np
-def compute_pmi(joint_counts, total_counts_x, total_counts_y, total_samples):
- if not all(isinstance(x, int) and x >= 0 for x in [joint_counts, total_counts_x, total_counts_y, total_samples]):
+def compute_pmi(joint_counts, total_counts_x, total_counts_y, total_samples):
+ if not all(
+ isinstance(x, int) and x >= 0
+ for x in [joint_counts, total_counts_x, total_counts_y, total_samples]
+ ):
raise ValueError("All inputs must be non-negative integers.")
if total_samples == 0:
@@ -16,7 +19,7 @@ def compute_pmi(joint_counts, total_counts_x, total_counts_y, total_samples):
p_xy = joint_counts / total_samples
if p_xy == 0:
- return float('-inf')
+ return float("-inf")
pmi = np.log2(p_xy / (p_x * p_y))
diff --git a/questions/111_compute-pointwise-mutual-information/starter_code.py b/questions/111_compute-pointwise-mutual-information/starter_code.py
index 074a1b49..bbaa58e7 100644
--- a/questions/111_compute-pointwise-mutual-information/starter_code.py
+++ b/questions/111_compute-pointwise-mutual-information/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def compute_pmi(joint_counts, total_counts_x, total_counts_y, total_samples):
- # Implement PMI calculation here
- pass
+ # Implement PMI calculation here
+ pass
diff --git a/questions/112_min-max-normalization-of-feature-values/starter_code.py b/questions/112_min-max-normalization-of-feature-values/starter_code.py
index 8576094f..9616a244 100644
--- a/questions/112_min-max-normalization-of-feature-values/starter_code.py
+++ b/questions/112_min-max-normalization-of-feature-values/starter_code.py
@@ -1,3 +1,3 @@
def min_max(x: list[int]) -> list[float]:
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/113_implement-a-simple-residual-block-with-shortcut-co/solution.py b/questions/113_implement-a-simple-residual-block-with-shortcut-co/solution.py
index 72c43423..bffae114 100644
--- a/questions/113_implement-a-simple-residual-block-with-shortcut-co/solution.py
+++ b/questions/113_implement-a-simple-residual-block-with-shortcut-co/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def residual_block(x: np.ndarray, w1: np.ndarray, w2: np.ndarray) -> np.ndarray:
# First weight layer
y = np.dot(w1, x)
diff --git a/questions/113_implement-a-simple-residual-block-with-shortcut-co/starter_code.py b/questions/113_implement-a-simple-residual-block-with-shortcut-co/starter_code.py
index fa60a0c2..dbad4dbb 100644
--- a/questions/113_implement-a-simple-residual-block-with-shortcut-co/starter_code.py
+++ b/questions/113_implement-a-simple-residual-block-with-shortcut-co/starter_code.py
@@ -1,5 +1,6 @@
import numpy as np
+
def residual_block(x: np.ndarray, w1: np.ndarray, w2: np.ndarray) -> np.ndarray:
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/114_implement-global-average-pooling/solution.py b/questions/114_implement-global-average-pooling/solution.py
index 392baa3e..c860ac53 100644
--- a/questions/114_implement-global-average-pooling/solution.py
+++ b/questions/114_implement-global-average-pooling/solution.py
@@ -1,4 +1,5 @@
import numpy as np
+
def global_avg_pool(x: np.ndarray) -> np.ndarray:
return np.mean(x, axis=(0, 1))
diff --git a/questions/114_implement-global-average-pooling/starter_code.py b/questions/114_implement-global-average-pooling/starter_code.py
index d2a5b571..ffad9e54 100644
--- a/questions/114_implement-global-average-pooling/starter_code.py
+++ b/questions/114_implement-global-average-pooling/starter_code.py
@@ -1,5 +1,6 @@
import numpy as np
+
def global_avg_pool(x: np.ndarray) -> np.ndarray:
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/115_implement-batch-normalization-for-bchw-input/solution.py b/questions/115_implement-batch-normalization-for-bchw-input/solution.py
index 9ac70d49..8192edb5 100644
--- a/questions/115_implement-batch-normalization-for-bchw-input/solution.py
+++ b/questions/115_implement-batch-normalization-for-bchw-input/solution.py
@@ -1,6 +1,9 @@
import numpy as np
-def batch_normalization(X: np.ndarray, gamma: np.ndarray, beta: np.ndarray, epsilon: float = 1e-5) -> np.ndarray:
+
+def batch_normalization(
+ X: np.ndarray, gamma: np.ndarray, beta: np.ndarray, epsilon: float = 1e-5
+) -> np.ndarray:
# Compute mean and variance across the batch and spatial dimensions
mean = np.mean(X, axis=(0, 2, 3), keepdims=True) # Mean over (B, H, W)
variance = np.var(X, axis=(0, 2, 3), keepdims=True) # Variance over (B, H, W)
diff --git a/questions/115_implement-batch-normalization-for-bchw-input/starter_code.py b/questions/115_implement-batch-normalization-for-bchw-input/starter_code.py
index 00f654ab..8c770457 100644
--- a/questions/115_implement-batch-normalization-for-bchw-input/starter_code.py
+++ b/questions/115_implement-batch-normalization-for-bchw-input/starter_code.py
@@ -1,5 +1,8 @@
import numpy as np
-def batch_normalization(X: np.ndarray, gamma: np.ndarray, beta: np.ndarray, epsilon: float = 1e-5) -> np.ndarray:
- # Your code here
- pass
+
+def batch_normalization(
+ X: np.ndarray, gamma: np.ndarray, beta: np.ndarray, epsilon: float = 1e-5
+) -> np.ndarray:
+ # Your code here
+ pass
diff --git a/questions/117_compute-orthonormal-basis-for-2d-vectors/solution.py b/questions/117_compute-orthonormal-basis-for-2d-vectors/solution.py
index ec67479b..7bfdd236 100644
--- a/questions/117_compute-orthonormal-basis-for-2d-vectors/solution.py
+++ b/questions/117_compute-orthonormal-basis-for-2d-vectors/solution.py
@@ -1,6 +1,9 @@
import numpy as np
-def orthonormal_basis(vectors: list[list[float]], tol: float = 1e-10) -> list[np.ndarray]:
+
+def orthonormal_basis(
+ vectors: list[list[float]], tol: float = 1e-10
+) -> list[np.ndarray]:
basis = []
for v in vectors:
v = np.array(v, dtype=float)
diff --git a/questions/117_compute-orthonormal-basis-for-2d-vectors/starter_code.py b/questions/117_compute-orthonormal-basis-for-2d-vectors/starter_code.py
index d48f8721..89b38df9 100644
--- a/questions/117_compute-orthonormal-basis-for-2d-vectors/starter_code.py
+++ b/questions/117_compute-orthonormal-basis-for-2d-vectors/starter_code.py
@@ -1,5 +1,8 @@
import numpy as np
-def orthonormal_basis(vectors: list[list[float]], tol: float = 1e-10) -> list[np.ndarray]:
+
+def orthonormal_basis(
+ vectors: list[list[float]], tol: float = 1e-10
+) -> list[np.ndarray]:
# Your code here
pass
diff --git a/questions/118_compute-the-cross-product-of-two-3d-vectors/solution.py b/questions/118_compute-the-cross-product-of-two-3d-vectors/solution.py
index 7b794769..fea1845f 100644
--- a/questions/118_compute-the-cross-product-of-two-3d-vectors/solution.py
+++ b/questions/118_compute-the-cross-product-of-two-3d-vectors/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def cross_product(a, b):
"""
Compute the cross product of two 3D vectors a and b.
@@ -15,9 +16,11 @@ def cross_product(a, b):
if a.shape != (3,) or b.shape != (3,):
raise ValueError("Both input vectors must be of length 3.")
- cross = np.array([
- a[1] * b[2] - a[2] * b[1],
- a[2] * b[0] - a[0] * b[2],
- a[0] * b[1] - a[1] * b[0]
- ])
+ cross = np.array(
+ [
+ a[1] * b[2] - a[2] * b[1],
+ a[2] * b[0] - a[0] * b[2],
+ a[0] * b[1] - a[1] * b[0],
+ ]
+ )
return cross
diff --git a/questions/118_compute-the-cross-product-of-two-3d-vectors/starter_code.py b/questions/118_compute-the-cross-product-of-two-3d-vectors/starter_code.py
index e035d042..46d47cc2 100644
--- a/questions/118_compute-the-cross-product-of-two-3d-vectors/starter_code.py
+++ b/questions/118_compute-the-cross-product-of-two-3d-vectors/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def cross_product(a, b):
# Your code here
pass
diff --git a/questions/119_solve-system-of-linear-equations-using-cramer-s-ru/solution.py b/questions/119_solve-system-of-linear-equations-using-cramer-s-ru/solution.py
index 37be8292..bae7faf5 100644
--- a/questions/119_solve-system-of-linear-equations-using-cramer-s-ru/solution.py
+++ b/questions/119_solve-system-of-linear-equations-using-cramer-s-ru/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def cramers_rule(A, b):
A = np.array(A, dtype=float)
b = np.array(b, dtype=float)
diff --git a/questions/119_solve-system-of-linear-equations-using-cramer-s-ru/starter_code.py b/questions/119_solve-system-of-linear-equations-using-cramer-s-ru/starter_code.py
index b99c6a91..aeb0c34f 100644
--- a/questions/119_solve-system-of-linear-equations-using-cramer-s-ru/starter_code.py
+++ b/questions/119_solve-system-of-linear-equations-using-cramer-s-ru/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def cramers_rule(A, b):
# Your code here
pass
diff --git a/questions/11_solve-linear-equations-using-jacobi-method/pytorch/solution.py b/questions/11_solve-linear-equations-using-jacobi-method/pytorch/solution.py
index c4a81c43..28a79bfa 100644
--- a/questions/11_solve-linear-equations-using-jacobi-method/pytorch/solution.py
+++ b/questions/11_solve-linear-equations-using-jacobi-method/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def solve_jacobi(A, b, n) -> torch.Tensor:
"""
Solve Ax = b using the Jacobi iterative method for n iterations.
diff --git a/questions/11_solve-linear-equations-using-jacobi-method/pytorch/starter_code.py b/questions/11_solve-linear-equations-using-jacobi-method/pytorch/starter_code.py
index 563e4d7a..af979fa0 100644
--- a/questions/11_solve-linear-equations-using-jacobi-method/pytorch/starter_code.py
+++ b/questions/11_solve-linear-equations-using-jacobi-method/pytorch/starter_code.py
@@ -1,12 +1,13 @@
import torch
+
def solve_jacobi(A, b, n) -> torch.Tensor:
"""
Solve Ax = b using the Jacobi iterative method for n iterations.
A: (m,m) tensor; b: (m,) tensor; n: number of iterations.
Returns a 1-D tensor of length m, rounded to 4 decimals.
"""
- A_t = torch.as_tensor(A, dtype=torch.float)
- b_t = torch.as_tensor(b, dtype=torch.float)
+ torch.as_tensor(A, dtype=torch.float)
+ torch.as_tensor(b, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/11_solve-linear-equations-using-jacobi-method/solution.py b/questions/11_solve-linear-equations-using-jacobi-method/solution.py
index e6c1cded..8ef58cb1 100644
--- a/questions/11_solve-linear-equations-using-jacobi-method/solution.py
+++ b/questions/11_solve-linear-equations-using-jacobi-method/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def solve_jacobi(A: np.ndarray, b: np.ndarray, n: int) -> list:
d_a = np.diag(A)
nda = A - np.diag(d_a)
@@ -7,6 +8,6 @@ def solve_jacobi(A: np.ndarray, b: np.ndarray, n: int) -> list:
x_hold = np.zeros(len(b))
for _ in range(n):
for i in range(len(A)):
- x_hold[i] = (1/d_a[i]) * (b[i] - sum(nda[i]*x))
+ x_hold[i] = (1 / d_a[i]) * (b[i] - sum(nda[i] * x))
x = x_hold.copy()
- return np.round(x,4).tolist()
+ return np.round(x, 4).tolist()
diff --git a/questions/11_solve-linear-equations-using-jacobi-method/starter_code.py b/questions/11_solve-linear-equations-using-jacobi-method/starter_code.py
index acbd4e67..873474c8 100644
--- a/questions/11_solve-linear-equations-using-jacobi-method/starter_code.py
+++ b/questions/11_solve-linear-equations-using-jacobi-method/starter_code.py
@@ -1,3 +1,5 @@
import numpy as np
+
+
def solve_jacobi(A: np.ndarray, b: np.ndarray, n: int) -> list:
- return x
+ return x
diff --git a/questions/11_solve-linear-equations-using-jacobi-method/tinygrad/solution.py b/questions/11_solve-linear-equations-using-jacobi-method/tinygrad/solution.py
index 3bbb2b3c..cdb81de4 100644
--- a/questions/11_solve-linear-equations-using-jacobi-method/tinygrad/solution.py
+++ b/questions/11_solve-linear-equations-using-jacobi-method/tinygrad/solution.py
@@ -1,6 +1,7 @@
import numpy as np
from tinygrad.tensor import Tensor
+
def solve_jacobi_tg(A, b, n) -> Tensor:
"""
Solve Ax = b using the Jacobi iterative method for n iterations in tinygrad.
@@ -11,12 +12,12 @@ def solve_jacobi_tg(A, b, n) -> Tensor:
b_t = Tensor(b).float()
m = A_t.shape[0]
# extract diagonal
- d_list = [A_t[i,i] for i in range(m)]
+ d_list = [A_t[i, i] for i in range(m)]
d = Tensor(d_list)
# build remainder matrix
- nda_list = [[A_t[i,j] if i != j else 0 for j in range(m)] for i in range(m)]
+ nda_list = [[A_t[i, j] if i != j else 0 for j in range(m)] for i in range(m)]
nda = Tensor(nda_list).float()
- x = Tensor([0.0]*m).float()
+ x = Tensor([0.0] * m).float()
for _ in range(n):
x = (b_t - nda.matmul(x)) / d
res = x.numpy()
diff --git a/questions/11_solve-linear-equations-using-jacobi-method/tinygrad/starter_code.py b/questions/11_solve-linear-equations-using-jacobi-method/tinygrad/starter_code.py
index 26576d3f..e9411833 100644
--- a/questions/11_solve-linear-equations-using-jacobi-method/tinygrad/starter_code.py
+++ b/questions/11_solve-linear-equations-using-jacobi-method/tinygrad/starter_code.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def solve_jacobi_tg(A, b, n) -> Tensor:
"""
Solve Ax = b using the Jacobi iterative method for n iterations in tinygrad.
diff --git a/questions/120_bhattacharyya-distance-between-two-distributions/solution.py b/questions/120_bhattacharyya-distance-between-two-distributions/solution.py
index 608e3f15..afffafc6 100644
--- a/questions/120_bhattacharyya-distance-between-two-distributions/solution.py
+++ b/questions/120_bhattacharyya-distance-between-two-distributions/solution.py
@@ -1,6 +1,7 @@
import numpy as np
-def bhattacharyya_distance(p : list[float], q : list[float]) -> float:
+
+def bhattacharyya_distance(p: list[float], q: list[float]) -> float:
if len(p) != len(q):
return 0.0
diff --git a/questions/120_bhattacharyya-distance-between-two-distributions/starter_code.py b/questions/120_bhattacharyya-distance-between-two-distributions/starter_code.py
index d2fe857f..19cdb443 100644
--- a/questions/120_bhattacharyya-distance-between-two-distributions/starter_code.py
+++ b/questions/120_bhattacharyya-distance-between-two-distributions/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def bhattacharyya_distance(p: list[float], q: list[float]) -> float:
# Your code here
pass
diff --git a/questions/121_vector-element-wise-sum/solution.py b/questions/121_vector-element-wise-sum/solution.py
index 27adfeec..51c81295 100644
--- a/questions/121_vector-element-wise-sum/solution.py
+++ b/questions/121_vector-element-wise-sum/solution.py
@@ -1,4 +1,4 @@
-def vector_sum(a: list[int|float], b: list[int|float]) -> list[int|float]:
+def vector_sum(a: list[int | float], b: list[int | float]) -> list[int | float]:
if len(a) != len(b):
return -1
return [a[i] + b[i] for i in range(len(a))]
diff --git a/questions/121_vector-element-wise-sum/starter_code.py b/questions/121_vector-element-wise-sum/starter_code.py
index 7549d00a..f3b099f8 100644
--- a/questions/121_vector-element-wise-sum/starter_code.py
+++ b/questions/121_vector-element-wise-sum/starter_code.py
@@ -1,4 +1,4 @@
-def vector_sum(a: list[int|float], b: list[int|float]) -> list[int|float]:
- # Return the element-wise sum of vectors 'a' and 'b'.
- # If vectors have different lengths, return -1.
- pass
+def vector_sum(a: list[int | float], b: list[int | float]) -> list[int | float]:
+ # Return the element-wise sum of vectors 'a' and 'b'.
+ # If vectors have different lengths, return -1.
+ pass
diff --git a/questions/122_policy-gradient-with-reinforce/solution.py b/questions/122_policy-gradient-with-reinforce/solution.py
index 1797b961..4dadd233 100644
--- a/questions/122_policy-gradient-with-reinforce/solution.py
+++ b/questions/122_policy-gradient-with-reinforce/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def compute_policy_gradient(theta, episodes):
def softmax(x):
x = x - np.max(x)
diff --git a/questions/122_policy-gradient-with-reinforce/starter_code.py b/questions/122_policy-gradient-with-reinforce/starter_code.py
index 816d333c..4caaa342 100644
--- a/questions/122_policy-gradient-with-reinforce/starter_code.py
+++ b/questions/122_policy-gradient-with-reinforce/starter_code.py
@@ -1,6 +1,9 @@
import numpy as np
-def compute_policy_gradient(theta: np.ndarray, episodes: list[list[tuple[int, int, float]]]) -> np.ndarray:
+
+def compute_policy_gradient(
+ theta: np.ndarray, episodes: list[list[tuple[int, int, float]]]
+) -> np.ndarray:
"""
Estimate the policy gradient using REINFORCE.
diff --git a/questions/124_implement-the-noisy-top-k-gating-function/solution.py b/questions/124_implement-the-noisy-top-k-gating-function/solution.py
index a079bd58..a953a1d1 100644
--- a/questions/124_implement-the-noisy-top-k-gating-function/solution.py
+++ b/questions/124_implement-the-noisy-top-k-gating-function/solution.py
@@ -1,11 +1,8 @@
import numpy as np
+
def noisy_topk_gating(
- X: np.ndarray,
- W_g: np.ndarray,
- W_noise: np.ndarray,
- N: np.ndarray,
- k: int
+ X: np.ndarray, W_g: np.ndarray, W_noise: np.ndarray, N: np.ndarray, k: int
) -> np.ndarray:
H_base = X @ W_g
H_noise = X @ W_noise
diff --git a/questions/124_implement-the-noisy-top-k-gating-function/starter_code.py b/questions/124_implement-the-noisy-top-k-gating-function/starter_code.py
index 1d02b699..099eb634 100644
--- a/questions/124_implement-the-noisy-top-k-gating-function/starter_code.py
+++ b/questions/124_implement-the-noisy-top-k-gating-function/starter_code.py
@@ -1,11 +1,8 @@
import numpy as np
+
def noisy_topk_gating(
- X: np.ndarray,
- W_g: np.ndarray,
- W_noise: np.ndarray,
- N: np.ndarray,
- k: int
+ X: np.ndarray, W_g: np.ndarray, W_noise: np.ndarray, N: np.ndarray, k: int
) -> np.ndarray:
"""
Args:
diff --git a/questions/125_implement-a-sparse-mixture-of-experts-layer/solution.py b/questions/125_implement-a-sparse-mixture-of-experts-layer/solution.py
index 6071d4c8..632c4bf3 100644
--- a/questions/125_implement-a-sparse-mixture-of-experts-layer/solution.py
+++ b/questions/125_implement-a-sparse-mixture-of-experts-layer/solution.py
@@ -1,24 +1,29 @@
import numpy as np
+
def softmax(x: np.ndarray, axis: int = -1) -> np.ndarray:
exp_x = np.exp(x - np.max(x, axis=axis, keepdims=True))
return exp_x / np.sum(exp_x, axis=axis, keepdims=True)
+
def get_top_k(arr: np.ndarray, k: int):
idx = np.argpartition(arr, -k)[..., -k:]
vals = np.take_along_axis(arr, idx, axis=-1)
return idx, vals
+
def expert(x: np.ndarray, We_i: np.ndarray):
# x: [n_tokens, d_model]
# We_i: [d_model, d_model]
return x @ We_i
+
def gate(x: np.ndarray, Wg: np.ndarray):
# x: [n_batch * l_seq, d_model]
# Wg: [n_batch * l_seq, n_experts]
return x @ Wg
+
def moe(x: np.ndarray, We: np.ndarray, Wg: np.ndarray, n_experts: int, top_k: int):
# x: [n_batch, l_seq, d_model]
# We: [n_experts, d_model, d_model]
diff --git a/questions/125_implement-a-sparse-mixture-of-experts-layer/starter_code.py b/questions/125_implement-a-sparse-mixture-of-experts-layer/starter_code.py
index 6b7873c7..13d37325 100644
--- a/questions/125_implement-a-sparse-mixture-of-experts-layer/starter_code.py
+++ b/questions/125_implement-a-sparse-mixture-of-experts-layer/starter_code.py
@@ -1,6 +1,9 @@
import numpy as np
-def moe(x: np.ndarray, We: np.ndarray, Wg: np.ndarray, n_experts: int, top_k: int) -> np.ndarray:
+
+def moe(
+ x: np.ndarray, We: np.ndarray, Wg: np.ndarray, n_experts: int, top_k: int
+) -> np.ndarray:
"""
Args:
x: Input tensor of shape (n_batch, l_seq, d_model)
diff --git a/questions/126_implement-group-normalization/solution.py b/questions/126_implement-group-normalization/solution.py
index 18cdb7fb..f47db6ec 100644
--- a/questions/126_implement-group-normalization/solution.py
+++ b/questions/126_implement-group-normalization/solution.py
@@ -1,17 +1,23 @@
-def group_normalization(X: np.ndarray, gamma: np.ndarray, beta: np.ndarray, num_groups: int, epsilon: float = 1e-5) -> np.ndarray:
- '''
+def group_normalization(
+ X: np.ndarray,
+ gamma: np.ndarray,
+ beta: np.ndarray,
+ num_groups: int,
+ epsilon: float = 1e-5,
+) -> np.ndarray:
+ """
Perform Group Normalization.
-
+
Args:
X: numpy array of shape (B, C, H, W), input data
gamma: numpy array of shape (C,), scale parameter
beta: numpy array of shape (C,), shift parameter
num_groups: number of groups for normalization
epsilon: small constant to avoid division by zero
-
+
Returns:
norm_X: numpy array of shape (B, C, H, W), normalized output
- '''
+ """
batch_size, num_channels, height, width = X.shape
group_size = num_channels // num_groups
diff --git a/questions/126_implement-group-normalization/starter_code.py b/questions/126_implement-group-normalization/starter_code.py
index a75bfe94..6edb23e3 100644
--- a/questions/126_implement-group-normalization/starter_code.py
+++ b/questions/126_implement-group-normalization/starter_code.py
@@ -1,5 +1,12 @@
import numpy as np
-def group_normalization(X: np.ndarray, gamma: np.ndarray, beta: np.ndarray, num_groups: int, epsilon: float = 1e-5) -> np.ndarray:
+
+def group_normalization(
+ X: np.ndarray,
+ gamma: np.ndarray,
+ beta: np.ndarray,
+ num_groups: int,
+ epsilon: float = 1e-5,
+) -> np.ndarray:
# Your code here
pass
diff --git a/questions/127_find-captain-redbeard-s-hidden-treasure/starter_code.py b/questions/127_find-captain-redbeard-s-hidden-treasure/starter_code.py
index 2e17590a..f692bf8a 100644
--- a/questions/127_find-captain-redbeard-s-hidden-treasure/starter_code.py
+++ b/questions/127_find-captain-redbeard-s-hidden-treasure/starter_code.py
@@ -1,9 +1,9 @@
def find_treasure(start_x: float) -> float:
"""
- Find the x-coordinate where f(x) = x^4 - 3x^3 + 2 is minimized.
+ Find the x-coordinate where f(x) = x^4 - 3x^3 + 2 is minimized.
- Returns:
- float: The x-coordinate of the minimum point.
+ Returns:
+ float: The x-coordinate of the minimum point.
"""
# Your code here
pass
diff --git a/questions/128_dynamic-tanh-normalization-free-transformer-activa/solution.py b/questions/128_dynamic-tanh-normalization-free-transformer-activa/solution.py
index 1c9cb05d..2a204bd5 100644
--- a/questions/128_dynamic-tanh-normalization-free-transformer-activa/solution.py
+++ b/questions/128_dynamic-tanh-normalization-free-transformer-activa/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def dynamic_tanh(x: np.ndarray, alpha: float, gamma: float, beta: float) -> list[float]:
def tanh(x: np.ndarray) -> np.ndarray:
return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))
diff --git a/questions/128_dynamic-tanh-normalization-free-transformer-activa/starter_code.py b/questions/128_dynamic-tanh-normalization-free-transformer-activa/starter_code.py
index 29bf9f12..9d71217d 100644
--- a/questions/128_dynamic-tanh-normalization-free-transformer-activa/starter_code.py
+++ b/questions/128_dynamic-tanh-normalization-free-transformer-activa/starter_code.py
@@ -1,5 +1,6 @@
import numpy as np
+
def dynamic_tanh(x: np.ndarray, alpha: float, gamma: float, beta: float) -> list[float]:
# Your code here
pass
diff --git a/questions/12_singular-value-decomposition-svd/pytorch/solution.py b/questions/12_singular-value-decomposition-svd/pytorch/solution.py
index 2ed6e967..95442d16 100644
--- a/questions/12_singular-value-decomposition-svd/pytorch/solution.py
+++ b/questions/12_singular-value-decomposition-svd/pytorch/solution.py
@@ -1,28 +1,31 @@
import torch
-def svd_2x2_singular_values(A: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
+
+def svd_2x2_singular_values(
+ A: torch.Tensor,
+) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
"""
Approximate the SVD of a 2×2 matrix A using one Jacobi rotation.
Returns (U, S, Vt) where S is a 1-D tensor of singular values.
"""
# compute AᵀA
- a2 = A.transpose(0,1) @ A
+ a2 = A.transpose(0, 1) @ A
# initialize V
V = torch.eye(2, dtype=A.dtype, device=A.device)
# Jacobi rotation angle
- if torch.isclose(a2[0,0], a2[1,1]):
- theta = torch.tensor(torch.pi/4, dtype=A.dtype, device=A.device)
+ if torch.isclose(a2[0, 0], a2[1, 1]):
+ theta = torch.tensor(torch.pi / 4, dtype=A.dtype, device=A.device)
else:
- theta = 0.5 * torch.atan2(2 * a2[0,1], a2[0,0] - a2[1,1])
+ theta = 0.5 * torch.atan2(2 * a2[0, 1], a2[0, 0] - a2[1, 1])
c = torch.cos(theta)
s = torch.sin(theta)
R = torch.stack([torch.stack([c, -s]), torch.stack([s, c])])
# diagonalize
- D = R.transpose(0,1) @ a2 @ R
+ D = R.transpose(0, 1) @ a2 @ R
V = V @ R
# singular values
- S = torch.sqrt(torch.tensor([D[0,0], D[1,1]], dtype=A.dtype, device=A.device))
+ S = torch.sqrt(torch.tensor([D[0, 0], D[1, 1]], dtype=A.dtype, device=A.device))
# compute U
S_inv = torch.diag(1.0 / S)
U = A @ V @ S_inv
- return U, S, V.transpose(0,1)
+ return U, S, V.transpose(0, 1)
diff --git a/questions/12_singular-value-decomposition-svd/pytorch/starter_code.py b/questions/12_singular-value-decomposition-svd/pytorch/starter_code.py
index 3dc609a5..bc03f473 100644
--- a/questions/12_singular-value-decomposition-svd/pytorch/starter_code.py
+++ b/questions/12_singular-value-decomposition-svd/pytorch/starter_code.py
@@ -1,6 +1,9 @@
import torch
-def svd_2x2_singular_values(A: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
+
+def svd_2x2_singular_values(
+ A: torch.Tensor,
+) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
"""
Approximate the SVD of a 2×2 matrix A using one Jacobi rotation.
Returns (U, S, Vt) where S is a 1-D tensor of singular values.
diff --git a/questions/12_singular-value-decomposition-svd/solution.py b/questions/12_singular-value-decomposition-svd/solution.py
index f6a8fbb3..9e48e7e1 100644
--- a/questions/12_singular-value-decomposition-svd/solution.py
+++ b/questions/12_singular-value-decomposition-svd/solution.py
@@ -1,44 +1,38 @@
-import numpy as np
+import numpy as np
def svd_2x2_singular_values(A: np.ndarray) -> tuple:
- # stick to lowercase
- a = A
-
- a_t = np.transpose(a)
- a_2 = a_t @ a
-
- v = np.eye(2)
-
- for _ in range(1):
- # Compute rotation angle for a 2x2 matrix
- if a_2[0,0] == a_2[1,1]:
- theta = np.pi/4
- else:
- theta = 0.5 * np.arctan2(2 * a_2[0,1], a_2[0,0] - a_2[1,1])
-
- # Create rotation matrix
- r = np.array(
- [
- [np.cos(theta), -np.sin(theta)],
- [np.sin(theta), np.cos(theta)]
- ]
- )
-
- # apply rotation
- d = np.transpose(r) @ a_2 @ r
-
- # update a_2
- a_2 = d
-
- # accumulate v
- v = v @ r
-
- # sigma is the diagonal elements squared
- s = np.sqrt([d[0,0], d[1,1]])
- s_inv = np.array([[1/s[0], 0], [0, 1/s[1]]])
-
- u = a @ v @ s_inv
-
- return (u, s, v.T)
-
+ # stick to lowercase
+ a = A
+
+ a_t = np.transpose(a)
+ a_2 = a_t @ a
+
+ v = np.eye(2)
+
+ for _ in range(1):
+ # Compute rotation angle for a 2x2 matrix
+ if a_2[0, 0] == a_2[1, 1]:
+ theta = np.pi / 4
+ else:
+ theta = 0.5 * np.arctan2(2 * a_2[0, 1], a_2[0, 0] - a_2[1, 1])
+
+ # Create rotation matrix
+ r = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
+
+ # apply rotation
+ d = np.transpose(r) @ a_2 @ r
+
+ # update a_2
+ a_2 = d
+
+ # accumulate v
+ v = v @ r
+
+ # sigma is the diagonal elements squared
+ s = np.sqrt([d[0, 0], d[1, 1]])
+ s_inv = np.array([[1 / s[0], 0], [0, 1 / s[1]]])
+
+ u = a @ v @ s_inv
+
+ return (u, s, v.T)
diff --git a/questions/12_singular-value-decomposition-svd/starter_code.py b/questions/12_singular-value-decomposition-svd/starter_code.py
index 04722225..1847529f 100644
--- a/questions/12_singular-value-decomposition-svd/starter_code.py
+++ b/questions/12_singular-value-decomposition-svd/starter_code.py
@@ -1,3 +1,3 @@
import numpy as np
- def svd_2x2_singular_values(A: np.ndarray) -> tuple:
+def svd_2x2_singular_values(A: np.ndarray) -> tuple:
return SVD
diff --git a/questions/12_singular-value-decomposition-svd/tinygrad/solution.py b/questions/12_singular-value-decomposition-svd/tinygrad/solution.py
index 42c9e31c..02758b3a 100644
--- a/questions/12_singular-value-decomposition-svd/tinygrad/solution.py
+++ b/questions/12_singular-value-decomposition-svd/tinygrad/solution.py
@@ -1,6 +1,7 @@
import numpy as np
from tinygrad.tensor import Tensor
+
def svd_2x2_singular_values_tg(A) -> tuple[Tensor, Tensor, Tensor]:
"""
Approximate the SVD of a 2×2 matrix A using one Jacobi rotation in tinygrad.
@@ -11,10 +12,12 @@ def svd_2x2_singular_values_tg(A) -> tuple[Tensor, Tensor, Tensor]:
a2 = A_t.T.matmul(A_t)
V = Tensor([[1.0, 0.0], [0.0, 1.0]])
# extract entries
- a_val = a2[0,0].numpy(); d_val = a2[1,1].numpy(); b_val = a2[0,1].numpy()
+ a_val = a2[0, 0].numpy()
+ d_val = a2[1, 1].numpy()
+ b_val = a2[0, 1].numpy()
# compute rotation angle
if np.isclose(a_val, d_val):
- theta = np.pi/4
+ theta = np.pi / 4
else:
theta = 0.5 * np.arctan2(2 * b_val, a_val - d_val)
c, s = np.cos(theta), np.sin(theta)
@@ -22,8 +25,8 @@ def svd_2x2_singular_values_tg(A) -> tuple[Tensor, Tensor, Tensor]:
D = R.T.matmul(a2).matmul(R)
V = V.matmul(R)
# singular values
- S = Tensor(np.sqrt([D[0,0].numpy(), D[1,1].numpy()]))
+ S = Tensor(np.sqrt([D[0, 0].numpy(), D[1, 1].numpy()]))
# compute U
- S_inv = Tensor([[1.0/S[0].numpy(), 0.0], [0.0, 1.0/S[1].numpy()]])
+ S_inv = Tensor([[1.0 / S[0].numpy(), 0.0], [0.0, 1.0 / S[1].numpy()]])
U = A_t.matmul(V).matmul(S_inv)
return U, S, V.T
diff --git a/questions/12_singular-value-decomposition-svd/tinygrad/starter_code.py b/questions/12_singular-value-decomposition-svd/tinygrad/starter_code.py
index 086402fa..07e1b6d7 100644
--- a/questions/12_singular-value-decomposition-svd/tinygrad/starter_code.py
+++ b/questions/12_singular-value-decomposition-svd/tinygrad/starter_code.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def svd_2x2_singular_values_tg(A) -> tuple[Tensor, Tensor, Tensor]:
"""
Approximate the SVD of a 2×2 matrix A using one Jacobi rotation in tinygrad.
diff --git a/questions/130_implement-a-simple-cnn-training-function-with-back/solution.py b/questions/130_implement-a-simple-cnn-training-function-with-back/solution.py
index da6929c5..43875dd9 100644
--- a/questions/130_implement-a-simple-cnn-training-function-with-back/solution.py
+++ b/questions/130_implement-a-simple-cnn-training-function-with-back/solution.py
@@ -1,7 +1,10 @@
import numpy as np
-def train_simple_cnn_with_backprop(X, y, epochs, learning_rate, kernel_size=3, num_filters=1):
- '''
+
+def train_simple_cnn_with_backprop(
+ X, y, epochs, learning_rate, kernel_size=3, num_filters=1
+):
+ """
Trains a simple CNN with one convolutional layer, ReLU activation, flattening, and a dense layer with softmax output using backpropagation.
Assumes X has shape (n_samples, height, width) for grayscale images and y is one-hot encoded with shape (n_samples, num_classes).
@@ -16,7 +19,7 @@ def train_simple_cnn_with_backprop(X, y, epochs, learning_rate, kernel_size=3, n
Returns:
W_conv, b_conv, W_dense, b_dense : Trained weights and biases for the convolutional and dense layers
- '''
+ """
n_samples, height, width = X.shape
num_classes = y.shape[1]
@@ -37,13 +40,21 @@ def train_simple_cnn_with_backprop(X, y, epochs, learning_rate, kernel_size=3, n
for k in range(num_filters):
for p in range(output_height):
for q in range(output_width):
- Z_conv[p, q, k] = np.sum(X[i, p:p+kernel_size, q:q+kernel_size] * W_conv[:, :, k]) + b_conv[k]
+ Z_conv[p, q, k] = (
+ np.sum(
+ X[i, p : p + kernel_size, q : q + kernel_size]
+ * W_conv[:, :, k]
+ )
+ + b_conv[k]
+ )
A_conv = np.maximum(Z_conv, 0) # ReLU activation
A_flat = A_conv.flatten() # Flatten the output
# Dense layer
Z_dense = np.dot(A_flat, W_dense) + b_dense
- exp_Z_dense = np.exp(Z_dense - np.max(Z_dense)) # Numerical stability for softmax
+ exp_Z_dense = np.exp(
+ Z_dense - np.max(Z_dense)
+ ) # Numerical stability for softmax
A_dense = exp_Z_dense / np.sum(exp_Z_dense)
# Backpropagation
@@ -66,11 +77,12 @@ def train_simple_cnn_with_backprop(X, y, epochs, learning_rate, kernel_size=3, n
db_conv[k] = np.sum(dZ_conv[:, :, k])
for ii in range(kernel_size):
for jj in range(kernel_size):
-
- dW_conv[ii, jj, k] = np.sum(dZ_conv[:, :, k] * X[i, ii:ii+output_height, jj:jj+output_width])
+ dW_conv[ii, jj, k] = np.sum(
+ dZ_conv[:, :, k]
+ * X[i, ii : ii + output_height, jj : jj + output_width]
+ )
-
-# Update weights and biases
+ # Update weights and biases
W_conv -= learning_rate * dW_conv
b_conv -= learning_rate * db_conv
W_dense -= learning_rate * dW_dense
diff --git a/questions/130_implement-a-simple-cnn-training-function-with-back/starter_code.py b/questions/130_implement-a-simple-cnn-training-function-with-back/starter_code.py
index cc6a5dc4..d5f90fc5 100644
--- a/questions/130_implement-a-simple-cnn-training-function-with-back/starter_code.py
+++ b/questions/130_implement-a-simple-cnn-training-function-with-back/starter_code.py
@@ -1,3 +1,5 @@
-def train_simple_cnn_with_backprop(X, y, epochs, learning_rate, kernel_size=3, num_filters=1):
+def train_simple_cnn_with_backprop(
+ X, y, epochs, learning_rate, kernel_size=3, num_filters=1
+):
# Your code here
pass
diff --git a/questions/131_implement-efficient-sparse-window-attention/solution.py b/questions/131_implement-efficient-sparse-window-attention/solution.py
index 1425246c..bc437b17 100644
--- a/questions/131_implement-efficient-sparse-window-attention/solution.py
+++ b/questions/131_implement-efficient-sparse-window-attention/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def sparse_window_attention(Q, K, V, window_size, scale_factor=None):
"""
Computes sparse attention with a sliding window mask to efficiently handle longer context lengths.
@@ -24,7 +25,7 @@ def sparse_window_attention(Q, K, V, window_size, scale_factor=None):
for i in range(seq_len):
start = max(0, i - window_size)
end = min(seq_len, i + window_size + 1)
- local_Q = Q[i:i+1]
+ local_Q = Q[i : i + 1]
local_K = K[start:end]
local_V = V[start:end]
scores = np.dot(local_Q, local_K.T) / scale_factor
diff --git a/questions/131_implement-efficient-sparse-window-attention/starter_code.py b/questions/131_implement-efficient-sparse-window-attention/starter_code.py
index e0ef4ce4..8417bb75 100644
--- a/questions/131_implement-efficient-sparse-window-attention/starter_code.py
+++ b/questions/131_implement-efficient-sparse-window-attention/starter_code.py
@@ -1,4 +1,3 @@
-import numpy as np
def sparse_window_attention(Q, K, V, window_size, scale_factor=None):
# Your code here
pass
diff --git a/questions/132_simulate-markov-chain-transitions/solution.py b/questions/132_simulate-markov-chain-transitions/solution.py
index 38090142..1176c2b9 100644
--- a/questions/132_simulate-markov-chain-transitions/solution.py
+++ b/questions/132_simulate-markov-chain-transitions/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def simulate_markov_chain(transition_matrix, initial_state, num_steps):
"""
Simulates a Markov Chain given a transition matrix, initial state, and number of steps.
diff --git a/questions/132_simulate-markov-chain-transitions/starter_code.py b/questions/132_simulate-markov-chain-transitions/starter_code.py
index e3f0e7b0..cf6e528d 100644
--- a/questions/132_simulate-markov-chain-transitions/starter_code.py
+++ b/questions/132_simulate-markov-chain-transitions/starter_code.py
@@ -1,4 +1,3 @@
-import numpy as np
def simulate_markov_chain(transition_matrix, initial_state, num_steps):
# Your code here
pass
diff --git a/questions/133_implement-q-learning-algorithm-for-mdps/solution.py b/questions/133_implement-q-learning-algorithm-for-mdps/solution.py
index 553155d0..b0150812 100644
--- a/questions/133_implement-q-learning-algorithm-for-mdps/solution.py
+++ b/questions/133_implement-q-learning-algorithm-for-mdps/solution.py
@@ -1,6 +1,9 @@
import numpy as np
-def q_learning(num_states, num_actions, P, R, terminal_states, alpha, gamma, epsilon, num_episodes):
+
+def q_learning(
+ num_states, num_actions, P, R, terminal_states, alpha, gamma, epsilon, num_episodes
+):
"""
Implements Q-Learning algorithm to learn the optimal Q-table for a given MDP.
@@ -19,34 +22,36 @@ def q_learning(num_states, num_actions, P, R, terminal_states, alpha, gamma, eps
- Q: NumPy array of shape (num_states, num_actions), the learned Q-table
"""
Q = np.zeros((num_states, num_actions))
-
+
for episode in range(num_episodes):
# Start from a random non-terminal state
- state = np.random.choice([s for s in range(num_states) if s not in set(terminal_states)])
-
+ state = np.random.choice(
+ [s for s in range(num_states) if s not in set(terminal_states)]
+ )
+
while state not in terminal_states:
# Epsilon-greedy action selection
if np.random.rand() < epsilon:
action = np.random.randint(num_actions)
else:
action = np.argmax(Q[state])
-
+
# Sample next state based on transition probabilities
next_state = np.random.choice(num_states, p=P[state, action])
-
+
# Get reward
reward = R[state, action]
-
+
# Compute target Q-value
if next_state in terminal_states:
target = reward
else:
target = reward + gamma * np.max(Q[next_state])
-
+
# Update Q-table
Q[state, action] += alpha * (target - Q[state, action])
-
+
# Transition to next state
state = next_state
-
+
return Q
diff --git a/questions/133_implement-q-learning-algorithm-for-mdps/starter_code.py b/questions/133_implement-q-learning-algorithm-for-mdps/starter_code.py
index c4b26350..b4bcdf89 100644
--- a/questions/133_implement-q-learning-algorithm-for-mdps/starter_code.py
+++ b/questions/133_implement-q-learning-algorithm-for-mdps/starter_code.py
@@ -1,4 +1,5 @@
-import numpy as np
-def q_learning(num_states, num_actions, P, R, terminal_states, alpha, gamma, epsilon, num_episodes):
+def q_learning(
+ num_states, num_actions, P, R, terminal_states, alpha, gamma, epsilon, num_episodes
+):
# Your code here
pass
diff --git a/questions/134_compute-multi-class-cross-entropy-loss/solution.py b/questions/134_compute-multi-class-cross-entropy-loss/solution.py
index 2ed25690..1575d696 100644
--- a/questions/134_compute-multi-class-cross-entropy-loss/solution.py
+++ b/questions/134_compute-multi-class-cross-entropy-loss/solution.py
@@ -1,10 +1,12 @@
import numpy as np
-def compute_cross_entropy_loss(predicted_probs: np.ndarray, true_labels: np.ndarray,epsilon = 1e-15) -> float:
+def compute_cross_entropy_loss(
+ predicted_probs: np.ndarray, true_labels: np.ndarray, epsilon=1e-15
+) -> float:
predicted_probs = np.clip(predicted_probs, epsilon, 1 - epsilon)
- #Write your code here
+ # Write your code here
log_probs = np.log(predicted_probs)
loss = -np.sum(true_labels * log_probs, axis=1)
return float(np.mean(loss))
diff --git a/questions/134_compute-multi-class-cross-entropy-loss/starter_code.py b/questions/134_compute-multi-class-cross-entropy-loss/starter_code.py
index c182289b..ece27566 100644
--- a/questions/134_compute-multi-class-cross-entropy-loss/starter_code.py
+++ b/questions/134_compute-multi-class-cross-entropy-loss/starter_code.py
@@ -1,5 +1,8 @@
import numpy as np
-def compute_cross_entropy_loss(predicted_probs: np.ndarray, true_labels: np.ndarray, epsilon = 1e-15) -> float:
+
+def compute_cross_entropy_loss(
+ predicted_probs: np.ndarray, true_labels: np.ndarray, epsilon=1e-15
+) -> float:
# Your code here
pass
diff --git a/questions/135_implement-early-stopping-based-on-validation-loss/solution.py b/questions/135_implement-early-stopping-based-on-validation-loss/solution.py
index 689d05ee..427f9569 100644
--- a/questions/135_implement-early-stopping-based-on-validation-loss/solution.py
+++ b/questions/135_implement-early-stopping-based-on-validation-loss/solution.py
@@ -1,7 +1,10 @@
from typing import Tuple
-def early_stopping(val_losses: list[float], patience: int, min_delta: float) -> Tuple[int, int]:
- best_loss = float('inf')
+
+def early_stopping(
+ val_losses: list[float], patience: int, min_delta: float
+) -> Tuple[int, int]:
+ best_loss = float("inf")
best_epoch = 0
epochs_without_improvement = 0
diff --git a/questions/135_implement-early-stopping-based-on-validation-loss/starter_code.py b/questions/135_implement-early-stopping-based-on-validation-loss/starter_code.py
index 9576b639..0560f4c7 100644
--- a/questions/135_implement-early-stopping-based-on-validation-loss/starter_code.py
+++ b/questions/135_implement-early-stopping-based-on-validation-loss/starter_code.py
@@ -1,5 +1,8 @@
from typing import Tuple
-def early_stopping(val_losses: list[float], patience: int, min_delta: float) -> Tuple[int, int]:
+
+def early_stopping(
+ val_losses: list[float], patience: int, min_delta: float
+) -> Tuple[int, int]:
# Your code here
pass
diff --git a/questions/136_calculate-kl-divergence-between-two-multivariate-g/solution.py b/questions/136_calculate-kl-divergence-between-two-multivariate-g/solution.py
index f899a960..e4b14313 100644
--- a/questions/136_calculate-kl-divergence-between-two-multivariate-g/solution.py
+++ b/questions/136_calculate-kl-divergence-between-two-multivariate-g/solution.py
@@ -1,12 +1,20 @@
import numpy as np
-def multivariate_kl_divergence(mu_p:np.ndarray, Cov_p:np.ndarray,
- mu_q:np.ndarray, Cov_q:np.ndarray) -> float:
+def multivariate_kl_divergence(
+ mu_p: np.ndarray, Cov_p: np.ndarray, mu_q: np.ndarray, Cov_q: np.ndarray
+) -> float:
def trace(x: np.ndarray) -> float:
return np.diag(x).sum()
p = Cov_p.shape[0]
- return float(1/2 * (
- np.log(np.linalg.det(Cov_q)/np.linalg.det(Cov_p)) - p + (mu_p-mu_q).T @ np.linalg.inv(Cov_q) @ (mu_p-mu_q) + trace(np.linalg.inv(Cov_q) @ Cov_p)
- ))
+ return float(
+ 1
+ / 2
+ * (
+ np.log(np.linalg.det(Cov_q) / np.linalg.det(Cov_p))
+ - p
+ + (mu_p - mu_q).T @ np.linalg.inv(Cov_q) @ (mu_p - mu_q)
+ + trace(np.linalg.inv(Cov_q) @ Cov_p)
+ )
+ )
diff --git a/questions/136_calculate-kl-divergence-between-two-multivariate-g/starter_code.py b/questions/136_calculate-kl-divergence-between-two-multivariate-g/starter_code.py
index 91200797..7e4ceee8 100644
--- a/questions/136_calculate-kl-divergence-between-two-multivariate-g/starter_code.py
+++ b/questions/136_calculate-kl-divergence-between-two-multivariate-g/starter_code.py
@@ -1,9 +1,12 @@
import numpy as np
-def multivariate_kl_divergence(mu_p: np.ndarray, Cov_p: np.ndarray, mu_q: np.ndarray, Cov_q: np.ndarray) -> float:
+
+def multivariate_kl_divergence(
+ mu_p: np.ndarray, Cov_p: np.ndarray, mu_q: np.ndarray, Cov_q: np.ndarray
+) -> float:
"""
Computes the KL divergence between two multivariate Gaussian distributions.
-
+
Parameters:
mu_p: mean vector of the first distribution
Cov_p: covariance matrix of the first distribution
diff --git a/questions/137_implement-a-dense-block-with-2d-convolutions/solution.py b/questions/137_implement-a-dense-block-with-2d-convolutions/solution.py
index bc273341..172df837 100644
--- a/questions/137_implement-a-dense-block-with-2d-convolutions/solution.py
+++ b/questions/137_implement-a-dense-block-with-2d-convolutions/solution.py
@@ -1,8 +1,11 @@
import numpy as np
+
def conv2d(x, kernel, padding=0):
if padding > 0:
- x_padded = np.pad(x, ((0, 0), (padding, padding), (padding, padding), (0, 0)), mode='constant')
+ x_padded = np.pad(
+ x, ((0, 0), (padding, padding), (padding, padding), (0, 0)), mode="constant"
+ )
else:
x_padded = x
batch_size, in_height, in_width, in_channels = x_padded.shape
@@ -16,10 +19,14 @@ def conv2d(x, kernel, padding=0):
for c_out in range(out_channels):
sum_val = 0.0
for c_in in range(in_channels):
- sum_val += np.sum(x_padded[b, i:i+kh, j:j+kw, c_in] * kernel[:, :, c_in, c_out])
+ sum_val += np.sum(
+ x_padded[b, i : i + kh, j : j + kw, c_in]
+ * kernel[:, :, c_in, c_out]
+ )
output[b, i, j, c_out] = sum_val
return output
+
def dense_net_block(input_data, num_layers, growth_rate, kernels, kernel_size=(3, 3)):
kh, kw = kernel_size
padding = (kh - 1) // 2
@@ -27,5 +34,7 @@ def dense_net_block(input_data, num_layers, growth_rate, kernels, kernel_size=(3
for l in range(num_layers):
activated = np.maximum(concatenated_features, 0.0)
conv_output = conv2d(activated, kernels[l], padding=padding)
- concatenated_features = np.concatenate([concatenated_features, conv_output], axis=3)
+ concatenated_features = np.concatenate(
+ [concatenated_features, conv_output], axis=3
+ )
return concatenated_features
diff --git a/questions/137_implement-a-dense-block-with-2d-convolutions/starter_code.py b/questions/137_implement-a-dense-block-with-2d-convolutions/starter_code.py
index 90abdcee..ac79804b 100644
--- a/questions/137_implement-a-dense-block-with-2d-convolutions/starter_code.py
+++ b/questions/137_implement-a-dense-block-with-2d-convolutions/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def dense_net_block(input_data, num_layers, growth_rate, kernels, kernel_size=(3, 3)):
# Your code here
pass
diff --git a/questions/138_find-the-best-gini-based-split-for-a-binary-decisi/solution.py b/questions/138_find-the-best-gini-based-split-for-a-binary-decisi/solution.py
index 806300f5..578297e2 100644
--- a/questions/138_find-the-best-gini-based-split-for-a-binary-decisi/solution.py
+++ b/questions/138_find-the-best-gini-based-split-for-a-binary-decisi/solution.py
@@ -1,16 +1,17 @@
import numpy as np
from typing import Tuple
+
def find_best_split(X: np.ndarray, y: np.ndarray) -> Tuple[int, float]:
def gini(y_subset: np.ndarray) -> float:
if y_subset.size == 0:
return 0.0
p = y_subset.mean()
- return 1.0 - (p**2 + (1 - p)**2)
+ return 1.0 - (p**2 + (1 - p) ** 2)
n_samples, n_features = X.shape
- best_feature, best_threshold = -1, float('inf')
- best_gini = float('inf')
+ best_feature, best_threshold = -1, float("inf")
+ best_gini = float("inf")
for f in range(n_features):
for threshold in np.unique(X[:, f]):
diff --git a/questions/138_find-the-best-gini-based-split-for-a-binary-decisi/starter_code.py b/questions/138_find-the-best-gini-based-split-for-a-binary-decisi/starter_code.py
index 15d4c06d..7a5cbe84 100644
--- a/questions/138_find-the-best-gini-based-split-for-a-binary-decisi/starter_code.py
+++ b/questions/138_find-the-best-gini-based-split-for-a-binary-decisi/starter_code.py
@@ -1,6 +1,7 @@
import numpy as np
from typing import Tuple
+
def find_best_split(X: np.ndarray, y: np.ndarray) -> Tuple[int, float]:
"""Return the (feature_index, threshold) that minimises weighted Gini impurity."""
# ✏️ TODO: implement
diff --git a/questions/139_elastic-net-regression-via-gradient-descent/solution.py b/questions/139_elastic-net-regression-via-gradient-descent/solution.py
index 90f8e267..022dde2e 100644
--- a/questions/139_elastic-net-regression-via-gradient-descent/solution.py
+++ b/questions/139_elastic-net-regression-via-gradient-descent/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def elastic_net_gradient_descent(
X: np.ndarray,
y: np.ndarray,
@@ -16,7 +17,11 @@ def elastic_net_gradient_descent(
for _ in range(max_iter):
y_pred = np.dot(X, weights) + bias
error = y_pred - y
- grad_w = (1 / n_samples) * np.dot(X.T, error) + alpha1 * np.sign(weights) + 2 * alpha2 * weights
+ grad_w = (
+ (1 / n_samples) * np.dot(X.T, error)
+ + alpha1 * np.sign(weights)
+ + 2 * alpha2 * weights
+ )
grad_b = (1 / n_samples) * np.sum(error)
weights -= learning_rate * grad_w
bias -= learning_rate * grad_b
diff --git a/questions/139_elastic-net-regression-via-gradient-descent/starter_code.py b/questions/139_elastic-net-regression-via-gradient-descent/starter_code.py
index f383c038..f0efa364 100644
--- a/questions/139_elastic-net-regression-via-gradient-descent/starter_code.py
+++ b/questions/139_elastic-net-regression-via-gradient-descent/starter_code.py
@@ -1,5 +1,6 @@
import numpy as np
+
def elastic_net_gradient_descent(
X: np.ndarray,
y: np.ndarray,
diff --git a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/pytorch/solution.py b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/pytorch/solution.py
index 54f64913..5785e894 100644
--- a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/pytorch/solution.py
+++ b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def determinant_4x4(matrix) -> float:
"""
Compute the determinant of a 4×4 matrix using PyTorch.
diff --git a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/pytorch/starter_code.py b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/pytorch/starter_code.py
index acf9ccb6..0380e1ca 100644
--- a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/pytorch/starter_code.py
+++ b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/pytorch/starter_code.py
@@ -1,5 +1,6 @@
import torch
+
def determinant_4x4(matrix) -> float:
"""
Compute the determinant of a 4×4 matrix using PyTorch.
@@ -7,6 +8,6 @@ def determinant_4x4(matrix) -> float:
Returns a Python float.
"""
# Convert to tensor
- m = torch.as_tensor(matrix, dtype=torch.float)
+ torch.as_tensor(matrix, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/solution.py b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/solution.py
index 17825b2a..35caeb91 100644
--- a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/solution.py
+++ b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/solution.py
@@ -1,11 +1,11 @@
-def determinant_4x4(matrix: list[list[int|float]]) -> float:
+def determinant_4x4(matrix: list[list[int | float]]) -> float:
# Base case: If the matrix is 1x1, return its single element
if len(matrix) == 1:
return matrix[0][0]
# Recursive case: Calculate determinant using Laplace's Expansion
det = 0
for c in range(len(matrix)):
- minor = [row[:c] + row[c+1:] for row in matrix[1:]] # Remove column c
- cofactor = ((-1)**c) * determinant_4x4(minor) # Compute cofactor
+ minor = [row[:c] + row[c + 1 :] for row in matrix[1:]] # Remove column c
+ cofactor = ((-1) ** c) * determinant_4x4(minor) # Compute cofactor
det += matrix[0][c] * cofactor # Add to running total
return det
diff --git a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/starter_code.py b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/starter_code.py
index 32d67a49..49527285 100644
--- a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/starter_code.py
+++ b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/starter_code.py
@@ -1,3 +1,3 @@
-def determinant_4x4(matrix: list[list[int|float]]) -> float:
- # Your recursive implementation here
- pass
+def determinant_4x4(matrix: list[list[int | float]]) -> float:
+ # Your recursive implementation here
+ pass
diff --git a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/tinygrad/solution.py b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/tinygrad/solution.py
index ea44aba5..944ad1e1 100644
--- a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/tinygrad/solution.py
+++ b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/tinygrad/solution.py
@@ -1,6 +1,7 @@
import numpy as np
from tinygrad.tensor import Tensor
+
def determinant_4x4_tg(matrix) -> Tensor:
"""
Compute the determinant of a 4×4 matrix using tinygrad.
diff --git a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/tinygrad/starter_code.py b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/tinygrad/starter_code.py
index cdcef93e..b33dfc40 100644
--- a/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/tinygrad/starter_code.py
+++ b/questions/13_determinant-of-a-4x4-matrix-using-laplace-s-expans/tinygrad/starter_code.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def determinant_4x4_tg(matrix) -> Tensor:
"""
Compute the determinant of a 4×4 matrix using tinygrad.
diff --git a/questions/14_linear-regression-using-normal-equation/pytorch/solution.py b/questions/14_linear-regression-using-normal-equation/pytorch/solution.py
index 2469e162..cdb533dc 100644
--- a/questions/14_linear-regression-using-normal-equation/pytorch/solution.py
+++ b/questions/14_linear-regression-using-normal-equation/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def linear_regression_normal_equation(X, y) -> torch.Tensor:
"""
Solve linear regression via the normal equation using PyTorch.
@@ -7,9 +8,9 @@ def linear_regression_normal_equation(X, y) -> torch.Tensor:
Returns a 1-D tensor of length n, rounded to 4 decimals.
"""
X_t = torch.as_tensor(X, dtype=torch.float)
- y_t = torch.as_tensor(y, dtype=torch.float).reshape(-1,1)
+ y_t = torch.as_tensor(y, dtype=torch.float).reshape(-1, 1)
# normal equation: theta = (XᵀX)⁻¹ Xᵀ y
- XtX = X_t.transpose(0,1) @ X_t
- theta = torch.linalg.inv(XtX) @ (X_t.transpose(0,1) @ y_t)
+ XtX = X_t.transpose(0, 1) @ X_t
+ theta = torch.linalg.inv(XtX) @ (X_t.transpose(0, 1) @ y_t)
theta = theta.flatten()
return torch.round(theta * 10000) / 10000
diff --git a/questions/14_linear-regression-using-normal-equation/pytorch/starter_code.py b/questions/14_linear-regression-using-normal-equation/pytorch/starter_code.py
index c9c5c8ce..9e1ce35a 100644
--- a/questions/14_linear-regression-using-normal-equation/pytorch/starter_code.py
+++ b/questions/14_linear-regression-using-normal-equation/pytorch/starter_code.py
@@ -1,12 +1,13 @@
import torch
+
def linear_regression_normal_equation(X, y) -> torch.Tensor:
"""
Solve linear regression via the normal equation using PyTorch.
X: Tensor or convertible of shape (m,n); y: shape (m,) or (m,1).
Returns a 1-D tensor of length n, rounded to 4 decimals.
"""
- X_t = torch.as_tensor(X, dtype=torch.float)
- y_t = torch.as_tensor(y, dtype=torch.float).reshape(-1,1)
+ torch.as_tensor(X, dtype=torch.float)
+ torch.as_tensor(y, dtype=torch.float).reshape(-1, 1)
# Your implementation here
pass
diff --git a/questions/14_linear-regression-using-normal-equation/solution.py b/questions/14_linear-regression-using-normal-equation/solution.py
index 0c60e015..30e2717e 100644
--- a/questions/14_linear-regression-using-normal-equation/solution.py
+++ b/questions/14_linear-regression-using-normal-equation/solution.py
@@ -1,6 +1,9 @@
-
import numpy as np
-def linear_regression_normal_equation(X: list[list[float]], y: list[float]) -> list[float]:
+
+
+def linear_regression_normal_equation(
+ X: list[list[float]], y: list[float]
+) -> list[float]:
X = np.array(X)
y = np.array(y).reshape(-1, 1)
X_transpose = X.T
diff --git a/questions/14_linear-regression-using-normal-equation/starter_code.py b/questions/14_linear-regression-using-normal-equation/starter_code.py
index 38642e7e..cb981cc4 100644
--- a/questions/14_linear-regression-using-normal-equation/starter_code.py
+++ b/questions/14_linear-regression-using-normal-equation/starter_code.py
@@ -1,4 +1,5 @@
-import numpy as np
-def linear_regression_normal_equation(X: list[list[float]], y: list[float]) -> list[float]:
- # Your code here, make sure to round
- return theta
+def linear_regression_normal_equation(
+ X: list[list[float]], y: list[float]
+) -> list[float]:
+ # Your code here, make sure to round
+ return theta
diff --git a/questions/14_linear-regression-using-normal-equation/tinygrad/solution.py b/questions/14_linear-regression-using-normal-equation/tinygrad/solution.py
index 832f53ff..dc107027 100644
--- a/questions/14_linear-regression-using-normal-equation/tinygrad/solution.py
+++ b/questions/14_linear-regression-using-normal-equation/tinygrad/solution.py
@@ -1,6 +1,7 @@
import numpy as np
from tinygrad.tensor import Tensor
+
def linear_regression_normal_equation_tg(X, y) -> Tensor:
"""
Solve linear regression via the normal equation using tinygrad.
@@ -8,7 +9,7 @@ def linear_regression_normal_equation_tg(X, y) -> Tensor:
Returns a 1-D Tensor of length n, rounded to 4 decimals.
"""
X_np = np.array(X, dtype=float)
- y_np = np.array(y, dtype=float).reshape(-1,1)
+ y_np = np.array(y, dtype=float).reshape(-1, 1)
theta = np.linalg.inv(X_np.T.dot(X_np)).dot(X_np.T).dot(y_np)
theta = np.round(theta.flatten(), 4)
return Tensor(theta)
diff --git a/questions/14_linear-regression-using-normal-equation/tinygrad/starter_code.py b/questions/14_linear-regression-using-normal-equation/tinygrad/starter_code.py
index eead5dfc..36b81d7d 100644
--- a/questions/14_linear-regression-using-normal-equation/tinygrad/starter_code.py
+++ b/questions/14_linear-regression-using-normal-equation/tinygrad/starter_code.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def linear_regression_normal_equation_tg(X, y) -> Tensor:
"""
Solve linear regression via the normal equation using tinygrad.
diff --git a/questions/15_linear-regression-using-gradient-descent/pytorch/solution.py b/questions/15_linear-regression-using-gradient-descent/pytorch/solution.py
index 657c914a..55d984a7 100644
--- a/questions/15_linear-regression-using-gradient-descent/pytorch/solution.py
+++ b/questions/15_linear-regression-using-gradient-descent/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def linear_regression_gradient_descent(X, y, alpha, iterations) -> torch.Tensor:
"""
Solve linear regression via gradient descent using PyTorch autograd.
@@ -8,9 +9,9 @@ def linear_regression_gradient_descent(X, y, alpha, iterations) -> torch.Tensor:
Returns a 1-D tensor of length n, rounded to 4 decimals.
"""
X_t = torch.as_tensor(X, dtype=torch.float)
- y_t = torch.as_tensor(y, dtype=torch.float).reshape(-1,1)
+ y_t = torch.as_tensor(y, dtype=torch.float).reshape(-1, 1)
m, n = X_t.shape
- theta = torch.zeros((n,1), requires_grad=True)
+ theta = torch.zeros((n, 1), requires_grad=True)
for _ in range(iterations):
preds = X_t @ theta
loss = ((preds - y_t) ** 2).mean()
diff --git a/questions/15_linear-regression-using-gradient-descent/pytorch/starter_code.py b/questions/15_linear-regression-using-gradient-descent/pytorch/starter_code.py
index 3dce5f52..1aeff4c2 100644
--- a/questions/15_linear-regression-using-gradient-descent/pytorch/starter_code.py
+++ b/questions/15_linear-regression-using-gradient-descent/pytorch/starter_code.py
@@ -1,5 +1,6 @@
import torch
+
def linear_regression_gradient_descent(X, y, alpha, iterations) -> torch.Tensor:
"""
Solve linear regression via gradient descent using PyTorch autograd.
@@ -8,8 +9,8 @@ def linear_regression_gradient_descent(X, y, alpha, iterations) -> torch.Tensor:
Returns a 1-D tensor of length n, rounded to 4 decimals.
"""
X_t = torch.as_tensor(X, dtype=torch.float)
- y_t = torch.as_tensor(y, dtype=torch.float).reshape(-1,1)
+ torch.as_tensor(y, dtype=torch.float).reshape(-1, 1)
m, n = X_t.shape
- theta = torch.zeros((n,1), requires_grad=True)
+ torch.zeros((n, 1), requires_grad=True)
# Your implementation here
pass
diff --git a/questions/15_linear-regression-using-gradient-descent/solution.py b/questions/15_linear-regression-using-gradient-descent/solution.py
index ff331bd6..92b82451 100644
--- a/questions/15_linear-regression-using-gradient-descent/solution.py
+++ b/questions/15_linear-regression-using-gradient-descent/solution.py
@@ -1,4 +1,3 @@
-
import numpy as np
def linear_regression_gradient_descent(X: np.ndarray, y: np.ndarray, alpha: float, iterations: int) -> np.ndarray:
"""
diff --git a/questions/15_linear-regression-using-gradient-descent/tinygrad/solution.py b/questions/15_linear-regression-using-gradient-descent/tinygrad/solution.py
index 2dc4ad60..dba53deb 100644
--- a/questions/15_linear-regression-using-gradient-descent/tinygrad/solution.py
+++ b/questions/15_linear-regression-using-gradient-descent/tinygrad/solution.py
@@ -1,6 +1,7 @@
import numpy as np
from tinygrad.tensor import Tensor
+
def linear_regression_gradient_descent_tg(X, y, alpha, iterations) -> Tensor:
"""
Solve linear regression via gradient descent using tinygrad autograd.
@@ -9,7 +10,7 @@ def linear_regression_gradient_descent_tg(X, y, alpha, iterations) -> Tensor:
Returns a 1-D Tensor of length n, rounded to 4 decimals.
"""
X_t = Tensor(X).float()
- y_t = Tensor(y).float().reshape(-1,1)
+ y_t = Tensor(y).float().reshape(-1, 1)
m, n = X_t.shape
theta = Tensor([[0.0] for _ in range(n)])
for _ in range(iterations):
diff --git a/questions/15_linear-regression-using-gradient-descent/tinygrad/starter_code.py b/questions/15_linear-regression-using-gradient-descent/tinygrad/starter_code.py
index 9e98b0a3..bdc0dde7 100644
--- a/questions/15_linear-regression-using-gradient-descent/tinygrad/starter_code.py
+++ b/questions/15_linear-regression-using-gradient-descent/tinygrad/starter_code.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def linear_regression_gradient_descent_tg(X, y, alpha, iterations) -> Tensor:
"""
Solve linear regression via gradient descent using tinygrad autograd.
@@ -8,8 +9,8 @@ def linear_regression_gradient_descent_tg(X, y, alpha, iterations) -> Tensor:
Returns a 1-D Tensor of length n, rounded to 4 decimals.
"""
X_t = Tensor(X).float()
- y_t = Tensor(y).float().reshape(-1,1)
+ Tensor(y).float().reshape(-1, 1)
m, n = X_t.shape
- theta = Tensor([[0.0] for _ in range(n)])
+ Tensor([[0.0] for _ in range(n)])
# Your implementation here
pass
diff --git a/questions/16_feature-scaling-implementation/pytorch/solution.py b/questions/16_feature-scaling-implementation/pytorch/solution.py
index 4d0508bc..b1bb2f89 100644
--- a/questions/16_feature-scaling-implementation/pytorch/solution.py
+++ b/questions/16_feature-scaling-implementation/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def feature_scaling(data) -> tuple[torch.Tensor, torch.Tensor]:
"""
Standardize and Min-Max normalize input data using PyTorch.
diff --git a/questions/16_feature-scaling-implementation/pytorch/starter_code.py b/questions/16_feature-scaling-implementation/pytorch/starter_code.py
index 827f55c3..a51ae44e 100644
--- a/questions/16_feature-scaling-implementation/pytorch/starter_code.py
+++ b/questions/16_feature-scaling-implementation/pytorch/starter_code.py
@@ -1,11 +1,12 @@
import torch
+
def feature_scaling(data) -> tuple[torch.Tensor, torch.Tensor]:
"""
Standardize and Min-Max normalize input data using PyTorch.
Input: Tensor or convertible of shape (m,n).
Returns (standardized_data, normalized_data), both rounded to 4 decimals.
"""
- data_t = torch.as_tensor(data, dtype=torch.float)
+ torch.as_tensor(data, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/16_feature-scaling-implementation/solution.py b/questions/16_feature-scaling-implementation/solution.py
index 6b6a0fd7..f39a8429 100644
--- a/questions/16_feature-scaling-implementation/solution.py
+++ b/questions/16_feature-scaling-implementation/solution.py
@@ -1,15 +1,17 @@
-
import numpy as np
+
def feature_scaling(data):
# Standardization
mean = np.mean(data, axis=0)
std = np.std(data, axis=0)
standardized_data = (data - mean) / std
-
+
# Min-Max Normalization
min_val = np.min(data, axis=0)
max_val = np.max(data, axis=0)
normalized_data = (data - min_val) / (max_val - min_val)
-
- return np.round(standardized_data,4).tolist(), np.round(normalized_data,4).tolist()
+
+ return np.round(standardized_data, 4).tolist(), np.round(
+ normalized_data, 4
+ ).tolist()
diff --git a/questions/16_feature-scaling-implementation/starter_code.py b/questions/16_feature-scaling-implementation/starter_code.py
index 42618d0a..19260847 100644
--- a/questions/16_feature-scaling-implementation/starter_code.py
+++ b/questions/16_feature-scaling-implementation/starter_code.py
@@ -1,3 +1,3 @@
def feature_scaling(data: np.ndarray) -> (np.ndarray, np.ndarray):
- # Your code here
- return standardized_data, normalized_data
+ # Your code here
+ return standardized_data, normalized_data
diff --git a/questions/16_feature-scaling-implementation/tinygrad/solution.py b/questions/16_feature-scaling-implementation/tinygrad/solution.py
index aee85f1b..78bd0bc4 100644
--- a/questions/16_feature-scaling-implementation/tinygrad/solution.py
+++ b/questions/16_feature-scaling-implementation/tinygrad/solution.py
@@ -1,6 +1,7 @@
import numpy as np
from tinygrad.tensor import Tensor
+
def feature_scaling_tg(data) -> tuple[Tensor, Tensor]:
"""
Standardize and Min-Max normalize input data using tinygrad.
diff --git a/questions/16_feature-scaling-implementation/tinygrad/starter_code.py b/questions/16_feature-scaling-implementation/tinygrad/starter_code.py
index 0e367e7d..17cceb8f 100644
--- a/questions/16_feature-scaling-implementation/tinygrad/starter_code.py
+++ b/questions/16_feature-scaling-implementation/tinygrad/starter_code.py
@@ -1,11 +1,12 @@
from tinygrad.tensor import Tensor
+
def feature_scaling_tg(data) -> tuple[Tensor, Tensor]:
"""
Standardize and Min-Max normalize input data using tinygrad.
Input: Tensor or convertible of shape (m,n).
Returns (standardized_data, normalized_data), both rounded to 4 decimals.
"""
- data_t = Tensor(data).float()
+ Tensor(data).float()
# Your implementation here
pass
diff --git a/questions/17_k-means-clustering/pytorch/solution.py b/questions/17_k-means-clustering/pytorch/solution.py
index ed0f38d0..46f40c22 100644
--- a/questions/17_k-means-clustering/pytorch/solution.py
+++ b/questions/17_k-means-clustering/pytorch/solution.py
@@ -1,6 +1,9 @@
import torch
-def k_means_clustering(points, k, initial_centroids, max_iterations) -> list[tuple[float, ...]]:
+
+def k_means_clustering(
+ points, k, initial_centroids, max_iterations
+) -> list[tuple[float, ...]]:
"""
Perform k-means clustering on `points` into `k` clusters.
points: tensor of shape (n_points, n_features)
@@ -13,7 +16,7 @@ def k_means_clustering(points, k, initial_centroids, max_iterations) -> list[tup
for _ in range(max_iterations):
# compute distances (k, n_points)
diffs = points_t.unsqueeze(0) - centroids.unsqueeze(1)
- distances = torch.sqrt((diffs ** 2).sum(dim=2))
+ distances = torch.sqrt((diffs**2).sum(dim=2))
# assign each point to nearest centroid
assignments = distances.argmin(dim=0)
new_centroids = []
diff --git a/questions/17_k-means-clustering/pytorch/starter_code.py b/questions/17_k-means-clustering/pytorch/starter_code.py
index 7101417a..9acc490e 100644
--- a/questions/17_k-means-clustering/pytorch/starter_code.py
+++ b/questions/17_k-means-clustering/pytorch/starter_code.py
@@ -1,6 +1,9 @@
import torch
-def k_means_clustering(points, k, initial_centroids, max_iterations) -> list[tuple[float, ...]]:
+
+def k_means_clustering(
+ points, k, initial_centroids, max_iterations
+) -> list[tuple[float, ...]]:
"""
Perform k-means clustering on `points` into `k` clusters.
points: tensor of shape (n_points, n_features)
@@ -9,7 +12,7 @@ def k_means_clustering(points, k, initial_centroids, max_iterations) -> list[tup
Returns a list of k centroids as tuples, rounded to 4 decimals.
"""
# Convert to tensors
- points_t = torch.as_tensor(points, dtype=torch.float)
- centroids = torch.as_tensor(initial_centroids, dtype=torch.float)
+ torch.as_tensor(points, dtype=torch.float)
+ torch.as_tensor(initial_centroids, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/17_k-means-clustering/solution.py b/questions/17_k-means-clustering/solution.py
index 97d79341..0f65d1d5 100644
--- a/questions/17_k-means-clustering/solution.py
+++ b/questions/17_k-means-clustering/solution.py
@@ -1,23 +1,33 @@
-
import numpy as np
+
def euclidean_distance(a, b):
return np.sqrt(((a - b) ** 2).sum(axis=1))
+
def k_means_clustering(points, k, initial_centroids, max_iterations):
points = np.array(points)
centroids = np.array(initial_centroids)
-
+
for iteration in range(max_iterations):
# Assign points to the nearest centroid
- distances = np.array([euclidean_distance(points, centroid) for centroid in centroids])
+ distances = np.array(
+ [euclidean_distance(points, centroid) for centroid in centroids]
+ )
assignments = np.argmin(distances, axis=0)
- new_centroids = np.array([points[assignments == i].mean(axis=0) if len(points[assignments == i]) > 0 else centroids[i] for i in range(k)])
-
+ new_centroids = np.array(
+ [
+ points[assignments == i].mean(axis=0)
+ if len(points[assignments == i]) > 0
+ else centroids[i]
+ for i in range(k)
+ ]
+ )
+
# Check for convergence
if np.all(centroids == new_centroids):
break
centroids = new_centroids
- centroids = np.round(centroids,4)
+ centroids = np.round(centroids, 4)
return [tuple(centroid) for centroid in centroids]
diff --git a/questions/17_k-means-clustering/starter_code.py b/questions/17_k-means-clustering/starter_code.py
index 8a792434..9807adfa 100644
--- a/questions/17_k-means-clustering/starter_code.py
+++ b/questions/17_k-means-clustering/starter_code.py
@@ -1,3 +1,8 @@
-def k_means_clustering(points: list[tuple[float, float]], k: int, initial_centroids: list[tuple[float, float]], max_iterations: int) -> list[tuple[float, float]]:
- # Your code here
- return final_centroids
+def k_means_clustering(
+ points: list[tuple[float, float]],
+ k: int,
+ initial_centroids: list[tuple[float, float]],
+ max_iterations: int,
+) -> list[tuple[float, float]]:
+ # Your code here
+ return final_centroids
diff --git a/questions/17_k-means-clustering/tinygrad/solution.py b/questions/17_k-means-clustering/tinygrad/solution.py
index 53a3370c..3458de98 100644
--- a/questions/17_k-means-clustering/tinygrad/solution.py
+++ b/questions/17_k-means-clustering/tinygrad/solution.py
@@ -1,7 +1,9 @@
import numpy as np
-from tinygrad.tensor import Tensor
-def k_means_clustering_tg(points, k, initial_centroids, max_iterations) -> list[tuple[float, ...]]:
+
+def k_means_clustering_tg(
+ points, k, initial_centroids, max_iterations
+) -> list[tuple[float, ...]]:
"""
Perform k-means clustering on `points` into `k` clusters using tinygrad.
points: list of lists or Tensor, shape (n_points, n_features)
@@ -16,10 +18,14 @@ def k_means_clustering_tg(points, k, initial_centroids, max_iterations) -> list[
dists = np.array([np.linalg.norm(pts - c, axis=1) for c in centroids])
# assign points
assignments = dists.argmin(axis=0)
- new_centroids = np.array([
- pts[assignments == i].mean(axis=0) if np.any(assignments == i) else centroids[i]
- for i in range(k)
- ])
+ new_centroids = np.array(
+ [
+ pts[assignments == i].mean(axis=0)
+ if np.any(assignments == i)
+ else centroids[i]
+ for i in range(k)
+ ]
+ )
new_centroids = np.round(new_centroids, 4)
if np.array_equal(new_centroids, centroids):
break
diff --git a/questions/17_k-means-clustering/tinygrad/starter_code.py b/questions/17_k-means-clustering/tinygrad/starter_code.py
index 2ae44a09..0f3f73ac 100644
--- a/questions/17_k-means-clustering/tinygrad/starter_code.py
+++ b/questions/17_k-means-clustering/tinygrad/starter_code.py
@@ -1,6 +1,6 @@
-from tinygrad.tensor import Tensor
-
-def k_means_clustering_tg(points, k, initial_centroids, max_iterations) -> list[tuple[float, ...]]:
+def k_means_clustering_tg(
+ points, k, initial_centroids, max_iterations
+) -> list[tuple[float, ...]]:
"""
Perform k-means clustering on `points` into `k` clusters using tinygrad.
points: list of lists or Tensor, shape (n_points, n_features)
diff --git a/questions/18_implement-k-fold-cross-validation/pytorch/solution.py b/questions/18_implement-k-fold-cross-validation/pytorch/solution.py
index b9ca822a..6d0ef5a4 100644
--- a/questions/18_implement-k-fold-cross-validation/pytorch/solution.py
+++ b/questions/18_implement-k-fold-cross-validation/pytorch/solution.py
@@ -1,6 +1,9 @@
import torch
-def k_fold_cross_validation(X, y, k=5, shuffle=True) -> list[tuple[list[int], list[int]]]:
+
+def k_fold_cross_validation(
+ X, y, k=5, shuffle=True
+) -> list[tuple[list[int], list[int]]]:
"""
Return train/test index splits for k-fold cross-validation using PyTorch.
X: Tensor or convertible of shape (n_samples, ...)
@@ -20,7 +23,7 @@ def k_fold_cross_validation(X, y, k=5, shuffle=True) -> list[tuple[list[int], li
folds = []
start = 0
for fs in fold_sizes:
- folds.append(indices[start:start+fs].tolist())
+ folds.append(indices[start : start + fs].tolist())
start += fs
result = []
for i in range(k):
diff --git a/questions/18_implement-k-fold-cross-validation/pytorch/starter_code.py b/questions/18_implement-k-fold-cross-validation/pytorch/starter_code.py
index c881f619..16d78e89 100644
--- a/questions/18_implement-k-fold-cross-validation/pytorch/starter_code.py
+++ b/questions/18_implement-k-fold-cross-validation/pytorch/starter_code.py
@@ -1,6 +1,9 @@
import torch
-def k_fold_cross_validation(X, y, k=5, shuffle=True) -> list[tuple[list[int], list[int]]]:
+
+def k_fold_cross_validation(
+ X, y, k=5, shuffle=True
+) -> list[tuple[list[int], list[int]]]:
"""
Return train/test index splits for k-fold cross-validation using PyTorch.
X: Tensor or convertible of shape (n_samples, ...)
@@ -22,7 +25,7 @@ def k_fold_cross_validation(X, y, k=5, shuffle=True) -> list[tuple[list[int], li
folds = []
start = 0
for fs in fold_sizes:
- folds.append(indices[start:start+fs].tolist())
+ folds.append(indices[start : start + fs].tolist())
start += fs
# build train/test pairs
result = []
diff --git a/questions/18_implement-k-fold-cross-validation/starter_code.py b/questions/18_implement-k-fold-cross-validation/starter_code.py
index 8a3ebdbc..2adb7db9 100644
--- a/questions/18_implement-k-fold-cross-validation/starter_code.py
+++ b/questions/18_implement-k-fold-cross-validation/starter_code.py
@@ -1,5 +1,6 @@
import numpy as np
+
def k_fold_cross_validation(X: np.ndarray, y: np.ndarray, k=5, shuffle=True):
"""
Implement k-fold cross-validation by returning train-test indices.
diff --git a/questions/18_implement-k-fold-cross-validation/tinygrad/solution.py b/questions/18_implement-k-fold-cross-validation/tinygrad/solution.py
index d564f51b..5dfc4603 100644
--- a/questions/18_implement-k-fold-cross-validation/tinygrad/solution.py
+++ b/questions/18_implement-k-fold-cross-validation/tinygrad/solution.py
@@ -1,6 +1,9 @@
import numpy as np
-def k_fold_cross_validation_tg(X, y, k=5, shuffle=True) -> list[tuple[list[int], list[int]]]:
+
+def k_fold_cross_validation_tg(
+ X, y, k=5, shuffle=True
+) -> list[tuple[list[int], list[int]]]:
"""
Return train/test index splits for k-fold cross-validation using NumPy backend.
X: list or NumPy array or Tensor of shape (n_samples, ...)
@@ -20,7 +23,7 @@ def k_fold_cross_validation_tg(X, y, k=5, shuffle=True) -> list[tuple[list[int],
folds = []
start = 0
for fs in fold_sizes:
- folds.append(indices[start:start+fs].tolist())
+ folds.append(indices[start : start + fs].tolist())
start += fs
result = []
for i in range(k):
diff --git a/questions/18_implement-k-fold-cross-validation/tinygrad/starter_code.py b/questions/18_implement-k-fold-cross-validation/tinygrad/starter_code.py
index 2d0c8230..a440c8ab 100644
--- a/questions/18_implement-k-fold-cross-validation/tinygrad/starter_code.py
+++ b/questions/18_implement-k-fold-cross-validation/tinygrad/starter_code.py
@@ -1,4 +1,6 @@
-def k_fold_cross_validation_tg(X, y, k=5, shuffle=True) -> list[tuple[list[int], list[int]]]:
+def k_fold_cross_validation_tg(
+ X, y, k=5, shuffle=True
+) -> list[tuple[list[int], list[int]]]:
"""
Return train/test index splits for k-fold cross-validation using pure Python or tinygrad.
X: list or Tensor of shape (n_samples, ...)
diff --git a/questions/19_principal-component-analysis-pca-implementation/pytorch/solution.py b/questions/19_principal-component-analysis-pca-implementation/pytorch/solution.py
index 7a8263fc..dccbee4e 100644
--- a/questions/19_principal-component-analysis-pca-implementation/pytorch/solution.py
+++ b/questions/19_principal-component-analysis-pca-implementation/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def pca(data, k) -> torch.Tensor:
"""
Perform PCA on `data`, returning the top `k` principal components as a tensor.
@@ -9,7 +10,7 @@ def pca(data, k) -> torch.Tensor:
data_t = torch.as_tensor(data, dtype=torch.float)
# Standardize
mean = data_t.mean(dim=0, keepdim=True)
- std = data_t.std(dim=0, unbiased=False, keepdim=True)
+ std = data_t.std(dim=0, unbiased=False, keepdim=True)
data_std = (data_t - mean) / std
# Covariance
cov = torch.cov(data_std.T)
diff --git a/questions/19_principal-component-analysis-pca-implementation/pytorch/starter_code.py b/questions/19_principal-component-analysis-pca-implementation/pytorch/starter_code.py
index 3df21fa1..ddcbfea8 100644
--- a/questions/19_principal-component-analysis-pca-implementation/pytorch/starter_code.py
+++ b/questions/19_principal-component-analysis-pca-implementation/pytorch/starter_code.py
@@ -1,11 +1,12 @@
import torch
+
def pca(data, k) -> torch.Tensor:
"""
Perform PCA on `data`, returning the top `k` principal components as a tensor.
Input: Tensor or convertible of shape (n_samples, n_features).
Returns: a torch.Tensor of shape (n_features, k), with floats rounded to 4 decimals.
"""
- data_t = torch.as_tensor(data, dtype=torch.float)
+ torch.as_tensor(data, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/19_principal-component-analysis-pca-implementation/solution.py b/questions/19_principal-component-analysis-pca-implementation/solution.py
index 75b349e5..02222015 100644
--- a/questions/19_principal-component-analysis-pca-implementation/solution.py
+++ b/questions/19_principal-component-analysis-pca-implementation/solution.py
@@ -1,22 +1,22 @@
-
import numpy as np
+
def pca(data, k):
# Standardize the data
data_standardized = (data - np.mean(data, axis=0)) / np.std(data, axis=0)
-
+
# Compute the covariance matrix
covariance_matrix = np.cov(data_standardized, rowvar=False)
-
+
# Eigen decomposition
eigenvalues, eigenvectors = np.linalg.eig(covariance_matrix)
-
+
# Sort the eigenvectors by decreasing eigenvalues
idx = np.argsort(eigenvalues)[::-1]
- eigenvalues_sorted = eigenvalues[idx]
- eigenvectors_sorted = eigenvectors[:,idx]
-
+ eigenvalues[idx]
+ eigenvectors_sorted = eigenvectors[:, idx]
+
# Select the top k eigenvectors (principal components)
principal_components = eigenvectors_sorted[:, :k]
-
+
return np.round(principal_components, 4)
diff --git a/questions/19_principal-component-analysis-pca-implementation/starter_code.py b/questions/19_principal-component-analysis-pca-implementation/starter_code.py
index 3cb75f74..5799f625 100644
--- a/questions/19_principal-component-analysis-pca-implementation/starter_code.py
+++ b/questions/19_principal-component-analysis-pca-implementation/starter_code.py
@@ -1,4 +1,6 @@
-import numpy as np
+import numpy as np
+
+
def pca(data: np.ndarray, k: int) -> np.ndarray:
- # Your code here
- return np.round(principal_components, 4)
+ # Your code here
+ return np.round(principal_components, 4)
diff --git a/questions/19_principal-component-analysis-pca-implementation/tinygrad/solution.py b/questions/19_principal-component-analysis-pca-implementation/tinygrad/solution.py
index 61724c54..4ea761da 100644
--- a/questions/19_principal-component-analysis-pca-implementation/tinygrad/solution.py
+++ b/questions/19_principal-component-analysis-pca-implementation/tinygrad/solution.py
@@ -1,6 +1,7 @@
import numpy as np
from tinygrad.tensor import Tensor
+
def pca_tg(data, k) -> Tensor:
"""
Perform PCA on `data`, returning the top `k` principal components as a tinygrad Tensor.
diff --git a/questions/19_principal-component-analysis-pca-implementation/tinygrad/starter_code.py b/questions/19_principal-component-analysis-pca-implementation/tinygrad/starter_code.py
index d46a32e7..9d2b4029 100644
--- a/questions/19_principal-component-analysis-pca-implementation/tinygrad/starter_code.py
+++ b/questions/19_principal-component-analysis-pca-implementation/tinygrad/starter_code.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def pca_tg(data, k) -> Tensor:
"""
Perform PCA on `data`, returning the top `k` principal components as a tinygrad Tensor.
diff --git a/questions/1_matrix-vector-dot-product/pytorch/solution.py b/questions/1_matrix-vector-dot-product/pytorch/solution.py
index 17a3f582..e43a2e3d 100644
--- a/questions/1_matrix-vector-dot-product/pytorch/solution.py
+++ b/questions/1_matrix-vector-dot-product/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def matrix_dot_vector(a, b) -> torch.Tensor:
"""
Compute the product of matrix `a` and vector `b` using PyTorch.
diff --git a/questions/1_matrix-vector-dot-product/pytorch/starter_code.py b/questions/1_matrix-vector-dot-product/pytorch/starter_code.py
index 776632b8..0139dc98 100644
--- a/questions/1_matrix-vector-dot-product/pytorch/starter_code.py
+++ b/questions/1_matrix-vector-dot-product/pytorch/starter_code.py
@@ -1,5 +1,6 @@
import torch
+
def matrix_dot_vector(a, b) -> torch.Tensor:
"""
Compute the product of matrix `a` and vector `b` using PyTorch.
diff --git a/questions/1_matrix-vector-dot-product/solution.py b/questions/1_matrix-vector-dot-product/solution.py
index db795872..2356e2a7 100644
--- a/questions/1_matrix-vector-dot-product/solution.py
+++ b/questions/1_matrix-vector-dot-product/solution.py
@@ -1,4 +1,6 @@
-def matrix_dot_vector(a: list[list[int|float]], b: list[int|float]) -> list[int|float]:
+def matrix_dot_vector(
+ a: list[list[int | float]], b: list[int | float]
+) -> list[int | float]:
if len(a[0]) != len(b):
return -1
result = []
diff --git a/questions/1_matrix-vector-dot-product/starter_code.py b/questions/1_matrix-vector-dot-product/starter_code.py
index 9d681c5b..eafcef69 100644
--- a/questions/1_matrix-vector-dot-product/starter_code.py
+++ b/questions/1_matrix-vector-dot-product/starter_code.py
@@ -1,4 +1,6 @@
-def matrix_dot_vector(a: list[list[int|float]], b: list[int|float]) -> list[int|float]:
- # Return a list where each element is the dot product of a row of 'a' with 'b'.
- # If the number of columns in 'a' does not match the length of 'b', return -1.
- pass
+def matrix_dot_vector(
+ a: list[list[int | float]], b: list[int | float]
+) -> list[int | float]:
+ # Return a list where each element is the dot product of a row of 'a' with 'b'.
+ # If the number of columns in 'a' does not match the length of 'b', return -1.
+ pass
diff --git a/questions/20_decision-tree-learning/pytorch/solution.py b/questions/20_decision-tree-learning/pytorch/solution.py
index 52e72cc7..20eaeb77 100644
--- a/questions/20_decision-tree-learning/pytorch/solution.py
+++ b/questions/20_decision-tree-learning/pytorch/solution.py
@@ -1,4 +1,3 @@
-import torch
import math
from collections import Counter
from typing import List, Dict, Any, Union
@@ -15,9 +14,7 @@ def calculate_entropy(labels: List[Any]) -> float:
def calculate_information_gain(
- examples: List[Dict[str, Any]],
- attr: str,
- target_attr: str
+ examples: List[Dict[str, Any]], attr: str, target_attr: str
) -> float:
total_labels = [ex[target_attr] for ex in examples]
total_ent = calculate_entropy(total_labels)
@@ -25,30 +22,27 @@ def calculate_information_gain(
rem = 0.0
for v in set(ex[attr] for ex in examples):
subset_labels = [ex[target_attr] for ex in examples if ex[attr] == v]
- rem += (len(subset_labels)/n) * calculate_entropy(subset_labels)
+ rem += (len(subset_labels) / n) * calculate_entropy(subset_labels)
return total_ent - rem
-def majority_class(
- examples: List[Dict[str, Any]],
- target_attr: str
-) -> Any:
+def majority_class(examples: List[Dict[str, Any]], target_attr: str) -> Any:
return Counter(ex[target_attr] for ex in examples).most_common(1)[0][0]
def learn_decision_tree(
- examples: List[Dict[str, Any]],
- attributes: List[str],
- target_attr: str
+ examples: List[Dict[str, Any]], attributes: List[str], target_attr: str
) -> Union[Dict[str, Any], Any]:
if not examples:
- return 'No examples'
+ return "No examples"
first_label = examples[0][target_attr]
if all(ex[target_attr] == first_label for ex in examples):
return first_label
if not attributes:
return majority_class(examples, target_attr)
- gains = {a: calculate_information_gain(examples, a, target_attr) for a in attributes}
+ gains = {
+ a: calculate_information_gain(examples, a, target_attr) for a in attributes
+ }
best = max(gains, key=gains.get)
tree: Dict[str, Any] = {best: {}}
for v in set(ex[best] for ex in examples):
diff --git a/questions/20_decision-tree-learning/pytorch/starter_code.py b/questions/20_decision-tree-learning/pytorch/starter_code.py
index 4531de26..fdff605f 100644
--- a/questions/20_decision-tree-learning/pytorch/starter_code.py
+++ b/questions/20_decision-tree-learning/pytorch/starter_code.py
@@ -1,6 +1,3 @@
-import torch
-import math
-from collections import Counter
from typing import List, Dict, Any, Union
@@ -15,9 +12,7 @@ def calculate_entropy(labels: List[Any]) -> float:
def calculate_information_gain(
- examples: List[Dict[str, Any]],
- attr: str,
- target_attr: str
+ examples: List[Dict[str, Any]], attr: str, target_attr: str
) -> float:
"""
Compute information gain for splitting `examples` on `attr` w.r.t. `target_attr`.
@@ -27,10 +22,7 @@ def calculate_information_gain(
pass
-def majority_class(
- examples: List[Dict[str, Any]],
- target_attr: str
-) -> Any:
+def majority_class(examples: List[Dict[str, Any]], target_attr: str) -> Any:
"""
Return the most common value of `target_attr` in `examples`.
"""
@@ -39,9 +31,7 @@ def majority_class(
def learn_decision_tree(
- examples: List[Dict[str, Any]],
- attributes: List[str],
- target_attr: str
+ examples: List[Dict[str, Any]], attributes: List[str], target_attr: str
) -> Union[Dict[str, Any], Any]:
"""
Learn a decision tree using the ID3 algorithm.
diff --git a/questions/20_decision-tree-learning/solution.py b/questions/20_decision-tree-learning/solution.py
index 3a66870e..78cfc6bd 100644
--- a/questions/20_decision-tree-learning/solution.py
+++ b/questions/20_decision-tree-learning/solution.py
@@ -1,43 +1,54 @@
-
import math
from collections import Counter
+
def calculate_entropy(labels):
label_counts = Counter(labels)
total_count = len(labels)
- entropy = -sum((count / total_count) * math.log2(count / total_count) for count in label_counts.values())
+ entropy = -sum(
+ (count / total_count) * math.log2(count / total_count)
+ for count in label_counts.values()
+ )
return entropy
+
def calculate_information_gain(examples, attr, target_attr):
total_entropy = calculate_entropy([example[target_attr] for example in examples])
values = set(example[attr] for example in examples)
attr_entropy = 0
for value in values:
- value_subset = [example[target_attr] for example in examples if example[attr] == value]
+ value_subset = [
+ example[target_attr] for example in examples if example[attr] == value
+ ]
value_entropy = calculate_entropy(value_subset)
attr_entropy += (len(value_subset) / len(examples)) * value_entropy
return total_entropy - attr_entropy
+
def majority_class(examples, target_attr):
return Counter([example[target_attr] for example in examples]).most_common(1)[0][0]
+
def learn_decision_tree(examples, attributes, target_attr):
if not examples:
- return 'No examples'
+ return "No examples"
if all(example[target_attr] == examples[0][target_attr] for example in examples):
return examples[0][target_attr]
if not attributes:
return majority_class(examples, target_attr)
-
- gains = {attr: calculate_information_gain(examples, attr, target_attr) for attr in attributes}
+
+ gains = {
+ attr: calculate_information_gain(examples, attr, target_attr)
+ for attr in attributes
+ }
best_attr = max(gains, key=gains.get)
tree = {best_attr: {}}
-
+
for value in set(example[best_attr] for example in examples):
subset = [example for example in examples if example[best_attr] == value]
new_attributes = attributes.copy()
new_attributes.remove(best_attr)
subtree = learn_decision_tree(subset, new_attributes, target_attr)
tree[best_attr][value] = subtree
-
+
return tree
diff --git a/questions/20_decision-tree-learning/starter_code.py b/questions/20_decision-tree-learning/starter_code.py
index fd8e7112..943552ef 100644
--- a/questions/20_decision-tree-learning/starter_code.py
+++ b/questions/20_decision-tree-learning/starter_code.py
@@ -1,3 +1,5 @@
-def learn_decision_tree(examples: list[dict], attributes: list[str], target_attr: str) -> dict:
- # Your code here
- return decision_tree
+def learn_decision_tree(
+ examples: list[dict], attributes: list[str], target_attr: str
+) -> dict:
+ # Your code here
+ return decision_tree
diff --git a/questions/20_decision-tree-learning/tinygrad/solution.py b/questions/20_decision-tree-learning/tinygrad/solution.py
index 808c6f85..95f46466 100644
--- a/questions/20_decision-tree-learning/tinygrad/solution.py
+++ b/questions/20_decision-tree-learning/tinygrad/solution.py
@@ -8,13 +8,11 @@ def calculate_entropy_tg(labels) -> float:
arr = labels.tolist() if isinstance(labels, Tensor) else labels
total = len(arr)
cnt = Counter(arr)
- return -sum((c/total)*math.log2(c/total) for c in cnt.values())
+ return -sum((c / total) * math.log2(c / total) for c in cnt.values())
def calculate_information_gain_tg(
- examples: List[Dict[str, Any]],
- attr: str,
- target_attr: str
+ examples: List[Dict[str, Any]], attr: str, target_attr: str
) -> float:
total = [ex[target_attr] for ex in examples]
total_ent = calculate_entropy_tg(total)
@@ -22,30 +20,27 @@ def calculate_information_gain_tg(
rem = 0.0
for v in set(ex[attr] for ex in examples):
subset = [ex[target_attr] for ex in examples if ex[attr] == v]
- rem += (len(subset)/n) * calculate_entropy_tg(subset)
+ rem += (len(subset) / n) * calculate_entropy_tg(subset)
return total_ent - rem
-def majority_class_tg(
- examples: List[Dict[str, Any]],
- target_attr: str
-) -> Any:
+def majority_class_tg(examples: List[Dict[str, Any]], target_attr: str) -> Any:
return Counter(ex[target_attr] for ex in examples).most_common(1)[0][0]
def learn_decision_tree_tg(
- examples: List[Dict[str, Any]],
- attributes: List[str],
- target_attr: str
+ examples: List[Dict[str, Any]], attributes: List[str], target_attr: str
) -> Union[Dict[str, Any], Any]:
if not examples:
- return 'No examples'
+ return "No examples"
first_label = examples[0][target_attr]
if all(ex[target_attr] == first_label for ex in examples):
return first_label
if not attributes:
return majority_class_tg(examples, target_attr)
- gains = {a: calculate_information_gain_tg(examples, a, target_attr) for a in attributes}
+ gains = {
+ a: calculate_information_gain_tg(examples, a, target_attr) for a in attributes
+ }
best = max(gains, key=gains.get)
tree: Dict[str, Any] = {best: {}}
for v in set(ex[best] for ex in examples):
diff --git a/questions/20_decision-tree-learning/tinygrad/starter_code.py b/questions/20_decision-tree-learning/tinygrad/starter_code.py
index 510b469b..e3cafa7f 100644
--- a/questions/20_decision-tree-learning/tinygrad/starter_code.py
+++ b/questions/20_decision-tree-learning/tinygrad/starter_code.py
@@ -1,12 +1,8 @@
-import math
-from collections import Counter
from typing import List, Dict, Any, Union
def learn_decision_tree_tg(
- examples: List[Dict[str, Any]],
- attributes: List[str],
- target_attr: str
+ examples: List[Dict[str, Any]], attributes: List[str], target_attr: str
) -> Union[Dict[str, Any], Any]:
"""
Learn a decision tree using ID3 with tinygrad for entropy/gain.
diff --git a/questions/21_pegasos-kernel-svm-implementation/solution.py b/questions/21_pegasos-kernel-svm-implementation/solution.py
index bee077e2..1f07bcc5 100644
--- a/questions/21_pegasos-kernel-svm-implementation/solution.py
+++ b/questions/21_pegasos-kernel-svm-implementation/solution.py
@@ -1,13 +1,17 @@
-
import numpy as np
+
def linear_kernel(x, y):
return np.dot(x, y)
+
def rbf_kernel(x, y, sigma=1.0):
- return np.exp(-np.linalg.norm(x-y)**2 / (2 * (sigma ** 2)))
+ return np.exp(-(np.linalg.norm(x - y) ** 2) / (2 * (sigma**2)))
-def pegasos_kernel_svm(data, labels, kernel='linear', lambda_val=0.01, iterations=100, sigma=1.0):
+
+def pegasos_kernel_svm(
+ data, labels, kernel="linear", lambda_val=0.01, iterations=100, sigma=1.0
+):
n_samples = len(data)
alphas = np.zeros(n_samples)
b = 0
@@ -15,14 +19,21 @@ def pegasos_kernel_svm(data, labels, kernel='linear', lambda_val=0.01, iteration
for t in range(1, iterations + 1):
for i in range(n_samples):
eta = 1.0 / (lambda_val * t)
- if kernel == 'linear':
+ if kernel == "linear":
kernel_func = linear_kernel
- elif kernel == 'rbf':
- kernel_func = lambda x, y: rbf_kernel(x, y, sigma)
-
- decision = sum(alphas[j] * labels[j] * kernel_func(data[j], data[i]) for j in range(n_samples)) + b
+ elif kernel == "rbf":
+ def kernel_func(x, y):
+ return rbf_kernel(x, y, sigma)
+
+ decision = (
+ sum(
+ alphas[j] * labels[j] * kernel_func(data[j], data[i])
+ for j in range(n_samples)
+ )
+ + b
+ )
if labels[i] * decision < 1:
alphas[i] += eta * (labels[i] - lambda_val * alphas[i])
b += eta * labels[i]
- return np.round(alphas,4).tolist(), np.round(b,4)
+ return np.round(alphas, 4).tolist(), np.round(b, 4)
diff --git a/questions/21_pegasos-kernel-svm-implementation/starter_code.py b/questions/21_pegasos-kernel-svm-implementation/starter_code.py
index 06fbcc08..b6069bda 100644
--- a/questions/21_pegasos-kernel-svm-implementation/starter_code.py
+++ b/questions/21_pegasos-kernel-svm-implementation/starter_code.py
@@ -1,3 +1,10 @@
-def pegasos_kernel_svm(data: np.ndarray, labels: np.ndarray, kernel='linear', lambda_val=0.01, iterations=100,sigma=1.0) -> (list, float):
- # Your code here
- return alphas, b
+def pegasos_kernel_svm(
+ data: np.ndarray,
+ labels: np.ndarray,
+ kernel="linear",
+ lambda_val=0.01,
+ iterations=100,
+ sigma=1.0,
+) -> (list, float):
+ # Your code here
+ return alphas, b
diff --git a/questions/22_sigmoid-activation-function-understanding/pytorch/solution.py b/questions/22_sigmoid-activation-function-understanding/pytorch/solution.py
index 8ec1343d..4604b9c0 100644
--- a/questions/22_sigmoid-activation-function-understanding/pytorch/solution.py
+++ b/questions/22_sigmoid-activation-function-understanding/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def sigmoid(z: float) -> float:
"""
Compute the sigmoid activation function.
diff --git a/questions/22_sigmoid-activation-function-understanding/pytorch/starter_code.py b/questions/22_sigmoid-activation-function-understanding/pytorch/starter_code.py
index c1503f83..28ac05aa 100644
--- a/questions/22_sigmoid-activation-function-understanding/pytorch/starter_code.py
+++ b/questions/22_sigmoid-activation-function-understanding/pytorch/starter_code.py
@@ -1,5 +1,3 @@
-import torch
-
def sigmoid(z: float) -> float:
"""
Compute the sigmoid activation function.
diff --git a/questions/22_sigmoid-activation-function-understanding/solution.py b/questions/22_sigmoid-activation-function-understanding/solution.py
index c3a97bb9..f6ef453c 100644
--- a/questions/22_sigmoid-activation-function-understanding/solution.py
+++ b/questions/22_sigmoid-activation-function-understanding/solution.py
@@ -1,5 +1,6 @@
-
import math
+
+
def sigmoid(z: float) -> float:
- result = 1 / (1 + math.exp(-z))
- return round(result, 4)
+ result = 1 / (1 + math.exp(-z))
+ return round(result, 4)
diff --git a/questions/22_sigmoid-activation-function-understanding/starter_code.py b/questions/22_sigmoid-activation-function-understanding/starter_code.py
index 256d2e53..7b5ab6a1 100644
--- a/questions/22_sigmoid-activation-function-understanding/starter_code.py
+++ b/questions/22_sigmoid-activation-function-understanding/starter_code.py
@@ -1,5 +1,3 @@
-import math
-
def sigmoid(z: float) -> float:
- #Your code here
- return result
+ # Your code here
+ return result
diff --git a/questions/22_sigmoid-activation-function-understanding/tinygrad/solution.py b/questions/22_sigmoid-activation-function-understanding/tinygrad/solution.py
index 4309ce0b..ae2e5797 100644
--- a/questions/22_sigmoid-activation-function-understanding/tinygrad/solution.py
+++ b/questions/22_sigmoid-activation-function-understanding/tinygrad/solution.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def sigmoid_tg(z: float) -> float:
"""
Compute the sigmoid activation function using tinygrad.
diff --git a/questions/22_sigmoid-activation-function-understanding/tinygrad/starter_code.py b/questions/22_sigmoid-activation-function-understanding/tinygrad/starter_code.py
index d7bda8d1..f1e3e90e 100644
--- a/questions/22_sigmoid-activation-function-understanding/tinygrad/starter_code.py
+++ b/questions/22_sigmoid-activation-function-understanding/tinygrad/starter_code.py
@@ -1,5 +1,3 @@
-from tinygrad.tensor import Tensor
-
def sigmoid_tg(z: float) -> float:
"""
Compute the sigmoid activation function using tinygrad.
diff --git a/questions/23_softmax-activation-function-implementation/pytorch/solution.py b/questions/23_softmax-activation-function-implementation/pytorch/solution.py
index c67de0f3..09141274 100644
--- a/questions/23_softmax-activation-function-implementation/pytorch/solution.py
+++ b/questions/23_softmax-activation-function-implementation/pytorch/solution.py
@@ -1,6 +1,7 @@
import torch
import torch.nn.functional as F
+
def softmax(scores: list[float]) -> list[float]:
"""
Compute the softmax activation function using PyTorch's built-in API.
diff --git a/questions/23_softmax-activation-function-implementation/pytorch/starter_code.py b/questions/23_softmax-activation-function-implementation/pytorch/starter_code.py
index 92c9f722..1925a07b 100644
--- a/questions/23_softmax-activation-function-implementation/pytorch/starter_code.py
+++ b/questions/23_softmax-activation-function-implementation/pytorch/starter_code.py
@@ -1,6 +1,3 @@
-import torch
-import torch.nn.functional as F
-
def softmax(scores: list[float]) -> list[float]:
"""
Compute the softmax activation function using PyTorch's built-in API.
diff --git a/questions/23_softmax-activation-function-implementation/solution.py b/questions/23_softmax-activation-function-implementation/solution.py
index e715515f..c0f0b2af 100644
--- a/questions/23_softmax-activation-function-implementation/solution.py
+++ b/questions/23_softmax-activation-function-implementation/solution.py
@@ -1,5 +1,6 @@
-
import math
+
+
def softmax(scores: list[float]) -> list[float]:
exp_scores = [math.exp(score) for score in scores]
sum_exp_scores = sum(exp_scores)
diff --git a/questions/23_softmax-activation-function-implementation/starter_code.py b/questions/23_softmax-activation-function-implementation/starter_code.py
index e4daa5cb..c8234764 100644
--- a/questions/23_softmax-activation-function-implementation/starter_code.py
+++ b/questions/23_softmax-activation-function-implementation/starter_code.py
@@ -1,5 +1,3 @@
-import math
-
def softmax(scores: list[float]) -> list[float]:
- # Your code here
- return probabilities
+ # Your code here
+ return probabilities
diff --git a/questions/23_softmax-activation-function-implementation/tinygrad/solution.py b/questions/23_softmax-activation-function-implementation/tinygrad/solution.py
index 28d20dd0..13bedf12 100644
--- a/questions/23_softmax-activation-function-implementation/tinygrad/solution.py
+++ b/questions/23_softmax-activation-function-implementation/tinygrad/solution.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def softmax_tg(scores: list[float]) -> list[float]:
"""
Compute the softmax activation function using tinygrad.
diff --git a/questions/23_softmax-activation-function-implementation/tinygrad/starter_code.py b/questions/23_softmax-activation-function-implementation/tinygrad/starter_code.py
index c393b378..3f6c89ca 100644
--- a/questions/23_softmax-activation-function-implementation/tinygrad/starter_code.py
+++ b/questions/23_softmax-activation-function-implementation/tinygrad/starter_code.py
@@ -1,5 +1,3 @@
-from tinygrad.tensor import Tensor
-
def softmax_tg(scores: list[float]) -> list[float]:
"""
Compute the softmax activation function using tinygrad.
diff --git a/questions/24_single-neuron/pytorch/solution.py b/questions/24_single-neuron/pytorch/solution.py
index e107e0a4..b06d42c6 100644
--- a/questions/24_single-neuron/pytorch/solution.py
+++ b/questions/24_single-neuron/pytorch/solution.py
@@ -2,11 +2,9 @@
import torch.nn.functional as F
from typing import List, Tuple
+
def single_neuron_model(
- features: List[List[float]],
- labels: List[float],
- weights: List[float],
- bias: float
+ features: List[List[float]], labels: List[float], weights: List[float], bias: float
) -> Tuple[List[float], float]:
X = torch.tensor(features, dtype=torch.float)
y = torch.tensor(labels, dtype=torch.float)
@@ -17,6 +15,6 @@ def single_neuron_model(
probs_t = torch.sigmoid(logits)
probs = probs_t.tolist()
- mse = F.mse_loss(probs_t, y, reduction='mean').item()
+ mse = F.mse_loss(probs_t, y, reduction="mean").item()
return probs, mse
diff --git a/questions/24_single-neuron/pytorch/starter_code.py b/questions/24_single-neuron/pytorch/starter_code.py
index 6949c284..260a445a 100644
--- a/questions/24_single-neuron/pytorch/starter_code.py
+++ b/questions/24_single-neuron/pytorch/starter_code.py
@@ -1,12 +1,8 @@
-import torch
-import torch.nn.functional as F
from typing import List, Tuple
+
def single_neuron_model(
- features: List[List[float]],
- labels: List[float],
- weights: List[float],
- bias: float
+ features: List[List[float]], labels: List[float], weights: List[float], bias: float
) -> Tuple[List[float], float]:
"""
Compute output probabilities and MSE for a single neuron.
diff --git a/questions/24_single-neuron/solution.py b/questions/24_single-neuron/solution.py
index 273e9e03..4b502700 100644
--- a/questions/24_single-neuron/solution.py
+++ b/questions/24_single-neuron/solution.py
@@ -1,13 +1,19 @@
-
import math
+
+
def single_neuron_model(features, labels, weights, bias):
probabilities = []
for feature_vector in features:
- z = sum(weight * feature for weight, feature in zip(weights, feature_vector)) + bias
+ z = (
+ sum(weight * feature for weight, feature in zip(weights, feature_vector))
+ + bias
+ )
prob = 1 / (1 + math.exp(-z))
probabilities.append(round(prob, 4))
-
- mse = sum((prob - label) ** 2 for prob, label in zip(probabilities, labels)) / len(labels)
+
+ mse = sum((prob - label) ** 2 for prob, label in zip(probabilities, labels)) / len(
+ labels
+ )
mse = round(mse, 4)
-
+
return probabilities, mse
diff --git a/questions/24_single-neuron/starter_code.py b/questions/24_single-neuron/starter_code.py
index 87219501..15e5cc8c 100644
--- a/questions/24_single-neuron/starter_code.py
+++ b/questions/24_single-neuron/starter_code.py
@@ -1,5 +1,5 @@
-import math
-
-def single_neuron_model(features: list[list[float]], labels: list[int], weights: list[float], bias: float) -> (list[float], float):
- # Your code here
- return probabilities, mse
+def single_neuron_model(
+ features: list[list[float]], labels: list[int], weights: list[float], bias: float
+) -> (list[float], float):
+ # Your code here
+ return probabilities, mse
diff --git a/questions/24_single-neuron/tinygrad/solution.py b/questions/24_single-neuron/tinygrad/solution.py
index e8c00bd8..c440ca02 100644
--- a/questions/24_single-neuron/tinygrad/solution.py
+++ b/questions/24_single-neuron/tinygrad/solution.py
@@ -1,11 +1,9 @@
from tinygrad.tensor import Tensor
from typing import List, Tuple
+
def single_neuron_model_tg(
- features: List[List[float]],
- labels: List[float],
- weights: List[float],
- bias: float
+ features: List[List[float]], labels: List[float], weights: List[float], bias: float
) -> Tuple[List[float], float]:
X = Tensor(features)
w = Tensor(weights)
@@ -16,7 +14,7 @@ def single_neuron_model_tg(
p = z.sigmoid().numpy().tolist()
probs.append(round(p, 4))
- mse = sum((p - y)**2 for p, y in zip(probs, labels)) / len(labels)
+ mse = sum((p - y) ** 2 for p, y in zip(probs, labels)) / len(labels)
mse = round(mse, 4)
return probs, mse
diff --git a/questions/24_single-neuron/tinygrad/starter_code.py b/questions/24_single-neuron/tinygrad/starter_code.py
index 5dd4e8c4..8a8722dd 100644
--- a/questions/24_single-neuron/tinygrad/starter_code.py
+++ b/questions/24_single-neuron/tinygrad/starter_code.py
@@ -1,11 +1,8 @@
-from tinygrad.tensor import Tensor
from typing import List, Tuple
+
def single_neuron_model_tg(
- features: List[List[float]],
- labels: List[float],
- weights: List[float],
- bias: float
+ features: List[List[float]], labels: List[float], weights: List[float], bias: float
) -> Tuple[List[float], float]:
"""
Compute output probabilities and MSE for a single neuron using tinygrad.
diff --git a/questions/25_single-neuron-with-backpropagation/pytorch/solution.py b/questions/25_single-neuron-with-backpropagation/pytorch/solution.py
index 960ad81b..1292b492 100644
--- a/questions/25_single-neuron-with-backpropagation/pytorch/solution.py
+++ b/questions/25_single-neuron-with-backpropagation/pytorch/solution.py
@@ -4,16 +4,15 @@
def train_neuron(
features: Union[List[List[float]], torch.Tensor],
- labels: Union[List[float], torch.Tensor],
+ labels: Union[List[float], torch.Tensor],
initial_weights: Union[List[float], torch.Tensor],
initial_bias: float,
learning_rate: float,
- epochs: int
+ epochs: int,
) -> Tuple[List[float], float, List[float]]:
-
# Ensure tensors
X = torch.as_tensor(features, dtype=torch.float)
- y = torch.as_tensor(labels, dtype=torch.float)
+ y = torch.as_tensor(labels, dtype=torch.float)
w = torch.as_tensor(initial_weights, dtype=torch.float)
b = torch.tensor(initial_bias, dtype=torch.float)
@@ -22,9 +21,9 @@ def train_neuron(
for _ in range(epochs):
# Forward
- z = X @ w + b # (n,)
- preds = torch.sigmoid(z) # (n,)
- errors = preds - y # (n,)
+ z = X @ w + b # (n,)
+ preds = torch.sigmoid(z) # (n,)
+ errors = preds - y # (n,)
# MSE
mse = torch.mean(errors**2).item()
@@ -32,10 +31,10 @@ def train_neuron(
# Manual gradients (chain-rule): dMSE/dz = 2/n * (preds-y) * σ'(z)
sigma_prime = preds * (1 - preds)
- delta = (2.0 / n) * errors * sigma_prime # (n,)
+ delta = (2.0 / n) * errors * sigma_prime # (n,)
- grad_w = X.t() @ delta # (f,)
- grad_b = delta.sum() # scalar
+ grad_w = X.t() @ delta # (f,)
+ grad_b = delta.sum() # scalar
# Parameter update (gradient descent)
w -= learning_rate * grad_w
@@ -43,5 +42,5 @@ def train_neuron(
# Round final params for return
updated_weights = [round(val, 4) for val in w.tolist()]
- updated_bias = round(b.item(), 4)
+ updated_bias = round(b.item(), 4)
return updated_weights, updated_bias, mse_values
diff --git a/questions/25_single-neuron-with-backpropagation/pytorch/starter_code.py b/questions/25_single-neuron-with-backpropagation/pytorch/starter_code.py
index 91dffc29..9b0b0d93 100644
--- a/questions/25_single-neuron-with-backpropagation/pytorch/starter_code.py
+++ b/questions/25_single-neuron-with-backpropagation/pytorch/starter_code.py
@@ -4,11 +4,11 @@
def train_neuron(
features: Union[List[List[float]], torch.Tensor],
- labels: Union[List[float], torch.Tensor],
+ labels: Union[List[float], torch.Tensor],
initial_weights: Union[List[float], torch.Tensor],
initial_bias: float,
learning_rate: float,
- epochs: int
+ epochs: int,
) -> Tuple[List[float], float, List[float]]:
"""
Train a single neuron (sigmoid activation) with mean-squared-error loss.
diff --git a/questions/25_single-neuron-with-backpropagation/solution.py b/questions/25_single-neuron-with-backpropagation/solution.py
index b4d38e8e..f1fe9a65 100644
--- a/questions/25_single-neuron-with-backpropagation/solution.py
+++ b/questions/25_single-neuron-with-backpropagation/solution.py
@@ -1,10 +1,13 @@
-
import numpy as np
+
def sigmoid(x):
return 1 / (1 + np.exp(-x))
-def train_neuron(features, labels, initial_weights, initial_bias, learning_rate, epochs):
+
+def train_neuron(
+ features, labels, initial_weights, initial_bias, learning_rate, epochs
+):
weights = np.array(initial_weights)
bias = initial_bias
features = np.array(features)
@@ -14,15 +17,19 @@ def train_neuron(features, labels, initial_weights, initial_bias, learning_rate,
for _ in range(epochs):
z = np.dot(features, weights) + bias
predictions = sigmoid(z)
-
+
mse = np.mean((predictions - labels) ** 2)
mse_values.append(round(mse, 4))
# Gradient calculation for weights and bias
errors = predictions - labels
- weight_gradients = (2/len(labels)) * np.dot(features.T, errors * predictions * (1 - predictions))
- bias_gradient = (2/len(labels)) * np.sum(errors * predictions * (1 - predictions))
-
+ weight_gradients = (2 / len(labels)) * np.dot(
+ features.T, errors * predictions * (1 - predictions)
+ )
+ bias_gradient = (2 / len(labels)) * np.sum(
+ errors * predictions * (1 - predictions)
+ )
+
# Update weights and bias
weights -= learning_rate * weight_gradients
bias -= learning_rate * bias_gradient
diff --git a/questions/25_single-neuron-with-backpropagation/starter_code.py b/questions/25_single-neuron-with-backpropagation/starter_code.py
index a92792bf..6d1f896e 100644
--- a/questions/25_single-neuron-with-backpropagation/starter_code.py
+++ b/questions/25_single-neuron-with-backpropagation/starter_code.py
@@ -1,4 +1,13 @@
import numpy as np
-def train_neuron(features: np.ndarray, labels: np.ndarray, initial_weights: np.ndarray, initial_bias: float, learning_rate: float, epochs: int) -> (np.ndarray, float, list[float]):
- # Your code here
- return updated_weights, updated_bias, mse_values
+
+
+def train_neuron(
+ features: np.ndarray,
+ labels: np.ndarray,
+ initial_weights: np.ndarray,
+ initial_bias: float,
+ learning_rate: float,
+ epochs: int,
+) -> (np.ndarray, float, list[float]):
+ # Your code here
+ return updated_weights, updated_bias, mse_values
diff --git a/questions/25_single-neuron-with-backpropagation/tinygrad/solution.py b/questions/25_single-neuron-with-backpropagation/tinygrad/solution.py
index 7ec48fff..507a904c 100644
--- a/questions/25_single-neuron-with-backpropagation/tinygrad/solution.py
+++ b/questions/25_single-neuron-with-backpropagation/tinygrad/solution.py
@@ -4,11 +4,11 @@
def train_neuron_tg(
features: List[List[float]],
- labels: List[float],
+ labels: List[float],
initial_weights: List[float],
initial_bias: float,
learning_rate: float,
- epochs: int
+ epochs: int,
) -> Tuple[List[float], float, List[float]]:
X = Tensor(features)
y = Tensor(labels).reshape(len(labels), 1)
@@ -19,9 +19,9 @@ def train_neuron_tg(
n = len(labels)
for _ in range(epochs):
- z = X.matmul(w) + b # (n,1)
- preds = z.sigmoid() # (n,1)
- errors = preds - y # (n,1)
+ z = X.matmul(w) + b # (n,1)
+ preds = z.sigmoid() # (n,1)
+ errors = preds - y # (n,1)
mse = float(((errors**2).mean()).numpy())
mse_values.append(round(mse, 4))
@@ -36,5 +36,5 @@ def train_neuron_tg(
b -= Tensor(learning_rate) * grad_b
updated_weights = [round(val, 4) for val in w.numpy().flatten().tolist()]
- updated_bias = round(float(b.numpy()), 4)
+ updated_bias = round(float(b.numpy()), 4)
return updated_weights, updated_bias, mse_values
diff --git a/questions/25_single-neuron-with-backpropagation/tinygrad/starter_code.py b/questions/25_single-neuron-with-backpropagation/tinygrad/starter_code.py
index 53b1796c..f04cb5df 100644
--- a/questions/25_single-neuron-with-backpropagation/tinygrad/starter_code.py
+++ b/questions/25_single-neuron-with-backpropagation/tinygrad/starter_code.py
@@ -1,14 +1,13 @@
-from tinygrad.tensor import Tensor
from typing import List, Tuple
def train_neuron_tg(
features: List[List[float]],
- labels: List[float],
+ labels: List[float],
initial_weights: List[float],
initial_bias: float,
learning_rate: float,
- epochs: int
+ epochs: int,
) -> Tuple[List[float], float, List[float]]:
"""
Tinygrad version — same contract as PyTorch implementation.
diff --git a/questions/26_implementing-basic-autograd-operations/pytorch/solution.py b/questions/26_implementing-basic-autograd-operations/pytorch/solution.py
index 6ebd0a1b..991141f2 100644
--- a/questions/26_implementing-basic-autograd-operations/pytorch/solution.py
+++ b/questions/26_implementing-basic-autograd-operations/pytorch/solution.py
@@ -1,10 +1,15 @@
import torch
+
class Value:
"""Scalar autograd value powered by PyTorch tensors."""
def __init__(self, data, _tensor=None):
- self._t = _tensor if _tensor is not None else torch.tensor(float(data), requires_grad=True)
+ self._t = (
+ _tensor
+ if _tensor is not None
+ else torch.tensor(float(data), requires_grad=True)
+ )
self._t.retain_grad()
# ----- helpers -----
@@ -20,6 +25,7 @@ def grad(self):
def __repr__(self):
def fmt(x):
return int(x) if float(x).is_integer() else round(x, 4)
+
return f"Value(data={fmt(self.data)}, grad={fmt(self.grad)})"
def _wrap(self, other):
diff --git a/questions/26_implementing-basic-autograd-operations/pytorch/starter_code.py b/questions/26_implementing-basic-autograd-operations/pytorch/starter_code.py
index c98e2a0c..5ece49ff 100644
--- a/questions/26_implementing-basic-autograd-operations/pytorch/starter_code.py
+++ b/questions/26_implementing-basic-autograd-operations/pytorch/starter_code.py
@@ -1,11 +1,16 @@
import torch
+
class Value:
"""A tiny scalar wrapper that delegates all gradient work to PyTorch autograd."""
def __init__(self, data, _tensor=None):
# leaf node: create fresh tensor with grad; internal node: reuse tensor
- self._t = _tensor if _tensor is not None else torch.tensor(float(data), requires_grad=True)
+ self._t = (
+ _tensor
+ if _tensor is not None
+ else torch.tensor(float(data), requires_grad=True)
+ )
# make sure every Tensor (leaf or not) keeps its grad for printing
self._t.retain_grad()
@@ -22,6 +27,7 @@ def grad(self):
def __repr__(self):
def fmt(x):
return int(x) if float(x).is_integer() else round(x, 4)
+
return f"Value(data={fmt(self.data)}, grad={fmt(self.grad)})"
# ensure rhs is Value
diff --git a/questions/26_implementing-basic-autograd-operations/solution.py b/questions/26_implementing-basic-autograd-operations/solution.py
index fe158bef..61aab2ff 100644
--- a/questions/26_implementing-basic-autograd-operations/solution.py
+++ b/questions/26_implementing-basic-autograd-operations/solution.py
@@ -1,6 +1,5 @@
-
class Value:
- def __init__(self, data, _children=(), _op=''):
+ def __init__(self, data, _children=(), _op=""):
self.data = data
self.grad = 0
self._backward = lambda: None
@@ -9,41 +8,50 @@ def __init__(self, data, _children=(), _op=''):
def __add__(self, other):
other = other if isinstance(other, Value) else Value(other)
- out = Value(self.data + other.data, (self, other), '+')
+ out = Value(self.data + other.data, (self, other), "+")
+
def _backward():
self.grad += out.grad
other.grad += out.grad
+
out._backward = _backward
return out
def __mul__(self, other):
other = other if isinstance(other, Value) else Value(other)
- out = Value(self.data * other.data, (self, other), '*')
+ out = Value(self.data * other.data, (self, other), "*")
+
def _backward():
self.grad += other.data * out.grad
other.grad += self.data * out.grad
+
out._backward = _backward
return out
def relu(self):
- out = Value(0 if self.data < 0 else self.data, (self,), 'ReLU')
+ out = Value(0 if self.data < 0 else self.data, (self,), "ReLU")
+
def _backward():
self.grad += (out.data > 0) * out.grad
+
out._backward = _backward
return out
def backward(self):
topo = []
visited = set()
+
def build_topo(v):
if v not in visited:
visited.add(v)
for child in v._prev:
build_topo(child)
topo.append(v)
+
build_topo(self)
self.grad = 1
for v in reversed(topo):
v._backward()
+
def __repr__(self):
return f"Value(data={self.data}, grad={self.grad})"
diff --git a/questions/26_implementing-basic-autograd-operations/starter_code.py b/questions/26_implementing-basic-autograd-operations/starter_code.py
index 5c002e14..8e844a11 100644
--- a/questions/26_implementing-basic-autograd-operations/starter_code.py
+++ b/questions/26_implementing-basic-autograd-operations/starter_code.py
@@ -1,25 +1,26 @@
class Value:
- def __init__(self, data, _children=(), _op=''):
- self.data = data
- self.grad = 0
- self._backward = lambda: None
- self._prev = set(_children)
- self._op = _op
- def __repr__(self):
- return f"Value(data={self.data}, grad={self.grad})"
+ def __init__(self, data, _children=(), _op=""):
+ self.data = data
+ self.grad = 0
+ self._backward = lambda: None
+ self._prev = set(_children)
+ self._op = _op
- def __add__(self, other):
- # Implement addition here
- pass
+ def __repr__(self):
+ return f"Value(data={self.data}, grad={self.grad})"
- def __mul__(self, other):
- # Implement multiplication here
- pass
+ def __add__(self, other):
+ # Implement addition here
+ pass
- def relu(self):
- # Implement ReLU here
- pass
+ def __mul__(self, other):
+ # Implement multiplication here
+ pass
- def backward(self):
- # Implement backward pass here
- pass
+ def relu(self):
+ # Implement ReLU here
+ pass
+
+ def backward(self):
+ # Implement backward pass here
+ pass
diff --git a/questions/26_implementing-basic-autograd-operations/tinygrad/solution.py b/questions/26_implementing-basic-autograd-operations/tinygrad/solution.py
index 2ecbecc3..322d305f 100644
--- a/questions/26_implementing-basic-autograd-operations/tinygrad/solution.py
+++ b/questions/26_implementing-basic-autograd-operations/tinygrad/solution.py
@@ -1,8 +1,11 @@
from tinygrad.tensor import Tensor
+
class Value:
def __init__(self, data, _tensor=None):
- self._t = _tensor if _tensor is not None else Tensor(float(data), requires_grad=True)
+ self._t = (
+ _tensor if _tensor is not None else Tensor(float(data), requires_grad=True)
+ )
@property
def data(self):
@@ -16,6 +19,7 @@ def grad(self):
def __repr__(self):
def fmt(x):
return int(x) if float(x).is_integer() else round(x, 4)
+
return f"Value(data={fmt(self.data)}, grad={fmt(self.grad)})"
def _wrap(self, other):
diff --git a/questions/26_implementing-basic-autograd-operations/tinygrad/starter_code.py b/questions/26_implementing-basic-autograd-operations/tinygrad/starter_code.py
index e5b75577..97d5b3d7 100644
--- a/questions/26_implementing-basic-autograd-operations/tinygrad/starter_code.py
+++ b/questions/26_implementing-basic-autograd-operations/tinygrad/starter_code.py
@@ -1,10 +1,13 @@
from tinygrad.tensor import Tensor
+
class Value:
"""Same idea, but using tinygrad’s automatic differentiation."""
def __init__(self, data, _tensor=None):
- self._t = _tensor if _tensor is not None else Tensor(float(data), requires_grad=True)
+ self._t = (
+ _tensor if _tensor is not None else Tensor(float(data), requires_grad=True)
+ )
@property
def data(self):
@@ -18,6 +21,7 @@ def grad(self):
def __repr__(self):
def fmt(x):
return int(x) if float(x).is_integer() else round(x, 4)
+
return f"Value(data={fmt(self.data)}, grad={fmt(self.grad)})"
def _wrap(self, other):
diff --git a/questions/27_transformation-matrix-from-basis-b-to-c/solution.py b/questions/27_transformation-matrix-from-basis-b-to-c/solution.py
index 3ed4fc56..b7ebe3c9 100644
--- a/questions/27_transformation-matrix-from-basis-b-to-c/solution.py
+++ b/questions/27_transformation-matrix-from-basis-b-to-c/solution.py
@@ -1,4 +1,6 @@
import numpy as np
+
+
def transform_basis(B, C):
C = np.array(C)
B = np.array(B)
diff --git a/questions/27_transformation-matrix-from-basis-b-to-c/starter_code.py b/questions/27_transformation-matrix-from-basis-b-to-c/starter_code.py
index fbca1c18..c51008d4 100644
--- a/questions/27_transformation-matrix-from-basis-b-to-c/starter_code.py
+++ b/questions/27_transformation-matrix-from-basis-b-to-c/starter_code.py
@@ -1,2 +1,2 @@
def transform_basis(B: list[list[int]], C: list[list[int]]) -> list[list[float]]:
- return P
+ return P
diff --git a/questions/28_svd-of-a-2x2-matrix-using-eigen-values-vectors/solution.py b/questions/28_svd-of-a-2x2-matrix-using-eigen-values-vectors/solution.py
index afc802ae..c1114c66 100644
--- a/questions/28_svd-of-a-2x2-matrix-using-eigen-values-vectors/solution.py
+++ b/questions/28_svd-of-a-2x2-matrix-using-eigen-values-vectors/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def svd_2x2(A: np.ndarray) -> tuple:
y1, x1 = (A[1, 0] + A[0, 1]), (A[0, 0] - A[1, 1])
y2, x2 = (A[1, 0] - A[0, 1]), (A[0, 0] + A[1, 1])
@@ -23,4 +24,3 @@ def svd_2x2(A: np.ndarray) -> tuple:
V = np.diag(1.0 / s) @ U.T @ A
return U, s, V
-
diff --git a/questions/28_svd-of-a-2x2-matrix-using-eigen-values-vectors/starter_code.py b/questions/28_svd-of-a-2x2-matrix-using-eigen-values-vectors/starter_code.py
index cc445909..84995f6d 100644
--- a/questions/28_svd-of-a-2x2-matrix-using-eigen-values-vectors/starter_code.py
+++ b/questions/28_svd-of-a-2x2-matrix-using-eigen-values-vectors/starter_code.py
@@ -1,5 +1,6 @@
import numpy as np
+
def svd_2x2(A: np.ndarray) -> tuple:
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/29_random-shuffle-of-dataset/solution.py b/questions/29_random-shuffle-of-dataset/solution.py
index f9b91d92..c88a1c5e 100644
--- a/questions/29_random-shuffle-of-dataset/solution.py
+++ b/questions/29_random-shuffle-of-dataset/solution.py
@@ -1,9 +1,9 @@
import numpy as np
+
def shuffle_data(X, y, seed=None):
if seed:
np.random.seed(seed)
idx = np.arange(X.shape[0])
np.random.shuffle(idx)
return X[idx], y[idx]
-
diff --git a/questions/29_random-shuffle-of-dataset/starter_code.py b/questions/29_random-shuffle-of-dataset/starter_code.py
index ca6942c5..aab13a2d 100644
--- a/questions/29_random-shuffle-of-dataset/starter_code.py
+++ b/questions/29_random-shuffle-of-dataset/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def shuffle_data(X, y, seed=None):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/2_transpose-of-a-matrix/pytorch/solution.py b/questions/2_transpose-of-a-matrix/pytorch/solution.py
index 34643c08..287953f8 100644
--- a/questions/2_transpose-of-a-matrix/pytorch/solution.py
+++ b/questions/2_transpose-of-a-matrix/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def transpose_matrix(a) -> torch.Tensor:
"""
Transpose a 2D matrix `a` using PyTorch.
diff --git a/questions/2_transpose-of-a-matrix/pytorch/starter_code.py b/questions/2_transpose-of-a-matrix/pytorch/starter_code.py
index 1c648f73..3b4326d0 100644
--- a/questions/2_transpose-of-a-matrix/pytorch/starter_code.py
+++ b/questions/2_transpose-of-a-matrix/pytorch/starter_code.py
@@ -1,11 +1,12 @@
import torch
+
def transpose_matrix(a) -> torch.Tensor:
"""
Transpose a 2D matrix `a` using PyTorch.
Inputs can be Python lists, NumPy arrays, or torch Tensors.
Returns a transposed tensor.
"""
- a_t = torch.as_tensor(a)
+ torch.as_tensor(a)
# Your implementation here
pass
diff --git a/questions/2_transpose-of-a-matrix/solution.py b/questions/2_transpose-of-a-matrix/solution.py
index 10158c7e..51092ddb 100644
--- a/questions/2_transpose-of-a-matrix/solution.py
+++ b/questions/2_transpose-of-a-matrix/solution.py
@@ -1,2 +1,2 @@
-def transpose_matrix(a: list[list[int|float]]) -> list[list[int|float]]:
+def transpose_matrix(a: list[list[int | float]]) -> list[list[int | float]]:
return [list(i) for i in zip(*a)]
diff --git a/questions/2_transpose-of-a-matrix/starter_code.py b/questions/2_transpose-of-a-matrix/starter_code.py
index a247d5ba..24aa0400 100644
--- a/questions/2_transpose-of-a-matrix/starter_code.py
+++ b/questions/2_transpose-of-a-matrix/starter_code.py
@@ -1,2 +1,2 @@
-def transpose_matrix(a: list[list[int|float]]) -> list[list[int|float]]:
- return b
+def transpose_matrix(a: list[list[int | float]]) -> list[list[int | float]]:
+ return b
diff --git a/questions/2_transpose-of-a-matrix/tinygrad/solution.py b/questions/2_transpose-of-a-matrix/tinygrad/solution.py
index 52be5f2d..07f3115d 100644
--- a/questions/2_transpose-of-a-matrix/tinygrad/solution.py
+++ b/questions/2_transpose-of-a-matrix/tinygrad/solution.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def transpose_matrix_tg(a) -> Tensor:
"""
Transpose a 2D matrix `a` using tinygrad.
diff --git a/questions/30_batch-iterator-for-dataset/solution.py b/questions/30_batch-iterator-for-dataset/solution.py
index b4dee373..37355502 100644
--- a/questions/30_batch-iterator-for-dataset/solution.py
+++ b/questions/30_batch-iterator-for-dataset/solution.py
@@ -1,13 +1,13 @@
import numpy as np
+
def batch_iterator(X, y=None, batch_size=64):
n_samples = X.shape[0]
batches = []
for i in np.arange(0, n_samples, batch_size):
- begin, end = i, min(i+batch_size, n_samples)
+ begin, end = i, min(i + batch_size, n_samples)
if y is not None:
batches.append([X[begin:end], y[begin:end]])
else:
- batches.append( X[begin:end])
+ batches.append(X[begin:end])
return batches
-
diff --git a/questions/30_batch-iterator-for-dataset/starter_code.py b/questions/30_batch-iterator-for-dataset/starter_code.py
index 68d236ca..447bed19 100644
--- a/questions/30_batch-iterator-for-dataset/starter_code.py
+++ b/questions/30_batch-iterator-for-dataset/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def batch_iterator(X, y=None, batch_size=64):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/31_divide-dataset-based-on-feature-threshold/solution.py b/questions/31_divide-dataset-based-on-feature-threshold/solution.py
index 458a2c4f..28f3ec0b 100644
--- a/questions/31_divide-dataset-based-on-feature-threshold/solution.py
+++ b/questions/31_divide-dataset-based-on-feature-threshold/solution.py
@@ -1,14 +1,17 @@
import numpy as np
+
def divide_on_feature(X, feature_i, threshold):
# Define the split function based on the threshold type
split_func = None
if isinstance(threshold, int) or isinstance(threshold, float):
# For numeric threshold, check if feature value is greater than or equal to the threshold
- split_func = lambda sample: sample[feature_i] >= threshold
+ def split_func(sample):
+ return sample[feature_i] >= threshold
else:
# For non-numeric threshold, check if feature value is equal to the threshold
- split_func = lambda sample: sample[feature_i] == threshold
+ def split_func(sample):
+ return sample[feature_i] == threshold
# Create two subsets based on the split function
X_1 = np.array([sample for sample in X if split_func(sample)])
@@ -16,4 +19,3 @@ def divide_on_feature(X, feature_i, threshold):
# Return the two subsets
return [X_1, X_2]
-
diff --git a/questions/31_divide-dataset-based-on-feature-threshold/starter_code.py b/questions/31_divide-dataset-based-on-feature-threshold/starter_code.py
index d7118c47..0f8c7485 100644
--- a/questions/31_divide-dataset-based-on-feature-threshold/starter_code.py
+++ b/questions/31_divide-dataset-based-on-feature-threshold/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def divide_on_feature(X, feature_i, threshold):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/32_generate-sorted-polynomial-features/solution.py b/questions/32_generate-sorted-polynomial-features/solution.py
index 66551401..eae33931 100644
--- a/questions/32_generate-sorted-polynomial-features/solution.py
+++ b/questions/32_generate-sorted-polynomial-features/solution.py
@@ -1,12 +1,16 @@
import numpy as np
from itertools import combinations_with_replacement
+
def polynomial_features(X, degree):
n_samples, n_features = X.shape
# All index combinations for powers 0 … degree (constant term included)
- combs = [c for d in range(degree + 1)
- for c in combinations_with_replacement(range(n_features), d)]
+ combs = [
+ c
+ for d in range(degree + 1)
+ for c in combinations_with_replacement(range(n_features), d)
+ ]
# Compute raw polynomial terms
X_poly = np.empty((n_samples, len(combs)))
diff --git a/questions/32_generate-sorted-polynomial-features/starter_code.py b/questions/32_generate-sorted-polynomial-features/starter_code.py
index 41a4c312..a4845a49 100644
--- a/questions/32_generate-sorted-polynomial-features/starter_code.py
+++ b/questions/32_generate-sorted-polynomial-features/starter_code.py
@@ -1,6 +1,3 @@
-import numpy as np
-from itertools import combinations_with_replacement
-
def polynomial_features(X, degree):
# ✏️ Your code here
pass
diff --git a/questions/33_generate-random-subsets-of-a-dataset/solution.py b/questions/33_generate-random-subsets-of-a-dataset/solution.py
index 73a80d2e..850c15de 100644
--- a/questions/33_generate-random-subsets-of-a-dataset/solution.py
+++ b/questions/33_generate-random-subsets-of-a-dataset/solution.py
@@ -1,12 +1,17 @@
import numpy as np
+
def get_random_subsets(X, y, n_subsets, replacements=True, seed=42):
np.random.seed(seed)
n, m = X.shape
-
+
subset_size = n if replacements else n // 2
- idx = np.array([np.random.choice(n, subset_size, replace=replacements) for _ in range(n_subsets)])
+ idx = np.array(
+ [
+ np.random.choice(n, subset_size, replace=replacements)
+ for _ in range(n_subsets)
+ ]
+ )
# convert all ndarrays to lists
return [(X[idx][i].tolist(), y[idx][i].tolist()) for i in range(n_subsets)]
-
diff --git a/questions/33_generate-random-subsets-of-a-dataset/starter_code.py b/questions/33_generate-random-subsets-of-a-dataset/starter_code.py
index fa59e9f1..015e28ce 100644
--- a/questions/33_generate-random-subsets-of-a-dataset/starter_code.py
+++ b/questions/33_generate-random-subsets-of-a-dataset/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def get_random_subsets(X, y, n_subsets, replacements=True, seed=42):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/34_one-hot-encoding-of-nominal-values/solution.py b/questions/34_one-hot-encoding-of-nominal-values/solution.py
index 7fbb679d..828cac34 100644
--- a/questions/34_one-hot-encoding-of-nominal-values/solution.py
+++ b/questions/34_one-hot-encoding-of-nominal-values/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def to_categorical(x, n_col=None):
# One-hot encoding of nominal values
# If n_col is not provided, determine the number of columns from the input array
@@ -10,4 +11,3 @@ def to_categorical(x, n_col=None):
# Set the appropriate elements to 1
one_hot[np.arange(x.shape[0]), x] = 1
return one_hot
-
diff --git a/questions/34_one-hot-encoding-of-nominal-values/starter_code.py b/questions/34_one-hot-encoding-of-nominal-values/starter_code.py
index f510543c..92b93e5a 100644
--- a/questions/34_one-hot-encoding-of-nominal-values/starter_code.py
+++ b/questions/34_one-hot-encoding-of-nominal-values/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def to_categorical(x, n_col=None):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/35_convert-vector-to-diagonal-matrix/solution.py b/questions/35_convert-vector-to-diagonal-matrix/solution.py
index 6d70ed68..d6ab720a 100644
--- a/questions/35_convert-vector-to-diagonal-matrix/solution.py
+++ b/questions/35_convert-vector-to-diagonal-matrix/solution.py
@@ -1,6 +1,6 @@
import numpy as np
+
def make_diagonal(x):
identity_matrix = np.identity(np.size(x))
- return (identity_matrix*x)
-
+ return identity_matrix * x
diff --git a/questions/35_convert-vector-to-diagonal-matrix/starter_code.py b/questions/35_convert-vector-to-diagonal-matrix/starter_code.py
index 2d840a10..436e1382 100644
--- a/questions/35_convert-vector-to-diagonal-matrix/starter_code.py
+++ b/questions/35_convert-vector-to-diagonal-matrix/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def make_diagonal(x):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/36_calculate-accuracy-score/solution.py b/questions/36_calculate-accuracy-score/solution.py
index 590b51e5..24ec0344 100644
--- a/questions/36_calculate-accuracy-score/solution.py
+++ b/questions/36_calculate-accuracy-score/solution.py
@@ -1,6 +1,6 @@
import numpy as np
+
def accuracy_score(y_true, y_pred):
accuracy = np.sum(y_true == y_pred, axis=0) / len(y_true)
return accuracy
-
diff --git a/questions/36_calculate-accuracy-score/starter_code.py b/questions/36_calculate-accuracy-score/starter_code.py
index e34f69e4..7a2dbfb3 100644
--- a/questions/36_calculate-accuracy-score/starter_code.py
+++ b/questions/36_calculate-accuracy-score/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def accuracy_score(y_true, y_pred):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/37_calculate-correlation-matrix/solution.py b/questions/37_calculate-correlation-matrix/solution.py
index 60334207..6b9784e0 100644
--- a/questions/37_calculate-correlation-matrix/solution.py
+++ b/questions/37_calculate-correlation-matrix/solution.py
@@ -1,10 +1,11 @@
import numpy as np
+
def calculate_correlation_matrix(X, Y=None):
# Helper function to calculate standard deviation
def calculate_std_dev(A):
- return np.sqrt(np.mean((A - A.mean(0))**2, axis=0))
-
+ return np.sqrt(np.mean((A - A.mean(0)) ** 2, axis=0))
+
if Y is None:
Y = X
n_samples = np.shape(X)[0]
@@ -17,4 +18,3 @@ def calculate_std_dev(A):
correlation_matrix = np.divide(covariance, std_dev_X.dot(std_dev_y.T))
return np.array(correlation_matrix, dtype=float)
-
diff --git a/questions/37_calculate-correlation-matrix/starter_code.py b/questions/37_calculate-correlation-matrix/starter_code.py
index 3629df50..372b3084 100644
--- a/questions/37_calculate-correlation-matrix/starter_code.py
+++ b/questions/37_calculate-correlation-matrix/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def calculate_correlation_matrix(X, Y=None):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/38_implement-adaboost-fit-method/solution.py b/questions/38_implement-adaboost-fit-method/solution.py
index 763a9b25..0c94ddcb 100644
--- a/questions/38_implement-adaboost-fit-method/solution.py
+++ b/questions/38_implement-adaboost-fit-method/solution.py
@@ -1,41 +1,43 @@
import math
import numpy as np
+
+
def adaboost_fit(X, y, n_clf):
n_samples, n_features = np.shape(X)
w = np.full(n_samples, (1 / n_samples))
clfs = []
-
+
for _ in range(n_clf):
clf = {}
- min_error = float('inf')
-
+ min_error = float("inf")
+
for feature_i in range(n_features):
feature_values = np.expand_dims(X[:, feature_i], axis=1)
unique_values = np.unique(feature_values)
-
+
for threshold in unique_values:
p = 1
prediction = np.ones(np.shape(y))
prediction[X[:, feature_i] < threshold] = -1
error = sum(w[y != prediction])
-
+
if error > 0.5:
error = 1 - error
p = -1
-
+
if error < min_error:
- clf['polarity'] = p
- clf['threshold'] = threshold
- clf['feature_index'] = feature_i
+ clf["polarity"] = p
+ clf["threshold"] = threshold
+ clf["feature_index"] = feature_i
min_error = error
-
- clf['alpha'] = 0.5 * math.log((1.0 - min_error) / (min_error + 1e-10))
+
+ clf["alpha"] = 0.5 * math.log((1.0 - min_error) / (min_error + 1e-10))
predictions = np.ones(np.shape(y))
- negative_idx = (X[:, clf['feature_index']] < clf['threshold'])
- if clf['polarity'] == -1:
+ negative_idx = X[:, clf["feature_index"]] < clf["threshold"]
+ if clf["polarity"] == -1:
negative_idx = np.logical_not(negative_idx)
predictions[negative_idx] = -1
- w *= np.exp(-clf['alpha'] * y * predictions)
+ w *= np.exp(-clf["alpha"] * y * predictions)
w /= np.sum(w)
clfs.append(clf)
diff --git a/questions/38_implement-adaboost-fit-method/starter_code.py b/questions/38_implement-adaboost-fit-method/starter_code.py
index c64371c7..d704d049 100644
--- a/questions/38_implement-adaboost-fit-method/starter_code.py
+++ b/questions/38_implement-adaboost-fit-method/starter_code.py
@@ -1,12 +1,11 @@
import numpy as np
-import math
+
def adaboost_fit(X, y, n_clf):
- n_samples, n_features = np.shape(X)
- w = np.full(n_samples, (1 / n_samples))
- clfs = []
+ n_samples, n_features = np.shape(X)
+ np.full(n_samples, (1 / n_samples))
+ clfs = []
- # Your code here
+ # Your code here
- return clfs
-
+ return clfs
diff --git a/questions/39_implementation-of-log-softmax-function/solution.py b/questions/39_implementation-of-log-softmax-function/solution.py
index 27a508f2..7c456109 100644
--- a/questions/39_implementation-of-log-softmax-function/solution.py
+++ b/questions/39_implementation-of-log-softmax-function/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def log_softmax(scores: list) -> np.ndarray:
# Subtract the maximum value for numerical stability
scores = scores - np.max(scores)
diff --git a/questions/39_implementation-of-log-softmax-function/starter_code.py b/questions/39_implementation-of-log-softmax-function/starter_code.py
index f1cd1bd9..866beafb 100644
--- a/questions/39_implementation-of-log-softmax-function/starter_code.py
+++ b/questions/39_implementation-of-log-softmax-function/starter_code.py
@@ -1,5 +1,6 @@
import numpy as np
+
def log_softmax(scores: list) -> np.ndarray:
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/3_reshape-matrix/pytorch/solution.py b/questions/3_reshape-matrix/pytorch/solution.py
index 9f453142..70c5719d 100644
--- a/questions/3_reshape-matrix/pytorch/solution.py
+++ b/questions/3_reshape-matrix/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def reshape_matrix(a, new_shape) -> torch.Tensor:
"""
Reshape a 2D matrix `a` to shape `new_shape` using PyTorch.
diff --git a/questions/3_reshape-matrix/pytorch/starter_code.py b/questions/3_reshape-matrix/pytorch/starter_code.py
index 59f70dda..d684a6b1 100644
--- a/questions/3_reshape-matrix/pytorch/starter_code.py
+++ b/questions/3_reshape-matrix/pytorch/starter_code.py
@@ -1,5 +1,6 @@
import torch
+
def reshape_matrix(a, new_shape) -> torch.Tensor:
"""
Reshape a 2D matrix `a` to shape `new_shape` using PyTorch.
@@ -10,6 +11,6 @@ def reshape_matrix(a, new_shape) -> torch.Tensor:
if len(a) * len(a[0]) != new_shape[0] * new_shape[1]:
return torch.tensor([])
# Convert to tensor and reshape
- a_t = torch.as_tensor(a, dtype=torch.float)
+ torch.as_tensor(a, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/3_reshape-matrix/solution.py b/questions/3_reshape-matrix/solution.py
index bca93b75..0192eaf1 100644
--- a/questions/3_reshape-matrix/solution.py
+++ b/questions/3_reshape-matrix/solution.py
@@ -1,7 +1,10 @@
import numpy as np
-def reshape_matrix(a: list[list[int|float]], new_shape: tuple[int|float]) -> list[list[int|float]]:
+
+def reshape_matrix(
+ a: list[list[int | float]], new_shape: tuple[int | float]
+) -> list[list[int | float]]:
# Not compatible case
- if len(a)*len(a[0]) != new_shape[0]*new_shape[1]:
+ if len(a) * len(a[0]) != new_shape[0] * new_shape[1]:
return []
return np.array(a).reshape(new_shape).tolist()
diff --git a/questions/3_reshape-matrix/starter_code.py b/questions/3_reshape-matrix/starter_code.py
index e4c8e214..91ea2426 100644
--- a/questions/3_reshape-matrix/starter_code.py
+++ b/questions/3_reshape-matrix/starter_code.py
@@ -1,5 +1,5 @@
-import numpy as np
-
-def reshape_matrix(a: list[list[int|float]], new_shape: tuple[int, int]) -> list[list[int|float]]:
- #Write your code here and return a python list after reshaping by using numpy's tolist() method
- return reshaped_matrix
+def reshape_matrix(
+ a: list[list[int | float]], new_shape: tuple[int, int]
+) -> list[list[int | float]]:
+ # Write your code here and return a python list after reshaping by using numpy's tolist() method
+ return reshaped_matrix
diff --git a/questions/3_reshape-matrix/tinygrad/solution.py b/questions/3_reshape-matrix/tinygrad/solution.py
index 67e4cad9..22c87152 100644
--- a/questions/3_reshape-matrix/tinygrad/solution.py
+++ b/questions/3_reshape-matrix/tinygrad/solution.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def reshape_matrix_tg(a, new_shape) -> Tensor:
"""
Reshape a 2D matrix `a` to shape `new_shape` using tinygrad.
diff --git a/questions/40_implementing-a-custom-dense-layer-in-python/solution.py b/questions/40_implementing-a-custom-dense-layer-in-python/solution.py
index deb07195..bf730f01 100644
--- a/questions/40_implementing-a-custom-dense-layer-in-python/solution.py
+++ b/questions/40_implementing-a-custom-dense-layer-in-python/solution.py
@@ -1,4 +1,3 @@
-
class Dense(Layer):
def __init__(self, n_units, input_shape=None):
self.layer_input = None
@@ -10,9 +9,9 @@ def __init__(self, n_units, input_shape=None):
def initialize(self, optimizer):
limit = 1 / math.sqrt(self.input_shape[0])
- self.W = np.random.uniform(-limit, limit, (self.input_shape[0], self.n_units))
+ self.W = np.random.uniform(-limit, limit, (self.input_shape[0], self.n_units))
self.w0 = np.zeros((1, self.n_units))
- self.W_opt = copy.copy(optimizer)
+ self.W_opt = copy.copy(optimizer)
self.w0_opt = copy.copy(optimizer)
def parameters(self):
@@ -33,5 +32,4 @@ def backward_pass(self, accum_grad):
return accum_grad
def output_shape(self):
- return (self.n_units, )
-
+ return (self.n_units,)
diff --git a/questions/40_implementing-a-custom-dense-layer-in-python/starter_code.py b/questions/40_implementing-a-custom-dense-layer-in-python/starter_code.py
index 10d711c0..dfe53523 100644
--- a/questions/40_implementing-a-custom-dense-layer-in-python/starter_code.py
+++ b/questions/40_implementing-a-custom-dense-layer-in-python/starter_code.py
@@ -1,4 +1,3 @@
-
import numpy as np
import copy
import math
@@ -38,13 +37,16 @@ def __init__(self, n_units, input_shape=None):
self.W = None
self.w0 = None
- def forward_pass():
+ def forward_pass(self):
+ # Your code here
+ pass
def backward_pass(self, accum_grad):
+ # Your code here
+ pass
- def number_of_parameters():
-
-
-
+ def number_of_parameters(self):
+ # Your code here
+ pass
diff --git a/questions/41_simple-convolutional-2d-layer/solution.py b/questions/41_simple-convolutional-2d-layer/solution.py
index 0eb1a9d0..53cde2b8 100644
--- a/questions/41_simple-convolutional-2d-layer/solution.py
+++ b/questions/41_simple-convolutional-2d-layer/solution.py
@@ -1,10 +1,15 @@
import numpy as np
-def simple_conv2d(input_matrix: np.ndarray, kernel: np.ndarray, padding: int, stride: int):
+
+def simple_conv2d(
+ input_matrix: np.ndarray, kernel: np.ndarray, padding: int, stride: int
+):
input_height, input_width = input_matrix.shape
kernel_height, kernel_width = kernel.shape
- padded_input = np.pad(input_matrix, ((padding, padding), (padding, padding)), mode='constant')
+ padded_input = np.pad(
+ input_matrix, ((padding, padding), (padding, padding)), mode="constant"
+ )
input_height_padded, input_width_padded = padded_input.shape
output_height = (input_height_padded - kernel_height) // stride + 1
@@ -14,7 +19,10 @@ def simple_conv2d(input_matrix: np.ndarray, kernel: np.ndarray, padding: int, st
for i in range(output_height):
for j in range(output_width):
- region = padded_input[i*stride:i*stride + kernel_height, j*stride:j*stride + kernel_width]
+ region = padded_input[
+ i * stride : i * stride + kernel_height,
+ j * stride : j * stride + kernel_width,
+ ]
output_matrix[i, j] = np.sum(region * kernel)
return output_matrix
diff --git a/questions/41_simple-convolutional-2d-layer/starter_code.py b/questions/41_simple-convolutional-2d-layer/starter_code.py
index ce0d3708..e747b6ce 100644
--- a/questions/41_simple-convolutional-2d-layer/starter_code.py
+++ b/questions/41_simple-convolutional-2d-layer/starter_code.py
@@ -1,9 +1,12 @@
import numpy as np
-def simple_conv2d(input_matrix: np.ndarray, kernel: np.ndarray, padding: int, stride: int):
- input_height, input_width = input_matrix.shape
- kernel_height, kernel_width = kernel.shape
- # Your code here
-
- return output_matrix
+def simple_conv2d(
+ input_matrix: np.ndarray, kernel: np.ndarray, padding: int, stride: int
+):
+ input_height, input_width = input_matrix.shape
+ kernel_height, kernel_width = kernel.shape
+
+ # Your code here
+
+ return output_matrix
diff --git a/questions/42_implement-relu-activation-function/starter_code.py b/questions/42_implement-relu-activation-function/starter_code.py
index 7f8448a5..3e408399 100644
--- a/questions/42_implement-relu-activation-function/starter_code.py
+++ b/questions/42_implement-relu-activation-function/starter_code.py
@@ -1,3 +1,3 @@
def relu(z: float) -> float:
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/43_implement-ridge-regression-loss-function/solution.py b/questions/43_implement-ridge-regression-loss-function/solution.py
index d11dd544..801bfa86 100644
--- a/questions/43_implement-ridge-regression-loss-function/solution.py
+++ b/questions/43_implement-ridge-regression-loss-function/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def ridge_loss(X: np.ndarray, w: np.ndarray, y_true: np.ndarray, alpha: float) -> float:
- loss = np.mean((y_true - X @ w)**2) + alpha * np.sum(w**2)
+ loss = np.mean((y_true - X @ w) ** 2) + alpha * np.sum(w**2)
return loss
diff --git a/questions/43_implement-ridge-regression-loss-function/starter_code.py b/questions/43_implement-ridge-regression-loss-function/starter_code.py
index 3322d600..c741737e 100644
--- a/questions/43_implement-ridge-regression-loss-function/starter_code.py
+++ b/questions/43_implement-ridge-regression-loss-function/starter_code.py
@@ -1,5 +1,6 @@
import numpy as np
+
def ridge_loss(X: np.ndarray, w: np.ndarray, y_true: np.ndarray, alpha: float) -> float:
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/44_leaky-relu-activation-function/solution.py b/questions/44_leaky-relu-activation-function/solution.py
index 64be7210..0c3c77d5 100644
--- a/questions/44_leaky-relu-activation-function/solution.py
+++ b/questions/44_leaky-relu-activation-function/solution.py
@@ -1,2 +1,2 @@
-def leaky_relu(z: float, alpha: float = 0.01) -> float|int:
+def leaky_relu(z: float, alpha: float = 0.01) -> float | int:
return z if z > 0 else alpha * z
diff --git a/questions/44_leaky-relu-activation-function/starter_code.py b/questions/44_leaky-relu-activation-function/starter_code.py
index bb2327fe..7620badd 100644
--- a/questions/44_leaky-relu-activation-function/starter_code.py
+++ b/questions/44_leaky-relu-activation-function/starter_code.py
@@ -1,3 +1,3 @@
-def leaky_relu(z: float, alpha: float = 0.01) -> float|int:
- # Your code here
- pass
+def leaky_relu(z: float, alpha: float = 0.01) -> float | int:
+ # Your code here
+ pass
diff --git a/questions/45_linear-kernel-function/solution.py b/questions/45_linear-kernel-function/solution.py
index 488266c9..56d72d10 100644
--- a/questions/45_linear-kernel-function/solution.py
+++ b/questions/45_linear-kernel-function/solution.py
@@ -1,4 +1,5 @@
import numpy as np
+
def kernel_function(x1, x2):
return np.inner(x1, x2)
diff --git a/questions/45_linear-kernel-function/starter_code.py b/questions/45_linear-kernel-function/starter_code.py
index 9a45be24..b420a29e 100644
--- a/questions/45_linear-kernel-function/starter_code.py
+++ b/questions/45_linear-kernel-function/starter_code.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def kernel_function(x1, x2):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/46_implement-precision-metric/solution.py b/questions/46_implement-precision-metric/solution.py
index 92fb27ee..1ddaf22b 100644
--- a/questions/46_implement-precision-metric/solution.py
+++ b/questions/46_implement-precision-metric/solution.py
@@ -1,6 +1,11 @@
import numpy as np
+
def precision(y_true, y_pred):
true_positives = np.sum((y_true == 1) & (y_pred == 1))
false_positives = np.sum((y_true == 0) & (y_pred == 1))
- return true_positives / (true_positives + false_positives) if (true_positives + false_positives) > 0 else 0.0
+ return (
+ true_positives / (true_positives + false_positives)
+ if (true_positives + false_positives) > 0
+ else 0.0
+ )
diff --git a/questions/46_implement-precision-metric/starter_code.py b/questions/46_implement-precision-metric/starter_code.py
index 9cedd696..b4931b3b 100644
--- a/questions/46_implement-precision-metric/starter_code.py
+++ b/questions/46_implement-precision-metric/starter_code.py
@@ -1,4 +1,3 @@
-import numpy as np
def precision(y_true, y_pred):
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/47_implement-gradient-descent-variants-with-mse-loss/solution.py b/questions/47_implement-gradient-descent-variants-with-mse-loss/solution.py
index fa4579b3..acefcde3 100644
--- a/questions/47_implement-gradient-descent-variants-with-mse-loss/solution.py
+++ b/questions/47_implement-gradient-descent-variants-with-mse-loss/solution.py
@@ -1,32 +1,32 @@
-import numpy as np
-
-def gradient_descent(X, y, weights, learning_rate, n_iterations, batch_size=1, method='batch'):
+def gradient_descent(
+ X, y, weights, learning_rate, n_iterations, batch_size=1, method="batch"
+):
m = len(y)
-
+
for _ in range(n_iterations):
- if method == 'batch':
+ if method == "batch":
# Calculate the gradient using all data points
predictions = X.dot(weights)
errors = predictions - y
gradient = 2 * X.T.dot(errors) / m
weights = weights - learning_rate * gradient
-
- elif method == 'stochastic':
+
+ elif method == "stochastic":
# Update weights for each data point individually
for i in range(m):
prediction = X[i].dot(weights)
error = prediction - y[i]
gradient = 2 * X[i].T.dot(error)
weights = weights - learning_rate * gradient
-
- elif method == 'mini_batch':
+
+ elif method == "mini_batch":
# Update weights using sequential batches of data points without shuffling
for i in range(0, m, batch_size):
- X_batch = X[i:i+batch_size]
- y_batch = y[i:i+batch_size]
+ X_batch = X[i : i + batch_size]
+ y_batch = y[i : i + batch_size]
predictions = X_batch.dot(weights)
errors = predictions - y_batch
gradient = 2 * X_batch.T.dot(errors) / batch_size
weights = weights - learning_rate * gradient
-
+
return weights
diff --git a/questions/47_implement-gradient-descent-variants-with-mse-loss/starter_code.py b/questions/47_implement-gradient-descent-variants-with-mse-loss/starter_code.py
index 41108c48..91fee248 100644
--- a/questions/47_implement-gradient-descent-variants-with-mse-loss/starter_code.py
+++ b/questions/47_implement-gradient-descent-variants-with-mse-loss/starter_code.py
@@ -1,5 +1,5 @@
-import numpy as np
-
-def gradient_descent(X, y, weights, learning_rate, n_iterations, batch_size=1, method='batch'):
- # Your code here
- pass
+def gradient_descent(
+ X, y, weights, learning_rate, n_iterations, batch_size=1, method="batch"
+):
+ # Your code here
+ pass
diff --git a/questions/48_implement-reduced-row-echelon-form-rref-function/solution.py b/questions/48_implement-reduced-row-echelon-form-rref-function/solution.py
index f6c83dd4..0a65cac5 100644
--- a/questions/48_implement-reduced-row-echelon-form-rref-function/solution.py
+++ b/questions/48_implement-reduced-row-echelon-form-rref-function/solution.py
@@ -1,33 +1,34 @@
import numpy as np
+
def rref(matrix):
# Convert to float for division operations
A = matrix.astype(np.float32)
n, m = A.shape
row = 0 # Current row index for pivot placement
-
+
# Iterate over columns, up to the number of columns m
for col in range(m):
if row >= n: # No more rows to process
break
-
+
# Find a row with a non-zero entry in the current column
nonzero_rel_id = np.nonzero(A[row:, col])[0]
if len(nonzero_rel_id) == 0: # No pivot in this column
continue
-
+
# Swap the current row with the row containing the non-zero entry
k = nonzero_rel_id[0] + row
A[[row, k]] = A[[k, row]]
-
+
# Normalize the pivot row to make the pivot 1
A[row] = A[row] / A[row, col]
-
+
# Eliminate all other entries in this column
for j in range(n):
if j != row:
A[j] -= A[j, col] * A[row]
-
+
row += 1 # Move to the next row for the next pivot
-
+
return A
diff --git a/questions/48_implement-reduced-row-echelon-form-rref-function/starter_code.py b/questions/48_implement-reduced-row-echelon-form-rref-function/starter_code.py
index c7869868..f3b68d26 100644
--- a/questions/48_implement-reduced-row-echelon-form-rref-function/starter_code.py
+++ b/questions/48_implement-reduced-row-echelon-form-rref-function/starter_code.py
@@ -1,5 +1,5 @@
import numpy as np
def rref(matrix):
- Your code here
+ #Your code here
pass
diff --git a/questions/49_implement-adam-optimization-algorithm/solution.py b/questions/49_implement-adam-optimization-algorithm/solution.py
index f4651e78..d9c3d80b 100644
--- a/questions/49_implement-adam-optimization-algorithm/solution.py
+++ b/questions/49_implement-adam-optimization-algorithm/solution.py
@@ -1,6 +1,16 @@
import numpy as np
-def adam_optimizer(f, grad, x0, learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8, num_iterations=10):
+
+def adam_optimizer(
+ f,
+ grad,
+ x0,
+ learning_rate=0.001,
+ beta1=0.9,
+ beta2=0.999,
+ epsilon=1e-8,
+ num_iterations=10,
+):
x = x0
m = np.zeros_like(x)
v = np.zeros_like(x)
diff --git a/questions/49_implement-adam-optimization-algorithm/starter_code.py b/questions/49_implement-adam-optimization-algorithm/starter_code.py
index 0ed4610a..f00c2505 100644
--- a/questions/49_implement-adam-optimization-algorithm/starter_code.py
+++ b/questions/49_implement-adam-optimization-algorithm/starter_code.py
@@ -1,5 +1,12 @@
-import numpy as np
-
-def adam_optimizer(f, grad, x0, learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8, num_iterations=10):
- # Your code here
- pass
+def adam_optimizer(
+ f,
+ grad,
+ x0,
+ learning_rate=0.001,
+ beta1=0.9,
+ beta2=0.999,
+ epsilon=1e-8,
+ num_iterations=10,
+):
+ # Your code here
+ pass
diff --git a/questions/4_calculate-mean-by-row-or-column/pytorch/solution.py b/questions/4_calculate-mean-by-row-or-column/pytorch/solution.py
index 5501b2e5..50bd374c 100644
--- a/questions/4_calculate-mean-by-row-or-column/pytorch/solution.py
+++ b/questions/4_calculate-mean-by-row-or-column/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def calculate_matrix_mean(matrix, mode: str) -> torch.Tensor:
"""
Calculate mean of a 2D matrix per row or per column using PyTorch.
@@ -7,9 +8,9 @@ def calculate_matrix_mean(matrix, mode: str) -> torch.Tensor:
Returns a 1-D tensor of means or raises ValueError on invalid mode.
"""
a_t = torch.as_tensor(matrix, dtype=torch.float)
- if mode == 'column':
+ if mode == "column":
return a_t.mean(dim=0)
- elif mode == 'row':
+ elif mode == "row":
return a_t.mean(dim=1)
else:
raise ValueError("Mode must be 'row' or 'column'")
diff --git a/questions/4_calculate-mean-by-row-or-column/pytorch/starter_code.py b/questions/4_calculate-mean-by-row-or-column/pytorch/starter_code.py
index f30b54e6..8d0e3f38 100644
--- a/questions/4_calculate-mean-by-row-or-column/pytorch/starter_code.py
+++ b/questions/4_calculate-mean-by-row-or-column/pytorch/starter_code.py
@@ -1,11 +1,12 @@
import torch
+
def calculate_matrix_mean(matrix, mode: str) -> torch.Tensor:
"""
Calculate mean of a 2D matrix per row or per column using PyTorch.
Inputs can be Python lists, NumPy arrays, or torch Tensors.
Returns a 1-D tensor of means or raises ValueError on invalid mode.
"""
- a_t = torch.as_tensor(matrix, dtype=torch.float)
+ torch.as_tensor(matrix, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/4_calculate-mean-by-row-or-column/solution.py b/questions/4_calculate-mean-by-row-or-column/solution.py
index 021ca6c2..e2508d3e 100644
--- a/questions/4_calculate-mean-by-row-or-column/solution.py
+++ b/questions/4_calculate-mean-by-row-or-column/solution.py
@@ -1,7 +1,7 @@
def calculate_matrix_mean(matrix: list[list[float]], mode: str) -> list[float]:
- if mode == 'column':
+ if mode == "column":
return [sum(col) / len(matrix) for col in zip(*matrix)]
- elif mode == 'row':
+ elif mode == "row":
return [sum(row) / len(row) for row in matrix]
else:
raise ValueError("Mode must be 'row' or 'column'")
diff --git a/questions/4_calculate-mean-by-row-or-column/starter_code.py b/questions/4_calculate-mean-by-row-or-column/starter_code.py
index 02ab4a1a..a1553e80 100644
--- a/questions/4_calculate-mean-by-row-or-column/starter_code.py
+++ b/questions/4_calculate-mean-by-row-or-column/starter_code.py
@@ -1,2 +1,2 @@
def calculate_matrix_mean(matrix: list[list[float]], mode: str) -> list[float]:
- return means
+ return means
diff --git a/questions/4_calculate-mean-by-row-or-column/tinygrad/solution.py b/questions/4_calculate-mean-by-row-or-column/tinygrad/solution.py
index fb5e68d6..ef5f99c3 100644
--- a/questions/4_calculate-mean-by-row-or-column/tinygrad/solution.py
+++ b/questions/4_calculate-mean-by-row-or-column/tinygrad/solution.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def calculate_matrix_mean_tg(matrix, mode: str) -> Tensor:
"""
Calculate mean of a 2D matrix per row or per column using tinygrad.
@@ -9,9 +10,9 @@ def calculate_matrix_mean_tg(matrix, mode: str) -> Tensor:
v_t = Tensor(matrix).float()
n_obs = v_t.shape[1]
n_feat = v_t.shape[0]
- if mode == 'column':
+ if mode == "column":
return v_t.sum(axis=1) / n_obs
- elif mode == 'row':
+ elif mode == "row":
return v_t.sum(axis=0) / n_feat
else:
raise ValueError("Mode must be 'row' or 'column'")
diff --git a/questions/4_calculate-mean-by-row-or-column/tinygrad/starter_code.py b/questions/4_calculate-mean-by-row-or-column/tinygrad/starter_code.py
index f85354a4..44f5ffe9 100644
--- a/questions/4_calculate-mean-by-row-or-column/tinygrad/starter_code.py
+++ b/questions/4_calculate-mean-by-row-or-column/tinygrad/starter_code.py
@@ -1,11 +1,12 @@
from tinygrad.tensor import Tensor
+
def calculate_matrix_mean_tg(matrix, mode: str) -> Tensor:
"""
Calculate mean of a 2D matrix per row or per column using tinygrad.
Inputs can be Python lists, NumPy arrays, or tinygrad Tensors.
Returns a 1-D Tensor of means or raises ValueError on invalid mode.
"""
- v_t = Tensor(matrix).float()
+ Tensor(matrix).float()
# Your implementation here
pass
diff --git a/questions/50_implement-lasso-regression-using-gradient-descent/solution.py b/questions/50_implement-lasso-regression-using-gradient-descent/solution.py
index d8d3a5b8..e7ab551f 100644
--- a/questions/50_implement-lasso-regression-using-gradient-descent/solution.py
+++ b/questions/50_implement-lasso-regression-using-gradient-descent/solution.py
@@ -1,11 +1,19 @@
import numpy as np
-def l1_regularization_gradient_descent(X: np.array, y: np.array, alpha: float = 0.1, learning_rate: float = 0.01, max_iter: int = 1000, tol: float = 1e-4) -> tuple:
+
+def l1_regularization_gradient_descent(
+ X: np.array,
+ y: np.array,
+ alpha: float = 0.1,
+ learning_rate: float = 0.01,
+ max_iter: int = 1000,
+ tol: float = 1e-4,
+) -> tuple:
n_samples, n_features = X.shape
# Zero out weights and bias
weights = np.zeros(n_features)
bias = 0
-
+
for iteration in range(max_iter):
# Predict values
y_pred = np.dot(X, weights) + bias
@@ -15,13 +23,13 @@ def l1_regularization_gradient_descent(X: np.array, y: np.array, alpha: float =
grad_w = (1 / n_samples) * np.dot(X.T, error) + alpha * np.sign(weights)
# Gradient for bias (no penalty for bias)
grad_b = (1 / n_samples) * np.sum(error)
-
+
# Update weights and bias
weights -= learning_rate * grad_w
bias -= learning_rate * grad_b
-
+
# Check for convergence
if np.linalg.norm(grad_w, ord=1) < tol:
break
-
+
return weights, bias
diff --git a/questions/50_implement-lasso-regression-using-gradient-descent/starter_code.py b/questions/50_implement-lasso-regression-using-gradient-descent/starter_code.py
index 69ca086d..eb4d938e 100644
--- a/questions/50_implement-lasso-regression-using-gradient-descent/starter_code.py
+++ b/questions/50_implement-lasso-regression-using-gradient-descent/starter_code.py
@@ -1,9 +1,16 @@
import numpy as np
-def l1_regularization_gradient_descent(X: np.array, y: np.array, alpha: float = 0.1, learning_rate: float = 0.01, max_iter: int = 1000, tol: float = 1e-4) -> tuple:
- n_samples, n_features = X.shape
- weights = np.zeros(n_features)
- bias = 0
- # Your code here
- pass
+def l1_regularization_gradient_descent(
+ X: np.array,
+ y: np.array,
+ alpha: float = 0.1,
+ learning_rate: float = 0.01,
+ max_iter: int = 1000,
+ tol: float = 1e-4,
+) -> tuple:
+ n_samples, n_features = X.shape
+
+ np.zeros(n_features)
+ # Your code here
+ pass
diff --git a/questions/51_optimal-string-alignment-distance/solution.py b/questions/51_optimal-string-alignment-distance/solution.py
index b21c69b3..cc233d29 100644
--- a/questions/51_optimal-string-alignment-distance/solution.py
+++ b/questions/51_optimal-string-alignment-distance/solution.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def OSA(source: str, target: str) -> int:
source_len, target_len = len(source), len(target)
@@ -18,9 +16,17 @@ def OSA(source: str, target: str) -> int:
osa_matrix[i][j] = min(
osa_matrix[i - 1][j] + 1, # Deletion
osa_matrix[i][j - 1] + 1, # Insertion
- osa_matrix[i - 1][j - 1] + (1 if source[i - 1] != target[j - 1] else 0) # Substitution
+ osa_matrix[i - 1][j - 1]
+ + (1 if source[i - 1] != target[j - 1] else 0), # Substitution
)
- if i > 1 and j > 1 and source[i - 1] == target[j - 2] and source[i - 2] == target[j - 1]:
- osa_matrix[i][j] = min(osa_matrix[i][j], osa_matrix[i - 2][j - 2] + 1) # Transposition
+ if (
+ i > 1
+ and j > 1
+ and source[i - 1] == target[j - 2]
+ and source[i - 2] == target[j - 1]
+ ):
+ osa_matrix[i][j] = min(
+ osa_matrix[i][j], osa_matrix[i - 2][j - 2] + 1
+ ) # Transposition
return osa_matrix[-1][-1]
diff --git a/questions/51_optimal-string-alignment-distance/starter_code.py b/questions/51_optimal-string-alignment-distance/starter_code.py
index eed1af3c..2cd0e816 100644
--- a/questions/51_optimal-string-alignment-distance/starter_code.py
+++ b/questions/51_optimal-string-alignment-distance/starter_code.py
@@ -1,3 +1,3 @@
def OSA(source: str, target: str) -> int:
- # Your code here
- pass
+ # Your code here
+ pass
diff --git a/questions/52_implement-recall-metric-in-binary-classification/solution.py b/questions/52_implement-recall-metric-in-binary-classification/solution.py
index 54271f46..a07708ee 100644
--- a/questions/52_implement-recall-metric-in-binary-classification/solution.py
+++ b/questions/52_implement-recall-metric-in-binary-classification/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def recall(y_true, y_pred):
tp = np.sum((y_true == 1) & (y_pred == 1))
fn = np.sum((y_true == 1) & (y_pred == 0))
diff --git a/questions/52_implement-recall-metric-in-binary-classification/starter_code.py b/questions/52_implement-recall-metric-in-binary-classification/starter_code.py
index d70c1d3f..54216a40 100644
--- a/questions/52_implement-recall-metric-in-binary-classification/starter_code.py
+++ b/questions/52_implement-recall-metric-in-binary-classification/starter_code.py
@@ -1,3 +1,4 @@
import numpy as np
def recall(y_true, y_pred):
-
+ # Your code here
+ pass
diff --git a/questions/53_implement-self-attention-mechanism/solution.py b/questions/53_implement-self-attention-mechanism/solution.py
index 2d727c7a..88088a62 100644
--- a/questions/53_implement-self-attention-mechanism/solution.py
+++ b/questions/53_implement-self-attention-mechanism/solution.py
@@ -1,11 +1,13 @@
import numpy as np
+
def compute_qkv(X, W_q, W_k, W_v):
Q = np.dot(X, W_q)
K = np.dot(X, W_k)
V = np.dot(X, W_v)
return Q, K, V
+
def self_attention(Q, K, V):
d_k = Q.shape[1]
scores = np.matmul(Q, K.T) / np.sqrt(d_k)
diff --git a/questions/53_implement-self-attention-mechanism/starter_code.py b/questions/53_implement-self-attention-mechanism/starter_code.py
index 230bf496..4303ff74 100644
--- a/questions/53_implement-self-attention-mechanism/starter_code.py
+++ b/questions/53_implement-self-attention-mechanism/starter_code.py
@@ -1,5 +1,2 @@
-import numpy as np
-
def self_attention(Q, K, V):
-
- return attention_output
+ return attention_output
diff --git a/questions/54_implementing-a-simple-rnn/solution.py b/questions/54_implementing-a-simple-rnn/solution.py
index 8bb293ba..ece11194 100644
--- a/questions/54_implementing-a-simple-rnn/solution.py
+++ b/questions/54_implementing-a-simple-rnn/solution.py
@@ -1,6 +1,6 @@
-
import numpy as np
+
def rnn_forward(input_sequence, initial_hidden_state, Wx, Wh, b):
h = np.array(initial_hidden_state)
Wx = np.array(Wx)
diff --git a/questions/54_implementing-a-simple-rnn/starter_code.py b/questions/54_implementing-a-simple-rnn/starter_code.py
index 3139eed9..ff15ab7b 100644
--- a/questions/54_implementing-a-simple-rnn/starter_code.py
+++ b/questions/54_implementing-a-simple-rnn/starter_code.py
@@ -1,5 +1,9 @@
-import numpy as np
-
-def rnn_forward(input_sequence: list[list[float]], initial_hidden_state: list[float], Wx: list[list[float]], Wh: list[list[float]], b: list[float]) -> list[float]:
- # Your code here
- return final_hidden_state
+def rnn_forward(
+ input_sequence: list[list[float]],
+ initial_hidden_state: list[float],
+ Wx: list[list[float]],
+ Wh: list[list[float]],
+ b: list[float],
+) -> list[float]:
+ # Your code here
+ return final_hidden_state
diff --git a/questions/55_2d-translation-matrix-implementation/solution.py b/questions/55_2d-translation-matrix-implementation/solution.py
index e456a0c6..5198045a 100644
--- a/questions/55_2d-translation-matrix-implementation/solution.py
+++ b/questions/55_2d-translation-matrix-implementation/solution.py
@@ -1,14 +1,11 @@
import numpy as np
+
def translate_object(points, tx, ty):
- translation_matrix = np.array([
- [1, 0, tx],
- [0, 1, ty],
- [0, 0, 1]
- ])
-
+ translation_matrix = np.array([[1, 0, tx], [0, 1, ty], [0, 0, 1]])
+
homogeneous_points = np.hstack([np.array(points), np.ones((len(points), 1))])
-
+
translated_points = np.dot(homogeneous_points, translation_matrix.T)
-
+
return translated_points[:, :2].tolist()
diff --git a/questions/55_2d-translation-matrix-implementation/starter_code.py b/questions/55_2d-translation-matrix-implementation/starter_code.py
index 788d9056..2a6110f5 100644
--- a/questions/55_2d-translation-matrix-implementation/starter_code.py
+++ b/questions/55_2d-translation-matrix-implementation/starter_code.py
@@ -1,3 +1,2 @@
-import numpy as np
def translate_object(points, tx, ty):
- return translated_points
+ return translated_points
diff --git a/questions/56_kl-divergence-between-two-normal-distributions/solution.py b/questions/56_kl-divergence-between-two-normal-distributions/solution.py
index 82999017..03f2749d 100644
--- a/questions/56_kl-divergence-between-two-normal-distributions/solution.py
+++ b/questions/56_kl-divergence-between-two-normal-distributions/solution.py
@@ -1,7 +1,8 @@
import numpy as np
+
def kl_divergence_normal(mu_p, sigma_p, mu_q, sigma_q):
term1 = np.log(sigma_q / sigma_p)
- term2 = (sigma_p ** 2 + (mu_p - mu_q) ** 2) / (2 * sigma_q ** 2)
+ term2 = (sigma_p**2 + (mu_p - mu_q) ** 2) / (2 * sigma_q**2)
kl_div = term1 + term2 - 0.5
return kl_div
diff --git a/questions/56_kl-divergence-between-two-normal-distributions/starter_code.py b/questions/56_kl-divergence-between-two-normal-distributions/starter_code.py
index afa7998b..1bcf31f6 100644
--- a/questions/56_kl-divergence-between-two-normal-distributions/starter_code.py
+++ b/questions/56_kl-divergence-between-two-normal-distributions/starter_code.py
@@ -1,4 +1,2 @@
-import numpy as np
-
def kl_divergence_normal(mu_p, sigma_p, mu_q, sigma_q):
- return 0.0
+ return 0.0
diff --git a/questions/57_gauss-seidel-method-for-solving-linear-systems/solution.py b/questions/57_gauss-seidel-method-for-solving-linear-systems/solution.py
index bd5c4ad4..6e407627 100644
--- a/questions/57_gauss-seidel-method-for-solving-linear-systems/solution.py
+++ b/questions/57_gauss-seidel-method-for-solving-linear-systems/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def gauss_seidel_it(A, b, x):
rows, cols = A.shape
for i in range(rows):
@@ -10,6 +11,7 @@ def gauss_seidel_it(A, b, x):
x[i] = x_new / A[i, i]
return x
+
def gauss_seidel(A, b, n, x_ini=None):
x = x_ini or np.zeros_like(b)
for _ in range(n):
diff --git a/questions/57_gauss-seidel-method-for-solving-linear-systems/starter_code.py b/questions/57_gauss-seidel-method-for-solving-linear-systems/starter_code.py
index 1364f5df..ed80ee88 100644
--- a/questions/57_gauss-seidel-method-for-solving-linear-systems/starter_code.py
+++ b/questions/57_gauss-seidel-method-for-solving-linear-systems/starter_code.py
@@ -1,4 +1,5 @@
import numpy as np
+
def gauss_seidel(A, b, n, x_ini=None):
- return np.zeros_like(b)
+ return np.zeros_like(b)
diff --git a/questions/58_gaussian-elimination-for-solving-linear-systems/solution.py b/questions/58_gaussian-elimination-for-solving-linear-systems/solution.py
index 6d851796..a89ba512 100644
--- a/questions/58_gaussian-elimination-for-solving-linear-systems/solution.py
+++ b/questions/58_gaussian-elimination-for-solving-linear-systems/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def partial_pivoting(A_aug, row_num, col_num):
rows, cols = A_aug.shape
max_row = row_num
@@ -13,16 +14,17 @@ def partial_pivoting(A_aug, row_num, col_num):
A_aug[[row_num, max_row]] = A_aug[[max_row, row_num]]
return A_aug
+
def gaussian_elimination(A, b):
rows, cols = A.shape
A_aug = np.hstack((A, b.reshape(-1, 1)))
- for i in range(rows-1):
+ for i in range(rows - 1):
A_aug = partial_pivoting(A_aug, i, i)
- for j in range(i+1, rows):
+ for j in range(i + 1, rows):
A_aug[j, i:] -= (A_aug[j, i] / A_aug[i, i]) * A_aug[i, i:]
x = np.zeros_like(b, dtype=float)
- for i in range(rows-1, -1, -1):
- x[i] = (A_aug[i, -1] - np.dot(A_aug[i, i+1:cols], x[i+1:])) / A_aug[i, i]
+ for i in range(rows - 1, -1, -1):
+ x[i] = (A_aug[i, -1] - np.dot(A_aug[i, i + 1 : cols], x[i + 1 :])) / A_aug[i, i]
return x
diff --git a/questions/58_gaussian-elimination-for-solving-linear-systems/starter_code.py b/questions/58_gaussian-elimination-for-solving-linear-systems/starter_code.py
index 9da83506..e2d412f2 100644
--- a/questions/58_gaussian-elimination-for-solving-linear-systems/starter_code.py
+++ b/questions/58_gaussian-elimination-for-solving-linear-systems/starter_code.py
@@ -1,11 +1,12 @@
import numpy as np
+
def gaussian_elimination(A, b):
- """
- Solves the system Ax = b using Gaussian Elimination with partial pivoting.
-
- :param A: Coefficient matrix
- :param b: Right-hand side vector
- :return: Solution vector x
- """
- return np.zeros_like(b)
+ """
+ Solves the system Ax = b using Gaussian Elimination with partial pivoting.
+
+ :param A: Coefficient matrix
+ :param b: Right-hand side vector
+ :return: Solution vector x
+ """
+ return np.zeros_like(b)
diff --git a/questions/59_implement-long-short-term-memory-lstm-network/solution.py b/questions/59_implement-long-short-term-memory-lstm-network/solution.py
index 3437bfe2..68105aff 100644
--- a/questions/59_implement-long-short-term-memory-lstm-network/solution.py
+++ b/questions/59_implement-long-short-term-memory-lstm-network/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
class LSTM:
def __init__(self, input_size, hidden_size):
self.input_size = input_size
diff --git a/questions/59_implement-long-short-term-memory-lstm-network/starter_code.py b/questions/59_implement-long-short-term-memory-lstm-network/starter_code.py
index d9db3696..195bb652 100644
--- a/questions/59_implement-long-short-term-memory-lstm-network/starter_code.py
+++ b/questions/59_implement-long-short-term-memory-lstm-network/starter_code.py
@@ -1,23 +1,24 @@
import numpy as np
+
class LSTM:
- def __init__(self, input_size, hidden_size):
- self.input_size = input_size
- self.hidden_size = hidden_size
+ def __init__(self, input_size, hidden_size):
+ self.input_size = input_size
+ self.hidden_size = hidden_size
- # Initialize weights and biases
- self.Wf = np.random.randn(hidden_size, input_size + hidden_size)
- self.Wi = np.random.randn(hidden_size, input_size + hidden_size)
- self.Wc = np.random.randn(hidden_size, input_size + hidden_size)
- self.Wo = np.random.randn(hidden_size, input_size + hidden_size)
+ # Initialize weights and biases
+ self.Wf = np.random.randn(hidden_size, input_size + hidden_size)
+ self.Wi = np.random.randn(hidden_size, input_size + hidden_size)
+ self.Wc = np.random.randn(hidden_size, input_size + hidden_size)
+ self.Wo = np.random.randn(hidden_size, input_size + hidden_size)
- self.bf = np.zeros((hidden_size, 1))
- self.bi = np.zeros((hidden_size, 1))
- self.bc = np.zeros((hidden_size, 1))
- self.bo = np.zeros((hidden_size, 1))
+ self.bf = np.zeros((hidden_size, 1))
+ self.bi = np.zeros((hidden_size, 1))
+ self.bc = np.zeros((hidden_size, 1))
+ self.bo = np.zeros((hidden_size, 1))
- def forward(self, x, initial_hidden_state, initial_cell_state):
- """
- Processes a sequence of inputs and returns the hidden states, final hidden state, and final cell state.
- """
- pass
+ def forward(self, x, initial_hidden_state, initial_cell_state):
+ """
+ Processes a sequence of inputs and returns the hidden states, final hidden state, and final cell state.
+ """
+ pass
diff --git a/questions/5_scalar-multiplication-of-a-matrix/pytorch/solution.py b/questions/5_scalar-multiplication-of-a-matrix/pytorch/solution.py
index 195a9048..05bcbd4e 100644
--- a/questions/5_scalar-multiplication-of-a-matrix/pytorch/solution.py
+++ b/questions/5_scalar-multiplication-of-a-matrix/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def scalar_multiply(matrix, scalar) -> torch.Tensor:
"""
Multiply each element of a 2D matrix by a scalar using PyTorch.
diff --git a/questions/5_scalar-multiplication-of-a-matrix/pytorch/starter_code.py b/questions/5_scalar-multiplication-of-a-matrix/pytorch/starter_code.py
index e02b71c3..a157f6ed 100644
--- a/questions/5_scalar-multiplication-of-a-matrix/pytorch/starter_code.py
+++ b/questions/5_scalar-multiplication-of-a-matrix/pytorch/starter_code.py
@@ -1,5 +1,6 @@
import torch
+
def scalar_multiply(matrix, scalar) -> torch.Tensor:
"""
Multiply each element of a 2D matrix by a scalar using PyTorch.
@@ -7,6 +8,6 @@ def scalar_multiply(matrix, scalar) -> torch.Tensor:
Returns a 2D tensor of the same shape.
"""
# Convert input to tensor
- m_t = torch.as_tensor(matrix, dtype=torch.float)
+ torch.as_tensor(matrix, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/5_scalar-multiplication-of-a-matrix/solution.py b/questions/5_scalar-multiplication-of-a-matrix/solution.py
index a025c49e..f642dbce 100644
--- a/questions/5_scalar-multiplication-of-a-matrix/solution.py
+++ b/questions/5_scalar-multiplication-of-a-matrix/solution.py
@@ -1,2 +1,4 @@
-def scalar_multiply(matrix: list[list[int|float]], scalar: int|float) -> list[list[int|float]]:
+def scalar_multiply(
+ matrix: list[list[int | float]], scalar: int | float
+) -> list[list[int | float]]:
return [[element * scalar for element in row] for row in matrix]
diff --git a/questions/5_scalar-multiplication-of-a-matrix/starter_code.py b/questions/5_scalar-multiplication-of-a-matrix/starter_code.py
index 2f260f30..e1dd4561 100644
--- a/questions/5_scalar-multiplication-of-a-matrix/starter_code.py
+++ b/questions/5_scalar-multiplication-of-a-matrix/starter_code.py
@@ -1,2 +1,4 @@
-def scalar_multiply(matrix: list[list[int|float]], scalar: int|float) -> list[list[int|float]]:
- return result
+def scalar_multiply(
+ matrix: list[list[int | float]], scalar: int | float
+) -> list[list[int | float]]:
+ return result
diff --git a/questions/5_scalar-multiplication-of-a-matrix/tinygrad/solution.py b/questions/5_scalar-multiplication-of-a-matrix/tinygrad/solution.py
index 3c58ac52..951ca3b4 100644
--- a/questions/5_scalar-multiplication-of-a-matrix/tinygrad/solution.py
+++ b/questions/5_scalar-multiplication-of-a-matrix/tinygrad/solution.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def scalar_multiply_tg(matrix, scalar) -> Tensor:
"""
Multiply each element of a 2D matrix by a scalar using tinygrad.
diff --git a/questions/5_scalar-multiplication-of-a-matrix/tinygrad/starter_code.py b/questions/5_scalar-multiplication-of-a-matrix/tinygrad/starter_code.py
index 0d96bc7e..87b6206b 100644
--- a/questions/5_scalar-multiplication-of-a-matrix/tinygrad/starter_code.py
+++ b/questions/5_scalar-multiplication-of-a-matrix/tinygrad/starter_code.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def scalar_multiply_tg(matrix, scalar) -> Tensor:
"""
Multiply each element of a 2D matrix by a scalar using tinygrad.
@@ -7,6 +8,6 @@ def scalar_multiply_tg(matrix, scalar) -> Tensor:
Returns a 2D Tensor of the same shape.
"""
# Convert input to Tensor
- m_t = Tensor(matrix)
+ Tensor(matrix)
# Your implementation here
pass
diff --git a/questions/60_implement-tf-idf-term-frequency-inverse-document-f/solution.py b/questions/60_implement-tf-idf-term-frequency-inverse-document-f/solution.py
index 1bd42c03..5542c4a7 100644
--- a/questions/60_implement-tf-idf-term-frequency-inverse-document-f/solution.py
+++ b/questions/60_implement-tf-idf-term-frequency-inverse-document-f/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def compute_tf_idf(corpus, query):
"""
Compute TF-IDF scores for a query against a corpus of documents using only NumPy.
diff --git a/questions/60_implement-tf-idf-term-frequency-inverse-document-f/starter_code.py b/questions/60_implement-tf-idf-term-frequency-inverse-document-f/starter_code.py
index 9bbd011f..cb1aef17 100644
--- a/questions/60_implement-tf-idf-term-frequency-inverse-document-f/starter_code.py
+++ b/questions/60_implement-tf-idf-term-frequency-inverse-document-f/starter_code.py
@@ -1,11 +1,9 @@
-import numpy as np
-
def compute_tf_idf(corpus, query):
- """
- Compute TF-IDF scores for a query against a corpus of documents.
-
- :param corpus: List of documents, where each document is a list of words
- :param query: List of words in the query
- :return: List of lists containing TF-IDF scores for the query words in each document
- """
- pass
+ """
+ Compute TF-IDF scores for a query against a corpus of documents.
+
+ :param corpus: List of documents, where each document is a list of words
+ :param query: List of words in the query
+ :return: List of lists containing TF-IDF scores for the query words in each document
+ """
+ pass
diff --git a/questions/61_implement-f-score-calculation-for-binary-classific/solution.py b/questions/61_implement-f-score-calculation-for-binary-classific/solution.py
index 8b6deab6..8776ae39 100644
--- a/questions/61_implement-f-score-calculation-for-binary-classific/solution.py
+++ b/questions/61_implement-f-score-calculation-for-binary-classific/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def f_score(y_true, y_pred, beta):
tp = np.sum((y_true == 1) & (y_pred == 1))
fn = np.sum((y_true == 1) & (y_pred == 0))
@@ -14,5 +15,5 @@ def f_score(y_true, y_pred, beta):
if div == 0 or op == 0:
return 0.0
- score = (1 + (beta ** 2)) * op / div
+ score = (1 + (beta**2)) * op / div
return round(score, 3)
diff --git a/questions/61_implement-f-score-calculation-for-binary-classific/starter_code.py b/questions/61_implement-f-score-calculation-for-binary-classific/starter_code.py
index dfdb6834..c6261c1f 100644
--- a/questions/61_implement-f-score-calculation-for-binary-classific/starter_code.py
+++ b/questions/61_implement-f-score-calculation-for-binary-classific/starter_code.py
@@ -1,12 +1,10 @@
-import numpy as np
-
def f_score(y_true, y_pred, beta):
- """
- Calculate F-Score for a binary classification task.
+ """
+ Calculate F-Score for a binary classification task.
- :param y_true: Numpy array of true labels
- :param y_pred: Numpy array of predicted labels
- :param beta: The weight of precision in the harmonic mean
- :return: F-Score rounded to three decimal places
- """
- pass
+ :param y_true: Numpy array of true labels
+ :param y_pred: Numpy array of predicted labels
+ :param beta: The weight of precision in the harmonic mean
+ :return: F-Score rounded to three decimal places
+ """
+ pass
diff --git a/questions/62_implement-a-simple-rnn-with-backpropagation-throug/solution.py b/questions/62_implement-a-simple-rnn-with-backpropagation-throug/solution.py
index d28e5063..2075cee8 100644
--- a/questions/62_implement-a-simple-rnn-with-backpropagation-throug/solution.py
+++ b/questions/62_implement-a-simple-rnn-with-backpropagation-throug/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
class SimpleRNN:
def __init__(self, input_size, hidden_size, output_size):
self.hidden_size = hidden_size
@@ -14,14 +15,16 @@ def forward(self, x):
outputs = []
self.last_inputs = []
self.last_hiddens = [h]
-
+
for t in range(len(x)):
self.last_inputs.append(x[t].reshape(-1, 1))
- h = np.tanh(np.dot(self.W_xh, self.last_inputs[t]) + np.dot(self.W_hh, h) + self.b_h)
+ h = np.tanh(
+ np.dot(self.W_xh, self.last_inputs[t]) + np.dot(self.W_hh, h) + self.b_h
+ )
y = np.dot(self.W_hy, h) + self.b_y
outputs.append(y)
self.last_hiddens.append(h)
-
+
self.last_outputs = outputs
return np.array(outputs)
@@ -36,11 +39,11 @@ def backward(self, x, y, learning_rate):
for t in reversed(range(len(x))):
dy = self.last_outputs[t] - y[t].reshape(-1, 1) # (Predicted - Actual)
- dW_hy += np.dot(dy, self.last_hiddens[t+1].T)
+ dW_hy += np.dot(dy, self.last_hiddens[t + 1].T)
db_y += dy
dh = np.dot(self.W_hy.T, dy) + dh_next
- dh_raw = (1 - self.last_hiddens[t+1] ** 2) * dh # Derivative of tanh
+ dh_raw = (1 - self.last_hiddens[t + 1] ** 2) * dh # Derivative of tanh
dW_xh += np.dot(dh_raw, self.last_inputs[t].T)
dW_hh += np.dot(dh_raw, self.last_hiddens[t].T)
diff --git a/questions/62_implement-a-simple-rnn-with-backpropagation-throug/starter_code.py b/questions/62_implement-a-simple-rnn-with-backpropagation-throug/starter_code.py
index 52b6f515..f9b354d6 100644
--- a/questions/62_implement-a-simple-rnn-with-backpropagation-throug/starter_code.py
+++ b/questions/62_implement-a-simple-rnn-with-backpropagation-throug/starter_code.py
@@ -1,17 +1,16 @@
-
import numpy as np
class SimpleRNN:
- def __init__(self, input_size, hidden_size, output_size):
+ def __init__(self, input_size, hidden_size, output_size):
"""
Initializes the RNN with random weights and zero biases.
"""
- self.hidden_size = hidden_size
- self.W_xh = np.random.randn(hidden_size, input_size)*0.01
- self.W_hh = np.random.randn(hidden_size, hidden_size)*0.01
- self.W_hy = np.random.randn(output_size, hidden_size)*0.01
- self.b_h = np.zeros((hidden_size, 1))
- self.b_y = np.zeros((output_size, 1))
- def forward(self, x):
+ self.hidden_size = hidden_size
+ self.W_xh = np.random.randn(hidden_size, input_size)*0.01
+ self.W_hh = np.random.randn(hidden_size, hidden_size)*0.01
+ self.W_hy = np.random.randn(output_size, hidden_size)*0.01
+ self.b_h = np.zeros((hidden_size, 1))
+ self.b_y = np.zeros((output_size, 1))
+ def forward(self, x):
"""
Forward pass through the RNN for a given sequence of inputs.
"""
diff --git a/questions/63_implement-the-conjugate-gradient-method-for-solvin/solution.py b/questions/63_implement-the-conjugate-gradient-method-for-solvin/solution.py
index cfc4f6b5..4896802c 100644
--- a/questions/63_implement-the-conjugate-gradient-method-for-solvin/solution.py
+++ b/questions/63_implement-the-conjugate-gradient-method-for-solvin/solution.py
@@ -1,21 +1,22 @@
import numpy as np
-def conjugate_gradient(A: np.array, b: np.array, n: int, x0: np.array=None, tol=1e-8) -> np.array:
+def conjugate_gradient(
+ A: np.array, b: np.array, n: int, x0: np.array = None, tol=1e-8
+) -> np.array:
# calculate initial residual vector
x = np.zeros_like(b)
- r = residual(A, b, x) # residual vector
+ r = residual(A, b, x) # residual vector
rPlus1 = r
- p = r # search direction vector
+ p = r # search direction vector
for i in range(n):
-
# line search step value - this minimizes the error along the current search direction
alp = alpha(A, r, p)
# new x and r based on current p (the search direction vector)
x = x + alp * p
- rPlus1 = r - alp * (A@p)
+ rPlus1 = r - alp * (A @ p)
# calculate beta - this ensures that all vectors are A-orthogonal to each other
bet = beta(r, rPlus1)
@@ -28,27 +29,28 @@ def conjugate_gradient(A: np.array, b: np.array, n: int, x0: np.array=None, tol=
r = rPlus1
# break if less than tolerance
- if np.linalg.norm(residual(A,b,x)) < tol:
+ if np.linalg.norm(residual(A, b, x)) < tol:
break
return x
+
def residual(A: np.array, b: np.array, x: np.array) -> np.array:
# calculate linear system residuals
return b - A @ x
-def alpha(A: np.array, r: np.array, p: np.array) -> float:
+def alpha(A: np.array, r: np.array, p: np.array) -> float:
# calculate step size
alpha_num = np.dot(r, r)
alpha_den = np.dot(p @ A, p)
- return alpha_num/alpha_den
+ return alpha_num / alpha_den
-def beta(r: np.array, r_plus1: np.array) -> float:
+def beta(r: np.array, r_plus1: np.array) -> float:
# calculate direction scaling
beta_num = np.dot(r_plus1, r_plus1)
beta_den = np.dot(r, r)
- return beta_num/beta_den
+ return beta_num / beta_den
diff --git a/questions/63_implement-the-conjugate-gradient-method-for-solvin/starter_code.py b/questions/63_implement-the-conjugate-gradient-method-for-solvin/starter_code.py
index 781f48f0..c60966b6 100644
--- a/questions/63_implement-the-conjugate-gradient-method-for-solvin/starter_code.py
+++ b/questions/63_implement-the-conjugate-gradient-method-for-solvin/starter_code.py
@@ -1,15 +1,16 @@
import numpy as np
+
def conjugate_gradient(A, b, n, x0=None, tol=1e-8):
- """
- Solve the system Ax = b using the Conjugate Gradient method.
+ """
+ Solve the system Ax = b using the Conjugate Gradient method.
- :param A: Symmetric positive-definite matrix
- :param b: Right-hand side vector
- :param n: Maximum number of iterations
- :param x0: Initial guess for solution (default is zero vector)
- :param tol: Convergence tolerance
- :return: Solution vector x
- """
- # calculate initial residual vector
- x = np.zeros_like(b)
+ :param A: Symmetric positive-definite matrix
+ :param b: Right-hand side vector
+ :param n: Maximum number of iterations
+ :param x0: Initial guess for solution (default is zero vector)
+ :param tol: Convergence tolerance
+ :return: Solution vector x
+ """
+ # calculate initial residual vector
+ np.zeros_like(b)
diff --git a/questions/64_implement-gini-impurity-calculation-for-a-set-of-c/solution.py b/questions/64_implement-gini-impurity-calculation-for-a-set-of-c/solution.py
index 3b369812..236ab92f 100644
--- a/questions/64_implement-gini-impurity-calculation-for-a-set-of-c/solution.py
+++ b/questions/64_implement-gini-impurity-calculation-for-a-set-of-c/solution.py
@@ -1,13 +1,10 @@
-import numpy as np
-
def gini_impurity(y: list[int]) -> float:
-
classes = set(y)
n = len(y)
gini_impurity = 0
for cls in classes:
- gini_impurity += (y.count(cls)/n)**2
+ gini_impurity += (y.count(cls) / n) ** 2
- return round(1-gini_impurity,3)
+ return round(1 - gini_impurity, 3)
diff --git a/questions/64_implement-gini-impurity-calculation-for-a-set-of-c/starter_code.py b/questions/64_implement-gini-impurity-calculation-for-a-set-of-c/starter_code.py
index 4ea57fe8..346301af 100644
--- a/questions/64_implement-gini-impurity-calculation-for-a-set-of-c/starter_code.py
+++ b/questions/64_implement-gini-impurity-calculation-for-a-set-of-c/starter_code.py
@@ -1,12 +1,9 @@
-
-import numpy as np
-
def gini_impurity(y):
- """
- Calculate Gini Impurity for a list of class labels.
+ """
+ Calculate Gini Impurity for a list of class labels.
- :param y: List of class labels
- :return: Gini Impurity rounded to three decimal places
- """
- pass
- return round(val,3)
+ :param y: List of class labels
+ :return: Gini Impurity rounded to three decimal places
+ """
+ pass
+ return round(val, 3)
diff --git a/questions/65_implement-compressed-row-sparse-matrix-csr-format-/solution.py b/questions/65_implement-compressed-row-sparse-matrix-csr-format-/solution.py
index 9dd50aea..3ea88117 100644
--- a/questions/65_implement-compressed-row-sparse-matrix-csr-format-/solution.py
+++ b/questions/65_implement-compressed-row-sparse-matrix-csr-format-/solution.py
@@ -1,5 +1,3 @@
-import numpy as np
-
def compressed_row_sparse_matrix(dense_matrix):
vals = []
col_idx = []
diff --git a/questions/65_implement-compressed-row-sparse-matrix-csr-format-/starter_code.py b/questions/65_implement-compressed-row-sparse-matrix-csr-format-/starter_code.py
index 0c731d2d..28c9c294 100644
--- a/questions/65_implement-compressed-row-sparse-matrix-csr-format-/starter_code.py
+++ b/questions/65_implement-compressed-row-sparse-matrix-csr-format-/starter_code.py
@@ -1,10 +1,8 @@
-import numpy as np
-
def compressed_row_sparse_matrix(dense_matrix):
- """
- Convert a dense matrix to its Compressed Row Sparse (CSR) representation.
+ """
+ Convert a dense matrix to its Compressed Row Sparse (CSR) representation.
- :param dense_matrix: 2D list representing a dense matrix
- :return: A tuple containing (values array, column indices array, row pointer array)
- """
- pass
+ :param dense_matrix: 2D list representing a dense matrix
+ :return: A tuple containing (values array, column indices array, row pointer array)
+ """
+ pass
diff --git a/questions/66_implement-orthogonal-projection-of-a-vector-onto-a/solution.py b/questions/66_implement-orthogonal-projection-of-a-vector-onto-a/solution.py
index c3ce7ff2..b10cb195 100644
--- a/questions/66_implement-orthogonal-projection-of-a-vector-onto-a/solution.py
+++ b/questions/66_implement-orthogonal-projection-of-a-vector-onto-a/solution.py
@@ -1,9 +1,11 @@
def dot(v1, v2):
return sum([ax1 * ax2 for ax1, ax2 in zip(v1, v2)])
+
def scalar_mult(scalar, v):
return [scalar * ax for ax in v]
+
def orthogonal_projection(v, L):
L_mag_sq = dot(L, L)
proj_scalar = dot(v, L) / L_mag_sq
diff --git a/questions/66_implement-orthogonal-projection-of-a-vector-onto-a/starter_code.py b/questions/66_implement-orthogonal-projection-of-a-vector-onto-a/starter_code.py
index 4a131145..28cd3912 100644
--- a/questions/66_implement-orthogonal-projection-of-a-vector-onto-a/starter_code.py
+++ b/questions/66_implement-orthogonal-projection-of-a-vector-onto-a/starter_code.py
@@ -1,10 +1,9 @@
-
def orthogonal_projection(v, L):
- """
- Compute the orthogonal projection of vector v onto line L.
+ """
+ Compute the orthogonal projection of vector v onto line L.
- :param v: The vector to be projected
- :param L: The line vector defining the direction of projection
- :return: List representing the projection of v onto L
- """
- pass
+ :param v: The vector to be projected
+ :param L: The line vector defining the direction of projection
+ :return: List representing the projection of v onto L
+ """
+ pass
diff --git a/questions/67_implement-compressed-column-sparse-matrix-format-c/starter_code.py b/questions/67_implement-compressed-column-sparse-matrix-format-c/starter_code.py
index eb9c107a..5840923b 100644
--- a/questions/67_implement-compressed-column-sparse-matrix-format-c/starter_code.py
+++ b/questions/67_implement-compressed-column-sparse-matrix-format-c/starter_code.py
@@ -1,8 +1,8 @@
def compressed_col_sparse_matrix(dense_matrix):
- """
- Convert a dense matrix into its Compressed Column Sparse (CSC) representation.
+ """
+ Convert a dense matrix into its Compressed Column Sparse (CSC) representation.
- :param dense_matrix: List of lists representing the dense matrix
- :return: Tuple of (values, row indices, column pointer)
- """
- pass
+ :param dense_matrix: List of lists representing the dense matrix
+ :return: Tuple of (values, row indices, column pointer)
+ """
+ pass
diff --git a/questions/68_find-the-image-of-a-matrix-using-row-echelon-form/solution.py b/questions/68_find-the-image-of-a-matrix-using-row-echelon-form/solution.py
index 83653e26..1a3684b8 100644
--- a/questions/68_find-the-image-of-a-matrix-using-row-echelon-form/solution.py
+++ b/questions/68_find-the-image-of-a-matrix-using-row-echelon-form/solution.py
@@ -1,6 +1,6 @@
-
import numpy as np
+
def rref(A):
# Convert to float for division operations
A = A.astype(np.float32)
@@ -20,6 +20,7 @@ def rref(A):
A[j] -= A[i] * A[j, i]
return A
+
def find_pivot_columns(A):
n, m = A.shape
pivot_columns = []
@@ -29,6 +30,7 @@ def find_pivot_columns(A):
pivot_columns.append(nonzero[0])
return pivot_columns
+
def matrix_image(A):
# Find the RREF of the matrix
Arref = rref(A)
diff --git a/questions/68_find-the-image-of-a-matrix-using-row-echelon-form/starter_code.py b/questions/68_find-the-image-of-a-matrix-using-row-echelon-form/starter_code.py
index e59e24cb..3f5dbc68 100644
--- a/questions/68_find-the-image-of-a-matrix-using-row-echelon-form/starter_code.py
+++ b/questions/68_find-the-image-of-a-matrix-using-row-echelon-form/starter_code.py
@@ -1,6 +1,3 @@
-
-import numpy as np
-
def matrix_image(A):
- # Write your code here
- pass
+ # Write your code here
+ pass
diff --git a/questions/69_calculate-r-squared-for-regression-analysis/solution.py b/questions/69_calculate-r-squared-for-regression-analysis/solution.py
index 159ac2b1..2986b7f1 100644
--- a/questions/69_calculate-r-squared-for-regression-analysis/solution.py
+++ b/questions/69_calculate-r-squared-for-regression-analysis/solution.py
@@ -1,14 +1,14 @@
-
import numpy as np
+
def r_squared(y_true, y_pred):
"""
Calculate the R-squared (R²) coefficient of determination.
-
+
Args:
y_true (numpy.ndarray): Array of true values
y_pred (numpy.ndarray): Array of predicted values
-
+
Returns:
float: R-squared value rounded to 3 decimal places
"""
diff --git a/questions/69_calculate-r-squared-for-regression-analysis/starter_code.py b/questions/69_calculate-r-squared-for-regression-analysis/starter_code.py
index 5fbe9bb2..b41e4150 100644
--- a/questions/69_calculate-r-squared-for-regression-analysis/starter_code.py
+++ b/questions/69_calculate-r-squared-for-regression-analysis/starter_code.py
@@ -1,6 +1,3 @@
-
-import numpy as np
-
def r_squared(y_true, y_pred):
- # Write your code here
- pass
+ # Write your code here
+ pass
diff --git a/questions/6_calculate-eigenvalues-of-a-matrix/pytorch/solution.py b/questions/6_calculate-eigenvalues-of-a-matrix/pytorch/solution.py
index 7d5c4354..ca98ce86 100644
--- a/questions/6_calculate-eigenvalues-of-a-matrix/pytorch/solution.py
+++ b/questions/6_calculate-eigenvalues-of-a-matrix/pytorch/solution.py
@@ -1,12 +1,15 @@
import torch
+
def calculate_eigenvalues(matrix: torch.Tensor) -> torch.Tensor:
"""
Compute eigenvalues of a 2×2 matrix using PyTorch.
Input: 2×2 tensor; Output: 1-D tensor with the two eigenvalues in ascending order.
"""
- a = matrix[0,0]; b = matrix[0,1]
- c = matrix[1,0]; d = matrix[1,1]
+ a = matrix[0, 0]
+ b = matrix[0, 1]
+ c = matrix[1, 0]
+ d = matrix[1, 1]
trace = a + d
det = a * d - b * c
disc = trace * trace - 4 * det
diff --git a/questions/6_calculate-eigenvalues-of-a-matrix/pytorch/starter_code.py b/questions/6_calculate-eigenvalues-of-a-matrix/pytorch/starter_code.py
index 84d0f873..dbbd6a97 100644
--- a/questions/6_calculate-eigenvalues-of-a-matrix/pytorch/starter_code.py
+++ b/questions/6_calculate-eigenvalues-of-a-matrix/pytorch/starter_code.py
@@ -1,5 +1,6 @@
import torch
+
def calculate_eigenvalues(matrix: torch.Tensor) -> torch.Tensor:
"""
Compute eigenvalues of a 2×2 matrix using PyTorch.
diff --git a/questions/6_calculate-eigenvalues-of-a-matrix/starter_code.py b/questions/6_calculate-eigenvalues-of-a-matrix/starter_code.py
index e197597b..a223bd51 100644
--- a/questions/6_calculate-eigenvalues-of-a-matrix/starter_code.py
+++ b/questions/6_calculate-eigenvalues-of-a-matrix/starter_code.py
@@ -1,2 +1,2 @@
-def calculate_eigenvalues(matrix: list[list[float|int]]) -> list[float]:
- return eigenvalues
+def calculate_eigenvalues(matrix: list[list[float | int]]) -> list[float]:
+ return eigenvalues
diff --git a/questions/6_calculate-eigenvalues-of-a-matrix/tinygrad/solution.py b/questions/6_calculate-eigenvalues-of-a-matrix/tinygrad/solution.py
index b79fcdd6..30fe130e 100644
--- a/questions/6_calculate-eigenvalues-of-a-matrix/tinygrad/solution.py
+++ b/questions/6_calculate-eigenvalues-of-a-matrix/tinygrad/solution.py
@@ -1,13 +1,16 @@
from tinygrad.tensor import Tensor
+
def calculate_eigenvalues_tg(matrix) -> Tensor:
"""
Compute eigenvalues of a 2×2 matrix using tinygrad.
Input: 2×2 list, NumPy array, or Tensor; Output: 1-D Tensor with eigenvalues in ascending order.
"""
m = Tensor(matrix).float()
- a = m[0,0]; b = m[0,1]
- c = m[1,0]; d = m[1,1]
+ a = m[0, 0]
+ b = m[0, 1]
+ c = m[1, 0]
+ d = m[1, 1]
trace = a + d
det = a * d - b * c
disc = trace * trace - 4 * det
diff --git a/questions/6_calculate-eigenvalues-of-a-matrix/tinygrad/starter_code.py b/questions/6_calculate-eigenvalues-of-a-matrix/tinygrad/starter_code.py
index 7645439f..653f1a5b 100644
--- a/questions/6_calculate-eigenvalues-of-a-matrix/tinygrad/starter_code.py
+++ b/questions/6_calculate-eigenvalues-of-a-matrix/tinygrad/starter_code.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def calculate_eigenvalues_tg(matrix) -> Tensor:
"""
Compute eigenvalues of a 2×2 matrix using tinygrad.
diff --git a/questions/70_calculate-image-brightness/solution.py b/questions/70_calculate-image-brightness/solution.py
index 15b70614..d26d4bc3 100644
--- a/questions/70_calculate-image-brightness/solution.py
+++ b/questions/70_calculate-image-brightness/solution.py
@@ -1,4 +1,3 @@
-
def calculate_brightness(img):
# Check if image is empty or has no columns
if not img or not img[0]:
diff --git a/questions/70_calculate-image-brightness/starter_code.py b/questions/70_calculate-image-brightness/starter_code.py
index e5dfa325..f8fb6e94 100644
--- a/questions/70_calculate-image-brightness/starter_code.py
+++ b/questions/70_calculate-image-brightness/starter_code.py
@@ -1,4 +1,3 @@
-
def calculate_brightness(img):
- # Write your code here
- pass
+ # Write your code here
+ pass
diff --git a/questions/71_calculate-root-mean-square-error-rmse/solution.py b/questions/71_calculate-root-mean-square-error-rmse/solution.py
index a0d527f2..f72c8e4f 100644
--- a/questions/71_calculate-root-mean-square-error-rmse/solution.py
+++ b/questions/71_calculate-root-mean-square-error-rmse/solution.py
@@ -1,6 +1,6 @@
-
import numpy as np
+
def rmse(y_true, y_pred):
if y_true.shape != y_pred.shape:
raise ValueError("Arrays must have the same shape")
diff --git a/questions/71_calculate-root-mean-square-error-rmse/starter_code.py b/questions/71_calculate-root-mean-square-error-rmse/starter_code.py
index 4084991e..4bfedc7c 100644
--- a/questions/71_calculate-root-mean-square-error-rmse/starter_code.py
+++ b/questions/71_calculate-root-mean-square-error-rmse/starter_code.py
@@ -1,6 +1,3 @@
-
-import numpy as np
-
def rmse(y_true, y_pred):
- # Write your code here
- return round(rmse_res,3)
+ # Write your code here
+ return round(rmse_res, 3)
diff --git a/questions/72_calculate-jaccard-index-for-binary-classification/solution.py b/questions/72_calculate-jaccard-index-for-binary-classification/solution.py
index ce640a5e..e2087caa 100644
--- a/questions/72_calculate-jaccard-index-for-binary-classification/solution.py
+++ b/questions/72_calculate-jaccard-index-for-binary-classification/solution.py
@@ -1,6 +1,6 @@
-
import numpy as np
+
def jaccard_index(y_true, y_pred):
intersection = np.sum((y_true == 1) & (y_pred == 1))
union = np.sum((y_true == 1) | (y_pred == 1))
diff --git a/questions/72_calculate-jaccard-index-for-binary-classification/starter_code.py b/questions/72_calculate-jaccard-index-for-binary-classification/starter_code.py
index f00476ed..b2109807 100644
--- a/questions/72_calculate-jaccard-index-for-binary-classification/starter_code.py
+++ b/questions/72_calculate-jaccard-index-for-binary-classification/starter_code.py
@@ -1,6 +1,3 @@
-
-import numpy as np
-
def jaccard_index(y_true, y_pred):
- # Write your code here
- return round(result, 3)
+ # Write your code here
+ return round(result, 3)
diff --git a/questions/73_calculate-dice-score-for-classification/solution.py b/questions/73_calculate-dice-score-for-classification/solution.py
index 65a3928c..1f222c47 100644
--- a/questions/73_calculate-dice-score-for-classification/solution.py
+++ b/questions/73_calculate-dice-score-for-classification/solution.py
@@ -1,6 +1,6 @@
-
import numpy as np
+
def dice_score(y_true, y_pred):
intersection = np.logical_and(y_true, y_pred).sum()
true_sum = y_true.sum()
diff --git a/questions/73_calculate-dice-score-for-classification/starter_code.py b/questions/73_calculate-dice-score-for-classification/starter_code.py
index 146784ea..fd430df4 100644
--- a/questions/73_calculate-dice-score-for-classification/starter_code.py
+++ b/questions/73_calculate-dice-score-for-classification/starter_code.py
@@ -1,6 +1,3 @@
-
-import numpy as np
-
def dice_score(y_true, y_pred):
- # Write your code here
- return round(res, 3)
+ # Write your code here
+ return round(res, 3)
diff --git a/questions/74_create-composite-hypervector-for-a-dataset-row/solution.py b/questions/74_create-composite-hypervector-for-a-dataset-row/solution.py
index 39887062..00a596d7 100644
--- a/questions/74_create-composite-hypervector-for-a-dataset-row/solution.py
+++ b/questions/74_create-composite-hypervector-for-a-dataset-row/solution.py
@@ -1,23 +1,28 @@
-
import numpy as np
+
def create_hv(dim):
return np.random.choice([-1, 1], dim)
+
def create_col_hvs(dim, seed):
np.random.seed(seed)
return create_hv(dim), create_hv(dim)
+
def bind(hv1, hv2):
return hv1 * hv2
+
def bundle(hvs, dim):
bundled = np.sum(list(hvs.values()), axis=0)
return sign(bundled)
+
def sign(vector, threshold=0.01):
return np.array([1 if v >= 0 else -1 for v in vector])
+
def create_row_hv(row, dim, random_seeds):
row_hvs = {col: bind(*create_col_hvs(dim, random_seeds[col])) for col in row.keys()}
return bundle(row_hvs, dim)
diff --git a/questions/74_create-composite-hypervector-for-a-dataset-row/starter_code.py b/questions/74_create-composite-hypervector-for-a-dataset-row/starter_code.py
index 94223eee..e6f56fa3 100644
--- a/questions/74_create-composite-hypervector-for-a-dataset-row/starter_code.py
+++ b/questions/74_create-composite-hypervector-for-a-dataset-row/starter_code.py
@@ -1,6 +1,3 @@
-
-import numpy as np
-
def create_row_hv(row, dim, random_seeds):
- # Write your code here
- pass
+ # Write your code here
+ pass
diff --git a/questions/75_generate-a-confusion-matrix-for-binary-classificat/solution.py b/questions/75_generate-a-confusion-matrix-for-binary-classificat/solution.py
index 4cded5f8..b030bfbc 100644
--- a/questions/75_generate-a-confusion-matrix-for-binary-classificat/solution.py
+++ b/questions/75_generate-a-confusion-matrix-for-binary-classificat/solution.py
@@ -1,6 +1,6 @@
-
from collections import Counter
+
def confusion_matrix(data):
# Count all occurrences
counts = Counter(tuple(pair) for pair in data)
diff --git a/questions/75_generate-a-confusion-matrix-for-binary-classificat/starter_code.py b/questions/75_generate-a-confusion-matrix-for-binary-classificat/starter_code.py
index ff8f4564..fcdabe56 100644
--- a/questions/75_generate-a-confusion-matrix-for-binary-classificat/starter_code.py
+++ b/questions/75_generate-a-confusion-matrix-for-binary-classificat/starter_code.py
@@ -1,6 +1,3 @@
-
-from collections import Counter
-
def confusion_matrix(data):
- # Implement the function here
- pass
+ # Implement the function here
+ pass
diff --git a/questions/76_calculate-cosine-similarity-between-vectors/solution.py b/questions/76_calculate-cosine-similarity-between-vectors/solution.py
index 7f008790..73202825 100644
--- a/questions/76_calculate-cosine-similarity-between-vectors/solution.py
+++ b/questions/76_calculate-cosine-similarity-between-vectors/solution.py
@@ -1,6 +1,6 @@
-
import numpy as np
+
def cosine_similarity(v1, v2):
if v1.shape != v2.shape:
raise ValueError("Arrays must have the same shape")
diff --git a/questions/76_calculate-cosine-similarity-between-vectors/starter_code.py b/questions/76_calculate-cosine-similarity-between-vectors/starter_code.py
index 12c19667..c8d67387 100644
--- a/questions/76_calculate-cosine-similarity-between-vectors/starter_code.py
+++ b/questions/76_calculate-cosine-similarity-between-vectors/starter_code.py
@@ -1,6 +1,3 @@
-
-import numpy as np
-
def cosine_similarity(v1, v2):
- # Implement your code here
- pass
+ # Implement your code here
+ pass
diff --git a/questions/77_calculate-performance-metrics-for-a-classification/solution.py b/questions/77_calculate-performance-metrics-for-a-classification/solution.py
index 46639dcb..c9620a40 100644
--- a/questions/77_calculate-performance-metrics-for-a-classification/solution.py
+++ b/questions/77_calculate-performance-metrics-for-a-classification/solution.py
@@ -1,6 +1,6 @@
-
from collections import Counter
+
def performance_metrics(actual: list[int], predicted: list[int]) -> tuple:
data = list(zip(actual, predicted))
counts = Counter(tuple(pair) for pair in data)
@@ -12,4 +12,10 @@ def performance_metrics(actual: list[int], predicted: list[int]) -> tuple:
f1 = 2 * precision * recall / (precision + recall)
negativePredictive = TN / (TN + FN)
specificity = TN / (TN + FP)
- return confusion_matrix, round(accuracy, 3), round(f1, 3), round(specificity, 3), round(negativePredictive, 3)
+ return (
+ confusion_matrix,
+ round(accuracy, 3),
+ round(f1, 3),
+ round(specificity, 3),
+ round(negativePredictive, 3),
+ )
diff --git a/questions/77_calculate-performance-metrics-for-a-classification/starter_code.py b/questions/77_calculate-performance-metrics-for-a-classification/starter_code.py
index 667cc658..be22b9dd 100644
--- a/questions/77_calculate-performance-metrics-for-a-classification/starter_code.py
+++ b/questions/77_calculate-performance-metrics-for-a-classification/starter_code.py
@@ -1,4 +1,9 @@
-
def performance_metrics(actual: list[int], predicted: list[int]) -> tuple:
- # Implement your code here
- return confusion_matrix, round(accuracy, 3), round(f1, 3), round(specificity, 3), round(negativePredictive, 3)
+ # Implement your code here
+ return (
+ confusion_matrix,
+ round(accuracy, 3),
+ round(f1, 3),
+ round(specificity, 3),
+ round(negativePredictive, 3),
+ )
diff --git a/questions/78_descriptive-statistics-calculator/solution.py b/questions/78_descriptive-statistics-calculator/solution.py
index 7d4b8506..d537c175 100644
--- a/questions/78_descriptive-statistics-calculator/solution.py
+++ b/questions/78_descriptive-statistics-calculator/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def descriptive_statistics(data):
"""
Calculate various descriptive statistics metrics for a given dataset.
@@ -37,12 +38,12 @@ def descriptive_statistics(data):
"mean": mean,
"median": median,
"mode": mode,
- "variance": np.round(variance,4),
- "standard_deviation": np.round(std_dev,4),
+ "variance": np.round(variance, 4),
+ "standard_deviation": np.round(std_dev, 4),
"25th_percentile": percentiles[0],
"50th_percentile": percentiles[1],
"75th_percentile": percentiles[2],
- "interquartile_range": iqr
+ "interquartile_range": iqr,
}
return stats_dict
diff --git a/questions/78_descriptive-statistics-calculator/starter_code.py b/questions/78_descriptive-statistics-calculator/starter_code.py
index be9c5ca4..30c56cdc 100644
--- a/questions/78_descriptive-statistics-calculator/starter_code.py
+++ b/questions/78_descriptive-statistics-calculator/starter_code.py
@@ -1,15 +1,17 @@
-import numpy as np
+import numpy as np
+
+
def descriptive_statistics(data):
- # Your code here
- stats_dict = {
+ # Your code here
+ {
"mean": mean,
"median": median,
"mode": mode,
- "variance": np.round(variance,4),
- "standard_deviation": np.round(std_dev,4),
+ "variance": np.round(variance, 4),
+ "standard_deviation": np.round(std_dev, 4),
"25th_percentile": percentiles[0],
"50th_percentile": percentiles[1],
"75th_percentile": percentiles[2],
- "interquartile_range": iqr
+ "interquartile_range": iqr,
}
- return {}
+ return {}
diff --git a/questions/79_binomial-distribution-probability/solution.py b/questions/79_binomial-distribution-probability/solution.py
index 13d5c98d..14e6770c 100644
--- a/questions/79_binomial-distribution-probability/solution.py
+++ b/questions/79_binomial-distribution-probability/solution.py
@@ -1,5 +1,6 @@
import math
+
def binomial_probability(n, k, p):
"""
Calculate the probability of achieving exactly k successes in n independent Bernoulli trials,
@@ -12,6 +13,6 @@ def binomial_probability(n, k, p):
# Calculate binomial coefficient (n choose k)
binomial_coeff = math.comb(n, k)
# Calculate the probability using the binomial formula
- probability = binomial_coeff * (p ** k) * ((1 - p) ** (n - k))
+ probability = binomial_coeff * (p**k) * ((1 - p) ** (n - k))
# Return the probability, rounded to five decimal places
return round(probability, 5)
diff --git a/questions/79_binomial-distribution-probability/starter_code.py b/questions/79_binomial-distribution-probability/starter_code.py
index b2f0f1b0..190fb9cb 100644
--- a/questions/79_binomial-distribution-probability/starter_code.py
+++ b/questions/79_binomial-distribution-probability/starter_code.py
@@ -1,9 +1,7 @@
-import math
-
def binomial_probability(n, k, p):
- """
+ """
Calculate the probability of achieving exactly k successes in n independent Bernoulli trials,
each with probability p of success, using the Binomial distribution formula.
"""
- # Your code here
- return round(probability, 5)
+ # Your code here
+ return round(probability, 5)
diff --git a/questions/7_matrix-transformation/pytorch/solution.py b/questions/7_matrix-transformation/pytorch/solution.py
index 7708d4d8..380d23be 100644
--- a/questions/7_matrix-transformation/pytorch/solution.py
+++ b/questions/7_matrix-transformation/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def transform_matrix(A, T, S) -> torch.Tensor:
"""
Perform the change-of-basis transform T⁻¹ A S and round to 3 decimals using PyTorch.
@@ -10,7 +11,7 @@ def transform_matrix(A, T, S) -> torch.Tensor:
T_t = torch.as_tensor(T, dtype=torch.float)
S_t = torch.as_tensor(S, dtype=torch.float)
if torch.det(T_t) == 0 or torch.det(S_t) == 0:
- return torch.tensor(-1.)
+ return torch.tensor(-1.0)
T_inv = torch.inverse(T_t)
out = T_inv @ A_t @ S_t
return torch.round(out * 1000) / 1000
diff --git a/questions/7_matrix-transformation/pytorch/starter_code.py b/questions/7_matrix-transformation/pytorch/starter_code.py
index 8edada84..244a88d3 100644
--- a/questions/7_matrix-transformation/pytorch/starter_code.py
+++ b/questions/7_matrix-transformation/pytorch/starter_code.py
@@ -1,13 +1,14 @@
import torch
+
def transform_matrix(A, T, S) -> torch.Tensor:
"""
Perform the change-of-basis transform T⁻¹ A S and round to 3 decimals using PyTorch.
Inputs A, T, S can be Python lists, NumPy arrays, or torch Tensors.
Returns a 2×2 tensor or tensor(-1.) if T or S is singular.
"""
- A_t = torch.as_tensor(A, dtype=torch.float)
- T_t = torch.as_tensor(T, dtype=torch.float)
- S_t = torch.as_tensor(S, dtype=torch.float)
+ torch.as_tensor(A, dtype=torch.float)
+ torch.as_tensor(T, dtype=torch.float)
+ torch.as_tensor(S, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/7_matrix-transformation/solution.py b/questions/7_matrix-transformation/solution.py
index 08e8482d..234ad023 100644
--- a/questions/7_matrix-transformation/solution.py
+++ b/questions/7_matrix-transformation/solution.py
@@ -1,20 +1,23 @@
import numpy as np
-def transform_matrix(A: list[list[int|float]], T: list[list[int|float]], S: list[list[int|float]]) -> list[list[int|float]]:
+
+def transform_matrix(
+ A: list[list[int | float]], T: list[list[int | float]], S: list[list[int | float]]
+) -> list[list[int | float]]:
# Convert to numpy arrays for easier manipulation
A = np.array(A, dtype=float)
T = np.array(T, dtype=float)
S = np.array(S, dtype=float)
-
+
# Check if the matrices T and S are invertible
if np.linalg.det(T) == 0 or np.linalg.det(S) == 0:
# raise ValueError("The matrices T and/or S are not invertible.")
return -1
-
+
# Compute the inverse of T
T_inv = np.linalg.inv(T)
# Perform the matrix transformation; use @ for better readability
transformed_matrix = np.round(T_inv @ A @ S, 3)
-
+
return transformed_matrix.tolist()
diff --git a/questions/7_matrix-transformation/starter_code.py b/questions/7_matrix-transformation/starter_code.py
index 075d3b6d..bfac63cf 100644
--- a/questions/7_matrix-transformation/starter_code.py
+++ b/questions/7_matrix-transformation/starter_code.py
@@ -1,4 +1,4 @@
-import numpy as np
-
-def transform_matrix(A: list[list[int|float]], T: list[list[int|float]], S: list[list[int|float]]) -> list[list[int|float]]:
- return transformed_matrix
+def transform_matrix(
+ A: list[list[int | float]], T: list[list[int | float]], S: list[list[int | float]]
+) -> list[list[int | float]]:
+ return transformed_matrix
diff --git a/questions/7_matrix-transformation/tinygrad/solution.py b/questions/7_matrix-transformation/tinygrad/solution.py
index 31048e70..7b103fa4 100644
--- a/questions/7_matrix-transformation/tinygrad/solution.py
+++ b/questions/7_matrix-transformation/tinygrad/solution.py
@@ -1,6 +1,7 @@
import numpy as np
from tinygrad.tensor import Tensor
+
def transform_matrix_tg(A, T, S) -> Tensor:
"""
Perform the change-of-basis transform T⁻¹ A S for 2×2 matrices using tinygrad.
@@ -11,12 +12,12 @@ def transform_matrix_tg(A, T, S) -> Tensor:
T_t = Tensor(T).float()
S_t = Tensor(S).float()
# manual 2×2 determinant
- detT = T_t[0,0]*T_t[1,1] - T_t[0,1]*T_t[1,0]
- detS = S_t[0,0]*S_t[1,1] - S_t[0,1]*S_t[1,0]
+ detT = T_t[0, 0] * T_t[1, 1] - T_t[0, 1] * T_t[1, 0]
+ detS = S_t[0, 0] * S_t[1, 1] - S_t[0, 1] * S_t[1, 0]
if detT.numpy() == 0 or detS.numpy() == 0:
- return Tensor(-1.)
+ return Tensor(-1.0)
# inverse of 2×2
- a,b,c,d = T_t[0,0], T_t[0,1], T_t[1,0], T_t[1,1]
+ a, b, c, d = T_t[0, 0], T_t[0, 1], T_t[1, 0], T_t[1, 1]
T_inv = Tensor([[d, -b], [-c, a]]) / detT
out = T_inv.matmul(A_t).matmul(S_t)
# round via NumPy then wrap back
diff --git a/questions/7_matrix-transformation/tinygrad/starter_code.py b/questions/7_matrix-transformation/tinygrad/starter_code.py
index 8e24281b..b1f6680f 100644
--- a/questions/7_matrix-transformation/tinygrad/starter_code.py
+++ b/questions/7_matrix-transformation/tinygrad/starter_code.py
@@ -1,13 +1,14 @@
from tinygrad.tensor import Tensor
+
def transform_matrix_tg(A, T, S) -> Tensor:
"""
Perform the change-of-basis transform T⁻¹ A S for 2×2 matrices using tinygrad.
Inputs A, T, S can be Python lists, NumPy arrays, or tinygrad Tensors.
Returns a 2×2 Tensor or Tensor(-1.) if T or S is singular.
"""
- A_t = Tensor(A).float()
- T_t = Tensor(T).float()
- S_t = Tensor(S).float()
+ Tensor(A).float()
+ Tensor(T).float()
+ Tensor(S).float()
# Your implementation here
pass
diff --git a/questions/80_normal-distribution-pdf-calculator/solution.py b/questions/80_normal-distribution-pdf-calculator/solution.py
index f0d49ec9..4e06bfea 100644
--- a/questions/80_normal-distribution-pdf-calculator/solution.py
+++ b/questions/80_normal-distribution-pdf-calculator/solution.py
@@ -1,5 +1,6 @@
import math
+
def normal_pdf(x, mean, std_dev):
"""
Calculate the probability density function (PDF) of the normal distribution.
@@ -9,5 +10,5 @@ def normal_pdf(x, mean, std_dev):
:return: The PDF value for the given x.
"""
coefficient = 1 / (math.sqrt(2 * math.pi) * std_dev)
- exponent = math.exp(-((x - mean) ** 2) / (2 * std_dev ** 2))
+ exponent = math.exp(-((x - mean) ** 2) / (2 * std_dev**2))
return round(coefficient * exponent, 5)
diff --git a/questions/80_normal-distribution-pdf-calculator/starter_code.py b/questions/80_normal-distribution-pdf-calculator/starter_code.py
index eb259558..7e84deb5 100644
--- a/questions/80_normal-distribution-pdf-calculator/starter_code.py
+++ b/questions/80_normal-distribution-pdf-calculator/starter_code.py
@@ -1,12 +1,10 @@
-import math
-
def normal_pdf(x, mean, std_dev):
- """
- Calculate the probability density function (PDF) of the normal distribution.
- :param x: The value at which the PDF is evaluated.
- :param mean: The mean (μ) of the distribution.
- :param std_dev: The standard deviation (σ) of the distribution.
- """
- # Your code here
- pass
- return round(val,5)
+ """
+ Calculate the probability density function (PDF) of the normal distribution.
+ :param x: The value at which the PDF is evaluated.
+ :param mean: The mean (μ) of the distribution.
+ :param std_dev: The standard deviation (σ) of the distribution.
+ """
+ # Your code here
+ pass
+ return round(val, 5)
diff --git a/questions/81_poisson-distribution-probability-calculator/solution.py b/questions/81_poisson-distribution-probability-calculator/solution.py
index c43e9dfe..02060981 100644
--- a/questions/81_poisson-distribution-probability-calculator/solution.py
+++ b/questions/81_poisson-distribution-probability-calculator/solution.py
@@ -1,5 +1,6 @@
import math
+
def poisson_probability(k, lam):
"""
Calculate the probability of observing exactly k events in a fixed interval,
@@ -9,6 +10,6 @@ def poisson_probability(k, lam):
:return: Probability of k events occurring
"""
# Calculate the Poisson probability using the formula
- probability = (lam ** k) * math.exp(-lam) / math.factorial(k)
+ probability = (lam**k) * math.exp(-lam) / math.factorial(k)
# Return the probability, rounded to five decimal places
return round(probability, 5)
diff --git a/questions/81_poisson-distribution-probability-calculator/starter_code.py b/questions/81_poisson-distribution-probability-calculator/starter_code.py
index cf0abc0d..bc0c9039 100644
--- a/questions/81_poisson-distribution-probability-calculator/starter_code.py
+++ b/questions/81_poisson-distribution-probability-calculator/starter_code.py
@@ -1,12 +1,10 @@
-import math
-
def poisson_probability(k, lam):
- """
- Calculate the probability of observing exactly k events in a fixed interval,
- given the mean rate of events lam, using the Poisson distribution formula.
- :param k: Number of events (non-negative integer)
- :param lam: The average rate (mean) of occurrences in a fixed interval
- """
- # Your code here
- pass
- return round(val,5)
+ """
+ Calculate the probability of observing exactly k events in a fixed interval,
+ given the mean rate of events lam, using the Poisson distribution formula.
+ :param k: Number of events (non-negative integer)
+ :param lam: The average rate (mean) of occurrences in a fixed interval
+ """
+ # Your code here
+ pass
+ return round(val, 5)
diff --git a/questions/82_grayscale-image-contrast-calculator/solution.py b/questions/82_grayscale-image-contrast-calculator/solution.py
index ab98171c..8d20f096 100644
--- a/questions/82_grayscale-image-contrast-calculator/solution.py
+++ b/questions/82_grayscale-image-contrast-calculator/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def calculate_contrast(img):
"""
Calculate the contrast of a grayscale image.
diff --git a/questions/82_grayscale-image-contrast-calculator/starter_code.py b/questions/82_grayscale-image-contrast-calculator/starter_code.py
index 5f2d03be..25f07d73 100644
--- a/questions/82_grayscale-image-contrast-calculator/starter_code.py
+++ b/questions/82_grayscale-image-contrast-calculator/starter_code.py
@@ -1,10 +1,8 @@
-import numpy as np
-
def calculate_contrast(img) -> int:
- """
- Calculate the contrast of a grayscale image.
- Args:
- img (numpy.ndarray): 2D array representing a grayscale image with pixel values between 0 and 255.
- """
- # Your code here
- pass
+ """
+ Calculate the contrast of a grayscale image.
+ Args:
+ img (numpy.ndarray): 2D array representing a grayscale image with pixel values between 0 and 255.
+ """
+ # Your code here
+ pass
diff --git a/questions/83_dot-product-calculator/solution.py b/questions/83_dot-product-calculator/solution.py
index 3adf233a..722fafd2 100644
--- a/questions/83_dot-product-calculator/solution.py
+++ b/questions/83_dot-product-calculator/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def calculate_dot_product(vec1, vec2):
"""
Calculate the dot product of two vectors.
diff --git a/questions/83_dot-product-calculator/starter_code.py b/questions/83_dot-product-calculator/starter_code.py
index 7c6e3f29..13533d74 100644
--- a/questions/83_dot-product-calculator/starter_code.py
+++ b/questions/83_dot-product-calculator/starter_code.py
@@ -1,11 +1,9 @@
-import numpy as np
-
def calculate_dot_product(vec1, vec2) -> float:
- """
- Calculate the dot product of two vectors.
- Args:
- vec1 (numpy.ndarray): 1D array representing the first vector.
- vec2 (numpy.ndarray): 1D array representing the second vector.
- """
- # Your code here
- pass
+ """
+ Calculate the dot product of two vectors.
+ Args:
+ vec1 (numpy.ndarray): 1D array representing the first vector.
+ vec2 (numpy.ndarray): 1D array representing the second vector.
+ """
+ # Your code here
+ pass
diff --git a/questions/84_phi-transformation-for-polynomial-features/solution.py b/questions/84_phi-transformation-for-polynomial-features/solution.py
index 631462e1..514f317e 100644
--- a/questions/84_phi-transformation-for-polynomial-features/solution.py
+++ b/questions/84_phi-transformation-for-polynomial-features/solution.py
@@ -1,16 +1,17 @@
import numpy as np
+
def phi_transform(data: list[float], degree: int) -> list[list[float]]:
- """
- Perform a Phi Transformation to map input features into a higher-dimensional space by generating polynomial features.
+ """
+ Perform a Phi Transformation to map input features into a higher-dimensional space by generating polynomial features.
- Args:
- data (list[float]): A list of numerical values to transform.
- degree (int): The degree of the polynomial expansion.
+ Args:
+ data (list[float]): A list of numerical values to transform.
+ degree (int): The degree of the polynomial expansion.
- Returns:
- list[list[float]]: A nested list where each inner list represents the transformed features of a data point.
- """
- if degree < 0 or not data:
- return []
- return np.array([[x ** i for i in range(degree + 1)] for x in data]).tolist()
+ Returns:
+ list[list[float]]: A nested list where each inner list represents the transformed features of a data point.
+ """
+ if degree < 0 or not data:
+ return []
+ return np.array([[x**i for i in range(degree + 1)] for x in data]).tolist()
diff --git a/questions/84_phi-transformation-for-polynomial-features/starter_code.py b/questions/84_phi-transformation-for-polynomial-features/starter_code.py
index d4f6ea52..7adfb3df 100644
--- a/questions/84_phi-transformation-for-polynomial-features/starter_code.py
+++ b/questions/84_phi-transformation-for-polynomial-features/starter_code.py
@@ -1,13 +1,11 @@
-import numpy as np
-
def phi_transform(data: list[float], degree: int) -> list[list[float]]:
- """
- Perform a Phi Transformation to map input features into a higher-dimensional space by generating polynomial features.
+ """
+ Perform a Phi Transformation to map input features into a higher-dimensional space by generating polynomial features.
- Args:
- data (list[float]): A list of numerical values to transform.
- degree (int): The degree of the polynomial expansion.
+ Args:
+ data (list[float]): A list of numerical values to transform.
+ degree (int): The degree of the polynomial expansion.
- """
- # Your code here
- pass
+ """
+ # Your code here
+ pass
diff --git a/questions/85_positional-encoding-calculator/solution.py b/questions/85_positional-encoding-calculator/solution.py
index 8be23d67..0ba4b88c 100644
--- a/questions/85_positional-encoding-calculator/solution.py
+++ b/questions/85_positional-encoding-calculator/solution.py
@@ -1,7 +1,7 @@
import numpy as np
+
def pos_encoding(position: int, d_model: int):
-
if position == 0 or d_model <= 0:
return -1
diff --git a/questions/85_positional-encoding-calculator/starter_code.py b/questions/85_positional-encoding-calculator/starter_code.py
index 950eb203..494f29b7 100644
--- a/questions/85_positional-encoding-calculator/starter_code.py
+++ b/questions/85_positional-encoding-calculator/starter_code.py
@@ -1,6 +1,7 @@
import numpy as np
+
def pos_encoding(position: int, d_model: int):
- # Your code here
- pos_encoding = np.float16(pos_encoding)
- return pos_encoding
+ # Your code here
+ pos_encoding = np.float16(pos_encoding)
+ return pos_encoding
diff --git a/questions/86_detect-overfitting-or-underfitting/starter_code.py b/questions/86_detect-overfitting-or-underfitting/starter_code.py
index 07c9e2a5..5666b664 100644
--- a/questions/86_detect-overfitting-or-underfitting/starter_code.py
+++ b/questions/86_detect-overfitting-or-underfitting/starter_code.py
@@ -1,9 +1,9 @@
def model_fit_quality(training_accuracy, test_accuracy):
- """
- Determine if the model is overfitting, underfitting, or a good fit based on training and test accuracy.
- :param training_accuracy: float, training accuracy of the model (0 <= training_accuracy <= 1)
- :param test_accuracy: float, test accuracy of the model (0 <= test_accuracy <= 1)
- :return: int, one of '1', '-1', or '0'.
- """
- # Your code here
- pass
+ """
+ Determine if the model is overfitting, underfitting, or a good fit based on training and test accuracy.
+ :param training_accuracy: float, training accuracy of the model (0 <= training_accuracy <= 1)
+ :param test_accuracy: float, test accuracy of the model (0 <= test_accuracy <= 1)
+ :return: int, one of '1', '-1', or '0'.
+ """
+ # Your code here
+ pass
diff --git a/questions/87_adam-optimizer/solution.py b/questions/87_adam-optimizer/solution.py
index 9264cb23..c74ec039 100644
--- a/questions/87_adam-optimizer/solution.py
+++ b/questions/87_adam-optimizer/solution.py
@@ -1,6 +1,9 @@
import numpy as np
-def adam_optimizer(parameter, grad, m, v, t, learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8):
+
+def adam_optimizer(
+ parameter, grad, m, v, t, learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8
+):
"""
Update parameters using the Adam optimizer.
Adjusts the learning rate based on the moving averages of the gradient and squared gradient.
@@ -31,4 +34,4 @@ def adam_optimizer(parameter, grad, m, v, t, learning_rate=0.001, beta1=0.9, bet
update = learning_rate * m_hat / (np.sqrt(v_hat) + epsilon)
parameter = parameter - update
- return np.round(parameter,5), np.round(m,5), np.round(v,5)
+ return np.round(parameter, 5), np.round(m, 5), np.round(v, 5)
diff --git a/questions/87_adam-optimizer/starter_code.py b/questions/87_adam-optimizer/starter_code.py
index 30a72312..4839e688 100644
--- a/questions/87_adam-optimizer/starter_code.py
+++ b/questions/87_adam-optimizer/starter_code.py
@@ -1,19 +1,22 @@
import numpy as np
-def adam_optimizer(parameter, grad, m, v, t, learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8):
- """
- Update parameters using the Adam optimizer.
- Adjusts the learning rate based on the moving averages of the gradient and squared gradient.
- :param parameter: Current parameter value
- :param grad: Current gradient
- :param m: First moment estimate
- :param v: Second moment estimate
- :param t: Current timestep
- :param learning_rate: Learning rate (default=0.001)
- :param beta1: First moment decay rate (default=0.9)
- :param beta2: Second moment decay rate (default=0.999)
- :param epsilon: Small constant for numerical stability (default=1e-8)
- :return: tuple: (updated_parameter, updated_m, updated_v)
- """
- # Your code here
- return np.round(parameter,5), np.round(m,5), np.round(v,5)
+
+def adam_optimizer(
+ parameter, grad, m, v, t, learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8
+):
+ """
+ Update parameters using the Adam optimizer.
+ Adjusts the learning rate based on the moving averages of the gradient and squared gradient.
+ :param parameter: Current parameter value
+ :param grad: Current gradient
+ :param m: First moment estimate
+ :param v: Second moment estimate
+ :param t: Current timestep
+ :param learning_rate: Learning rate (default=0.001)
+ :param beta1: First moment decay rate (default=0.9)
+ :param beta2: Second moment decay rate (default=0.999)
+ :param epsilon: Small constant for numerical stability (default=1e-8)
+ :return: tuple: (updated_parameter, updated_m, updated_v)
+ """
+ # Your code here
+ return np.round(parameter, 5), np.round(m, 5), np.round(v, 5)
diff --git a/questions/88_gpt-2-text-generation/solution.py b/questions/88_gpt-2-text-generation/solution.py
index 56f70e93..df843321 100644
--- a/questions/88_gpt-2-text-generation/solution.py
+++ b/questions/88_gpt-2-text-generation/solution.py
@@ -1,51 +1,64 @@
import numpy as np
+
def gelu(x):
return 0.5 * x * (1 + np.tanh(np.sqrt(2 / np.pi) * (x + 0.044715 * x**3)))
+
def softmax(x):
exp_x = np.exp(x - np.max(x, axis=-1, keepdims=True))
return exp_x / np.sum(exp_x, axis=-1, keepdims=True)
+
def layer_norm(x, g, b, eps=1e-5):
mean = np.mean(x, axis=-1, keepdims=True)
variance = np.var(x, axis=-1, keepdims=True)
return g * (x - mean) / np.sqrt(variance + eps) + b
+
def linear(x, w, b):
return x @ w + b
+
def ffn(x, c_fc, c_proj):
return linear(gelu(linear(x, **c_fc)), **c_proj)
+
def attention(q, k, v, mask):
return softmax(q @ k.T / np.sqrt(q.shape[-1]) + mask) @ v
+
def mha(x, c_attn, c_proj, n_head):
x = linear(x, **c_attn)
- qkv_heads = list(map(lambda x: np.split(x, n_head, axis=-1), np.split(x, 3, axis=-1)))
+ qkv_heads = list(
+ map(lambda x: np.split(x, n_head, axis=-1), np.split(x, 3, axis=-1))
+ )
causal_mask = (1 - np.tri(x.shape[0], dtype=x.dtype)) * -1e10
out_heads = [attention(q, k, v, causal_mask) for q, k, v in zip(*qkv_heads)]
x = linear(np.hstack(out_heads), **c_proj)
return x
+
def transformer_block(x, mlp, attn, ln_1, ln_2, n_head):
x = x + mha(layer_norm(x, **ln_1), **attn, n_head=n_head)
x = x + ffn(layer_norm(x, **ln_2), **mlp)
return x
+
def gpt2(inputs, wte, wpe, blocks, ln_f, n_head):
x = wte[inputs] + wpe[range(len(inputs))]
for block in blocks:
x = transformer_block(x, **block, n_head=n_head)
return layer_norm(x, **ln_f) @ wte.T
+
def generate(inputs, params, n_head, n_tokens_to_generate):
for _ in range(n_tokens_to_generate):
logits = gpt2(inputs, **params, n_head=n_head)
next_id = np.argmax(logits[-1])
inputs.append(int(next_id))
- return inputs[len(inputs) - n_tokens_to_generate:]
+ return inputs[len(inputs) - n_tokens_to_generate :]
+
def gen_text(prompt: str, n_tokens_to_generate: int = 40):
np.random.seed(42) # Set the random seed for reproducibility
diff --git a/questions/88_gpt-2-text-generation/starter_code.py b/questions/88_gpt-2-text-generation/starter_code.py
index 8d977c38..0955dc27 100644
--- a/questions/88_gpt-2-text-generation/starter_code.py
+++ b/questions/88_gpt-2-text-generation/starter_code.py
@@ -1,34 +1,39 @@
def gen_text(prompt: str, n_tokens_to_generate: int = 40):
- ####your code goes here####
- pass
+ ####your code goes here####
+ pass
-def load_encoder_hparams_and_params(model_size: str = "124M", models_dir: str = "models"):
- class DummyBPE:
- def __init__(self):
- self.encoder_dict = {"hello": 1, "world": 2, "": 0}
- def encode(self, text: str):
- tokens = text.strip().split()
- return [self.encoder_dict.get(token, self.encoder_dict[""]) for token in tokens]
+def load_encoder_hparams_and_params(
+ model_size: str = "124M", models_dir: str = "models"
+):
+ class DummyBPE:
+ def __init__(self):
+ self.encoder_dict = {"hello": 1, "world": 2, "": 0}
- def decode(self, token_ids: list):
- reversed_dict = {v: k for k, v in self.encoder_dict.items()}
- return " ".join([reversed_dict.get(tok_id, "") for tok_id in token_ids])
+ def encode(self, text: str):
+ tokens = text.strip().split()
+ return [
+ self.encoder_dict.get(token, self.encoder_dict[""])
+ for token in tokens
+ ]
- hparams = {
- "n_ctx": 1024,
- "n_head": 12
- }
+ def decode(self, token_ids: list):
+ reversed_dict = {v: k for k, v in self.encoder_dict.items()}
+ return " ".join(
+ [reversed_dict.get(tok_id, "") for tok_id in token_ids]
+ )
- params = {
- "wte": np.random.rand(3, 10),
- "wpe": np.random.rand(1024, 10),
- "blocks": [],
- "ln_f": {
- "g": np.ones(10),
- "b": np.zeros(10),
- }
- }
+ hparams = {"n_ctx": 1024, "n_head": 12}
- encoder = DummyBPE()
- return encoder, hparams, params
+ params = {
+ "wte": np.random.rand(3, 10),
+ "wpe": np.random.rand(1024, 10),
+ "blocks": [],
+ "ln_f": {
+ "g": np.ones(10),
+ "b": np.zeros(10),
+ },
+ }
+
+ encoder = DummyBPE()
+ return encoder, hparams, params
diff --git a/questions/89_the-pattern-weaver-s-code/solution.py b/questions/89_the-pattern-weaver-s-code/solution.py
index 153b61e5..770083b1 100644
--- a/questions/89_the-pattern-weaver-s-code/solution.py
+++ b/questions/89_the-pattern-weaver-s-code/solution.py
@@ -1,9 +1,11 @@
import numpy as np
+
def softmax(values):
exps = np.exp(values - np.max(values))
return exps / np.sum(exps)
+
def pattern_weaver(n, crystal_values, dimension):
dimension_sqrt = np.sqrt(dimension)
final_patterns = []
diff --git a/questions/89_the-pattern-weaver-s-code/starter_code.py b/questions/89_the-pattern-weaver-s-code/starter_code.py
index 0c458d41..c5a40387 100644
--- a/questions/89_the-pattern-weaver-s-code/starter_code.py
+++ b/questions/89_the-pattern-weaver-s-code/starter_code.py
@@ -1,9 +1,11 @@
import numpy as np
+
def softmax(values):
- # Implement the softmax function
- pass
+ # Implement the softmax function
+ pass
+
def pattern_weaver(n, crystal_values, dimension):
- # Your code here
- return np.round(x,3)
+ # Your code here
+ return np.round(x, 3)
diff --git a/questions/8_calculate-2x2-matrix-inverse/pytorch/solution.py b/questions/8_calculate-2x2-matrix-inverse/pytorch/solution.py
index 71bd48d9..8eb71366 100644
--- a/questions/8_calculate-2x2-matrix-inverse/pytorch/solution.py
+++ b/questions/8_calculate-2x2-matrix-inverse/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def inverse_2x2(matrix) -> torch.Tensor | None:
"""
Compute inverse of a 2×2 matrix using PyTorch.
@@ -7,13 +8,12 @@ def inverse_2x2(matrix) -> torch.Tensor | None:
Returns a 2×2 tensor or None if the matrix is singular.
"""
m = torch.as_tensor(matrix, dtype=torch.float)
- a, b = m[0,0], m[0,1]
- c, d = m[1,0], m[1,1]
+ a, b = m[0, 0], m[0, 1]
+ c, d = m[1, 0], m[1, 1]
det = a * d - b * c
if det == 0:
return None
- inv = torch.stack([
- torch.stack([ d/det, -b/det]),
- torch.stack([-c/det, a/det])
- ])
+ inv = torch.stack(
+ [torch.stack([d / det, -b / det]), torch.stack([-c / det, a / det])]
+ )
return inv
diff --git a/questions/8_calculate-2x2-matrix-inverse/pytorch/starter_code.py b/questions/8_calculate-2x2-matrix-inverse/pytorch/starter_code.py
index fdcf698c..cf2168b0 100644
--- a/questions/8_calculate-2x2-matrix-inverse/pytorch/starter_code.py
+++ b/questions/8_calculate-2x2-matrix-inverse/pytorch/starter_code.py
@@ -1,11 +1,12 @@
import torch
+
def inverse_2x2(matrix) -> torch.Tensor | None:
"""
Compute inverse of a 2×2 matrix using PyTorch.
Input can be Python list, NumPy array, or torch Tensor.
Returns a 2×2 tensor or None if the matrix is singular.
"""
- m = torch.as_tensor(matrix, dtype=torch.float)
+ torch.as_tensor(matrix, dtype=torch.float)
# Your implementation here
pass
diff --git a/questions/8_calculate-2x2-matrix-inverse/solution.py b/questions/8_calculate-2x2-matrix-inverse/solution.py
index bb81ec34..5981ae28 100644
--- a/questions/8_calculate-2x2-matrix-inverse/solution.py
+++ b/questions/8_calculate-2x2-matrix-inverse/solution.py
@@ -3,5 +3,5 @@ def inverse_2x2(matrix: list[list[float]]) -> list[list[float]]:
determinant = a * d - b * c
if determinant == 0:
return None
- inverse = [[d/determinant, -b/determinant], [-c/determinant, a/determinant]]
+ inverse = [[d / determinant, -b / determinant], [-c / determinant, a / determinant]]
return inverse
diff --git a/questions/8_calculate-2x2-matrix-inverse/starter_code.py b/questions/8_calculate-2x2-matrix-inverse/starter_code.py
index 7fd34bd1..b143d0da 100644
--- a/questions/8_calculate-2x2-matrix-inverse/starter_code.py
+++ b/questions/8_calculate-2x2-matrix-inverse/starter_code.py
@@ -1,2 +1,2 @@
def inverse_2x2(matrix: list[list[float]]) -> list[list[float]]:
- return inverse
+ return inverse
diff --git a/questions/8_calculate-2x2-matrix-inverse/tinygrad/solution.py b/questions/8_calculate-2x2-matrix-inverse/tinygrad/solution.py
index a3b5e97b..dea96bc6 100644
--- a/questions/8_calculate-2x2-matrix-inverse/tinygrad/solution.py
+++ b/questions/8_calculate-2x2-matrix-inverse/tinygrad/solution.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def inverse_2x2_tg(matrix) -> Tensor | None:
"""
Compute inverse of a 2×2 matrix using tinygrad.
@@ -7,10 +8,10 @@ def inverse_2x2_tg(matrix) -> Tensor | None:
Returns a 2×2 Tensor or None if the matrix is singular.
"""
m = Tensor(matrix).float()
- a, b = m[0,0], m[0,1]
- c, d = m[1,0], m[1,1]
+ a, b = m[0, 0], m[0, 1]
+ c, d = m[1, 0], m[1, 1]
det = a * d - b * c
if det.numpy() == 0:
return None
- inv = Tensor([[ d, -b], [-c, a]]) / det
+ inv = Tensor([[d, -b], [-c, a]]) / det
return inv
diff --git a/questions/8_calculate-2x2-matrix-inverse/tinygrad/starter_code.py b/questions/8_calculate-2x2-matrix-inverse/tinygrad/starter_code.py
index cbd9226d..80c50294 100644
--- a/questions/8_calculate-2x2-matrix-inverse/tinygrad/starter_code.py
+++ b/questions/8_calculate-2x2-matrix-inverse/tinygrad/starter_code.py
@@ -1,11 +1,12 @@
from tinygrad.tensor import Tensor
+
def inverse_2x2_tg(matrix) -> Tensor | None:
"""
Compute inverse of a 2×2 matrix using tinygrad.
Input can be Python list, NumPy array, or tinygrad Tensor.
Returns a 2×2 Tensor or None if the matrix is singular.
"""
- m = Tensor(matrix).float()
+ Tensor(matrix).float()
# Your implementation here
pass
diff --git a/questions/90_bm25-ranking/solution.py b/questions/90_bm25-ranking/solution.py
index 5182ab96..c8abeaf4 100644
--- a/questions/90_bm25-ranking/solution.py
+++ b/questions/90_bm25-ranking/solution.py
@@ -1,6 +1,7 @@
import numpy as np
from collections import Counter
+
def calculate_bm25_scores(corpus, query, k1=1.5, b=0.75):
if not corpus or not query:
raise ValueError("Corpus and query cannot be empty")
diff --git a/questions/90_bm25-ranking/starter_code.py b/questions/90_bm25-ranking/starter_code.py
index 1f2482ed..b80bdded 100644
--- a/questions/90_bm25-ranking/starter_code.py
+++ b/questions/90_bm25-ranking/starter_code.py
@@ -1,7 +1,7 @@
import numpy as np
-from collections import Counter
+
def calculate_bm25_scores(corpus, query, k1=1.5, b=0.75):
- # Your code here
- pass
- return np.round(scores,3)
+ # Your code here
+ pass
+ return np.round(scores, 3)
diff --git a/questions/91_calculate-f1-score-from-predicted-and-true-labels/starter_code.py b/questions/91_calculate-f1-score-from-predicted-and-true-labels/starter_code.py
index f803bd87..ae531524 100644
--- a/questions/91_calculate-f1-score-from-predicted-and-true-labels/starter_code.py
+++ b/questions/91_calculate-f1-score-from-predicted-and-true-labels/starter_code.py
@@ -1,14 +1,14 @@
def calculate_f1_score(y_true, y_pred):
- """
- Calculate the F1 score based on true and predicted labels.
+ """
+ Calculate the F1 score based on true and predicted labels.
- Args:
- y_true (list): True labels (ground truth).
- y_pred (list): Predicted labels.
+ Args:
+ y_true (list): True labels (ground truth).
+ y_pred (list): Predicted labels.
- Returns:
- float: The F1 score rounded to three decimal places.
- """
- # Your code here
- pass
- return round(f1,3)
+ Returns:
+ float: The F1 score rounded to three decimal places.
+ """
+ # Your code here
+ pass
+ return round(f1, 3)
diff --git a/questions/92_linear-regression-power-grid-optimization/solution.py b/questions/92_linear-regression-power-grid-optimization/solution.py
index e70e2e9f..a1d72e4a 100644
--- a/questions/92_linear-regression-power-grid-optimization/solution.py
+++ b/questions/92_linear-regression-power-grid-optimization/solution.py
@@ -2,6 +2,7 @@
PI = 3.14159
+
def power_grid_forecast(consumption_data):
# consumption_data: list of 10 daily consumption values
# days: 1 through 10
diff --git a/questions/92_linear-regression-power-grid-optimization/starter_code.py b/questions/92_linear-regression-power-grid-optimization/starter_code.py
index ed373110..5c8a1b56 100644
--- a/questions/92_linear-regression-power-grid-optimization/starter_code.py
+++ b/questions/92_linear-regression-power-grid-optimization/starter_code.py
@@ -1,12 +1,11 @@
-import math
-
PI = 3.14159
+
def power_grid_forecast(consumption_data):
- # 1) Subtract the daily fluctuation (10 * sin(2π * i / 10)) from each data point.
- # 2) Perform linear regression on the detrended data.
- # 3) Predict day 15's base consumption.
- # 4) Add the day 15 fluctuation back.
- # 5) Round, then add a 5% safety margin (rounded up).
- # 6) Return the final integer.
- pass
+ # 1) Subtract the daily fluctuation (10 * sin(2π * i / 10)) from each data point.
+ # 2) Perform linear regression on the detrended data.
+ # 3) Predict day 15's base consumption.
+ # 4) Add the day 15 fluctuation back.
+ # 5) Round, then add a 5% safety margin (rounded up).
+ # 6) Return the final integer.
+ pass
diff --git a/questions/93_calculate-mean-absolute-error-mae/solution.py b/questions/93_calculate-mean-absolute-error-mae/solution.py
index 090fd72a..e2076f3b 100644
--- a/questions/93_calculate-mean-absolute-error-mae/solution.py
+++ b/questions/93_calculate-mean-absolute-error-mae/solution.py
@@ -1,5 +1,6 @@
import numpy as np
+
def mae(y_true, y_pred):
"""
Calculate Mean Absolute Error between two arrays.
diff --git a/questions/93_calculate-mean-absolute-error-mae/starter_code.py b/questions/93_calculate-mean-absolute-error-mae/starter_code.py
index 77758060..366af9df 100644
--- a/questions/93_calculate-mean-absolute-error-mae/starter_code.py
+++ b/questions/93_calculate-mean-absolute-error-mae/starter_code.py
@@ -1,16 +1,14 @@
-import numpy as np
-
def mae(y_true, y_pred):
- """
- Calculate Mean Absolute Error between two arrays.
+ """
+ Calculate Mean Absolute Error between two arrays.
- Parameters:
- y_true (numpy.ndarray): Array of true values
+ Parameters:
+ y_true (numpy.ndarray): Array of true values
y_pred (numpy.ndarray): Array of predicted values
- Returns:
- float: Mean Absolute Error rounded to 3 decimal places
- """
- # Your code here
- pass
- return round(val,3)
+ Returns:
+ float: Mean Absolute Error rounded to 3 decimal places
+ """
+ # Your code here
+ pass
+ return round(val, 3)
diff --git a/questions/94_implement-multi-head-attention/solution.py b/questions/94_implement-multi-head-attention/solution.py
index 19250794..16cbed38 100644
--- a/questions/94_implement-multi-head-attention/solution.py
+++ b/questions/94_implement-multi-head-attention/solution.py
@@ -1,14 +1,17 @@
import numpy as np
-from typing import Tuple, List
+from typing import Tuple
-def compute_qkv(X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
+
+def compute_qkv(
+ X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray
+) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""
Compute the Query (Q), Key (K), and Value (V) matrices.
-
+
Args:
X: numpy array of shape (seq_len, d_model), input sequence
W_q, W_k, W_v: numpy arrays of shape (d_model, d_model), weight matrices for Q, K, and V
-
+
Returns:
Q, K, V: numpy arrays of shape (seq_len, d_model)
"""
@@ -17,33 +20,45 @@ def compute_qkv(X: np.ndarray, W_q: np.ndarray, W_k: np.ndarray, W_v: np.ndarray
V = np.dot(X, W_v) # Compute the Value matrix V
return Q, K, V
+
def self_attention(Q: np.ndarray, K: np.ndarray, V: np.ndarray) -> np.ndarray:
"""
Compute self-attention for a single head.
-
+
Args:
Q: numpy array of shape (seq_len, d_k), Query matrix
K: numpy array of shape (seq_len, d_k), Key matrix
V: numpy array of shape (seq_len, d_k), Value matrix
-
+
Returns:
attention_output: numpy array of shape (seq_len, d_k), output of the self-attention mechanism
"""
d_k = Q.shape[1] # Get the dimension of the keys
- scores = np.matmul(Q, K.T) / np.sqrt(d_k) # Compute scaled dot-product attention scores
- score_max = np.max(scores, axis=1, keepdims=True) # Find the maximum score for numerical stability
- attention_weights = np.exp(scores - score_max) / np.sum(np.exp(scores - score_max), axis=1, keepdims=True) # Compute softmax to get attention weights
- attention_output = np.matmul(attention_weights, V) # Compute the final attention output
+ scores = np.matmul(Q, K.T) / np.sqrt(
+ d_k
+ ) # Compute scaled dot-product attention scores
+ score_max = np.max(
+ scores, axis=1, keepdims=True
+ ) # Find the maximum score for numerical stability
+ attention_weights = np.exp(scores - score_max) / np.sum(
+ np.exp(scores - score_max), axis=1, keepdims=True
+ ) # Compute softmax to get attention weights
+ attention_output = np.matmul(
+ attention_weights, V
+ ) # Compute the final attention output
return attention_output
-def multi_head_attention(Q: np.ndarray, K: np.ndarray, V: np.ndarray, n_heads: int) -> np.ndarray:
+
+def multi_head_attention(
+ Q: np.ndarray, K: np.ndarray, V: np.ndarray, n_heads: int
+) -> np.ndarray:
"""
Compute multi-head attention.
-
+
Args:
Q, K, V: numpy arrays of shape (seq_len, d_model), Query, Key, and Value matrices
n_heads: int, number of attention heads
-
+
Returns:
attention_output: numpy array of shape (seq_len, d_model), final attention output
"""
@@ -52,17 +67,27 @@ def multi_head_attention(Q: np.ndarray, K: np.ndarray, V: np.ndarray, n_heads: i
d_k = d_model // n_heads # Dimension for each head
# Reshape Q, K, V to separate heads
- Q_reshaped = Q.reshape(Q.shape[0], n_heads, d_k).transpose(1, 0, 2) # Reshape and transpose to (n_heads, seq_len, d_k)
- K_reshaped = K.reshape(K.shape[0], n_heads, d_k).transpose(1, 0, 2) # Reshape and transpose to (n_heads, seq_len, d_k)
- V_reshaped = V.reshape(V.shape[0], n_heads, d_k).transpose(1, 0, 2) # Reshape and transpose to (n_heads, seq_len, d_k)
+ Q_reshaped = Q.reshape(Q.shape[0], n_heads, d_k).transpose(
+ 1, 0, 2
+ ) # Reshape and transpose to (n_heads, seq_len, d_k)
+ K_reshaped = K.reshape(K.shape[0], n_heads, d_k).transpose(
+ 1, 0, 2
+ ) # Reshape and transpose to (n_heads, seq_len, d_k)
+ V_reshaped = V.reshape(V.shape[0], n_heads, d_k).transpose(
+ 1, 0, 2
+ ) # Reshape and transpose to (n_heads, seq_len, d_k)
# Compute attention scores for each head
attentions = [] # Store attention outputs for each head
for i in range(n_heads):
- attn = self_attention(Q_reshaped[i], K_reshaped[i], V_reshaped[i]) # Compute attention for the i-th head
+ attn = self_attention(
+ Q_reshaped[i], K_reshaped[i], V_reshaped[i]
+ ) # Compute attention for the i-th head
attentions.append(attn) # Collect attention output
# Concatenate all head outputs
- attention_output = np.concatenate(attentions, axis=-1) # Concatenate along the last axis (columns)
+ attention_output = np.concatenate(
+ attentions, axis=-1
+ ) # Concatenate along the last axis (columns)
return attention_output # Return the final attention output
diff --git a/questions/94_implement-multi-head-attention/starter_code.py b/questions/94_implement-multi-head-attention/starter_code.py
index d6a92880..a58052a4 100644
--- a/questions/94_implement-multi-head-attention/starter_code.py
+++ b/questions/94_implement-multi-head-attention/starter_code.py
@@ -1,10 +1,10 @@
-import numpy as np
-
def compute_qkv(X, W_q, W_k, W_v):
- pass
+ pass
+
def self_attention(Q, K, V):
- pass
+ pass
+
def multi_head_attention(Q, K, V, n_heads):
- pass
+ pass
diff --git a/questions/95_calculate-the-phi-coefficient/starter_code.py b/questions/95_calculate-the-phi-coefficient/starter_code.py
index 59b46f08..e30a69cb 100644
--- a/questions/95_calculate-the-phi-coefficient/starter_code.py
+++ b/questions/95_calculate-the-phi-coefficient/starter_code.py
@@ -1,14 +1,14 @@
def phi_corr(x: list[int], y: list[int]) -> float:
- """
- Calculate the Phi coefficient between two binary variables.
+ """
+ Calculate the Phi coefficient between two binary variables.
- Args:
- x (list[int]): A list of binary values (0 or 1).
- y (list[int]): A list of binary values (0 or 1).
+ Args:
+ x (list[int]): A list of binary values (0 or 1).
+ y (list[int]): A list of binary values (0 or 1).
- Returns:
- float: The Phi coefficient rounded to 4 decimal places.
- """
- # Your code here
- pass
- return round(val,4)
+ Returns:
+ float: The Phi coefficient rounded to 4 decimal places.
+ """
+ # Your code here
+ pass
+ return round(val, 4)
diff --git a/questions/96_implement-the-hard-sigmoid-activation-function/starter_code.py b/questions/96_implement-the-hard-sigmoid-activation-function/starter_code.py
index 235b390a..418bd8ae 100644
--- a/questions/96_implement-the-hard-sigmoid-activation-function/starter_code.py
+++ b/questions/96_implement-the-hard-sigmoid-activation-function/starter_code.py
@@ -1,12 +1,12 @@
def hard_sigmoid(x: float) -> float:
- """
- Implements the Hard Sigmoid activation function.
+ """
+ Implements the Hard Sigmoid activation function.
- Args:
- x (float): Input value
+ Args:
+ x (float): Input value
- Returns:
- float: The Hard Sigmoid of the input
- """
- # Your code here
- pass
+ Returns:
+ float: The Hard Sigmoid of the input
+ """
+ # Your code here
+ pass
diff --git a/questions/97_implement-the-elu-activation-function/solution.py b/questions/97_implement-the-elu-activation-function/solution.py
index bcabbec6..2479b2ee 100644
--- a/questions/97_implement-the-elu-activation-function/solution.py
+++ b/questions/97_implement-the-elu-activation-function/solution.py
@@ -1,5 +1,6 @@
import math
+
def elu(x: float, alpha: float = 1.0) -> float:
"""
Compute the ELU activation function.
@@ -11,4 +12,4 @@ def elu(x: float, alpha: float = 1.0) -> float:
Returns:
float: ELU activation value
"""
- return round(x if x > 0 else alpha * (math.exp(x) - 1),4)
+ return round(x if x > 0 else alpha * (math.exp(x) - 1), 4)
diff --git a/questions/97_implement-the-elu-activation-function/starter_code.py b/questions/97_implement-the-elu-activation-function/starter_code.py
index 2e3b9416..7ad87493 100644
--- a/questions/97_implement-the-elu-activation-function/starter_code.py
+++ b/questions/97_implement-the-elu-activation-function/starter_code.py
@@ -1,14 +1,14 @@
def elu(x: float, alpha: float = 1.0) -> float:
- """
- Compute the ELU activation function.
+ """
+ Compute the ELU activation function.
- Args:
- x (float): Input value
- alpha (float): ELU parameter for negative values (default: 1.0)
+ Args:
+ x (float): Input value
+ alpha (float): ELU parameter for negative values (default: 1.0)
- Returns:
- float: ELU activation value
- """
- # Your code here
- pass
- return round(val,4)
+ Returns:
+ float: ELU activation value
+ """
+ # Your code here
+ pass
+ return round(val, 4)
diff --git a/questions/98_implement-the-prelu-activation-function/starter_code.py b/questions/98_implement-the-prelu-activation-function/starter_code.py
index 7fd1049a..ae3ed547 100644
--- a/questions/98_implement-the-prelu-activation-function/starter_code.py
+++ b/questions/98_implement-the-prelu-activation-function/starter_code.py
@@ -1,13 +1,13 @@
def prelu(x: float, alpha: float = 0.25) -> float:
- """
- Implements the PReLU (Parametric ReLU) activation function.
+ """
+ Implements the PReLU (Parametric ReLU) activation function.
- Args:
- x: Input value
- alpha: Slope parameter for negative values (default: 0.25)
+ Args:
+ x: Input value
+ alpha: Slope parameter for negative values (default: 0.25)
- Returns:
- float: PReLU activation value
- """
- # Your code here
- pass
+ Returns:
+ float: PReLU activation value
+ """
+ # Your code here
+ pass
diff --git a/questions/99_implement-the-softplus-activation-function/solution.py b/questions/99_implement-the-softplus-activation-function/solution.py
index fd955bc7..13a70c0f 100644
--- a/questions/99_implement-the-softplus-activation-function/solution.py
+++ b/questions/99_implement-the-softplus-activation-function/solution.py
@@ -1,5 +1,6 @@
import math
+
def softplus(x: float) -> float:
"""
Compute the softplus activation function.
@@ -17,4 +18,4 @@ def softplus(x: float) -> float:
if x < -100:
return 0.0
- return round (math.log(1.0 + math.exp(x)),4)
+ return round(math.log(1.0 + math.exp(x)), 4)
diff --git a/questions/99_implement-the-softplus-activation-function/starter_code.py b/questions/99_implement-the-softplus-activation-function/starter_code.py
index 7da7016c..80ccdbaa 100644
--- a/questions/99_implement-the-softplus-activation-function/starter_code.py
+++ b/questions/99_implement-the-softplus-activation-function/starter_code.py
@@ -10,4 +10,4 @@ def softplus(x: float) -> float:
"""
# Your code here
pass
- return round(val,4)
+ return round(val,4)
diff --git a/questions/9_matrix-times-matrix/pytorch/solution.py b/questions/9_matrix-times-matrix/pytorch/solution.py
index 5947bf61..81b77fe2 100644
--- a/questions/9_matrix-times-matrix/pytorch/solution.py
+++ b/questions/9_matrix-times-matrix/pytorch/solution.py
@@ -1,5 +1,6 @@
import torch
+
def matrixmul(a, b) -> torch.Tensor:
"""
Multiply two matrices using PyTorch.
diff --git a/questions/9_matrix-times-matrix/pytorch/starter_code.py b/questions/9_matrix-times-matrix/pytorch/starter_code.py
index c33a93b3..e1d50d18 100644
--- a/questions/9_matrix-times-matrix/pytorch/starter_code.py
+++ b/questions/9_matrix-times-matrix/pytorch/starter_code.py
@@ -1,5 +1,6 @@
import torch
+
def matrixmul(a, b) -> torch.Tensor:
"""
Multiply two matrices using PyTorch.
diff --git a/questions/9_matrix-times-matrix/solution.py b/questions/9_matrix-times-matrix/solution.py
index 82c5891c..a4e7baef 100644
--- a/questions/9_matrix-times-matrix/solution.py
+++ b/questions/9_matrix-times-matrix/solution.py
@@ -1,9 +1,9 @@
-
-def matrixmul(a:list[list[int|float]],
- b:list[list[int|float]])-> list[list[int|float]]:
+def matrixmul(
+ a: list[list[int | float]], b: list[list[int | float]]
+) -> list[list[int | float]]:
if len(a[0]) != len(b):
return -1
-
+
vals = []
for i in range(len(a)):
hold = []
@@ -11,7 +11,7 @@ def matrixmul(a:list[list[int|float]],
val = 0
for k in range(len(b)):
val += a[i][k] * b[k][j]
-
+
hold.append(val)
vals.append(hold)
diff --git a/questions/9_matrix-times-matrix/starter_code.py b/questions/9_matrix-times-matrix/starter_code.py
index ce18d76e..0f6c098d 100644
--- a/questions/9_matrix-times-matrix/starter_code.py
+++ b/questions/9_matrix-times-matrix/starter_code.py
@@ -1,3 +1,4 @@
-def matrixmul(a:list[list[int|float]],
- b:list[list[int|float]])-> list[list[int|float]]:
- return c
+def matrixmul(
+ a: list[list[int | float]], b: list[list[int | float]]
+) -> list[list[int | float]]:
+ return c
diff --git a/questions/9_matrix-times-matrix/tinygrad/solution.py b/questions/9_matrix-times-matrix/tinygrad/solution.py
index 29ac51be..f437be1e 100644
--- a/questions/9_matrix-times-matrix/tinygrad/solution.py
+++ b/questions/9_matrix-times-matrix/tinygrad/solution.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def matrixmul_tg(a, b) -> Tensor:
"""
Multiply two matrices using tinygrad.
diff --git a/questions/9_matrix-times-matrix/tinygrad/starter_code.py b/questions/9_matrix-times-matrix/tinygrad/starter_code.py
index e1f41794..b18b9e09 100644
--- a/questions/9_matrix-times-matrix/tinygrad/starter_code.py
+++ b/questions/9_matrix-times-matrix/tinygrad/starter_code.py
@@ -1,5 +1,6 @@
from tinygrad.tensor import Tensor
+
def matrixmul_tg(a, b) -> Tensor:
"""
Multiply two matrices using tinygrad.
diff --git a/questions/_template/tinygrad/starter_code.py b/questions/_template/tinygrad/starter_code.py
index d3e5beb5..22c1b928 100644
--- a/questions/_template/tinygrad/starter_code.py
+++ b/questions/_template/tinygrad/starter_code.py
@@ -1,2 +1,2 @@
-def your_function(...):
+def your_function():
pass
diff --git a/utils/build_bundle.py b/utils/build_bundle.py
index 0edf110b..e05136d2 100644
--- a/utils/build_bundle.py
+++ b/utils/build_bundle.py
@@ -3,29 +3,35 @@
Walk questions/* folders → emit build/.json bundles.
"""
-import json, pathlib, re
+import json
+import pathlib
-ROOT = pathlib.Path("questions")
+ROOT = pathlib.Path("questions")
OUTDIR = pathlib.Path("build")
OUTDIR.mkdir(exist_ok=True)
-def load_text(p): return p.read_text(encoding="utf-8").rstrip("\n")
-def load_json(p): return json.loads(load_text(p))
+
+def load_text(p):
+ return p.read_text(encoding="utf-8").rstrip("\n")
+
+
+def load_json(p):
+ return json.loads(load_text(p))
+
def bundle_one(folder: pathlib.Path):
meta = load_json(folder / "meta.json")
- meta["description"] = load_text(folder / "description.md")
+ meta["description"] = load_text(folder / "description.md")
meta["learn_section"] = load_text(folder / "learn.md")
- meta["starter_code"] = load_text(folder / "starter_code.py")
- meta["solution"] = load_text(folder / "solution.py")
- meta["example"] = load_json(folder / "example.json")
- meta["test_cases"] = load_json(folder / "tests.json")
+ meta["starter_code"] = load_text(folder / "starter_code.py")
+ meta["solution"] = load_text(folder / "solution.py")
+ meta["example"] = load_json(folder / "example.json")
+ meta["test_cases"] = load_json(folder / "tests.json")
if "marimo_link" in meta:
meta["marimo_link"] = meta["marimo_link"]
-
for lang in ("tinygrad", "pytorch"):
sub = folder / lang
if sub.exists():
@@ -40,9 +46,13 @@ def bundle_one(folder: pathlib.Path):
out_path.write_text(json.dumps(meta, indent=2, ensure_ascii=False))
print(f"✓ bundled {out_path.name}")
+
def main():
- for qdir in sorted(p for p in ROOT.iterdir() if p.is_dir() and not p.name.startswith('_')):
+ for qdir in sorted(
+ p for p in ROOT.iterdir() if p.is_dir() and not p.name.startswith("_")
+ ):
bundle_one(qdir)
+
if __name__ == "__main__":
main()
diff --git a/utils/make_question_template.py b/utils/make_question_template.py
index 9eb1516c..a93b73ed 100644
--- a/utils/make_question_template.py
+++ b/utils/make_question_template.py
@@ -1,14 +1,17 @@
#!/usr/bin/env python
-import json, pathlib, textwrap
+import json
+import pathlib
TEMPLATE = pathlib.Path("questions/_template")
-LANGS = ["tinygrad", "pytorch"]
+LANGS = ["tinygrad", "pytorch"]
+
def w(path, txt):
path.parent.mkdir(parents=True, exist_ok=True)
if not path.exists():
path.write_text(txt.rstrip() + "\n")
+
def main():
META = {
"id": "XXX",
@@ -20,21 +23,36 @@ def main():
"dislikes": "0",
"contributor": [],
"tinygrad_difficulty": "",
- "pytorch_difficulty": ""
+ "pytorch_difficulty": "",
}
w(TEMPLATE / "meta.json", json.dumps(META, indent=2))
w(TEMPLATE / "description.md", "## Problem\n\nDescribe the task.")
- w(TEMPLATE / "learn.md", "## Solution Explanation\n\nExplain here.")
- w(TEMPLATE / "starter_code.py","def your_function(...):\n pass")
- w(TEMPLATE / "solution.py", "def your_function(...):\n ...")
- w(TEMPLATE / "example.json", json.dumps({"input":"...", "output":"...", "reasoning":"..."}, indent=2))
- w(TEMPLATE / "tests.json", json.dumps([{"test":"print(your_function(...))","expected_output":"..."}], indent=2))
+ w(TEMPLATE / "learn.md", "## Solution Explanation\n\nExplain here.")
+ w(TEMPLATE / "starter_code.py", "def your_function(...):\n pass")
+ w(TEMPLATE / "solution.py", "def your_function(...):\n ...")
+ w(
+ TEMPLATE / "example.json",
+ json.dumps({"input": "...", "output": "...", "reasoning": "..."}, indent=2),
+ )
+ w(
+ TEMPLATE / "tests.json",
+ json.dumps(
+ [{"test": "print(your_function(...))", "expected_output": "..."}], indent=2
+ ),
+ )
for lang in LANGS:
sub = TEMPLATE / lang
w(sub / "starter_code.py", "def your_function(...):\n pass")
- w(sub / "solution.py", "def your_function(...):\n ...")
- w(sub / "tests.json", json.dumps([{"test":"print(your_function(...))","expected_output":"..."}], indent=2))
+ w(sub / "solution.py", "def your_function(...):\n ...")
+ w(
+ sub / "tests.json",
+ json.dumps(
+ [{"test": "print(your_function(...))", "expected_output": "..."}],
+ indent=2,
+ ),
+ )
print("Template ready at questions/_template/")
+
if __name__ == "__main__":
main()
diff --git a/utils/validate_questions.py b/utils/validate_questions.py
index 1f13d3e0..ef269bb8 100644
--- a/utils/validate_questions.py
+++ b/utils/validate_questions.py
@@ -60,6 +60,7 @@ def validate_file(validator: Draft7Validator, fp: pathlib.Path) -> bool:
print(f"✓ {fp.name}")
return True
+
def main():
schema = load_schema()
validator = Draft7Validator(schema)
@@ -86,5 +87,6 @@ def main():
sys.exit(0 if ok else 1)
+
if __name__ == "__main__":
main()