本文通過分類問題講解判別式和生成式模型,會用到Logistics Regression 和 幾率模型
首先介紹一下,判別式模型是完全根據數據得出結果,而生成式模型會有人為設定的條件建立模型,再通過利用假設建立的模型得出結果。
Generative (生成式模型)
例: 利用iris數據進行分類
本文僅僅才用了target0和target1,且僅僅利用了前兩種屬性(便於可視化)
數據可視化
利用生成式建立模型,首先假設每一種花的屬性服從高斯分布,即
相當於每一種屬性主要分布在在以\(u\)為中心,以\(\sigma\)為半徑的圓中。
這樣就可以利用概率的大小來判斷圖中對應的點應該屬於哪一個分組。例如此例中
越靠近某類中心,該點為此類的概率越大。(本文假設其服從高斯分布,也可以假設其為其他分布,這也是生成式模型與判別式模型的不同之處)
首先看藍色的點,由於我們假設其為高斯分布,也就是說,某一個高斯分布會產生如此分布的點。很明顯,這樣高斯分布有無窮多個,我們需要找到一個高斯分布能夠最大概率的生成這樣分布的點。這就需要用到最大似然估計。
首先對於一個高斯分布的模型(參數為\(u,\sigma\)),圖中的任何一個點都會產生一個概率,我們只需要找到一個模型,讓產生這些點的概率最大即可(最大似然估計),公式化即為
極大似然函數
明顯對於連乘的問題取對數變為連加問題
將偏導數等於0,求得\((u^{'},\sigma^{'})\)
這部分可跳過。
以下為 \(u\) 的推導過程,(字很丑,請忽略,,,)
打開鏈接即可,,,csdn總是加載失敗,,emmm
http://img.caohongchuan.cn/picgo/20190708203542.jpg
得出
分別求出attribute0和attribute1,得出
這即為藍色點的中心。
其各自的方差為:
上面的推導過程都是利用1元高斯分布求得的,但是本文有2個自變量,\(attribute_0,attribute_1\),需要使用多元高斯分布。可參考博客
多元高斯分布
其中\(\sum\)為協方差矩陣,\(n\)為自變量的個數,\(u_x\)為每個自變量的均值
其中各個變量的均值和方差在一元高斯分布中已經求出。
之后,由貝葉斯公式
其中\(P(blue) = \frac{N(blue)}{N(blue)+N(green)},P(green) = \frac{N(green)}{N(blue)+N(green)}\), 其中的\(P(x|blue),P(x|green)\)的概率由我們上方假定的高斯分布模型求出。
至此為止,我們已經能夠得到 \(P(blue|x)\) 即選擇一個x,其為blue類的概率。假設此概率大於0.5,我們就認為這個x屬於blue類,否則不屬於。
畫出blue的高斯分布等高線
這樣就可以求出兩類的分界線。或許概率為0.6為分界線對上圖更加合適(僅僅根據圖做出的判斷)一般都選0.5作為分界點。
分類問題結束。
總結一下 : 生成式模型最大的特點是假設了各個變量之間的聯合分布函數\(f(attribute_0,attribue_1)\)——其服從高斯分布且兩者相互獨立。之后再利用貝葉斯公式,求得對於每個點其為blue類的概率。
對於判別式模型將利用Logistics Regression進行講解
判別式模型講解鏈接https://www.cnblogs.com/caohongchuan/p/11211087.html
附上本文的代碼(代碼寫的很爛,而且沒有注釋,,請大佬們勿笑,,)
為自己洗白一發,,這個代碼沒有通用性,所以我也懶得美化了,,就這樣,,
# classification
# @author Hongchuan CAO
# @date 2019-7-8
from numpy.core.multiarray import ndarray
from sklearn import datasets
import numpy as np
import matplotlib.pyplot as plt
import copy
class Genrative:
def __init__(self):
self.iris = datasets.load_iris()
self.part = [[],[],[]]
def classify(self):
for i in range(len(self.iris.target)):
self.part[self.iris.target[i]].append(self.iris.data[i,:2])
# change list to array
for i in range(0,3):
self.part[i] = np.array(self.part[i])
def cal_par(self):
u0 = np.mean(self.part[0],axis=0)
u1 = np.mean(self.part[1],axis=0)
record = copy.deepcopy(self.part)
for i in range(len(record[0])):
record[0][i][0] = (record[0][i][0] - u0[0])**2
record[0][i][1] = (record[0][i][1] - u0[1])**2
v0 = np.mean(record[0],axis=0)
v1 = np.mean(record[1],axis=0)
self.u = u0
self.v = v0
self.uu = u1
self.vv = v1
def f1(self,xx):
u0 = self.u
v0 = self.v
summ = np.zeros([2,2])
summ[0][0] = v0[0]
summ[1][1] = v0[1]
xx = xx-u0
z = np.dot(np.dot(xx,np.linalg.inv(summ)),xx.T)
zz = np.sqrt(np.linalg.det(summ))
return 1.0/(zz*np.sqrt(2*np.pi)**2)*np.exp(-1/2*z)
def f2(self,xx):
u1 = self.uu
v1 = self.vv
summ = np.zeros([2,2])
summ[0][0] = v1[0]
summ[1][1] = v1[1]
xx = xx-u1
z = np.dot(np.dot(xx,np.linalg.inv(summ)),xx.T)
zz = np.sqrt(np.linalg.det(summ))
return 1.0/(zz*np.sqrt(2*np.pi)**2)*np.exp(-1/2*z)
def pobablity(self,xx):
p1 = len(self.part[0])/(len(self.part[0]+self.part[1]))
p2 = len(self.part[1])/(len(self.part[0]+self.part[1]))
return self.f1(xx)*p1/(self.f1(xx)*p1+self.f2(xx)*p2)
def plot1(self):
x_a = [x for x in np.arange(3,8,0.1)]
y_a = [y for y in np.arange(1,6,0.1)]
z_a = [[self.pobablity([xx,yy]) for xx in x_a] for yy in y_a]
print(z_a)
X,Y = np.meshgrid(x_a,y_a)
cntr1 = plt.contourf(X,Y,z_a)
plt.clabel(cntr1, colors='k', inline_spacing=3, fmt='%.1f', fontsize=10)
plt.plot(self.part[0][:,0], self.part[0][:,1], 'b.', label='0')
plt.plot(self.part[1][:,0], self.part[1][:,1], 'g.', label='1')
# plt.plot(self.part[2][:,0], self.part[2][:,1], 'r.', label='2')
plt.legend()
plt.xlabel('attribute0')
plt.ylabel('attribute1')
plt.show()
if __name__ == '__main__':
obj = Genrative()
obj.classify()
obj.cal_par()
obj.plot1()