Files
2026_DesignAI/officefile/md/supplements/01-foundations/01.3-probability-and-uncertainty.md
T
pengxiao a90f7adfa1 refactor(officefile): 按 md/latex/word 三层结构重组文档目录
将 Markdown 源文件移入 md/,LaTeX 工作目录保留在 latex/,
Word 导出移入 word/;删除临时脚本、调试截图和空 stub。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 14:25:21 +08:00

678 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 01.3 概率与不确定性
## 核心问题
> 空间分析中的不确定性从何而来?
> AI系统如何表示和处理不确定性?
> 如何在不确定性下做出稳健的决策?
---
## 概念讲解
### 不确定性的来源
在空间分析和AI系统中,不确定性无处不在:
```
空间分析中的不确定性来源
┌─────────────────────────────────────────────────────────────┐
│ │
│ 1. 数据不确定性 │
│ - 测量误差 │
│ - 空间采样不完整 │
│ - 分类错误 │
│ - 时间延迟 │
│ │
│ 2. 参数不确定性 │
│ - 阻力权重不确定 │
│ - 阈值选择主观 │
│ - 模型参数拟合误差 │
│ │
│ 3. 结构不确定性 │
│ - 模型选择 │
│ - 变量关系假设 │
│ - 尺度效应 │
│ │
│ 4. 语义不确定性 │
│ - 概念模糊("生态质量"是什么?) │
│ - 分类边界不清 │
│ - 专家意见分歧 │
│ │
└─────────────────────────────────────────────────────────────┘
```
### 不确定性的类型
| 类型 | 说明 | 例子 |
|-----|------|------|
| **偶然不确定性** (Aleatoric) | 系统固有的随机性,无法通过更多数据消除 | 降雨量的随机波动 |
| **认知不确定性** (Epistemic) | 知识不足导致的不确定性,可通过更多数据减少 | 未调查区域的物种分布 |
| **模糊性** (Ambiguity) | 概念或分类的不明确 | "高生态价值"的定义 |
| **冲突** (Conflict) | 不同信息源的不一致 | 两个专家给出相反意见 |
### AI如何处理不确定性
**传统GIS vs 概率AI**
```
传统GIS: 确定性输出
输入 → [处理] → 单一结果
例如:这个区域是/不是生态源地
概率AI: 概率输出
输入 → [处理] → (结果, 置信度)
例如:这个区域是生态源地的概率是 0.78 ± 0.12
```
**置信度的表示**
```python
# 方式1: 点估计 + 置信区间
estimate = 0.75
confidence_interval = (0.65, 0.85)
# 方式2: 概率分布
from scipy.stats import beta
distribution = beta(a=8, b=3) # 基于共8次成功,3次失败
# 方式3: 分类概率
class_probabilities = {
"high_suitability": 0.65,
"medium_suitability": 0.25,
"low_suitability": 0.10
}
# 方式4: 模糊隶属度
fuzzy_membership = {
"is_source": 0.72,
"is_not_source": 0.28
}
```
---
## 设计原理
### 不确定性传播
当多个步骤串联时,不确定性会累积:
```python
"""
不确定性传播示例
"""
import numpy as np
from scipy.stats import norm
class UncertainValue:
"""带不确定性的值"""
def __init__(self, mean, std):
self.mean = mean
self.std = std
def __add__(self, other):
"""加法:方差相加"""
return UncertainValue(
self.mean + other.mean,
np.sqrt(self.std**2 + other.std**2)
)
def __mul__(self, scalar):
"""乘以标量:标准差也乘"""
return UncertainValue(
self.mean * scalar,
self.std * abs(scalar)
)
def __repr__(self):
return f"{self.mean:.2f} ± {self.std:.2f}"
# 示例:源地适宜性评估中的不确定性传播
def assess_suitability_with_uncertainty():
"""
每个指标都有测量不确定性,
最终的适宜性评分会累积这些不确定性
"""
# 各项指标(均值 ± 标准差)
vegetation_quality = UncertainValue(0.75, 0.10)
connectivity = UncertainValue(0.60, 0.15)
distance_to_threat = UncertainValue(0.80, 0.08)
# 加权组合(权重也有不确定性)
weights = {
"vegetation": 0.4,
"connectivity": 0.3,
"distance": 0.3
}
# 计算总分(简化传播)
total = (vegetation_quality * weights["vegetation"] +
connectivity * weights["connectivity"] +
distance_to_threat * weights["distance"])
print("各指标不确定性:")
print(f" 植被质量: {vegetation_quality}")
print(f" 连通性: {connectivity}")
print(f" 威胁距离: {distance_to_threat}")
print(f"\n总分: {total}")
print(f" 置信区间95%: [{total.mean - 1.96*total.std:.2f}, "
f"{total.mean + 1.96*total.std:.2f}]")
return total
if __name__ == "__main__":
assess_suitability_with_uncertainty()
```
### 敏感性分析
了解哪些参数对结果影响最大:
```python
"""
敏感性分析:识别关键参数
"""
import numpy as np
from typing import Dict, List, Tuple
def sensitivity_analysis(model_fn, param_ranges: Dict[str, Tuple[float, float]],
n_samples=1000) -> Dict[str, float]:
"""
使用蒙特卡洛方法进行敏感性分析
Args:
model_fn: 模型函数,接受参数字典,返回结果
param_ranges: 参数范围 {param_name: (min, max)}
n_samples: 采样次数
Returns:
各参数的敏感性系数
"""
results = {param: [] for param in param_ranges}
model_outputs = []
# 蒙特卡洛采样
for _ in range(n_samples):
# 随机采样参数
sample = {k: np.random.uniform(v[0], v[1])
for k, v in param_ranges.items()}
# 记录参数值
for param, value in sample.items():
results[param].append(value)
# 计算模型输出
output = model_fn(sample)
model_outputs.append(output)
# 计算相关性作为敏感性指标
sensitivities = {}
for param in param_ranges:
correlation = np.corrcoef(results[param], model_outputs)[0, 1]
sensitivities[param] = abs(correlation)
return sensitivities
# 示例:生态阻力面构建的敏感性分析
def resistance_model(params):
"""简化的阻力面模型"""
# 参数:各土地类型的阻力权重
forest_weight = params["forest"]
grass_weight = params["grass"]
urban_weight = params["urban"]
# 简化:计算平均阻力
# 实际应用中会是空间计算
landscape_composition = {
"forest": 0.4,
"grass": 0.3,
"urban": 0.3
}
total_resistance = (
forest_weight * landscape_composition["forest"] +
grass_weight * landscape_composition["grass"] +
urban_weight * landscape_composition["urban"]
)
return total_resistance
def run_sensitivity_example():
"""运行敏感性分析示例"""
print("=== 阻力面参数敏感性分析 ===\n")
# 定义参数范围
param_ranges = {
"forest": (1, 10),
"grass": (10, 50),
"urban": (50, 200)
}
# 运行敏感性分析
sensitivities = sensitivity_analysis(
resistance_model,
param_ranges,
n_samples=5000
)
# 排序并输出
sorted_sens = sorted(sensitivities.items(),
key=lambda x: x[1], reverse=True)
print("参数敏感性排序:")
for param, sensitivity in sorted_sens:
bar = "" * int(sensitivity * 30)
print(f" {param}: {sensitivity:.3f} {bar}")
print("\n解释:")
print(f" 最敏感的参数是 {sorted_sens[0][0]}")
print(f" 应当优先精确确定该参数的值")
if __name__ == "__main__":
run_sensitivity_example()
```
### 鲁棒决策
当不确定性无法消除时,做鲁棒的决策:
```python
"""
鲁棒决策:在不确定性下的稳健决策
"""
from typing import List, Callable
import numpy as np
def robust_decision_scenarios():
"""
鲁棒决策的几种策略
"""
# 策略1: 最大最小 (Maximin) - 最坏情况最优
def maximin(payoff_matrix):
"""
选择在最坏情况下表现最好的选项
payoff_matrix: 选项 × 场景 的收益矩阵
"""
worst_case_outcomes = payoff_matrix.min(axis=1)
best_option = worst_case_outcomes.argmax()
return best_option, worst_case_outcomes
# 策略2: 最大平均 (Maximum Expected Value)
def max_expected(payoff_matrix, probabilities=None):
"""选择期望收益最大的选项"""
if probabilities is None:
probabilities = np.ones(payoff_matrix.shape[1]) / payoff_matrix.shape[1]
expected_values = payoff_matrix @ probabilities
best_option = expected_values.argmax()
return best_option, expected_values
# 策略3: 最小后悔 (Minimax Regret)
def minimax_regret(payoff_matrix):
"""选择最小化最大后悔的选项"""
# 每个场景的最佳收益
best_per_scenario = payoff_matrix.max(axis=0)
# 后悔矩阵:每个选项在每个场景与最佳的差距
regret_matrix = best_per_scenario - payoff_matrix
# 每个选项的最大后悔
max_regret = regret_matrix.max(axis=1)
# 选择最大后悔最小的选项
best_option = max_regret.argmin()
return best_option, max_regret
# 示例:生态廊道选址决策
# 选项:3个候选廊道路线
# 场景:不同的未来土地变化情景
payoff_matrix = np.array([
# 情景1 情景2 情景3 情景4
[80, 60, 40, 70], # 选项A:穿过森林
[50, 90, 70, 50], # 选项B:沿河流
[60, 70, 90, 60], # 选项C:绕行城市边缘
])
print("=== 生态廊道选址:鲁棒决策分析 ===\n")
print("收益矩阵(廊道质量评分):")
print(" 情景1 情景2 情景3 情景4")
for i, row in enumerate(payoff_matrix, ord('A')):
print(f"选项{i}: {row}")
print("\n--- 策略1: 最大最小 (最坏情况最优) ---")
option, worst = maximin(payoff_matrix)
print(f"推荐: 选项{chr(ord('A') + option)}")
print(f"各选项最坏情况: {worst}")
print(" 原理: 选择在最坏情景下表现最好的")
print("\n--- 策略2: 最大期望 (平均收益最大) ---")
option, expected = max_expected(payoff_matrix)
print(f"推荐: 选项{chr(ord('A') + option)}")
print(f"各选项期望收益: {expected}")
print(" 原理: 选择平均表现最好的")
print("\n--- 策略3: 最小最大后悔 ---")
option, regret = minimax_regret(payoff_matrix)
print(f"推荐: 选项{chr(ord('A') + option)}")
print(f"各选项最大后悔: {regret}")
print(" 原理: 选择让'选错'的后悔最小的")
return payoff_matrix
if __name__ == "__main__":
robust_decision_scenarios()
```
---
## 代码示例
### 概率源地识别
```python
"""
带不确定性的生态源地识别
"""
import numpy as np
from scipy.stats import beta
from typing import Dict, List, Tuple
class ProbabilisticSource:
"""概率源地:带置信度的源地"""
def __init__(self, source_id: int, geometry,
probability: float, confidence: float):
self.id = source_id
self.geometry = geometry
self.probability = probability # 是源地的概率
self.confidence = confidence # 概率估计的置信度
def __repr__(self):
return (f"Source({self.id}, P={self.probability:.2f}±{self.confidence:.2f})")
class ProbabilisticSourceIdentifier:
"""概率源地识别器"""
def __init__(self, threshold=0.5):
self.threshold = threshold
def identify(self, landscape_data) -> List[ProbabilisticSource]:
"""
识别源地,返回概率源地
返回的不是"是/否"的判断,而是"是源地的概率"
"""
sources = []
# 模拟:对每个斑块计算是源地的概率
for i, patch in enumerate(landscape_data):
# 基于多个指标计算概率
probability = self._calculate_source_probability(patch)
# 估计置信度(基于数据质量)
confidence = self._estimate_confidence(patch)
if probability >= self.threshold:
source = ProbabilisticSource(
source_id=i,
geometry=patch['geometry'],
probability=probability,
confidence=confidence
)
sources.append(source)
return sources
def _calculate_source_probability(self, patch) -> float:
"""计算斑块是源地的概率"""
# 使用贝叶斯推理
# P(是源地|数据) ∝ P(数据|是源地) × P(是源地)
# 各指标的似然
area_likelihood = self._area_likelihood(patch['area'])
veg_likelihood = self._vegetation_likelihood(patch['vegetation'])
shape_likelihood = self._shape_likelihood(patch['shape_index'])
# 先验概率
prior = 0.3 # 假设30%的斑块可能是源地
# 后验概率(简化)
probability = (area_likelihood * veg_likelihood *
shape_likelihood * prior)
probability = min(probability, 1.0) # 限制在[0,1]
return probability
def _area_likelihood(self, area: float) -> float:
"""面积似然:大面积更像源地"""
if area > 1000:
return 1.0
elif area > 500:
return 0.7
else:
return 0.3
def _vegetation_likelihood(self, veg_quality: float) -> float:
"""植被质量似然"""
return veg_quality # 假设已归一化到[0,1]
def _shape_likelihood(self, shape_index: float) -> float:
"""形状指数似然:紧凑形状更好"""
return 1.0 - min(abs(shape_index - 1.0), 0.5)
def _estimate_confidence(self, patch) -> float:
"""估计概率的置信度"""
# 基于数据质量、分辨率等因素
data_quality = patch.get('data_quality', 0.8)
resolution_factor = patch.get('resolution', 30) / 30 # 归一化
return data_quality * min(resolution_factor, 1.0)
def uncertainty_propagation_example():
"""不确定性传播示例"""
print("=== 不确定性传播示例 ===\n")
# 创建一些模拟斑块
patches = [
{'id': 1, 'area': 1200, 'vegetation': 0.85, 'shape_index': 1.2,
'geometry': 'POLYGON(...)', 'data_quality': 0.9},
{'id': 2, 'area': 800, 'vegetation': 0.75, 'shape_index': 1.5,
'geometry': 'POLYGON(...)', 'data_quality': 0.7},
{'id': 3, 'area': 400, 'vegetation': 0.65, 'shape_index': 1.8,
'geometry': 'POLYGON(...)', 'data_quality': 0.6},
]
identifier = ProbabilisticSourceIdentifier(threshold=0.4)
sources = identifier.identify(patches)
print("识别到的概率源地:")
for source in sources:
print(f" {source}")
# 计算整体不确定性
if sources:
avg_prob = np.mean([s.probability for s in sources])
avg_conf = np.mean([s.confidence for s in sources])
print(f"\n总体置信度: {avg_conf:.2f}")
print(f"平均源地概率: {avg_prob:.2f}")
# 置信区间
margin_of_error = (1 - avg_conf) * 0.2 # 简化计算
print(f"源地数量估计: {len(sources)} ± {margin_of_error * len(sources):.1f}")
if __name__ == "__main__":
uncertainty_propagation_example()
```
---
## 案例分析
### ENAgent中的不确定性处理
在ENAgent项目中,不确定性处理体现在:
**1. 源地识别的不确定性**
```python
class ENAgentSourceIdentifier:
"""ENAgent的源地识别模块"""
def identify_with_uncertainty(self, landcover, species_params):
"""
识别源地,同时估计不确定性
Returns:
sources: 源地列表
uncertainty_map: 不确定性空间分布
"""
sources = []
uncertainty_map = np.zeros_like(landcover)
# 对每个候选斑块
for patch in self._candidate_patches(landcover):
# 计算适宜性(考虑物种参数)
suitability = self._calculate_suitability(patch, species_params)
# 估计不确定性(来自多个来源)
uncertainty = self._estimate_uncertainty(
patch,
data_quality=landcover.metadata['quality'],
species_uncertainty=species_params['uncertainty']
)
# 记录
if suitability > self.threshold:
sources.append({
'geometry': patch,
'suitability': suitability,
'uncertainty': uncertainty
})
# 更新不确定性地图
self._add_to_uncertainty_map(uncertainty_map, patch, uncertainty)
return sources, uncertainty_map
def _estimate_uncertainty(self, patch, data_quality, species_uncertainty):
"""
估计源地识别的不确定性
来源:
1. 数据质量 (data_quality)
2. 物种参数的不确定性 (species_uncertainty)
3. 分类误差 (classification_error)
4. 边界效应 (edge_effect)
"""
# 组合各种不确定性源
uncertainty = np.sqrt(
(1 - data_quality)**2 +
species_uncertainty**2 +
0.1**2 + # 分类误差
self._edge_uncertainty(patch)**2
)
return min(uncertainty, 1.0)
```
**2. 阻力面的敏感性分析**
```python
class ResistanceSurfaceSensitivity:
"""阻力面敏感性分析"""
def analyze(self, base_weights, variation_ranges, n_simulations=1000):
"""
分析阻力面权重对结果的敏感性
Args:
base_weights: 基础权重 {land_type: weight}
variation_ranges: 权重变化范围 {land_type: (min, max)}
n_simulations: 蒙特卡洛模拟次数
Returns:
sensitivity_results: 敏感性分析结果
"""
results = []
for _ in range(n_simulations):
# 随机采样权重
sample_weights = {}
for land_type, (min_w, max_w) in variation_ranges.items():
sample_weights[land_type] = np.random.uniform(min_w, max_w)
# 计算对应的阻力面
resistance = self._compute_resistance(sample_weights)
# 评估结果(例如:平均连通性)
connectivity = self._assess_connectivity(resistance)
results.append({
'weights': sample_weights,
'connectivity': connectivity
})
# 分析敏感性
sensitivity = self._compute_sensitivity(results, base_weights)
return sensitivity
def _compute_sensitivity(self, results, base_weights):
"""计算各土地类型的敏感性"""
# 计算每个权重变化与连通性变化的相关性
sensitivities = {}
for land_type in base_weights:
weight_values = [r['weights'][land_type] for r in results]
connectivity_values = [r['connectivity'] for r in results]
correlation = np.corrcoef(weight_values, connectivity_values)[0, 1]
sensitivities[land_type] = abs(correlation)
return sensitivities
```
---
## 反思与延伸
### 思考问题
1. **不确定性识别**:在你的项目中,不确定性来自哪些方面?哪些是可减少的,哪些是固有的?
2. **表示选择**:你应该用标准差、置信区间,还是概率分布?各有什么优劣?
3. **决策权衡**:当不确定性很高时,你应该继续分析还是寻求更多数据?
4. **沟通问题**:如何向非专家解释不确定性?
### 实践练习
1. **不确定性审计**:对一个分析流程,识别所有不确定性来源并分类
2. **敏感性分析**:对你熟悉的空间模型进行敏感性分析
3. **鲁棒决策**:为你的项目设计一个鲁棒决策框架
### 延伸阅读
- **"Uncertainty Quantification in Predictive Modeling"** - 不确定性量化的理论基础
- **"Flaw of Averages"** (Sam Savage) - 为什么平均值会误导
- **空间数据质量标准** - 空间不确定性的行业实践
---
## 关键要点
1. **不确定性在空间分析中普遍存在**,有多个来源
2. **偶然不确定性无法消除**,认知不确定性可以通过更多数据减少
3. **不确定性会传播**,多步骤分析需要考虑累积效应
4. **敏感性分析识别关键参数**,优先减少高敏感参数的不确定性
5. **鲁棒决策在不确定性下做稳健选择**,而非追求最优