Metropolis-Hastings-algoritmus
A Metropolis-Hastings-algoritmus egy Markov-lánc Monte Carlo (MCMC) módszer, amelyet valószínűségi eloszlásokból történő mintavételre használnak, ha közvetlen mintavétel nem lehetséges. Az algoritmus iteratív módon hoz létre egy Markov-láncot, amelynek egyensúlyi eloszlása a célzott eloszlás lesz.
Az alábbi példában egy normál eloszlásból mintavételezünk Metropolis-Hastings-algoritmussal.
import numpy as np
import matplotlib.pyplot as plt
def target_distribution(x):
"""Célzott valószínűségi eloszlás: Normál eloszlás."""
return np.exp(-0.5 * x**2) / np.sqrt(2 * np.pi)
def metropolis_hastings(target, proposal_std, iterations, start):
"""
Metropolis-Hastings algoritmus.
:param target: Célzott eloszlás függvénye.
:param proposal_std: Javaslateloszlás standard deviációja.
:param iterations: Iterációk száma.
:param start: Kezdőérték.
:return: Minták a célzott eloszlásból.
"""
samples =
current = start
for _ in range(iterations):
# Javasolt új érték
proposed = current + np.random.normal(0, proposal_std)
# Elfogadási arány kiszámítása
acceptance_ratio = target(proposed) / target(current)
# Véletlen szám generálása az elfogadáshoz
if np.random.uniform(0, 1) < acceptance_ratio:
current = proposed
samples.append(current)
return np.array(samples)
# Paraméterek
iterations = 10000
proposal_std = 1.0
start = 0.0
# Algoritmus futtatása
samples = metropolis_hastings(target_distribution, proposal_std, iterations, start)
# Eredmények megjelenítése
x = np.linspace(-5, 5, 1000)
plt.hist(samples, bins=50, density=True, alpha=0.6, label="MCMC Minták")
plt.plot(x, target_distribution(x), label="Célzott eloszlás", color="red")
plt.legend()
plt.title("Metropolis-Hastings mintavételezés")
plt.show()
A következő kód egy normál eloszlás mintavételét végzi el C++ segítségével.
#include <iostream>
#include <vector>
#include <cmath>
#include <random>
#include <algorithm>
using namespace std;
// Célzott valószínűségi eloszlás
double target_distribution(double x) {
return exp(-0.5 * x * x) / sqrt(2 * M_PI);
}
// Metropolis-Hastings algoritmus
vector<double> metropolis_hastings(int iterations, double proposal_std, double start) {
vector<double> samples;
double current = start;
random_device rd;
mt19937 gen(rd());
normal_distribution<> proposal_dist(0, proposal_std);
uniform_real_distribution<> uniform_dist(0, 1);
for (int i = 0; i < iterations; ++i) {
// Javasolt új érték
double proposed = current + proposal_dist(gen);
// Elfogadási arány kiszámítása
double acceptance_ratio = target_distribution(proposed) / target_distribution(current);
// Elfogadás vagy elutasítás
if (uniform_dist(gen) < acceptance_ratio) {
current = proposed;
}
samples.push_back(current);
}
return samples;
}
int main() {
int iterations = 10000;
double proposal_std = 1.0;
double start = 0.0;
// Mintavétel
vector<double> samples = metropolis_hastings(iterations, proposal_std, start);
// Alapvető statisztikák
double mean = accumulate(samples.begin(), samples.end(), 0.0) / samples.size();
cout << "Minták átlaga: " << mean << endl;
return 0;
}
A Metropolis-Hastings algoritmus hatékony és széles körben alkalmazható, különösen olyan helyzetekben, amikor bonyolult eloszlásokból kell mintát venni.