Generative Model/Generative Model
[Implementation] MCMC
밤 편지
2024. 3. 24. 18:02
수식을 이해해도 다소 막연했던 알고리즘은 실제 구현을 해서 돌려보면, 와닿는 경우가 많다.
1. Gibbs Sampling
automatic_samples = np.random.multivariate_normal([0,0],[[1,0.5],[0.5,1]], 10000)
plt.scatter(automatic_samples[:,0], automatic_samples[:,1], s=0.9);
samples = {'x':[1], 'y':[-1]}
num_samples = 10000
for _ in range(num_samples):
curr_y = samples['y'][-1]
new_x = np.random.normal(curr_y/2, np.sqrt(3/4))
new_y = np.random.normal(new_x/2, np.sqrt(3/4))
samples['x'].append(new_x)
samples['y'].append(new_y)
plt.scatter(samples['x'], samples['y'], s=0.9);
2. Accept-Reject (g(x)와 M을 달리하며 experiment)
# this function is the numerator of the target distribution
def f(x):
if x >= 1:
return np.exp(-(x-1)/2) + np.exp(-(x-1)**2)
else:
return np.exp((x-1)/3) + np.exp((x-1)**3)
# normal PDF
def g(x, mu, sigma):
return (1/(np.sqrt(2*np.pi) * sigma)) * np.exp(-0.5*((x-mu)/sigma)**2)
NORM_CONST = 7.16556
x_vals = np.arange(-5,15, .1)
f_vals = [f(x) for x in x_vals]
p_vals = [f/NORM_CONST for f in f_vals]
plt.figure(figsize=(9,4))
plt.plot(x_vals, f_vals)
plt.plot(x_vals, p_vals)
plt.legend(['f(x)', 'p(x)'], fontsize=19)
plt.xlabel('x', fontsize=19)
plt.ylabel('f(x)', fontsize=19)
plt.axvline(1, color='r', linestyle='--')
plt.show()
TRUE_EXPECTATION = 1.94709 / NORM_CONST
print(TRUE_EXPECTATION)
x_vals = np.arange(-30, 30, .1)
f_vals = [f(x) for x in x_vals]
g_vals = g(x_vals, 1, 4)
M = 75
plt.figure(figsize=(9,4))
plt.plot(x_vals, f_vals)
plt.plot(x_vals, M*g_vals)
plt.xlabel('x', fontsize=19)
plt.ylabel('Density', fontsize=19)
plt.legend(['f(x)', 'Mg(x)'], fontsize=19)
plt.title("M=%s" %M, fontsize=19)
plt.show()
samples = []
N = 1000000
for _ in range(N):
# get a candidate
candidate = np.random.normal(1, 4)
# calculate probability of accepting this sample
prob_accept = f(candidate) / (M*g(candidate, 1, 4))
# accept sample with this probability
if np.random.random() < prob_accept:
samples.append(candidate)
print("Num Samples Collected: %s" %len(samples))
print("Efficiency: %s"%round(len(samples) / N, 3))
plt.figure(figsize=(9,4))
plt.hist(samples, bins=200, density=True, alpha=.6)
plt.xlabel('x', fontsize=19)
plt.ylabel('Density', fontsize=19)
plt.plot(x_vals, [f/NORM_CONST for f in f_vals], linewidth=1, color='r')
plt.xlim(-15, 15)
plt.title('Empirical Expectation Value: %s\nTrue Expectation Value: %s'
%(round(np.mean(samples), 2), round(np.mean(TRUE_EXPECTATION), 2)), fontsize=19)
plt.show()
3. Metropolis Algorithm with N(x_prev, 4)
samples = [1]
num_accept = 0
for _ in range(N):
# sample candidate from normal distribution
candidate = np.random.normal(samples[-1], 4)
# calculate probability of accepting this candidate
prob = min(1, f(candidate) / f(samples[-1]))
# accept with the calculated probability
if np.random.random() < prob:
samples.append(candidate)
num_accept += 1
# otherwise report current sample again
else:
samples.append(samples[-1])
burn_in = 1000
retained_samples = samples[burn_in+1:]
print("Num Samples Collected: %s" %len(retained_samples))
print("Efficiency: %s" %round(len(retained_samples) / N, 3))
print("Fraction Acceptances: %s" %(num_accept / N))
plt.figure(figsize=(9,4))
plt.hist(retained_samples, bins=200, density=True, alpha=.6)
plt.xlabel('x',fontsize=19)
plt.ylabel('Density', fontsize=19)
plt.plot(x_vals, [f/NORM_CONST for f in f_vals], linewidth=1, color='r')
plt.xlim(-15, 15)
plt.title("Empirical Expectation Value: %s\nTrue Expectation Value: %s"
%(round(np.mean(retained_samples), 2), round(np.mean(TRUE_EXPECTATION), 2)), fontsize=19)
plt.show()
plt.figure(figsize=(6,6))
plt.scatter(retained_samples[:-1], retained_samples[1:], s=1)
plt.xlabel('Previous Sample', fontsize=14)
plt.ylabel('Current Sample', fontsize=14)
corr = round(pearsonr(samples[:-1], samples[1:])[0], 2)
plt.title('Correlation: %s' %corr, fontsize=19)
plt.show()