Esempio n. 1
0
    def test_train_intercept(self):

        a1_mat = DenseMatrix(np.mat([[3,4],[5,6]]))
        a2_mat = DenseMatrix(np.mat([[1,2],[3,4]]))

        train_data = [("a1", "man", "a1_man"),
                      ("a2", "car", "a2_car"),
                      ("a1", "boy", "a1_boy"),
                      ("a2", "boy", "a2_boy")
                      ]

        n_mat = DenseMatrix(np.mat([[13,21],[3,4],[5,6]]))
        n_space = Space(n_mat, ["man", "car", "boy"], self.ft)

        an1_mat = (a1_mat * n_mat.transpose()).transpose()
        an2_mat = (a2_mat * n_mat.transpose()).transpose()
        an_mat = an1_mat.vstack(an2_mat)

        an_space = Space(an_mat, ["a1_man","a1_car","a1_boy","a2_man","a2_car","a2_boy"], self.ft)

        #test train
        model = LexicalFunction(learner=LstsqRegressionLearner(intercept=True))
        model._MIN_SAMPLES = 1
        model.train(train_data, n_space, an_space)
        a_space = model.function_space

        a1_mat.reshape((1,4))
        #np.testing.assert_array_almost_equal(a1_mat.mat,
        #                                     a_space.cooccurrence_matrix.mat[0])

        a2_mat.reshape((1,4))
        #np.testing.assert_array_almost_equal(a2_mat.mat,
        #                                     a_space.cooccurrence_matrix.mat[1])

        self.assertListEqual(a_space.id2row, ["a1", "a2"])
        self.assertTupleEqual(a_space.element_shape, (2,3))

        #test compose
        a1_mat = DenseMatrix(np.mat([[3,4,5,6]]))
        a2_mat = DenseMatrix(np.mat([[1,2,3,4]]))
        a_mat = a_space.cooccurrence_matrix

        a_space = Space(a_mat, ["a1", "a2"], [], element_shape=(2,3))
        model = LexicalFunction(function_space=a_space, intercept=True)
        model._MIN_SAMPLES = 1
        comp_space = model.compose(train_data, n_space)

        self.assertListEqual(comp_space.id2row, ["a1_man", "a2_car", "a1_boy", "a2_boy"])
        self.assertListEqual(comp_space.id2column, [])

        self.assertEqual(comp_space.element_shape, (2,))

        np.testing.assert_array_almost_equal(comp_space.cooccurrence_matrix.mat,
                                             an_mat[[0,4,2,5]].mat, 8)
Esempio n. 2
0
    def test_intercept_lstsq_regression(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]]))

        res1 = Linalg.lstsq_regression(a, b)
        res2 = Linalg.lstsq_regression(a, b, intercept=True)

        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 = a.hstack(DenseMatrix(np.ones((a.shape[0], 1))))
        self.assertGreater(((a * res1) - b).norm(), ((new_a * res2) - b).norm())
Esempio n. 3
0
    def _dense_svd(matrix_, reduced_dimension):

        print "Running dense svd"
        u, s, vt = np.linalg.svd(matrix_.mat, False, True)
        rank = len(s[s > Linalg._SVD_TOL])

        no_cols = min(u.shape[1], reduced_dimension, rank)
        u = DenseMatrix(u[:,0:no_cols])
        s = s[0:no_cols]
        v = DenseMatrix(vt[0:no_cols,:].transpose())

        Linalg._check_reduced_dim(matrix_.shape[1], u.shape[1], reduced_dimension)

        if not u.is_mostly_positive():
            u = -u
            v = -v

        return u, s, v
