← 返回首页
🧠

不确定性估计:量化模型信心

📂 llm ⏱ 4 min 610 words

--- 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("预测不可靠,建议人工审核")

最佳实践

  1. 多方法结合:结合认知和偶然不确定性
  2. 阈值设定:根据应用需求设定可靠性阈值
  3. 持续校准:定期校准不确定性估计
  4. 决策支持:使用不确定性辅助决策

总结

不确定性估计是提高LLM可靠性的重要技术。通过量化预测的不确定性,可以为决策提供更多信息,避免过度自信的错误预测。