이 응답은 원래 형식에서 크게 수정되었습니다. 내 원래 응답의 결함에 대해서는 아래에서 설명하지만 크게 편집하기 전에이 응답이 어떻게 보이는지 보려면 다음 노트북을 살펴보십시오. https://nbviewer.jupyter.org/github /dmarx/data_generation_demo/blob/54be78fb5b68218971d2568f1680b4f783c0a79a/demo.ipynb
TL; DR : 사용 대략에 KDE (또는 당신의 선택의 절차) , 다음에서 샘플을 그릴 MCMC를 사용하여 P ( X | Y ) α P ( Y | X ) P ( X )피(X)피( X|와이) ∝ P( Y|엑스) P(X) 여기서 는 모델에서 제공합니다. 이 샘플에서 두 번째 KDE를 생성 한 샘플에 맞추고 KDE를 최대 사후 측정 (MAP) 추정값으로 최대화하는 관측 값을 선택 하여 "최적" X 를 추정 할 수 있습니다 .피(Y|엑스)엑스
최대 가능성 추정
... 그리고 왜 작동하지 않습니까?
필자의 원래 반응에서 내가 제안한 기술은 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)피( Y| 엑스)피( X)피( Y| 엑스) P( X)
베이 즈 규칙 입력
여기에서 수학에 손을 덜 대는 것으로 사냥을 한 후, 나는이 정도의 금액으로 놀았고 (따라서 GenerativeSampler
물건을 짓는 것), 나는 위에 제시 한 문제에 직면했습니다. 나는 이것을 깨달았을 때 정말 멍청한 느낌이 들었지만 분명히 베이 즈 규칙의 적용을 요구하는 것이 분명하고 일찍 기각 한 것에 대해 사과드립니다.
베이 규칙에 익숙하지 않은 경우 다음과 같습니다.
피( B | A ) = P( A | B ) P( B )피( A )
많은 애플리케이션에서 분모는 분자가 1에 통합되도록하기 위해 스케일링 항의 역할을하는 상수입니다. 따라서 규칙은 종종 다음과 같이 다시 정의됩니다.
피( B | A ) ∝ P( A | B ) P( B )
또는 일반 영어로 : "후부는 이전의 가능성에 비례합니다".
익숙해 보이나요? 지금은 어때:
피( X| 와이) ∝ P( Y| 엑스) P( X)
예, 이것은 데이터의 관측 된 분포에 고정 된 MLE에 대한 추정치를 구성하여 이전에 정확히 수행 한 것입니다. 베이 즈 규칙에 대해 이런 식으로 생각한 적이 없지만이 새로운 관점을 발견 할 수있는 기회를 주셔서 감사합니다.
피( 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()
엑스피( X| 와이)
# 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입니다).