xbe.at

Deep learning / Activation functions and loss

Regression and Classification Loss Functions

8 min read, 14 sections

Contents
  1. Regression Loss Functions: Mean Bias Error
  2. Mean Absolute Error
  3. Mean Squared Error
  4. Root Mean Squared Error
  5. Huber Loss
  6. Log-Cosh Loss
  7. Real-Life Example: Weather Prediction
  8. Binary Cross-Entropy Loss
  9. Hinge Loss
  10. Cross-Entropy Loss
  11. Kullback-Leibler Divergence
  12. Real-Life Example: Image Classification
  13. Comparing Loss Functions: Regression vs. Classification
  14. Additional Resources

Regression Loss Functions: Mean Bias Error

Mean Bias Error (MBE) captures the average bias in predictions. It's rarely used for training as positive and negative errors can cancel each other out, potentially masking the model's true performance. MBE is useful for understanding if a model consistently over- or under-predicts.

import numpy as np

def mean_bias_error(y_true, y_pred):
    return np.mean(y_pred - y_true)

# Example
y_true = np.array([3, 2, 5, 1, 7])
y_pred = np.array([2.5, 2.2, 4.8, 1.5, 6.5])

mbe = mean_bias_error(y_true, y_pred)
print(f"Mean Bias Error: {mbe:.4f}")

# Output: Mean Bias Error: -0.2400

Mean Absolute Error

Mean Absolute Error (MAE) measures the average absolute difference between predicted and actual values. It treats all errors equally, regardless of their magnitude. This can be advantageous when dealing with outliers, but it may not capture the severity of large errors effectively.

import numpy as np

def mean_absolute_error(y_true, y_pred):
    return np.mean(np.abs(y_pred - y_true))

# Example
y_true = np.array([3, 2, 5, 1, 7])
y_pred = np.array([2.5, 2.2, 4.8, 1.5, 6.5])

mae = mean_absolute_error(y_true, y_pred)
print(f"Mean Absolute Error: {mae:.4f}")

# Output: Mean Absolute Error: 0.3400

Mean Squared Error

Mean Squared Error (MSE) emphasizes larger errors by squaring the differences. This makes it more sensitive to outliers compared to MAE. MSE is widely used in regression tasks because it penalizes larger errors more heavily, encouraging the model to avoid significant mistakes.

import numpy as np

def mean_squared_error(y_true, y_pred):
    return np.mean((y_pred - y_true) ** 2)

# Example
y_true = np.array([3, 2, 5, 1, 7])
y_pred = np.array([2.5, 2.2, 4.8, 1.5, 6.5])

mse = mean_squared_error(y_true, y_pred)
print(f"Mean Squared Error: {mse:.4f}")

# Output: Mean Squared Error: 0.1780

Root Mean Squared Error

Root Mean Squared Error (RMSE) is the square root of MSE. It's used to ensure that the loss and the dependent variable (y) have the same units. RMSE is interpretable in the same scale as the target variable, making it easier to understand the magnitude of the error in the context of the problem.

import numpy as np

def root_mean_squared_error(y_true, y_pred):
    return np.sqrt(np.mean((y_pred - y_true) ** 2))

# Example
y_true = np.array([3, 2, 5, 1, 7])
y_pred = np.array([2.5, 2.2, 4.8, 1.5, 6.5])

rmse = root_mean_squared_error(y_true, y_pred)
print(f"Root Mean Squared Error: {rmse:.4f}")

# Output: Root Mean Squared Error: 0.4219

Huber Loss

Huber Loss combines the best properties of MAE and MSE. For smaller errors, it behaves like MSE, while for larger errors, it acts like MAE. This makes it less sensitive to outliers than MSE while still providing a smooth gradient for optimization. The delta parameter controls the transition point between the quadratic and linear portions of the loss.

import numpy as np

def huber_loss(y_true, y_pred, delta=1.0):
    error = y_pred - y_true
    is_small_error = np.abs(error) <= delta
    squared_loss = 0.5 * error ** 2
    linear_loss = delta * (np.abs(error) - 0.5 * delta)
    return np.mean(np.where(is_small_error, squared_loss, linear_loss))

# Example
y_true = np.array([3, 2, 5, 1, 7])
y_pred = np.array([2.5, 2.2, 4.8, 1.5, 6.5])

huber = huber_loss(y_true, y_pred)
print(f"Huber Loss: {huber:.4f}")

# Output: Huber Loss: 0.1140

Log-Cosh Loss

Log-Cosh Loss is a smooth approximation of the Huber Loss without the need for a delta parameter. It behaves like MSE for small errors and like MAE for large errors. This loss function is less sensitive to outliers and provides stable gradients for optimization.