Esempio n. 4
0
    def test_dense_lstsq_regression(self):

        test_cases = self.pinv_test_cases
        for m, m_inv in test_cases:
            m1 = DenseMatrix(m)
            id_ = DenseMatrix.identity(m1.shape[0])

            res = Linalg.lstsq_regression(m1, id_)
            np.testing.assert_array_almost_equal(res.mat, m_inv, 7)
    def test_space_compose_dense(self):

        test_cases = [([("a","b","a_b")], self.space4, self.space5, DenseMatrix.identity(2), DenseMatrix.identity(2)),
                      ([("a","b","a_b")], self.space4, self.space6, np.mat([[0,0],[0,0]]), np.mat([[0,0],[0,0]])),
                      ([("a","b","a_b"),("a","b","a_a")], self.space4, self.space7, DenseMatrix.identity(2), DenseMatrix.identity(2)),
                      ]
        
        for in_data, arg_space, phrase_space, mat_a, mat_b in test_cases:
            comp_model = FullAdditive(A=mat_a, B=mat_b)
            comp_space = comp_model.compose(in_data, arg_space)
            
            np.testing.assert_array_almost_equal(comp_space.cooccurrence_matrix.mat,
                                                 phrase_space.cooccurrence_matrix.mat, 10)
                  
            self.assertListEqual(comp_space.id2column, [])
            self.assertDictEqual(comp_space.column2id, {})
            
            self.assertListEqual(comp_space.id2row, phrase_space.id2row)
            self.assertDictEqual(comp_space.row2id, phrase_space.row2id)
            
            self.assertFalse(comp_model._has_intercept)
 def test_space_compose_sparse(self):
     #WHAT TO DO HERE???
     #PARAMTERS ARE GIVEN AS DENSE MATRICES, INPUT DATA AS SPARSE??
     
     test_cases = [([("a","b","a_b")], self.space1, self.space2, DenseMatrix.identity(2), DenseMatrix.identity(2)),
                   ([("a","b","a_b")], self.space1, self.space3, np.mat([[0,0],[0,0]]), np.mat([[0,0],[0,0]]))
                   ]
     
     for in_data, arg_space, phrase_space, mat_a, mat_b in test_cases:
         comp_model = FullAdditive(A=mat_a, B=mat_b)
         comp_space = comp_model.compose(in_data, arg_space)
         
         np.testing.assert_array_almost_equal(comp_space.cooccurrence_matrix.mat.todense(),
                                              phrase_space.cooccurrence_matrix.mat.todense(), 10)
Esempio n. 7
0
    def setUp(self):
        self.a = np.array([[1, 2, 3], [4, 0, 5]])
        self.b = np.array([[0, 0, 0], [0, 0, 0]])

        self.c = np.array([[0, 0], [0, 0], [0, 0]])
        self.d = np.array([[1, 0], [0, 1]])
        self.e = np.array([1, 10])
        self.f = np.array([1, 10, 100])

        self.matrix_a = DenseMatrix(self.a)
        self.matrix_b = DenseMatrix(self.b)

        self.matrix_c = DenseMatrix(self.c)
        self.matrix_d = DenseMatrix(self.d)
Esempio n. 8
0
    def test_dense_ridge_regression(self):
        test_cases = self.pinv_test_cases
        for m, m_inv in test_cases:
            m1 = DenseMatrix(m)
            id_ = DenseMatrix.identity(m1.shape[0])

            res1 = Linalg.lstsq_regression(m1, id_)
            np.testing.assert_array_almost_equal(res1.mat, m_inv, 7)

            res2 = Linalg.ridge_regression(m1, id_, 1)[0]

            error1 = (m1 * res1 - DenseMatrix(m_inv)).norm()
            error2 = (m1 * res2 - DenseMatrix(m_inv)).norm()

            #print "err", error1, error2

            norm1 = error1 + res1.norm()
            norm2 = error2 + res2.norm()

            #print "norm", norm1, norm2

            #THIS SHOULD HOLD, BUT DOES NOT, MAYBE ROUNDING ERROR?
            #self.assertGreaterEqual(error2, error1)
            self.assertGreaterEqual(norm1, norm2)
Esempio n. 9
0
 def train(self, matrix_a, matrix_b=None):
     """
     matrix_b is ignored
     """
     W = DenseMatrix.identity(matrix_a.shape[1])
     return W
