在Python中绘制两个多元高斯的决策边界
我会借用下面这个Stack Overflow问题中的图片来帮助我描述我的问题:
绘制两个多元高斯的决策边界
我有两个类别的二维点,我关心的是决策边界(或者叫判别函数)。
我已经写好了返回判别函数结果的函数(一个浮点值),这让我可以把样本分类到这两个模式中。
如果一个样本点是,比如说,x_i = [x, y]
我可以调用这些函数
如果 g1(x,y) > g2(x,y)
,那么它属于类别1;反之,如果
g1(x,y) <= g2(x,y)
,那么它属于类别2。
所以决策边界应该是在 g1(x,y) == g2(x,y)
的地方。
编辑:
希望下面的例子能帮助理解:
1) 假设我从数据集中取一个样本 x = [1, 2]
2) 然后我会调用,比如说:
g1(1,2)
--> 返回 0.345
g2(1,2)
--> 返回 0.453
--> 样本x属于类别2,因为 g2(1,2) > g1(1,2)
3) 现在对于决策边界,我有 g2(x,y) == g1(x,y)
,
或者
g1(x,y) - g2(x,y)
== 0
4) 我生成一系列 x
值,比如 1,2,3,4,5
,现在我想找到对应的 y
值,使得 g1(x,y) - g2(x,y) == 0
5) 然后我可以用这些 x,y
对来绘制决策边界。
在我上面链接的Stack Overflow帖子中,建议是:
你可以简单地绘制函数 f(x,y) := pdf1(x,y) > pdf2(x,y) 的等高线。所以你定义函数 f 为 1,当且仅当 pdf1(x,y) > pdf2(x,y)。这样,唯一的等高线就会出现在 pdf1(x,y) == pdf2(x,y) 的曲线上,这就是决策边界(判别函数)。如果你想定义一个“好”的函数,可以简单地设置
f(x,y) = sgn( pdf1(x,y) - pdf2(x,y) )
,绘制它的等高线图将得到完全相同的判别函数。
但是我该如何在Python和matplotlib中实现呢?我真的不知道该怎么写代码。非常感谢任何帮助!
编辑:
关于函数 g()
本身的更多信息:
def discr_func(x, y, cov_mat, mu_vec):
"""
Calculates the value of the discriminant function for a dx1 dimensional
sample given covariance matrix and mean vector.
Keyword arguments:
x_vec: A dx1 dimensional numpy array representing the sample.
cov_mat: dxd numpy array of the covariance matrix.
mu_vec: dx1 dimensional numpy array of the sample mean.
Returns a float value as result of the discriminant function.
"""
x_vec = np.array([[x],[y]])
W_i = (-1/2) * np.linalg.inv(cov_mat)
assert(W_i.shape[0] > 1 and W_i.shape[1] > 1), 'W_i must be a matrix'
w_i = np.linalg.inv(cov_mat).dot(mu_vec)
assert(w_i.shape[0] > 1 and w_i.shape[1] == 1), 'w_i must be a column vector'
omega_i_p1 = (((-1/2) * (mu_vec).T).dot(np.linalg.inv(cov_mat))).dot(mu_vec)
omega_i_p2 = (-1/2) * np.log(np.linalg.det(cov_mat))
omega_i = omega_i_p1 - omega_i_p2
assert(omega_i.shape == (1, 1)), 'omega_i must be a scalar'
g = ((x_vec.T).dot(W_i)).dot(x_vec) + (w_i.T).dot(x_vec) + omega_i
return float(g)
当我执行它时,它会返回一个浮点数,比如说:
discr_func(1, 2, cov_mat=cov_est_1, mu_vec=mu_est_1)
-3.726426544537969
如果我没有搞错的话,它应该是这个方程:
非常感谢你关于等高线的建议,不过我在实现它时遇到了问题:
import pylab as pl
X, Y = np.mgrid[-6:6:100j, -6:6:100j]
x = X.ravel()
y = Y.ravel()
p = (discr_func(x, y, cov_mat=cov_est_1, mu_vec=mu_est_1) -\
discr_func(x, y, cov_mat=cov_est_2, mu_vec=mu_est_2)).reshape(X.shape)
#pl.scatter(X_train[:, 0], X_train[:, 1])
pl.contour(X, Y, p, levels=[0])
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-192-28c1c8787237> in <module>()
5 y = Y.ravel()
6
----> 7 p = (discr_func(x, y, cov_mat=cov_est_1, mu_vec=mu_est_1) - discr_func(x, y, cov_mat=cov_est_2, mu_vec=mu_est_2)).reshape(X.shape)
8
9 #pl.scatter(X_train[:, 0], X_train[:, 1])
<ipython-input-184-fd2f8b7fad82> in discr_func(x, y, cov_mat, mu_vec)
25 assert(omega_i.shape == (1, 1)), 'omega_i must be a scalar'
26
---> 27 g = ((x_vec.T).dot(W_i)).dot(x_vec) + (w_i.T).dot(x_vec) + omega_i
28 return float(g)
ValueError: objects are not aligned
我感觉传递 .ravel()
列表与我设置这个函数的方式不太兼容……有什么建议吗?
1 个回答
计算 g1(x, y) - g2(x, y)
的结果,使用 mgrid[]
来生成数据,然后用 contour(..., levels=[0])
来画出等高线,这里有个例子。因为你没有提供任何示例数据和代码,所以我用 sklearn 来生成示例数据。你只需要看 #plot code from here
之后的代码:
import numpy as np
import pylab as pl
from sklearn import mixture
np.random.seed(0)
C1 = np.array([[3, -2.7], [1.5, 2.7]])
C2 = np.array([[1, 2.0], [-1.5, 1.7]])
X_train = np.r_[
np.random.multivariate_normal((-5, -5), C1, size=100),
np.random.multivariate_normal((5, 5), C2, size=100),
]
clf = mixture.GMM(n_components=2, covariance_type='full')
clf.fit(X_train)
#define g1(x, y) and g2(x, y)
def g1(x, y):
return clf.predict_proba(np.column_stack((x, y)))[:, 0]
def g2(x, y):
return clf.predict_proba(np.column_stack((x, y)))[:, 1]
#plot code from here
X, Y = np.mgrid[-15:15:100j, -15:15:100j]
x = X.ravel()
y = Y.ravel()
p = (g1(x, y) - g2(x, y)).reshape(X.shape)
pl.scatter(X_train[:, 0], X_train[:, 1])
pl.contour(X, Y, p, levels=[0])
这是输出结果: