Hồi quy phân phối có điều kiện sâu – Dự đoán toàn bộ phân phối đầu ra bằng mạng nơ-ron

Phương pháp Deep Conditional Distribution Regression (DCDR) cho phép ta không chỉ dự đoán giá trị kỳ vọng mà còn xây dựng toàn bộ phân phối xác suất của biến mục tiêu khi biết đầu vào. Kỹ thuật này đặc biệt hữu ích trong các bài toán quản lý rủi ro, dự báo thời tiết, phân tích tín dụng… nơi việc nắm rõ mức độ bất định quan trọng hơn một điểm dự đoán duy nhất.

1. Kiến trúc ý tưởng

Thay vì đầu ra là một số vô hướng ŷ, mạng nơ-ron sẽ sinh ra các tham số của một họ phân phối có thể thay đổi theo đầu vào x. Ví dụ, nếu ta chọn họ Normal, mạng sẽ trả về cặp μ(x)σ(x):

import tensorflow as tf
from tensorflow.keras import layers, models

def build_dist_network(n_features):
    inp = layers.Input(shape=(n_features,))
    h = layers.Dense(128, activation='relu')(inp)
    h = layers.Dense(64, activation='relu')(h)
    mu = layers.Dense(1, name='mu')(h)
    sigma = layers.Dense(1, activation='softplus', name='sigma')(h)
    return models.Model(inp, [mu, sigma])

Mất mát huấn luyện là NLL (Negative Log-Likelihood) của phân phối đã chọn:

def nll_normal(y_true, mu, sigma):
    dist = tf.distributions.Normal(mu, sigma)
    return -tf.reduce_mean(dist.log_prob(y_true))

2. Chuẩn bị dữ liệu

Giả sử ta có tập dữ liệu data.csv chứa các cột đặc trưng X1…Xn và biến liên tục target. Quy trình xử lý gồm:

  1. Xử lý giá trị thiếu bằng SimpleImputer.
  2. Mã hóa biến phân loại bằng OneHotEncoder.
  3. Chuẩn hóa đặc trưng số với StandardScaler.
  4. Chia tập huấn luyện/kiểm tra theo tỷ lệ 80/20.
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.model_selection import train_test_split
import pandas as pd

df = pd.read_csv('data.csv')
X, y = df.drop(columns=['target']), df['target']

num_cols = X.select_dtypes(include=['int64','float64']).columns
cat_cols = X.select_dtypes(include=['object','category']).columns

preproc = ColumnTransformer([
    ('num', Pipeline([
        ('imp', SimpleImputer(strategy='median')),
        ('sc', StandardScaler())
    ]), num_cols),
    ('cat', Pipeline([
        ('imp', SimpleImputer(strategy='most_frequent')),
        ('ohe', OneHotEncoder(handle_unknown='ignore'))
    ]), cat_cols)
])

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42)

3. Huấn luyện mô hình

Gắn bộ tiền xử lý vào pipeline, sau đó huấn luyện:

from tensorflow.keras import callbacks

X_train_proc = preproc.fit_transform(X_train)
X_test_proc  = preproc.transform(X_test)

model = build_dist_network(X_train_proc.shape[1])
mu_out, sigma_out = model.output
model.add_loss(nll_normal(y_train, mu_out, sigma_out))
model.compile(optimizer='adam')

early = callbacks.EarlyStopping(patience=10, restore_best_weights=True)
model.fit(X_train_proc, y_train,
          validation_split=0.15,
          epochs=200,
          batch_size=256,
          callbacks=[early])

4. Đánh giá và trực quan hóa

Sau khi huấn luyện, ta thu được phân phối N(μ(x), σ(x)) cho mỗi mẫu. Độ lỗi trung bình có thể được tính bằng CRPS (Continuous Ranked Probability Score) hoặc chỉ đơn giản là RMSE của giá trị kỳ vọng:

from scipy.stats import norm
import numpy as np
import matplotlib.pyplot as plt

mu_pred, sigma_pred = model.predict(X_test_proc)
rmse = np.sqrt(np.mean((mu_pred.ravel() - y_test)**2))
print('RMSE:', rmse)

# Vẽ 90% PI (prediction interval)
lower = norm.ppf(0.05, loc=mu_pred, scale=sigma_pred)
upper = norm.ppf(0.95, loc=mu_pred, scale=sigma_pred)

plt.scatter(y_test, mu_pred, alpha=0.6)
plt.plot([y_test.min(), y_test.max()],
         [y_test.min(), y_test.max()], 'r--')
plt.fill_between(y_test, lower, upper, color='gray', alpha=0.2)
plt.xlabel('Giá trị thực')
plt.ylabel('Giá trị dự đoán')
plt.title('Khoảng tin cậy 90%')
plt.show()

5. Triển khai nhanh với thư viện dcdreg

Thư viện đóng gói dcdreg đã bao gồm:

  • trainer.py – lớp huấn luyện tự động.
  • networks.py – các kiến trúc mạng phổ biến (Normal, Laplace, Mixture Density).
  • metrics.py – CRPS, NLL, Pinball loss.
  • examples/ – notebook demo với dữ liệu thật.

Cài đặt chỉ với một lệnh:

pip install dcdreg

Sử dụng:

from dcdreg import DistRegressor

reg = DistRegressor(dist='normal', hidden=[128,64], epochs=150)
reg.fit(X_train, y_train)
mu, sigma = reg.predict(X_test, return_std=True)

6. Lưu ý khi áp dụng

  • Chọn họ phân phối: Normal phù hợp dữ liệu có nhiễm đối xứng; Skew-Normal hoặc Sinh-Arcsinh hỗ trợ đuôi bất đối xứng; Gaussian Mixture bắt nhiều chế độ.
  • Kiểm soát overfitting: dùng dropout, early-stopping, hoặc regularization trên tham số σ.
  • Tối ưu hóa siêu tham số: thử optuna hoặc keras-tuner để tìm hidden units, learning rate tốt nhất.

Với khả năng cung cấp toàn bộ phân phối đầu ra, DCDR giúp ra quyết định linh hoạt dựa trên ngưỡng rủi ro chấp nhận được thay vì chỉ dựa vào một giá trị trung bình.

Thẻ: deep-learning probability-regression neural-networks tensorflow uncertainty-quantification

Đăng vào ngày 22 tháng 8 lúc 00:33