import numpy as np

def log_cosh_loss(y_true, y_pred):
    return np.mean(np.log(np.cosh(y_pred - y_true)))

# Example
y_true = np.array([3, 2, 5, 1, 7])
y_pred = np.array([2.5, 2.2, 4.8, 1.5, 6.5])

log_cosh = log_cosh_loss(y_true, y_pred)
print(f"Log-Cosh Loss: {log_cosh:.4f}")

# Output: Log-Cosh Loss: 0.0564

Real-Life Example: Weather Prediction

Consider a weather prediction model that forecasts daily temperatures. Different loss functions can be used depending on the specific requirements:

  1. MAE: Useful when we want to minimize the average error in temperature predictions, treating all errors equally.
  2. MSE/RMSE: Appropriate when larger errors (e.g., predicting 25°C when it's actually 15°C) are more problematic than smaller errors.
  3. Huber Loss: Suitable when we want to balance between MAE and MSE, being less sensitive to occasional large errors caused by unexpected weather events.
import numpy as np

# Actual temperatures for a week
actual_temps = np.array([20, 22, 25, 23, 19, 18, 21])

# Predicted temperatures
predicted_temps = np.array([19.5, 22.5, 24.0, 23.5, 20.0, 17.5, 21.5])

mae = mean_absolute_error(actual_temps, predicted_temps)
rmse = root_mean_squared_error(actual_temps, predicted_temps)
huber = huber_loss(actual_temps, predicted_temps)

print(f"MAE: {mae:.2f}°C")
print(f"RMSE: {rmse:.2f}°C")
print(f"Huber Loss: {huber:.2f}")

# Output:
# MAE: 0.75°C
# RMSE: 0.87°C
# Huber Loss: 0.28

Binary Cross-Entropy Loss

Binary Cross-Entropy (BCE) Loss is used for binary classification tasks. It measures the dissimilarity between predicted probabilities and true binary labels through logarithmic loss. BCE is particularly effective for problems where the output is a probability between 0 and 1.

import numpy as np

def binary_cross_entropy(y_true, y_pred):
    epsilon = 1e-15  # Small value to avoid log(0)
    y_pred = np.clip(y_pred, epsilon, 1 - epsilon)  # Clip values to avoid log(0)
    return -np.mean(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))

# Example
y_true = np.array([1, 0, 1, 0, 1])
y_pred = np.array([0.9, 0.1, 0.8, 0.3, 0.95])

bce = binary_cross_entropy(y_true, y_pred)
print(f"Binary Cross-Entropy Loss: {bce:.4f}")

# Output: Binary Cross-Entropy Loss: 0.2201

Hinge Loss

Hinge Loss is commonly used in support vector machines (SVMs) for binary classification. It penalizes both incorrect predictions and correct but less confident predictions. Hinge loss is based on the concept of margin, which represents the distance between a data point and the decision boundary.

import numpy as np

def hinge_loss(y_true, y_pred):
    # Convert binary labels to -1 and 1
    y_true = 2 * y_true - 1
    return np.mean(np.maximum(0, 1 - y_true * y_pred))

# Example
y_true = np.array([1, 0, 1, 0, 1])
y_pred = np.array([0.9, -0.1, 0.8, 0.3, 0.95])

hinge = hinge_loss(y_true, y_pred)
print(f"Hinge Loss: {hinge:.4f}")

# Output: Hinge Loss: 0.1900

Cross-Entropy Loss

Cross-Entropy Loss is an extension of BCE loss to multi-class classification tasks. It measures the dissimilarity between predicted probability distributions and true class labels. Cross-entropy loss is widely used in neural networks for classification problems with more than two classes.

import numpy as np

def cross_entropy_loss(y_true, y_pred):
    epsilon = 1e-15  # Small value to avoid log(0)
    y_pred = np.clip(y_pred, epsilon, 1 - epsilon)  # Clip values to avoid log(0)
    return -np.sum(y_true * np.log(y_pred)) / len(y_true)

# Example
y_true = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
y_pred = np.array([[0.8, 0.1, 0.1], [0.2, 0.7, 0.1], [0.1, 0.2, 0.7]])

ce = cross_entropy_loss(y_true, y_pred)
print(f"Cross-Entropy Loss: {ce:.4f}")

# Output: Cross-Entropy Loss: 0.3567

Kullback-Leibler Divergence

Kullback-Leibler (KL) Divergence measures the information lost when one distribution is approximated using another distribution. In classification tasks, minimizing KL divergence is equivalent to minimizing cross-entropy. KL divergence is used in various machine learning applications, including t-SNE and knowledge distillation for model compression.

import numpy as np

