def __init__(self, num_letters, first_equivariant): super(VerbDirectionSCAN, self).__init__(num_letters) self.num_equivariant = [4, 2] self.first_equivariant = [ first_equivariant, first_equivariant + self.num_equivariant[0] ] self.last_equivariant = [ fe + ne for fe, ne in zip(self.num_equivariant, self.first_equivariant) ] # Initialize separate symmetry groups for verbs and directions self.verb_sym = CircularShift(self.num_letters, self.num_equivariant[0], self.first_equivariant[0]) self.dir_sym = CircularShift(self.num_letters, self.num_equivariant[1], self.first_equivariant[1]) # Construct perm matrices as cartesian product between the groups for dir_mat in self.dir_sym.perm_matrices: for verb_mat in self.verb_sym.perm_matrices: new_mat = dir_mat @ verb_mat if not self.in_group(new_mat): self.perm_matrices.append(new_mat) self.index2mat, self.index2inverse, self.index2inverse_indices = {}, {}, {} for idx, mat in enumerate(self.perm_matrices): self.index2mat[idx] = mat self.index2inverse[idx] = torch.pinverse(mat) self.index2inverse_indices[idx] = torch.tensor( [ self.mat2index(torch.pinverse(mat) @ h) for h in self.perm_matrices ], dtype=torch.long).to(device)
def __init__(self, num_letters, num_equivariant, first_equivariant=0): super(CircularShift, self).__init__(num_letters) self.num_equivariant = num_equivariant self.first_equivariant = first_equivariant self.last_equivariant = first_equivariant + num_equivariant # Define initial shift self.init_perm = [ (i, i + 1) for i in range(self.first_equivariant, self.last_equivariant - 1) ] self.init_perm += [(self.last_equivariant - 1, self.first_equivariant)] self.tau1 = get_permutation_matrix(self.num_letters, self.init_perm) self.perm_matrices.append(self.tau1) for _ in range(self.num_equivariant - 2): perm_mat = self.perm_matrices[-1] @ self.tau1 self.perm_matrices.append(perm_mat) self.index2mat, self.index2inverse, self.index2inverse_indices = {}, {}, {} for idx, mat in enumerate(self.perm_matrices): self.index2mat[idx] = mat self.index2inverse[idx] = torch.pinverse(mat) self.index2inverse_indices[idx] = torch.tensor( [ self.mat2index(torch.pinverse(mat) @ h) for h in self.perm_matrices ], dtype=torch.long).to(device)
def fit_gamma_likelihood(self, X, y_vx, y_vy, y_vz, eps=1e-10): """ :param X: raw data :param y: labels """ X = self.__sparse_features(X, self.rbf_kernel_type) all_ys = torch.cat((y_vx, y_vy, y_vz), dim=-1) X = X.double() y_vx = y_vx.double() y_vy = y_vy.double() y_vz = y_vz.double() y_vx = torch.log(y_vx + eps) y_vy = torch.log(y_vy + eps) y_vz = torch.log(y_vz + eps) lam = 0.1 self.w_hatx = torch.pinverse( X.t().mm(X) + lam * torch.eye(X.shape[1], dtype=torch.double)).mm( X.t().mm(y_vx).double()) self.w_haty = torch.pinverse( X.t().mm(X) + lam * torch.eye(X.shape[1], dtype=torch.double)).mm( X.t().mm(y_vy).double()) self.w_hatz = torch.pinverse( X.t().mm(X) + lam * torch.eye(X.shape[1], dtype=torch.double)).mm( X.t().mm(y_vz).double())
def step(self, closure=None): """Performs a single optimization step. Arguments: closure (callable, optional): A closure that reevaluates the model and returns the loss. """ loss = None if closure is not None: loss = closure() for group in self.param_groups: momentum = group['momentum'] dampening = group['dampening'] nesterov = group['nesterov'] for p in group['params']: if p.grad is None: continue grad = p.grad.data if momentum != 0: param_state = self.state[p] if 'momentum_buffer' not in param_state: buf = param_state['momentum_buffer'] = torch.clone( grad).detach() else: buf = param_state['momentum_buffer'] buf.mul_(momentum).add_(1 - dampening, grad) if nesterov: G = G.add(momentum, buf.double()) else: G = buf.double() else: G = p.grad.data.double() X = p.data.double() n_dim = p.data.shape[0] n_component = p.data.shape[1] dtype = p.data.dtype if 2 * n_component < n_dim: U = torch.cat((G, X), dim=1) VT = torch.cat((X.T, -G.T), dim=0) p.data.add_(-group['lr'], (U @ torch.pinverse( torch.eye(2 * n_component, dtype=torch.double, device=X.device) + group['lr'] / 2 * VT @ U) @ VT @ X).type(dtype)) else: A = G @ X.T - X @ G.T p.data = (torch.pinverse( torch.eye(n_dim, dtype=torch.double, device=X.device) + group['lr'] / 2 * A) @ (torch.eye( n_dim, dtype=torch.double, device=X.device) - group['lr'] / 2 * A) @ X).type(dtype) return loss
def generateUinv(Ureal, Uimag): UinvReal = tc.pinverse(Ureal + tc.mm(tc.mm(Uimag, tc.pinverse(Ureal)), Uimag), rcond=1e-9) UinvImag = tc.pinverse(Uimag + tc.mm(tc.mm(Ureal, tc.pinverse(Uimag)), Ureal), rcond=1e-9) return UinvReal, UinvImag
def fit_gamma_likelihood(self, X, y_vx, y_vy, y_vz, eps=1e-10): X = self.__sparse_features(X, self.rbf_kernel_type) all_ys = torch.cat((y_vx, y_vy, y_vz), dim=-1) print("all_ys:\n", all_ys) print("all_ys.shape:", all_ys.shape) # print("y_vx.shape:", y_vx.shape) # exit() # print("X:", X) X = X.double() y_vx = y_vx.double() y_vy = y_vy.double() y_vz = y_vz.double() X_ = X.cpu().detach().numpy() y_vx_ = np.log(y_vx + eps) y_vy_ = np.log(y_vy + eps) y_vz_ = np.log(y_vz + eps) lam = 0.1 w_hatx_ = (np.linalg.pinv(X_.T.dot(X_) + lam*np.eye(X_.shape[1]))).dot(X_.T.dot(y_vx_)) w_haty_ = (np.linalg.pinv(X_.T.dot(X_) + lam*np.eye(X_.shape[1]))).dot(X_.T.dot(y_vy_)) w_hatz_ = (np.linalg.pinv(X_.T.dot(X_) + lam*np.eye(X_.shape[1]))).dot(X_.T.dot(y_vz_)) y_vx = torch.log(y_vx + eps) y_vy = torch.log(y_vy + eps) y_vz = torch.log(y_vz + eps) lam = 0.1 # print("X.t().mm(X) + lam*torch.eye(X.shape[1], dtype=torch.double):", X.t().mm(X) + lam*torch.eye(X.shape[1], dtype=torch.double)) # print("torch.pinverse(X.t().mm(X) + lam*torch.eye(X.shape[1], dtype=torch.double)):", torch.pinverse(X.t().mm(X) + lam*torch.eye(X.shape[1], dtype=torch.double))) # self.w_hatx = torch.tensor(np.linalg.pinv(X.t().mm(X) + lam*torch.eye(X.shape[1], dtype=torch.double))).mm(X.t().mm(y_vx).double()) # self.w_haty = torch.tensor(np.linalg.pinv(X.t().mm(X) + lam*torch.eye(X.shape[1], dtype=torch.double))).mm(X.t().mm(y_vy).double()) # self.w_hatz = torch.tensor(np.linalg.pinv(X.t().mm(X) + lam*torch.eye(X.shape[1], dtype=torch.double))).mm(X.t().mm(y_vz).double()) self.w_hatx = torch.pinverse(X.t().mm(X) + lam*torch.eye(X.shape[1], dtype=torch.double)).mm(X.t().mm(y_vx).double()) self.w_haty = torch.pinverse(X.t().mm(X) + lam*torch.eye(X.shape[1], dtype=torch.double)).mm(X.t().mm(y_vy).double()) self.w_hatz = torch.pinverse(X.t().mm(X) + lam*torch.eye(X.shape[1], dtype=torch.double)).mm(X.t().mm(y_vz).double()) # self.w_hatx = torch.pinverse(X.t().mm(X) + lam*torch.eye(X.shape[1])).mm(X.t().mm(y_vx)) # self.w_haty = torch.pinverse(X.t().mm(X) + lam*torch.eye(X.shape[1])).mm(X.t().mm(y_vy)) # self.w_hatz = torch.pinverse(X.t().mm(X) + lam*torch.eye(X.shape[1])).mm(X.t().mm(y_vz)) # print("self.w_hatx:", self.w_hatx) # print("w_hatx_:", w_hatx_) # print("self.w_hatx.shape:", self.w_hatx.shape) # print("w_hatx_.shape:", w_hatx_.shape) print("self.w_haty:", self.w_haty) print("w_haty_:", w_haty_) print("self.w_haty.shape:", self.w_haty.shape) print("w_haty_.shape:", w_haty_.shape) assert np.allclose(self.w_hatx.cpu().detach().numpy(), w_hatx_)# , rtol=100, atol=100) assert np.allclose(self.w_haty.cpu().detach().numpy(), w_haty_)#, rtol=100, atol=100) assert np.allclose(self.w_hatz.cpu().detach().numpy(), w_hatz_)#, rtol=100, atol=100)
def update_W(Y, U, V, S, W_other, omega, alpha, delta, code_length, device): I1 = torch.eye(Y.shape[0], device=device) # c*c I2 = torch.eye(code_length, device=device) # l*l A = omega * U @ U.t() + alpha * I2 # l*l B = delta * U @ U.t() # l*l C = W_other.t() @ V @ V.t() @ W_other # c*c D = omega * U @ Y.t() + delta * code_length * U @ S @ V.t() @ W_other # l*c vecBD = (torch.pinverse(B) @ D).t().reshape(-1, 1) # 1*(l*c) tmpBA = torch.pinverse(B) @ A vecW = torch.pinverse(kronecker(I1, tmpBA) + kronecker(C.t(), I2)) @ vecBD return vecW.reshape(-1, code_length).t()
def __init__(self, num_letters): super(TrivialGroup, self).__init__(num_letters=num_letters) self.tau = torch.eye(num_letters, dtype=torch.float64).to(device) self.perm_matrices = [self.tau] self.index2mat, self.index2inverse, self.index2inverse_indices = {}, {}, {} for idx, mat in enumerate(self.perm_matrices): self.index2mat[idx] = mat self.index2inverse[idx] = torch.pinverse(mat) self.index2inverse_indices[idx] = torch.tensor( [self.mat2index(torch.pinverse(mat) @ h) for h in self.perm_matrices], dtype=torch.long ).to(device)
def forward(self, x): encoded = self.encoder(x) self.decoder[6].weight.data = torch.pinverse( self.encoder[0].weight.data) self.decoder[4].weight.data = torch.pinverse( self.encoder[2].weight.data) self.decoder[2].weight.data = torch.pinverse( self.encoder[4].weight.data) self.decoder[0].weight.data = torch.pinverse( self.encoder[6].weight.data) decoded = self.decoder(encoded) return encoded, decoded
def update1_stiefelSGD(p, X, G, lr, K, n_dim, dtype, index=None): U = torch.cat((G, X), dim=1) VT = torch.cat((X.T, -G.T), dim=0) if index is None: p.data = (X - lr * U @ torch.pinverse( torch.eye(2 * K, dtype=torch.double, device=X.device) + lr / 2. * VT @ U) @ VT @ X).type(dtype) else: p.data[index] = (X - lr * U @ torch.pinverse( torch.eye(2 * K, dtype=torch.double, device=X.device) + lr / 2. * VT @ U) @ VT @ X).type(dtype) return
def update2_stiefelSGD(p, X, G, lr, K, n_dim, dtype, index=None): A = G @ X.T - X @ G.T if index is None: p.data = (torch.pinverse( torch.eye(n_dim, dtype=torch.double, device=X.device) + lr / 2 * A) @ (torch.eye(n_dim, dtype=torch.double, device=X.device) - lr / 2 * A) @ X).type(dtype) else: p.data[index] = (torch.pinverse( torch.eye(n_dim, dtype=torch.double, device=X.device) + lr / 2 * A) @ (torch.eye(n_dim, dtype=torch.double, device=X.device) - lr / 2 * A) @ X).type(dtype) return
def fit(self, X, y): # For polynomial transformation if self.polynomial_degree: X = polynomial_features(X, degree=self.polynomial_degree) n_samples, n_features = X.shape[0], X.shape[1] X_X_T = torch.mm(X.T, X) # Least squares approximate of beta beta_hat = torch.mm(torch.mm(torch.pinverse(X_X_T), X.T), y) # The posterior parameters can be determined analytically since we assume # conjugate priors for the likelihoods. # Normal prior / likelihood => Normal posterior mu_n = torch.mm( torch.pinverse(X_X_T + self.omega_0), torch.mm(X_X_T, beta_hat) + torch.mm(self.omega_0, self.mu_0.unsqueeze(1))) omega_n = X_X_T + self.omega_0 nu_n = self.nu_0 + n_samples # Scaled inverse chi-squared prior / likelihood => Scaled inverse chi-squared posterior sigma_sq_n = (1.0 / nu_n) * ( self.nu_0 * self.sigma_sq_0 + torch.mm(y.T, y) + torch.mm(torch.mm(self.mu_0.unsqueeze(1).T, self.omega_0), self.mu_0.unsqueeze(1)) - torch.mm(mu_n.T, torch.mm(omega_n, mu_n))) # Simulate parameter values for n_draws beta_draws = torch.empty((self.n_draws, n_features)) for i in range(self.n_draws): sigma_sq = self.scaled_inverse_chi_square(n=1, df=nu_n, scale=sigma_sq_n) beta = multivariate_normal.rvs(size=1, mean=mu_n[:, 0], cov=sigma_sq * torch.pinverse(omega_n)) beta_draws[1, :] = torch.tensor(beta, dtype=torch.float) # Select the mean of the simulated variables as the ones used to make predictions self.w = torch.mean(beta_draws, dim=0, dtype=torch.double) # Lower and upper boundary of the credible interval l_eti = 0.50 - self.credible_interval / 2 u_eti = 0.50 + self.credible_interval / 2 self.eti = torch.tensor([[ torch.quantile(beta_draws[:, i], q=l_eti), torch.quantile(beta_draws[:, i], q=u_eti) ] for i in range(n_features)], dtype=torch.double)
def generate_K_alpha(self, max_iter=10): """ should be used in mode 'load' and weight should be given """ assert self.mode == 'load', 'Err::K can only be generated with given weights' """ \arg\min | W - K*alpha |_F """ with torch.no_grad(): d = self.cin * self.ksize * self.ksize # [cout,cin,k,k] -> [cout,d] W = self.weight.view(self.cout, d) # K = [cL,d] _W = W.cpu().numpy() kmeans = skKmeans(n_clusters=self.cL, max_iter=600) kmeans.fit(_W) K = kmeans.cluster_centers_ K = torch.FloatTensor(K).to(self.weight.device) # add parameter 1 # self.K = nn.Parameter(K.reshape(self.cL,self.cin,self.ksize,self.ksize)) # K=[d,cL] W=[d,cout] W = W.transpose(0, 1) K = K.transpose(0, 1) # K = F.normalize(K,dim=0) for n_iter in range(max_iter): pKtK = torch.pinverse(K.transpose(0, 1) @ K) I = torch.diag(torch.ones(self.cL)).to(K.device) pKtK += 0.001 * I alpha = pKtK @ (K.transpose(0, 1)) @ W alpha = alpha.clamp(-0.5, 0.5) pxxt = torch.pinverse( alpha @ alpha.transpose(0, 1) + 0.01 * torch.diag(torch.ones(self.cL)).to(K.device)) K = W @ alpha.transpose(0, 1) @ pxxt loss = ((K @ alpha - W)**2).sum() K = K.transpose(0, 1).reshape(self.cL, self.cin, self.ksize, self.ksize) alpha = alpha.transpose(0, 1).view(self.cout, self.cL, 1, 1) alpha = alpha.clamp(-0.5, 0.5) # self.K = nn.Parameter(K.transpose(0, 1).reshape(self.cL, self.cin, self.ksize, self.ksize)) # self.alpha = nn.Parameter(alpha) print('Final templating loss = %1.2f for shaping:' % loss, self.weight.shape, 'to', K.shape) self.conv1.weight = nn.Parameter(K) self.conv2.weight = nn.Parameter(alpha)
def fit_plane_torch(p, pixel_grid, ransac_iter=50, inlier_thresh=0.03): ''' Parameters ---------- p : array of 3D coordinates pixel_grid: (u,v) coordinates for p Returns ------- best_normal : The normal direction of the plane that was fit using RANSAC best_inlier_list : indices of 3D points that are inliers (best_u, best_v) : image coordinates of inlier pixels ''' u_grid, v_grid = pixel_grid b = torch.ones((3,1)) most_inlier = 0 for n in range(0,ransac_iter): #sample 3 points idx = [] A = torch.zeros((3,3)) while len(idx)<= 2: num = np.random.randint(0, p.shape[0]) if num not in idx: idx.append(num) for i in range(0,3): A[i,:] = p[idx[i]] A_inv = torch.pinverse(A) normal = A_inv.mm(b) n = normal/torch.norm(normal) ## check number of inliers d = torch.abs(p.mm(normal)-1) inlier_list = torch.where(d<inlier_thresh)[0] inlier_u_pixels = u_grid[inlier_list] inlier_v_pixels = v_grid[inlier_list] if len(inlier_list) > most_inlier and (n[1,0]>0.9): most_inlier = len(inlier_list) best_inlier_list = inlier_list best_normal = normal best_u = inlier_u_pixels best_v = inlier_v_pixels b = torch.ones((best_inlier_list.size(0),1)) best_normal = torch.pinverse(p[best_inlier_list]).mm(b) ##recompute normal with all points return best_normal, best_inlier_list , (best_u, best_v)
def predict(self, X): """ Make predictions on test data X. :param X: a torch tensor that contains N data samples (N x d) :param return_probas: True if the user would like probabilities instead of predictions returned :return: the test predictions or probabilities """ # compute/load Lambda matrix if self.prev_num_updates != self.num_updates: # there have been updates to the model, compute Lambda self.Lambda = torch.pinverse( (1 - self.shrinkage_param) * self.Sigma + self.shrinkage_param * torch.eye(self.input_size, device=self.device)) self.prev_num_updates = self.num_updates # parameters for predictions M = self.muK.transpose(1, 0) W = torch.matmul(self.Lambda, M) c = 0.5 * torch.sum(M * W, dim=0) scores = torch.matmul(X, W) - c # return predictions or probabilities return scores
def backward(ctx, grad_output): """ calculate the necessary gradients Params: ctx: context object to save variables for the backward pass grad_output: current gradient at the output of the forward pass """ # get variables from the forward pass input_torch, weight, bias = ctx.saved_variables # calculate the gradients that are backpropagated # use the pseudoinverse for the backward path # this is a time-consuming operation pseudo_inverse = torch.pinverse(weight, rcond=1e-10) grad_input = grad_output.mm(pseudo_inverse.t()) # calculate the gradients on the weights grad_weight = grad_output.t().mm(input_torch) if (bias is not None) and (ctx.needs_input_grad[2]): # gradient at the bias if required grad_bias = grad_output.sum(0).squeeze(0) else: grad_bias = None return grad_input, grad_weight, grad_bias
def minimise_2d_residual_over_T(K, X, Y, v=None): ba, _, n = X.size() append1 = lambda x: torch.cat((x, x.new_ones(x[:, :1, :].size())), dim=1) Y_cam = torch.bmm(torch.inverse(K), append1(Y)) # construct a system AT = b A_u = torch.cat((Y_cam.new_ones(ba, n, 1), Y_cam.new_zeros( ba, n, 1), -Y_cam[:, :1, :].permute(0, 2, 1)), dim=2) A_v = torch.cat((Y_cam.new_zeros(ba, n, 1), Y_cam.new_ones( ba, n, 1), -Y_cam[:, 1:2, :].permute(0, 2, 1)), dim=2) b_u = (Y_cam[:, 0:1, :] * X[:, 2:, :] - X[:, 0:1, :]).permute(0, 2, 1) b_v = (Y_cam[:, 1:2, :] * X[:, 2:, :] - X[:, 1:2, :]).permute(0, 2, 1) res = Y_cam.new_empty(ba, 3) for i in range(ba): if v is not None: A = torch.cat((A_u[i, v[i] > 0., :], A_v[i, v[i] > 0., :]), dim=0) b = torch.cat((b_u[i, v[i] > 0., :], b_v[i, v[i] > 0., :]), dim=0) else: A = torch.cat((A_u[i, :, :], A_v[i, :, :]), dim=0) b = torch.cat((b_u[i, :, :], b_v[i, :, :]), dim=0) #res[i,:] = torch.lstsq(b, A)[0][:3, 0] res[i, :] = torch.matmul(torch.pinverse(A), b)[:, 0] return res
def __init__( self, n_fft: int, win_length: int, hop_length: int, n_iter: int, window_fn=torch.hann_window, ): super(GriffinLim, self).__init__() self.transform = TTSSpectrogram(n_fft, win_length, hop_length, return_phase=True) basis = get_fourier_basis(n_fft) basis = torch.pinverse(n_fft / hop_length * basis).T[:, None, :] basis *= get_window(window_fn, n_fft, win_length) self.register_buffer("basis", basis) self.n_fft = n_fft self.win_length = win_length self.hop_length = hop_length self.n_iter = n_iter self.tiny = 1.1754944e-38
def __init__(self, n_stft, n_mels, sample_rate, f_min, f_max) -> None: super(PseudoInverseMelScale, self).__init__() self.n_mels = n_mels basis = get_mel_filters(sample_rate, (n_stft - 1) * 2, n_mels, f_min, f_max) basis = torch.pinverse(basis) # F x F_mel self.register_buffer("basis", basis)
def opt_params(self, X, y_values): sigma = (torch.mm(y_values, torch.t(y_values))) * self.kernel(X, X) A_cross = torch.pinverse( torch.cat( ( # block matrix torch.cat((torch.tensor( 0, dtype=X.dtype, device=self.device).view( 1, 1), torch.t(y_values)), dim=1), torch.cat((y_values, sigma + self.gamma**-1 * torch.eye( len(y_values), dtype=X.dtype, device=self.device)), dim=1)), dim=0)) B = torch.tensor([0] + [1] * len(y_values), dtype=X.dtype, device=self.device).view(-1, 1) solution = torch.mm(A_cross, B) b = solution[0] alpha = solution[1:].view(-1) # 1D array form return (b, alpha)
def compute_filter_pinv(self, filters): """ Computes pseudo inverse filterbank of given filters.""" scale = self.filterbank.stride / self.filterbank.kernel_size shape = filters.shape ifilt = torch.pinverse(filters.squeeze()).transpose(-1, -2).view(shape) # Compensate for the overlap-add. return ifilt * scale
def plane_loss(self, plane_est, depth, intrinsics_inv): b, _, h, w = depth.size() i_range = torch.arange(0, h).view(1, h, 1).expand(1,h,w).type_as(depth) # [1, H, W] j_range = torch.arange(0, w).view(1, 1, w).expand(1,h,w).type_as(depth) # [1, H, W] ones = torch.ones(1,h,w).type_as(depth) pixel_coords = torch.stack((j_range, i_range, ones), dim=1) # [1, 3, H, W] ###pixel_coords is an array of camera pixel coordinates (x,y,1) where x,y origin is the upper left corner of the image. current_pixel_coords = pixel_coords[:,:,:h,:w].expand(b,3,h,w).view(b,3,-1) #.contiguous().view(b, 3, -1) # [B, 3, H*W] cam_coords = intrinsics_inv.bmm(current_pixel_coords).view(b,3,h,w) cam_coords = cam_coords*depth gp_coords = cam_coords[:,:,int(6.*h/7.):,int(4.5*w/10.):int(5.5*w/10.)].clone() cam_coords = cam_coords.reshape(b,3,-1).permute(0,2,1) gp_coords = gp_coords.reshape(b,3,-1).permute(0,2,1) plane_est = plane_est.reshape(b,-1,1) #.expand_as(cam_coords) ones = torch.ones((b,gp_coords.size(1),1)).type_as(gp_coords) computed_normal = torch.pinverse(gp_coords).bmm(ones) normal = computed_normal/( torch.norm(computed_normal,dim=1).view(b,1,1).expand_as(computed_normal) ) heights = (cam_coords.bmm(normal)) #.abs() #no abs to get rid of 'upper' pixels gp_height = gp_coords.bmm(normal).mean(1) #.abs() height_loss = plane_est*( (heights-gp_height.unsqueeze(1).expand_as(heights)).abs() ) return height_loss.mean()
def fit(self, A, Y): A_T = A.T A_T_A = torch.mm(A_T, A) A_T_Y = torch.mm(A_T, Y) model = torch.mm(torch.pinverse(A_T_A), A_T_Y) return model
def update_params( self, action: int, batch_size: int = 512, train_epochs: Optional[int] = None ): """Update parameters of the agent. Updated the posterior over beta though bayesian regression. Args: action (int): Action to update the parameters for. batch_size (int, optional): Size of batch to update parameters with. Defaults to 512 train_epochs (Optional[int], optional): Epochs to train neural network for. Not applicable in this agent. Defaults to None """ self.update_count += 1 x, y = self.db.get_data_for_action(action, batch_size) x = torch.cat([x, torch.ones(x.shape[0], 1)], dim=1) inv_cov = torch.mm(x.T, x) + self.lambda_prior * torch.eye(self.context_dim + 1) cov = torch.pinverse(inv_cov) mu = torch.mm(cov, torch.mm(x.T, y)) a = self.a0 + self.t / 2 b = self.b0 + (torch.mm(y.T, y) - torch.mm(mu.T, torch.mm(inv_cov, mu))) / 2 self.mu[action] = mu.squeeze(1) self.cov[action] = cov self.inv_cov[action] = inv_cov self.a[action] = a self.b[action] = b
def fit(self): if self.readout_training in {'gd', 'svd'}: return if self.readout_training == 'cholesky': W = torch.solve( self.XTy, self.XTX + self.lambda_reg * torch.eye(self.XTX.size(0), device=self.XTX.device))[0].t() self.XTX = None self.XTy = None self.readout.bias = nn.Parameter(W[:, 0]) self.readout.weight = nn.Parameter(W[:, 1:]) elif self.readout_training == 'inv': I = (self.lambda_reg * torch.eye(self.XTX.size(0))).to( self.XTX.device) A = self.XTX + I if torch.det(A) != 0: W = torch.mm(torch.inverse(A), self.XTy).t() else: pinv = torch.pinverse(A) W = torch.mm(pinv, self.XTy).t() self.readout.bias = nn.Parameter(W[:, 0]) self.readout.weight = nn.Parameter(W[:, 1:]) self.XTX = None self.XTy = None
def _calc_weights(self, X, Y, _lambda): # sets the rbf network weights based on the regularised # least squares solution; for full detail see section 6: # https://www.cc.gatech.edu/~isbell/tutorials/rbf-intro.pdf H = self.activations(X) A = H.T @ H + self._I * _lambda # try to use the torch SVD to perform the pseudoinverse (gessd) try: Ainv = torch.pinverse(A) # the faster torch pseudoinverse uses the 'gessd' method which handles # poorly-conditioned matrices badly. so, if this fails, switch to the # scipy version which used the more robust, but SLOWER, 'gesvd' method except: print('torch.pinverse() failed, using scipy') import scipy U, s, Vh = scipy.linalg.svd(A.detach().numpy(), lapack_driver="gesvd", full_matrices=False) mask = s != 0. s[mask] = 1 / s[mask] sT = np.diag(s).T Ainv = Vh.T @ sT @ U.T Ainv = torch.from_numpy(Ainv) # weights return Ainv @ H.T @ Y
def reconstruct_matrix(self, signal, calibration_matrix, eigval1_reciprocal, eigval2_reciprocal): """ Recovers the random matrix. Parameters ---------- signal: ComplexTensor, Tensor with the signal values calibration_matrix: torch.Tensor, calibration matrix (the partial one) eigenvalues_reciprocal1: ComplexTensor, eigenvalues of the first circulant matrix block of the partial calibration matrix. eigenvalues_reciprocal2: ComplexTensor, eigenvalues of the second circulant matrix block of the partial calibration matrix. Returns ------- reconstructed_A: ComplexTensor, recostructed transmission matrix. If batch size<rows, it is a batch of rows. """ start = time() if self.solver == "least-square": inv_calibration_matrix = torch.pinverse(calibration_matrix) reconstructed_A = ComplexTensor( real=torch.matmul(signal.real, inv_calibration_matrix), imag=torch.matmul(signal.imag, inv_calibration_matrix)) elif self.solver == "fft": signal = signal.conj().stack() signal1_star = signal[:, :self.n_signals // 2] signal2_star = signal[:, self.n_signals // 2:] fft_buffer = torch.fft(signal1_star, signal_ndim=1) block1 = ComplexTensor(real=fft_buffer[:, :, 0], imag=fft_buffer[:, :, 1]) block1 = block1.batch_elementwise(eigval1_reciprocal) fft_buffer = torch.fft(signal2_star, signal_ndim=1) block2 = ComplexTensor(real=fft_buffer[:, :, 0], imag=fft_buffer[:, :, 1]) block2 = block2.batch_elementwise(eigval2_reciprocal) reconstructed_A = torch.ifft((block1 + block2).stack(), signal_ndim=1) reconstructed_A = ComplexTensor(real=reconstructed_A[:, :, 0], imag=reconstructed_A[:, :, 1]).conj() self.time_logger["solver"] += time() - start return reconstructed_A
def learn_projections(base_kernels, xs, ys, max_projections=10, mse_threshold=0.0001, post_fit=False, backfit_iters=5, **optim_kwargs): n, d = xs.shape pred_means = torch.zeros(max_projections, n) models = [] for bf_iter in range(backfit_iters): for i in range(max_projections): residuals = ys - pred_means[:i, :].sum( dim=0) - pred_means[i + 1, :].sum(dim=0) if bf_iter == 0: with torch.no_grad(): coef = torch.pinverse(xs).matmul(residuals).reshape(1, -1) base_kernel = base_kernels[i] projection = torch.nn.Linear(d, 1, bias=False).to(xs) projection.weight.data = coef kernel = ScaledProjectionKernel(projection, base_kernel) model = ExactGPModel(xs, residuals, GaussianLikelihood(), kernel).to(xs) else: model = models[i] mll = ExactMarginalLogLikelihood(model.likelihood, model).to(xs) # mll.train() model.train() train_to_convergence(model, xs, residuals, objective=mll, **optim_kwargs) model.eval() models.append(model) with torch.no_grad(): pred_mean = model(xs).mean pred_means[i, :] = pred_mean residuals = residuals - pred_mean mse = (residuals**2).mean() print(mse.item(), end='; ') if mse < mse_threshold: break print() joint_kernel = AdditiveKernel(*[model.covar_module for model in models]) joint_model = ExactGPModel(xs, ys, GaussianLikelihood(), joint_kernel).to(xs) if post_fit: mll = ExactMarginalLogLikelihood(joint_model.likelihood, joint_model).to(xs) train_to_convergence(joint_model, xs, ys, objective=mll, **optim_kwargs) return joint_model
def lda(x1, x2, device="cpu"): with torch.no_grad(): x1 = torch.tensor(x1, device=device, dtype=torch.float) x2 = torch.tensor(x2, device=device, dtype=torch.float) m1 = torch.mean(x1, dim=0) m2 = torch.mean(x2, dim=0) m = (len(x1) * m1 + len(x2) * m2) / (len(x1) + len(x2)) d1 = x1 - m1[None, :] scatter1 = d1.t() @ d1 d2 = x2 - m2[None, :] scatter2 = d2.t() @ d2 within_class_scatter = scatter1 + scatter2 d1 = m1 - m[None, :] scatter1 = len(x1) * (d1.t() @ d1) d2 = m2 - m[None, :] scatter2 = len(x2) * (d2.t() @ d2) between_class_scatter = scatter1 + scatter2 p = torch.pinverse(within_class_scatter) @ between_class_scatter eigenvalues, eigenvectors = torch.eig(p, eigenvectors=True) idx = torch.argsort(eigenvalues[:, 0], descending=True) eigenvalues = eigenvalues[idx, 0] eigenvectors = eigenvectors[idx, :] return eigenvectors[0, :].cpu().numpy()
def reconstruction_loss_inverse_model(model, rn_threshold, **kwargs): regularization_loss = 0 for param in model.parameters(): regularization_loss += torch.sum(square(torch.pinverse(param))) if regularization_loss < rn_threshold: regularization_loss = torch.from_numpy(np.array(rn_threshold)) return regularization_loss