決策與概率估計
假設一個很簡單的實驗來看我們做決策的過程,有一個有偏的硬幣,投了100次,60次出現人頭,40次出現字,下一次拋硬幣,如果我們猜對我們得1元,猜錯我們交出1元。很直覺的,我們每次都會猜人頭的啦。細細一想,我們在做這樣一件事,max(60%*1+40%*(-1), 60%*(-1)+40%*1) 就是在估計了概率的情況下,我們看兩個決策(人頭/字)哪個帶來的收益大。
換一個想法,我們不先估計出經驗分布P(Y|X),而是直接看有沒有可能做出一個決策,使得它在歷史的數據上得到收益是最大的,即max(60*1+40*(-1), 60*(-1)+40%*1)。這兩種方法可以稱為概率估計法及決策函數法。
這個問題的兩種解決方案都有明確的最優解,但實際情況是決策函數無法直接優化(上面的例子的事件服從伯努利分布,優化比較簡單,但常常我們遇到的問題是包含像sign()這樣的函數), 所以我們會用代理損失函數來做. 所謂代理損失函數就是用一個高階可微的損失函數去接近決策的損失函數。但是有多接近呢,誰也不知道。於是很多人轉向另一個陣營:更精確的估計出條件概率分布,然后做決策。如果能精確估計出條件概率,當然很好,決策的問題也迎刃而解,但事實又不是,不考慮決策損失直接做概率分布,即使是適定的,也會有問題,這個后面再說。
這里介紹的是第二種方案,即條件概率分布的估計。對於決策而言,這是個兩步的過程,1)忽視Risk估概率 2)有了概率算對應的決策對應的Risk。2)比較簡單,我們又focus在第一步,即“估概率”。
概率估計常見的loss
估算概率常見的思路是最大似然或是最小均方誤差,這兩者形式上非常的不相同,甚至很多人認為最小均方誤差不適於做概率估計。原因有二,1)概率用和0及1的距離平方和做誤差有問題,P=0.4和P=0.5之間的誤差和0.1與P=0.001能一樣嗎? 2)使均方誤差最小的參數組合,會讓某些(X,Y) samples小於0或大於1。這兩個直覺有道理嗎?有道理,但這是直覺,能把你的疑問說清楚嗎?為什么你會覺得P=0.4和P=0.5之間的誤差和0.1與P=0.001之間的誤差不一樣?
由於一個概率分布P(Y|X)在每一點X上都可以看成伯努利分布,如果我們所假設的P(Y|X)的形式足夠復雜,這個條件概率分布函數的估計就轉化為每一點上的伯努利分布的估什,所以我們還是舉P(Y|X)為伯努利的例子看,設真實的概率為p,估計值為\hat{p},對最大似然(logistic loss)而言,損失函數是
, 對最小均方誤差而言,損失函數是
一個顯見的事實是,這兩個損失函數都在\hat{p}=p時取得最值,並且是凸的。既然能保證期望風險下經數值優化后最優的估計概率等於真實概率,二者都能達到相同的目的。這正是我們設計損失函數的目的:能正確地估計出概率分布函數?這就是最近很多人在研究的兩類和多類損失函數的設計,關於這個主題可以參考"On the Design of Loss Functions for Classification"及Savage有篇老文章“Elicition of Personal Probabilities”,最近有一篇關於多類問題的引申,可以看"composite multiclass loss"。
滿足上一節所說的兩個條件的loss是適定的(proper)。其它的一些loss像是hinge loss就不滿足,只是對Decision Risk的直接優化,即構造surrogate loss(當然SVM最初並沒有從surrogate loss的角度來設計)。下面我們只討論lse和logistic loss的區別,用一個實際的例子來說明。兩個loss有何區別
lse和logistic loss就伯努利分布的估計而言是沒有任何區別。我們現在稍加擴展,假定我們想要估計的P(Y|X)符合
而已知的訓練數據是我們人為設計的一組略有矛盾的數據,使得上面的條件分布函數無法精確描述數據。我們這樣來構造這組數據,固定\lambda_0=0 使得\lambda_1=0.5及 \lambda_1=1.0
我們有下面的表格| \lambda_1 | x=0.0 | x=-1.0 | x=-2.0 |
| 0.5 | 0.5 | 0.3775 | 0.2689 |
| 1.0 | 0.5 | 0.2689 | 0.1192 |
按上面表格的每一行P(Y|X)都能精確的估計參數,但我們選了加黑部分的P(Y|x)來生成訓練數據。每個單元格對應的概率值生成1000個樣本。生成如下表格的樣本
| P(Y|X) | 正例數量 | 負例數量 |
| 0.5 | 500 | 500 |
| 0.3775 | 378 | 622 |
| 0.1192 | 119 | 881 |
在這個訓練集合上我們可以看看用不同的loss訓練出來的參數有什么特點。Logistic loss訓練出的參數是0.841,LSE訓練出的參數是0.795。的確有差別,在這種簡單的情況之下,嘗試分析一下原因。我們畫出-p\log{\hat{p}}-(1-p)\log(1-\hat{p})在p=0.1192及p=0.500時的曲線,也許你能找到一些線索。這個解釋可以作為一個思維練習一下。

