├── LICENSE ├── README.md ├── app ├── DL_problems.py ├── DeepLearning.py ├── LinAlg.py ├── ML_problems.py ├── MachineLearning.py ├── __pycache__ │ ├── DL_problems.cpython-312.pyc │ ├── DeepLearning.cpython-312.pyc │ ├── LinAlg.cpython-312.pyc │ ├── ML_problems.cpython-312.pyc │ ├── MachineLearning.cpython-312.pyc │ ├── about.cpython-312.pyc │ ├── lin_alg_problems.cpython-312.pyc │ ├── main.cpython-312.pyc │ └── problems.cpython-312.pyc ├── about.py ├── assets │ └── favicon.ico ├── lin_alg_problems.py └── main.py ├── contribute.md └── requirements.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 moe chabot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeepMLeet 2 | 3 | Welcome to **DeepMLeet**: a cutting-edge platform tailored for Machine Learning enthusiasts and practitioners. Drawing inspiration from the challenge-based approach of platforms like LeetCode, DeepMLeet brings forth an interactive environment specifically crafted for Deep Learning and Machine Learning challenges. 4 | 5 | ## Overview 6 | 7 | DeepMLeet leverages the convenience and power of Streamlit, coupled with the code execution capabilities of pistonpy, to offer users a seamless experience in solving, testing, and submitting solutions for a variety of ML challenges. From data manipulation to complex algorithm implementations, our platform supports a broad spectrum of ML domains. 8 | 9 | ### Features 10 | 11 | - **Interactive Code Editor:** Utilize the streamlit-ace editor for an enhanced coding experience, complete with syntax highlighting and theme customization. 12 | - **Real-Time Execution and Feedback:** Submit your code to be executed by pistonpy, offering immediate feedback and results directly within the platform. 13 | - **Dynamic Problem Selection:** Choose from a growing list of ML problems, each with a detailed description, starter code, and test cases. 14 | - **Instant Test Case Evaluation:** Run your solutions against predefined test cases to ensure accuracy and performance, with immediate pass/fail feedback. 15 | - **Solution Insights:** Access the solution for learning purposes after attempting the problems, fostering understanding and improvement. 16 | 17 | ## Running the DeepMLeet Streamlit App 18 | 19 | Follow this guide to set up your environment and run the Streamlit app from the DeepMLeet repository. 20 | 21 | ### Prerequisites 22 | 23 | Ensure you have [Anaconda](https://www.anaconda.com/products/individual) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html) installed on your system. 24 | 25 | ### Setup 26 | 27 | #### 1. Clone the Repository 28 | 29 | Clone the DeepMLeet repository to your local machine using the terminal or command prompt: 30 | 31 | ```bash 32 | git clone https://github.com/moe18/DeepMLeet.git 33 | cd DeepMLeet 34 | ``` 35 | #### 2.Create a Conda Environment 36 | Create a new Conda environment using Python 3.12.2. Replace deepmleetenv with your preferred environment name if desired: 37 | ```bash 38 | conda create --name deepmleetenv python=3.12.2 39 | conda activate deepmleetenv 40 | ``` 41 | 42 | #### 3. Install Dependencies 43 | With the Conda environment activated, install the required dependencies, including Streamlit. This assumes there is a requirements.txt file present in the repository: 44 | 45 | ``` bash 46 | pip install -r requirements.txt 47 | ``` 48 | 49 | ### Running the App 50 | With the environment set and dependencies installed, run the Streamlit app by executing: 51 | ```bash 52 | streamlit run app/main.py 53 | ``` 54 | This command assumes that main.py is located within an app directory. Adjust the path accordingly if your file structure is different. 55 | 56 | 57 | ## How to Contribute 58 | 59 | We are excited to have you contribute to the DeepMLeet project! Whether you're looking to improve the UI, add new problems, or enhance existing ones, your contributions are welcome. 60 | 61 | For detailed instructions on how to contribute, including guidelines and best practices, please see our [contribute.md](contribute.md) page. This guide provides all the information you need to get started, including how to fork the repository, make changes, and submit your contributions for review. 62 | 63 | Your insights, improvements, and additions are what make this project thrive. We look forward to seeing your contributions! 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/DL_problems.py: -------------------------------------------------------------------------------- 1 | problems = { 2 | "Deep Learning": { 3 | "section": True, 4 | "description": """## Deep Learning 5 | 6 | Deep Learning (DL) is a transformative branch of machine learning, pivotal for handling complex data analysis and prediction tasks. This section explores the essential concepts and architectures of Deep Learning, equipping you with the knowledge to harness the power of neural networks: 7 | 8 | ### Foundational Skills 9 | 10 | - **Neural Network Basics**: Understand the architecture of neural networks, including neurons, layers, and activation functions. 11 | - **Backpropagation and Training**: Learn how neural networks learn through the backpropagation algorithm and the role of loss functions and optimizers. 12 | - **Data Preprocessing for DL**: Discover the specific requirements for preparing data for deep learning, such as normalization and data augmentation. 13 | 14 | ### Intermediate Understanding 15 | 16 | - **Convolutional Neural Networks (CNNs)**: Dive into CNNs for image processing, including layer types like convolutional layers, pooling layers, and fully connected layers. 17 | - **Recurrent Neural Networks (RNNs)**: Explore RNNs for sequence data analysis, useful in applications like language modeling and time series prediction. 18 | - **Regularization Techniques**: Understand methods like dropout and batch normalization to prevent overfitting in deep neural networks. 19 | 20 | ### Advanced Techniques 21 | 22 | - **Advanced Architectures**: Learn about advanced neural network architectures such as Transformers and GANs (Generative Adversarial Networks) for tasks like natural language processing and generative models. 23 | - **Transfer Learning**: Grasp how pre-trained models can be adapted for new tasks, significantly reducing the need for large labeled datasets. 24 | - **Autoencoders**: Explore how autoencoders can be used for unsupervised learning tasks, including dimensionality reduction and feature learning. 25 | 26 | Each topic is designed to build on the previous, ensuring a thorough understanding of Deep Learning's role in modern data analysis and predictive modeling. Practical exercises and real-world examples will demonstrate how to apply these concepts effectively, preparing learners to develop and evaluate their own deep learning models.""", "example": "", 27 | "learn": "", 28 | "starter_code": "", 29 | "solution": "", 30 | "test_cases": [], 31 | "use_micro": False 32 | }, 33 | "Sigmoid Activation Function Understanding (easy)": { 34 | "description": "Write a Python function that computes the output of the sigmoid activation function given an input value z. The function should return the output rounded to four decimal places.", 35 | "example": """Example: 36 | input: z = 0 37 | output: 0.5 38 | reasoning: The sigmoid function is defined as σ(z) = 1 / (1 + exp(-z)). For z = 0, exp(-0) = 1, hence the output is 1 / (1 + 1) = 0.5.""", 39 | "learn": r''' 40 | ## Understanding the Sigmoid Activation Function 41 | 42 | The sigmoid activation function is crucial in neural networks, especially for binary classification tasks. It maps any real-valued number into the (0, 1) interval, making it useful for modeling probability as an output. 43 | 44 | ### Mathematical Definition: 45 | 46 | The sigmoid function is mathematically defined as: 47 | 48 | $$ 49 | \sigma(z) = \frac{1}{1 + e^{-z}} 50 | $$ 51 | 52 | Where \(z\) is the input to the function. 53 | 54 | ### Characteristics: 55 | 56 | - **Output Range**: The output is always between 0 and 1. 57 | - **Shape**: It has an "S" shaped curve. 58 | - **Gradient**: The function's gradient is highest near z = 0 and decreases toward either end of the z-axis. 59 | 60 | This function is particularly useful for turning logits (raw prediction values) into probabilities in binary classification models. 61 | ''', 62 | 63 | "starter_code": """import math\n\ndef sigmoid(z: float) -> float:\n # Your code here\n return result""", 64 | "solution": """ 65 | import math 66 | def sigmoid(z: float) -> float: 67 | result = 1 / (1 + math.exp(-z)) 68 | return round(result, 4)""", 69 | "test_cases": [ 70 | { 71 | "test": "print(sigmoid(0))", 72 | "expected_output": "0.5" 73 | }, 74 | { 75 | "test": "print(sigmoid(1))", 76 | "expected_output": "0.7311" 77 | }, 78 | { 79 | "test": "print(sigmoid(-1))", 80 | "expected_output": "0.2689" 81 | } 82 | ], 83 | "use_micro": False 84 | }, 85 | "Softmax Activation Function Implementation (easy)": { 86 | "description": "Write a Python function that computes the softmax activation for a given list of scores. The function should return the softmax values as a list, each rounded to four decimal places.", 87 | "example": """Example: 88 | input: scores = [1, 2, 3] 89 | output: [0.0900, 0.2447, 0.6652] 90 | reasoning: The softmax function converts a list of values into a probability distribution. The probabilities are proportional to the exponential of each element divided by the sum of the exponentials of all elements in the list.""", 91 | "learn": r''' 92 | ## Understanding the Softmax Activation Function 93 | 94 | The softmax function is a generalization of the sigmoid function and is used in the output layer of a neural network model that handles multi-class classification tasks. 95 | 96 | ### Mathematical Definition: 97 | 98 | The softmax function is mathematically represented as: 99 | 100 | $$ 101 | \text{softmax}(z_i) = \frac{e^{z_i}}{\sum_{j} e^{z_j}} 102 | $$ 103 | 104 | Where: 105 | - \(z_i\) is the score for class \(i\), 106 | - The denominator is the sum of the exponentials of all the scores. 107 | 108 | ### Characteristics: 109 | 110 | - **Output Range**: Each output value is between 0 and 1, and the sum of all outputs is 1. 111 | - **Purpose**: It transforms scores into probabilities, which are easier to interpret and are useful for classification. 112 | 113 | This function is essential for models where the output needs to represent a probability distribution across multiple classes. 114 | ''', 115 | 116 | "starter_code": """import math\n\ndef softmax(scores: list[float]) -> list[float]:\n # Your code here\n return probabilities""", 117 | "solution": """ 118 | import math 119 | def softmax(scores: list[float]) -> list[float]: 120 | exp_scores = [math.exp(score) for score in scores] 121 | sum_exp_scores = sum(exp_scores) 122 | probabilities = [round(score / sum_exp_scores, 4) for score in exp_scores] 123 | return probabilities""", 124 | "test_cases": [ 125 | { 126 | "test": "print(softmax([1, 2, 3]))", 127 | "expected_output": "[0.09, 0.2447, 0.6652]" 128 | }, 129 | { 130 | "test": "print(softmax([1, 1, 1]))", 131 | "expected_output": "[0.3333, 0.3333, 0.3333]" 132 | }, 133 | { 134 | "test": "print(softmax([-1, 0, 5]))", 135 | "expected_output": "[0.0025, 0.0067, 0.9909]" 136 | } 137 | ], 138 | "use_micro": False 139 | }, 140 | "Single Neuron (easy)": { 141 | "description": "Write a Python function that simulates a single neuron with a sigmoid activation function for binary classification, handling multidimensional input features. The function should take a list of feature vectors (each vector representing multiple features for an example), associated true binary labels, and the neuron's weights (one for each feature) and bias as input. It should return the predicted probabilities after sigmoid activation and the mean squared error between the predicted probabilities and the true labels, both rounded to four decimal places.", 142 | "example": """Example: 143 | input: features = [[0.5, 1.0], [-1.5, -2.0], [2.0, 1.5]], labels = [0, 1, 0], weights = [0.7, -0.4], bias = -0.1 144 | output: ([0.4626, 0.4134, 0.6682], 0.3349) 145 | reasoning: For each input vector, the weighted sum is calculated by multiplying each feature by its corresponding weight, adding these up along with the bias, then applying the sigmoid function to produce a probability. The MSE is calculated as the average squared difference between each predicted probability and the corresponding true label.""", 146 | "learn": r''' 147 | ## Single Neuron Model with Multidimensional Input and Sigmoid Activation 148 | 149 | This task involves a neuron model designed for binary classification with multidimensional input features, using the sigmoid activation function to output probabilities. It also involves calculating the mean squared error (MSE) to evaluate prediction accuracy. 150 | 151 | ### Mathematical Background: 152 | 153 | 1. **Neuron Output Calculation**: 154 | $$ z = \sum (weight_i \times feature_i) + bias $$ 155 | 156 | $$ \sigma(z) = \frac{1}{1 + e^{-z}} $$ 157 | 158 | 2. **MSE Calculation**: 159 | $$ MSE = \frac{1}{n} \sum (predicted - true)^2 $$ 160 | 161 | Where: 162 | - $$z$$ is the sum of weighted inputs plus bias, 163 | - $$\sigma(z)$$ is the sigmoid activation output, 164 | - $$predicted$$ are the probabilities after sigmoid activation, 165 | - $$true$$ are the true binary labels. 166 | 167 | ### Practical Implementation: 168 | 169 | - Each feature vector is processed to calculate a combined weighted sum, which is then passed through the sigmoid function to determine the probability of the input belonging to the positive class. 170 | - MSE provides a measure of error, offering insights into the model's performance and aiding in its optimization. 171 | ''', 172 | 173 | "starter_code": """import math\n\ndef single_neuron_model(features: list[list[float]], labels: list[int], weights: list[float], bias: float) -> (list[float], float):\n # Your code here\n return probabilities, mse""", 174 | "solution": """ 175 | import math 176 | def single_neuron_model(features, labels, weights, bias): 177 | probabilities = [] 178 | for feature_vector in features: 179 | z = sum(weight * feature for weight, feature in zip(weights, feature_vector)) + bias 180 | prob = 1 / (1 + math.exp(-z)) 181 | probabilities.append(round(prob, 4)) 182 | 183 | mse = sum((prob - label) ** 2 for prob, label in zip(probabilities, labels)) / len(labels) 184 | mse = round(mse, 4) 185 | 186 | return probabilities, mse""", 187 | "test_cases": [ 188 | { 189 | "test": "print(single_neuron_model([[0.5, 1.0], [-1.5, -2.0], [2.0, 1.5]], [0, 1, 0], [0.7, -0.4], -0.1))", 190 | "expected_output": "([0.4626, 0.4134, 0.6682], 0.3349)" 191 | }, 192 | { 193 | "test": "print(single_neuron_model([[1, 2], [2, 3], [3, 1]], [1, 0, 1], [0.5, -0.2], 0))", 194 | "expected_output": " ([0.525, 0.5987, 0.7858], 0.21)" 195 | } 196 | ], 197 | }, 198 | "Single Neuron with Backpropagation (medium)": { 199 | "description": "Write a Python function that simulates a single neuron with sigmoid activation, and implements backpropagation to update the neuron's weights and bias. The function should take a list of feature vectors, associated true binary labels, initial weights, initial bias, a learning rate, and the number of epochs. The function should update the weights and bias using gradient descent based on the MSE loss, and return the updated weights, bias, and a list of MSE values for each epoch, each rounded to four decimal places.", 200 | "example": """Example: 201 | input: features = [[1.0, 2.0], [2.0, 1.0], [-1.0, -2.0]], labels = [1, 0, 0], initial_weights = [0.1, -0.2], initial_bias = 0.0, learning_rate = 0.1, epochs = 2 202 | output: updated_weights = [0.0808, -0.1916], updated_bias = -0.0214, mse_values = [0.2386, 0.2348] 203 | reasoning: The neuron receives feature vectors and computes predictions using the sigmoid activation. Based on the predictions and true labels, the gradients of MSE loss with respect to weights and bias are computed and used to update the model parameters across epochs.""", 204 | "learn": r''' 205 | ## Neural Network Learning with Backpropagation 206 | 207 | This question involves implementing backpropagation for a single neuron in a neural network. The neuron processes inputs and updates parameters to minimize the Mean Squared Error (MSE) between predicted outputs and true labels. 208 | 209 | ### Mathematical Background: 210 | 211 | 1. **Forward Pass**: 212 | - Compute the neuron output by calculating the dot product of the weights and input features and adding the bias: 213 | 214 | $$ z = w_1x_1 + w_2x_2 + ... + w_nx_n + b $$ 215 | 216 | - Apply the sigmoid activation function to convert the linear combination into a probability: 217 | 218 | $$ \sigma(z) = \frac{1}{1 + e^{-z}} $$ 219 | 220 | 2. **Loss Calculation (MSE)**: 221 | - The Mean Squared Error is used to quantify the error between the neuron's predictions and the actual labels: 222 | 223 | $$ MSE = \frac{1}{n} \sum_{i=1}^{n} (\sigma(z_i) - y_i)^2 $$ 224 | 225 | 3. **Backward Pass (Gradient Calculation)**: 226 | - Compute the gradient of the MSE with respect to each weight and the bias. This involves the partial derivatives of the loss function with respect to the output of the neuron, multiplied by the derivative of the sigmoid function: 227 | 228 | $$ \frac{\partial MSE}{\partial w_j} = \frac{2}{n} \sum_{i=1}^{n} (\sigma(z_i) - y_i) \sigma'(z_i) x_{ij} $$ 229 | 230 | $$ \frac{\partial MSE}{\partial b} = \frac{2}{n} \sum_{i=1}^{n} (\sigma(z_i) - y_i) \sigma'(z_i) $$ 231 | 232 | 4. **Parameter Update**: 233 | - Update each weight and the bias by subtracting a portion of the gradient determined by the learning rate: 234 | 235 | $$ w_j = w_j - \alpha \frac{\partial MSE}{\partial w_j} $$ 236 | 237 | $$ b = b - \alpha \frac{\partial MSE}{\partial b} $$ 238 | 239 | ### Practical Implementation: 240 | 241 | This process refines the neuron's ability to predict accurately by iteratively adjusting the weights and bias based on the error gradients, optimizing the neural network's performance over multiple iterations. 242 | ''', 243 | 244 | "starter_code": """import numpy as np\n\ndef 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]):\n # Your code here\n return updated_weights, updated_bias, mse_values""", 245 | "solution": """ 246 | import numpy as np 247 | 248 | def sigmoid(x): 249 | return 1 / (1 + np.exp(-x)) 250 | 251 | def train_neuron(features, labels, initial_weights, initial_bias, learning_rate, epochs): 252 | weights = np.array(initial_weights) 253 | bias = initial_bias 254 | features = np.array(features) 255 | labels = np.array(labels) 256 | mse_values = [] 257 | 258 | for _ in range(epochs): 259 | z = np.dot(features, weights) + bias 260 | predictions = sigmoid(z) 261 | 262 | mse = np.mean((predictions - labels) ** 2) 263 | mse_values.append(round(mse, 4)) 264 | 265 | # Gradient calculation for weights and bias 266 | errors = predictions - labels 267 | weight_gradients = np.dot(features.T, errors * predictions * (1 - predictions)) 268 | bias_gradient = np.sum(errors * predictions * (1 - predictions)) 269 | 270 | # Update weights and bias 271 | weights -= learning_rate * weight_gradients / len(labels) 272 | bias -= learning_rate * bias_gradient / len(labels) 273 | 274 | # Round weights and bias for output 275 | updated_weights = np.round(weights, 4) 276 | updated_bias = round(bias, 4) 277 | 278 | return updated_weights.tolist(), updated_bias, mse_values""", 279 | "test_cases": [ 280 | { 281 | "test": "print(train_neuron(np.array([[1.0, 2.0], [2.0, 1.0], [-1.0, -2.0]]), np.array([1, 0, 0]), np.array([0.1, -0.2]), 0.0, 0.1, 2))", 282 | "expected_output": "([0.1019, -0.1711], -0.0083, [0.3033, 0.2987])" 283 | }, 284 | { 285 | "test": "print(train_neuron(np.array([[1, 2], [2, 3], [3, 1]]), np.array([1, 0, 1]), np.array([0.5, -0.2]), 0, 0.1, 3))", 286 | "expected_output": "([0.4943, -0.2155], 0.0013, [0.21, 0.2093, 0.2087])" 287 | } 288 | ], 289 | "use_micro": False 290 | }, 291 | 292 | 293 | "Implementing Basic Autograd Operations (medium)": { 294 | "description": "Special thanks to Andrej Karpathy for making a video about this, if you havent already check out his videos on youtube https://youtu.be/VMj-3S1tku0?si=gjlnFP4o3JRN9dTg. Write a Python class similar to the provided 'Value' class that implements the basic autograd operations: addition, multiplication, and ReLU activation. The class should handle scalar values and should correctly compute gradients for these operations through automatic differentiation.", 295 | "example": """Example: 296 | a = Value(2) 297 | b = Value(-3) 298 | c = Value(10) 299 | d = a + b * c 300 | e = d.relu() 301 | e.backward() 302 | print(a, b, c, d, e) 303 | Output: Value(data=2, grad=0) Value(data=-3, grad=10) Value(data=10, grad=-3) Value(data=-28, grad=1) Value(data=0, grad=1) 304 | Explanation: The output reflects the forward computation and gradients after backpropagation. The ReLU on 'd' zeros out its output and gradient due to the negative data value.""", 305 | "learn": r''' 306 | ## Understanding Mathematical Concepts in Autograd Operations 307 | First off watch this: https://youtu.be/VMj-3S1tku0?si=gjlnFP4o3JRN9dTg 308 | 309 | This task focuses on the implementation of basic automatic differentiation mechanisms for neural networks. The operations of addition, multiplication, and ReLU are fundamental to neural network computations and their training through backpropagation. 310 | 311 | ### Mathematical Foundations: 312 | 313 | 1. **Addition (`__add__`)**: 314 | - **Forward pass**: For two scalar values $$ a $$ and $$b $$, their sum \( s \) is simply \( s = a + b \). 315 | - **Backward pass**: The derivative of \( s \) with respect to both \( a \) and \( b \) is 1. Therefore, during backpropagation, the gradient of the output is passed directly to both inputs. 316 | 317 | 2. **Multiplication (`__mul__`)**: 318 | - **Forward pass**: For two scalar values \( a \) and \( b \), their product \( p \) is \( p = a \times b \). 319 | - **Backward pass**: The gradient of \( p \) with respect to \( a \) is \( b \), and with respect to \( b \) is \( a \). This means that during backpropagation, each input's gradient is the product of the other input and the output's gradient. 320 | 321 | 3. **ReLU Activation (`relu`)**: 322 | - **Forward pass**: The ReLU function is defined as \( R(x) = \max(0, x) \). This function outputs \( x \) if \( x \) is positive and 0 otherwise. 323 | - **Backward pass**: The derivative of the ReLU function is 1 for \( x > 0 \) and 0 for \( x \leq 0 \). Thus, the gradient is propagated through the function only if the input is positive; otherwise, it stops. 324 | 325 | ### Conceptual Application in Neural Networks: 326 | 327 | - **Addition and Multiplication**: These operations are ubiquitous in neural networks, forming the basis of computing weighted sums of inputs in the neurons. 328 | - **ReLU Activation**: Commonly used as an activation function in neural networks due to its simplicity and effectiveness in introducing non-linearity, making learning complex patterns possible. 329 | 330 | Understanding these operations and their implications on gradient flow is crucial for designing and training effective neural network models. By implementing these from scratch, one gains deeper insights into the workings of more sophisticated deep learning libraries. 331 | ''', 332 | 333 | "starter_code": """class Value: 334 | def __init__(self, data, _children=(), _op=''): 335 | self.data = data 336 | self.grad = 0 337 | self._backward = lambda: None 338 | self._prev = set(_children) 339 | self._op = _op 340 | def __repr__(self): 341 | return f"Value(data={self.data}, grad={self.grad})" 342 | 343 | def __add__(self, other): 344 | # Implement addition here 345 | pass 346 | 347 | def __mul__(self, other): 348 | # Implement multiplication here 349 | pass 350 | 351 | def relu(self): 352 | # Implement ReLU here 353 | pass 354 | 355 | def backward(self): 356 | # Implement backward pass here 357 | pass""", 358 | "solution": """ 359 | class Value: 360 | def __init__(self, data, _children=(), _op=''): 361 | self.data = data 362 | self.grad = 0 363 | self._backward = lambda: None 364 | self._prev = set(_children) 365 | self._op = _op 366 | 367 | def __add__(self, other): 368 | other = other if isinstance(other, Value) else Value(other) 369 | out = Value(self.data + other.data, (self, other), '+') 370 | def _backward(): 371 | self.grad += out.grad 372 | other.grad += out.grad 373 | out._backward = _backward 374 | return out 375 | 376 | def __mul__(self, other): 377 | other = other if isinstance(other, Value) else Value(other) 378 | out = Value(self.data * other.data, (self, other), '*') 379 | def _backward(): 380 | self.grad += other.data * out.grad 381 | other.grad += self.data * out.grad 382 | out._backward = _backward 383 | return out 384 | 385 | def relu(self): 386 | out = Value(0 if self.data < 0 else self.data, (self,), 'ReLU') 387 | def _backward(): 388 | self.grad += (out.data > 0) * out.grad 389 | out._backward = _backward 390 | return out 391 | 392 | def backward(self): 393 | topo = [] 394 | visited = set() 395 | def build_topo(v): 396 | if v not in visited: 397 | visited.add(v) 398 | for child in v._prev: 399 | build_topo(child) 400 | topo.append(v) 401 | build_topo(self) 402 | self.grad = 1 403 | for v in reversed(topo): 404 | v._backward() 405 | def __repr__(self): 406 | return f"Value(data={self.data}, grad={self.grad})" 407 | """, 408 | "test_cases": [ 409 | { 410 | "test": """a = Value(2);b = Value(3);c = Value(10);d = a + b * c ;e = Value(7) * Value(2);f = e + d;g = f.relu() 411 | g.backward() 412 | print(a,b,c,d,e,f,g) 413 | """, 414 | "expected_output": """ Value(data=2, grad=1) Value(data=3, grad=10) Value(data=10, grad=3) Value(data=32, grad=1) Value(data=14, grad=1) Value(data=46, grad=1) Value(data=46, grad=1)""" 415 | } 416 | ], 417 | "use_micro": False 418 | }, 419 | "Implementing and Training a Simple Neural Network (medium)": { 420 | "description": "Inspired by the foundational work in neural networks, your task is to build a basic multi-layer perceptron (MLP) that can be trained on a small dataset using stochastic gradient descent (SGD). The network should include forward and backward propagation capabilities for training. Implement a network with one hidden layer and ReLU activation, followed by an output layer with a linear activation for regression tasks. The network should also compute the mean squared error (MSE) loss and perform parameter updates via backpropagation.", 421 | "example": """Example: 422 | # Network setup 423 | mlp = MLP(2, [3, 1]) # 2 input features, 3 neurons in hidden layer, 1 output 424 | # Training data (simple xor function) 425 | inputs = [Value(0.5), Value(0.5)] 426 | target = Value(0.25) 427 | # Training loop 428 | for epoch in range(100): # Train for 100 epochs 429 | output = mlp(inputs) 430 | loss = (output - target) ** 2 # MSE loss 431 | mlp.zero_grad() # Zero gradients before backpropagation 432 | loss.backward() # Compute gradients 433 | mlp.update_parameters(0.01) # Update parameters with learning rate of 0.01 434 | print(f'Epoch {epoch}, Loss: {loss.data}') 435 | Output: Display loss per epoch to monitor training progress. 436 | Explanation: This setup trains the MLP on fixed data to minimize MSE loss, demonstrating basic network training dynamics.""", 437 | "learn": r''' 438 | ## Building and Training a Neural Network 439 | This task involves constructing a neural network that includes all necessary components for supervised learning, including: 440 | 441 | ### Components: 442 | - **Neuron**: Fundamental unit that computes weighted inputs plus a bias. 443 | - **Layer**: Composes multiple neurons to transform inputs to outputs. 444 | - **MLP**: Integrates layers to form a complete network. 445 | - **Forward Pass**: Computes the network's output. 446 | - **Loss Calculation**: Measures the network's prediction error. 447 | - **Backward Pass**: Applies the chain rule to compute gradients for learning. 448 | - **Parameter Update**: Adjusts the network's weights based on gradients to reduce loss. 449 | 450 | ### Conceptual Workflow: 451 | - Data is processed by the network to produce predictions. 452 | - Loss is calculated from the predictions and true data. 453 | - Gradients are calculated to understand how to adjust weights to improve predictions. 454 | - Parameters are updated based on these gradients to minimize future loss. 455 | 456 | By understanding each step, you gain insights into how neural networks learn from data, which is crucial for developing more complex AI systems. 457 | ''', 458 | "starter_code": """class MLP(Module): 459 | # Define your MLP architecture here 460 | # Implement forward, backward, and parameter update methods 461 | 462 | def train_network(): 463 | mlp = MLP(...) 464 | # Define your training loop 465 | 466 | train_network() 467 | """, 468 | "solution": """ 469 | import random 470 | 471 | class Module: 472 | def zero_grad(self): 473 | for p in self.parameters(): 474 | p.grad = 0 475 | 476 | def parameters(self): 477 | return [] 478 | 479 | class Neuron(Module): 480 | def __init__(self, nin, nonlin=True): 481 | self.w = [Value(random.uniform(-1,1)) for _ in range(nin)] 482 | self.b = Value(0) 483 | self.nonlin = nonlin 484 | 485 | def __call__(self, x): 486 | act = sum((wi*xi for wi,xi in zip(self.w, x)), self.b) 487 | return act.relu() if self.nonlin else act 488 | 489 | def parameters(self): 490 | return self.w + [self.b] 491 | 492 | class Layer(Module): 493 | def __init__(self, nin, nout, **kwargs): 494 | self.neurons = [Neuron(nin, **kwargs) for _ in range(nout)] 495 | 496 | def __call__(self, x): 497 | return [n(x) for n in self.neurons] 498 | 499 | def parameters(self): 500 | return [p for n in self.neurons for p in n.parameters()] 501 | 502 | class MLP(Module): 503 | def __init__(self, nin, nouts): 504 | sizes = [nin] + nouts 505 | self.layers = [Layer(sizes[i], sizes[i+1], nonlin=i Expected: {expected}, Got: {output}") 85 | else: 86 | st.error(f"Failed: {test} => Expected: {expected}, Got: {output}") 87 | all_passed = False 88 | if all_passed: 89 | st.balloons() 90 | 91 | 92 | 93 | # Button for "Show Solution" 94 | if st.button("Show Solution"): 95 | # Display the solution code 96 | st.subheader("Solution:") 97 | st.code(problem_info["solution"], language="python") 98 | 99 | if __name__ == "__main__": 100 | app() 101 | 102 | -------------------------------------------------------------------------------- /app/LinAlg.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | from streamlit_ace import st_ace 3 | from pistonpy import PistonApp 4 | 5 | from lin_alg_problems import problems 6 | 7 | # Instantiate the piston client 8 | piston = PistonApp() 9 | 10 | def execute_code(user_code): 11 | # Execute the user code using pistonpy 12 | result = piston.run(language="python", version="3.10.0", code=user_code) 13 | return result 14 | 15 | 16 | def run_test_cases(user_code, test_cases): 17 | results = [] 18 | for test_case in test_cases: 19 | # Modify user_code to include the test case at the end 20 | code_to_run = f"{user_code}\n\nprint({test_case['test']})" 21 | result = execute_code(code_to_run) 22 | 23 | stdout = result['run']['output'].strip() 24 | expected_output = test_case['expected_output'].strip() 25 | 26 | # Check if the test case passed 27 | passed = stdout == expected_output 28 | results.append((test_case['test'], expected_output, stdout, passed)) 29 | 30 | return results 31 | 32 | def app(): 33 | st.title("Machine Learning Challenge Platform") 34 | 35 | # Let user select a problem 36 | problem_names = list(problems.keys()) 37 | selected_problem = st.selectbox("Select a Problem:", problem_names) 38 | problem_info = problems[selected_problem] 39 | 40 | try: 41 | is_section = problem_info['section'] 42 | st.markdown(problem_info["description"]) 43 | 44 | except KeyError: 45 | 46 | # Display the selected problem 47 | st.header(selected_problem) 48 | st.write(problem_info["description"]) 49 | st.code(problem_info["example"]) 50 | 51 | # Button for "Show Solution" 52 | if st.button("Learn More"): 53 | # Display the solution code 54 | st.write(problem_info["learn"]) 55 | 56 | if st.button("Video"): 57 | try: 58 | VIDEO_URL = problem_info['video'] 59 | st.video(VIDEO_URL) 60 | except: 61 | st.write("Video coming soon") 62 | 63 | # Streamlit-ace editor for user code input 64 | 65 | user_code = st_ace(language="python", theme="twilight", key=f"code_editor_{selected_problem}", value=problem_info["starter_code"], height=350) 66 | st.warning('Make sure to apply changes to your code before running it') 67 | 68 | # Button for "Run Code" 69 | if st.button("Run Code"): 70 | # Execute user code without testing against test cases 71 | result = execute_code(user_code) 72 | if result: 73 | st.subheader("Execution Result:") 74 | stdout = result['run']['output'] 75 | st.text_area("Output", stdout, height=150) 76 | else: 77 | st.error("Failed to execute the code.",'Error:',stdout) 78 | 79 | # Button for "Submit Code" 80 | if st.button("Submit Code"): 81 | # Execute user code and run test cases 82 | results = run_test_cases(user_code, problem_info["test_cases"]) 83 | all_passed = True 84 | st.subheader("Test Results:") 85 | for test, expected, output, passed in results: 86 | if passed: 87 | st.success(f"Passed: {test} => Expected: {expected}, Got: {output}") 88 | else: 89 | st.error(f"Failed: {test} => Expected: {expected}, Got: {output}") 90 | all_passed = False 91 | if all_passed: 92 | st.balloons() 93 | 94 | 95 | 96 | # Button for "Show Solution" 97 | if st.button("Show Solution"): 98 | # Display the solution code 99 | st.subheader("Solution:") 100 | st.code(problem_info["solution"], language="python") 101 | 102 | if __name__ == "__main__": 103 | app() 104 | 105 | -------------------------------------------------------------------------------- /app/ML_problems.py: -------------------------------------------------------------------------------- 1 | problems = { 2 | "1. Machine Learning Fundamentals": { 3 | "section": True, 4 | "description": """## Machine Learning in Data Analysis and Prediction 5 | 6 | Machine Learning (ML) is a pivotal technology for data analysis, prediction, and automated decision-making. This section delves into the core concepts and algorithms of Machine Learning, providing a pathway to mastering the techniques that enable computers to learn from and make predictions based on data: 7 | 8 | ### Foundational Skills 9 | 10 | - **Supervised vs Unsupervised Learning**: Understand the differences between these two main types of learning and when to use each. 11 | - **Data Preprocessing**: Learn the importance of data cleaning, normalization, and splitting datasets for training and testing. 12 | - **Feature Engineering and Selection**: Discover how to enhance model performance by selecting or creating new features from existing data. 13 | - **Model Evaluation**: Grasp the concepts of overfitting, underfitting, and how to use metrics to evaluate a model's performance. 14 | 15 | ### Intermediate Understanding 16 | 17 | - **Classification Algorithms**: Dive into algorithms like Decision Trees, Support Vector Machines (SVM), and Random Forests, understanding their workings and applications. 18 | - **Regression Analysis**: Explore linear and non-linear regression models to predict continuous outcomes. 19 | - **Clustering Techniques**: Learn about K-Means, Hierarchical Clustering, and DBSCAN for segmenting datasets into meaningful groups. 20 | 21 | ### Advanced Techniques 22 | 23 | - **Deep Learning**: Introduce the fundamentals of neural networks, including convolutional and recurrent neural networks, for complex problems like image and speech recognition. 24 | - **Ensemble Methods**: Understand how combining models through techniques like Bagging and Boosting can improve prediction accuracy. 25 | - **Dimensionality Reduction**: Learn about Principal Component Analysis (PCA) and t-SNE for reducing the dimensionality of data while preserving its structure. 26 | 27 | Each topic is crafted to build upon the previous, ensuring a deep and comprehensive understanding of Machine Learning's role in data analysis and predictive modeling. Practical exercises and examples will illustrate how to apply these concepts to real-world scenarios, preparing learners to develop and evaluate their own machine learning models.""", 28 | "example": "", 29 | "learn": "", 30 | "starter_code": "", 31 | "solution": "", 32 | "test_cases": [] 33 | } 34 | , 35 | "Entropy Calculation (easy)": { 36 | "description": "Write a Python function that calculates the entropy of a dataset. The function should take a list of class labels as input and return the entropy of the dataset. Round your answer to four decimal places.", 37 | "example": """Example: 38 | input: labels = [1, 1, 1, 0, 0, 0] 39 | output: 1.0 40 | reasoning: There are two classes (1 and 0), each occurring 3 times out of 6, leading to a probability of 0.5 for each class. The entropy is -2 * (0.5 * log2(0.5)) = 1.0.""", 41 | "learn": r''' 42 | ## Entropy in Information Theory and Machine Learning 43 | 44 | Entropy is a measure of the unpredictability or randomness of a dataset. In the context of machine learning, particularly in decision tree algorithms, entropy can be used to quantify the impurity or disorder within a set of items. It helps in determining the best features that contribute to dividing the dataset into the best possible homogeneous sets. 45 | 46 | The formula for entropy of a dataset is: 47 | 48 | $$ 49 | H(X) = -\sum_{i=1}^{n} p(x_i) \cdot \log_2(p(x_i)) 50 | $$ 51 | 52 | Where: 53 | - $$H(X)$$ is the entropy of the set $$X$$, 54 | - $$p(x_i)$$ is the probability of occurrence of class $$x_i$$ in the set, 55 | - The sum is calculated over all unique classes in the dataset. 56 | 57 | Entropy is 0 when the dataset is completely uniform (all elements belong to a single class), and it reaches its maximum value when the dataset is evenly split between classes. 58 | 59 | ### Practical Implementation 60 | 61 | Calculating the entropy of a dataset involves determining the frequency of each class in the dataset, calculating the probability of each class, and then applying the entropy formula. 62 | ''', 63 | 64 | "starter_code": """import numpy as np 65 | def calculate_entropy(labels: list) -> float: 66 | # Your code here, make sure to round 67 | return entropy""", 68 | "solution": """ 69 | import numpy as np 70 | def calculate_entropy(labels: list) -> float: 71 | _, counts = np.unique(labels, return_counts=True) 72 | probabilities = counts / counts.sum() 73 | entropy = -np.sum(probabilities * np.log2(probabilities)) 74 | return np.round(entropy, 4)""", 75 | "test_cases": [ 76 | { 77 | "test": "calculate_entropy([1, 1, 1, 0, 0, 0])", 78 | "expected_output": "1.0" 79 | }, 80 | { 81 | "test": "calculate_entropy([1, 1, 1, 1, 0, 0, 0, 0])", 82 | "expected_output": "1.0" 83 | }, 84 | { 85 | "test": "calculate_entropy([1, 1, 0, 0, 0, 0])", 86 | "expected_output": "0.9183" 87 | }, 88 | { 89 | "test": "calculate_entropy([1, 1, 1, 1, 1, 0])", 90 | "expected_output": "0.65" 91 | } 92 | ], 93 | }, 94 | 95 | "Linear Regression Using Normal Equation (easy)": { 96 | "description": "Write a Python function that performs linear regression using the normal equation. The function should take a matrix X (features) and a vector y (target) as input, and return the coefficients of the linear regression model. Round your answer to four decimal places, -0.0 is a valid result for rounding a very small number.", 97 | "example": """Example: 98 | input: X = [[1, 1], [1, 2], [1, 3]], y = [1, 2, 3] 99 | output: [0.0, 1.0] 100 | reasoning: The linear model is y = 0.0 + 1.0*x, perfectly fitting the input data.""", 101 | "learn": r''' 102 | ## Linear Regression Using the Normal Equation 103 | 104 | Linear regression aims to model the relationship between a scalar dependent variable $$y$$ and one or more explanatory variables (or independent variables) $$X$$. The normal equation provides an analytical solution to finding the coefficients $$\theta$$ that minimize the cost function for linear regression. 105 | 106 | Given a matrix $$X$$ (with each row representing a training example and each column a feature) and a vector $$y$$ (representing the target values), the normal equation is: 107 | 108 | $$ 109 | \theta = (X^TX)^{-1}X^Ty 110 | $$ 111 | 112 | Where: 113 | - $$X^T$$ is the transpose of $$X$$, 114 | - $$(X^TX)^{-1}$$ is the inverse of the matrix $$X^TX$$, 115 | - $$y$$ is the vector of target values. 116 | 117 | **Things to note**: This method does not require any feature scaling, and there's no need to choose a learning rate. However, computing the inverse of $$X^TX$$ can be computationally expensive if the number of features is very large. 118 | 119 | ### Practical Implementation 120 | 121 | A practical implementation involves augmenting $$X$$ with a column of ones to account for the intercept term and then applying the normal equation directly to compute $$\theta$$. 122 | ''', 123 | 124 | "starter_code": """import numpy as np\n def linear_regression_normal_equation(X: list[list[float]], y: list[float]) -> list[float]: 125 | # Your code here, make sure to round 126 | return theta""", 127 | "solution": """ 128 | import numpy as np 129 | def linear_regression_normal_equation(X: list[list[float]], y: list[float]) -> list[float]: 130 | X = np.array(X) 131 | y = np.array(y).reshape(-1, 1) 132 | X_transpose = X.T 133 | theta = np.linalg.inv(X_transpose.dot(X)).dot(X_transpose).dot(y) 134 | theta = np.round(theta,4).flatten().tolist() 135 | return theta""", 136 | "test_cases": [ 137 | { 138 | "test": "linear_regression_normal_equation([[1,1], [1,2], [1,3]], [1, 2, 3])", 139 | "expected_output": "[-0.0, 1.0]" 140 | }, 141 | { 142 | "test": "linear_regression_normal_equation([[1, 3, 4], [1, 2, 5], [1, 3, 2]], [1,2,1])", 143 | "expected_output": "[4.0, -1.0, -0.0]" 144 | } 145 | ], 146 | }, 147 | "Linear Regression Using Gradient Descent (easy)": { 148 | "description": "Write a Python function that performs linear regression using gradient descent. The function should take NumPy arrays X (features with a column of ones for the intercept) and y (target) as input, along with learning rate alpha and the number of iterations, and return the coefficients of the linear regression model as a NumPy array. Round your answer to four decimal places. -0.0 is a valid result for rounding a very small number.", 149 | "example": """Example: 150 | input: X = np.array([[1, 1], [1, 2], [1, 3]]), y = np.array([1, 2, 3]), alpha = 0.01, iterations = 1000 151 | output: np.array([0.1107, 0.9513]) 152 | reasoning: The linear model is y = 0.0 + 1.0*x, which fits the input data after gradient descent optimization.""", 153 | "learn": r''' 154 | ## Linear Regression Using Gradient Descent 155 | 156 | Linear regression can also be performed using a technique called gradient descent, where the coefficients (or weights) of the model are iteratively adjusted to minimize a cost function (usually mean squared error). This method is particularly useful when the number of features is too large for analytical solutions like the normal equation or when the feature matrix is not invertible. 157 | 158 | The gradient descent algorithm updates the weights by moving in the direction of the negative gradient of the cost function with respect to the weights. The updates occur iteratively until the algorithm converges to a minimum of the cost function. 159 | 160 | The update rule for each weight is given by: 161 | 162 | $$ 163 | \theta_j := \theta_j - \alpha \frac{1}{m} \sum_{i=1}^{m} \left( h_{\theta}(x^{(i)}) - y^{(i)} \right)x_j^{(i)} 164 | $$ 165 | 166 | Where: 167 | - $$\alpha$$ is the learning rate, 168 | - $$m$$ is the number of training examples, 169 | - $$h_{\theta}(x^{(i)})$$ is the hypothesis function at iteration $$i$$, 170 | - $$x^{(i)}$$ is the feature vector of the $$i$$th training example, 171 | - $$y^{(i)}$$ is the actual target value for the $$i$$th training example, 172 | - $$x_j^{(i)}$$ is the value of feature $$j$$ for the $$i$$th training example. 173 | 174 | **Things to note**: The choice of learning rate and the number of iterations are crucial for the convergence and performance of gradient descent. Too small a learning rate may lead to slow convergence, while too large a learning rate may cause overshooting and divergence. 175 | 176 | ### Practical Implementation 177 | 178 | Implementing gradient descent involves initializing the weights, computing the gradient of the cost function, and iteratively updating the weights according to the update rule. 179 | ''', 180 | 181 | "starter_code": """import numpy as np 182 | def linear_regression_gradient_descent(X: np.ndarray, y: np.ndarray, alpha: float, iterations: int) -> np.ndarray: 183 | # Your code here, make sure to round 184 | m, n = X.shape 185 | theta = np.zeros((n, 1)) 186 | return theta""", 187 | "solution": """ 188 | import numpy as np 189 | def linear_regression_gradient_descent(X: np.ndarray, y: np.ndarray, alpha: float, iterations: int) -> np.ndarray: 190 | m, n = X.shape 191 | theta = np.zeros((n, 1)) 192 | for _ in range(iterations): 193 | predictions = X @ theta 194 | errors = predictions - y.reshape(-1, 1) 195 | updates = X.T @ errors / m 196 | theta -= alpha * updates 197 | return np.round(theta.flatten(), 4)""", 198 | "test_cases": [ 199 | { 200 | "test": "linear_regression_gradient_descent(np.array([[1, 1], [1, 2], [1, 3]]), np.array([1, 2, 3]), 0.01, 1000)", 201 | "expected_output": "[0.1107 0.9513]" 202 | }, 203 | { 204 | "test": "linear_regression_gradient_descent(np.array([[1, 1, 3], [1, 2, 4], [1, 3, 5]]), np.array([2, 3, 5]), 0.1, 10)", 205 | "expected_output": "[-1.0241 -1.9133 -3.9616]" 206 | } 207 | ], 208 | }, 209 | "Feature Scaling Implementation (easy)": { 210 | "description": "Write a Python function that performs feature scaling on a dataset using both standardization and min-max normalization. The function should take a 2D NumPy array as input, where each row represents a data sample and each column represents a feature. It should return two 2D NumPy arrays: one scaled by standardization and one by min-max normalization. Make sure all results are rounded to the nearest 4th decimal.", 211 | "example": """Example: 212 | input: data = np.array([[1, 2], [3, 4], [5, 6]]) 213 | output: ([[-1.2247, -1.2247], [0.0, 0.0], [1.2247, 1.2247]], [[0.0, 0.0], [0.5, 0.5], [1.0, 1.0]]) 214 | reasoning: Standardization rescales the feature to have a mean of 0 and a standard deviation of 1. Min-max normalization rescales the feature to a range of [0, 1], where the minimum feature value maps to 0 and the maximum to 1.""", 215 | "learn": r''' 216 | ## Feature Scaling Techniques 217 | 218 | Feature scaling is crucial in many machine learning algorithms that are sensitive to the magnitude of features. This includes algorithms that use distance measures like k-nearest neighbors and gradient descent-based algorithms like linear regression. 219 | 220 | ### Standardization: 221 | Standardization (or Z-score normalization) is the process where the features are rescaled so that they have the properties of a standard normal distribution with a mean of zero and a standard deviation of one: 222 | $$ 223 | z = \frac{(x - \mu)}{\sigma} 224 | $$ 225 | Where \(x\) is the original feature, $$mu$$ is the mean of that feature, and $$sigma$$ is the standard deviation. 226 | 227 | ### Min-Max Normalization: 228 | Min-max normalization rescales the feature to a fixed range, typically 0 to 1, or it can be shifted to any range \([a, b]\) by transforming the data according to the formula: 229 | $$ 230 | x' = \frac{(x - \text{min}(x))}{(\text{max}(x) - \text{min}(x))} \times (\text{max} - \text{min}) + \text{min} 231 | $$ 232 | Where $$x$$ is the original value, $${min}(x)$$ is the minimum value for that feature, $${max}(x)$$ is the maximum value, and $${min}$$ and $${max}$$ are the new minimum and maximum values for the scaled data. 233 | 234 | Implementing these scaling techniques will ensure that the features contribute equally to the development of the model and improve the convergence speed of learning algorithms. 235 | ''', 236 | 237 | "starter_code": """def feature_scaling(data: np.ndarray) -> (np.ndarray, np.ndarray): 238 | # Your code here 239 | return standardized_data, normalized_data""", 240 | "solution": """ 241 | import numpy as np 242 | 243 | def feature_scaling(data): 244 | # Standardization 245 | mean = np.mean(data, axis=0) 246 | std = np.std(data, axis=0) 247 | standardized_data = (data - mean) / std 248 | 249 | # Min-Max Normalization 250 | min_val = np.min(data, axis=0) 251 | max_val = np.max(data, axis=0) 252 | normalized_data = (data - min_val) / (max_val - min_val) 253 | 254 | return np.round(standardized_data,4).tolist(), np.round(normalized_data,4).tolist()""", 255 | "test_cases": [ 256 | { 257 | "test": "feature_scaling(np.array([[1, 2], [3, 4], [5, 6]]))", 258 | "expected_output": "([[-1.2247, -1.2247], [0.0, 0.0], [1.2247, 1.2247]], [[0.0, 0.0], [0.5, 0.5], [1.0, 1.0]])" 259 | } 260 | ], 261 | } 262 | 263 | , 264 | "K-Means Clustering(medium)": { 265 | "description": "Write a Python function that implements the k-Means algorithm for clustering, starting with specified initial centroids and a set number of iterations. The function should take a list of points (each represented as a tuple of coordinates), an integer k representing the number of clusters to form, a list of initial centroids (each a tuple of coordinates), and an integer representing the maximum number of iterations to perform. The function will iteratively assign each point to the nearest centroid and update the centroids based on the assignments until the centroids do not change significantly, or the maximum number of iterations is reached. The function should return a list of the final centroids of the clusters. Round to the nearest fourth decimal.", 266 | "example": """Example: 267 | input: points = [(1, 2), (1, 4), (1, 0), (10, 2), (10, 4), (10, 0)], k = 2, initial_centroids = [(1, 1), (10, 1)], max_iterations = 10 268 | output: [(1, 2), (10, 2)] 269 | reasoning: Given the initial centroids and a maximum of 10 iterations, 270 | the points are clustered around these points, and the centroids are 271 | updated to the mean of the assigned points, resulting in the final 272 | centroids which approximate the means of the two clusters. 273 | The exact number of iterations needed may vary, 274 | but the process will stop after 10 iterations at most.""", 275 | "learn": r''' 276 | ## Implementing k-Means Clustering 277 | 278 | k-Means clustering is a method to partition `n` points into `k` clusters. Here is a brief overview of how to implement the k-Means algorithm: 279 | 280 | 1. **Initialization**: Start by selecting `k` initial centroids. These can be randomly selected from the dataset or based on prior knowledge. 281 | 282 | 2. **Assignment Step**: For each point in the dataset, find the nearest centroid. The "nearest" can be defined using Euclidean distance. Assign the point to the cluster represented by this nearest centroid. 283 | 284 | 3. **Update Step**: Once all points are assigned to clusters, update the centroids by calculating the mean of all points in each cluster. This becomes the new centroid of the cluster. 285 | 286 | 4. **Iteration**: Repeat the assignment and update steps until the centroids no longer change significantly, or until a predetermined number of iterations have been completed. This iterative process helps in refining the clusters to minimize within-cluster variance. 287 | 288 | 5. **Result**: The final centroids represent the center of the clusters, and the points are partitioned accordingly. 289 | 290 | This algorithm assumes that the `mean` is a meaningful measure, which might not be the case for non-numeric data. The choice of initial centroids can significantly affect the final clusters, hence multiple runs with different starting points can lead to a more comprehensive understanding of the cluster structure in the data. 291 | ''', 292 | 293 | "starter_code": """def k_means_clustering(points: list[tuple[float, float]], k: int, initial_centroids: list[tuple[float, float]], max_iterations: int) -> list[tuple[float, float]]: 294 | # Your code here 295 | return final_centroids""", 296 | "solution": """ 297 | import numpy as np 298 | 299 | def euclidean_distance(a, b): 300 | return np.sqrt(((a - b) ** 2).sum(axis=1)) 301 | 302 | def k_means_clustering(points, k, initial_centroids, max_iterations): 303 | points = np.array(points) 304 | centroids = np.array(initial_centroids) 305 | 306 | for iteration in range(max_iterations): 307 | # Assign points to the nearest centroid 308 | distances = np.array([euclidean_distance(points, centroid) for centroid in centroids]) 309 | assignments = np.argmin(distances, axis=0) 310 | 311 | new_centroids = np.array([points[assignments == i].mean(axis=0) if len(points[assignments == i]) > 0 else centroids[i] for i in range(k)]) 312 | 313 | # Check for convergence 314 | if np.all(centroids == new_centroids): 315 | break 316 | centroids = new_centroids 317 | centroids = np.round(centroids,4) 318 | return [tuple(centroid) for centroid in centroids]""", 319 | "test_cases": [ 320 | { 321 | "test": "k_means_clustering([(1, 2), (1, 4), (1, 0), (10, 2), (10, 4), (10, 0)], 2, [(1, 1), (10, 1)], 10)", 322 | "expected_output": "[(1.0, 2.0), (10.0, 2.0)]" 323 | }, 324 | { 325 | "test": "k_means_clustering([(0, 0, 0), (2, 2, 2), (1, 1, 1), (9, 10, 9), (10, 11, 10), (12, 11, 12)], 2, [(1, 1, 1), (10, 10, 10)], 10)", 326 | "expected_output": "[(1.0, 1.0, 1.0), (10.3333, 10.6667, 10.3333)]" 327 | } 328 | ], 329 | }, 330 | "Cross-Validation Data Split Implementation (medium)": { 331 | "description": "Write a Python function that performs k-fold cross-validation data splitting from scratch. The function should take a dataset (as a 2D NumPy array where each row represents a data sample and each column represents a feature) and an integer k representing the number of folds. The function should split the dataset into k parts, systematically use one part as the test set and the remaining as the training set, and return a list where each element is a tuple containing the training set and test set for each fold.", 332 | "example": """Example: 333 | input: data = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]), k = 5 334 | output: [[[[3, 4], [5, 6], [7, 8], [9, 10]], [[1, 2]]], 335 | [[[1, 2], [5, 6], [7, 8], [9, 10]], [[3, 4]]], 336 | [[[1, 2], [3, 4], [7, 8], [9, 10]], [[5, 6]]], 337 | [[[1, 2], [3, 4], [5, 6], [9, 10]], [[7, 8]]], 338 | [[[1, 2], [3, 4], [5, 6], [7, 8]], [[9, 10]]]] 339 | reasoning: The dataset is divided into 5 parts, each being used once as a test set while the remaining parts serve as the training set.""", 340 | "learn": r''' 341 | ## Understanding k-Fold Cross-Validation Data Splitting 342 | 343 | k-Fold cross-validation is a technique used to evaluate the generalizability of a model by dividing the data into `k` folds or subsets. Each fold acts as a test set once, with the remaining `k-1` folds serving as the training set. This approach ensures that every data point gets used for both training and testing, improving model validation. 344 | 345 | ### Steps in k-Fold Cross-Validation Data Split: 346 | 347 | 1. **Shuffle the dataset randomly**. (but not in this case becuase we test for a unique result) 348 | 2. **Split the dataset into k groups**. 349 | 3. **Generate Data Splits**: For each group, treat that group as the test set and the remaining groups as the training set. 350 | 351 | ### Benefits of this Approach: 352 | 353 | - Ensures all data is used for both training and testing. 354 | - Reduces bias since each data point gets to be in a test set exactly once. 355 | - Provides a more robust estimate of model performance. 356 | 357 | Implementing this data split function will allow a deeper understanding of how data partitioning affects machine learning models and will provide a foundation for more complex validation techniques. 358 | ''', 359 | 360 | "starter_code": """def cross_validation_split(data: np.ndarray, k: int) -> list: 361 | # Your code here 362 | return folds""", 363 | "solution": """ 364 | import numpy as np 365 | 366 | def cross_validation_split(data, k): 367 | np.random.shuffle(data) # This line can be removed if shuffling is not desired in examples 368 | fold_size = len(data) // k 369 | folds = [] 370 | 371 | for i in range(k): 372 | start, end = i * fold_size, (i + 1) * fold_size if i != k-1 else len(data) 373 | test = data[start:end] 374 | train = np.concatenate([data[:start], data[end:]]) 375 | folds.append([train.tolist(), test.tolist()]) 376 | 377 | return folds""", 378 | "test_cases": [ 379 | { 380 | "test": "cross_validation_split(np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]), 2)", 381 | "expected_output": 382 | """[[[[5, 6], [7, 8], [9, 10]], [[1, 2], [3, 4]]], [[[1, 2], [3, 4]], [[5, 6], [7, 8], [9, 10]]]]""" 383 | } 384 | ], 385 | } 386 | 387 | , 388 | 389 | 390 | "Principal Component Analysis (PCA) Implementation (medium)": { 391 | "description": "Write a Python function that performs Principal Component Analysis (PCA) from scratch. The function should take a 2D NumPy array as input, where each row represents a data sample and each column represents a feature. The function should standardize the dataset, compute the covariance matrix, find the eigenvalues and eigenvectors, and return the principal components (the eigenvectors corresponding to the largest eigenvalues). The function should also take an integer k as input, representing the number of principal components to return.", 392 | "example": """Example: 393 | input: data = np.array([[1, 2], [3, 4], [5, 6]]), k = 1 394 | output: [[0.7071], [0.7071]] 395 | reasoning: After standardizing the data and computing the covariance matrix, the eigenvalues and eigenvectors are calculated. The largest eigenvalue's corresponding eigenvector is returned as the principal component, rounded to four decimal places.""", 396 | "learn": r''' 397 | ## Understanding Eigenvalues in PCA 398 | 399 | Principal Component Analysis (PCA) utilizes the concept of eigenvalues and eigenvectors to identify the principal components of a dataset. Here's how eigenvalues fit into the PCA process: 400 | 401 | ### Eigenvalues and Eigenvectors: The Foundation of PCA 402 | 403 | For a given square matrix \(A\), representing the covariance matrix in PCA, eigenvalues \(\lambda\) and their corresponding eigenvectors \(v\) satisfy: 404 | $$ 405 | Av = \lambda v 406 | $$ 407 | 408 | ### Calculating Eigenvalues 409 | 410 | The eigenvalues of matrix \(A\) are found by solving the characteristic equation: 411 | $$ 412 | \det(A - \lambda I) = 0 413 | $$ 414 | where \(I\) is the identity matrix of the same dimension as \(A\). This equation highlights the relationship between a matrix, its eigenvalues, and eigenvectors. 415 | 416 | ### Role in PCA 417 | 418 | In PCA, the covariance matrix's eigenvalues represent the variance explained by its eigenvectors. Thus, selecting the eigenvectors associated with the largest eigenvalues is akin to choosing the principal components that retain the most data variance. 419 | 420 | ### Eigenvalues and Dimensionality Reduction 421 | 422 | The magnitude of an eigenvalue correlates with the importance of its corresponding eigenvector (principal component) in representing the dataset's variability. By selecting a subset of eigenvectors corresponding to the largest eigenvalues, PCA achieves dimensionality reduction while preserving as much of the dataset's variability as possible. 423 | 424 | ### Practical Application 425 | 426 | 1. **Standardize the Dataset**: Ensure that each feature has a mean of 0 and a standard deviation of 1. 427 | 2. **Compute the Covariance Matrix**: Reflects how features vary together. 428 | 3. **Find Eigenvalues and Eigenvectors**: Solve the characteristic equation for the covariance matrix. 429 | 4. **Select Principal Components**: Choose eigenvectors (components) with the highest eigenvalues for dimensionality reduction. 430 | 431 | Through this process, PCA transforms the original features into a new set of uncorrelated features (principal components), ordered by the amount of original variance they explain. 432 | ''', 433 | 434 | "starter_code": """import numpy as np \ndef pca(data: np.ndarray, k: int) -> list[list[int|float]]: 435 | # Your code here 436 | return principal_components""", 437 | "solution": """ 438 | import numpy as np 439 | 440 | def pca(data, k): 441 | # Standardize the data 442 | data_standardized = (data - np.mean(data, axis=0)) / np.std(data, axis=0) 443 | 444 | # Compute the covariance matrix 445 | covariance_matrix = np.cov(data_standardized, rowvar=False) 446 | 447 | # Eigen decomposition 448 | eigenvalues, eigenvectors = np.linalg.eig(covariance_matrix) 449 | 450 | # Sort the eigenvectors by decreasing eigenvalues 451 | idx = np.argsort(eigenvalues)[::-1] 452 | eigenvalues_sorted = eigenvalues[idx] 453 | eigenvectors_sorted = eigenvectors[:,idx] 454 | 455 | # Select the top k eigenvectors (principal components) 456 | principal_components = eigenvectors_sorted[:, :k] 457 | 458 | return np.round(principal_components, 4).tolist()""", 459 | "test_cases": [ 460 | { 461 | "test": "pca(np.array([[4,2,1],[5,6,7],[9,12,1],[4,6,7]]),2)", 462 | "expected_output": "[[0.6855, 0.0776], [0.6202, 0.4586], [-0.3814, 0.8853]]" 463 | }, 464 | { 465 | "test": "pca(np.array([[1, 2], [3, 4], [5, 6]]), k = 1)", 466 | "expected_output": " [[0.7071], [0.7071]]" 467 | } 468 | ], 469 | } 470 | 471 | , 472 | 473 | "Decision Tree Learning (hard)": { 474 | "description": "Write a Python function that implements the decision tree learning algorithm for classification. The function should use recursive binary splitting based on entropy and information gain to build a decision tree. It should take a list of examples (each example is a dict of attribute-value pairs) and a list of attribute names as input, and return a nested dictionary representing the decision tree.", 475 | "example":""" 476 | Example: 477 | input: examples = [ 478 | {'Outlook': 'Sunny', 'Temperature': 'Hot', 'Humidity': 'High', 'Wind': 'Weak', 'PlayTennis': 'No'}, 479 | {'Outlook': 'Sunny', 'Temperature': 'Hot', 'Humidity': 'High', 'Wind': 'Strong', 'PlayTennis': 'No'}, 480 | {'Outlook': 'Overcast', 'Temperature': 'Hot', 'Humidity': 'High', 'Wind': 'Weak', 'PlayTennis': 'Yes'}, 481 | {'Outlook': 'Rain', 'Temperature': 'Mild', 'Humidity': 'High', 'Wind': 'Weak', 'PlayTennis': 'Yes'} 482 | ], 483 | attributes = ['Outlook', 'Temperature', 'Humidity', 'Wind'] 484 | output: { 485 | 'Outlook': { 486 | 'Sunny': {'Humidity': {'High': 'No', 'Normal': 'Yes'}}, 487 | 'Overcast': 'Yes', 488 | 'Rain': {'Wind': {'Weak': 'Yes', 'Strong': 'No'}} 489 | } 490 | } 491 | reasoning: Using the given examples, the decision tree algorithm determines that 'Outlook' is the best attribute to split the data initially. When 'Outlook' is 'Overcast', the outcome is always 'Yes', so it becomes a leaf node. In cases of 'Sunny' and 'Rain', it further splits based on 'Humidity' and 'Wind', respectively. The resulting tree structure is able to classify the training examples with the attributes 'Outlook', 'Temperature', 'Humidity', and 'Wind'. 492 | """, 493 | "learn": "## Decision Tree Learning Algorithm\n\nThe decision tree learning algorithm is a method used for classification that predicts the value of a target variable based on several input variables. Each internal node of the tree corresponds to an input variable, and each leaf node corresponds to a class label.\n\nThe recursive binary splitting starts by selecting the attribute that best separates the examples according to the entropy and information gain, which are calculated as follows:\n\nEntropy: $$H(X) = -\\sum p(x) \\log_2 p(x)$$ \n\n Information Gain: $$IG(D, A) = H(D) - \\sum \\frac{|D_v|}{|D|} H(D_v)$$\n\nWhere:\n- $$H(X)$$ is the entropy of the set,\n- $$IG(D, A)$$ is the information gain of dataset $$D$$ after splitting on attribute $$A$$,\n- $$D_v$$ is the subset of $$D$$ for which attribute $$A$$ has value $$v$$.\n\nThe attribute with the highest information gain is used at each step, and the dataset is split based on this attribute's values. This process continues recursively until all data is perfectly classified or no remaining attributes can be used to make a split.", 494 | "starter_code": "def learn_decision_tree(examples: list[dict], attributes: list[str], target_attr: str) -> dict:\n # Your code here\n return decision_tree", 495 | "solution": """ 496 | import math 497 | from collections import Counter 498 | 499 | def calculate_entropy(labels): 500 | label_counts = Counter(labels) 501 | total_count = len(labels) 502 | entropy = -sum((count / total_count) * math.log2(count / total_count) for count in label_counts.values()) 503 | return entropy 504 | 505 | def calculate_information_gain(examples, attr, target_attr): 506 | total_entropy = calculate_entropy([example[target_attr] for example in examples]) 507 | values = set(example[attr] for example in examples) 508 | attr_entropy = 0 509 | for value in values: 510 | value_subset = [example[target_attr] for example in examples if example[attr] == value] 511 | value_entropy = calculate_entropy(value_subset) 512 | attr_entropy += (len(value_subset) / len(examples)) * value_entropy 513 | return total_entropy - attr_entropy 514 | 515 | def majority_class(examples, target_attr): 516 | return Counter([example[target_attr] for example in examples]).most_common(1)[0][0] 517 | 518 | def learn_decision_tree(examples, attributes, target_attr): 519 | if not examples: 520 | return 'No examples' 521 | if all(example[target_attr] == examples[0][target_attr] for example in examples): 522 | return examples[0][target_attr] 523 | if not attributes: 524 | return majority_class(examples, target_attr) 525 | 526 | gains = {attr: calculate_information_gain(examples, attr, target_attr) for attr in attributes} 527 | best_attr = max(gains, key=gains.get) 528 | tree = {best_attr: {}} 529 | 530 | for value in set(example[best_attr] for example in examples): 531 | subset = [example for example in examples if example[best_attr] == value] 532 | new_attributes = attributes.copy() 533 | new_attributes.remove(best_attr) 534 | subtree = learn_decision_tree(subset, new_attributes, target_attr) 535 | tree[best_attr][value] = subtree 536 | 537 | return tree 538 | """, 539 | "test_cases": [ 540 | { 541 | "test": "learn_decision_tree([\n" 542 | " {'Outlook': 'Sunny', 'Wind': 'Weak', 'PlayTennis': 'No'},\n" 543 | " {'Outlook': 'Overcast', 'Wind': 'Strong', 'PlayTennis': 'Yes'},\n" 544 | " {'Outlook': 'Rain', 'Wind': 'Weak', 'PlayTennis': 'Yes'},\n" 545 | " {'Outlook': 'Sunny', 'Wind': 'Strong', 'PlayTennis': 'No'},\n" 546 | " {'Outlook': 'Sunny', 'Wind': 'Weak', 'PlayTennis': 'Yes'},\n" 547 | " {'Outlook': 'Overcast', 'Wind': 'Weak', 'PlayTennis': 'Yes'},\n" 548 | " {'Outlook': 'Rain', 'Wind': 'Strong', 'PlayTennis': 'No'},\n" 549 | " {'Outlook': 'Rain', 'Wind': 'Weak', 'PlayTennis': 'Yes'}\n" 550 | "], ['Outlook', 'Wind'], 'PlayTennis')", 551 | "expected_output": "{'Outlook': {'Sunny': {'Wind': {'Weak': 'No', 'Strong': 'No'}}, 'Rain': {'Wind': {'Weak': 'Yes', 'Strong': 'No'}}, 'Overcast': 'Yes'}}" 552 | } 553 | ] 554 | 555 | 556 | },"Pegasos Kernel SVM Implementation (advanced)": { 557 | "description": "Write a Python function that implements the Pegasos algorithm to train a kernel SVM classifier from scratch. The function should take a dataset (as a 2D NumPy array where each row represents a data sample and each column represents a feature), a label vector (1D NumPy array where each entry corresponds to the label of the sample), and training parameters such as the choice of kernel (linear or RBF), regularization parameter (lambda), and the number of iterations. The function should perform binary classification and return the model's alpha coefficients and bias.", 558 | "example": """Example: 559 | input: data = np.array([[1, 2], [2, 3], [3, 1], [4, 1]]), labels = np.array([1, 1, -1, -1]), kernel = 'rbf', lambda_val = 0.01, iterations = 100 560 | output: alpha = [0.03, 0.02, 0.05, 0.01], b = -0.05 561 | reasoning: Using the RBF kernel, the Pegasos algorithm iteratively updates the weights based on a sub-gradient descent method, taking into account the non-linear separability of the data induced by the kernel transformation.""", 562 | "learn": r''' 563 | ## Pegasos Algorithm and Kernel SVM 564 | 565 | The Pegasos (Primal Estimated sub-GrAdient SOlver for SVM) algorithm is a simple and efficient stochastic gradient descent method designed for solving the SVM optimization problem in its primal form. 566 | 567 | ### Key Concepts: 568 | 569 | - **Kernel Trick**: Allows SVM to classify data that is not linearly separable by implicitly mapping input features into high-dimensional feature spaces. 570 | - **Regularization Parameter (λ)**: Controls the trade-off between achieving a low training error and a low model complexity. 571 | - **Sub-Gradient Descent**: Used in the Pegasos algorithm to optimize the objective function, which includes both the hinge loss and a regularization term. 572 | 573 | ### Steps in the Pegasos Algorithm: 574 | 575 | 1. **Initialize Parameters**: Start with zero weights and choose an appropriate value for the regularization parameter \( \lambda \). 576 | 2. **Iterative Updates**: For each iteration and for each randomly selected example, update the model parameters using the learning rule derived from the sub-gradient of the loss function. 577 | 3. **Kernel Adaptation**: Use the chosen kernel to compute the dot products required in the update step, allowing for non-linear decision boundaries. 578 | 579 | ### Practical Implementation: 580 | 581 | The implementation involves selecting a kernel function, calculating the kernel matrix, and performing iterative updates on the alpha coefficients according to the Pegasos rule: 582 | $$ 583 | \alpha_{t+1} = (1 - \eta_t \lambda) \alpha_t + \eta_t (y_i K(x_i, x)) 584 | $$ 585 | where \( \eta_t \) is the learning rate at iteration \( t \), and \( K \) denotes the kernel function. 586 | 587 | This method is particularly well-suited for large-scale learning problems due to its efficient use of data and incremental learning nature. 588 | ''', 589 | 590 | "starter_code": """def pegasos_kernel_svm(data: np.ndarray, labels: np.ndarray, kernel='linear', lambda_val=0.01, iterations=100) -> (list, float): 591 | # Your code here 592 | return alphas, b""", 593 | "solution": """ 594 | import numpy as np 595 | 596 | def linear_kernel(x, y): 597 | return np.dot(x, y) 598 | 599 | def rbf_kernel(x, y, sigma=1.0): 600 | return np.exp(-np.linalg.norm(x-y)**2 / (2 * (sigma ** 2))) 601 | 602 | def pegasos_kernel_svm(data, labels, kernel='linear', lambda_val=0.01, iterations=100, sigma=1.0): 603 | n_samples = len(data) 604 | alphas = np.zeros(n_samples) 605 | b = 0 606 | 607 | for t in range(1, iterations + 1): 608 | for i in range(n_samples): 609 | eta = 1.0 / (lambda_val * t) 610 | if kernel == 'linear': 611 | kernel_func = linear_kernel 612 | elif kernel == 'rbf': 613 | kernel_func = lambda x, y: rbf_kernel(x, y, sigma) 614 | 615 | decision = sum(alphas[j] * labels[j] * kernel_func(data[j], data[i]) for j in range(n_samples)) + b 616 | if labels[i] * decision < 1: 617 | alphas[i] += eta * (labels[i] - lambda_val * alphas[i]) 618 | b += eta * labels[i] 619 | 620 | return np.round(alphas,4).tolist(), np.round(b,4)""", 621 | "test_cases": [ 622 | { 623 | "test": "pegasos_kernel_svm(np.array([[1, 2], [2, 3], [3, 1], [4, 1]]), np.array([1, 1, -1, -1]), kernel='linear', lambda_val=0.01, iterations=100)", 624 | "expected_output": "([100.0, 0.0, -100.0, -100.0], -937.4755)" 625 | }, 626 | { 627 | "test": "pegasos_kernel_svm(np.array([[1, 2], [2, 3], [3, 1], [4, 1]]), np.array([1, 1, -1, -1]), kernel='rbf', lambda_val=0.01, iterations=100, sigma=0.5)", 628 | "expected_output": "([100.0, 99.0, -100.0, -100.0], -115.0)" 629 | } 630 | ], 631 | } 632 | 633 | } 634 | 635 | 636 | 637 | -------------------------------------------------------------------------------- /app/MachineLearning.py: -------------------------------------------------------------------------------- 1 | import ast 2 | import streamlit as st 3 | from streamlit_ace import st_ace 4 | from pistonpy import PistonApp 5 | 6 | from ML_problems import problems 7 | 8 | # Instantiate the piston client 9 | piston = PistonApp() 10 | 11 | def execute_code(user_code): 12 | # Execute the user code using pistonpy 13 | result = piston.run(language="python", version="3.10.0", code=user_code) 14 | return result 15 | 16 | 17 | def run_test_cases(user_code, test_cases): 18 | results = [] 19 | for test_case in test_cases: 20 | # Modify user_code to include the test case at the end 21 | code_to_run = f"{user_code}\n\nprint({test_case['test']})" 22 | result = execute_code(code_to_run) 23 | 24 | stdout = result['run']['output'].strip() 25 | expected_output = test_case['expected_output'].strip() 26 | 27 | # Check if the test case passed 28 | if '{' in stdout: 29 | passed = ast.literal_eval(stdout) == ast.literal_eval(expected_output) 30 | else: 31 | passed = stdout == expected_output 32 | results.append((test_case['test'], expected_output, stdout, passed)) 33 | 34 | return results 35 | 36 | def app(): 37 | st.title("Machine Learning Challenge Platform") 38 | 39 | # Let user select a problem 40 | problem_names = list(problems.keys()) 41 | selected_problem = st.selectbox("Select a Problem:", problem_names) 42 | problem_info = problems[selected_problem] 43 | 44 | try: 45 | is_section = problem_info['section'] 46 | st.markdown(problem_info["description"]) 47 | 48 | except KeyError: 49 | 50 | # Display the selected problem 51 | st.header(selected_problem) 52 | st.write(problem_info["description"]) 53 | st.code(problem_info["example"]) 54 | 55 | # Button for "Show Solution" 56 | if st.button("Learn More"): 57 | # Display the solution code 58 | st.write(problem_info["learn"]) 59 | 60 | # Streamlit-ace editor for user code input 61 | 62 | user_code = st_ace(language="python", theme="twilight", key=f"code_editor_{selected_problem}", value=problem_info["starter_code"], height=350) 63 | st.warning('Make sure to apply changes to your code before running it') 64 | 65 | # Button for "Run Code" 66 | if st.button("Run Code"): 67 | # Execute user code without testing against test cases 68 | result = execute_code(user_code) 69 | if result: 70 | st.subheader("Execution Result:") 71 | stdout = result['run']['output'] 72 | st.text_area("Output", stdout, height=150) 73 | else: 74 | st.error("Failed to execute the code.",'Error:',stdout) 75 | 76 | # Button for "Submit Code" 77 | if st.button("Submit Code"): 78 | # Execute user code and run test cases 79 | results = run_test_cases(user_code, problem_info["test_cases"]) 80 | all_passed = True 81 | st.subheader("Test Results:") 82 | for test, expected, output, passed in results: 83 | if passed: 84 | st.success(f"Passed: {test} => Expected: {expected}, Got: {output}") 85 | else: 86 | st.error(f"Failed: {test} => Expected: {expected}, Got: {output}") 87 | all_passed = False 88 | if all_passed: 89 | st.balloons() 90 | 91 | 92 | 93 | # Button for "Show Solution" 94 | if st.button("Show Solution"): 95 | # Display the solution code 96 | st.subheader("Solution:") 97 | st.code(problem_info["solution"], language="python") 98 | 99 | if __name__ == "__main__": 100 | app() 101 | 102 | -------------------------------------------------------------------------------- /app/__pycache__/DL_problems.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moe18/DeepMLeet/51b4e10bec4a0bd45a40e9b4dd20f4b57fafa968/app/__pycache__/DL_problems.cpython-312.pyc -------------------------------------------------------------------------------- /app/__pycache__/DeepLearning.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moe18/DeepMLeet/51b4e10bec4a0bd45a40e9b4dd20f4b57fafa968/app/__pycache__/DeepLearning.cpython-312.pyc -------------------------------------------------------------------------------- /app/__pycache__/LinAlg.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moe18/DeepMLeet/51b4e10bec4a0bd45a40e9b4dd20f4b57fafa968/app/__pycache__/LinAlg.cpython-312.pyc -------------------------------------------------------------------------------- /app/__pycache__/ML_problems.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moe18/DeepMLeet/51b4e10bec4a0bd45a40e9b4dd20f4b57fafa968/app/__pycache__/ML_problems.cpython-312.pyc -------------------------------------------------------------------------------- /app/__pycache__/MachineLearning.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moe18/DeepMLeet/51b4e10bec4a0bd45a40e9b4dd20f4b57fafa968/app/__pycache__/MachineLearning.cpython-312.pyc -------------------------------------------------------------------------------- /app/__pycache__/about.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moe18/DeepMLeet/51b4e10bec4a0bd45a40e9b4dd20f4b57fafa968/app/__pycache__/about.cpython-312.pyc -------------------------------------------------------------------------------- /app/__pycache__/lin_alg_problems.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moe18/DeepMLeet/51b4e10bec4a0bd45a40e9b4dd20f4b57fafa968/app/__pycache__/lin_alg_problems.cpython-312.pyc -------------------------------------------------------------------------------- /app/__pycache__/main.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moe18/DeepMLeet/51b4e10bec4a0bd45a40e9b4dd20f4b57fafa968/app/__pycache__/main.cpython-312.pyc -------------------------------------------------------------------------------- /app/__pycache__/problems.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moe18/DeepMLeet/51b4e10bec4a0bd45a40e9b4dd20f4b57fafa968/app/__pycache__/problems.cpython-312.pyc -------------------------------------------------------------------------------- /app/about.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | def app(): 4 | st.markdown("""# About DeepMLeet 5 | 6 | **Welcome to DeepMLeet**, your new go-to platform for diving deep into the world of Machine Learning (ML) and Deep Learning (DL) through challenge-based learning. Inspired by the ethos of platforms like LeetCode, DeepMLeet brings a unique twist, focusing exclusively on the realms of ML and DL. It's more than just a platform; it's a community-driven project where enthusiasts and practitioners come together to test their skills, learn, and grow. 7 | 8 | ## Our Mission 9 | 10 | At DeepMLeet, we believe that the best way to master ML and DL is through practice and collaboration. Our mission is to provide an accessible, engaging, and continuously evolving space where anyone, from beginners to seasoned experts, can come to polish their skills, tackle intriguing problems, and contribute to a body of knowledge that benefits the entire community. 11 | 12 | ## What We Offer 13 | 14 | - **A Growing Collection of Challenges:** From foundational Linear Algebra to cutting-edge Deep Learning techniques, our challenges are designed to cater to learners at all levels. Each problem comes with a detailed description, starter code, and test cases to help you focus on solving and learning. 15 | - **Interactive Learning Experience:** With our platform, you get immediate feedback on your solutions, thanks to the integration of tools like Streamlit and pistonpy. This real-time execution environment makes learning interactive and fun. 16 | - **Community Contributions:** DeepMLeet is proudly open-source. We invite our users to contribute by adding new problems, enhancing existing ones, or suggesting features. It's a collaborative effort to make DeepMLeet better for everyone. 17 | 18 | ## Join the Community 19 | 20 | Ready to take on the challenge? Join DeepMLeet today and be part of a growing community of ML/DL enthusiasts dedicated to learning and sharing their knowledge. Whether you're looking to improve your skills, contribute to the platform, or just explore what others have created, there's a place for you here. 21 | 22 | ## Contribute on GitHub 23 | 24 | DeepMLeet is open source, and we welcome contributions of all kinds. Whether you have a suggestion for a new challenge, improvements to our platform, or want to help fix bugs, your input is valuable. Check out our project on GitHub at [moe18/DeepMLeet](https://github.com/moe18/DeepMLeet) and see how you can contribute. 25 | 26 | Thank you for being part of our journey. Together, we're not just learning – we're building the future of ML and DL education. 27 | """) -------------------------------------------------------------------------------- /app/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moe18/DeepMLeet/51b4e10bec4a0bd45a40e9b4dd20f4b57fafa968/app/assets/favicon.ico -------------------------------------------------------------------------------- /app/lin_alg_problems.py: -------------------------------------------------------------------------------- 1 | problems = { 2 | 3 | "1. Linear Algebra": { 4 | "section": True, 5 | "description": """## Linear Algebra in Machine Learning and Deep Learning 6 | 7 | Linear Algebra is crucial for understanding and working with data in Machine Learning (ML) and Deep Learning (DL). This section introduces Linear Algebra concepts that are fundamental for ML and DL, providing a structured approach to mastering this essential mathematical foundation: 8 | 9 | ### Foundational Skills 10 | 11 | - **Get Matrix Shape**: Knowing the dimensions of data matrices is essential for preprocessing and model architecture design. 12 | - **Matrix Multiplication**: Crucial for forward and backward passes in neural networks, filters in convolutional networks, and more. 13 | - **Scalar and Element-wise Operations**: Understand how to manipulate matrices and vectors for feature scaling and normalization. 14 | - **Determinants and Inverses**: Learn about matrix properties that are vital for understanding linear transformations and solving systems of linear equations. 15 | - **Eigenvalues and Eigenvectors**: Discover how these concepts are used in dimensionality reduction techniques such as PCA, and in understanding the stability of systems. 16 | 17 | ### Intermediate Understanding 18 | 19 | - **Singular Value Decomposition (SVD)**: A key factorization method for solving linear systems, data compression, and noise reduction. 20 | - **Covariance Matrices**: Essential for understanding the variance within datasets and for feature selection. 21 | 22 | ### Advanced Techniques 23 | 24 | - **Linear Transformations**: Dive into the geometric interpretations of matrix operations and their applications in ML and DL. 25 | - **Orthogonality and Orthonormality**: Concepts critical for understanding the stability of numerical methods and for reducing overfitting through regularization. 26 | 27 | Each topic is designed to build upon the previous, ensuring a deep and comprehensive understanding of how Linear Algebra powers machine learning algorithms and data analysis. Practical exercises and examples will demonstrate the application of these mathematical concepts in real-world ML and DL scenarios.""", 28 | "example": '', 29 | "learn": '', 30 | "starter_code": "", 31 | "solution": """""", 32 | "test_cases": [], 33 | }, 34 | 35 | "Get Matrix Shape (easy)": { 36 | "description": "Write a Python function that gets the shape of a matrix", 37 | "example": """ Example: 38 | input: a = [[1,2],[2,4],[4,5]] 39 | output:(3,2) 40 | reasoning: There are three rows and two columns """, 41 | "video":"https://youtu.be/eQWOcMiT7ks?si=xu5pD44Tq2wZOxgO", 42 | "learn": r''' 43 | ## Matrix Shape Determination 44 | 45 | Consider a general matrix \(M\) consisting of rows and columns: 46 | 47 | Matrix \(M\): 48 | $$ 49 | M = \begin{pmatrix} 50 | m_{11} & m_{12} & \cdots & m_{1n} \\ 51 | m_{21} & m_{22} & \cdots & m_{2n} \\ 52 | \vdots & \vdots & \ddots & \vdots \\ 53 | m_{m1} & m_{m2} & \cdots & m_{mn} 54 | \end{pmatrix} 55 | $$ 56 | 57 | The shape of matrix \(M\) is defined by the number of rows and columns it contains, represented as a tuple \((m, n)\), where \(m\) is the number of rows, and \(n\) is the number of columns in the matrix. 58 | 59 | **Things to note**: Understanding the shape of a matrix is crucial for matrix operations, including addition, multiplication, and transposition, as these operations often require specific dimensional compatibilities. For example, when multiplying two matrices \(A\) and \(B\) where \(A\) is of shape \((m, n)\) and \(B\) is of shape \((p, q)\), the operation is valid only if \(n = p\), resulting in a new matrix of shape \((m, q)\). 60 | ''', 61 | "starter_code": "def get_shape(a:list[list[int|float]])-> set:\n return (n,m)", 62 | "solution": """def get_shape(a:list[list[int|float]])-> set: 63 | return (len(a), len(a[0]))""", 64 | "test_cases": [ 65 | {"test": "get_shape([[1,2,3],[2,4,5],[6,8,9]])", "expected_output": "(3, 3)"}, 66 | {"test": "get_shape([[1,2,3],[2,4,5]])", "expected_output": "(2, 3)"}, 67 | {"test": "get_shape([[1,2],[2,4],[6,8],[12,4]])", "expected_output": "(4, 2)"}, 68 | ], 69 | }, 70 | 71 | "Matrix times Vector (easy)": { 72 | "description": "Write a Python function that takes the dot product of a matrix and a vector. return -1 if the matrix could not be dotted with the vector", 73 | "example": """ Example: 74 | input: a = [[1,2],[2,4]], b = [1,2] 75 | output:[5, 10] 76 | reasoning: 1*1 + 2*2 = 5; 77 | 1*2+ 2*4 = 10 """, 78 | "video":"https://youtu.be/DNoLs5tTGAw?si=vpkPobZMA8YY10WY", 79 | "learn": r''' 80 | ## Matrix Times Vector 81 | 82 | Consider a matrix \(A\) and a vector \(v\), where: 83 | 84 | Matrix \(A\): 85 | $$ 86 | A = \begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{pmatrix} 87 | $$ 88 | 89 | Vector \(v\): 90 | $$ 91 | v = \begin{pmatrix} v_1 \\ v_2 \end{pmatrix} 92 | $$ 93 | 94 | The dot product of \(A\) and \(v\) results in a new vector: 95 | $$ 96 | A \cdot v = \begin{pmatrix} a_{11}v_1 + a_{12}v_2 \\ a_{21}v_1 + a_{22}v_2 \end{pmatrix} 97 | $$ 98 | things to note: a n x m matrix will need to be multiplied by a vector of size m or else this would not work. 99 | ''', 100 | "starter_code": "def matrix_dot_vector(a:list[list[int|float]],b:list[int|float])-> list[int|float]:\n return c", 101 | "solution": """def matrix_dot_vector(a:list[list[int|float]],b:list[int|float])-> list[int|float]: 102 | if len(a[0]) != len(b): 103 | return -1 104 | vals = [] 105 | for i in a: 106 | hold = 0 107 | for j in range(len(i)): 108 | hold+=(i[j] * b[j]) 109 | vals.append(hold) 110 | 111 | return vals""", 112 | "test_cases": [ 113 | {"test": "matrix_dot_vector([[1,2,3],[2,4,5],[6,8,9]],[1,2,3])", "expected_output": "[14, 25, 49]"}, 114 | {"test": "matrix_dot_vector([[1,2,3],[2,4,5],[6,8,9],[12,4,0]],[1,2,3])", "expected_output": "[14, 25, 49, 20]"}, 115 | {"test": "matrix_dot_vector([[1,2],[2,4],[6,8],[12,4]],[1,2,3])", "expected_output": "-1"}, 116 | ], 117 | },"Transpose of a Matrix (easy)": { 118 | "description": "Write a Python function that computes the transpose of a given matrix.", 119 | "example": """Example: 120 | input: a = [[1,2,3],[4,5,6]] 121 | output: [[1,4],[2,5],[3,6]] 122 | reasoning: The transpose of a matrix is obtained by flipping rows and columns.""", 123 | "video": "https://youtu.be/fj0ZJ2gTSmI?si=vG8VSqASjyG0eNLY", 124 | "learn": r''' 125 | ## Transpose of a Matrix 126 | 127 | Consider a matrix \(M\) and its transpose \(M^T\), where: 128 | 129 | Original Matrix \(M\): 130 | $$ 131 | M = \begin{pmatrix} a & b & c \\ d & e & f \end{pmatrix} 132 | $$ 133 | 134 | Transposed Matrix \(M^T\): 135 | $$ 136 | M^T = \begin{pmatrix} a & d \\ b & e \\ c & f \end{pmatrix} 137 | $$ 138 | 139 | Transposing a matrix involves converting its rows into columns and vice versa. This operation is fundamental in linear algebra for various computations and transformations. 140 | ''', 141 | "starter_code": "def transpose_matrix(a: list[list[int|float]]) -> list[list[int|float]]:\n return b", 142 | "solution": """def transpose_matrix(a: list[list[int|float]]) -> list[list[int|float]]: 143 | return [list(i) for i in zip(*a)]""", 144 | "test_cases": [ 145 | {"test": "transpose_matrix([[1,2],[3,4],[5,6]])", "expected_output": "[[1, 3, 5], [2, 4, 6]]"}, 146 | {"test": "transpose_matrix([[1,2,3],[4,5,6]])", "expected_output": "[[1, 4], [2, 5], [3, 6]]"} 147 | ] 148 | }, "Reshape Matrix (easy)": { 149 | "description": "Write a Python function that reshapes a given matrix into a specified shape.", 150 | "example": """Example: 151 | input: a = [[1,2,3,4],[5,6,7,8]], new_shape = (4, 2) 152 | output: [[1, 2], [3, 4], [5, 6], [7, 8]] 153 | reasoning: The given matrix is reshaped from 2x4 to 4x2.""", 154 | "video": "Coming Soon", 155 | "learn": r''' 156 | ## Reshaping a Matrix 157 | 158 | Matrix reshaping involves changing the shape of a matrix without altering its data. This is essential in many machine learning tasks where the input data needs to be formatted in a specific way. 159 | 160 | For example, consider a matrix \(M\): 161 | 162 | Original Matrix \(M\): 163 | $$ 164 | M = \begin{pmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \end{pmatrix} 165 | $$ 166 | 167 | Reshaped Matrix \(M'\) with shape (4, 2): 168 | $$ 169 | M' = \begin{pmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \\ 7 & 8 \end{pmatrix} 170 | $$ 171 | 172 | Ensure the total number of elements remains constant during reshaping. 173 | ''', 174 | "starter_code": "import numpy as np\n\ndef reshape_matrix(a: list[list[int|float]], new_shape: tuple[int, int]) -> list[list[int|float]]:\n #Write your code here and return a python list after reshaping by using numpy's tolist() method\n return reshaped_matrix", 175 | "solution": """def reshape_matrix(a: list[list[int|float]], new_shape: tuple[int, int]) -> list[list[int|float]]: 176 | return np.array(a).reshape(new_shape).tolist()""", 177 | "test_cases": [ 178 | {"test": "reshape_matrix([[1,2,3,4],[5,6,7,8]], (4, 2))", "expected_output": "[[1, 2], [3, 4], [5, 6], [7, 8]]"}, 179 | {"test": "reshape_matrix([[1,2,3],[4,5,6]], (3, 2))", "expected_output": "[[1, 2], [3, 4], [5, 6]]"}, 180 | {"test": "reshape_matrix([[1,2,3,4],[5,6,7,8]], (2, 4))", "expected_output": "[[1, 2, 3, 4], [5, 6, 7, 8]]"}, 181 | ], 182 | }, 183 | "Calculate Mean by Row or Column (easy)":{ 184 | "description": "Write a Python function that calculates the mean of a matrix either by row or by column, based on a given mode. The function should take a matrix (list of lists) and a mode ('row' or 'column') as input and return a list of means according to the specified mode.", 185 | "example": """Example1: 186 | input: matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], mode = 'column' 187 | output: [4.0, 5.0, 6.0] 188 | reasoning: Calculating the mean of each column results in [(1+4+7)/3, (2+5+8)/3, (3+6+9)/3]. 189 | 190 | Example 2: 191 | input: matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], mode = 'row' 192 | output: [2.0, 5.0, 8.0] 193 | reasoning: Calculating the mean of each row results in [(1+2+3)/3, (4+5+6)/3, (7+8+9)/3].""", 194 | "video":'Coming Soon', 195 | "learn": r''' 196 | ## Calculate Mean by Row or Column 197 | 198 | Calculating the mean of a matrix by row or column involves averaging the elements across the specified dimension. This operation provides insights into the distribution of values within the dataset, useful for data normalization and scaling. 199 | 200 | ### Row Mean 201 | The mean of a row is computed by summing all elements in the row and dividing by the number of elements. For row \(i\), the mean is: 202 | $$ 203 | \mu_{\text{row } i} = \frac{1}{n} \sum_{j=1}^{n} a_{ij} 204 | $$ 205 | where \(a_{ij}\) is the matrix element in the \(i^{th}\) row and \(j^{th}\) column, and \(n\) is the total number of columns. 206 | 207 | ### Column Mean 208 | Similarly, the mean of a column is found by summing all elements in the column and dividing by the number of elements. For column \(j\), the mean is: 209 | $$ 210 | \mu_{\text{column } j} = \frac{1}{m} \sum_{i=1}^{m} a_{ij} 211 | $$ 212 | where \(m\) is the total number of rows. 213 | 214 | This mathematical formulation helps in understanding how data is aggregated across different dimensions, a critical step in various data preprocessing techniques. 215 | ''', 216 | "starter_code": "def calculate_matrix_mean(matrix: list[list[float]], mode: str) -> list[float]:\n return means", 217 | "solution": """def calculate_matrix_mean(matrix: list[list[float]], mode: str) -> list[float]: 218 | if mode == 'column': 219 | return [sum(col) / len(matrix) for col in zip(*matrix)] 220 | elif mode == 'row': 221 | return [sum(row) / len(row) for row in matrix] 222 | else: 223 | raise ValueError("Mode must be 'row' or 'column'")""", 224 | "test_cases": [ 225 | { 226 | "test": "calculate_matrix_mean([[1, 2, 3], [4, 5, 6], [7, 8, 9]], 'column')", 227 | "expected_output": "[4.0, 5.0, 6.0]" 228 | }, 229 | { 230 | "test": "calculate_matrix_mean([[1, 2, 3], [4, 5, 6], [7, 8, 9]], 'row')", 231 | "expected_output": "[2.0, 5.0, 8.0]" 232 | } 233 | ] 234 | } 235 | 236 | , 237 | "Scalar Multiplication of a Matrix (easy)":{ 238 | "description": "Write a Python function that multiplies a matrix by a scalar and returns the result.", 239 | "example": """Example: 240 | input: matrix = [[1, 2], [3, 4]], scalar = 2 241 | output: [[2, 4], [6, 8]] 242 | reasoning: Each element of the matrix is multiplied by the scalar.""", 243 | "video": "https://youtu.be/iE2NvpvZRBk", 244 | "learn": r''' 245 | ## Scalar Multiplication of a Matrix 246 | 247 | When a matrix \(A\) is multiplied by a scalar \(k\), the operation is defined as multiplying each element of \(A\) by \(k\). 248 | 249 | Given a matrix \(A\): 250 | $$ 251 | A = \begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{pmatrix} 252 | $$ 253 | 254 | And a scalar \(k\), the result of the scalar multiplication \(kA\) is: 255 | $$ 256 | kA = \begin{pmatrix} ka_{11} & ka_{12} \\ ka_{21} & ka_{22} \end{pmatrix} 257 | $$ 258 | 259 | This operation scales the matrix by \(k\) without changing its dimension or the relative proportion of its elements. 260 | ''', 261 | "starter_code": "def scalar_multiply(matrix: list[list[int|float]], scalar: int|float) -> list[list[int|float]]:\n return result", 262 | "solution": """def scalar_multiply(matrix: list[list[int|float]], scalar: int|float) -> list[list[int|float]]: 263 | return [[element * scalar for element in row] for row in matrix]""", 264 | "test_cases": [ 265 | {"test": "scalar_multiply([[1,2],[3,4]], 2)", "expected_output": "[[2, 4], [6, 8]]"}, 266 | {"test": "scalar_multiply([[0,-1],[1,0]], -1)", "expected_output": "[[0, 1], [-1, 0]]"} 267 | ] 268 | } 269 | , 270 | "Calculate Eigenvalues of a Matrix (medium)": { 271 | "description": """Write a Python function that calculates the eigenvalues of a 2x2 matrix. 272 | The function should return a list containing the eigenvalues, sort values from highest to lowest.""", 273 | "example": """Example: 274 | input: matrix = [[2, 1], [1, 2]] 275 | output: [3.0, 1.0] 276 | reasoning: The eigenvalues of the matrix are calculated using the characteristic equation of the matrix, 277 | which for a 2x2 matrix is λ^2 - trace(A)λ + det(A) = 0, where λ are the eigenvalues.""", 278 | "video": 'https://youtu.be/AMCFzIaHc4Y', 279 | "learn": r'''## Calculate Eigenvalues 280 | 281 | Eigenvalues of a matrix offer significant insight into the matrix's behavior, particularly in the context of linear transformations and systems of linear equations. 282 | 283 | ### Definition 284 | For a square matrix \(A\), eigenvalues are scalars \(\lambda\) that satisfy the equation for some non-zero vector \(v\) (eigenvector): 285 | $$ 286 | Av = \lambda v 287 | $$ 288 | 289 | ### Calculation for a 2x2 Matrix 290 | The eigenvalues of a 2x2 matrix \(A\), given by: 291 | $$ 292 | A = \begin{pmatrix} a & b \\ c & d \end{pmatrix} 293 | $$ 294 | are determined by solving the characteristic equation: 295 | $$ 296 | \det(A - \lambda I) = 0 297 | $$ 298 | This simplifies to a quadratic equation: 299 | $$ 300 | \lambda^2 - \text{tr}(A) \lambda + \det(A) = 0 301 | $$ 302 | Here, the trace of A, denoted as tr(A), is a + d, and the determinant of A, denoted as det(A), is ad - bc. Solving this equation yields the eigenvalues, λ. 303 | 304 | ### Significance 305 | Understanding eigenvalues is essential for analyzing the effects of linear transformations represented by the matrix. They are crucial in various applications, including stability analysis, vibration analysis, and Principal Component Analysis (PCA) in machine learning. 306 | ''', 307 | "starter_code": "def calculate_eigenvalues(matrix: list[list[float|int]]) -> list[float]:\n return eigenvalues", 308 | "solution": """def calculate_eigenvalues(matrix: list[list[float]]) -> list[float]: 309 | a, b, c, d = matrix[0][0], matrix[0][1], matrix[1][0], matrix[1][1] 310 | trace = a + d 311 | determinant = a * d - b * c 312 | # Calculate the discriminant of the quadratic equation 313 | discriminant = trace**2 - 4 * determinant 314 | # Solve for eigenvalues 315 | lambda_1 = (trace + discriminant**0.5) / 2 316 | lambda_2 = (trace - discriminant**0.5) / 2 317 | return [lambda_1, lambda_2]""", 318 | "test_cases": [ 319 | { 320 | "test": "calculate_eigenvalues([[2, 1], [1, 2]])", 321 | "expected_output": "[3.0, 1.0]" 322 | }, 323 | { 324 | "test": "calculate_eigenvalues([[4, -2], [1, 1]])", 325 | "expected_output": "[3.0, 2.0]" 326 | } 327 | ] 328 | }, 329 | "Calculate 2x2 Matrix Inverse (medium)": { 330 | "description": "Write a Python function that calculates the inverse of a 2x2 matrix. Return 'None' if the matrix is not invertible.", 331 | "example": """Example: 332 | input: matrix = [[4, 7], [2, 6]] 333 | output: [[0.6, -0.7], [-0.2, 0.4]] 334 | reasoning: The inverse of a 2x2 matrix [a, b], [c, d] is given by (1/(ad-bc)) * [d, -b], [-c, a], provided ad-bc is not zero.""", 335 | "video": "", 336 | "learn": r''' 337 | ## Calculating the Inverse of a 2x2 Matrix 338 | 339 | The inverse of a matrix A is another matrix, often denoted A^-1, such that: 340 | 341 | $$ 342 | AA^-1 = A^-1A = I 343 | $$ 344 | 345 | where I is the identity matrix. For a 2x2 matrix: 346 | $$ 347 | A = \begin{pmatrix} a & b \\ c & d \end{pmatrix} 348 | $$ 349 | 350 | The inverse is: 351 | $$ 352 | A^-1 = \frac{1}{\det(A)} \begin{pmatrix} d & -b \\ -c & a \end{pmatrix} 353 | $$ 354 | 355 | provided that the determinant $$\det(A) = ad - bc$$ is non-zero. If $$det(A) = 0 $$, the matrix does not have an inverse. 356 | 357 | This process is critical in many applications including solving systems of linear equations, where the inverse is used to find solutions efficiently. 358 | ''', 359 | "starter_code": "def inverse_2x2(matrix: list[list[float]]) -> list[list[float]]:\n return inverse", 360 | "solution": """def inverse_2x2(matrix: list[list[float]]) -> list[list[float]]: 361 | a, b, c, d = matrix[0][0], matrix[0][1], matrix[1][0], matrix[1][1] 362 | determinant = a * d - b * c 363 | if determinant == 0: 364 | return None 365 | inverse = [[d/determinant, -b/determinant], [-c/determinant, a/determinant]] 366 | return inverse""", 367 | "test_cases": [ 368 | {"test": "inverse_2x2([[4, 7], [2, 6]])", "expected_output": "[[0.6, -0.7], [-0.2, 0.4]]"}, 369 | {"test": "inverse_2x2([[1, 2], [2, 4]])", "expected_output": "None"}, 370 | {"test": "inverse_2x2([[2, 1], [6, 2]])", "expected_output": "[[-1.0, 0.5], [3.0, -1.0]]"} 371 | ] 372 | } 373 | 374 | , 375 | "Matrix times Matrix (medium)": { 376 | "description": "multiply two matrices together (return -1 if shapes of matrix dont aline), i.e. C = A dot product B", 377 | "example": """ 378 | Example: 379 | input: A = [[1,2], 380 | [2,4]], 381 | B = [[2,1], 382 | [3,4]] 383 | output:[[ 8, 9], 384 | [16, 18]] 385 | reasoning: 1*2 + 2*3 = 8; 386 | 2*2 + 3*4 = 16; 387 | 1*1 + 2*4 = 9; 388 | 2*1 + 4*4 = 18 389 | 390 | Example 2: 391 | input: A = [[1,2], 392 | [2,4]], 393 | B = [[2,1], 394 | [3,4], 395 | [4,5]] 396 | output: -1 397 | reasoning: the length of the rows of A does not equal 398 | the column length of B""", 399 | "video":'https://youtu.be/N2j0fA2E9k4', 400 | "learn": r''' 401 | ## Matrix Multiplication 402 | 403 | Consider two matrices \(A\) and \(B\), to demonstrate their multiplication, defined as follows: 404 | 405 | - Matrix \(A\): 406 | $$ 407 | A = \begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{pmatrix} 408 | $$ 409 | 410 | - Matrix \(B\): 411 | $$ 412 | B = \begin{pmatrix} b_{11} & b_{12} \\ b_{21} & b_{22} \end{pmatrix} 413 | $$ 414 | 415 | The multiplication of matrix \(A\) by matrix \(B\) is calculated as: 416 | $$ 417 | A \times B = \begin{pmatrix} a_{11}b_{11} + a_{12}b_{21} & a_{11}b_{12} + a_{12}b_{22} \\ a_{21}b_{11} + a_{22}b_{21} & a_{21}b_{12} + a_{22}b_{22} \end{pmatrix} 418 | $$ 419 | 420 | This operation results in a new matrix where each element is the result of the dot product between the rows of matrix \(A\) and the columns of matrix \(B\). 421 | ''', 422 | "starter_code": """def matrixmul(a:list[list[int|float]],\n b:list[list[int|float]])-> list[list[int|float]]: \n return c""", 423 | "solution": """ 424 | 425 | def matrixmul(a:list[list[int|float]], 426 | b:list[list[int|float]])-> list[list[int|float]]: 427 | if len(a[0]) != len(b): 428 | return -1 429 | 430 | vals = [] 431 | for i in range(len(a)): 432 | hold = [] 433 | for j in range(len(b[0])): 434 | val = 0 435 | for k in range(len(b)): 436 | val += a[i][k] * b[k][j] 437 | 438 | hold.append(val) 439 | vals.append(hold) 440 | 441 | return vals""", 442 | "test_cases": [ 443 | {"test": "matrixmul([[1,2,3],[2,3,4],[5,6,7]],[[3,2,1],[4,3,2],[5,4,3]])", "expected_output": "[[26, 20, 14], [38, 29, 20], [74, 56, 38]]"}, 444 | {"test": "matrixmul([[0,0],[2,4],[1,2]],[[0,0],[2,4]])", "expected_output": "[[0, 0], [8, 16], [4, 8]]"}, 445 | {"test": "matrixmul([[0,0],[2,4],[1,2]],[[0,0,1],[2,4,1],[1,2,3]])", "expected_output": "-1"}, 446 | ], 447 | }, 448 | "Calculate Covariance Matrix (medium)":{ 449 | "description": "Write a Python function that calculates the covariance matrix from a list of vectors. Assume that the input list represents a dataset where each vector is a feature, and vectors are of equal length.", 450 | "example": """Example: 451 | input: vectors = [[1, 2, 3], [4, 5, 6]] 452 | output: [[1.0, 1.0], [1.0, 1.0]] 453 | reasoning: The dataset has two features with three observations each. The covariance between each pair of features (including covariance with itself) is calculated and returned as a 2x2 matrix.""", 454 | "video":"https://youtu.be/-BHegXJZAww", 455 | "learn": r''' 456 | ## Calculate Covariance Matrix 457 | 458 | The covariance matrix is a fundamental concept in statistics, illustrating how much two random variables change together. It's essential for understanding the relationships between variables in a dataset. 459 | 460 | For a dataset with n features, the covariance matrix is an n x n square matrix where each element (i, j) represents the covariance between the ith and jth features. Covariance is defined by the formula: 461 | 462 | $$ 463 | \text{cov}(X, Y) = \frac{\sum_{i=1}^{n} (x_i - \bar{x})(y_i - \bar{y})}{n-1} 464 | $$ 465 | 466 | Where: 467 | 468 | - X and Y are two random variables (features), 469 | - x_i and y_i are individual observations of X and Y, 470 | - x̄ (x-bar) and ȳ (y-bar) are the means of X and Y, 471 | - n is the number of observations. 472 | 473 | In the covariance matrix: 474 | 475 | - The diagonal elements (where i = j) indicate the variance of each feature. 476 | - The off-diagonal elements show the covariance between different features. This matrix is symmetric, as the covariance between X and Y is equal to the covariance between Y and X, denoted as cov(X, Y) = cov(Y, X). 477 | ''', 478 | "starter_code": "def calculate_covariance_matrix(vectors: list[list[float]]) -> list[list[float]]:\n return covariance_matrix", 479 | "solution": """def calculate_covariance_matrix(vectors: list[list[float]]) -> list[list[float]]: 480 | n_features = len(vectors) 481 | n_observations = len(vectors[0]) 482 | covariance_matrix = [[0 for _ in range(n_features)] for _ in range(n_features)] 483 | 484 | means = [sum(feature) / n_observations for feature in vectors] 485 | 486 | for i in range(n_features): 487 | for j in range(i, n_features): 488 | covariance = sum((vectors[i][k] - means[i]) * (vectors[j][k] - means[j]) for k in range(n_observations)) / (n_observations - 1) 489 | covariance_matrix[i][j] = covariance_matrix[j][i] = covariance 490 | 491 | return covariance_matrix""", 492 | "test_cases": [ 493 | { 494 | "test": "calculate_covariance_matrix([[1, 2, 3], [4, 5, 6]])", 495 | "expected_output": "[[1.0, 1.0], [1.0, 1.0]]" 496 | }, 497 | { 498 | "test": "calculate_covariance_matrix([[1, 5, 6], [2, 3, 4], [7, 8, 9]])", 499 | "expected_output": "[[7.0, 2.5, 2.5], [2.5, 1.0, 1.0], [2.5, 1.0, 1.0]]" 500 | } 501 | ] 502 | }, 503 | "Solve Linear Equations using Jacobi Method (medium)": { 504 | "description": "Write a Python function that uses the Jacobi method to solve a system of linear equations given by Ax = b. The function should iterate 10 times, rounding each intermediate solution to four decimal places, and return the approximate solution x.", 505 | "example": """Example: 506 | input: A = [[5, -2, 3], [-3, 9, 1], [2, -1, -7]], b = [-1, 2, 3], n=2 507 | output: [0.146, 0.2032, -0.5175] 508 | reasoning: The Jacobi method iteratively solves each equation for x[i] using the formula x[i] = (1/a_ii) * (b[i] - sum(a_ij * x[j] for j != i)), where a_ii is the diagonal element of A and a_ij are the off-diagonal elements.""", 509 | "video": "https://youtu.be/Y7WSn7K092g", 510 | "learn": r''' 511 | ## Solving Linear Equations Using the Jacobi Method 512 | 513 | The Jacobi method is an iterative algorithm used for solving a system of linear equations Ax = b. This method is particularly useful for large systems where direct methods like Gaussian elimination are computationally expensive. 514 | 515 | ### Algorithm Overview 516 | 517 | For a system of equations represented by $$Ax = b $$, where $$ A $$ is a matrix and $$ x $$ and $$ b $$ are vectors, the Jacobi method involves the following steps: 518 | 519 | 1. **Initialization**: Start with an initial guess for \( x \). 520 | 2. **Iteration**: For each equation \( i \), update \( x[i] \) using: 521 | $$ 522 | x[i] = \frac{1}{a_{ii}} (b[i] - \sum_{j \neq i} a_{ij} x[j]) 523 | $$ 524 | where $$ a_{ii} $$ are the diagonal elements of $$ A $$, and $$ a_{ij} $$ are the off-diagonal elements. 525 | 3. **Convergence**: Repeat the iteration until the changes in $$ x $$ are below a certain tolerance or until a maximum number of iterations is reached. 526 | 527 | This method assumes that all diagonal elements of $$ A $$ are non-zero and that the matrix is diagonally dominant or properly conditioned for convergence. 528 | 529 | ### Practical Considerations 530 | 531 | - The method may not converge for all matrices. 532 | - Choosing a good initial guess can improve convergence. 533 | - Diagonal dominance of \( A \) ensures convergence of the Jacobi method. 534 | ''', 535 | "starter_code": "import numpy as np\ndef solve_jacobi(A: np.ndarray, b: np.ndarray, n: int) -> list:\n return x", 536 | "solution": """import numpy as np 537 | 538 | def solve_jacobi(A: np.ndarray, b: np.ndarray, n: int) -> list: 539 | d_a = np.diag(A) 540 | nda = A - np.diag(d_a) 541 | x = np.zeros(len(b)) 542 | x_hold = np.zeros(len(b)) 543 | for _ in range(n): 544 | for i in range(len(A)): 545 | x_hold[i] = (1/d_a[i]) * (b[i] - sum(nda[i]*x)) 546 | x = x_hold.copy() 547 | return np.round(x,4).tolist()""", 548 | "test_cases": [ 549 | {"test": "solve_jacobi(np.array([[5, -2, 3], [-3, 9, 1], [2, -1, -7]]), np.array([-1, 2, 3]),2)", "expected_output": "[0.146, 0.2032, -0.5175]"}, 550 | {"test": "solve_jacobi(np.array([[4, 1, 2], [1, 5, 1], [2, 1, 3]]), np.array([4, 6, 7]),5)", "expected_output": "[-0.0806, 0.9324, 2.4422]"}, 551 | {"test": "solve_jacobi(np.array([[4,2,-2],[1,-3,-1],[3,-1,4]]), np.array([0,7,5]),3)", "expected_output": "[1.7083, -1.9583, -0.7812]"} 552 | 553 | ] 554 | } 555 | 556 | 557 | , 558 | 559 | "Singular Value Decomposition (SVD) (hard)": { 560 | "description": """Write a Python function that approximates the Singular Value Decomposition on a 2x2 matrix by 561 | using the jacobian method and without using numpy svd function, 562 | i mean you could but you wouldn't learn anything. return the result i this format.""", 563 | "example": """Example: 564 | input: a = [[2, 1], [1, 2]] 565 | output: (array([[-0.70710678, -0.70710678], 566 | [-0.70710678, 0.70710678]]), 567 | array([3., 1.]), 568 | array([[-0.70710678, -0.70710678], 569 | [-0.70710678, 0.70710678]])) 570 | reasoning: U is the first matrix sigma is the second vector and V is the third matrix""", 571 | "learn": r''' 572 | ## Singular Value Decomposition (SVD) via the Jacobi Method 573 | 574 | Singular Value Decomposition (SVD) is a powerful matrix decomposition technique in linear algebra that expresses a matrix as the product of three other matrices, revealing its intrinsic geometric and algebraic properties. When using the Jacobi method, SVD decomposes a matrix $$A$$ into: 575 | 576 | $$ 577 | A = U\Sigma V^T 578 | $$ 579 | 580 | - $$A$$ is the original $$m \times n$$ matrix. 581 | - $$U$$ is an $$m \times m$$ orthogonal matrix whose columns are the left singular vectors of $$A$$. 582 | - $$\Sigma$$ is an $$m \times n$$ diagonal matrix containing the singular values of $$A$$. 583 | - $$V^T$$ is the transpose of an $$n \times n$$ orthogonal matrix whose columns are the right singular vectors of $$A$$. 584 | 585 | ### The Jacobi Method for SVD 586 | 587 | The Jacobi method is an iterative algorithm used for diagonalizing a symmetric matrix through a series of rotational transformations. It is particularly suited for computing the SVD by iteratively applying rotations to minimize off-diagonal elements until the matrix is diagonal. 588 | 589 | ### Steps of the Jacobi SVD Algorithm 590 | 591 | 1. **Initialization**: Start with $$A^TA$$ (or $$AA^T$$ for $$U$$) and set $$V$$ (or $$U$$) as an identity matrix. The goal is to diagonalize $$A^TA$$, obtaining $$V$$ in the process. 592 | 593 | 2. **Choosing Rotation Targets**: Identify off-diagonal elements in $$A^TA$$ to be minimized or zeroed out through rotations. 594 | 595 | 3. **Calculating Rotation Angles**: For each target off-diagonal element, calculate the angle $$\theta$$ for the Jacobi rotation matrix $$J$$ that would zero it. This involves solving for $$\theta$$ using $$\text{atan2}$$ to accurately handle the quadrant of rotation: 596 | 597 | $$ 598 | \theta = 0.5 \cdot \text{atan2}(2a_{ij}, a_{ii} - a_{jj}) 599 | $$ 600 | 601 | where $$a_{ij}$$ is the target off-diagonal element, and $$a_{ii}$$, $$a_{jj}$$ are the diagonal elements of $$A^TA$$. 602 | 603 | 4. **Applying Rotations**: Construct $$J$$ using $$\theta$$ and apply the rotation to $$A^TA$$, effectively reducing the magnitude of the target off-diagonal element. Update $$V$$ (or $$U$$) by multiplying it by $$J$$. 604 | 605 | 5. **Iteration and Convergence**: Repeat the process of selecting off-diagonal elements, calculating rotation angles, and applying rotations until $$A^TA$$ is sufficiently diagonalized. 606 | 607 | 6. **Extracting SVD Components**: Once diagonalized, the diagonal entries of $$A^TA$$ represent the squared singular values of $$A$$. The matrices $$U$$ and $$V$$ are constructed from the accumulated rotations, containing the left and right singular vectors of $$A$$, respectively. 608 | 609 | ### Practical Considerations 610 | 611 | - The Jacobi method is particularly effective for dense matrices where off-diagonal elements are significant. 612 | - Careful implementation is required to ensure numerical stability and efficiency, especially for large matrices. 613 | - The iterative nature of the Jacobi method makes it computationally intensive, but it is highly parallelizable. 614 | 615 | This iterative process underscores the adaptability of the Jacobi method for computing the SVD, offering a detailed insight into the matrix's structure through its singular values and vectors. 616 | ''', 617 | "starter_code": "import numpy as np \n svd_2x2_singular_values(A: np.ndarray) -> tuple: \n return SVD", 618 | "solution": """import numpy as np 619 | 620 | def svd_2x2_singular_values(A: np.ndarray) -> tuple: 621 | A_T_A = A.T @ A 622 | theta = 0.5 * np.arctan2(2 * A_T_A[0, 1], A_T_A[0, 0] - A_T_A[1, 1]) 623 | j = np.array([[np.cos(theta), -np.sin(theta)], 624 | [np.sin(theta), np.cos(theta)]]) 625 | A_prime = j.T @ A_T_A @ j 626 | 627 | # Calculate singular values from the diagonalized A^TA (approximation for 2x2 case) 628 | singular_values = np.sqrt(np.diag(A_prime)) 629 | 630 | # Process for AA^T, if needed, similar to A^TA can be added here for completeness 631 | 632 | return j, singular_values, j.T""", 633 | "test_cases": [ 634 | { 635 | "test": "svd_2x2_singular_values(np.array([[2, 1], [1, 2]]))", 636 | "expected_output": """(array([[ 0.70710678, -0.70710678], 637 | [ 0.70710678, 0.70710678]]), array([3., 1.]), array([[ 0.70710678, 0.70710678], 638 | [-0.70710678, 0.70710678]]))""" 639 | }, 640 | { 641 | "test": "svd_2x2_singular_values(np.array([[1, 2], [3, 4]]))", 642 | "expected_output": """(array([[ 0.57604844, -0.81741556], 643 | [ 0.81741556, 0.57604844]]), array([5.4649857 , 0.36596619]), array([[ 0.57604844, 0.81741556], 644 | [-0.81741556, 0.57604844]]))""" 645 | } 646 | ] 647 | }, 648 | "Determinant of a 4x4 Matrix using Laplace's Expansion (hard)": { 649 | "description": "Write a Python function that calculates the determinant of a 4x4 matrix using Laplace's Expansion method. The function should take a single argument, a 4x4 matrix represented as a list of lists, and return the determinant of the matrix. The elements of the matrix can be integers or floating-point numbers. Implement the function recursively to handle the computation of determinants for the 3x3 minor matrices.", 650 | "example": """Example: 651 | input: a = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]] 652 | output: 0 653 | reasoning: Using Laplace's Expansion, the determinant of a 4x4 matrix is calculated by expanding it into minors and cofactors along any row or column. Given the symmetrical and linear nature of this specific matrix, its determinant is 0. The calculation for a generic 4x4 matrix involves more complex steps, breaking it down into the determinants of 3x3 matrices.""", 654 | "learn": r''' 655 | ## Determinant of a 4x4 Matrix using Laplace's Expansion 656 | 657 | Laplace's Expansion, also known as cofactor expansion, is a method to calculate the determinant of a square matrix of any size. For a 4x4 matrix \(A\), this method involves expanding \(A\) into minors and cofactors along a chosen row or column. 658 | 659 | Consider a 4x4 matrix \(A\): 660 | $$ 661 | A = \begin{pmatrix} 662 | a_{11} & a_{12} & a_{13} & a_{14} \\ 663 | a_{21} & a_{22} & a_{23} & a_{24} \\ 664 | a_{31} & a_{32} & a_{33} & a_{34} \\ 665 | a_{41} & a_{42} & a_{43} & a_{44} 666 | \end{pmatrix} 667 | $$ 668 | 669 | The determinant of \(A\), \(\det(A)\), can be calculated by selecting any row or column (e.g., the first row) and using the formula that involves the elements of that row (or column), their corresponding cofactors, and the determinants of the 3x3 minor matrices obtained by removing the row and column of each element. This process is recursive, as calculating the determinants of the 3x3 matrices involves further expansions. 670 | 671 | The expansion formula for the first row is as follows: 672 | $$ 673 | \det(A) = a_{11}C_{11} - a_{12}C_{12} + a_{13}C_{13} - a_{14}C_{14} 674 | $$ 675 | 676 | Here, \(C_{ij}\) represents the cofactor of element \(a_{ij}\), which is calculated as \((-1)^{i+j}\) times the determinant of the minor matrix obtained after removing the \(i\)th row and \(j\)th column from \(A\). 677 | ''', 678 | "starter_code": "def determinant_4x4(matrix: list[list[int|float]]) -> float:\n # Your recursive implementation here\n pass", 679 | "solution": """def determinant_4x4(matrix: list[list[int|float]]) -> float: 680 | # Base case: If the matrix is 1x1, return its single element 681 | if len(matrix) == 1: 682 | return matrix[0][0] 683 | # Recursive case: Calculate determinant using Laplace's Expansion 684 | det = 0 685 | for c in range(len(matrix)): 686 | minor = [row[:c] + row[c+1:] for row in matrix[1:]] # Remove column c 687 | cofactor = ((-1)**c) * determinant_4x4(minor) # Compute cofactor 688 | det += matrix[0][c] * cofactor # Add to running total 689 | return det""", 690 | "test_cases": [ 691 | {"test": 'determinant_4x4([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])', "expected_output": '0'}, 692 | {"test": 'determinant_4x4([[4, 3, 2, 1], [3, 2, 1, 4], [2, 1, 4, 3], [1, 4, 3, 2]])', "expected_output": '-160'}, 693 | {"test": 'determinant_4x4([[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]])', "expected_output": '0'}, 694 | ] 695 | }} 696 | -------------------------------------------------------------------------------- /app/main.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | # Set page configuration 4 | st.set_page_config(page_icon="assets\\favicon.ico", page_title='DeepMLeet') 5 | 6 | # Import your page modules 7 | import LinAlg 8 | import MachineLearning 9 | import DeepLearning 10 | import about 11 | 12 | # Define pages in the app 13 | pages = { 14 | "About": about, 15 | "Linear Algebra": LinAlg, 16 | "Machine Learning": MachineLearning, 17 | "Deep Learning [In Progress]": DeepLearning 18 | } 19 | 20 | # Sidebar for navigation for navigating 21 | url = 'https://www.deep-ml.com/' 22 | st.warning("check my new site [deep-ml](%s)" % url, icon="⚠️") 23 | 24 | st.sidebar.title('Navigation') 25 | selection = st.sidebar.radio("Sections", list(pages.keys())) 26 | 27 | # Page selection 28 | page = pages[selection] 29 | page.app() 30 | -------------------------------------------------------------------------------- /contribute.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We welcome contributions to the project in various forms. There are primarily two ways you can contribute: 4 | 5 | ## 1. Enhancing the User Interface (UI) 6 | 7 | If you're interested in improving the user interface, follow these steps: 8 | 9 | - **Fork the repository**: Begin by forking the project repository to your GitHub account. 10 | - **Clone your fork**: Clone your forked repository to your local machine to make your changes. 11 | - **Make your changes**: Work on enhancing the UI in your local setup. 12 | - **Submit a Pull Request (PR)**: Once you're satisfied with your changes, commit them and push to your fork on GitHub. Then, submit a Pull Request to the original repository. Your changes will be reviewed and, if approved, merged into the project. 13 | 14 | ## 2. Adding or Improving Problems 15 | 16 | Contributing problems or solutions is another excellent way to help out. Here’s how to add a new problem: 17 | 18 | 1. **Fork and Clone**: Similar to UI enhancements, start by forking the repository and cloning it to your local system. 19 | 2. **Create the Problem**: Add a new problem to the appropriate directory. Here's the template you should follow: 20 | 21 | ```bash 22 | "Name of Problem (difficulty)": { 23 | "description": "A brief description of the problem.", 24 | "example": """Example: 25 | Input: 26 | Output: 27 | Reasoning:""", 28 | "learn": "This section is designed to teach the user how to solve the problem without directly giving away the answer.", 29 | "starter_code": "def test_func(a: List[List[int|float]]) -> Set:\n return (n, m)", 30 | "solution": """def test_func(a: List[List[int|float]]) -> Set: 31 | # The solution to the questions""", 32 | "test_cases": [ 33 | {"test": "test_func(input_1)", "expected_output": "result_1"}, 34 | {"test": "test_func(input_2)", "expected_output": "result_2"}, 35 | {"test": "test_func(input_3)", "expected_output": "result_3"}, 36 | ], 37 | } 38 | ``` 39 | **Submit Your Changes:** After adding the new problem, commit your changes and push them to your fork. Submit a Pull Request to the main repository with your additions. 40 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | altair==5.2.0 2 | attrs==23.2.0 3 | blinker==1.7.0 4 | cachetools==5.3.3 5 | certifi==2024.2.2 6 | charset-normalizer==3.3.2 7 | click==8.1.7 8 | colorama==0.4.6 9 | gitdb==4.0.11 10 | GitPython==3.1.42 11 | idna==3.6 12 | Jinja2==3.1.3 13 | jsonschema==4.21.1 14 | jsonschema-specifications==2023.12.1 15 | markdown-it-py==3.0.0 16 | MarkupSafe==2.1.5 17 | mdurl==0.1.2 18 | numpy==1.26.4 19 | packaging==23.2 20 | pandas==2.2.1 21 | pillow==10.2.0 22 | pistonpy==0.0.3 23 | protobuf==4.25.3 24 | pyarrow==15.0.1 25 | pydeck==0.8.1b0 26 | Pygments==2.17.2 27 | python-dateutil==2.9.0.post0 28 | pytz==2024.1 29 | referencing==0.33.0 30 | requests==2.31.0 31 | rich==13.7.1 32 | rpds-py==0.18.0 33 | setuptools==68.2.2 34 | six==1.16.0 35 | smmap==5.0.1 36 | streamlit==1.32.2 37 | streamlit-ace==0.1.1 38 | tenacity==8.2.3 39 | toml==0.10.2 40 | toolz==0.12.1 41 | tornado==6.4 42 | typing==3.7.4.3 43 | typing_extensions==4.10.0 44 | tzdata==2024.1 45 | urllib3==2.2.1 46 | watchdog==4.0.0 47 | wheel==0.41.2 48 | --------------------------------------------------------------------------------