001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.ml.clustering.spectral; 031 032import java.util.ArrayList; 033import java.util.List; 034 035import org.openimaj.citation.annotation.Reference; 036import org.openimaj.citation.annotation.ReferenceType; 037import org.openimaj.math.matrix.MatlibMatrixUtils; 038import org.openimaj.ml.clustering.IndexClusters; 039import org.openimaj.ml.clustering.MultiviewSimilarityClusterer; 040import org.openimaj.util.pair.IndependentPair; 041 042import ch.akuhn.matrix.DenseMatrix; 043import ch.akuhn.matrix.Matrix; 044import ch.akuhn.matrix.SparseMatrix; 045 046/** 047 * 048 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 049 * 050 */ 051@Reference( 052 type = ReferenceType.Incollection, 053 author = { "Abhishek Kumar", "Piyush Rai", "Hal Daume III" }, 054 title = "Co-regularized Multi-view Spectral Clustering", 055 year = "2011", 056 booktitle = "Advances in Neural Information Processing Systems 24", 057 pages = { "1413", "", "1421" }, 058 editor = { "J. Shawe-Taylor", "R.S. Zemel", "P. Bartlett", "F.C.N. Pereira", "K.Q. Weinberger" }) 059public class DoubleMultiviewSpectralClustering implements MultiviewSimilarityClusterer<IndexClusters> { 060 061 private MultiviewSpectralClusteringConf<double[]> conf; 062 063 /** 064 * @param conf 065 * cluster the eigen vectors 066 */ 067 public DoubleMultiviewSpectralClustering(MultiviewSpectralClusteringConf<double[]> conf) { 068 this.conf = conf; 069 } 070 071 @Override 072 public IndexClusters cluster(List<SparseMatrix> data) { 073 final DoubleSpectralClustering dsp = new DoubleSpectralClustering(conf); 074 075 if (data.size() == 1) { 076 return dsp.cluster(data.get(0)); 077 } 078 079 // Solve the spectral clustering for each view 080 final ArrayList<IndependentPair<double[], double[][]>> answers = new ArrayList<IndependentPair<double[], double[][]>>(data.size()); 081 PreparedSpectralClustering prep = new PreparedSpectralClustering(conf); 082 for (int i = 0; i < data.size(); i++) { 083 answers.add(prep.bestCols(dsp.spectralCluster(data.get(i)))); 084 } 085 while (!conf.stop.stop(answers)) { 086 for (int i = 0; i < answers.size(); i++) { 087 // L 088 final SparseMatrix laplacian = dsp.laplacian(data.get(i)); 089 // lambda * (Sum_w!=v u_w . u_w^T) 090 SparseMatrix ujujSum = null; 091 for (int j = 0; j < answers.size(); j++) { 092 if (i == j) 093 continue; 094 final Matrix uj = new DenseMatrix(answers.get(j).secondObject()); 095 final SparseMatrix ujuj = MatlibMatrixUtils.dotProductTranspose(uj, uj, 096 new SparseMatrix(uj.rowCount(), uj.rowCount())); 097 if (ujujSum == null) { 098 ujujSum = ujuj; 099 } 100 else { 101 MatlibMatrixUtils.plusInplace(ujujSum, ujuj); 102 } 103 } 104 // L + lambda * (Sum_w!=v u_w . u_w^T) 105 MatlibMatrixUtils.plusInplace(laplacian, MatlibMatrixUtils.scaleInplace(ujujSum, conf.lambda)); 106 // eig 107 answers.add(i, prep.bestCols(dsp.laplacianEigenVectors(laplacian))); 108 } 109 } 110 // Concatenate the eigen spaces and cluster using the conf clusterer 111 // return 112 // dsp.eigenspaceCluster(ArrayUtils.concatenate(answers.toArray(new 113 // double[answers.size()][][]))); 114 return null; 115 } 116 117 @Override 118 public int[][] performClustering(List<SparseMatrix> data) { 119 return this.cluster(data).clusters(); 120 } 121 122}