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) và σ(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:
- Xử lý giá trị thiếu bằng
SimpleImputer. - Mã hóa biến phân loại bằng
OneHotEncoder. - Chuẩn hóa đặc trưng số với
StandardScaler. - 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ử
optunahoặckeras-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.