Esempio n. 10
0
    def test_3d(self):

        # setting up
        v_mat = DenseMatrix(np.mat([[0,0,1,1,2,2,3,3],#hate
                                    [0,1,2,4,5,6,8,9]])) #love


        vo11_mat = DenseMatrix(np.mat([[0,11],[22,33]])) #hate boy
        vo12_mat = DenseMatrix(np.mat([[0,7],[14,21]])) #hate man
        vo21_mat = DenseMatrix(np.mat([[6,34],[61,94]])) #love boy
        vo22_mat = DenseMatrix(np.mat([[2,10],[17,26]])) #love car

        train_vo_data = [("hate_boy", "man", "man_hate_boy"),
                      ("hate_man", "man", "man_hate_man"),
                      ("hate_boy", "boy", "boy_hate_boy"),
                      ("hate_man", "boy", "boy_hate_man"),
                      ("love_car", "boy", "boy_love_car"),
                      ("love_boy", "man", "man_love_boy"),
                      ("love_boy", "boy", "boy_love_boy"),
                      ("love_car", "man", "man_love_car")
                      ]

        # if do not find a phrase
        # what to do?
        train_v_data = [("love", "boy", "love_boy"),
                        ("hate", "man", "hate_man"),
                        ("hate", "boy", "hate_boy"),
                        ("love", "car", "love_car")]


        sentences = ["man_hate_boy", "car_hate_boy", "boy_hate_boy",
                     "man_hate_man", "car_hate_man", "boy_hate_man",
                     "man_love_boy", "car_love_boy", "boy_love_boy",
                     "man_love_car", "car_love_car", "boy_love_car" ]
        n_mat = DenseMatrix(np.mat([[3,4],[1,2],[5,6]]))


        n_space = Space(n_mat, ["man", "car", "boy"], self.ft)

        s1_mat = (vo11_mat * n_mat.transpose()).transpose()
        s2_mat = (vo12_mat * n_mat.transpose()).transpose()
        s3_mat = (vo21_mat * n_mat.transpose()).transpose()
        s4_mat = (vo22_mat * n_mat.transpose()).transpose()

        s_mat = vo11_mat.nary_vstack([s1_mat,s2_mat,s3_mat,s4_mat])
        s_space = Space(s_mat, sentences, self.ft)

        #test train 2d
        model = LexicalFunction(learner=LstsqRegressionLearner(intercept=False))
        model._MIN_SAMPLES = 1
        model.train(train_vo_data, n_space, s_space)
        vo_space = model.function_space

        self.assertListEqual(vo_space.id2row, ["hate_boy", "hate_man","love_boy", "love_car"])
        self.assertTupleEqual(vo_space.element_shape, (2,2))
        vo11_mat.reshape((1,4))
        np.testing.assert_array_almost_equal(vo11_mat.mat,
                                             vo_space.cooccurrence_matrix.mat[0])
        vo12_mat.reshape((1,4))
        np.testing.assert_array_almost_equal(vo12_mat.mat,
                                             vo_space.cooccurrence_matrix.mat[1])
        vo21_mat.reshape((1,4))
        np.testing.assert_array_almost_equal(vo21_mat.mat,
                                             vo_space.cooccurrence_matrix.mat[2])
        vo22_mat.reshape((1,4))
        np.testing.assert_array_almost_equal(vo22_mat.mat,
                                             vo_space.cooccurrence_matrix.mat[3])

        # test train 3d
        model2 = LexicalFunction(learner=LstsqRegressionLearner(intercept=False))
        model2._MIN_SAMPLES = 1
        model2.train(train_v_data, n_space, vo_space)
        v_space = model2.function_space
        np.testing.assert_array_almost_equal(v_mat.mat,
                                             v_space.cooccurrence_matrix.mat)
        self.assertListEqual(v_space.id2row, ["hate","love"])
        self.assertTupleEqual(v_space.element_shape, (2,2,2))

        # test compose 3d
        vo_space2 = model2.compose(train_v_data, n_space)
        id2row1 = list(vo_space.id2row)
        id2row2 = list(vo_space2.id2row)
        id2row2.sort()
        self.assertListEqual(id2row1, id2row2)
        row_list = vo_space.id2row
        vo_rows1 = vo_space.get_rows(row_list)
        vo_rows2 = vo_space2.get_rows(row_list)
        np.testing.assert_array_almost_equal(vo_rows1.mat, vo_rows2.mat,7)
        self.assertTupleEqual(vo_space.element_shape, vo_space2.element_shape)
Esempio n. 11
0
class TestDenseMatrix(unittest.TestCase):
    def setUp(self):
        self.a = np.array([[1, 2, 3], [4, 0, 5]])
        self.b = np.array([[0, 0, 0], [0, 0, 0]])

        self.c = np.array([[0, 0], [0, 0], [0, 0]])
        self.d = np.array([[1, 0], [0, 1]])
        self.e = np.array([1, 10])
        self.f = np.array([1, 10, 100])

        self.matrix_a = DenseMatrix(self.a)
        self.matrix_b = DenseMatrix(self.b)

        self.matrix_c = DenseMatrix(self.c)
        self.matrix_d = DenseMatrix(self.d)

    def tearDown(self):
        pass

    def test_init(self):
        nparr = self.a
        test_cases = [nparr, np.mat(nparr), csr_matrix(nparr), csc_matrix(nparr), SparseMatrix(nparr)]

        for inmat in test_cases:
            outmat = DenseMatrix(inmat)
            self.assertIsInstance(outmat.mat, np.matrix)
            numpy.testing.assert_array_equal(nparr, np.array(outmat.mat))

    def test_add(self):
        test_cases = [
            (self.matrix_a, self.matrix_a, np.mat([[2, 4, 6], [8, 0, 10]])),
            (self.matrix_a, self.matrix_b, self.matrix_a.mat),
        ]

        for (term1, term2, expected) in test_cases:
            sum_ = term1 + term2
            numpy.testing.assert_array_equal(sum_.mat, expected)
            self.assertIsInstance(sum_, type(term1))

    def test_add_raises(self):
        test_cases = [(self.matrix_a, self.a), (self.matrix_a, SparseMatrix(self.a))]

        for (term1, term2) in test_cases:
            self.assertRaises(TypeError, term1.__add__, term2)

    def test_div(self):
        test_cases = [
            (self.matrix_a, 2, np.mat([[0.5, 1.0, 1.5], [2.0, 0.0, 2.5]])),
            (self.matrix_c, 2, np.mat(self.c)),
        ]

        for (term1, term2, expected) in test_cases:
            sum_ = term1 / term2
            numpy.testing.assert_array_equal(sum_.mat, expected)
            self.assertIsInstance(sum_, DenseMatrix)

    def test_div_raises(self):
        test_cases = [
            (self.matrix_a, self.a, TypeError),
            (self.matrix_a, SparseMatrix(self.a), TypeError),
            (self.matrix_a, "3", TypeError),
            (self.matrix_a, 0, ZeroDivisionError),
        ]

        for (term1, term2, error_type) in test_cases:
            self.assertRaises(error_type, term1.__div__, term2)

    def test_mul(self):
        test_cases = [
            (self.matrix_a, self.matrix_c, np.mat([[0, 0], [0, 0]])),
            (self.matrix_d, self.matrix_a, self.matrix_a.mat),
            (self.matrix_a, 2, np.mat([[2, 4, 6], [8, 0, 10]])),
            (2, self.matrix_a, np.mat([[2, 4, 6], [8, 0, 10]])),
            (self.matrix_a, np.int64(2), np.mat([[2, 4, 6], [8, 0, 10]])),
            (np.int64(2), self.matrix_a, np.mat([[2, 4, 6], [8, 0, 10]])),
        ]

        for (term1, term2, expected) in test_cases:
            sum_ = term1 * term2
            numpy.testing.assert_array_equal(sum_.mat, expected)
            self.assertIsInstance(sum_, DenseMatrix)

    def test_mul_raises(self):
        test_cases = [
            (self.matrix_a, self.a),
            (self.matrix_a, SparseMatrix(self.a)),
            (self.matrix_a, "3"),
            ("3", self.matrix_a),
        ]

        for (term1, term2) in test_cases:
            self.assertRaises(TypeError, term1.__mul__, term2)

    def test_multiply(self):
        test_cases = [
            (self.matrix_a, self.matrix_a, np.mat([[1, 4, 9], [16, 0, 25]])),
            (self.matrix_a, self.matrix_b, np.mat(self.b)),
        ]

        for (term1, term2, expected) in test_cases:
            mult1 = term1.multiply(term2)
            mult2 = term2.multiply(term1)

            numpy.testing.assert_array_equal(mult1.mat, expected)
            numpy.testing.assert_array_equal(mult2.mat, expected)

            self.assertIsInstance(mult1, DenseMatrix)
            self.assertIsInstance(mult2, DenseMatrix)

    def test_multiply_raises(self):

        test_cases = [
            (self.matrix_a, self.matrix_d, ValueError),
            (self.matrix_a, self.a, TypeError),
            (self.matrix_a, SparseMatrix(self.a), TypeError),
        ]

        for (term1, term2, error_type) in test_cases:
            self.assertRaises(error_type, term1.multiply, term2)

    def test_scale_rows(self):
        outcome = np.mat([[1, 2, 3], [40, 0, 50]])
        test_cases = [(self.matrix_a, self.e, outcome), (self.matrix_a, np.mat(self.e).T, outcome)]

        for (term1, term2, expected) in test_cases:
            term1 = term1.scale_rows(term2)
            numpy.testing.assert_array_equal(term1.mat, expected)

    def test_scale_columns(self):
        test_cases = [(self.matrix_a, self.f, np.mat([[1, 20, 300], [4, 0, 500]]))]

        for (term1, term2, expected) in test_cases:
            term1 = term1.scale_columns(term2)
            numpy.testing.assert_array_equal(term1.mat, expected)

    def test_scale_raises(self):
        test_cases = [
            (self.matrix_a, self.f, ValueError, self.matrix_a.scale_rows),
            (self.matrix_a, self.e, ValueError, self.matrix_a.scale_columns),
            (self.matrix_a, self.b, ValueError, self.matrix_a.scale_rows),
            (self.matrix_a, self.b, ValueError, self.matrix_a.scale_columns),
            (self.matrix_a, "3", TypeError, self.matrix_a.scale_rows),
        ]
        for (term1, term2, error_type, function) in test_cases:
            self.assertRaises(error_type, function, term2)

    def test_plog(self):
        m = DenseMatrix(np.mat([[0.5, 1.0, 1.5], [2.0, 0.0, 2.5]]))
        m_expected = np.mat([[0.0, 0.0, 0.4054], [0.6931, 0.0, 0.9162]])
        a_expected = np.mat([[0.0, 0.6931, 1.0986], [1.3862, 0.0, 1.6094]])
        test_cases = [(self.matrix_a.copy(), a_expected), (m, m_expected)]

        for (term, expected) in test_cases:
            term.plog()
            numpy.testing.assert_array_almost_equal(term.mat, expected, 3)
    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")
