樸素貝葉斯分類器
基本概念
樸素貝葉斯分類器計算一個樣本屬於某一類的概率(後驗概率),進而比較概率大小來決定樣本的分類結果。分類器需要資料集作為已知樣本集,還需要這些樣本的分類結果,最後對新給出的樣本集進行分類。
具體來說,假設已經得到樣本集 \(D=\{x_1,\cdots,x_n\}\) ,每一個 \(x_i\) 都有 \(k\) 個特徵,分別記為 \(a_i\) , 可能類別為 \(Y=\{y_1,\cdots,y_m\}\) ,根據每個 \(x_i\) 的特徵,它會被分類到某一個 \(y_j\) 類中。
現在我們已經知道 \(D\) 分類的結果,分類器需要根據已經有的這些資訊對新的樣本 \(x=(a_1,\cdots,a_k)\)
離散分類
需要計算已知 \(x\) 時分類到 \(y_j\) 的概率 \(\Pr(y_j|x)\) ,然後比較其中最大的概率,選擇對應的 \(y_j\) 作為分類結果。根據貝葉斯公式
\[\Pr(y_j|x) = \dfrac{\Pr(x|y_j)\Pr(y_j)}{\Pr(x)} \]與先前類似,其中 \(\Pr(x)\) 可以忽略,我們用 \(D\) 中分類到 \(y_j\) 的元素佔 \(D\) 所有元素的比例來估計 \(y_j\) 出現的概率 \(\Pr(y_j)\)
於是重點就在於計算 \(\Pr(x|y_j)\) ,我們知道 \(x\) 有一些特徵,那麼
\[\Pr(x|y_j) = \prod_{i=1}^k\Pr(a_i|y_j) \]也就是 \(x\) 的每一個特徵都出現在 \(y_j\) 中的概率,其中 \(\Pr(a_i|y_j)\) 是 \(a_i\) 出現在 \(y_j\) 分類中的比例。最終就得到
\[\Pr(y_j|x) \varpropto \Pr(y_j)\prod_{i=1}^k\Pr(a_i|y_j) \]計算右邊的最大值,然後選擇對應的 \(y_j\) 作為分類結果即可。
以下面離散資料集的程式碼為例,首先給出已知資料
fea_dis = [[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3]',[1,2,2,1,1,1,2,2,3,3,3,2,2,3,3]']; % 已經分類的資料集
gnd_dis = [-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1]'; % 對應的分類結果集
需要對 \((a_1,a_2)=(2,1)\) 進行分類,可以看出有 \(-1,1\) 兩類,記為 \(y_1,y_2\)
target_dis = [2,1];
因此需要計算每個分類中不同特徵出現的概率
\[\begin{matrix} \Pr(a_1| y_1) & \Pr(a_2| y_1)\\ \Pr(a_1| y_2) & \Pr(a_2| y_2) \end{matrix} \]用一個矩陣來存放上面的概率
% 記錄概率 P(a_i|y_j)
P = zeros(2,2);
% 統計 1 和 -1 兩類分別有多少元素
p_count1 = sum(gnd_dis == 1);
p_count2 = sum(gnd_dis == -1);
% x = (a1,a2) = (2,1)
% 統計 1 類中 2 和 1 出現的概率
P(1,1) = sum(fea_dis(:,1) == 2 & gnd_dis == 1) / p_count1;
P(1,2) = sum(fea_dis(:,2) == 1 & gnd_dis == 1) / p_count1;
% 統計 -1 類中 2 和 1 出現的概率
P(2,1) = sum(fea_dis(:,1) == 2 & gnd_dis == -1) / p_count2;
P(2,2) = sum(fea_dis(:,2) == 1 & gnd_dis == -1) / p_count2;
然後計算出似然估計
\[\Pr(x|y_1) = \Pr(a_1| y_1) \Pr(a_2| y_1)\cdot \Pr(y_1)\\ \Pr(x|y_2) = \Pr(a_1| y_2) \Pr(a_2| y_2)\cdot \Pr(y_2)\\ \]p1 = P(1,1) * P(1,2) * p_count1 / (p_count1 + p_count2);
p2 = P(2,1) * P(2,2) * p_count2 / (p_count1 + p_count2);
比較兩個概率的大小決定分到哪一類即可。
連續分類
對於連續資料,通常是將其轉化為離散資料集,包括兩種方法
- 將特徵取值範圍分成幾個較少的區間
- 假設每個類別中樣本特徵服從不同期望方差下的正態分佈
第一種方法下,直接使用上面的方案即可;如果是第二種方法,我們假定 \(y_j\) 類中出現的特徵 \(a_i\) 服從正態分佈
\[g(x,\mu,\sigma) = \dfrac{1}{\sqrt{2\pi}\sigma}\exp(-\frac{(x-\mu)^2}{2\sigma^2}) \]這樣就可令 \(\Pr(a_i|y_j) = g(a_i,\mu,\sigma)\) ,其中 \(\mu\) 和 \(\sigma^2\) 是 \(y_j\) 中出現的特徵 \(a_i\) 的期望和方差。我們用平均值來近似期望,使用無偏方差
\[D(X) = \dfrac{1}{n-1}\sum_{i=1}^n(X_i-\overline{X})^2 \]假定不同特徵的協方差為 \(0\) ,也就是它們相互獨立。
我們生成一個連續資料集
% 生成連續資料
mu = [0,2];
sigma = [1 0;0,1];
r1 = mvnrnd(mu,sigma,200);
target_r1 = mvnrnd(mu,sigma,10);
mu = [3,6];
sigma = [1 0;0,1];
r2 = mvnrnd(mu,sigma,200);
target_r2 = mvnrnd(mu,sigma,10);
% 資料集
fea_con = [r1;r2];
gnd_con = [ones(200,1);-1*ones(200,1)];
target_con = [target_r1;target_r2];
% 清除無用資料
clear mu sigma r1 r2 target_r1 target_r2
這裡是利用二元正態分佈生成了兩組資料集,分別為 \(1,-1\) 類,然後將它們拼在一起,不過這不重要。
這次要對 \(10\) 個樣本進行分類,還是按照之前的方法計算 \(\Pr(y_j)\) ,而 \(\Pr(a_i|y_j)\) 則採用上面的正態分佈估計,就得到
% 統計 1 和 -1 兩類分別有多少元素
p_count1 = sum(gnd_con == 1);
p_count2 = sum(gnd_con == -1);
% 獲取 1 類和 -1 類的元素
y1 = fea_con(gnd_con == 1,:);
y2 = fea_con(gnd_con == -1,:);
% 計算平均值作為期望
mu1 = [mean(y1(:,1)) mean(y1(:,2))];
mu2 = [mean(y2(:,1)) mean(y2(:,2))];
% 計算方差
sigma1 = [(y1(:,1) - mu1(1))' * (y1(:,1) - mu1(1)) / (p_count1 - 1) 0;
0 (y1(:,2) - mu1(2))' * (y1(:,2) - mu1(2)) / (p_count1 - 1)];
sigma2 = [(y2(:,1) - mu2(1))' * (y2(:,1) - mu2(1)) / (p_count2 - 1) 0;
0 (y2(:,2) - mu2(2))' * (y2(:,2) - mu2(2)) / (p_count2 - 1)];
% 目標長度
n = length(target_con);
% 記錄概率 P(a_i|y_j) 通過正態分佈估計
P = zeros(2,2);
res = zeros(n,1);
% x = (a1,a2)
for i = 1:n
% 當前元素的兩個特徵
a1 = target_con(i,1);
a2 = target_con(i,2);
% 計算 1 類中 a1 a2 的概率
P(1,1) = 1 / sqrt(2*pi) / sigma1(1,1) * exp(-(a1-mu1(1))^2/(2 * sigma1(1,1)^2));
P(1,2) = 1 / sqrt(2*pi) / sigma1(2,2) * exp(-(a2-mu1(2))^2/(2 * sigma1(2,2)^2));
% 計算 -1 類中 a1 a2 的概率
P(2,1) = 1 / sqrt(2*pi) / sigma2(1,1) * exp(-(a1-mu2(1))^2/(2 * sigma2(1,1)^2));
P(2,2) = 1 / sqrt(2*pi) / sigma2(2,2) * exp(-(a2-mu2(2))^2/(2 * sigma2(2,2)^2));
% 計算條件概率
p1 = P(1,1) * P(1,2) * p_count1 / (p_count1 + p_count2);
p2 = P(2,1) * P(2,2) * p_count2 / (p_count1 + p_count2);
% 根據概率大小判斷分類
if p1 > p2
res(i) = 1;
else
res(i) = -1;
end
end
由於只有兩類,所以分類也較為簡單,不過更多類的情況也是類似的。
準確度
只介紹簡單的分類準確度指標 accuracy ,定義為分類正確的樣本數與總樣本數之比。
% 計算準確度
acc = sum(res == target_con_gnd) / n;