Skip to content

Commit 6218283

Browse files
authored
Merge pull request #389 from emharsha1812/main
Problems Added - 112-Cross entropy loss, 113-Early Stopping
2 parents 2495768 + 8eb9f69 commit 6218283

File tree

7 files changed

+263
-0
lines changed

7 files changed

+263
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## Multi-class Cross-Entropy Loss Implementation
2+
3+
Cross-entropy loss, also known as log loss, measures the performance of a classification model whose output is a probability value between 0 and 1. For multi-class classification tasks, we use the categorical cross-entropy loss.
4+
5+
### Mathematical Background
6+
7+
For a single sample with C classes, the categorical cross-entropy loss is defined as:
8+
9+
$L = -\sum_{c=1}^{C} y_c \log(p_c)$
10+
11+
where:
12+
13+
- $y_c$ is a binary indicator (0 or 1) if class label c is the correct classification for the sample
14+
- $p_c$ is the predicted probability that the sample belongs to class c
15+
- $C$ is the number of classes
16+
17+
### Implementation Requirements
18+
19+
Your task is to implement a function that computes the average cross-entropy loss across multiple samples:
20+
21+
$L_{batch} = -\frac{1}{N}\sum_{n=1}^{N}\sum_{c=1}^{C} y_{n,c} \log(p_{n,c})$
22+
23+
where N is the number of samples in the batch.
24+
25+
### Important Considerations
26+
27+
- Handle numerical stability by adding a small epsilon to avoid log(0)
28+
- Ensure predicted probabilities sum to 1 for each sample
29+
- Return average loss across all samples
30+
- Handle invalid inputs appropriately
31+
32+
The function should take predicted probabilities and true labels as input and return the average cross-entropy loss.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import numpy as np
2+
3+
def compute_cross_entropy_loss(predicted_probs: np.ndarray, true_labels: np.ndarray) -> float:
4+
5+
#Given
6+
epsilon = 1e-15
7+
predicted_probs = np.clip(predicted_probs, epsilon, 1 - epsilon)
8+
9+
#Write your code here
10+
log_probs = np.log(predicted_probs)
11+
loss = -np.sum(true_labels * log_probs, axis=1)
12+
return float(np.mean(loss))
13+
14+
def test_compute_cross_entropy_loss():
15+
# Test case 1: Perfect predictions
16+
pred1 = np.array([[1, 0, 0], [0, 1, 0]])
17+
true1 = np.array([[1, 0, 0], [0, 1, 0]])
18+
expected1 = 0.0
19+
assert np.isclose(compute_cross_entropy_loss(pred1, true1), expected1), "Test case 1 failed"
20+
21+
# Test case 2: Completely wrong predictions
22+
pred2 = np.array([[0.1, 0.8, 0.1], [0.8, 0.1, 0.1]])
23+
true2 = np.array([[0, 0, 1], [0, 1, 0]])
24+
expected2 = -np.mean([np.log(0.1), np.log(0.1)])
25+
assert np.isclose(compute_cross_entropy_loss(pred2, true2), expected2), "Test case 2 failed"
26+
27+
# Test case 3: Typical predictions
28+
pred3 = np.array([[0.7, 0.2, 0.1], [0.3, 0.6, 0.1]])
29+
true3 = np.array([[1, 0, 0], [0, 1, 0]])
30+
expected3 = -np.mean([np.log(0.7), np.log(0.6)])
31+
assert np.isclose(compute_cross_entropy_loss(pred3, true3), expected3), "Test case 3 failed"
32+
33+
if __name__ == "__main__":
34+
test_compute_cross_entropy_loss()
35+
print("All test cases passed!")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
## Implementing Early Stopping Criterion
2+
3+
Early stopping is a regularization technique that helps prevent overfitting in machine learning models. Your task is to implement the early stopping decision logic based on the validation loss history.
4+
5+
### Problem Description
6+
7+
Given a sequence of validation losses from model training, determine if training should be stopped based on the following criteria:
8+
9+
- Training should stop if the validation loss hasn't improved (decreased) for a specified number of epochs (patience)
10+
- An improvement is only counted if the loss decreases by more than a minimum threshold (min_delta)
11+
- The best model is the one with the lowest validation loss
12+
13+
### Example
14+
15+
Consider the following validation losses: [0.9, 0.8, 0.75, 0.77, 0.76, 0.77, 0.78]
16+
17+
- With patience=2 and min_delta=0.01:
18+
- Best loss is 0.75 at epoch 2
19+
- No improvement > 0.01 for next 2 epochs
20+
- Should stop at epoch 4
21+
22+
### Function Requirements
23+
24+
- Return both the epoch to stop at and the best epoch
25+
- If no stopping is needed, return the last epoch
26+
- Epochs are 0-indexed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import numpy as np
2+
from typing import Tuple
3+
4+
def early_stopping(val_losses: list[float], patience: int, min_delta: float) -> Tuple[int, int]:
5+
6+
best_loss = float('inf')
7+
best_epoch = 0
8+
epochs_without_improvement = 0
9+
10+
for epoch, loss in enumerate(val_losses):
11+
# Check if current loss is better than best loss by at least min_delta
12+
if loss < best_loss - min_delta:
13+
best_loss = loss
14+
best_epoch = epoch
15+
epochs_without_improvement = 0
16+
else:
17+
epochs_without_improvement += 1
18+
19+
# Check if we should stop
20+
if epochs_without_improvement >= patience:
21+
return epoch, best_epoch
22+
23+
# If we never hit the patience threshold, return the last epoch
24+
return len(val_losses) - 1, best_epoch
25+
26+
def test_early_stopping():
27+
28+
losses1 = [0.9, 0.8, 0.75, 0.77, 0.76, 0.77, 0.78]
29+
stop_epoch1, best_epoch1 = early_stopping(losses1, patience=2, min_delta=0.01)
30+
assert stop_epoch1 == 4 and best_epoch1 == 2, "Test case 1 failed"
31+
32+
losses2 = [0.9, 0.8, 0.7, 0.6, 0.5]
33+
stop_epoch2, best_epoch2 = early_stopping(losses2, patience=2, min_delta=0.01)
34+
assert stop_epoch2 == 4 and best_epoch2 == 4, "Test case 2 failed"
35+
36+
losses3 = [0.9, 0.8, 0.79, 0.78, 0.77]
37+
stop_epoch3, best_epoch3 = early_stopping(losses3, patience=2, min_delta=0.1)
38+
assert stop_epoch3 == 4 and best_epoch3 == 2, "Test case 3 failed"
39+
40+
losses4 = [0.5, 0.4]
41+
stop_epoch4, best_epoch4 = early_stopping(losses4, patience=3, min_delta=0.01)
42+
assert stop_epoch4 == 1 and best_epoch4 == 1, "Test case 4 failed"
43+
44+
losses5 = [0.5, 0.4, 0.4, 0.4, 0.4]
45+
stop_epoch5, best_epoch5 = early_stopping(losses5, patience=2, min_delta=0.01)
46+
assert stop_epoch5 == 3 and best_epoch5 == 1, "Test case 5 failed"
47+
48+
if __name__ == "__main__":
49+
test_early_stopping()
50+
print("All test cases passed!")

