樸素貝葉斯分類及應用

貝葉斯學習

貝葉斯公式

貝葉斯學習器其實是從經典的貝葉斯概率公式的來的,對於經典的貝葉斯公式:

P(A|B)=P(B|A)P(A)P(B)

式中P(A)表示A的先驗概率(即A發生的概率與B無關),P(A|B)表示A的後驗概率(即在已知B發生的情況下,A發生的概率)

樸素貝葉斯分類

我們都知道貝葉斯是一個經典的求取概率的公式,那麼貝葉斯又是怎麼和分類相聯繫起來的呢?

實際上,在分類的過程中,我們要判斷某樣本x是否屬於某類別A時,可以將這件事看成是個概率問題,即判斷x屬於A的可能性有多大。假設類別有n種,則只需求取x分別屬於每個樣本的概率有多大,概率值最大的,即可認爲是x的所屬類別。

樸素貝葉斯分類的正式定義如下:
1. 設x={a1,a2,...,am} 爲一個帶分類項,其中每個a 的爲x的一個特徵屬性.
2. 有類別集合

$C={y1,y2,...yn}
$。
  1. 計算P(y1|x)P(y2|x) ,…,P(yn|x)

  2. 如果P(yk|x)=max{(y1|x),P(y2|x),...,P(yn|x)}
    xyk

現在從定義可以看出每步並不難理解。關鍵時第三步中的每個概率值怎麼求取。對於單個變量,求取其概率值比較好求,可是這裏的x時一個含有m個屬性的變量,這種情況下,該怎麼求取其屬於某類別yn 的概率是多少呢?

下面給出求解推導:
已知我們要求取P(yi|x) 的概率值,根據貝葉斯公式可以將其轉換爲如下形式:

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

所以求取P(yi|x) 就變成了求P(x|yi)P(yi)P(x)
對於P(x|yi) ,因爲x含有m個屬性變量,因此可以將其寫成P({a1,a2,...,am}|yi) 。對於大多數情況,x的各個屬性之間都是相互獨立,所以有:
P(x|yi)P(yi)=P(a1|yi)P(a2|yi)...P(am|yi)P(yi)=P(yi)j=1mP(aj|yi)

因此:
P(yi|x)=P(yi)mj=1P(aj|yi)P(x)

至此,便得到了P(yi|x) 的概率值求解表達式,不過這裏的P(X)的值不知道爲多少。但是,根據貝葉斯分類的思想,我們只要找到概率最大的一項即即可,對於不同的類別yiP(yi|x) 最終的求解表達式中都含有P(X),因此只要求解,使P(yi)mj=1P(aj|yi) 最大即可。

樸素貝葉斯分類應用實例(目標跟蹤)

對於目標跟蹤,目前用的比較多的方法都是在待跟蹤目標區域周圍獲取候選窗口,然後判斷這些候選窗口是否是目標。在判斷的過程中,往往採都是計算候選窗口屬於時目標的概率值,值越大,則其時目標的可能性就越大。這種思想和樸素貝葉斯分類的思想非常相似。

下面以壓縮感知跟蹤爲例。
在感知壓縮跟蹤,作者將貝葉斯當成了一個在線學習的分類器,此分類器在分爲分類和更新參數兩個部分。

在分類階段(第t幀)

首先在目標框(t-1幀確定的位置)周圍一定範圍內選取m個候選框。對候選框提取特徵,得到特徵向量v⃗ =(v1,v2,...,vn) 每個向量都含有n個屬性值,現要求v⃗  是後選框的概率值,根據樸素貝葉斯可知:

P(y=1|v⃗ )=P(y=1)ni=1P(vj|y=1)P(v⃗ )

但是要是單純的求取這個式子並不好求,因爲我們並不知道式子中P(v⃗ ) 的概率值。
不過,注意到既然不能求解P(v⃗ ) ,那是否可以將這一項消去?

因此將求取P(y=1|v⃗ ) 轉化爲求取P(y=1|v⃗ )P(y=0|v⃗ )

P(y=1|v⃗ )P(y=0|v⃗ )=P(y=1)ni=1P(vj|y=1)P(y=0)ni=1P(vj|y=0)

對上式左右兩邊同取log(爲了方便計算,將累乘變爲累加)
H(v)=i=1nlogP(y=1)P(vi|y=1)P(y=0)P(vi|y=0)

這裏假定先驗概率P(y=1)=P(y=0) ,y代表樣本標籤。
則可得:
H(v)=i=1nlogP(vi|y=1)P(vi|y=0)

其中:
P(vi|y=1)N(μ1i,σ1i)

P(vi|y=0)N(μ0i,σ0i)

在參數更新階段(第t幀)

在分類階段時,已經確定了第t幀中目標所在的位置,接下來來便更新學習機的參數。,會在目標框周圍一定範圍α 內獲取m個候選框(α 代表到目標框中心位置的距離),將其定爲正樣本;然後在範圍(α,β) 內獲取n個負樣本框(mn )。得到正負樣本後,便開始跟新分類器的參數,更新方式如下:

μ1iλμ1i+(1λ)μ1

σ1iλ(σ1i)2+(1λ)(σ1)2+λ(1λ)(μ1iμ1)2

式子中的λ 時學習參數。

實踐代碼

這是分類代碼

void CompressiveTracker::radioClassifier(vector<float>& _muPos, vector<float>& _sigmaPos, vector<float>& _muNeg, vector<float>& _sigmaNeg,
                                         Mat& _sampleFeatureValue, float& _radioMax, int& _radioMaxIndex)
{
    float sumRadio;
    _radioMax = -FLT_MAX;
    _radioMaxIndex = 0;
    float pPos;
    float pNeg;
    int sampleBoxNum = _sampleFeatureValue.cols;

    for (int j=0; j<sampleBoxNum; j++)
    {
        sumRadio = 0.0f;
        for (int i=0; i<featureNum; i++)
        {
            pPos = exp( (_sampleFeatureValue.at<float>(i,j)-_muPos[i])*(_sampleFeatureValue.at<float>(i,j)-_muPos[i]) / -(2.0f*_sigmaPos[i]*_sigmaPos[i]+1e-30) ) / (_sigmaPos[i]+1e-30);
            pNeg = exp( (_sampleFeatureValue.at<float>(i,j)-_muNeg[i])*(_sampleFeatureValue.at<float>(i,j)-_muNeg[i]) / -(2.0f*_sigmaNeg[i]*_sigmaNeg[i]+1e-30) ) / (_sigmaNeg[i]+1e-30);
            sumRadio += log(pPos+1e-30) - log(pNeg+1e-30);  // equation 4
        }
        if (_radioMax < sumRadio)
        {
            _radioMax = sumRadio;
            _radioMaxIndex = j;
        }
    }
}

這是參數跟新代碼

void CompressiveTracker::classifierUpdate(Mat& _sampleFeatureValue, vector<float>& _mu, vector<float>& _sigma, float _learnRate)
{
    Scalar muTemp;
    Scalar sigmaTemp;

    for (int i=0; i<featureNum; i++)
    {
        meanStdDev(_sampleFeatureValue.row(i), muTemp, sigmaTemp);

        _sigma[i] = (float)sqrt( _learnRate*_sigma[i]*_sigma[i] + (1.0f-_learnRate)*sigmaTemp.val[0]*sigmaTemp.val[0] 
        + _learnRate*(1.0f-_learnRate)*(_mu[i]-muTemp.val[0])*(_mu[i]-muTemp.val[0]));  // equation 6 in paper

        _mu[i] = _mu[i]*_learnRate + (1.0f-_learnRate)*muTemp.val[0];   // equation 6 in paper
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章