Ignore:
Location:
Orange
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • Orange/projection/linear.py

    r10613 r10645  
    163163 
    164164        return Projector(input_domain=domain, 
    165                          mean=Xm, 
    166                          stdev=stdev, 
     165                         center=Xm, 
     166                         scale=stdev, 
    167167                         standardize=False, 
    168168                         projection=U) 
     
    933933        if method == DR_PCA: 
    934934            pca = Pca(standardize=False, max_components=ncomps, 
    935                       use_generalized_eigenvectors=False) 
     935                      use_generalized_eigenvectors=False, ddof=0) 
    936936            domain = data.Domain([feature.Continuous("g%d" % i) for i 
    937937                                  in xrange(len(data_matrix))], False) 
     
    940940        elif method == DR_SPCA and self.graph.data_has_class: 
    941941            pca = Spca(standardize=False, max_components=ncomps, 
    942                        use_generalized_eigenvectors=self.use_generalized_eigenvectors) 
     942                       use_generalized_eigenvectors=self.use_generalized_eigenvectors, ddof=0) 
    943943            domain = data.Domain([feature.Continuous("g%d" % i) for i 
    944944                                  in xrange(len(data_matrix))], feature.Continuous("c")) 
     
    12091209    #: Array containing means of each variable in the data set that was used 
    12101210    #: to construct the projection. 
    1211     mean = numpy.array(()) 
     1211    center = numpy.array(()) 
    12121212 
    12131213    #: An array containing standard deviations of each variable in the data 
    12141214    #: set that was used to construct the projection. 
    1215     stdev = numpy.array(()) 
     1215    scale = numpy.array(()) 
    12161216 
    12171217    #: True, if standardization was used when constructing the projection. If 
     
    12381238    def _project_single(self, example, return_what, new_feature, feature_idx): 
    12391239        ex = Orange.data.Table([example]).to_numpy("a")[0] 
    1240         ex -= self.mean 
     1240        ex -= self.center 
    12411241        if self.standardize: 
    1242             ex /= self.stdev 
     1242            ex /= self.scale 
    12431243        return new_feature(numpy.dot(self.projection[feature_idx, :], ex.T)[0]) 
    12441244 
     
    12571257            dataset = data.Table(self.input_domain, dataset) 
    12581258 
    1259         X, = dataset.to_numpy("a") 
    1260         Xm, U = self.mean, self.projection 
     1259        X, = dataset.to_numpy_MA("a") 
     1260        Xm, U = self.center, self.projection 
    12611261        n, m = X.shape 
    12621262 
     
    12671267 
    12681268        if self.standardize: 
    1269             Xd /= self.stdev 
     1269            Xd /= self.scale 
    12701270 
    12711271        self.A = numpy.dot(Xd, U.T) 
    1272  
    1273         # TODO: Delete when orange will support creating data.Table from masked array. 
    1274         self.A = self.A.filled(0.) if isinstance(self.A, numpy.ma.core.MaskedArray) else self.A 
    1275         # append class variable 
    12761272 
    12771273        class_, classes = dataset.to_numpy("c")[0], dataset.to_numpy("m")[0] 
     
    12991295    """ 
    13001296 
     1297    #: Delta degrees of freedom used for numpy operations. 
     1298    #: 1 means normalization with (N-1) in cov and std operations 
     1299    ddof = 1 
     1300 
    13011301    def __new__(cls, dataset=None, **kwds): 
    13021302        optimizer = object.__new__(cls) 
     
    13441344 
    13451345        return PcaProjector(input_domain=dataset.domain, 
    1346                             mean=mean, 
    1347                             stdev=stdev, 
     1346                            center=mean, 
     1347                            scale=stdev, 
    13481348                            standardize=self.standardize, 
    1349                             eigen_vectors=components, 
    13501349                            projection=components, 
    1351                             eigen_values=variances, 
     1350                            variances=variances, 
    13521351                            variance_sum=variance_sum) 
    13531352 
     
    13551354        if not len(dataset) or not len(dataset.domain.features): 
    13561355            raise ValueError("Empty dataset") 
    1357         X = dataset.to_numpy("a")[0] 
     1356        X = dataset.to_numpy_MA("a")[0] 
    13581357 
    13591358        Xm = numpy.mean(X, axis=0) 
     
    13641363 
    13651364        #take care of the constant features 
    1366         stdev = numpy.std(Xd, axis=0) 
     1365        stdev = numpy.std(Xd, axis=0, ddof=self.ddof) 
    13671366        stdev[stdev == 0] = 1. # to prevent division by zero 
    13681367        relevant_features = stdev != 0 
     
    13751374        n, m = Xd.shape 
    13761375        if n < m: 
    1377             C = numpy.dot(Xg.T, Xd.T) 
     1376            C = numpy.dot(Xg.T, Xd.T) / (m - self.ddof) 
    13781377            V, D, T = numpy.linalg.svd(C) 
    1379             U = numpy.dot(V.T, Xd) / numpy.sqrt(D.reshape(-1, 1)) 
     1378            U = numpy.dot(V.T, Xd) / numpy.sqrt(D.reshape(-1, 1) * (m - self.ddof)) 
    13801379        else: 
    1381             C = numpy.dot(Xg, Xd) 
     1380            C = numpy.dot(Xg, Xd) / (n - self.ddof) 
    13821381            U, D, T = numpy.linalg.svd(C) 
    13831382            U = U.T  # eigenvectors are now in rows 
     
    14081407 
    14091408 
    1410 class Spca(Pca): 
     1409class Spca(PCA): 
    14111410    def _perform_pca(self, dataset, Xd, Xg): 
    14121411        # define the Laplacian matrix 
     
    14221421@deprecated_members({"pc_domain": "output_domain"}) 
    14231422class PcaProjector(Projector): 
    1424     #: Synonymous for :obj:`~Orange.projection.linear.Projector.projection`. 
    1425     eigen_vectors = numpy.array(()).reshape(0, 0) 
    1426  
    1427     #: Array containing standard deviations of principal components. 
    1428     eigen_values = numpy.array(()) 
     1423    #: Array containing variances of principal components. 
     1424    variances = numpy.array(()) 
    14291425 
    14301426    #: Sum of all variances in the data set that was used to construct the PCA space. 
     
    14341430        ncomponents = 10 
    14351431        s = self.variance_sum 
    1436         cs = numpy.cumsum(self.eigen_values) / s 
     1432        cs = numpy.cumsum(self.variances) / s 
     1433        stdev = numpy.sqrt(self.variances) 
    14371434        return "\n".join([ 
    14381435            "PCA SUMMARY", 
     
    14421439                     ["%10s" % a.name for a in self.output_domain.attributes]), 
    14431440            " ".join(["Std. deviation"] + 
    1444                      ["%10.3f" % a for a in self.eigen_values]), 
     1441                     ["%10.3f" % a for a in stdev]), 
    14451442            " ".join(["Proportion Var"] + 
    1446                      ["%10.3f" % a for a in self.eigen_values / s * 100]), 
     1443                     ["%10.3f" % a for a in self.variances / s * 100]), 
    14471444            " ".join(["Cumulative Var"] + 
    14481445                     ["%10.3f" % a for a in cs * 100]), 
     
    14581455                     ["%10s" % self.output_domain.attributes[-1].name]), 
    14591456            " ".join(["Std. deviation"] + 
    1460                      ["%10.3f" % a for a in self.eigen_values[:ncomponents]] + 
     1457                     ["%10.3f" % a for a in stdev[:ncomponents]] + 
    14611458                     ["%10s" % ""] + 
    1462                      ["%10.3f" % self.eigen_values[-1]]), 
     1459                     ["%10.3f" % stdev[-1]]), 
    14631460            " ".join(["Proportion Var"] + 
    1464                      ["%10.3f" % a for a in self.eigen_values[:ncomponents] / s * 100] + 
     1461                     ["%10.3f" % a for a in self.variances[:ncomponents] / s * 100] + 
    14651462                     ["%10s" % ""] + 
    1466                      ["%10.3f" % (self.eigen_values[-1] / s * 100)]), 
     1463                     ["%10.3f" % (self.variances[-1] / s * 100)]), 
    14671464            " ".join(["Cumulative Var"] + 
    14681465                     ["%10.3f" % a for a in cs[:ncomponents] * 100] + 
     
    14861483 
    14871484        s = self.variance_sum 
    1488         vc = self.eigen_values / s 
    1489         cs = numpy.cumsum(self.eigen_values) / s 
     1485        vc = self.variances / s 
     1486        cs = numpy.cumsum(self.variances) / s 
    14901487 
    14911488        fig = plt.figure() 
    14921489        ax = fig.add_subplot(111) 
    14931490 
    1494         x_axis = range(len(self.eigen_values)) 
     1491        x_axis = range(len(self.variances)) 
    14951492        plt.grid(True) 
    14961493 
     
    15051502        ax.legend(loc=0) 
    15061503 
    1507         ax.axis([-0.5, len(self.eigen_values) - 0.5, 0, 1]) 
     1504        ax.axis([-0.5, len(self.variances) - 0.5, 0, 1]) 
    15081505 
    15091506        if filename: 
     
    15301527            raise ValueError, 'Two components are needed for biplot' 
    15311528 
    1532         if not (0 <= min(components) <= max(components) < len(self.eigen_values)): 
     1529        if not (0 <= min(components) <= max(components) < len(self.variances)): 
    15331530            raise ValueError, 'Invalid components' 
    15341531 
     
    15361533        Y = self.A[:, components[1]] 
    15371534 
    1538         vectorsX = self.eigen_vectors[:, components[0]] 
    1539         vectorsY = self.eigen_vectors[:, components[1]] 
    1540  
    1541         max_load_value = self.eigen_vectors.max() * 1.5 
     1535        vectorsX = self.variances[:, components[0]] 
     1536        vectorsY = self.variances[:, components[1]] 
     1537 
     1538        max_load_value = self.variances.max() * 1.5 
    15421539 
    15431540        fig = plt.figure() 
    15441541        ax1 = fig.add_subplot(111) 
    15451542        ax1.set_title(title + "\n") 
    1546         ax1.set_xlabel("PC%s (%d%%)" % (components[0], self.eigen_values[components[0]] / self.variance_sum * 100)) 
    1547         ax1.set_ylabel("PC%s (%d%%)" % (components[1], self.eigen_values[components[1]] / self.variance_sum * 100)) 
     1543        ax1.set_xlabel("PC%s (%d%%)" % (components[0], self.variances[components[0]] / self.variance_sum * 100)) 
     1544        ax1.set_ylabel("PC%s (%d%%)" % (components[1], self.variances[components[1]] / self.variance_sum * 100)) 
    15481545        ax1.xaxis.set_label_position('bottom') 
    15491546        ax1.xaxis.set_ticks_position('bottom') 
     
    16721669        return FdaProjector(input_domain=dataset.domain, 
    16731670                            output_domain=out_domain, 
    1674                             mean=Xm, 
    1675                             stdev=stdev, 
     1671                            center=Xm, 
     1672                            scale=stdev, 
    16761673                            standardize=True, 
    16771674                            eigen_vectors=U, 
  • Orange/testing/unit/tests/test_projection_linear.py

    r10612 r10645  
    2828 
    2929 
     30 
    3031class TestPca(unittest.TestCase): 
    3132    def create_normal_dataset(self): 
     
    4344        self.dataset = data.Table(*prepare_dataset(components=([0, 0, 0, 0, 0],))) 
    4445 
    45     def create_dataset_with_classes(self): 
    46         domain, features = prepare_dataset(components=[[random.randint(0, 5) for _ in range(10)]]) 
    47         domain = data.Domain(domain.features, 
    48                              feature.Discrete("C", values=["F", "T"]), 
    49                              class_vars=[feature.Discrete("MC%i" % i, values=["F", "T"]) for i in range(4)]) 
     46    def create_dataset_with_unknowns(self, percentage=0.05): 
     47        self.principal_component = normalize([random.randint(0, 5) for _ in range(10)]) 
     48        self.dataset = data.Table(*prepare_dataset(components=[self.principal_component])) 
    5049 
    51         self.dataset = data.Table(domain, np.hstack((features, np.random.random((len(features), 5))))) 
     50        for ex in self.dataset: 
     51            for i, _ in enumerate(ex): 
     52                if random.random() < percentage: 
     53                    ex[i] = "?" 
    5254 
    5355 
     
    5860        self.assertIsInstance(pca, linear.PcaProjector) 
    5961 
    60         absolute_error = (np.abs(pca.eigen_vectors[0]) - np.abs(self.principal_component)).sum() 
     62        absolute_error = (np.abs(pca.projection[0]) - np.abs(self.principal_component)).sum() 
    6163        self.assertAlmostEqual(absolute_error, 0.) 
    6264 
     
    6769        self.assertIsInstance(pca, linear.PcaProjector) 
    6870 
    69         absolute_error = (np.abs(pca.eigen_vectors[0]) - np.abs(self.principal_component)).sum() 
     71        absolute_error = (np.abs(pca.projection[0]) - np.abs(self.principal_component)).sum() 
    7072        self.assertAlmostEqual(absolute_error, 0., 1) 
    7173 
     
    7476 
    7577        pca = linear.Pca(standardize=True)(self.dataset) 
    76         eigen_vector = pca.eigen_vectors[0] 
     78        eigen_vector = pca.projection[0] 
    7779        non_zero_elements = eigen_vector[eigen_vector.nonzero()] 
    7880 
     
    8587        pca = linear.Pca(variance_covered=.99)(self.dataset) 
    8688        # all data points lie in one dimension, one component should cover all the variance 
    87         nvectors, vector_dimension = pca.eigen_vectors.shape 
     89        nvectors, vector_dimension = pca.projection.shape 
    8890        self.assertEqual(nvectors, 1) 
    8991 
     
    9496        pca = linear.Pca(max_components=max_components)(self.dataset) 
    9597        # all data points lie in one dimension, one component should cover all the variance 
    96         nvectors, vector_dimension = pca.eigen_vectors.shape 
     98        nvectors, vector_dimension = pca.projection.shape 
    9799        self.assertEqual(nvectors, max_components) 
    98100 
    99     def test_pca_converts_domain(self): 
    100         self.create_dataset_with_classes() 
    101         pca = linear.Pca(variance_covered=.99)(self.dataset) 
     101    def test_pca_handles_unknowns(self): 
     102        self.create_dataset_with_unknowns() 
    102103 
    103         projected_data = pca(self.dataset) 
    104         converted_data = data.Table(projected_data.domain, self.dataset) 
     104        pca = linear.Pca()(self.dataset) 
    105105 
    106         self.assertItemsEqual(projected_data, converted_data) 
    107  
    108     def test_pca_converts_classless_domain(self): 
    109         self.create_normal_dataset() 
    110         pca = linear.Pca(variance_covered=.99)(self.dataset) 
    111  
    112         projected_data = pca(self.dataset) 
    113         converted_data = data.Table(projected_data.domain, self.dataset) 
    114  
    115         self.assertItemsEqual(projected_data, converted_data) 
    116  
    117     def test_pca_keeps_class_vars(self): 
    118         self.create_dataset_with_classes() 
    119  
    120         pca = linear.Pca(variance_covered=.99)(self.dataset) 
    121         projected_data = pca(self.dataset) 
    122  
    123         self.assertIn(self.dataset.domain.class_var, projected_data.domain) 
    124         for class_ in self.dataset.domain.class_vars: 
    125             self.assertIn(class_, projected_data.domain) 
    126         for ex1, ex2 in zip(self.dataset, projected_data): 
    127             self.assertEqual(ex1.get_class(), ex2.get_class()) 
    128             for v1, v2 in zip(ex1.get_classes(), ex2.get_classes()): 
    129                 self.assertEqual(v2, v2) 
    130106 
    131107 
     
    143119 
    144120 
     121class TestProjector(unittest.TestCase): 
     122    def create_normal_dataset(self): 
     123        self.principal_component = normalize([random.randint(0, 5) for _ in range(10)]) 
     124        self.dataset = data.Table(*prepare_dataset(components=[self.principal_component])) 
     125 
     126    def create_dataset_with_classes(self): 
     127        domain, features = prepare_dataset(components=[[random.randint(0, 5) for _ in range(10)]]) 
     128        domain = data.Domain(domain.features, 
     129                             feature.Discrete("C", values=["F", "T"]), 
     130                             class_vars=[feature.Discrete("MC%i" % i, values=["F", "T"]) for i in range(4)]) 
     131 
     132        self.dataset = data.Table(domain, np.hstack((features, np.random.random((len(features), 5))))) 
     133 
     134 
     135    def test_projected_domain_can_convert_data_with_class(self): 
     136        self.create_dataset_with_classes() 
     137        projector = linear.Pca(variance_covered=.99)(self.dataset) 
     138 
     139        projected_data = projector(self.dataset) 
     140        converted_data = data.Table(projected_data.domain, self.dataset) 
     141 
     142        self.assertItemsEqual(projected_data, converted_data) 
     143 
     144    def test_projected_domain_can_convert_data_without_class(self): 
     145        self.create_normal_dataset() 
     146        projector = linear.Pca(variance_covered=.99)(self.dataset) 
     147 
     148        projected_data = projector(self.dataset) 
     149        converted_data = data.Table(projected_data.domain, self.dataset) 
     150 
     151        self.assertItemsEqual(projected_data, converted_data) 
     152 
     153    def test_projected_domain_contains_class_vars(self): 
     154        self.create_dataset_with_classes() 
     155 
     156        projector = linear.Pca(variance_covered=.99)(self.dataset) 
     157        projected_data = projector(self.dataset) 
     158 
     159        self.assertIn(self.dataset.domain.class_var, projected_data.domain) 
     160        for class_ in self.dataset.domain.class_vars: 
     161            self.assertIn(class_, projected_data.domain) 
     162        for ex1, ex2 in zip(self.dataset, projected_data): 
     163            self.assertEqual(ex1.get_class(), ex2.get_class()) 
     164            for v1, v2 in zip(ex1.get_classes(), ex2.get_classes()): 
     165                self.assertEqual(v2, v2) 
     166 
     167 
     168    def test_projects_example(self): 
     169        self.create_normal_dataset() 
     170        projector = linear.Pca(variance_covered=.99)(self.dataset) 
     171 
     172        projector(self.dataset[0]) 
     173 
     174    def test_projects_data_table(self): 
     175        self.create_normal_dataset() 
     176        projector = linear.Pca(variance_covered=.99)(self.dataset) 
     177 
     178        projector(self.dataset) 
     179 
     180    def test_converts_input_domain_if_needed(self): 
     181        self.create_normal_dataset() 
     182        projector = linear.Pca(variance_covered=.99)(self.dataset) 
     183 
     184        new_examples = data.Table(data.Domain(self.dataset.domain.features[:5]), [[1.,2.,3.,4.,5.]]) 
     185 
     186        projector(new_examples) 
     187 
     188 
    145189class TestFda(unittest.TestCase): 
    146190    pass 
Note: See TracChangeset for help on using the changeset viewer.