Package pyvision :: Package vector :: Module PCA
[hide private]
[frames] | no frames]

Source Code for Module pyvision.vector.PCA

  1  # PyVision License 
  2  # 
  3  # Copyright (c) 2006-2008 David S. Bolme 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  #  
 10  # 1. Redistributions of source code must retain the above copyright 
 11  # notice, this list of conditions and the following disclaimer. 
 12  #  
 13  # 2. Redistributions in binary form must reproduce the above copyright 
 14  # notice, this list of conditions and the following disclaimer in the 
 15  # documentation and/or other materials provided with the distribution. 
 16  #  
 17  # 3. Neither name of copyright holders nor the names of its contributors 
 18  # may be used to endorse or promote products derived from this software 
 19  # without specific prior written permission. 
 20  #  
 21  #  
 22  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 23  # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 24  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 25  # A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR 
 26  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 27  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 28  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 29  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 30  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 31  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 32  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 33   
 34  import logging 
 35  import pyvision as pv 
 36  import numpy 
 37  from numpy.linalg import svd 
 38   
39 -def show(feature):
40 pv.Image(feature.reshape(64,64)).show()
41 42 43 #####################################################################
44 -class PCA:
45 ''' Performs principal components analysis on a set of images, features, or vectors. ''' 46 47 48 #----------------------------------------------------------------
49 - def __init__(self, center_points=True, one_std=True ):
50 ''' Create a PCA object ''' 51 self.logger = logging.getLogger("pyvis") 52 self.features = [] 53 self.center_points = center_points
54 55 56 #----------------------------------------------------------------
57 - def __setstate__(self,state):
58 # Translate everything but the svm because that cannot be simply pickled. 59 for key,value in state.iteritems(): 60 if key == 'basis': 61 # Workaround for a numpy pickle problem. 62 # TODO: Remove this after numpy bug 551 is fixed. 63 self.basis = numpy.array(value) 64 continue 65 66 self.__dict__[key] = value
67 68 69 #----------------------------------------------------------------
70 - def addFeature(self,feature):
71 ''' Add a feature vector to the analysis. ''' 72 feat = self.toVector(feature) 73 74 self.features.append(feat)
75 76 77 #----------------------------------------------------------------
78 - def toVector(self,feature):
79 if isinstance(feature,pv.Image): 80 feat = feature.asMatrix2D().flatten() 81 return feat 82 if isinstance(feature,numpy.ndarray): 83 feat = feature.flatten() 84 return feat 85 raise TypeError("Could not create feature from type: %s"%type(feature))
86 87 88 #----------------------------------------------------------------
89 - def train(self, drop_front=None, number=None, energy=None):
90 ''' Compute the PCA basis vectors using the SVD ''' 91 self.logger.info("Computing PCA basis vectors.") 92 93 # One feature per row 94 features = numpy.array(self.features) 95 96 if self.center_points: 97 self.center = features.mean(axis=0) 98 for i in range(features.shape[0]): 99 features[i,:] -= self.center 100 #show(features[i,:]) 101 102 features = features.transpose() 103 104 u,d,_ = svd(features,full_matrices=0) 105 if drop_front: 106 u = u[:,drop_front:] 107 d = d[drop_front:] 108 109 if number: 110 u = u[:,:number] 111 d = d[:number] 112 if energy: 113 # compute teh sum of energy 114 s = 0.0 115 for each in d: 116 s += each*each 117 cutoff = energy * s 118 119 # compute the cutoff 120 s = 0.0 121 for i in range(len(d)): 122 each = d[i] 123 s += each*each 124 if s > cutoff: 125 break 126 127 u = u[:,:i] 128 d = d[:i] 129 130 self.basis = u.transpose() 131 self.values = d 132 133 # Remove features because they are no longer needed and 134 # they take up a lot of space. 135 del self.features
136 137 138 #----------------------------------------------------------------
139 - def project(self, feature, whiten=False):
140 ''' Transform a feature into its low dimentional representation ''' 141 feat = self.toVector(feature) 142 143 if self.center_points: 144 feat = feat - self.center 145 146 vec = numpy.dot(self.basis,feat) 147 148 if whiten: 149 vec = vec/numpy.sqrt(self.values) 150 151 return vec
152 153 154 #----------------------------------------------------------------
155 - def reconstruct(self,feat):
156 ''' return the eigen values for this computation ''' 157 feat = numpy.dot(self.basis.transpose(),feat) 158 if self.center_points: 159 feat += self.center 160 return feat
161 162 163 #----------------------------------------------------------------
164 - def getBasis(self):
165 ''' return the eigen vectors returned by the computation ''' 166 return self.basis
167 168 169 #----------------------------------------------------------------
170 - def getValues(self):
171 ''' return the bases used for transforming features ''' 172 return self.values
173 174 175 # TODO: Needs Unit Tests 176