app/oryx-app-mllib/src/main/java/com/cloudera/oryx/app/batch/mllib/kmeans/SilhouetteCoefficient.java
double silhouetteCoefficient(Map<Integer,Iterable<double[]>> clusterPointsByID) {
    double totalSilhouetteCoefficient = 0.0;
    long sampleCount = 0L;

    for (Map.Entry<Integer, Iterable<double[]>> entry : clusterPointsByID.entrySet()) {
      List<double[]> clusteredPoints = iterableToList(entry.getValue());
      long clusterSize = clusteredPoints.size();
      // Increment the total sample count for computing silhouette coefficient
      sampleCount += clusterSize;
      // if there's only one element in a cluster, then assume the silhouetteCoefficient for
      // the cluster = 0, this is an arbitrary choice per Section 2: Construction of Silhouettes
      // in the referenced paper
      if (clusterSize > 1) {
        for (double[] point : clusteredPoints) {
          double pointIntraClusterDissimilarity = clusterDissimilarityForPoint(point, clusteredPoints, true);
          double pointInterClusterDissimilarity =
              minInterClusterDissimilarityForPoint(entry.getKey(), point, clusterPointsByID);
          totalSilhouetteCoefficient += silhouetteCoefficient(
              pointIntraClusterDissimilarity, pointInterClusterDissimilarity);
        }
      }

    }

    return sampleCount == 0 ? 0.0 : totalSilhouetteCoefficient / sampleCount;
  }
double silhouetteCoefficient(Map<Integer,Iterable<double[]>> clusterPointsByID) {
    double totalSilhouetteCoefficient = 0.0;
    long sampleCount = 0L;

    for (Map.Entry<Integer, Iterable<double[]>> entry : clusterPointsByID.entrySet()) {
      List<double[]> clusteredPoints = iterableToList(entry.getValue());
      long clusterSize = clusteredPoints.size();
      // Increment the total sample count for computing silhouette coefficient
      sampleCount += clusterSize;
      // if there's only one element in a cluster, then assume the silhouetteCoefficient for
      // the cluster = 0, this is an arbitrary choice per Section 2: Construction of Silhouettes
      // in the referenced paper
      if (clusterSize > 1) {
        for (double[] point : clusteredPoints) {
          double pointIntraClusterDissimilarity = clusterDissimilarityForPoint(point, clusteredPoints, true);
          double pointInterClusterDissimilarity =
              minInterClusterDissimilarityForPoint(entry.getKey(), point, clusterPointsByID);
          totalSilhouetteCoefficient += silhouetteCoefficient(
              pointIntraClusterDissimilarity, pointInterClusterDissimilarity);
        }
      }

    }

    return sampleCount == 0 ? 0.0 : totalSilhouetteCoefficient / sampleCount;
  }
double silhouetteCoefficient ( Map < Integer , Iterable < double [ ] > > clusterPointsByID ) { double totalSilhouetteCoefficient = 0.0 ; long sampleCount = 0L ; for ( Map . Entry < Integer , Iterable < double [ ] > > entry : clusterPointsByID . entrySet ( ) ) { List < double [ ] > clusteredPoints = iterableToList ( entry . getValue ( ) ) ; long clusterSize = clusteredPoints . size ( ) ; // Increment the total sample count for computing silhouette coefficient sampleCount += clusterSize ; // if there's only one element in a cluster, then assume the silhouetteCoefficient for // the cluster = 0, this is an arbitrary choice per Section 2: Construction of Silhouettes // in the referenced paper if ( clusterSize > 1 ) { for ( double [ ] point : clusteredPoints ) { double pointIntraClusterDissimilarity = clusterDissimilarityForPoint ( point , clusteredPoints , true ) ; double pointInterClusterDissimilarity = minInterClusterDissimilarityForPoint ( entry . getKey ( ) , point , clusterPointsByID ) ; totalSilhouetteCoefficient += silhouetteCoefficient ( pointIntraClusterDissimilarity , pointInterClusterDissimilarity ) ; } } } return sampleCount == 0 ? 0.0 : totalSilhouetteCoefficient / sampleCount ; }
Computes the Silhouette Coefficient for this clustering.
See https://en.wikipedia.org/wiki/Silhouette_(clustering)

@param clusterPointsByID map of cluster ID to points that map to that cluster,
for whom Silhouette coefficient needs to be computed
@return Silhouette Coefficient in range [-1,1]; higher is better
Computes the Silhouette Coefficient for this clustering . See https : // en . wikipedia . org / wiki / Silhouette_ ( clustering )