點擊上方「AI有道」,選擇「星標」公眾號
重磅乾貨,第一時間送達
本文介紹對數線性分類模型,在線性模型的基礎上通過複合函數(sigmoid,softmax,entropy )將其映射到概率區間,使用對數損失構建目標函數。首先以概率的方式解釋了logistic回歸為什麼使用sigmoid函數和對數損失,然後將二分類擴展到多分類,導出sigmoid函數的高維形式softmax函數對應softmax回歸,最後最大熵模型可以看作是softmax回歸的離散型版本,logistic回歸和softmax回歸處理數值型分類問題,最大熵模型對應處理離散型分類問題。
作者 | 文杰
編輯 | yuquanle
分類問題可以看作是在回歸函數上的一個分類。一般情況下定義二值函數,然而二值函數構成的損失函數非凸,一般採用sigmoid函數平滑擬合(當然也可以看作是一種軟劃分,概率劃分):從函數圖像我們能看出,該函數有很好的特性,適合二分類問題。至於為何選擇Sigmoid函數,後面可以從廣義線性模型導出為什麼是Sigmoid函數。
邏輯回歸可以看作是在線性回歸的基礎上構建的分類模型,理解的角度有多種(最好的當然是概率解釋和最小對數損失),而最直接的理解是考慮邏輯回歸是將線性回歸值離散化。即一個二分類問題(二值函數)如下:
0-1損失的二分類問題屬於一種硬劃分,即是與否的劃分,而sigmoid函數則將這種硬劃分軟化,以一定的概率屬於某一類(且屬於兩類的加和為1)。
Sigmoid函數將線性回歸值映射到
這裡對於目標函數的構建不再是最小化函數值與真實值的平方誤差了,按分類原則來講最直接的損失因該是0-1損失,即分類正確沒有損失,分類錯誤損失計數加1。但是0-1損失難以優化,存在弊端。結合sigmoid函數將硬劃分轉化為概率劃分的特點,採用概率
同樣採用梯度下降的方法有:
又:
所以有:
B、概率解釋
邏輯回歸的概率解釋同線性回歸模型一致,只是假設不再是服從高斯分布,而是
所以最大化似然估計有:
logistic採用對數損失(對數似然函數)原因:
1) 從概率解釋來看,多次伯努利分布是指數的形式。由於最大似然估計導出的結果是概率連乘,而概率(sigmoid函數)恆小於1,為了防止計算下溢,取對數將連乘轉換成連加的形式,而且目標函數和對數函數具備單調性,取對數不會影響目標函數的優化值。
2)從對數損失目標函數來看,取對數之後在求導過程會大大簡化計算量。
Softmax回歸可以看作是Logistic回歸在多分類上的一個推廣。考慮二分類的另一種表示形式:
當logistic回歸採用二維表示的話,那麼其損失函數如下:
其中,在邏輯回歸中兩類分別為
其中向量的第
其中函數值是一個
其中
二分類與多分類可以看作是二元伯努利分布到多元伯努利分布的一個推廣,概率解釋同Logistic回歸一致。詳細解釋放到廣義線性模型中。
對於多分類問題,同樣可以借鑑二分類學習方法,在二分類學習基礎上採用一些策略以實現多分類,基本思路是「拆解法」,假設N個類別一對一的基本思想是從所有類別中選出兩類來實現一個兩分類學習器,即學習出
一對多的基本思想是把所有類別進行二分類,即屬於
很奇怪,為什麼會把最大熵模型放到這,原因很簡單,它和Logistic回歸和SoftMax回歸實在是驚人的相似,同屬於對數線性模型。
A、熵的概念
信息熵:熵是一種對隨機變量不確定性的度量,不確定性越大,熵越大。若隨機變量退化成定值,熵為0。均勻分布是「最不確定」的分布 。
假設離散隨機變量X的概率分布為
其中熵滿足不等式
聯合熵:對於多個隨機變量的不確定性可以用聯合熵度量。
假設離散隨機變量
條件熵:在給定條件下描述隨機變量的不確定性。
假設離散隨機變量
互信息:衡量兩個隨機變量相關性的大小。
相對熵(KL散度):衡量對於同一個隨機變量兩個概率分布
有互信息和相對熵的定義有下式:
關於熵的介紹就到此,不細究,雖然上面的這些定義在機器學習中都會遇到,不過後面涉及到的主要還是熵和條件熵,互信息。
B、最大熵模型
最大熵原理是概率模型學習中的一個準則。最大熵原理認為,學習概率模型時,在所有可能的概率模型分布中(滿足所有條件下),熵最大的模型是最好的模型。熵最大即為最均勻的分布,從某種角度講均勻分布總是符合我們理解的損失風險最小,也就是「不要不所有的雞蛋放到一個籃子裡,均勻的放置」。
給定訓練集:
假設
一般來講,最大熵模型常用於處理離散化數據集,定義隨機變量
特徵函數:
約束條件:對於任意的特徵函數
特徵函數
所以,滿足約束條件的模型集合為:
因此最大熵模型的形式化表示如下:
由拉格讓日乘子法,引入拉格讓日乘子,定義拉格讓日函數:
根據拉格朗日乘子法,
裡層是
對偶問題是:
求解對偶問題,第一步最小化內部:
那麼外層最大化目標函數為:
為了求解
求解得:
這裡,雖然我們不知道
因此,
代回
回顧對偶函數,內部最小化求解得到了
C、概率解釋
已知訓練集的經驗概率分布
其中,我們發現對數似然函數與條件熵的形式一致,最大熵模型目標函數前面有負號(這與最大化對數似然函數完全相反),同時最大熵模型中有約束條件。也正是因為約束條件,我們將原問題轉化為對偶問題後發現,在滿足約束條件的對偶函數的極大化等價於最大化對數似然函數。
當條件概率
代入到對數似然函數,同樣有:
最後,我們再來看對偶函數表達式,我們發現,第一項其實是
下面再來對比下Logistic回歸,SoftMax回歸,最大熵模型:
1)同屬於對數線性模型。
2)Logistic回歸和SoftMax回歸都基於條件概率
3)由於都採用線性模型,三者都假設特徵之間是獨立的。
最大熵模型的優化問題:
最大熵模型從拉格朗日乘子法最大化對偶函數,還是從最大化對數似然函數,其目標函數如下:
常用的梯度優化算法都可以,另外對於最大熵模型也有專門的算法有GIS IIS 算法 。
int LogReg()
{
const char *file="data\\LogReg.txt";
const string model="gradAscent";
const double alpha=0.01;
Matrix x;
cout<<"loadData"<<endl;
cout<<"--"<<endl;
x.LoadData(file);
Matrix y;
y=x.getOneCol(x.col-1);
x.deleteOneCol(x.col-1);
if(model=="gradAscent")
gradAscent_Log(x,y);
if(model=="stoGradAscent")
stoGradAscent_Log(x,y);
return 0;
}
int gradAscent_Log(Matrix x,Matrix y)
{
if(y.col!=1)
{
cout<<"logReg is two class"<<endl;
return -1;
}
Matrix weights(x.col,y.col,0.1,"T");
Matrix xT = x.transposeMatrix();
float alpha=0.01;
float error=0;
int iter=0;
int i,j;
Matrix z(y.row,y.col,0,"T");
Matrix grad(x.col,y.col,0,"T");
for(iter=0; iter<5000; iter++)
{
z = x * weights;
for(i=0; i<z.row; i++)
{
z.data[i][0]=sigmoid(z.data[i][0]);
}
z = y - z;
error=0;
for(i=0; i<x.row; i++)
error+=z.data[i][0];
grad = xT * z;
for(i=0; i<grad.row; i++)
grad.data[i][0]*= alpha;
weights = weights + grad;
}
int er1=0,er2=0;
Matrix train=x * weights;
cout<<"test"<<endl;
for(i=0; i<y.row; i++)
{
if(train.data[i][0]>0)
{
cout<<1-y.data[i][0]<<endl;
er1+=(1-y.data[i][0]);
}
else
{
cout<<0-y.data[i][0]<<endl;
er2-=(0-y.data[i][0]);
}
}
}
int SoftMaxReg()
{
const char *file="data\\LogReg.txt";
const string model="gradAscent";
const double alpha=0.01;
Matrix x;
cout<<"loadData"<<endl;
cout<<"--"<<endl;
x.LoadData(file);
Matrix y;
y=x.getOneCol(x.col-1);
y=one_hot(y,2);
x.deleteOneCol(x.col-1);
if(model=="gradAscent")
gradAscent_SoftMax(x,y);
if(model=="stoGradAscent")
stoGradAscent_SoftMax(x,y);
return 0;
}
int stoGradAscent_SoftMax(Matrix x,Matrix y)
{
Matrix xOneRow(1,x.col,0,"T");
Matrix xOneRowT(x.col,1,0,"T");
Matrix weights(x.col,y.col,0.1,"T");
Matrix z(1,y.col,0,"T");
Matrix grad(x.col,y.col,0,"T");
double zRowSum=0;
double alpha=0.001;
double error;
int i,j,k,iter;
for(iter=0; iter<5000; iter++)
{
for(i=0; i<x.row; i++)
{
xOneRow=x.getOneRow(i);
z = xOneRow * weights;
zRowSum=0;
for(j=0;j<z.col;j++)
{
z.data[0][j]=sigmoid(z.data[0][j]);
zRowSum+=z.data[0][j];
}
for(j=0;j<z.col;j++)
{
z.data[0][j]/=zRowSum;
if(iter%1000==0)
cout<<z.data[0][j] <<" s ";
}
if(iter%1000==0)
cout<<endl;
for(j=0;j<y.col;j++)
{
z.data[0][j]=y.data[i][j]-z.data[0][j];
}
xOneRowT = xOneRow.transposeMatrix();
grad = xOneRowT * z;
for(k=0; k<grad.row;k++)
{
for(j=0;j<grad.col; j++)
{
grad.data[k][j]*= alpha;
}
}
weights = weights + grad;
}
}
Matrix test=x * weights;
cout<<"test"<<endl;
for(i=0; i<y.row; i++)
{
if(test.data[i][0]>test.data[i][1])
cout<<0-y.data[i][1]<<" ";
else
cout<<1-y.data[i][1]<<" ";
cout<<endl;
}
}
完整代碼:
https://github.com/myazi/myLearn/blob/master/LineReg.cpp