def kl_divergence(p, q):
    epsilon = 1e-15  # Small value to avoid log(0)
    p = np.clip(p, epsilon, 1)
    q = np.clip(q, epsilon, 1)
    return np.sum(p * np.log(p / q))

# Example
p = np.array([0.3, 0.5, 0.2])  # True distribution
q = np.array([0.25, 0.6, 0.15])  # Predicted distribution

kl_div = kl_divergence(p, q)
print(f"KL Divergence: {kl_div:.4f}")

# Output: KL Divergence: 0.0389

Real-Life Example: Image Classification

Consider an image classification model that categorizes images of fruits into three classes: apples, bananas, and oranges. We can use cross-entropy loss to train this model:

import numpy as np

def softmax(x):
    e_x = np.exp(x - np.max(x))
    return e_x / e_x.sum(axis=0)

# True labels (one-hot encoded)
y_true = np.array([
    [1, 0, 0],  # Apple
    [0, 1, 0],  # Banana
    [0, 0, 1],  # Orange
    [1, 0, 0]   # Apple
])

# Model predictions (raw scores before softmax)
raw_predictions = np.array([
    [2.0, 1.0, 0.5],
    [0.8, 2.5, 1.2],
    [0.6, 1.5, 2.8],
    [2.2, 0.9, 1.1]
])

# Apply softmax to get probability distributions
y_pred = softmax(raw_predictions)

ce_loss = cross_entropy_loss(y_true, y_pred)
print(f"Cross-Entropy Loss: {ce_loss:.4f}")

# Output: Cross-Entropy Loss: 0.4184

This example demonstrates how cross-entropy loss can be used to evaluate and train a multi-class image classification model.

Comparing Loss Functions: Regression vs. Classification

Regression and classification tasks require different loss functions due to their distinct objectives. Regression aims to predict continuous values, while classification focuses on assigning discrete labels. Here's a comparison of key loss functions:

Regression:

  • MSE/RMSE: Suitable for general regression tasks, sensitive to outliers
  • MAE: Less sensitive to outliers, useful when outliers are expected
  • Huber Loss: Balances MSE and MAE, adaptable to various scenarios

Classification:

  • Binary Cross-Entropy: Ideal for binary classification
  • Cross-Entropy: Extends to multi-class problems
  • Hinge Loss: Useful for maximum-margin classifiers like SVMs

The choice of loss function depends on the specific problem, data characteristics, and desired model behavior.

import numpy as np
import matplotlib.pyplot as plt

# Generate data
x = np.linspace(-3, 3, 100)
mse = x**2
mae = np.abs(x)
huber = np.where(np.abs(x) <= 1, 0.5 * x**2, np.abs(x) - 0.5)

# Plot
plt.figure(figsize=(10, 6))
plt.plot(x, mse, label='MSE')
plt.plot(x, mae, label='MAE')
plt.plot(x, huber, label='Huber')
plt.title('Comparison of Regression Loss Functions')
plt.xlabel('Error')
plt.ylabel('Loss')
plt.legend()
plt.grid(True)
plt.show()

Additional Resources

For those interested in diving deeper into loss functions and their applications in machine learning, the following resources provide valuable insights:

  1. "Understanding the difficulty of training deep feedforward neural networks" by Xavier Glorot and Yoshua Bengio (2010) ArXiv: https://arxiv.org/abs/1010.3099
  2. "Visualizing the Loss Landscape of Neural Nets" by Hao Li et al. (2018) ArXiv: https://arxiv.org/abs/1712.09913
  3. "An Overview of Loss Functions in Machine Learning" by Sebastian Raschka (2018) ArXiv: https://arxiv.org/abs/1804.09170

These papers offer in-depth discussions on loss functions, their properties, and their impact on model training and performance.

More in Activation functions and loss

  1. Response:8 min

    Neural networks transform input data through layers of interconnected nodes, with activation functions determining the output of each neuron. These...

  2. Neural Network Loss Functions in Python5 min

    Introduction to Neural Network Loss Functions

  3. Sigmoid Activation Function in Python7 min

    The sigmoid activation function is a fundamental component in neural networks and machine learning. It maps input values to an output range between 0 and 1...

  4. Mastering Loss Functions for Linear Regression in Machine Learning9 min

    Loss functions are mathematical constructs that measure the difference between predicted and actual values in machine learning models. For linear regression...

  5. Softmax Activation Function in Neural Networks with Python10 min

    The Softmax activation function is a crucial component in neural networks, particularly for multi-class classification problems. It transforms a vector of...

  6. Machine Learning Loss Functions for Regression and Classification Using Python6 min

    Mean Squared Error is a common loss function for regression tasks. It measures the average squared difference between predicted and actual values, penalizing...