從貝葉斯理論到圖像馬爾科夫隨機場

轉載 https://blog.csdn.net/heyc861221/article/details/80174472

首先關於貝葉斯定理,感覺簡單而偉大,前些天一直在看吳軍的數學之美(沒看過的極力推薦)系列文章,看到自然語言處理從規則模型到統計模型轉變的時候,語言的識別準確率上升好幾個等級,以至於今天的語言識別到達很強大的地步,同時對於搜索引擎,網頁搜索的準確率,也上升好多。這其中的最最重要的就是使用了貝葉斯準則,運用一種統計學的概念,將識別搜索的結果可能性最大化。由此我聯想到當今的圖像識別領域,其實和自然語言處理一樣(當然實現上較之複雜多),現在的感覺就和當初自然語言的規則模型一樣,受到條條框框的限制,那麼圖像識別爲什麼不也弄一個統計識別模型來呢?貝葉斯定理實現的關鍵是需要歷史,需要樣本,需要基礎來訓練,語言識別有非常多的語料庫正好可以用,那麼圖像識別當然也可以有圖像庫拿來訓練,只不過對圖像,其本身不是最小單元,需要再進行處理,這一點一定程度上加大了它與語言的區別。其次圖像本身的性質決定了它不是單一的元素存在,比如給你一副圖像,裏面可能有好幾個物體可以識別。所以這一切也決定了它的困難。但是統計模式下的圖像識別感覺更具有價值,只待一種方法將圖像視爲最小單元的算法,那個時候圖像的識別將真正上升一個等級,而與之孕育而生的產業、科技,比如機器人、人工智能將會在現實中崛起。

再來談貝葉斯分類。現實生活中,我們常常會遇到這樣的問題,比如一個東西我們知道了可以分爲好幾類,那麼現實是我們拿到一個東西后開始並不知道它屬於哪一個類,我們所知道的是拿到這個東西后,對其身上的特徵進行分析,把它的特徵都分析出來了。比如一個人吧,我們要將其分成男女(有點不恰當,現實是你一看就知道,但是看,你也是看了其典型特徵才知道的),假設一眼看不出來男女,機器沒那麼智能。那麼對於這個人我們首先分析其特徵,可以是體重,身高,頭髮長短,鼻子嘴巴耳朵大小等等。那麼現在的問題是已知了這些特徵來判斷這個人是男是女,把這些特徵用xi表示,男女用yi表示,那麼在概率上講問題就變化爲已知特徵下是男女的概率了,用數學表示就是:P(y|x)P(y|x),已知x那麼它是y的概率。x不止一個,y也不止一個,那麼最終可以求得已知所有x,是y1概率多大,是y2概率多大,等等,挑其中最大的概率就認爲是屬於yi了。

那麼問題的描述用數學就是:

  1. x是一個樣本,x=a1,a2,...,anx=a1,a2,...,an

看看上面4步,就是第三步不知道怎麼辦。還好偉大的貝葉斯定理告訴了我們怎麼辦。貝葉斯定理如下:

P(yi|x)=P(x|yi)P(yi)P(x)P(yi|x)=P(x|yi)P(yi)P(x)

這個定理怎麼解釋呢?還是以上述男女分別爲例,假設x取兩個特徵,身高體重,詳細點的值就是身高170,體重50,那麼這個人是男是女。則數學表示就是

  • 是男性的概率,P(男|(身高=170,體重=50))=P((身高=170,體重=50)|男)*P(男)/P((身高=170,體重=50)),假設身高與體重這兩個特徵獨立沒有關係,那麼P((身高=170,體重=50)|男)=P(身高=170|男)*P(體重=50|男),這個應該好理解,因爲獨立,兩個連在一起的概率就是分別的概率相乘,再看看P((身高=170,體重=50)),這是什麼,身高體重使我們的觀察量,它的概率是多少,既然是觀察量,無論是男是女,這個值是一樣的,也就是是定值了,姑且認爲是1吧,再看看P(男)是多少,我們訓練樣本,那麼在所有訓練樣本中,每個樣本屬於哪一類是知道的,比如我選了50個人,其中30男20女,那麼對於這個訓練樣本P(男)=3/5,這一項也就是樣本中某一類的概率。好了最終P(男|(身高=170,體重=50))=P(身高=170|男)*P(體重=50|男)*P(男)。
  • 同理是女性的概率:P(女|(身高=170,體重=50))=P(身高=170|女)*P(體重=50|女)*P(女)。

繼續往下求,以男的爲例,現在的問題就轉變爲求P(身高=170|男)*P(體重=50|男)*P(男),P(男)說了怎麼辦,那麼P(身高=170|男)和P(體重=50|男)怎麼辦,這個時候就是訓練樣本大發神威的作用了。P(身高=170|男)的意思表示男的裏面身高爲170的概率,既然求男的裏面身高是170的概率,因爲我們有一大堆訓練樣本,好了把樣本里面的男的挑出來,單看男的裏面身高規律,我們再去統計一下,假設發現30個男的,有15個男的升高在170左右,其他的都不在,那麼我們是不是可以認爲男的裏面身高爲170的概率就是15/30=0.5了呢?當然可以。同理可以算出男的裏面體重爲50的概率。至於怎麼根據這些值算這個概率,有很多講究,比如我們認爲人的身高符合正態分佈,那麼我們用一個正態分佈函數去擬合身高的概率密度函數不就可以了嗎?求出身高這些值得均值與方差,然後用

