Source code for anomalib.models.components.dimensionality_reduction.pca
"""Principle Component Analysis (PCA) with PyTorch."""# Copyright (C) 2020 Intel Corporation## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing,# software distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions# and limitations under the License.fromtypingimportUnionimporttorchfromtorchimportTensorfromanomalib.models.components.baseimportDynamicBufferModule
[docs]classPCA(DynamicBufferModule):"""Principle Component Analysis (PCA). Args: n_components (float): Number of components. Can be either integer number of components or a ratio between 0-1. """def__init__(self,n_components:Union[float,int]):super().__init__()self.n_components=n_componentsself.register_buffer("singular_vectors",Tensor())self.register_buffer("mean",Tensor())self.register_buffer("num_components",Tensor())self.singular_vectors:Tensorself.singular_values:Tensorself.mean:Tensorself.num_components:Tensor
[docs]deffit(self,dataset:Tensor)->None:"""Fits the PCA model to the dataset. Args: dataset (Tensor): Input dataset to fit the model. """mean=dataset.mean(dim=0)dataset-=mean_,sig,v_h=torch.linalg.svd(dataset.double())num_components:intifself.n_components<=1:variance_ratios=torch.cumsum(sig*sig,dim=0)/torch.sum(sig*sig)num_components=torch.nonzero(variance_ratios>=self.n_components)[0]else:num_components=int(self.n_components)self.num_components=Tensor([num_components])self.singular_vectors=v_h.transpose(-2,-1)[:,:num_components].float()self.singular_values=sig[:num_components].float()self.mean=mean
[docs]deffit_transform(self,dataset:Tensor)->Tensor:"""Fit and transform PCA to dataset. Args: dataset (Tensor): Dataset to which the PCA if fit and transformed Returns: Transformed dataset """mean=dataset.mean(dim=0)dataset-=meannum_components=int(self.n_components)self.num_components=Tensor([num_components])v_h=torch.linalg.svd(dataset)[-1]self.singular_vectors=v_h.transpose(-2,-1)[:,:num_components]self.mean=meanreturntorch.matmul(dataset,self.singular_vectors)
[docs]deftransform(self,features:Tensor)->Tensor:"""Transforms the features based on singular vectors calculated earlier. Args: features (Tensor): Input features Returns: Transformed features """features-=self.meanreturntorch.matmul(features,self.singular_vectors)
[docs]definverse_transform(self,features:Tensor)->Tensor:"""Inverses the transformed features. Args: features (Tensor): Transformed features Returns: Inverse features """inv_features=torch.matmul(features,self.singular_vectors.transpose(-2,-1))returninv_features
[docs]defforward(self,features:Tensor)->Tensor:"""Transforms the features. Args: features (Tensor): Input features Returns: Transformed features """returnself.transform(features)