def partial_EM(self, data, cond_muh_ijk, indices, weights=None, eps=1e-4, maxiter=10, verbose=0): (i, j, k) = indices converged = False previous_L = utilities.average( self.likelihood(data), weights=weights) / self.N mini_epochs = 0 if verbose: print('Partial EM %s, L = %.3f' % (mini_epochs, previous_L)) while not converged: if self.nature in ['Bernoulli', 'Spin']: f = np.dot(data, self.weights[[i, j, k], :].T) elif self.nature == 'Potts': f = cy_utilities.compute_output_C(data, self.weights[[i, j, k], :, :], np.zeros([ data.shape[0], 3], dtype=curr_float)) tmp = f - self.logZ[np.newaxis, [i, j, k]] tmp -= tmp.max(-1)[:, np.newaxis] cond_muh = np.exp(tmp) * self.muh[np.newaxis, [i, j, k]] cond_muh /= cond_muh.sum(-1)[:, np.newaxis] cond_muh *= cond_muh_ijk[:, np.newaxis] self.muh[[i, j, k]] = utilities.average(cond_muh, weights=weights) self.cum_muh = np.cumsum(self.muh) self.gh[[i, j, k]] = np.log(self.muh[[i, j, k]]) self.gh -= self.gh.mean() if self.nature == 'Bernoulli': self.cond_muv[[i, j, k]] = utilities.average_product( cond_muh, data, mean1=True, weights=weights) / self.muh[[i, j, k], np.newaxis] self.weights[[i, j, k]] = np.log( (self.cond_muv[[i, j, k]] + eps) / (1 - self.cond_muv[[i, j, k]] + eps)) self.logZ[[i, j, k]] = np.logaddexp( 0, self.weights[[i, j, k]]).sum(-1) elif self.nature == 'Spin': self.cond_muv[[i, j, k]] = utilities.average_product( cond_muh, data, mean1=True, weights=weights) / self.muh[[i, j, k], np.newaxis] self.weights[[i, j, k]] = 0.5 * np.log( (1 + self.cond_muv[[i, j, k]] + eps) / (1 - self.cond_muv[[i, j, k]] + eps)) self.logZ[[i, j, k]] = np.logaddexp( self.weights[[i, j, k]], -self.weights[[i, j, k]]).sum(-1) elif self.nature == 'Potts': self.cond_muv[[i, j, k]] = utilities.average_product( cond_muh, data, c2=self.n_c, mean1=True, weights=weights) / self.muh[[i, j, k], np.newaxis, np.newaxis] self.cum_cond_muv[[i, j, k]] = np.cumsum( self.cond_muv[[i, j, k]], axis=-1) self.weights[[i, j, k]] = np.log( self.cond_muv[[i, j, k]] + eps) self.weights[[i, j, k]] -= self.weights[[i, j, k] ].mean(-1)[:, :, np.newaxis] self.logZ[[i, j, k]] = utilities.logsumexp( self.weights[[i, j, k]], axis=-1).sum(-1) current_L = utilities.average( self.likelihood(data), weights=weights) / self.N mini_epochs += 1 converged = (mini_epochs >= maxiter) | ( np.abs(current_L - previous_L) < eps) previous_L = current_L.copy() if verbose: print('Partial EM %s, L = %.3f' % (mini_epochs, current_L)) return current_L
def likelihood(self, data): if data.ndim == 1: data = data[np.newaxis, :] if self.nature in ['Bernoulli', 'Spin']: f = np.dot(data, self.weights.T) elif self.nature == 'Potts': f = cy_utilities.compute_output_C(data, self.weights, np.zeros( [data.shape[0], self.M], dtype=curr_float)) return utilities.logsumexp((f - self.logZ[np.newaxis, :] + np.log(self.muh)[np.newaxis, :]), axis=1)
def likelihood_and_expectation(self, data): if self.nature in ['Bernoulli', 'Spin']: f = np.dot(data, self.weights.T) elif self.nature == 'Potts': f = cy_utilities.compute_output_C(data, self.weights, np.zeros( [data.shape[0], self.M], dtype=curr_float)) L = utilities.logsumexp( (f - self.logZ[np.newaxis, :] + np.log(self.muh)[np.newaxis, :]), axis=1) cond_muh = np.exp( f - self.logZ[np.newaxis, :]) * self.muh[np.newaxis, :] cond_muh /= cond_muh.sum(-1)[:, np.newaxis] return L, cond_muh
def expectation(self, data): if data.ndim == 1: data = data[np.newaxis, :] if self.nature in ['Bernoulli', 'Spin']: f = np.dot(data, self.weights.T) elif self.nature == 'Potts': f = cy_utilities.compute_output_C(data, self.weights, np.zeros( [data.shape[0], self.M], dtype=curr_float)) tmp = f - self.logZ[np.newaxis, :] tmp -= tmp.max(-1)[:, np.newaxis] cond_muh = np.exp(tmp) * self.muh[np.newaxis, :] cond_muh /= cond_muh.sum(-1)[:, np.newaxis] return cond_muh
def bilinear_form(W, X1, X2, c1=1, c2=1): xshape = X1.shape X1, xdim = reshape_in(X1, xdim=1) X2, xdim = reshape_in(X2, xdim=1) if (c1 == 1) & (c2 == 1): out = np.sum(X1 * np.tensordot(X2, W, axes=(-1, 1)), -1) elif (c1 == 1) & (c2 > 1): out = np.sum( X1 * cy_utilities.compute_output_C( X2, W, np.zeros(X1.shape, dtype=curr_float)), -1) elif (c1 > 1) & (c2 == 1): out = cy_utilities.dot_Potts2_C( X1.shape[1], c1, X1, np.tensordot(X2.astype(curr_float), W, (1, 1))) elif (c1 > 1) & (c2 > 1): out = cy_utilities.bilinear_form_Potts_C(X1, X2, W) return reshape_out(out, xshape, xdim=1)