Bias-Variance Decomposition for Regression Problems

In this example, we will see how to calculate the bias-variance decomposition for regression problems.

[1]:
import pandas as pd

from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split

from mvtk.bias_variance import bias_variance_compute, bias_variance_mse
from mvtk.bias_variance.estimators import EstimatorWrapper
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
I0000 00:00:1701450845.494601       1 tfrt_cpu_pjrt_client.cc:349] TfrtCpuClient created.
[2]:
random_state=123

Load the example dataset

[3]:
housing = fetch_california_housing()
X = pd.DataFrame(housing.data, columns=housing.feature_names)
y = housing.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=random_state)

Scikit-Learn Example

[4]:
from sklearn.linear_model import LinearRegression

from mvtk.bias_variance.estimators import SciKitLearnEstimatorWrapper
[5]:
model_scikit = LinearRegression()

Need to instantiate a wrapper class for usage by the bias variance calculation

[6]:
model_scikit_wrapped = SciKitLearnEstimatorWrapper(model_scikit)
[7]:
# Use wrapped estimator
avg_loss, avg_bias, avg_var, net_var = bias_variance_compute(model_scikit_wrapped, X_train, y_train, X_test, y_test, iterations=200,
                                                             random_state=random_state, decomp_fn=bias_variance_mse)

print(f'average loss: {avg_loss:10.8f}')
print(f'average bias: {avg_bias:10.8f}')
print(f'average variance: {avg_var:10.8f}')
print(f'net variance: {net_var:10.8f}')
average loss: 0.59902430
average bias: 0.52119134
average variance: 0.07783295
net variance: 0.07783295

PyTorch Example

[8]:
import torch
import torch.nn as nn

from mvtk.bias_variance.estimators import PyTorchEstimatorWrapper
[9]:
X_train_torch = torch.FloatTensor(X_train.values)
X_test_torch = torch.FloatTensor(X_test.values)
y_train_torch = torch.FloatTensor(y_train).reshape(-1, 1)
y_test_torch = torch.FloatTensor(y_test).reshape(-1, 1)
[10]:
class ModelPyTorch(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear1 = nn.Linear(8, 24)
        self.linear2 = nn.Linear(24, 12)
        self.linear3 = nn.Linear(12, 6)
        self.linear4 = nn.Linear(6, 1)

    def forward(self, x):
        x = self.linear1(x)
        x = self.linear2(x)
        x = self.linear3(x)
        x = self.linear4(x)
        return x
[11]:
model_pytorch = ModelPyTorch()
optimizer = torch.optim.Adam(model_pytorch.parameters(), lr=0.001)
loss_fn = nn.MSELoss()

Need to instantiate a wrapper class for usage by the bias variance calculation

[12]:
def optimizer_generator(x):
    return torch.optim.Adam(x.parameters(), lr=0.001)
[13]:
model_pytorch_wrapped = PyTorchEstimatorWrapper(model_pytorch, optimizer_generator, loss_fn)
[14]:
# Use wrapped estimator
avg_loss, avg_bias, avg_var, net_var = bias_variance_compute(model_pytorch_wrapped, X_train_torch, y_train_torch, X_test_torch, y_test,
                                                             iterations=200, random_state=random_state, decomp_fn=bias_variance_mse,
                                                             fit_kwargs={'epochs': 25})

print(f'average loss: {avg_loss:10.8f}')
print(f'average bias: {avg_bias:10.8f}')
print(f'average variance: {avg_var:10.8f}')
print(f'net variance: {net_var:10.8f}')
average loss: 153.52321480
average bias: 5.05105724
average variance: 148.47215756
net variance: 148.47215756

TensorFlow example

[15]:
import tensorflow as tf
from keras import initializers

from mvtk.bias_variance.estimators import TensorFlowEstimatorWrapper
[16]:
model_tensorflow = tf.keras.Sequential([
    tf.keras.layers.Dense(64, activation='relu', kernel_initializer=initializers.glorot_uniform(seed=0)),
    tf.keras.layers.Dense(64, activation='relu', kernel_initializer=initializers.glorot_uniform(seed=0)),
    tf.keras.layers.Dense(1, kernel_initializer=initializers.glorot_uniform(seed=0))
])
[17]:
model_tensorflow.compile(optimizer=tf.keras.optimizers.legacy.Adam(learning_rate=0.001),
             loss='mean_absolute_error',
             metrics=['mean_squared_error'])
[18]:
model_tensorflow_wrapped = TensorFlowEstimatorWrapper(model_tensorflow)
[19]:
# Use wrapped estimator
avg_loss, avg_bias, avg_var, net_var = bias_variance_compute(model_tensorflow_wrapped, X_train, y_train, X_test, y_test, iterations=200,
                                                             random_state=random_state, decomp_fn=bias_variance_mse,
                                                             fit_kwargs={'epochs': 25, 'batch_size': 5000, 'verbose': False},
                                                             predict_kwargs={'verbose': False})

print(f'average loss: {avg_loss:10.8f}')
print(f'average bias: {avg_bias:10.8f}')
print(f'average variance: {avg_var:10.8f}')
print(f'net variance: {net_var:10.8f}')
average loss: 12.15213883
average bias: 3.08502204
average variance: 9.06711679
net variance: 9.06711679

We can run the same bias variance calculation in parallel for faster execution (in general for larger datasets and more intensive computations)

[20]:
from mvtk.bias_variance import bias_variance_compute_parallel

avg_loss, avg_bias, avg_var, net_var = bias_variance_compute_parallel(model_tensorflow_wrapped, X_train, y_train, X_test, y_test,
                                                                      iterations=200, random_state=random_state,
                                                                      decomp_fn=bias_variance_mse,
                                                                      fit_kwargs={'epochs': 25, 'batch_size': 5000, 'verbose': False},
                                                                      predict_kwargs={'verbose': False})

print(f'average loss: {avg_loss:10.8f}')
print(f'average bias: {avg_bias:10.8f}')
print(f'average variance: {avg_var:10.8f}')
print(f'net variance: {net_var:10.8f}')
2023-12-01 12:15:52,912 INFO worker.py:1673 -- Started a local Ray instance.
(pid=73435) WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
(pid=73435) I0000 00:00:1701450956.584361       1 tfrt_cpu_pjrt_client.cc:349] TfrtCpuClient created.
average loss: 7.90420163
average bias: 4.06288774
average variance: 3.84131389
net variance: 3.84131389
[ ]: