Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
title: Conditionals and Branching
sidebar_label: Conditionals
description: "Mastering If, Else, and Elif statements to control program flow and handle logic in Machine Learning pipelines."
tags: [python, programming, logic, conditionals, branching, mathematics-for-ml]
---

Machine Learning is often about making decisions. **Conditionals** allow our code to react differently depending on the input. Whether it's checking if a dataset is empty or deciding which model to load, `if-else` logic is the foundation of programmatic decision-making.

## 1. The `if`, `elif`, and `else` Structure

Python uses indentation to define the scope of conditional blocks.

```python
accuracy = 0.85

if accuracy > 0.90:
print("Excellent model performance!")
elif accuracy > 0.70:
print("Good performance, but could be improved.")
else:
print("Model needs retraining.")

```

```mermaid
flowchart TD
Start([Check Accuracy]) --> C1{Acc > 0.90?}
C1 -- Yes --> R1[Print: Excellent]
C1 -- No --> C2{Acc > 0.70?}
C2 -- Yes --> R2[Print: Good]
C2 -- No --> R3[Print: Retrain]

```

## 2. Comparison and Logical Operators

Conditionals rely on boolean expressions that evaluate to either `True` or `False`.

### A. Comparison Operators

* `==` (Equal to)
* `!=` (Not equal to)
* `>` / `<` (Greater/Less than)
* `>=` / `<=` (Greater/Less than or equal to)

### B. Logical Operators (Chaining)

* `and`: Both conditions must be True.
* `or`: At least one condition must be True.
* `not`: Reverses the boolean value.

```python
# Check if learning rate is within a safe range
lr = 0.001
if lr > 0 and lr < 0.1:
print("Learning rate is valid.")

```

## 3. The "ReLU" Example: Math meets Logic

One of the most famous conditional operations in Deep Learning is the **Rectified Linear Unit (ReLU)** activation function.

$$
\text{ReLU}(x) = \max(0, x)
$$

In Python code, this is a simple conditional:

```python
def relu(x):
if x > 0:
return x
else:
return 0

```

## 4. Truthiness and Identity

In ML data cleaning, we often check if a variable actually contains data.

* **Falsy values:** `None`, `0`, `0.0`, `""` (empty string), `[]` (empty list), `{}` (empty dict).
* **Truthy values:** Everything else.

```python
features = get_features()

if not features:
print("Warning: No features found in dataset!")

```

### `is` vs `==`

* `==` checks for **Value equality** (Are the numbers the same?).
* `is` checks for **Identity** (Are they the exact same object in memory?).

## 5. Inline Conditionals (Ternary Operator)

For simple logic, Python allows a one-liner known as a ternary operator.

```python
# status = "Spam" if probability > 0.5 else "Not Spam"
prediction = "Positive" if y_hat > 0.5 else "Negative"

```

## 6. Match-Case (Python 3.10+)

For complex branching based on specific patterns (like different file extensions or model types), the `match` statement provides a cleaner syntax than multiple `elif` blocks.

```python
optimizer_type = "adam"

match optimizer_type:
case "sgd":
print("Using Stochastic Gradient Descent")
case "adam":
print("Using Adam Optimizer")
case _:
print("Using Default Optimizer")

```

---

Decision-making is key, but to keep our code clean, we shouldn't repeat our logic. We need to wrap our conditionals and loops into reusable components.
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
title: Data Structures
sidebar_label: Data Structures
description: "Mastering Python's built-in collections: Lists, Tuples, Dictionaries, and Sets, and their specific roles in data science pipelines."
tags: [python, data-structures, lists, dictionaries, tuples, sets, mathematics-for-ml]
---

While basic types hold single values, **Data Structures** allow us to group, organize, and manipulate large amounts of information. In ML, choosing the wrong structure can lead to code that runs $100\times$ slower than it should.

## 1. Lists: The Versatile Workhorse

A **List** is an ordered, mutable collection of items. Think of it as a flexible array that can grow or shrink.

* **Syntax:** `my_list = [0.1, 0.2, 0.3]`
* **ML Use Case:** Storing the history of "Loss" values during training so you can plot them later.

```python
losses = []
for epoch in range(10):
current_loss = train_step()
losses.append(current_loss) # Dynamic growth

```

## 2. Tuples: The Immutable Safeguard

A **Tuple** is like a list, but it **cannot be changed** after creation (immutable).

* **Syntax:** `shape = (224, 224, 3)`
* **ML Use Case:** Defining image dimensions or model architectures. Since these shouldn't change accidentally during execution, a tuple is safer than a list.

```mermaid
graph LR
L[List: Mutable] --> L_Edit["Can change: my_list[0] = 5"]
T[Tuple: Immutable] --> T_Edit["Error: 'tuple' object does not support assignment"]
style T fill:#fffde7,stroke:#fbc02d,color:#333

```

## 3. Dictionaries: Key-Value Mapping

A **Dictionary** stores data in pairs: a unique **Key** and its associated **Value**. It uses a "Hash Table" internally, making lookups incredibly fast ( complexity).

* **Syntax:** `params = {"learning_rate": 0.001, "batch_size": 32}`
* **ML Use Case:** Managing hyperparameters or mapping integer IDs back to human-readable text labels.

```mermaid
graph TD
Key["Key: 'Cat'"] --> Hash["Hash Function"]
Hash --> Index["Memory Index: 0x42"]
Index --> Val["Value: [0.98, 0.02, ...]"]
style Hash fill:#e1f5fe,stroke:#01579b,color:#333

```

