def optimize(self, E, iterations): M = self.M W, H = utils.init_wh(M, self.k) V, U = utils.init_wh(M, self.k) for i in range(iterations): print(i, utils.objective(M, W, H, E)) H, _ = admm_H_update(M, W, H, U, E, self.k) W, _ = admm_W_update(M, W, H, V, E, self.k) return W, H
def optimize(self, E, iterations): M = self.M W, H = utils.init_wh(M, self.k) for j in range(self.k): W[:, j] = W[:, j] / torch.norm(W[:, j]) H[j, :] = H[j, :] / torch.norm(H[j, :]) for i in range(iterations): print(i, utils.objective(M, W, H, E)) Dif = E * (M - W.mm(H)) for j in range(self.k): uj = W[:, j] vj = H[j, :] Dif = Dif + uj.reshape(-1, 1).mm(vj.reshape(1, -1)) u_nom = Dif.t().mv(uj).clamp_min(0) if torch.norm(u_nom) > 1e-18: vj = u_nom / (torch.norm(uj)**2) else: vj = torch.zeros_like(vj) v_nom = Dif.mv(vj).clamp_min(0) if torch.norm(v_nom) > 1e-18: uj = v_nom / (torch.norm(vj)**2) else: uj = torch.zeros_like(uj) W[:, j] = uj H[j, :] = vj Dif = Dif - uj.reshape(-1, 1).mm(vj.reshape(1, -1)) return W, H
def optimize(self, E, iterations): M = self.M W, H = utils.init_wh(M, self.k) for i in range(iterations): print(i, utils.objective(M, W, H, E)) pH = H H = H + self.step * (W.T.mm(E * (M - W.mm(H)))) H = utils.proj(H, pH, self.sticky) pW = W W = W + self.step * ((E * (M - W.mm(H))).mm(H.T)) W = utils.proj(W, pW, self.sticky) return W, H
def optimize(self, E, iterations): M = self.M W, H = utils.init_wh(M, self.k) for i in range(iterations): print(i, utils.objective(M, W, H, E)) # M_aux = (M - W.mm(H)) * E + W.mm(H) h_denom = W.t().mm(E * W.mm(H)) H = H * torch.where(h_denom < 1e-10, eps, W.t().mm(M) / h_denom) # TODO # M_aux = (M - W.mm(H)) * E + W.mm(H) w_denom = (E * W.mm(H)).mm(H.t()) W = W * torch.where(w_denom < 1e-10, eps, (M).mm(H.t()) / w_denom) # TODO return W, H
def optimize(self, E: Tensor, iterations): M = self.M W, H = utils.init_wh(M, self.k) mW, mH = 0, 0 for i in range(iterations): print(i, utils.objective(M, W, H, E)) prevW, prevH = W, H W = W + (1 - self.momentum) * mW H = H + (1 - self.momentum) * mH (gW, gH) = self.grad(M, W, H, E) # nW = np.random.normal(0, 0.01 * self.step, (n, self.k)) # nH = np.random.normal(0, 0.01 * self.step, (self.k, m)) W = utils.proj(W - self.step * gW, W, self.sticky) H = utils.proj(H - self.step * gH, H, self.sticky) mW = W - prevW mH = H - prevH return W, H
def optimize(self, iterations): M = self.M w, h = utils.init_wh(M, self.k) distance_type = self.distance_type w_aux = w.copy() h_aux = h.copy() # init dual variables for w, h, y dual_w = np.zeros_like(w) dual_h = np.zeros_like(h) v_aux = np.zeros_like(M) dual_v = np.zeros_like(M) reg_w = (0, 'nn') reg_h = (0, 'l2n') rho = 1 for i in range(iterations): print(i, utils.objective(M, w, h)) if distance_type == 'eu': h_aux = aux_update(h, dual_h, w_aux, M, None, rho, distance_type) w_aux = aux_update(w.T, dual_w.T, h_aux.T, M.T, None, rho, distance_type) w_aux = w_aux.T h = prox(reg_h[1], h_aux, dual_h, rho=rho, lambda_=reg_h[0]) w = prox(reg_w[1], w_aux.T, dual_w.T, rho=rho, lambda_=reg_w[0]) w = w.T elif distance_type == 'kl': h_aux = aux_update(h, dual_h, w_aux, v_aux, dual_v, rho, distance_type) w_aux = aux_update(w.T, dual_w.T, h_aux.T, v_aux.T, dual_v.T, rho, distance_type) w_aux = w_aux.T h = prox(reg_h[1], h_aux, dual_h, rho=rho, lambda_=reg_h[0]) w = prox(reg_w[1], w_aux.T, dual_w.T, rho=rho, lambda_=reg_w[0]) w = w.T v_bar = w_aux @ h_aux - dual_v v_aux = 1 / 2 * ((v_bar - 1) + np.sqrt((v_bar - 1)**2 + 4 * M)) dual_v = dual_v + v_aux - w_aux @ h_aux else: raise TypeError('Unknown loss type.') dual_h = dual_h + h - h_aux dual_w = dual_w + w - w_aux return w, h