Esempio n. 13
0
 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 do lexical insertions by calling 
     #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 = [] #default semantic representation for syntactic elements we ignore
         else:
             numrep = [temp_numrep[0].transpose()]
             dimensionality=(temp_numrep[0].shape[1])
             if len(temp_numrep)>1:
                 # Matrices are "flattened", stored as vectors.
                 # We reshape each matrix to a normal shape (usually square)
                 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
         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))
         #get the arity of two daughter nodes in order to determine which of
         #them is the function and which is the argument
         arity1=len(matrep1)-1
         arity2=len(matrep2)-1
         # first, compute symbolic matrix representation
         if arity1-arity2 == 0:
             for x in range(0, arity1+1):
                 self._matrep.append('(' + matrep1[x] + '+' + matrep2[x] + ')')
         #left 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 vector of the mother node
                     self._matrep.append('(' + matrep2[x] + '+' + matrep2[arity2] + '*' + matrep1[x] + ')')
                 elif x < len(matrep1): # compute matrices of the mother node
                     if multiply_matrices: self._matrep.append('(' + matrep2[x] + '*' + matrep1[x] + ')')
                     else: self._matrep.append('(' + matrep2[x] + '+' + matrep1[x] + ')')
                 else:
                     self._matrep.append(matrep2[x])
         #right 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] + ')')
                 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])
     #if one of the daughters is 'empty' (marked to be ignored), ignore it
         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.
         # First, get arity of the daughters to establish the directionality
         # of function application
         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 application
         if arity1 < arity2 and not numrep1==[] and not numrep2==[]:
             for x in range(0, arity2):
                 # compute the vector
                 if x == 0:
                     self._numrep.append(numrep2[x].__add__(numrep2[arity2] * numrep1[x]))
                 # compute a matrix
                 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 aplication
         if arity1 > arity2 and not numrep1==[] and not numrep2==[]:
             for x in range(0, arity1):
                 if x == 0:
                     self._numrep.append(numrep1[x].__add__(numrep1[arity1]*numrep2[x]))
                 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 in composition
         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")
