不少人說,看了再多的文章,但是沒有人手把手地教授,仍是很難真正地入門AI。爲了將AI知識體系以最簡單的方式呈現給你,從這個星期開始,芯君邀請AI專業人士開設「週末學習課堂」——每週就AI學習中的一個重點問題進行深度分析,課程會分爲理論篇和代碼篇,理論與實操,一個都不能少!框架
來,退出讓你廢寢忘食的遊戲頁面,取消只有胡吃海塞的週末聚會吧。將來你與同齡人的差別,也許就從每週末的這堂AI課開啓了!dom
在昨天的課程中,咱們提到屬性的取值一旦由離散變得連續,就不能用頻率來估計機率。可是咱們能夠用一個機率密度函數來指定屬性的類條件機率的估計,好比令條件機率爲一個高斯分佈:機器學習
高斯分佈由兩個參數(均值和標準差)惟一肯定,咱們惟一須要作的只是對高斯分佈的參數進行估計,參數一旦估計完成,咱們的學習過程也就結束了,將新的樣本添加進去,對參數進行更新便可。ide
爲方便你們與前面的進行對比,咱們採用與《核技巧(代碼篇)》同樣的數據:函數
from sklearn import datasets import matplotlib.pyplot as plt import seaborn as sns X,y=datasets.make_moons(200,noise=.2,random_state=0) sns.set(style='darkgrid') for i,v,l in [[0,'r','class_0'],[1,'b','class_1']]: plt.scatter(X[y==i][:,0],X[y==i][:,1],c=v,label=l) plt.legend() plt.show()
對於這種屬性連續但目標離散的數據,咱們能夠很方便的用sklearn的naive_bayes構建分類器並使用它來適應數據:post
from sklearn import datasets import matplotlib.pyplot as plt import seaborn as sns from sklearn.naive_bayes import GaussianNB import numpy as np def make_meshgrid(x, y, h=.02): x_min, x_max = x.min() - 1, x.max() + 1 y_min, y_max = y.min() - 1, y.max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) return(xx, yy) X,y=datasets.make_moons(200,noise=.4,random_state=0) xx,yy=make_meshgrid(X[:,0],X[:,1]) gnb=GaussianNB() gnb.fit(X,y) Z=gnb.predict_proba(np.c_[xx.ravel(),yy.ravel()])[:,1] Z=Z.reshape(xx.shape) sns.set(style='white') plt.contourf(xx,yy,Z,cmap=plt.cm.RdBu,alpha=.8) for i,v,l in [[0,'r','class_0'],[1,'b','class_1']]: plt.scatter(X[y==i][:,0],X[y==i][:,1],c=v,label=l,edgecolors='k') plt.legend() plt.show()
如圖,紅藍色逐漸變淺的分界線就是咱們的決策邊界,並且顏色越深,表明着離決策邊界越遠,說明了屬於某一類的機率也就越大。學習
咱們在上一節所提到,根據貝葉斯定理,咱們的相對後驗機率不只取決於似然,還取決於先驗,咱們最終獲得的機率會有着先驗偏好的影響。在這裏,咱們調節高斯樸素貝葉斯類器的先驗,就能夠看到先驗分佈的影響:優化
...... piror=zip([0.01,0.2,0.8,0.99],[0.99,0.8,0.2,0.01]) sns.set(style='darkgrid') for i,p in enumerate(piror): gnb=GaussianNB(p)# 先驗機率 gnb.fit(X,y) Z=gnb.predict_proba(np.c_[xx.ravel(),yy.ravel()])[:,1] Z=Z.reshape(xx.shape) plt.subplot(2,2,i+1) plt.contourf(xx,yy,Z,cmap=plt.cm.RdBu,alpha=.8) for i,v,l in [[0,'r','class_0'],[1,'b','class_1']]: plt.scatter(X[y==i][:,0],X[y==i][:,1],c=v,label=l,edgecolors='k') plt.title('piror of red point:%s' %p[0]) plt.legend() plt.show()
從圖中能夠看出,隨着紅色數據點的先驗機率的增大,決策邊界往藍色數據點處移動,意味着咱們的分類器對於紅色點賦予更大的後驗機率。spa
除了假設似然是高斯分佈,咱們還能夠假設多項分佈,伯努利分佈,拉普拉斯分佈等不一樣的分佈形式,最終獲得的決策邊界也會不一樣。在面對具體的問題時,咱們能夠根據本身的經驗或者領域知識來選取合適的先驗和似然函數,從而更有針對性的處理問題。3d
接下來討論一種更爲複雜的情形,即特徵值連續並且目標值也連續,即廣泛的迴歸的問題。在上一篇《基於貝葉斯推斷的迴歸模型》中提到了貝葉斯線性估計,它的基本思想是經過增量學習,將上一個數據點的後驗機率做爲下一次的先驗機率,並使用所有的數據點經過極大後驗估計來估計參數值。在《特徵選擇代碼篇》中,咱們曾經意外發現了一個比較完美的迴歸數據,是S1血清和S2血清的關係圖,咱們用線性迴歸的辦法能夠處理爲:
獲得一條直線,若是咱們利用貝葉斯估計的方法,很大程度上會獲得一條相似的曲線(可能只是參數空間的微小變化),但正由於如此,咱們須要對貝葉斯估計的過程作進一步的程序上的分析。將每一個數據點依次添加,在參數空間上觀察後驗機率(後一次估計的先驗機率)和似然函數,而且隨着數據點的增長,對直線參數的約束也就愈來愈強,咱們還能夠在樣本空間上直觀的看到這種約束做用。
沒有數據進入時,咱們默認數據的先驗爲一個標準的高斯分佈,而參數是從這個高斯分佈上隨機取到的點:
from matplotlib import pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D import seaborn as sns mean=0 sigma=1 x=np.linspace(-1,1,100) y=np.linspace(-1,1,100) X,Y=np.meshgrid(x,y) z = np.exp(-((X-mean)**2 + (Y- mean)**2)/(2*(sigma**2))) z = z/(np.sqrt(2*np.pi)*sigma) plt.figure() plt.contourf(Y,X,z,100,alpha=1,cmap=plt.cm.RdBu) plt.xlabel('$\omega_0$') plt.ylabel('$\omega_1$') plt.title('Piror') plt.show()
這是先驗分佈的contour
接着從高斯分佈中隨機採樣獲得一系列參數,而後將參數代入直線中,獲得樣本空間:
...... np.random.seed(42) plt.figure() a=np.linspace(-0.1,0.2,100) for i,v in np.random.normal(loc=0.0,scale=1.0,size=(10,2)): omega1,omega2=i,v plt.plot(a,omega1+omega2*a) plt.title('Data Space') plt.xlabel('S1') plt.ylabel('S2') plt.show()
參數是從先驗分佈上隨機取得,而後根據參數和咱們的線性模型,在樣本空間上直接能夠看到,沒有添加任何數據的時候,模型並無獲得約束。
考慮到咱們的樣本有442個,爲了更直觀的表示數據對參數的約束做用,咱們一次性添加50個點,來獲得後驗分佈,寫出這樣的代碼並不難,只須要利用咱們在理論篇講過的極大後驗估計的方法:
import matplotlib.pyplot as plt import numpy as np from sklearn import datasets Data=datasets.load_diabetes() x=Data['data'][:,4][100:150] y=Data['data'][:,5][100:150] def fun(x,omega): return(omega[1]+omega[0]*x) def posterior(omega,x,y): post=lnlike(omega,x,y)+5*(omega[0]*omega[0]+omega[1]*omega[1])#取了對數,後驗就等於先驗和似然的和 return(post) def lnlike(omega,x,y): hood=0 for i in range(x.shape[0]): hood+=0.5*np.dot((y[i]-fun(x[i],omega)),(y[i]-fun(x[i],omega))) return(hood) a=np.linspace(-1,1,100) b=np.linspace(-1,1,100) A,B=np.meshgrid(a,b) plt.figure() plt.contourf(A,B,posterior([A,B],x,y),100,alpha=1,cmap=plt.cm.RdBu) plt.title('Posterior') plt.xlabel('$\omega_0$') plt.ylabel('$\omega_1$') plt.show()
能夠看到,由於數據的約束,參數的contour向上方移動,更偏向於0,更偏向於1,咱們能夠簡單的在附近對參數進行採樣,觀察樣本空間的變化:
plt.figure() plt.plot(x,y,'k.') for i,v in zip(np.random.uniform(0.8,1.2,10),np.random.uniform(-0.025,0.025,10)): omega2,omega1=i,v plt.plot(a,omega1+omega2*a) plt.title('Data Space') plt.xlabel('S1') plt.ylabel('S2') plt.show()
能夠看到,添加數據對後驗分佈的影響直接體如今了樣本空間上,本來隨機的直線開始集中在樣本週圍。若是咱們繼續添加樣本,直線也會變的愈來愈集中,而對應着的參數空間也會變得愈來愈小。
這個數據的迴歸趨勢過於完美,能夠預想到繼續添加數據,參數空間變小的速度會愈來愈慢,一方面,這是數據量增長的必然結果,但更重要的是,咱們要知道,對於太過完美的數據,添加的數據所影響的後驗分佈仍然與前面的數據保持一致,想象一個極端的例子,兩點就能夠肯定一條直線,然後續的點會所有落在這條直線上,而參數並無變化。
但絕對不縮小到一個點,由於貝葉斯估計的性質決定了咱們獲得的參數只能是一個分佈,而不是一個點。雖然能夠將參數優化到一個點,但這樣作存在必定的風險,由於不一樣的數據獲得的最佳參數值並不會同樣,更加合理的的方式是爲參數估計出一個置信區間(其實,置信區間就對應着參數空間的contour)。
若是模型攜帶參數,那麼勢必要對模型進行的參數進行估計。在整個機器學習中存不存在非參數的模型呢?咱們下一節會介紹非參模型的表示,評估和優化。
課堂TIPS
• 須要注意的是,對連續屬性值所做的假設分佈,仍然包含在樸素貝葉斯的框架以內,由於樸素貝葉斯假設了屬性之間互相獨立,而處理連續屬性值的方式是對每個屬性都須要作出假設分佈,最後的後驗機率仍然是各屬性分佈的連乘。
• 除了一些特殊狀況,好比二值化的數據,咱們會用伯努利分佈來嘗試。大多數狀況下,咱們會使用高斯分佈,一方面因爲中心極限定理的存在,沒有經驗的情形下,高斯分佈可能更爲合理,另外一方面則是由於高斯分佈用的性質在數學上有着不少便利。
• 使用貝葉斯估計來處理迴歸問題時,須要處理一系列的超參數(初始先驗分佈的參數,批量的大小,以及最終寫入優化目標的正則化項的係數),這些超參數的調節固然經過網格搜索或者隨即搜索來嘗試,但更重要的是,深入理解貝葉斯估計的整個過程,就算你在調參的時候,也會比別人調的更快。好比,當你代入數據點估計後驗的時候,若是後驗分佈變化並不明顯,應該嘗試更大的批量或者進行更屢次的迭代,若是每次帶入數據,後驗分佈就會發生鉅變,你或許應該檢查本身的數據是否存在異常。
做者:唐僧不用海飛絲 如需轉載,請後臺留言,遵照轉載規範
【週末AI課堂 | 第十三講】基於貝葉斯推斷的迴歸模型(理論篇) 【週末AI課堂 | 第十二講】基於貝葉斯推斷的分類模型(代碼篇) 【週末AI課堂 | 第十一講】基於貝葉斯推斷的分類模型(理論篇) 【週末AI課堂 | 第十講】核技巧(代碼篇) 【週末AI課堂 | 第九講】核技巧(理論篇) 【週末AI課堂 | 第八講】非線性降維方法(代碼篇) 【週末AI課堂 | 第七講】非線性降維方法(理論篇) 【週末AI課堂 | 第六講】線性降維方法(代碼篇) 【週末AI課堂 | 第五講】線性降維方法(理論篇) 【週末AI課堂 | 第四講】如何進行特徵選擇(代碼篇) 【週末AI課堂 | 第三講】如何進行特徵選擇(理論篇) 【週末AI課堂 | 第二講】過擬合問題(代碼篇) 【週末AI課堂 | 第一講】過擬合問題(理論篇)