1. MAP估計基本原理
MAP(Maximum A Posteriori,最大后驗概率估計)是貝葉斯推斷中的重要概念,它的目標是:
給定觀測數據,找到使得后驗概率最大的參數值。
公式化表示:
[ θ MAP = arg ? max ? θ P ( θ ∣ x ) ] [ \theta_{\text{MAP}} = \arg\max_{\theta} P(\theta | x) ] [θMAP?=argθmax?P(θ∣x)]
其中:
- ( θ ) ( \theta ) (θ) 是我們要估計的參數,
- ( x ) ( x ) (x) 是觀測數據,
- ( P ( θ ∣ x ) ) ( P(\theta | x) ) (P(θ∣x)) 是參數在觀測數據下的后驗概率。
利用貝葉斯公式展開:
[ P ( θ ∣ x ) = P ( x ∣ θ ) P ( θ ) P ( x ) ] [ P(\theta | x) = \frac{P(x|\theta) P(\theta)}{P(x)} ] [P(θ∣x)=P(x)P(x∣θ)P(θ)?]
其中:
- ( P ( x ∣ θ ) ) ( P(x|\theta) ) (P(x∣θ)) 是似然(likelihood),
- ( P ( θ ) ) ( P(\theta) ) (P(θ)) 是先驗(prior),
- ( P ( x ) ) ( P(x) ) (P(x)) 是證據(evidence),與參數無關,可忽略在優化中。
所以 MAP 估計可以等價為最大化:
[ θ MAP = arg ? max ? θ P ( x ∣ θ ) P ( θ ) ] [ \theta_{\text{MAP}} = \arg\max_{\theta} P(x|\theta) P(\theta) ] [θMAP?=argθmax?P(x∣θ)P(θ)]
也可以取對數(為了數值穩定和方便求導):
[ θ MAP = arg ? max ? θ ( log ? P ( x ∣ θ ) + log ? P ( θ ) ) ] [ \theta_{\text{MAP}} = \arg\max_{\theta} \left( \log P(x|\theta) + \log P(\theta) \right) ] [θMAP?=argθmax?(logP(x∣θ)+logP(θ))]
總結:
- MLE(最大似然估計)只最大化 ( P ( x ∣ θ ) ) ( P(x|\theta) ) (P(x∣θ)),不考慮先驗。
- MAP 估計既考慮似然 ( P ( x ∣ θ ) ) ( P(x|\theta) ) (P(x∣θ)),又考慮先驗 ( P ( θ ) ) ( P(\theta) ) (P(θ))。
2. MAP推導示例 —— 估計正態分布均值
假設觀測數據集 ( x = { x 1 , x 2 , . . . , x N } ) ( x = \{x_1, x_2, ..., x_N\} ) (x={x1?,x2?,...,xN?}) 是從均值為 ( μ ) ( \mu ) (μ)、方差為已知 ( σ 2 ) ( \sigma^2 ) (σ2) 的正態分布中采樣得到的。
我們要用 MAP 估計 ( μ ) ( \mu ) (μ)。
- 似然函數(假設獨立同分布):
[ P ( x ∣ μ ) = ∏ i = 1 N 1 2 π σ 2 exp ? ( ? ( x i ? μ ) 2 2 σ 2 ) ] [ P(x|\mu) = \prod_{i=1}^N \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left( -\frac{(x_i-\mu)^2}{2\sigma^2} \right) ] [P(x∣μ)=i=1∏N?2πσ2?1?exp(?2σ2(xi??μ)2?)]
取對數似然:
[ log ? P ( x ∣ μ ) = ? N 2 log ? ( 2 π σ 2 ) ? 1 2 σ 2 ∑ i = 1 N ( x i ? μ ) 2 ] [ \log P(x|\mu) = -\frac{N}{2} \log(2\pi\sigma^2) - \frac{1}{2\sigma^2} \sum_{i=1}^N (x_i-\mu)^2 ] [logP(x∣μ)=?2N?log(2πσ2)?2σ21?i=1∑N?(xi??μ)2] - 假設先驗 ( μ ~ N ( μ 0 , σ 0 2 ) ) ( \mu \sim \mathcal{N}(\mu_0, \sigma_0^2) ) (μ~N(μ0?,σ02?)),即:
[ P ( μ ) = 1 2 π σ 0 2 exp ? ( ? ( μ ? μ 0 ) 2 2 σ 0 2 ) ] [ P(\mu) = \frac{1}{\sqrt{2\pi\sigma_0^2}} \exp\left( -\frac{(\mu-\mu_0)^2}{2\sigma_0^2} \right) ] [P(μ)=2πσ02??1?exp(?2σ02?(μ?μ0?)2?)]
取對數先驗:
[ log ? P ( μ ) = ? 1 2 log ? ( 2 π σ 0 2 ) ? ( μ ? μ 0 ) 2 2 σ 0 2 ] [ \log P(\mu) = -\frac{1}{2} \log(2\pi\sigma_0^2) - \frac{(\mu-\mu_0)^2}{2\sigma_0^2} ] [logP(μ)=?21?log(2πσ02?)?2σ02?(μ?μ0?)2?] - 總目標:
[ θ MAP = arg ? max ? μ ( log ? P ( x ∣ μ ) + log ? P ( μ ) ) ] [ \theta_{\text{MAP}} = \arg\max_{\mu} \left( \log P(x|\mu) + \log P(\mu) \right) ] [θMAP?=argμmax?(logP(x∣μ)+logP(μ))]
去掉無關常數后,最大化:
[ ? 1 2 σ 2 ∑ i = 1 N ( x i ? μ ) 2 ? 1 2 σ 0 2 ( μ ? μ 0 ) 2 ] [ -\frac{1}{2\sigma^2} \sum_{i=1}^N (x_i-\mu)^2 - \frac{1}{2\sigma_0^2} (\mu-\mu_0)^2 ] [?2σ21?i=1∑N?(xi??μ)2?2σ02?1?(μ?μ0?)2]
即最小化:
[ ∑ i = 1 N ( x i ? μ ) 2 + σ 2 σ 0 2 ( μ ? μ 0 ) 2 ] [ \sum_{i=1}^N (x_i-\mu)^2 + \frac{\sigma^2}{\sigma_0^2} (\mu-\mu_0)^2 ] [i=1∑N?(xi??μ)2+σ02?σ2?(μ?μ0?)2]
展開、對 ( μ ) ( \mu ) (μ) 求導并令導數為零,得到:
[ μ MAP = σ 0 2 ∑ i = 1 N x i + σ 2 μ 0 N σ 0 2 + σ 2 ] [ \mu_{\text{MAP}} = \frac{\sigma_0^2 \sum_{i=1}^N x_i + \sigma^2 \mu_0}{N\sigma_0^2 + \sigma^2} ] [μMAP?=Nσ02?+σ2σ02?∑i=1N?xi?+σ2μ0??]
直觀理解: - 當先驗方差 ( σ 0 2 ) ( \sigma_0^2 ) (σ02?) 很大時,先驗很弱,MAP 估計趨近于 MLE(樣本均值)。
- 當先驗方差小,先驗很強,結果更接近先驗均值 ( μ 0 ) ( \mu_0 ) (μ0?)。
3. MAP應用實例
常見的 MAP 應用領域包括:
- SLAM后端優化(g2o, GTSAM):地圖和軌跡估計通常是 MAP 問題。
- 機器學習(L2正則化):加了正則項的回歸可解釋為 MAP。
- 信號處理:濾波器設計中有 MAP估計噪聲。
- 計算機視覺:圖像配準、姿態估計等。
- NLP生成模型:文本生成時選概率最大的輸出。
4. C++代碼示例 —— 正態分布均值的MAP估計
下面給出簡單的 C++ 代碼示例:
#include <iostream>
#include <vector>
#include <numeric> // std::accumulate// 計算均值
double compute_mean(const std::vector<double>& data) {return std::accumulate(data.begin(), data.end(), 0.0) / data.size();
}// MAP估計
double map_estimate(const std::vector<double>& data, double sigma2, double mu0, double sigma0_2) {double N = static_cast<double>(data.size());double sum_x = std::accumulate(data.begin(), data.end(), 0.0);double numerator = sigma0_2 * sum_x + sigma2 * mu0;double denominator = N * sigma0_2 + sigma2;return numerator / denominator;
}int main() {// 觀測數據std::vector<double> x = {1.2, 1.8, 2.0, 1.5, 2.2};// 已知觀測噪聲方差double sigma2 = 0.1;// 先驗均值和方差double mu0 = 2.0;double sigma0_2 = 0.5;double mu_map = map_estimate(x, sigma2, mu0, sigma0_2);std::cout << "MAP估計的均值為: " << mu_map << std::endl;return 0;
}
輸出示例:
MAP估計的均值為: 1.87321
總結一句話
MAP估計 = 在最大似然上加上先驗知識,讓推斷更加魯棒。
5. MAP下擬合直線示例:推導
假設我們有 ( N ) ( N ) (N) 個觀測點 ( ( x i , y i ) ) ( (x_i, y_i) ) ((xi?,yi?)),我們想擬合一條直線:
[ y = a x + b ] [ y = ax + b ] [y=ax+b]
其中參數 ( a , b ) ( a, b ) (a,b) 是我們要估計的。
- 似然模型(假設觀測有高斯噪聲):
[ y i = a x i + b + ? i , ? i ~ N ( 0 , σ 2 ) ] [ y_i = a x_i + b + \epsilon_i, \quad \epsilon_i \sim \mathcal{N}(0, \sigma^2) ] [yi?=axi?+b+?i?,?i?~N(0,σ2)]
所以似然為:
[ P ( y i ∣ x i , a , b ) ∝ exp ? ( ? ( y i ? ( a x i + b ) ) 2 2 σ 2 ) ] [ P(y_i|x_i, a, b) \propto \exp\left( -\frac{(y_i - (a x_i + b))^2}{2\sigma^2} \right) ] [P(yi?∣xi?,a,b)∝exp(?2σ2(yi??(axi?+b))2?)] - 先驗模型:
假設我們對 ( a ) ( a ) (a) 和 ( b ) ( b ) (b) 有正則化先驗(例如,偏好較小的斜率和截距):
[ P ( a , b ) ∝ exp ? ( ? λ 2 ( a 2 + b 2 ) ) ] [ P(a, b) \propto \exp\left( -\frac{\lambda}{2} (a^2 + b^2) \right) ] [P(a,b)∝exp(?2λ?(a2+b2))] - MAP目標函數(取負對數,變成最小化問題):
[ Cost ( a , b ) = ∑ i = 1 N ( y i ? ( a x i + b ) ) 2 + λ ( a 2 + b 2 ) ] [ \text{Cost}(a, b) = \sum_{i=1}^N (y_i - (a x_i + b))^2 + \lambda (a^2 + b^2) ] [Cost(a,b)=i=1∑N?(yi??(axi?+b))2+λ(a2+b2)]
就是常規的最小二乘項 + 正則項!
這個目標就是典型的帶L2正則化的線性回歸(也叫Ridge Regression)。
6. 用Eigen實現完整C++版
下面給你完整示例,包括矩陣推導、解法、繪圖。
基于Eigen的 C++代碼示例
#include <iostream>
#include <vector>
#include <Eigen/Dense>// 用于生成一些模擬數據
void generate_data(std::vector<double>& xs, std::vector<double>& ys, double true_a, double true_b, double noise_std, int N) {std::default_random_engine generator;std::normal_distribution<double> noise(0.0, noise_std);xs.resize(N);ys.resize(N);for (int i = 0; i < N; ++i) {xs[i] = i * 0.1; // 讓x均勻增長ys[i] = true_a * xs[i] + true_b + noise(generator);}
}// MAP線性回歸:最小化 (Ax - y)^2 + lambda * ||x||^2
void map_fit(const std::vector<double>& xs, const std::vector<double>& ys, double lambda, double& est_a, double& est_b) {int N = xs.size();Eigen::MatrixXd A(N, 2);Eigen::VectorXd y(N);for (int i = 0; i < N; ++i) {A(i, 0) = xs[i];A(i, 1) = 1.0;y(i) = ys[i];}// 正規方程帶正則項:(A^T A + lambda * I) x = A^T yEigen::Matrix2d ATA = A.transpose() * A;Eigen::Vector2d ATy = A.transpose() * y;ATA += lambda * Eigen::Matrix2d::Identity(); // 加上正則化Eigen::Vector2d x = ATA.ldlt().solve(ATy);est_a = x(0);est_b = x(1);
}int main() {std::vector<double> xs, ys;double true_a = 2.0, true_b = 1.0;generate_data(xs, ys, true_a, true_b, 0.1, 50);double est_a = 0.0, est_b = 0.0;double lambda = 1.0; // 正則化強度map_fit(xs, ys, lambda, est_a, est_b);std::cout << "真實值: a = " << true_a << ", b = " << true_b << std::endl;std::cout << "MAP估計: a = " << est_a << ", b = " << est_b << std::endl;return 0;
}
7. 總結一下
對象 | 含義 |
---|---|
似然 | 擬合觀測數據的準確性 |
先驗 | 防止參數過大(正則化) |
MAP估計 | 似然 × 先驗的最大化 |
公式 | 最小化誤差項 + 正則項 |
直觀理解:
- 你希望擬合數據,同時又不希望參數太大(比如防止過擬合)。
- 正則化參數 ( λ ) ( \lambda ) (λ) 越大,先驗越強,越傾向于把 ( a , b ) ( a, b ) (a,b) 拉向 0。