Esempio n. 14
0
    def tracenorm_regression(matrix_a , matrix_b, lmbd, iterations, intercept=False):
        #log.print_info(logger, "In Tracenorm 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 Trace Norm Regression.

        This method uses approximate gradient descent
        to solve the problem:
            :math:`X = argmin(||AX - B||_2 + \\lambda||X||_*)`
        where :math:`||X||_*` is the trace norm of :math:`X`, the sum of its
        singular values.
        It is implemented for dense matrices only.
        The algorithm is the Extended Gradient Algorithm from (Ji and Ye, 2009).

        Args:
            matrix_a: input matrix A, of type Matrix
            matrix_b: input matrix A, of type Matrix. If None, it is defined as matrix_a
            lambda_: scalar, lambda parameter
            intercept: bool. If True intercept is used. Optional, default False.

        Returns:
            solution X of type Matrix

        """

        if intercept:
            matrix_a = matrix_a.hstack(matrix_type(np.ones((matrix_a.shape[0],
                                                             1))))
        if matrix_b == None:
            matrix_b = matrix_a

        
        # TODO remove this
        matrix_a = DenseMatrix(matrix_a).mat
        matrix_b = DenseMatrix(matrix_b).mat

        # Matrix shapes
        p = matrix_a.shape[0]
        q = matrix_a.shape[1]
        assert_same_shape(matrix_a, matrix_b, 0)

        # Initialization of the algorithm
        W = (1.0/p)* Linalg._kronecker_product(matrix_a)

        # Sub-expressions reused at various places in the code
        matrix_a_t = matrix_a.transpose()
        at_times_a = np.dot(matrix_a_t, matrix_a)

        # Epsilon: to ensure that our bound on the Lipschitz constant is large enough
        epsilon_lbound = 0.05
        # Expression of the bound of the Lipschitz constant of the cost function
        L_bound = (1+epsilon_lbound)*2*Linalg._frobenius_norm_squared(at_times_a)
        # Current "guess" of the local Lipschitz constant
        L = 1.0
        # Factor by which L should be increased when it happens to be too small
        gamma = 1.2
        # Epsilon to ensure that mu is increased when the inequality hold tightly
        epsilon_cost = 0.00001
        # Real lambda: resized according to the number of training samples (?)
        lambda_ = lmbd*p
        # Variables used for the accelerated algorithm (check the original paper)
        Z = W
        alpha = 1.0
        # Halting condition
        epsilon = 0.00001
        last_cost = 1
        current_cost = -1
        linalg_error_caught = False

        costs = []
        iter_counter = 0
        while iter_counter < iterations and (abs((current_cost - last_cost)/last_cost)>epsilon) and not linalg_error_caught:
            sys.stdout.flush()
            # Cost tracking
            try:
                next_W, tracenorm = Linalg._next_tracenorm_guess(matrix_a, matrix_b, lambda_, L, Z, at_times_a)
            except LinAlgError:
                print "LinAlgError caught in trace norm regression"
                linalg_error_caught = True
                break

            last_cost = current_cost
            current_fitness = Linalg._fitness(matrix_a, matrix_b, next_W)
            current_cost = current_fitness + lambda_ * tracenorm
            if iter_counter > 0: # The first scores are messy
                cost_list =  [L, L_bound, current_fitness, current_cost]
                costs.append(cost_list)

            while (current_fitness + epsilon_cost >=
                    Linalg._intermediate_cost(matrix_a, matrix_b, next_W, Z, L)):
                if L > L_bound:
                    print "Trace Norm Regression: numerical error detected at iteration "+str(iter_counter)
                    break
                L = gamma * L
                try:
                    next_W, tracenorm = Linalg._next_tracenorm_guess(matrix_a, matrix_b, lambda_, L, Z, at_times_a)
                except LinAlgError:
                    print "LinAlgError caught in trace norm regression"
                    linalg_error_caught = True
                    break

                last_cost = current_cost
                current_fitness = Linalg._fitness(matrix_a, matrix_a, next_W)
                current_cost = current_fitness + lambda_*tracenorm

            if linalg_error_caught:
                break

            previous_W = W
            W = next_W
            previous_alpha = alpha
            alpha = (1.0 + sqrt(1.0 + 4.0*alpha*alpha))/2.0
            Z = W
            # Z = W + ((alpha - 1)/alpha)*(W - previous_W)
            iter_counter += 1

        sys.stdout.flush()
        W = np.real(W)
        return DenseMatrix(W), costs