-
Notifications
You must be signed in to change notification settings - Fork 0
/
functions.py
154 lines (121 loc) · 5.01 KB
/
functions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import random
import matplotlib.pyplot as plt
from IPython.display import set_matplotlib_formats
set_matplotlib_formats('svg', 'pdf')
from scipy.stats import beta
from scipy.special import logsumexp
from math import log, log1p, exp
def wta(items):
maxweight = max(items)
candidates = []
for i in range(len(items)):
if items[i] == maxweight:
candidates.append(i)
return random.choice(candidates)
def ca_monte(speaker_system, hearer_system, trials):
total = 0.
accumulator = []
for n in range(trials):
total += communicate(speaker_system, hearer_system,
random.randrange(len(speaker_system)))
accumulator.append(total / (n + 1))
return accumulator
def mutate(system):
for row_i in range(len(system)):
for column_i in range(len(system[0])):
if random.random() < mutation_rate:
system[row_i][column_i] = random.randint(0, mutation_max)
def pick_parent(population, sum_f):
accumulator = 0
r = random.uniform(0, sum_f)
for agent in population:
accumulator += fitness(agent)
if r < accumulator:
return agent
def log_subtract(x,y):
""" Substract logarithmic numbers """
return x + log1p(-exp(y - x))
def normalize_probs(probs):
""" Normalize probabilities """
total = sum(probs) #calculates the summed log probabilities
normedprobs = []
for p in probs:
normedprobs.append(p / total) #normalise - subtracting in the log domain
#equivalent to dividing in the normal domain
return normedprobs
def normalize_logprobs(logprobs):
""" Normalize Logarithmic probabilities """
logtotal = logsumexp(logprobs) #calculates the summed log probabilities
normedlogs = []
for logp in logprobs:
normedlogs.append(logp - logtotal) #normalise - subtracting in the log domain
#equivalent to dividing in the normal domain
return normedlogs
def log_roulette_wheel(normedlogs):
""" Given a normalized logarithmic distribution, get a random value """
r = log(random.random()) #generate a random number between 0 and 1, then convert to log
accumulator = normedlogs[0]
for i in range(len(normedlogs)):
if r < accumulator:
return i
accumulator = logsumexp([accumulator, normedlogs[i + 1]])
def calculate_prior(alpha):
""" Calculate prior distribution given an alpha """
logprior = []
for pW1 in possible_pW1:
logprior.append(beta.pdf(pW1, alpha, alpha))
return normalize_probs(logprior)
def calculate_logprior(alpha):
""" Calculate logarithmic prior distribution given an alpha """
logprior = []
for pW1 in possible_pW1:
logprior.append(beta.logpdf(pW1, alpha, alpha))
return normalize_logprobs(logprior)
def likelihood(data, logpW1):
""" Calculate the likelihood of a data given a probability distr """
logpW0 = log_subtract(log(1), logpW1) #probability of w0 is 1-prob of w1
logprobs = [logpW0, logpW1]
loglikelihoods = []
for d in data:
loglikelihood_this_item = logprobs[d] #d will be either 0 or 1,
#so can use as index
loglikelihoods.append(loglikelihood_this_item)
return sum(loglikelihoods) #summing log probabilities =
#multiply non-log probabilities
def posterior(data, prior):
""" Given data and a prior, calculate the posterior """
posterior_logprobs = []
for i in range(len(possible_logpW1)):
logpW1 = possible_logpW1[i]
logp_h = prior[i] #prior probability of this pW1
logp_d = likelihood(data, logpW1) #likelihood of data given this pW1
posterior_logprobs.append(logp_h + logp_d) #adding logs =
#multiplying non-logs
return normalize_logprobs(posterior_logprobs)
def iterate(alpha, n_productions, starting_count_w1, generations):
prior = calculate_logprior(alpha)
pW1_accumulator = []
data_accumulator = []
data = [1] * starting_count_w1 + [0] * (n_productions - starting_count_w1)
for generation in range(generations):
logpW1 = learn(data, prior)
data = produce(logpW1, n_productions)
pW1_accumulator.append(exp(logpW1))
data_accumulator.append(sum(data))
return pW1_accumulator, data_accumulator
def prior(language):
for i in range(len(priors)):
if languages[i] == language:
return priors[i]
def update_posterior(posterior, meaning, signal):
in_language = log(1 - noise)
out_of_language = log(noise / (len(signals) - 1))
new_posterior = []
for i in range(len(posterior)):
if (meaning, signal) in languages[i]:
new_posterior.append(posterior[i] + in_language)
else:
new_posterior.append(posterior[i] + out_of_language)
return normalize_logprobs(new_posterior)
def sample(posterior):
return languages[log_roulette_wheel(posterior)]