不确定性估计:量化模型信心
--- title: "不确定性估计:量化模型信心" description: "估计LLM预测的不确定性,为决策提供置信度信息" tags: ["不确定性估计", "置信度", "贝叶斯深度学习", "LLM", "可靠性"] category: "llm" icon: "📊"
不确定性估计:量化模型信心
不确定性概述
不确定性估计是量化模型预测可信度的技术,帮助判断模型输出的可靠性。
不确定性类型
1. 认知不确定性
import numpy as np
import torch
from typing import List, Dict
class EpistemicUncertaintyEstimator:
"""认知不确定性估计"""
def __init__(self, model, tokenizer, n_samples: int = 10):
self.model = model
self.tokenizer = tokenizer
self.n_samples = n_samples
def estimate(self, text: str) -> Dict:
"""估计认知不确定性"""
inputs = self.tokenizer(text, return_tensors="pt")
# MC Dropout采样
predictions = []
self.model.train() # 启用dropout
for _ in range(self.n_samples):
with torch.no_grad():
outputs = self.model(**inputs)
logits = outputs.logits
probs = torch.softmax(logits, dim=-1)
predictions.append(probs.numpy())
self.model.eval()
predictions = np.array(predictions)
# 计算均值预测
mean_prediction = predictions.mean(axis=0)
# 认知不确定性 = 预测方差
epistemic_uncertainty = np.var(predictions, axis=0).mean()
return {
"epistemic_uncertainty": float(epistemic_uncertainty),
"mean_prediction": mean_prediction.tolist(),
"n_samples": self.n_samples
}
def estimate_batch(self, texts: List[str]) -> List[Dict]:
"""批量估计"""
return [self.estimate(text) for text in texts]
2. 偶然不确定性
class AleatoricUncertaintyEstimator:
"""偶然不确定性估计"""
def __init__(self, model, tokenizer):
self.model = model
self.tokenizer = tokenizer
def estimate(self, text: str) -> Dict:
"""估计偶然不确定性"""
inputs = self.tokenizer(text, return_tensors="pt")
with torch.no_grad():
outputs = self.model(**inputs)
logits = outputs.logits
# 计算概率
probs = torch.softmax(logits, dim=-1)
# 偶然不确定性 = 预测熵
entropy = -torch.sum(probs * torch.log(probs + 1e-10), dim=-1)
# 预测置信度
confidence = probs.max(dim=-1).values
return {
"aleatoric_uncertainty": float(entropy.mean()),
"confidence": float(confidence.mean()),
"entropy": float(entropy.mean()),
"probabilities": probs.numpy().tolist()
}
3. 集成不确定性
class EnsembleUncertaintyEstimator:
"""集成不确定性估计"""
def __init__(self, models: List, tokenizer):
self.models = models
self.tokenizer = tokenizer
def estimate(self, text: str) -> Dict:
"""估计集成不确定性"""
inputs = self.tokenizer(text, return_tensors="pt")
all_predictions = []
for model in self.models:
with torch.no_grad():
outputs = model(**inputs)
probs = torch.softmax(outputs.logits, dim=-1)
all_predictions.append(probs.numpy())
all_predictions = np.array(all_predictions)
# 模型间方差
model_variance = np.var(all_predictions, axis=0).mean()
# 平均预测
mean_prediction = all_predictions.mean(axis=0)
# 集成不确定性
ensemble_uncertainty = model_variance
return {
"ensemble_uncertainty": float(ensemble_uncertainty),
"mean_prediction": mean_prediction.tolist(),
"model_agreement": 1.0 - float(model_variance)
}
高级方法
1. 贝叶斯神经网络
class BayesianUncertaintyEstimator:
"""贝叶斯不确定性估计"""
def __init__(self, model, tokenizer, prior_variance: float = 1.0):
self.model = model
self.tokenizer = tokenizer
self.prior_variance = prior_variance
def variational_inference(self, text: str, n_samples: int = 10) -> Dict:
"""变分推断"""
inputs = self.tokenizer(text, return_tensors="pt")
predictions = []
for _ in range(n_samples):
# 添加参数噪声
noisy_model = self._add_noise_to_model()
with torch.no_grad():
outputs = noisy_model(**inputs)
probs = torch.softmax(outputs.logits, dim=-1)
predictions.append(probs.numpy())
predictions = np.array(predictions)
# 计算不确定性
mean_pred = predictions.mean(axis=0)
variance = predictions.var(axis=0)
# KL散度近似
kl_divergence = 0.5 * np.sum(variance / self.prior_variance)
return {
"predictive_uncertainty": float(variance.mean()),
"kl_divergence": float(kl_divergence),
"mean_prediction": mean_pred.tolist()
}
def _add_noise_to_model(self):
"""为模型参数添加噪声"""
import copy
noisy_model = copy.deepcopy(self.model)
for param in noisy_model.parameters():
noise = torch.randn_like(param) * 0.01
param.data += noise
return noisy_model
2. 深度集成
class DeepEnsembleUncertainty:
"""深度集成不确定性"""
def __init__(self, n_models: int = 5):
self.n_models = n_models
self.models = []
def train_ensemble(self, train_data, val_data, **kwargs):
"""训练集成模型"""
for i in range(self.n_models):
# 初始化不同随机种子的模型
torch.manual_seed(i * 42)
model = self._create_model()
# 训练
self._train_model(model, train_data, val_data, **kwargs)
self.models.append(model)
def predict_with_uncertainty(self, text: str, tokenizer) -> Dict:
"""带不确定性的预测"""
inputs = tokenizer(text, return_tensors="pt")
all_logits = []
for model in self.models:
with torch.no_grad():
outputs = model(**inputs)
all_logits.append(outputs.logits.numpy())
all_logits = np.array(all_logits)
all_probs = np.exp(all_logits) / np.exp(all_logits).sum(axis=-1, keepdims=True)
# 集成预测
mean_probs = all_probs.mean(axis=0)
# 不确定性
uncertainty = {
"entropy": float(-np.sum(mean_probs * np.log(mean_probs + 1e-10))),
"variance": float(np.var(all_probs, axis=0).mean()),
"mutual_info": float(np.sum(mean_probs * np.log(mean_probs / all_probs.mean(axis=0) + 1e-10)))
}
return {
"prediction": mean_probs.tolist(),
"uncertainty": uncertainty,
"model_predictions": all_probs.tolist()
}
def _create_model(self):
"""创建模型"""
# 简化实现
return None
def _train_model(self, model, train_data, val_data, **kwargs):
"""训练模型"""
pass
可视化
import matplotlib.pyplot as plt
def plot_uncertainty_analysis(texts: List[str], uncertainty_results: List[Dict]):
"""绘制不确定性分析图"""
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 不确定性分布
uncertainties = [r["uncertainty"].get("entropy", 0) for r in uncertainty_results]
axes[0].hist(uncertainties, bins=20, edgecolor="black")
axes[0].set_xlabel("Uncertainty (Entropy)")
axes[0].set_ylabel("Count")
axes[0].set_title("Uncertainty Distribution")
# 不确定性 vs 文本长度
text_lengths = [len(t) for t in texts]
axes[1].scatter(text_lengths, uncertainties)
axes[1].set_xlabel("Text Length")
axes[1].set_ylabel("Uncertainty")
axes[1].set_title("Uncertainty vs Text Length")
plt.tight_layout()
plt.show()
实用工具
def predict_with_confidence(model, tokenizer, text: str, threshold: float = 0.8) -> Dict:
"""带置信度的预测"""
estimator = EpistemicUncertaintyEstimator(model, tokenizer)
uncertainty_result = estimator.estimate(text)
# 获取预测
inputs = tokenizer(text, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs)
prediction = torch.argmax(outputs.logits, dim=-1)
# 计算置信度
confidence = 1.0 - uncertainty_result["epistemic_uncertainty"]
return {
"prediction": prediction.item(),
"confidence": confidence,
"reliable": confidence > threshold,
"uncertainty": uncertainty_result
}
# 使用示例
# result = predict_with_confidence(model, tokenizer, "测试文本")
# if result["reliable"]:
# print(f"预测: {result['prediction']}, 置信度: {result['confidence']:.2f}")
# else:
# print("预测不可靠,建议人工审核")
最佳实践
- 多方法结合:结合认知和偶然不确定性
- 阈值设定:根据应用需求设定可靠性阈值
- 持续校准:定期校准不确定性估计
- 决策支持:使用不确定性辅助决策
总结
不确定性估计是提高LLM可靠性的重要技术。通过量化预测的不确定性,可以为决策提供更多信息,避免过度自信的错误预测。