public Clustering < M > run ( Database database , Relation < V > relation ) { if ( relation . size ( ) == 0 ) { throw new IllegalArgumentException ( "database empty: must contain elements" ) ; } // initial models List < ? extends EMClusterModel < M > > models = mfactory . buildInitialModels ( database , relation , k , SquaredEuclideanDistanceFunction . STATIC ) ; WritableDataStore < double [ ] > probClusterIGivenX = DataStoreUtil . makeStorage ( relation . getDBIDs ( ) , DataStoreFactory . HINT_HOT | DataStoreFactory . HINT_SORTED , double [ ] . class ) ; double loglikelihood = assignProbabilitiesToInstances ( relation , models , probClusterIGivenX ) ; DoubleStatistic likestat = LOG . isStatistics ( ) ? new DoubleStatistic ( this . getClass ( ) . getName ( ) + ".loglikelihood" ) : null ; if ( LOG . isStatistics ( ) ) { LOG . statistics ( likestat . setDouble ( loglikelihood ) ) ; } // iteration unless no change int it = 0 , lastimprovement = 0 ; double bestloglikelihood = loglikelihood ; // For detecting instabilities. for ( ++ it ; it < maxiter || maxiter < 0 ; it ++ ) { final double oldloglikelihood = loglikelihood ; recomputeCovarianceMatrices ( relation , probClusterIGivenX , models , prior ) ; // reassign probabilities loglikelihood = assignProbabilitiesToInstances ( relation , models , probClusterIGivenX ) ; if ( LOG . isStatistics ( ) ) { LOG . statistics ( likestat . setDouble ( loglikelihood ) ) ; } if ( loglikelihood - bestloglikelihood > delta ) { lastimprovement = it ; bestloglikelihood = loglikelihood ; } if ( Math . abs ( loglikelihood - oldloglikelihood ) <= delta || lastimprovement < it >> 1 ) { break ; } } if ( LOG . isStatistics ( ) ) { LOG . statistics ( new LongStatistic ( KEY + ".iterations" , it ) ) ; } // fill result with clusters and models List < ModifiableDBIDs > hardClusters = new ArrayList <> ( k ) ; for ( int i = 0 ; i < k ; i ++ ) { hardClusters . add ( DBIDUtil . newArray ( ) ) ; } // provide a hard clustering for ( DBIDIter iditer = relation . iterDBIDs ( ) ; iditer . valid ( ) ; iditer . advance ( ) ) { hardClusters . get ( argmax ( probClusterIGivenX . get ( iditer ) ) ) . add ( iditer ) ; } Clustering < M > result = new Clustering <> ( "EM Clustering" , "em-clustering" ) ; // provide models within the result for ( int i = 0 ; i < k ; i ++ ) { result . addToplevelCluster ( new Cluster <> ( hardClusters . get ( i ) , models . get ( i ) . finalizeCluster ( ) ) ) ; } if ( isSoft ( ) ) { result . addChildResult ( new MaterializedRelation <> ( "cluster assignments" , "em-soft-score" , SOFT_TYPE , probClusterIGivenX , relation . getDBIDs ( ) ) ) ; } else { probClusterIGivenX . destroy ( ) ; } return result ; }
Performs the EM clustering algorithm on the given database .