## 4. Sets: Uniqueness and Logic

A **Set** is an unordered collection of **unique** items.

* **Syntax:** `classes = {"dog", "cat", "bird"}`
* **ML Use Case:** Finding the unique labels in a messy dataset or performing mathematical operations like Union and Intersection on feature sets.

## 5. Performance Comparison

Choosing the right structure is about balancing **Speed** and **Memory**.

| Feature | List | Tuple | Dictionary | Set |
| --- | --- | --- | --- | --- |
| **Ordering** | Ordered | Ordered | Ordered (Python 3.7+) | Unordered |
| **Mutable** | **Yes** | No | **Yes** | **Yes** |
| **Duplicates** | Allowed | Allowed | Keys must be unique | Must be unique |
| **Search Speed** | (Slow) | (Slow) | (Very Fast) | (Very Fast) |

```mermaid
xychart-beta
title "Search Speed (Lower is Better)"
x-axis ["List", "Tuple", "Set", "Dict"]
y-axis "Time Complexity" 0 --> 120
bar [100, 100, 5, 5]

```

## 6. Slicing and Indexing

In ML, we often need to "slice" our data (e.g., taking the first 80% for training and the last 20% for testing).

$$
\text{Syntax: } \text{data}[\text{start} : \text{stop} : \text{step}]
$$

```python
data = [10, 20, 30, 40, 50, 60]
train = data[:4] # [10, 20, 30, 40]
test = data[4:] # [50, 60]

```

---

Now that we can organize data, we need to control the flow of our program—making decisions based on that data and repeating tasks efficiently.
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
---
title: Exception Handling
sidebar_label: Exceptions
description: "Learning to handle errors gracefully in Python to build robust and fault-tolerant Machine Learning pipelines."
tags: [python, programming, exceptions, error-handling, debugging, mathematics-for-ml]
---

In Machine Learning, things often go wrong: a dataset file is missing, a GPU runs out of memory, or a feature contains a `NaN` (Not a Number) that crashes a calculation. **Exception Handling** allows your program to "fail gracefully" rather than crashing completely.

## 1. The Try-Except Block

The basic tool for handling errors is the `try...except` block. You "try" a piece of code, and if it raises an error, the "except" block catches it.

```python
try:
# Attempting to load a large dataset
data = load_dataset("huge_data.csv")
except FileNotFoundError:
print("Error: The dataset file was not found. Please check the path.")

```

```mermaid
flowchart TD
Start([Start Try Block]) --> Op[Execute Code]
Op --> Success{Error Occurred?}
Success -- No --> End([Continue Program])
Success -- Yes --> Catch[Match Exception Type]
Catch --> Handle[Execute Except Block]
Handle --> End
style Catch fill:#ffebee,stroke:#c62828,color:#333

```

## 2. Handling Multiple Exceptions

Different operations can fail in different ways. You can catch specific errors to provide tailored solutions.

* **`ValueError`**: Raised when a function receives an argument of the right type but inappropriate value (e.g., trying to take the square root of a negative number).
* **`TypeError`**: Raised when an operation is applied to an object of inappropriate type.
* **`ZeroDivisionError`**: Common in manual normalization logic.

```python
try:
result = total_loss / num_samples
except ZeroDivisionError:
result = 0
print("Warning: num_samples was zero. Setting loss to 0.")
except TypeError:
print("Error: Check if total_loss and num_samples are numbers.")

```

## 3. The Full Lifecycle: `else` and `finally`

To build truly robust pipelines (like those that open and close database connections), we use the extended syntax:

1. **`try`**: The code that might fail.
2. **`except`**: Code that runs only if an error occurs.
3. **`else`**: Code that runs only if **no** error occurs.
4. **`finally`**: Code that runs **no matter what** (perfect for closing files or releasing GPU memory).

```python
try:
file = open("model_weights.bin", "rb")
weights = file.read()
except IOError:
print("Could not read file.")
else:
print("Weights loaded successfully.")
finally:
file.close()
print("File resource released.")

```

## 4. Raising Exceptions

Sometimes, you *want* to stop the program if a specific condition isn't met. For example, if a user provides a negative learning rate.

```python
def set_learning_rate(lr):
if lr <= 0:
raise ValueError(f"Learning rate must be positive. Received: {lr}")
return lr

```

## 5. Exceptions in ML Data Pipelines

In production ML, we use exceptions to ensure data quality.

```mermaid
graph LR
Input[Data Source] --> Check{Check Data}
Check -->|Valid| Train[Start Training]
Check -->|Corrupted| Exc[Raise DataValidationError]
Exc --> Log[Log Error to Dashboard]
Exc --> Fallback[Use Last Known Good Data]
style Exc fill:#ffc107,stroke:#ff8f00,color:#333

```

## 6. Summary of Common ML Exceptions

| Exception | When it happens in ML |
| --- | --- |
| **`IndexError`** | Trying to access a non-existent column or row index in an array. |
| **`KeyError`** | Looking for a hyperparameter in a config dictionary that doesn't exist. |
| **`AttributeError`** | Calling a method (like `.predict()`) on a model that hasn't been trained yet. |
| **`MemoryError`** | Loading a dataset that is larger than the available RAM. |

---

Handling errors ensures your code doesn't crash, but how do we organize our code so it's easy to read and maintain? Let's explore the world of Classes and Objects.
Loading