Isso pode ou não ser útil para você, dependendo de quais são suas necessidades. Supondo que você esteja interessado em similaridade entre atribuições de cluster:
O coeficiente de semelhança Jaccard ou o índice Jaccard pode ser usado para calcular a semelhança de duas atribuições de cluster.
Dadas as etiquetas L1
e L2
, Ben-Hur, Elisseeff e Guyon (2002) mostraram que o índice de Jaccard pode ser calculado usando produtos pontuais de uma matriz intermediária. O código abaixo aproveita isso para calcular rapidamente o índice Jaccard sem precisar armazenar as matrizes intermediárias na memória.
O código é escrito em C ++, mas pode ser carregado no R usando o sourceCpp
comando
/**
* The Jaccard Similarity Coefficient or Jaccard Index is used to compare the
* similarity/diversity of sample sets. It is defined as the size of the
* intersection of the sets divided by the size of the union of the sets. Here,
* it is used to determine how similar to clustering assignments are.
*
* INPUTS:
* L1: A list. Each element of the list is a number indicating the cluster
* assignment of that number.
* L2: The same as L1. Must be the same length as L1.
*
* RETURNS:
* The Jaccard Similarity Index
*
* SIDE-EFFECTS:
* None
*
* COMPLEXITY:
* Time: O(K^2+n), where K = number of clusters
* Space: O(K^2)
*
* SOURCES:
* Asa Ben-Hur, Andre Elisseeff, and Isabelle Guyon (2001) A stability based
* method for discovering structure in clustered data. Biocomputing 2002: pp.
* 6-17.
*/
// [[Rcpp::export]]
NumericVector JaccardIndex(const NumericVector L1, const NumericVector L2){
int n = L1.size();
int K = max(L1);
int overlaps[K][K];
int cluster_sizes1[K], cluster_sizes2[K];
for(int i = 0; i < K; i++){ // We can use NumericMatrix (default 0)
cluster_sizes1[i] = 0;
cluster_sizes2[i] = 0;
for(int j = 0; j < K; j++)
overlaps[i][j] = 0;
}
//O(n) time. O(K^2) space. Determine the size of each cluster as well as the
//size of the overlaps between the clusters.
for(int i = 0; i < n; i++){
cluster_sizes1[(int)L1[i] - 1]++; // -1's account for zero-based indexing
cluster_sizes2[(int)L2[i] - 1]++;
overlaps[(int)L1[i] - 1][(int)L2[i] - 1]++;
}
// O(K^2) time. O(1) space. Square the overlap values.
int C1dotC2 = 0;
for(int j = 0; j < K; j++){
for(int k = 0; k < K; k++){
C1dotC2 += pow(overlaps[j][k], 2);
}
}
// O(K) time. O(1) space. Square the cluster sizes
int C1dotC1 = 0, C2dotC2 = 0;
for(int i = 0; i < K; i++){
C1dotC1 += pow(cluster_sizes1[i], 2);
C2dotC2 += pow(cluster_sizes2[i], 2);
}
return NumericVector::create((double)C1dotC2/(double)(C1dotC1+C2dotC2-C1dotC2));
}
vegan
pacote. Eu acho que eles tendem a ser bastante otimizados para velocidade também.