Iti0210w101demo
Allikas: Lambda
Peidetud Markovi mudeli näide loengust
Parameetrid (ülemineku- ja emissioonitõenäosused) ja abifunktsioon valimi võtmiseks.
import random
prior = {
"cheat" : 0.5,
"fair" : 0.5
}
transition = {
"cheat" : {"fair" : 0.2, "cheat" : 0.8},
"fair" : {"fair" : 0.7, "cheat" : 0.3},
}
emission = {
"fair" : { "1" : 1/6, "2" : 1/6,"3" : 1/6,"4" : 1/6,"5" : 1/6,"6" : 1/6},
"cheat" : { "1" : 0, "2" : 0,"3" : 0,"4" : 0,"5" : 0.2,"6" : 0.8}
}
def sample(d):
population = []
weights = []
for k, v in d.items():
population.append(k)
weights.append(v)
return random.choices(population, weights=weights)[0]
Genereerime mudeliga juhusliku seeria.
X = []
E = []
for i in range(50):
if i == 0:
Xi = sample(prior)
print("picking", Xi, "die")
else:
prev = X[-1]
Xi = sample(transition[prev])
if prev != Xi:
print("swapping die to", Xi)
Ei = sample(emission[Xi])
print(Ei)
X.append(Xi)
E.append(Ei)
Edasi-tagasi sõnumite arvutamine ja normaliseerimine:
# let's use a tuple for distributions
# { "fair": 0.6, "cheat": 0.4} ==> (0.6, 0.4)
def forward(fw_prev, e_k):
# returns distribution over X_{k+1}
result = []
for x_k in ["fair", "cheat"]:
S = 0
for i, x_prev in enumerate(["fair", "cheat"]):
S += transition[x_prev][x_k] * fw_prev[i]
result.append(S * emission[x_k][e_k])
res_S = sum(result)
return tuple([r/res_S for r in result])
def backward(b_next, e_next):
result = []
for x_k in ["fair", "cheat"]:
S = 0
for i, x_next in enumerate(["fair", "cheat"]):
S += emission[x_next][e_next] * transition[x_k][x_next] * b_next[i]
result.append(S)
return tuple(result)
def normalize(vect):
S = sum(vect)
return tuple([v/S for v in vect])
Peidetud muutujate leidmine.
def smoothed_estimate(E, t=50):
f_prev = (prior["fair"], prior["cheat"])
f_X = []
for k in range(t):
f_k = forward(f_prev, E[k])
f_X.append(f_k)
f_prev = f_k
b = (0.5, 0.5)
smooth_X = []
for k in range(t-1, -1, -1):
smooth_X.append(normalize([f_X[k][0] * b[0], f_X[k][1] * b[1]]))
b = backward(b, E[k])
smooth_X.reverse()
return smooth_X
s_X = smoothed_estimate(E)
for i in range(50):
print(X[i], E[i], "cheat probability", s_X[i][1])
Tulemuse hindamine.
def evaluate(guess_X, real_X, threshold=0.7):
TP = 0
FN = 0
FP = 0
for i in range(len(guess_X)):
if guess_X[i][1] > threshold:
if real_X[i] == "cheat":
TP += 1
else:
FP += 1
else:
if real_X[i] == "cheat":
FN += 1
print("")
print("Cheating caught {:.0f}%".format((TP/(TP+FN))*100))
print("False accusations {:.0f}%".format((FP/(TP+FP))*100))
evaluate(s_X, X)
EM-algoritmiga üleminekujaotuse leidmine.
transition_orig = transition
transition = {}
for x in ["fair", "cheat"]:
p = random.random()
transition[x] = {"fair": p, "cheat": 1-p}
from collections import defaultdict
def em(E, iters=100):
for i in range(iters):
expected_X = smoothed_estimate(E)
virtual_t = {"fair" : defaultdict(float),
"cheat" : defaultdict(float)}
virtual_N = {"fair" : 0.0, "cheat" : 0.0}
for j in range(len(E)-1):
virtual_N["fair"] += expected_X[j][0]
virtual_t["fair"]["fair"] += expected_X[j][0] * expected_X[j+1][0]
virtual_t["cheat"]["fair"] += expected_X[j][1] * expected_X[j+1][0]
virtual_N["cheat"] = len(E) - 1 - virtual_N["fair"]
for x in ["fair", "cheat"]:
p = virtual_t[x]["fair"]/virtual_N[x]
transition[x] = {"fair": p, "cheat": 1-p}
print(transition)
return expected_X
em_X = em(E, 20)
evaluate(em_X, X)