def _map(self, prior, samples, weights, out, initializations): """ Emit computation of the estimated maximum-likelihood parameter. """ # mise en place K = self._model._K N = samples.shape[0] # generate some initial parameters self._map_initialize(prior, samples, weights, out, initializations) # run EM until convergence total = qy.stack_allocate(float) component_ll = qy.stack_allocate(float) this_r_KN = StridedArray.heap_allocated(float, (K, N)) last_r_KN = StridedArray.heap_allocated(float, (K, N)) this_r_KN_data = Variable.set_to(this_r_KN.data) last_r_KN_data = Variable.set_to(last_r_KN.data) @qy.for_(self._model._iterations) def _(i): # compute responsibilities r_KN = this_r_KN.using(this_r_KN_data.value) @qy.for_(N) def _(n): sample = samples.at(n) qy.value_from_any(-numpy.inf).store(total) @qy.for_(K) def _(k): responsibility = r_KN.at(k, n).data self._sub_emitter.ll( StridedArray.from_typed_pointer( out.at(k).data.gep(0, 1)), StridedArray.from_typed_pointer(sample.data), responsibility, ) log_add_double(total.load(), responsibility.load()).store(total) total_value = total.load() @qy.if_else(total_value == -numpy.inf) def _(then): if then: @qy.for_(K) def _(k): qy.value_from_any(1.0 / K).store( r_KN.at(k, n).data) else: @qy.for_(K) def _(k): responsibility = r_KN.at(k, n).data qy.exp(responsibility.load() - total_value).store(responsibility) # estimate new mixture and component parameters @qy.for_(K) def _(k): component = out.at(k).data self._sub_emitter.map( prior.at(k), samples, r_KN.at(k), StridedArray.from_typed_pointer(component.gep(0, 1)), ) qy.value_from_any(0.0).store(total) @qy.for_(N) def _(n): (total.load() + r_KN.at(k, n).data.load()).store(total) (total.load() / float(N)).store(component.gep(0, 0)) # check for termination last_r_KN = this_r_KN.using(last_r_KN_data.value) @qy.if_(i > 0) def _(): qy.value_from_any(0.0).store(total) @qy.for_(K) def _(k): @qy.for_(N) def _(n): delta = r_KN.at(k, n).data.load() - last_r_KN.at( k, n).data.load() (total.load() + abs(delta)).store(total) @qy.if_(total.load() < 1e-12) def _(): qy.break_() total_delta = total.load() # swap the responsibility matrices temp_r_KN_data_value = this_r_KN_data.value this_r_KN_data.set(last_r_KN_data.value) last_r_KN_data.set(temp_r_KN_data_value) # compute the ll at this step @qy.for_(N) def _(n): sample = samples.at(n) total_ll = total.load() qy.value_from_any(-numpy.inf).store(total) @qy.for_(K) def _(k): self._sub_emitter.ll( StridedArray.from_typed_pointer( out.at(k).data.gep(0, 1)), StridedArray.from_typed_pointer(sample.data), component_ll, ) log_add_double( total.load(), qy.log(out.at(k).data.gep(0, 0).load()) + component_ll.load(), ) \ .store(total) (total_ll + total.load()).store(total) total_ll = total.load() # be informative qy.py_printf("after EM step %i: delta %s; ll %s\n", i, total_delta, total_ll) # clean up qy.heap_free(this_r_KN.data) qy.heap_free(last_r_KN.data) qy.return_()
def _map(self, prior, samples, weights, out, initializations): """ Emit computation of the estimated maximum-likelihood parameter. """ # mise en place K = self._model._K N = samples.shape[0] # generate some initial parameters self._map_initialize(prior, samples, weights, out, initializations) # run EM until convergence total = qy.stack_allocate(float) component_ll = qy.stack_allocate(float) this_r_KN = StridedArray.heap_allocated(float, (K, N)) last_r_KN = StridedArray.heap_allocated(float, (K, N)) this_r_KN_data = Variable.set_to(this_r_KN.data) last_r_KN_data = Variable.set_to(last_r_KN.data) @qy.for_(self._model._iterations) def _(i): # compute responsibilities r_KN = this_r_KN.using(this_r_KN_data.value) @qy.for_(N) def _(n): sample = samples.at(n) qy.value_from_any(-numpy.inf).store(total) @qy.for_(K) def _(k): responsibility = r_KN.at(k, n).data self._sub_emitter.ll( StridedArray.from_typed_pointer(out.at(k).data.gep(0, 1)), StridedArray.from_typed_pointer(sample.data), responsibility, ) log_add_double(total.load(), responsibility.load()).store(total) total_value = total.load() @qy.if_else(total_value == -numpy.inf) def _(then): if then: @qy.for_(K) def _(k): qy.value_from_any(1.0 / K).store(r_KN.at(k, n).data) else: @qy.for_(K) def _(k): responsibility = r_KN.at(k, n).data qy.exp(responsibility.load() - total_value).store(responsibility) # estimate new mixture and component parameters @qy.for_(K) def _(k): component = out.at(k).data self._sub_emitter.map( prior.at(k), samples, r_KN.at(k), StridedArray.from_typed_pointer(component.gep(0, 1)), ) qy.value_from_any(0.0).store(total) @qy.for_(N) def _(n): (total.load() + r_KN.at(k, n).data.load()).store(total) (total.load() / float(N)).store(component.gep(0, 0)) # check for termination last_r_KN = this_r_KN.using(last_r_KN_data.value) @qy.if_(i > 0) def _(): qy.value_from_any(0.0).store(total) @qy.for_(K) def _(k): @qy.for_(N) def _(n): delta = r_KN.at(k, n).data.load() - last_r_KN.at(k, n).data.load() (total.load() + abs(delta)).store(total) @qy.if_(total.load() < 1e-12) def _(): qy.break_() total_delta = total.load() # swap the responsibility matrices temp_r_KN_data_value = this_r_KN_data.value this_r_KN_data.set(last_r_KN_data.value) last_r_KN_data.set(temp_r_KN_data_value) # compute the ll at this step @qy.for_(N) def _(n): sample = samples.at(n) total_ll = total.load() qy.value_from_any(-numpy.inf).store(total) @qy.for_(K) def _(k): self._sub_emitter.ll( StridedArray.from_typed_pointer(out.at(k).data.gep(0, 1)), StridedArray.from_typed_pointer(sample.data), component_ll, ) log_add_double( total.load(), qy.log(out.at(k).data.gep(0, 0).load()) + component_ll.load(), ) \ .store(total) (total_ll + total.load()).store(total) total_ll = total.load() # be informative qy.py_printf("after EM step %i: delta %s; ll %s\n", i, total_delta, total_ll) # clean up qy.heap_free(this_r_KN.data) qy.heap_free(last_r_KN.data) qy.return_()
def _map_initialize(self, prior, samples, weights, out, initializations): """ Emit parameter initialization for EM. """ # generate a random initial component assignment K = self._model._K N = samples.shape[0] total = qy.stack_allocate(float) best_ll = qy.stack_allocate(float, -numpy.inf) assigns = StridedArray.heap_allocated(int, (K, )) best_assigns = StridedArray.heap_allocated(int, (K, )) @qy.for_(initializations) def _(i): @qy.for_(K) def _(k): # randomly assign the component j = qy.random_int(N) component = StridedArray.from_typed_pointer( out.at(k).data.gep(0, 1)) j.store(assigns.at(k).data) self._sub_emitter.map( prior.at(k), samples.at(j).envelop(), weights.at(j).envelop(), component, ) # compute our total likelihood qy.value_from_any(0.0).store(total) @qy.for_(N) def _(n): sample = samples.at(n) mixture_ll = total.load() qy.value_from_any(-numpy.inf).store(total) @qy.for_(K) def _(k): component_ll = total.load() self._sub_emitter.ll( StridedArray.from_typed_pointer( out.at(k).data.gep(0, 1)), sample, total, ) log_add_double(component_ll, total.load()).store(total) (mixture_ll + total.load()).store(total) # best observed so far? @qy.if_(total.load() >= best_ll.load()) def _(): total.load().store(best_ll) @qy.for_(K) def _(k): assigns.at(k).data.load().store(best_assigns.at(k).data) # recompute the best observed assignment @qy.for_(K) def _(k): j = assigns.at(k).data.load() self._sub_emitter.ml( samples.at(j).envelop(), weights.at(j).envelop(), StridedArray.from_typed_pointer(out.at(k).data.gep(0, 1)), ) qy.heap_free(assigns.data) qy.heap_free(best_assigns.data) # generate random initial component weights @qy.for_(K) def _(k): r = qy.random() r.store(out.at(k).data.gep(0, 0)) (total.load() + r).store(total) @qy.for_(K) def _(k): p = out.at(k).data.gep(0, 0) (p.load() / total.load()).store(p)
def _map_initialize(self, prior, samples, weights, out, initializations): """ Emit parameter initialization for EM. """ # generate a random initial component assignment K = self._model._K N = samples.shape[0] total = qy.stack_allocate(float) best_ll = qy.stack_allocate(float, -numpy.inf) assigns = StridedArray.heap_allocated(int, (K,)) best_assigns = StridedArray.heap_allocated(int, (K,)) @qy.for_(initializations) def _(i): @qy.for_(K) def _(k): # randomly assign the component j = qy.random_int(N) component = StridedArray.from_typed_pointer(out.at(k).data.gep(0, 1)) j.store(assigns.at(k).data) self._sub_emitter.map( prior.at(k), samples.at(j).envelop(), weights.at(j).envelop(), component, ) # compute our total likelihood qy.value_from_any(0.0).store(total) @qy.for_(N) def _(n): sample = samples.at(n) mixture_ll = total.load() qy.value_from_any(-numpy.inf).store(total) @qy.for_(K) def _(k): component_ll = total.load() self._sub_emitter.ll( StridedArray.from_typed_pointer(out.at(k).data.gep(0, 1)), sample, total, ) log_add_double(component_ll, total.load()).store(total) (mixture_ll + total.load()).store(total) # best observed so far? @qy.if_(total.load() >= best_ll.load()) def _(): total.load().store(best_ll) @qy.for_(K) def _(k): assigns.at(k).data.load().store(best_assigns.at(k).data) # recompute the best observed assignment @qy.for_(K) def _(k): j = assigns.at(k).data.load() self._sub_emitter.ml( samples.at(j).envelop(), weights.at(j).envelop(), StridedArray.from_typed_pointer(out.at(k).data.gep(0, 1)), ) qy.heap_free(assigns.data) qy.heap_free(best_assigns.data) # generate random initial component weights @qy.for_(K) def _(k): r = qy.random() r.store(out.at(k).data.gep(0, 0)) (total.load() + r).store(total) @qy.for_(K) def _(k): p = out.at(k).data.gep(0, 0) (p.load() / total.load()).store(p)