Fun with Factor Graph via DeepDive’s example Factor Graph

DeepDive’s Factor Graph Example

I tried creating factor graph described in this example
(no guarantee for the correctness of script)

if I add many (Jone smokes, john has cancer) = (1,1) data into the training data, I see the weight of factor1 becomes larger.

Also, the joint probability of (Jone smokes, john has cancer) = (1,1) becomes larger. So, looks ok

Learning algorithm is not efficient at all.

just calculate log likelihood for certain number of weight patterns in order to find the best weights giving maximum log likelihood

## Learning Factor Graph with brute force checking for Loglikelihood
##
import numpy as np
from scipy.stats import uniform
import matplotlib.pyplot as plt
import random
import math

def f1(a,b):
    # if the correct patterns happens, then return 1. Otherwiese, return 0
    if a == 1 and b == 1:
        return 1
    else:
        return 0

def f2(b):
    return b

# b=0 && !(a==1&&b==1) => measure=0
def measure(_w1,_w2,a,b):
    return _w1*f1(a,b)+_w2*f2(b)

def Probability(_w1,_w2,a,b):
    return measure(_w1,_w2,a,b) / (measure(_w1,_w2,0,0)+measure(_w1,_w2,1,0)+measure(_w1,_w2,0,1)+measure(_w1,_w2,1,1))

def loglikelihood(_w1,_w2, D):
    sum=0.0
    for line in D:
        prob = Probability(_w1,_w2,line[0],line[1])
        if prob != 0: sum += math.log(prob)

    return sum

def Marginal_A_Probability(_w1,_w2,a):
    return Probability(_w1,_w2,a,0)+Probability(_w1,_w2,a,1)

# P(B | A)
def conditional_B_prob(_w1,_w2,a,b):
    numerator = Probability(_w1,_w2,a,b)
    denominator = Marginal_A_Probability(_w1,_w2,a)

    return numerator / denominator

w1 = 0.5
w2 = 0.5

training_data =[
    [1,1],
    [1,1],
    [1,1],
    [1,0],
    [1,1],
    [1,1],
    [0,1],
    [0,1],
    [0,1],
    [0,1],
    [0,1],
    [0,1],
    [0,1],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [0,0],
    [1,0],
    [1,0],
    [1,0],
    [1,0],
    [1,0],
    [1,0],
    [1,0],
    [1,0]
]

## Bruteforce checking for log likelihood to find what weights are best
result = []
size = 1000
for w1_candidate in range(10, size, 10):
    for w2_candidate in range(10, size, 10):
        w1_candidate_val = w1_candidate/size
        w2_candidate_val = w2_candidate/size
        result.append([w1_candidate_val,w2_candidate_val,loglikelihood(w1_candidate_val,w2_candidate_val,training_data)])


mle = max(result, key=lambda x:x[2])

print("pseudo maximum likelihood estimate")
print(mle)

w1 = mle[0]
w2 = mle[1]
print("JOINT probability")
print(Probability(w1,w2,0,0))
print(Probability(w1,w2,1,1))
print(Probability(w1,w2,1,0))
print(Probability(w1,w2,0,1))

print("measurement")

print(measure(w1,w2,0,0))
print(measure(w1,w2,1,1))
print(measure(w1,w2,1,0))
print(measure(w1,w2,0,1))

print("conditional probability P(B|A)")

print(conditional_B_prob(w1,w2,0,1))
print(conditional_B_prob(w1,w2,1,1))
print(conditional_B_prob(w1,w2,1,0))
print(conditional_B_prob(w1,w2,0,1))