P(x)=12πσexp((xu)22σ2)P(x)=12πσexp(−(x−u)22σ2)
去算當具體的一個x來了的時候它的概率。知道了身高這個特徵怎麼算了,那麼同理體重算法。然後在同理女性的算法。這樣就計算完了,可以比較了吧

好了再整理一下整體的步驟:
(1)確定用於分類的訓練樣本集,這個樣本集中,每個樣本有多少個特徵,以及樣本屬於哪一個類別要明確。
(2)計算每個類別的概率P(ci)P(ci)
至於P(x|y)怎麼算,一般對於連續變化的數值,可以用正態分佈函數來模擬它的概率密度。

至此訓練完成,那麼如何分類?分類是相對測試樣本而言的,這個時候你是不知道測試的樣本的分類的,只知道它的特徵。好了,假設來了一個測試樣本x,它的特徵都知道,它屬於哪一類呢?用下面公式:

P(yi|x)=P(x|yi)P(yi)P(x)P(yi|x)=P(x|yi)P(yi)P(x)
都算一遍,比較選擇其中的最大的那個概率就是所屬的類了。

這裏面有一些小的細節問題可以優化一下:

  • 當有些特徵P(x|y)P(x|y)設置爲0吧,這樣乘積爲0了,這個時候我們把特徵x對應下的頻數加1,話句話說將它認爲加一點,設置爲一個小的量。

  • 當樣本多了,每個樣本特徵數多了的時候,我們知道上述是一些列p的乘積,想想每個p在0-1之間,然後在相乘,假設每個樣本由100個特徵,那就是100個0-1的p相乘,得是多小的一個數?小到一定程度的時候計算機直接溢出了,或者四捨五入變爲0了,最後一堆0你怎麼比較屬於哪一類?這個時候我們採取將上述概率計算左右都取對數,對數函數對於0-1之間的數是單調變化的,原來的p大,那麼log(p)也大,所以沒有影響。這樣可以把數據都拉回來。相乘這個時候就變爲相加了。

下面在matlab下用一個實例說明樸素貝葉斯算法。
首先是樣本的選擇,這個樣本曾經在
聚類之詳解FCM算法原理及應用
裏面用過,是關於種子分類的,每個種子有7個特徵,種子分爲3類,共210個樣本,樣本下載地址:

http://archive.ics.uci.edu/ml/datasets/seeds#

將數據存爲txt保存到matlab工作目錄下,編寫一個bayes.m的腳本,具體程序如下:

clc
clear
close all
data = load('data.txt');
%選擇訓練樣本個數
num_train = 50;
choose = randperm(length(data));%構造隨機選擇序列
train_data = data(choose(1:num_train),:);
test_data = data(choose(num_train+1:end),:);
mu = zeros(3,7);
sigma = zeros(3,7);
pc = zeros(3,1);
%training
for i = 1:3 %3類
    index = find(train_data(:,8)==i);
    pc(i) = length(index)/num_train;
    data_index = train_data(index,:);
    for j = 1:7 %每類7個特徵
        mu(i,j) = mean(data_index(:,j));
        sigma(i,j) = var(data_index(:,j));
    end
end
%testing
ture_num = 0;
for i = 1:length(test_data)
    test_simple_data = test_data(i,:);
    for j = 1:3
        for k = 1:7
            p(j,k) = 1/sqrt(2*pi*sigma(j,k))*...
                exp(-(test_simple_data(k)-mu(j,k))^2/2/sigma(j,k));
        end
    end
    log_p = sum(log(p),2)+log(pc);
    [~,index_maxP] = max(log_p);
    predict(i) = index_maxP;
    if index_maxP == test_simple_data(8)
        ture_num = ture_num + 1;
    end
end
accuracy = ture_num/length(test_data);
plot(test_data(:,8),'or')
axis([0,length(test_data),0,5])
hold on
plot(predict,'+');
hold on
plot(abs(predict'-test_data(:,8)));
title(['the accuracy is : ',num2str(accuracy)])  

    程序中可以看到,這裏我們將每一個特徵認爲是服從正態分佈的,同時訓練樣本選擇是隨機挑的,所以每次結果會不一樣。
    看看訓練樣本選擇50個(測試樣本210-50)下的結果:
    這裏寫圖片描述

    加號與圈在一起證明分對了,不在一起就錯了,並且用一個尖尖凸顯出來。可以看到這一次準確率有0.93。改變訓練樣本個數去試驗其他的情況吧。我試驗了多次,普遍準確率都在0.9左右,這個結果是不是還算可以。

    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章