Problems/problem_list.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import os
2+
3+
problems_folder = "Problems"
4+
folder_names = []
5+
6+
# Check if the "Problems" folder exists
7+
if os.path.exists(problems_folder) and os.path.isdir(problems_folder):
8+
# Iterate through all items in the "Problems" folder
9+
for item in os.listdir(problems_folder):
10+
# Check if the item is a directory
11+
item_path = os.path.join(problems_folder, item)
12+
if os.path.isdir(item_path):
13+
folder_names.append(item)
14+
15+
# Write the folder names to a text file
16+
with open("problems_folder_list.txt", "w") as f:
17+
for name in folder_names:
18+
f.write(name + "\n")
19+
20+
print("Folder names inside 'Problems' written to problems_folder_list.txt")
21+
else:
22+
print("The 'Problems' folder does not exist.")

folder_list.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.git
2+
.github
3+
example_problem
4+
Problems
5+
__pycache__

problems_folder_list.txt

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
100_Softsign
2+
102_Swish
3+
103_SELU
4+
104_logistic_regression
5+
105_train_softmaxreg
6+
106_train_logreg
7+
107_masked_attention
8+
10_Calculate_cov_matrix
9+
110_METEOR
10+
111_PMI
11+
112_cross_entropy_loss
12+
113_early_stopping
13+
11_Linear_equations_jacobi
14+
12_svd_2x2_singular_values
15+
13_determinant_4x4
16+
14_linear_regression_normal_equation
17+
15_linear_regression_gradient_descent
18+
16_feature_scaling
19+
17_k_means_clustering
20+
18_cross_validation_split
21+
19_PCA
22+
1_matrix_times_vector
23+
20_decision_tree_learning
24+
21_pegasos_kernel_svm
25+
22_sigmoid
26+
23_softmax
27+
24_single_neuron
28+
25_Single_Neuron_with_Backpropagation
29+
26_Autograd
30+
28_svd_2x2_eign
31+
2_transpose_matrix
32+
32_polynomial_features
33+
33_random_subsets
34+
35 - Vector to Matrix
35+
39_log_softmax
36+
3_reshape_matrix
37+
41_simple_conv2d_layer
38+
42_relu_activation_function
39+
43_ridge_loss
40+
44_leaky_relu
41+
45_linear_kernel
42+
46_precision
43+
47_gradient_descent
44+
48_rref
45+
4_calculate_mean_by_row_or_column
46+
50_lasso_regression_gradient_descent
47+
51_OSA_distance
48+
52_recall
49+
53_self_attention
50+
54_RNN_layer
51+
55_2D_translation_matrix
52+
57_gauss_seidel
53+
58_gaussian_elimination_partial_pivoting
54+
5_scalar_multiplication_of_a_matrix
55+
60_TF-IDF
56+
61_f_score
57+
63_conjugate_gradient
58+
64_gini_impurity
59+
65_compressed_row_sparse_matrix
60+
66_orthogonal_projection
61+
67_compressed_column_sparse_matrix
62+
69_r-squared
63+
6_calculate_eigenvalues
64+
70_image_brightness_calculator
65+
71_Room_Mean_Square_Error
66+
73_Dice_Score
67+
74_hdc_bundling_binding
68+
75_classification_performance_metrics
69+
76_Cosine_Similarity
70+
77_classification_performance_metrics
71+
78_binomial_distribution
72+
78_descriptive_stats
73+
7_transform_matrix
74+
80_normal_distribution
75+
81_poisson_distribution
76+
82_image_basic_contrast_calculator
77+
83_vector_dot_product
78+
84_phi_transformation
79+
85_Positional_encoding
80+
86_overfitting_underfitting
81+
87_adam_optimizer
82+
88_GPT_2
83+
8_Calculate_2x2_Matrix_Inverse
84+
94_multi_head_attention
85+
95_phi_correlation_coefficient
86+
96_Hard_Sigmoid
87+
97_ELU
88+
98_PReLU
89+
99_Softplus
90+
9_matrixmul
91+
BM25
92+
interactive_learn
93+
MAE

0 commit comments

Comments
 (0)