訓練的代碼可以用最近比較火的theano庫寫,支持符號計算,不需要寫梯度函數。
import re,sys,os import time import numpy import theano import theano.tensor as T data_path = sys.argv[1] max_feat_num = 1 X_var = T.dmatrix() Y_var = T.ivector() s_Wb = theano.shared(numpy.zeros(max_feat_num+1, dtype='float64'), name='s_Wb') s_W = s_Wb[:max_feat_num].reshape((max_feat_num,1)) s_b = s_Wb[max_feat_num:] #exp_linear = T.dot(X_var, s_W)+s_b exp_linear = T.dot(X_var, s_W) exp_py_given_x = T.nnet.sigmoid(exp_linear);#p exp_npy_given_x = T.nnet.sigmoid(-exp_linear);# 1-p (softmax and sigmoid) # loss # 1. logistic loss exp_py_npy = T.concatenate((exp_npy_given_x, exp_py_given_x), axis = 1) exp_logistic = -T.mean(T.log(exp_py_npy)[T.arange(Y_var.shape[0]), Y_var])
# 2. LSE I_p = (exp_py_given_x-1)*(exp_py_given_x-1) I_n = exp_py_given_x*exp_py_given_x exp_lse = T.mean(T.concatenate((I_n, I_p), axis = 1)[T.arange(Y_var.shape[0]), Y_var])
# gradient exp_logistic_grad = T.grad(exp_logistic, s_Wb) exp_lse_grad = T.grad(exp_lse, s_Wb) X=[] Y=[] data_file = open(data_path, "r") for line in data_file: ss = re.split("\s+", line.strip()) Y.append((int(ss[0])+1)/2) x = [0.0]*max_feat_num; for i in range(1, len(ss)): ss1 = re.split(":", ss[i]) x[int(ss1[0])] = float(ss1[1]) X.append(x) data_file.close() # try to use logistic loss or adaptive loss or mse loss loss_and_grad = [exp_lse, exp_lse_grad] s_X = theano.shared(numpy.asarray(X, dtype="float64"), name='s_X') s_Y = theano.shared(numpy.asarray(Y, dtype="int32"), name='s_Y') func_cost = theano.function([], loss_and_grad[0], givens={ X_var: s_X, Y_var: s_Y }, name='func_cost'); func_grad = theano.function([], loss_and_grad[1], givens={ X_var: s_X, Y_var: s_Y }, name='func_grad'); def cost(wb): s_Wb.set_value(wb, borrow=True) cost = func_cost() print cost return cost def grad(wb): s_Wb.set_value(wb, borrow=True) return func_grad() def cb(wb): s_Wb.set_value(wb, borrow=True) print wb # try solve the optimization through lbfgs import scipy.optimize best_w_b = scipy.optimize.fmin_l_bfgs_b( func=cost, x0=numpy.zeros(max_feat_num+1, dtype="float64"), fprime=grad, iprint=1, maxfun=100) print best_w_b
設計你所需要的loss
上面兩種是最常見的兩種proper的loss。在實際應用中,我們如果將loss design和decision risk完全隔裂,就會產生一種觀點,只需要一個loss是proper的,估完probability再做decision.但我們往往需要將decision risk本身考慮到conditional probability estimation的過程中。因為有時把某個區域內的條件概率估對(或估錯)對於最后的decision making 沒有任何的幫助(或損失)。這種因素如果我們不在probability estimation時就考慮,就讓訓練專注於那些本不該專注的地方。如何把decision risk考慮到probability estimation中is art rather than science。所以可能需要更多的工程經驗和想象力才行。
