@@ -86,12 +86,13 @@ def __init__(self, vars=None, num_particles=10, max_stages=5000, chunk="auto", m
86
86
87
87
def astep (self , _ ):
88
88
bart = self .bart
89
+ inv_link = bart .inv_link
89
90
num_observations = bart .num_observations
90
91
variable_inclusion = np .zeros (bart .num_variates , dtype = "int" )
91
92
92
93
# For the tunning phase we restrict max_stages to a low number, otherwise it is almost sure
93
94
# we will reach max_stages given that our first set of m trees is not good at all.
94
- # Can set max_stages as a function of the number of variables/dimensions?
95
+ # Can set max_stages as a function of the number of variables/dimensions? XXX
95
96
if self .tune :
96
97
max_stages = 5
97
98
else :
@@ -105,10 +106,11 @@ def astep(self, _):
105
106
break
106
107
self .idx += 1
107
108
tree = bart .trees [idx ]
108
- R_j = bart .get_residuals_loo (tree )
109
+ old_prediction = tree .predict_output ()
110
+ bart .sum_trees_output -= old_prediction
109
111
# Generate an initial set of SMC particles
110
112
# at the end of the algorithm we return one of these particles as the new tree
111
- particles = self .init_particles (tree .tree_id , R_j , num_observations )
113
+ particles = self .init_particles (tree .tree_id , num_observations , inv_link )
112
114
113
115
for t in range (1 , max_stages ):
114
116
# Get old particle at stage t
@@ -119,13 +121,12 @@ def astep(self, _):
119
121
# Update weights. Since the prior is used as the proposal,the weights
120
122
# are updated additively as the ratio of the new and old log_likelihoods
121
123
for p_idx , p in enumerate (particles ):
122
- new_likelihood = self .likelihood_logp (p .tree .predict_output (num_observations ))
124
+ new_likelihood = self .likelihood_logp (inv_link ( p .tree .predict_output () ))
123
125
p .log_weight += new_likelihood - p .old_likelihood_logp
124
126
p .old_likelihood_logp = new_likelihood
125
127
126
128
# Normalize weights
127
129
W , normalized_weights = self .normalize (particles )
128
-
129
130
# Resample all but first particle
130
131
re_n_w = normalized_weights [1 :] / normalized_weights [1 :].sum ()
131
132
new_indices = np .random .choice (self .indices , size = len (self .indices ), p = re_n_w )
@@ -148,8 +149,8 @@ def astep(self, _):
148
149
new_tree = np .random .choice (particles , p = normalized_weights )
149
150
self .old_trees_particles_list [tree .tree_id ] = new_tree
150
151
bart .trees [idx ] = new_tree .tree
151
- new_prediction = new_tree .tree .predict_output (num_observations )
152
- bart .sum_trees_output = bart . Y - R_j + new_prediction
152
+ new_prediction = new_tree .tree .predict_output ()
153
+ bart .sum_trees_output += new_prediction
153
154
154
155
if not self .tune :
155
156
self .iter += 1
@@ -161,8 +162,7 @@ def astep(self, _):
161
162
variable_inclusion [index ] += 1
162
163
163
164
stats = {"variable_inclusion" : variable_inclusion }
164
-
165
- return bart .sum_trees_output , [stats ]
165
+ return inv_link (bart .sum_trees_output ), [stats ]
166
166
167
167
@staticmethod
168
168
def competence (var , has_grad ):
@@ -194,31 +194,26 @@ def get_old_tree_particle(self, tree_id, t):
194
194
old_tree_particle .set_particle_to_step (t )
195
195
return old_tree_particle
196
196
197
- def init_particles (self , tree_id , R_j , num_observations ):
197
+ def init_particles (self , tree_id , num_observations , inv_link ):
198
198
"""
199
199
Initialize particles
200
200
"""
201
201
# The first particle is from the tree we are trying to replace
202
202
prev_tree = self .get_old_tree_particle (tree_id , 0 )
203
- likelihood = self .likelihood_logp (prev_tree .tree .predict_output (num_observations ))
203
+ likelihood = self .likelihood_logp (inv_link ( prev_tree .tree .predict_output () ))
204
204
prev_tree .old_likelihood_logp = likelihood
205
205
prev_tree .log_weight = likelihood - self .log_num_particles
206
206
particles = [prev_tree ]
207
207
208
208
# The rest of the particles are identically initialized
209
- initial_value_leaf_nodes = R_j .mean ()
210
209
initial_idx_data_points_leaf_nodes = np .arange (num_observations , dtype = "int32" )
211
210
new_tree = Tree .init_tree (
212
211
tree_id = tree_id ,
213
- leaf_node_value = initial_value_leaf_nodes ,
212
+ leaf_node_value = 0 ,
214
213
idx_data_points = initial_idx_data_points_leaf_nodes ,
215
214
)
216
- likelihood_logp = self .likelihood_logp (new_tree .predict_output (num_observations ))
217
- log_weight = likelihood_logp - self .log_num_particles
218
215
for i in range (1 , self .num_particles ):
219
- particles .append (
220
- ParticleTree (new_tree , self .bart .prior_prob_leaf_node , log_weight , likelihood_logp )
221
- )
216
+ particles .append (ParticleTree (new_tree , self .bart .prior_prob_leaf_node , 0 , 0 ))
222
217
223
218
return np .array (particles )
224
219
@@ -237,10 +232,10 @@ class ParticleTree:
237
232
238
233
def __init__ (self , tree , prior_prob_leaf_node , log_weight = 0 , likelihood = 0 ):
239
234
self .tree = tree .copy () # keeps the tree that we care at the moment
240
- self .expansion_nodes = tree . idx_leaf_nodes . copy () # This should be the array [0]
235
+ self .expansion_nodes = [0 ]
241
236
self .tree_history = [self .tree ]
242
237
self .expansion_nodes_history = [self .expansion_nodes ]
243
- self .log_weight = 0
238
+ self .log_weight = log_weight
244
239
self .prior_prob_leaf_node = prior_prob_leaf_node
245
240
self .old_likelihood_logp = likelihood
246
241
self .used_variates = []
@@ -253,7 +248,8 @@ def sample_tree_sequential(self, bart):
253
248
254
249
if prob_leaf < np .random .random ():
255
250
grow_successful , index_selected_predictor = bart .grow_tree (
256
- self .tree , index_leaf_node
251
+ self .tree ,
252
+ index_leaf_node ,
257
253
)
258
254
if grow_successful :
259
255
# Add new leaf nodes indexes
0 commit comments