此响应已从其原始形式进行了重大修改。我的原始回复的缺陷将在下面讨论,但是如果您想在进行大的编辑之前大致了解一下此回复的外观,请查看以下笔记本:https : //nbviewer.jupyter.org/github /dmarx/data_generation_demo/blob/54be78fb5b68218971d2568f1680b4f783c0a79a/demo.ipynb
P(X)P(X|Y)∝P(Y|X)P(X)P(Y|X)X
最大似然估计
...以及为什么它在这里不起作用
在我最初的回答中,我建议的技术是使用MCMC来执行最大似然估计。通常,MLE是找到条件概率“最佳”解决方案的好方法,但是这里存在一个问题:因为我们使用的是判别模型(在这种情况下为随机森林),所以我们相对于决策边界计算概率。谈论这样一个模型的“最佳”解决方案实际上是没有意义的,因为一旦我们离类边界足够远,该模型就将为所有事物预测它们。如果我们有足够的类,其中的一些类可能会完全“包围”,在这种情况下这将不是问题,但是我们数据边界上的类将被不一定可行的值“最大化”。
为了演示,我将利用一些方便的代码,您可以在此处找到GenerativeSampler
该代码,该类提供了包装原始响应中的代码的类,此更好的解决方案的一些其他代码以及我正在使用的其他一些功能(其中一些起作用) ,其中一些不是),我可能不会在这里讲到。
np.random.seed(123)
sampler = GenerativeSampler(model=RFC, X=X, y=y,
target_class=2,
prior=None,
class_err_prob=0.05, # <-- the score we use for candidates that aren't predicted as the target class
rw_std=.05, # <-- controls the step size of the random walk proposal
verbose=True,
use_empirical=False)
samples, _ = sampler.run_chain(n=5000)
burn = 1000
thin = 20
X_s = pca.transform(samples[burn::thin,:])
# Plot the iris data
col=['r','b','g']
for i in range(3):
plt.scatter(*X_r[y==i,:].T, c=col[i], marker='x')
plt.plot(*X_s.T, 'k')
plt.scatter(*X_s.T, c=np.arange(X_s.shape[0]))
plt.colorbar()
plt.show()
在此可视化中,x是真实数据,而我们感兴趣的类是绿色。线连接的点是我们绘制的样本,它们的颜色与采样的顺序相对应,其“变细”的序列位置由右侧的色条标签指定。
如您所见,采样器相当快地与数据分离,然后基本上与与任何实际观测值相对应的要素空间值相去甚远。显然这是一个问题。
我们作弊的一种方法是更改提案功能,以仅允许要素采用我们在数据中实际观察到的值。让我们尝试一下,看看它如何改变结果的行为。
np.random.seed(123)
sampler = GenerativeSampler(model=RFC, X=X, y=y,
target_class=2,
prior=None,
class_err_prob=0.05,
verbose=True,
use_empirical=True) # <-- magic happening under the hood
samples, _ = sampler.run_chain(n=5000)
X_s = pca.transform(samples[burn::thin,:])
# Constrain attention to just the target class this time
i=2
plt.scatter(*X_r[y==i,:].T, c='k', marker='x')
plt.scatter(*X_s.T, c='g', alpha=0.3)
#plt.colorbar()
plt.show()
sns.kdeplot(X_s, cmap=sns.dark_palette('green', as_cmap=True))
plt.scatter(*X_r[y==i,:].T, c='k', marker='x')
plt.show()
X
P(X)P(Y|X)P(X)P(Y|X)P(X)
输入贝叶斯规则
在您使我对这里的数学不再那么动摇之后,我就花了相当多的钱(因此我开始构建GenerativeSampler
东西),然后遇到了上面提出的问题。当我意识到这一点时,我真的感到非常愚蠢,但是显然您是在要求应用贝叶斯规则,我对此表示歉意,对此我深表歉意。
如果您不熟悉贝叶斯规则,则如下所示:
P(B|A)=P(A|B)P(B)P(A)
在许多应用程序中,分母是一个常数,用作缩放项以确保分子积分为1,因此通常会这样重申规则:
P(B|A)∝P(A|B)P(B)
或用简单的英语说:“后验与可能性成正比”。
看起来熟悉?现在怎么样:
P(X|Y)∝P(Y|X)P(X)
是的,这正是我们之前通过为MLE构造一个估计值(该锚定到观察到的数据分布)所做的工作。我从未考虑过贝叶斯规则,但是这很有意义,因此感谢您给我机会发掘这一新观点。
P(Y)
因此,在获得了需要结合数据先验知识的洞察力之后,让我们通过安装标准KDE并查看其如何改变结果来做到这一点。
np.random.seed(123)
sampler = GenerativeSampler(model=RFC, X=X, y=y,
target_class=2,
prior='kde', # <-- the new hotness
class_err_prob=0.05,
rw_std=.05, # <-- back to the random walk proposal
verbose=True,
use_empirical=False)
samples, _ = sampler.run_chain(n=5000)
burn = 1000
thin = 20
X_s = pca.transform(samples[burn::thin,:])
# Plot the iris data
col=['r','b','g']
for i in range(3):
plt.scatter(*X_r[y==i,:].T, c=col[i], marker='x')
plt.plot(*X_s.T, 'k--')
plt.scatter(*X_s.T, c=np.arange(X_s.shape[0]), alpha=0.2)
plt.colorbar()
plt.show()
XP(X|Y)
# MAP estimation
from sklearn.neighbors import KernelDensity
from sklearn.model_selection import GridSearchCV
from scipy.optimize import minimize
grid = GridSearchCV(KernelDensity(), {'bandwidth': np.linspace(0.1, 1.0, 30)}, cv=10, refit=True)
kde = grid.fit(samples[burn::thin,:]).best_estimator_
def map_objective(x):
try:
score = kde.score_samples(x)
except ValueError:
score = kde.score_samples(x.reshape(1,-1))
return -score
x_map = minimize(map_objective, samples[-1,:].reshape(1,-1)).x
print(x_map)
x_map_r = pca.transform(x_map.reshape(1,-1))[0]
col=['r','b','g']
for i in range(3):
plt.scatter(*X_r[y==i,:].T, c=col[i], marker='x')
sns.kdeplot(*X_s.T, cmap=sns.dark_palette('green', as_cmap=True))
plt.scatter(x_map_r[0], x_map_r[1], c='k', marker='x', s=150)
plt.show()
到此为止:黑色的大“ X”是我们的MAP估计(那些轮廓是后验的KDE)。