def ridge_regression(matrix_a, matrix_b, lambda_, intercept=False): #log.print_info(logger, "In Ridge regression..", 4) #log.print_matrix_info(logger, matrix_a, 5, "Input matrix A:") #log.print_matrix_info(logger, matrix_b, 5, "Input matrix B:") """ Performs Ridge Regression. This method use the general formula: ... to solve the problem: :math:`X = argmin(||AX - B||_2 + \\lambda||X||_2)` Args: matrix_a: input matrix A, of type Matrix matrix_b: input matrix A, of type Matrix lambda_: scalar, lambda parameter intercept: bool. If True intercept is used. Optional, default False. Returns: solution X of type Matrix """ matrix_a._assert_same_type(matrix_b) # TODO: check out where to define this assert assert_same_shape(matrix_a, matrix_b, 0) matrix_type = type(matrix_a) dim = matrix_a.shape[1] if intercept: matrix_a = matrix_a.hstack( matrix_type(np.ones((matrix_a.shape[0], 1)))) lambda_diag = (lambda_) * matrix_type.identity(dim) if intercept: lambda_diag = padd_matrix(padd_matrix(lambda_diag, 0, 0.0), 1, 0.0) matrix_a_t = matrix_a.transpose() try: tmp_mat = Linalg.pinv(((matrix_a_t * matrix_a) + lambda_diag)) except np.linalg.LinAlgError: print "Warning! LinAlgError" tmp_mat = matrix_type.identity(lambda_diag.shape[0]) tmp_res = tmp_mat * matrix_a_t result = tmp_res * matrix_b #S: used in generalized cross validation, page 244 7.52 (YZ also used it) # S is defined in 7.31, page 232 # instead of computing the matrix and then its trace, we can compute # its trace directly # NOTE when lambda = 0 we get out trace(S) = rank(matrix_a) dist = (matrix_a * result - matrix_b).norm() S_trace = matrix_a_t.multiply(tmp_res).sum() return result, S_trace, dist
def ridge_regression(matrix_a , matrix_b, lambda_, intercept=False): #log.print_info(logger, "In Ridge regression..", 4) #log.print_matrix_info(logger, matrix_a, 5, "Input matrix A:") #log.print_matrix_info(logger, matrix_b, 5, "Input matrix B:") """ Performs Ridge Regression. This method use the general formula: ... to solve the problem: :math:`X = argmin(||AX - B||_2 + \\lambda||X||_2)` Args: matrix_a: input matrix A, of type Matrix matrix_b: input matrix A, of type Matrix lambda_: scalar, lambda parameter intercept: bool. If True intercept is used. Optional, default False. Returns: solution X of type Matrix """ matrix_a._assert_same_type(matrix_b) # TODO: check out where to define this assert assert_same_shape(matrix_a, matrix_b, 0) matrix_type = type(matrix_a) dim = matrix_a.shape[1] if intercept: matrix_a = matrix_a.hstack(matrix_type(np.ones((matrix_a.shape[0], 1)))) lambda_diag = (lambda_ ) * matrix_type.identity(dim) if intercept: lambda_diag = padd_matrix(padd_matrix(lambda_diag, 0, 0.0), 1, 0.0) matrix_a_t = matrix_a.transpose() try: tmp_mat = Linalg.pinv(((matrix_a_t * matrix_a) + lambda_diag)) except np.linalg.LinAlgError: print "Warning! LinAlgError" tmp_mat = matrix_type.identity(lambda_diag.shape[0]) tmp_res = tmp_mat * matrix_a_t result = tmp_res * matrix_b #S: used in generalized cross validation, page 244 7.52 (YZ also used it) # S is defined in 7.31, page 232 # instead of computing the matrix and then its trace, we can compute # its trace directly # NOTE when lambda = 0 we get out trace(S) = rank(matrix_a) dist = (matrix_a * result - matrix_b).norm() S_trace = matrix_a_t.multiply(tmp_res).sum() return result, S_trace, dist
def _compose(self, arg1_mat, arg2_mat): #NOTE when we get in this compose arg1 mat and arg2 mat have the same type [mat_a_t, mat_b_t, arg1_mat ] = resolve_type_conflict([self._mat_a_t, self._mat_b_t, arg1_mat], type(arg1_mat)) if self._has_intercept: return arg1_mat * mat_a_t + padd_matrix(arg2_mat, 1) * mat_b_t else: return arg1_mat * mat_a_t + arg2_mat * mat_b_t
def _compose(self, arg1_mat, arg2_mat): #NOTE when we get in this compose arg1 mat and arg2 mat have the same type [mat_a_t, mat_b_t, arg1_mat] = resolve_type_conflict([self._mat_a_t, self._mat_b_t, arg1_mat], type(arg1_mat)) if self._has_intercept: return arg1_mat * mat_a_t + padd_matrix(arg2_mat, 1) * mat_b_t else: return arg1_mat * mat_a_t + arg2_mat * mat_b_t
def _compose(self, function_arg_vec, arg_vec, function_arg_element_shape): new_shape = (np.prod(function_arg_element_shape[0:-1]), function_arg_element_shape[-1]) function_arg_vec.reshape(new_shape) if self._has_intercept: comp_el = function_arg_vec * padd_matrix(arg_vec.transpose(), 0) else: comp_el = function_arg_vec * arg_vec.transpose() return comp_el.transpose()
def test_crossvalidation(self): a = DenseMatrix(np.matrix([[1, 1],[2, 3],[4, 6]])) b = DenseMatrix(np.matrix([[12, 15, 18],[21, 27, 33],[35, 46, 57]])) res = DenseMatrix(np.matrix([[1, 2, 3],[4, 5, 6],[7, 8, 9]])) learner = RidgeRegressionLearner(intercept=True, param_range=[0]) learner2 = LstsqRegressionLearner(intercept=False) res1 = learner2.train(a, b) res2 = learner.train(a, b) np.testing.assert_array_almost_equal(res2.mat[:-1,:], res[0:2,:].mat, 6) np.testing.assert_array_almost_equal(res2.mat[-1,:], res[2:3,:].mat, 6) new_a = padd_matrix(a, 1) self.assertGreater(((a * res1) - b).norm(), ((new_a * res2) - b).norm())
def test_crossvalidation(self): a = DenseMatrix(np.matrix([[1, 1], [2, 3], [4, 6]])) b = DenseMatrix(np.matrix([[12, 15, 18], [21, 27, 33], [35, 46, 57]])) res = DenseMatrix(np.matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) learner = RidgeRegressionLearner(intercept=True, param_range=[0]) learner2 = LstsqRegressionLearner(intercept=False) res1 = learner2.train(a, b) res2 = learner.train(a, b) np.testing.assert_array_almost_equal(res2.mat[:-1, :], res[0:2, :].mat, 6) np.testing.assert_array_almost_equal(res2.mat[-1, :], res[2:3, :].mat, 6) new_a = padd_matrix(a, 1) self.assertGreater(((a * res1) - b).norm(), ((new_a * res2) - b).norm())
def compute_matreps(self,vecspace,matspace,multiply_matrices=False): ''' This method computes symbolic and numeric matrix representations od a papfunc node, taking as input a vector space, a matrix space. An optional Boolean argument, if set to True, makes matrices to be multiplied rather than summed when both subconstituents have arity greater than 0. ''' # for terminal nodes call insert_terminal_node_representation if self.is_terminal(): matrep,temp_numrep=self.insert_terminal_node_representation(vecspace,matspace) self._matrep = matrep if temp_numrep[0] == "empty": numrep = [] else: numrep = [temp_numrep[0].transpose()] dimensionality=(temp_numrep[0].shape[1]) if len(temp_numrep)>1: # all matrices are stored flattened, as long vectors. We need to # reshape them before we use them in computations for x in range(1, (len(temp_numrep))): y = DenseMatrix(temp_numrep[x]) y.reshape((dimensionality,(y.shape[1]/dimensionality))) numrep.append(y) self._numrep = numrep #raise an exception for a non-terminal node without children elif len(self._children) == 0: raise ValueError("Non-terminal non-branching node!") # inherit the value of the single daughter in case of unary branching if len(self._children) == 1: self._matrep = self.get_child(0)._matrep self._numrep = self.get_child(0)._numrep #apply composition for binary branching nodes if len(self._children) == 2 and self._matrep == []: matrep1=self.get_child(0)._matrep #ignore 'empty' nodes if not matrep1: raise ValueError("Empty matrix representation for node %s!" %self.get_child(0)) matrep2=self.get_child(1)._matrep if not matrep2: raise ValueError("Empty matrix representation for node %s!" %self.get_child(1)) arity1=len(matrep1)-1 arity2=len(matrep2)-1 # first, compute symbolic matrix representation # default to componentwise addition for daughters of equal arity if arity1-arity2 == 0: for x in range(0, arity1+1): self._matrep.append('(' + matrep1[x] + '+' + matrep2[x] + ')') # left function application if arity1 < arity2 and not re.search('empty$',matrep2[0]) and not re.search('empty$',matrep1[0]): for x in range(0, arity2): if x == 0: #compute the vector self._matrep.append('(' + matrep2[x] + '+' + matrep2[arity2] + '*' + matrep1[x] + ')') # compute a matrix # If both daughters have matrices in the xth position in # their vector-matrix structures, add or multiply those # matrices according to the multiply_matrices parameter elif x < len(matrep1): if multiply_matrices: self._matrep.append('(' + matrep2[x] + '*' + matrep1[x] + ')') else: self._matrep.append('(' + matrep2[x] + '+' + matrep1[x] + ')') # inherit the function's extra lexical matrix else: self._matrep.append(matrep2[x]) # right function application if arity1 > arity2 and not re.search('empty$',matrep2[0]) and not re.search('empty$',matrep1[0]): for x in range(0, arity1): if x == 0: self._matrep.append('(' + matrep1[x] + '+' + matrep1[arity1] + '*' + matrep2[x] + ')') # compute a matrix # If both daughters have matrices in the xth position in # their vector-matrix structures, add or multiply those # matrices according to the multiply_matrices parameter elif x < len(matrep2): if multiply_matrices: self._matrep.append('(' + matrep1[x] + '*' + matrep2[x] + ')') else: self._matrep.append('(' + matrep1[x] + '+' + matrep2[x] + ')') else: self._matrep.append(matrep1[x]) # ignore 'empty' elements if re.search('empty$',matrep1[0]): self._matrep = matrep2 if re.search('empty$',matrep2[0]): self._matrep = matrep1 # computing numeric matrix representation of a node from those of its two daughters numrep1=self.get_child(0)._numrep numrep2=self.get_child(1)._numrep if arity1-arity2 == 0 and numrep1 and numrep2: for x in range(0, arity1+1): self._numrep.append(numrep1[x].__add__(numrep2[x])) # left function application if arity1 < arity2 and not numrep1==[] and not numrep2==[]: for x in range(0, arity2): if x == 0: #compute the vector self._numrep.append(numrep2[x].__add__(numrep2[arity2] * padd_matrix(numrep1[x],0))) elif x < len(numrep1): if multiply_matrices: self._numrep.append(numrep2[x] * numrep1[x]) else: self._numrep.append(numrep1[x].__add__(numrep2[x])) else: self._numrep.append(numrep2[x]) # right function application if arity1 > arity2 and not numrep1==[] and not numrep2==[]: for x in range(0, arity1): if x == 0: # compute the vector self._numrep.append(numrep1[x].__add__(numrep1[arity1] * padd_matrix(numrep2[x],0))) elif x < len(numrep2): if multiply_matrices: self._numrep.append(numrep2[x] * numrep1[x]) else: self._numrep.append(numrep1[x].__add__(numrep2[x])) else: self._numrep.append(numrep1[x]) # ignore 'empty' elements if (numrep1 == []): self._numrep = numrep2 if (numrep2 == []): self._numrep = numrep1 # end of numrep computation # Raise an exception for non-binary branching - we don't want to handle those structures if len(self._children)>2: raise ValueError("Matrix representations are not defined for trees with more than binary branching")