1 Introdução

O objetivo deste tutorial, ou artigo técnico, é explicar um pouco sobre como utilizar as medidas de similaridades para dados categóricos ou binários, em um dataset multirrótulo.

Vou utilizar aqui uma porção do dataset GpositiveGO para ilustrar a explicação. Na verdade esse é um dos 10 folds do conjunto de treinamento do dataset GpositiveGO que eu criei usando este código aqui: https://github.com/cissagatto/CrossValidationMultiLabel. Preferi usar algo mais curto para facilitar o desenvolvimento do tutorial.

O código está disponível neste repositório no meu Github: https://github.com/cissagatto/MultiLabelSimilaritiesMeasures

# setando a pasta onde o arquivo está salvo
setwd("/home/elaine/MultiLabelSimilaritiesMeasures/GpositiveGO/CrossValidation/Tr")
# abrindo o FOLD 1
dados = foreign::read.arff("GpositiveGO-Split-Tr-1.arff")

O arquivo “datasets.csv” foi criado com base nos datasets disponívels no site https://cometa.ujaen.es/datasets/. É um arquivo com informações dos 74 datasets disponíveis no site, incluindo também o número de neurônios para ser utilizado no mapa de Kohonen. Este dataset tem as seguintes características:

setwd("/home/elaine/MultiLabelSimilaritiesMeasures/")
datasets = read.csv("datasets.csv")
ds = datasets[29,]
print(t(ds))
##            29           
## Id         "29"         
## Name       "GpositiveGO"
## Instances  "519"        
## Attributes "916"        
## Inputs     "912"        
## Labels     "4"          
## Labelsets  "7"          
## Single     "2"          
## Max.freq   "206"        
## Card       "1.0077"     
## Dens       "0.2519"     
## Mean.IR    "3.8605"     
## Scumble    "1"          
## TCS        "10.1478"    
## AttStart   "1"          
## AttEnd     "912"        
## LabelStart "913"        
## LabelEnd   "916"        
## Distinct   "0"          
## xn         "2"          
## yn         "2"          
## gridn      "4"

Aqui vou separar algumas informações em variáveis para que possamos utilizá-las no código.

start.label = as.numeric(ds$LabelStart) # coluna onde começa o espaço de rótulos no dataset
end.label = as.numeric(ds$LabelEnd) # coluna onde termina o espaço de rótulos
num.labels = as.numeric(ds$Labels) # número de rótulos do espaço de rótulos

Também vou separar o espaço de rótulos dos outros atributos. As medidas de similaridades serão aplicadas apenas nos rótulos.

labels = data.frame(dados[,start.label:end.label])
head(labels)
##   Label1 Label2 Label3 Label4
## 1      1      0      0      0
## 2      1      0      0      0
## 3      1      0      0      0
## 4      1      0      0      0
## 5      1      0      0      0
## 6      1      0      0      0

Relembrando: um dataset é composto por atributos e instâncias (também chamadas de observações ou exemplos). Os atributos podem ser atributos de entrada ou de saída. Em nosso caso, os rótulos são os atributos de saída e eles são compostos por valores 0 ou 1, indicando se a instância pertence ou não àquele rótulo.

Vamos precisar também dos pacotes a seguir. Verifique se eles estão instalados.

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(progress)

Agora vamos entender um pouco a respeito das medidas que vamos trabalhar aqui. Todas elas são baseadas em uma tabela chamada de tabela de contingência.

A partir dessa tabela de contingência conseguimos obter as seguintes informações básicas:

  1. a = [Label1 == 1 E Label2 == 1]. Proporção de uns (1) que os rótulos compartilham nas mesmas posições. Também podemos dizer que são os encontros positivos entre os dois rótulos em questão, pois os dois estão presentes;

  2. b = [Label1 == 0 E Label2 == 1]. Proporção de uns (1) no primeiro rótulo e zeros (0) no segundo rótulo nas mesmas posições. Aqui podemos dizer que o Label1 está presente e o Label2 ausente;

  3. c = [Label1 == 1 E Label2 == 0]. Proporção de zeros (0) no primeiro rótulo e uns (1) no segundo rótulo nas mesmas posições. Também podemos entender que o Label1 está ausente e o Label2 presente;

  4. d = [Label1 == 0 E Label2 == 0]. Proporção de zeros (0) que ambas os rótulos compartilham nas mesmas posições. Neste caso, temos que nem Label1 e nem Label2 estão presentes, portanto, são os encontros negativos.

Basicamente é uma tabela que conta a frequência de pares de rótulos. Como temos vários rótulos em nosso dataset, então temos que calulcar uma tabela dessa para cada combinação. Em nosso exemplo temos 4 rótulos: Label1, Label2, Label3 e Label4. Então, temos que calcular a tabela de contingência para todos os pares de rótulos possíveis desse conjunto.

Ainda a partir da tabela de contingência podemos calcular as probabilidades marginais:

  1. Soma das Linhas
  • p1 = a + b, onde a representa 11 e b representa 10 na tabela

  • p2 = c + d, onde a representa 01 e b representa 00 na tabela

  1. Soma das Colunas
  • p3 = a + c, onde a representa 11 e b representa 01 na tabela

  • p4 = b + d, onde a representa 10 e b representa 00 na tabela

  1. Soma das Diagonais
  • p5 = a + d, onde a representa 11 e b representa 00 na tabela

  • p6 = b + c, onde a representa 10 e b representa 01 na tabela

Para exemplificar, vamos pegar o Label1 e o Label2 do dataset GpositiveGO:

print(labels$Label1)
##   [1] 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
##  [38] 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
##  [75] 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
## [112] 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0
## [149] 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [186] 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0
## [223] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
## [260] 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
## [297] 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
## [334] 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
## [371] 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0
## [408] 0 0 0 0 0 0 0 0
## Levels: 0 1
print(labels$Label2)
##   [1] 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [38] 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
##  [75] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [112] 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
## [149] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [186] 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0
## [223] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [260] 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [297] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
## [334] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [371] 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
## [408] 0 0 0 0 0 0 0 0
## Levels: 0 1

Observaram que ao final está escrito “levels 0 and 1”? Bem, precisamos converter os fatores em número:

x = as.numeric(levels(labels$Label1))[labels$Label1]
head(x)
## [1] 1 1 1 1 1 1
y = as.numeric(levels(labels$Label2))[labels$Label2]
head(y)
## [1] 0 0 0 0 0 0

Notem que agora não aparece mais a palavra levels! Feitos estes preparativos vamos calcular os valores da tabela. Apenas reforçando que estou usando head() para printar no console de saída apenas os primeiros resultados.

2 Calculando a tabela de contingência

2.1 Calculando a

Primeiro vou fazer o passo a passo, apenas pra mostrar bem didaticamente o que está acontecendo. Depois vou mostrar como fazer o cálculo de forma mais objetiva. No caso do a, sabemos que devemos contar a frequencia em que ambos os rótulos estão presentes. Lembrando que no R FALSE é igual a zero e TRUE é igual a 1.

# verificando onde o Label1 é igual a 1
res1 = (x == 1)
head(res1)
## [1] TRUE TRUE TRUE TRUE TRUE TRUE
# verificando onde o Label2 é igual a 1
res2 = (y == 1)
head(res2)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
# verificando quando os dois rótulos estão presentes
res3 = (res1 == 1 & res2 == 1)
head(res3)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
# somando 
sum(res3)
## [1] 1
# ou podemos fazer diretamente:
a = sum( (x == 1) & (y == 1) )
a
## [1] 1

O resultado final nos diz que os rótulos Label1 e Label2 estão presentes juntos apenas uma vez! Assim, podemos ir formando a nossa tabela de contingência, vejam:

2.2 Calculando b

Para calcular b, devemos contar a frequencia em que o rótulo Label1 está presente e o Label2 ausente.

# verificando onde o Label1 é igual a 1
res1 = (x == 1)
head(res1)
## [1] TRUE TRUE TRUE TRUE TRUE TRUE
# verificando onde o Label2 é igual a 0
res2 = (y == 0)
head(res2)
## [1] TRUE TRUE TRUE TRUE TRUE TRUE
# aqui é onde verificamos Label1=1 e Label2=0
res3 = (res1 == 1 & res2 == 0)
head(res3)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
# somando 
sum(res3)
## [1] 1
# ou podemos fazer diretamente:
b = sum( (x == 1) & (y == 0) )
b
## [1] 138

Podemos entender que o rótulo Label1 aparece sozinho 138 vezes. Atualizando a tabela:

2.3 Calculando c

O c é basicamente o inverso do b, vamos verificar quantas vezes o rótulo Label2 está presente e o Label1 ausente.

# verificando onde o Label1 é igual a 0
res1 = (x == 0)
head(res1)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
# verificando onde o Label2 é igual a 1
res2 = (y == 1)
head(res2)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
# aqui é onde verificamos Label1=0 e Label2=1
res3 = (res1 == 0 & res2 == 1)
head(res3)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
# somando 
sum(res3)
## [1] 1
# ou podemos fazer diretamente:
c = sum( (x == 0) & (y == 1) )
c
## [1] 14

Podemos entender que o rótulo Label2 aparece sozinho 14 vezes. A tabela ficará da seguinte forma:

2.4 Calculando d

Já o d é o inverso do a, aqui queremos contar quantas vezes ambos os rótulos estão ausentes.

# verificando onde o Label1 é igual a 0
res1 = (x == 0)
head(res1)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
# verificando onde o Label2 é igual a 0
res2 = (y == 0)
head(res2)
## [1] TRUE TRUE TRUE TRUE TRUE TRUE
# aqui é onde verificamos Label1=0 e Label2=0
res3 = (res1 == 0 & res2 == 0)
head(res3)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
# somando 
sum(res3)
## [1] 1
# ou podemos fazer diretamente:
d = sum( (x == 0) & (y == 0) )
d
## [1] 262

O resultado final nos diz que os rótulos Label1 e Label2 nunca estão presentes juntos 262 vezes! A tabela ficará da seguinte forma:

Bem, mas convenhamos que fazer isso semi-automatizado para todos os rótulos dará muito trabalho. Se o espaço de rótulos tiver 500 rótulo, teremos de fazer esse cálculo muitas vezes. O ideal é que automatizemos todo o processo. Na seção “Calculando para todos os rótulos” eu mostrarei para vocês como calcular tudo isso de forma automática, independente da quantidade de rótulos do dataset.

3 Calculando as probabilidades marginais

3.1 Calculando “ab”

ab = sum(a+b)
print(ab)
## [1] 139

3.2 Calculando “ac”

ac = sum(a+c)
print(ac)
## [1] 15

3.3 Calculando “bd”

bd = sum(b+d)
print(bd)
## [1] 400

3.4 Calculando “cd”

cd = sum(c+d)
print(cd)
## [1] 276

3.5 Calculando a diagonal “ad”

ad = sum(a+d)
print(ad)
## [1] 263

3.6 Calculando a diagonal “bc”

bc = sum(b+c)
print(bc)
## [1] 152

3.7 Calculando n = a + b + c + d

n = a + b + c + d
print(n)
## [1] 415

Resumindo o que temos até agora:

Podemos então concluir que neste dataset os rótulos Label1 e Label2 tem pouca correlação entre eles já que só ocorrem juntos uma única vez. Isso também pode ser confirmado quando olhamos para o total de vezes em que eles nunca aparecem juntos: 262. Também podemos concluir que o rótulo Label1 é predominante, 138 ocorrências, enquanto que o rótulo Label2 não, apenas 14 ocorrências. Como podemos notar, esta tabela nos fornece bastante informação a respeito dos rótulos individualmente, e também de suas ocorrências com os outros rótulos.

3.8 Calculando a covariância

Duas variáveis binárias são chamadas de não correlacionadas se elas compartilham covariância zero, ou seja, ad - bc = 0. Em nosso exemplo não existe covariância.

(ab-bc)==0
## [1] FALSE

4 Calculando para todos os rótulos

Para facilitar a nossa vida, vamos criar funções para cada cálculo, de forma que será possível computar tudo para todos os pares de rótulos do dataset. Para isso, vamos precisar utilizar uma matriz. Nosso dataset de exemplo tem 4 rótulos, portanto, temos 4 x 4 combinações de rótulos, o que nos dá 16 pares de rótulos. Assim, vamos construir uma matriz quadrada L X L onde L é o número de rótulos do dataset. Em nosso caso será uma matriz com 4 X 4, o que nos dá as 16 posições que precisamos para armazenar o resultado das 16 combinações.

Chamarei a função de “build.matrix.corr.” e passarei como parâmetros o espaço de rótulos e o número total de rótulos do espaço de rótulos. Na primeira linha dentro da função criamos a matriz propriamente dita, enquanto na segunda e terceira linhas apenas nomeamos as linhas e colunas de acordo com os nomes de rótulos do dataset. Ao final, retornamos a matriz construida.

4.1 Construindo a matriz de correlação

# num.labels = número de rótulos do espaço de rótulos
# labels = espaço de rótulos
build.matrix.corr <- function(labels, num.labels){
  matrix.corr <- matrix(nrow=num.labels, ncol=num.labels, data=0)
  colnames(matrix.corr) <- colnames(labels)
  rownames(matrix.corr) <- colnames(labels)
  return(matrix.corr)
  gc()
}

4.2 Funções da tabela de contingência

Para cada função, nós vamos passar dois parâmetros, x e y, que serão os valores nas posições correspondentes de cada rótulo. Nós vamos considerar que nosso espaço de rótulos é uma matriz, então cada posição será computada individualmente. As imagens a seguir ilustram isto. A primeira imagem é a matriz de correlação resultante, isto é, a matriz que armazerá os resultados dos cálculo para todos os pares de rótulos.

Imagem 1

Esta segunda imagem ilustra os pares de rótulos que estão sendo computados.

Imagem 2

A terceira imagem ilustra o espaço de rótulos como uma matriz. As linhas são as instâncias e as colunas são os rótulos. Cada célula corresponde ao valor 1 ou 0. Assim, vamos calcular L11 com L11, depois L11 com L12, L11 com L13, L11 com L14 e assim por diante.

Imagem 3

A seguir apresento as funções para calcular cada item da tabela de contingência. Observe que elas são simples e objetivas. Dei o nome de *compute.___* para não haver problemas com outras bibliotecas ou outros objetos que estejam sendo usados no ambiente R durante a execução do código. As funções abaixo podem ser ainda mais simplificadas, no entanto para ser um pouco mais didático, as deixei num formato mais comum. Por exemplo, poderiam ficar assim:

compute.a <- function(x, y)sum(x == 1 & y == 1)

FUNÇÕES:

# proporção de 1s que ambas as variáveis compartilham nas mesmas posições
# correspondências positivas entre x e y: x e y == 1 
compute.a <- function(x, y){
  return(sum(x == 1 & y == 1))
}

# proporção de 0s na primeira variável e 1s na segunda variável nas mesmas posições
# x ausente: x == 0 e y == 1 
compute.b <- function(x, y){
  return(sum(x == 0 & y == 1))
}

# proporção de 1s na primeira variável e 0s na segunda variável nas mesmas posições
# y ausente: x == 1 e y == 0 
compute.c <- function(x, y){
  return(sum(x == 1 & y == 0))
}

# proporção de zeros que ambas as variáveis compartilham
# correspondências positivas entre x e y: x and y == 0
compute.d <- function(x,y,m){
  return(sum(x == 0 & y == 0))
}

# marginal probabilities

# p1 = a + b --> proporção de uns na primeira variável
compute.ab <- function(a, b){
  return(a+b)
}

# p2 = a + c --> proporção de uns na segunda variável
compute.ac <- function(a, c){
  return(a+c)
}

# p3 = a + d --> diagonal (11) (00)
compute.ad <- function(a, d){
  return(a+d)
}

# p4 = b + c --> diagonal (10) (01) 
compute.bc <- function(b, c){
  return(b+c)
}

# p5 = b + d --> proporção de zeros na segunda variável
compute.bd <- function(b, d){
  return(b+d)
}

# p6 = c + d --> proporção de zeros na primeira variável
compute.cd <- function(c, d){
  return(c+d)
}

# all
compute.n <- function(a,b,c,d){
  return(a+b+c+d)
}

Essas funções computam a ocorrência para apenas as posições correntes de x e y. Elas devem ser chamadas dentro de uma outra função para preencher a matriz resultante, como veremos a seguir.

4.3 Função para computar a tabela de contigência para todos os rótulos

Para cada item da tabela de contingência criaremos uma matriz. Ficará assim:

Portanto, estamos trabalhando com operações de matrizes!!! A imagem a seguir ilustra a matriz a:

O mesmo pode ser aplicado às matrizes b, c e d. Quanto às matrizes de probabilidades marginais, vejamos como fica a matriz ab:

Novamente, o mesmo serve como base para as outras matrizes. Quanto à função, primeiro nós precisamos construir a matrizes e depois preenchê-las. Estou passando dois parâmetros nesta função, que é o espaço de rótulos e o número de rótulos do dataset. O código da função para calcular a, b, c e d para todos os rótulos é mostrado abaixo:

# num.labels = número de rótulos do espaço de rótulos
# labels = espaço de rótulos
compute.cont.table <- function(labels, num.labels){
  
  retorno = list() # lista para retornar os resultados
  
  # construindo as respectivas matrizes
  ma <- build.matrix.corr(labels,num.labels) # matriz a
  mb <- build.matrix.corr(labels,num.labels) # matriz b
  mc <- build.matrix.corr(labels,num.labels) # matriz c
  md <- build.matrix.corr(labels,num.labels) # matriz d
  
  # o tamanha da matriz é o número de labels vezes ele mesmo
  # exemplo: 4 x 4 = 16
  u = (num.labels*num.labels)
  
  # usarei o progress bar apenas para vermos o progresso do andamento da função
  pb <- progress_bar$new(total = u)
  
  # linha
  for (i in 1:num.labels){
    
    # coluna
    for (j in 1:num.labels){
      
      # pegando a primeira coluna a ser comparada
      x = labels[,i]
      
      # pegando a segunda coluna a ser comparada
      y = labels[,j]
      
      # convertendo os fatores para números
      x = as.numeric(levels(x))[x]
      y = as.numeric(levels(y))[y]
      
      # calculando a, b, c e d - chama as respectivas funções
      ma[i,j] = compute.a(x,y)
      mb[i,j] = compute.b(x,y)
      mc[i,j] = compute.c(x,y)
      md[i,j] = compute.d(x,y)
      
      # barra de progresso
      pb$tick()
      Sys.sleep(1/u)
      
      gc()
    } # fim do for interno
    gc()
  } # fim do for externo
  
  # retorna os resultados
  retorno$ma = ma
  retorno$mb = mb
  retorno$mc = mc 
  retorno$md = md
  return(retorno)
  
  gc()
}

Usando a função

res1 = compute.cont.table(labels, num.labels)
res1
## $ma
##        Label1 Label2 Label3 Label4
## Label1    139      1      0      1
## Label2      1     15      0      0
## Label3      0      0    167      2
## Label4      1      0      2     98
## 
## $mb
##        Label1 Label2 Label3 Label4
## Label1      0     14    167     97
## Label2    138      0    167     98
## Label3    139     15      0     96
## Label4    138     15    165      0
## 
## $mc
##        Label1 Label2 Label3 Label4
## Label1      0    138    139    138
## Label2     14      0     15     15
## Label3    167    167      0    165
## Label4     97     98     96      0
## 
## $md
##        Label1 Label2 Label3 Label4
## Label1    276    262    109    179
## Label2    262    400    233    302
## Label3    109    233    248    152
## Label4    179    302    152    317

Agora podemos fazer algo parecido para calcular as probabilidades marginais para todos os rótulos:

# num.labels = número de rótulos do espaço de rótulos
# labels = espaço de rótulos
# a, b, c, d = matrizes
compute.marg.probs <- function(labels, num.labels, a, b, c, d){
  
  retorno = list() # lista para retornar os resultados
  
  # construindo as respectivas matrizes
  mab <- build.matrix.corr(labels, num.labels) # matriz ab
  mac <- build.matrix.corr(labels, num.labels) # matriz ac
  mad <- build.matrix.corr(labels, num.labels) # matriz ad
  mbc <- build.matrix.corr(labels, num.labels) # matriz bc
  mbd <- build.matrix.corr(labels, num.labels) # matriz bd
  mcd <- build.matrix.corr(labels, num.labels) # matriz cd
  mn <- build.matrix.corr(labels, num.labels) # matriz n
  
  u = (num.labels*num.labels) # número de linhas e colunas da matriz resultante
  pb <- progress_bar$new(total = u) # barra de progresso
  
  # linha
  for (i in 1:num.labels){
    
    # coluna
    for (j in 1:num.labels){
      
      # matriz ab
      x = ma[i,j]
      y = mb[i,j]
      mab[i,j] = compute.ab(x,y)
      
      # matriz ac
      w = ma[i,j]
      v = mc[i,j]
      mac[i,j] = compute.ac(w,v)
      
      # matriz ad
      e = ma[i,j]
      f = md[i,j]
      mad[i,j] = compute.ad(e,f)
      
      # matriz bc
      g = mb[i,j]
      h = mc[i,j]
      mbc[i,j] = compute.bc(g,h)
      
      # matriz bd
      k = mb[i,j]
      l = md[i,j]
      mbd[i,j] = compute.bd(k,l)
      
      # matriz cd
      m = mc[i,j]
      n = md[i,j]
      mcd[i,j] = compute.cd(m,n)
      
      # matriz n
      o = ma[i,j]
      p = mb[i,j]
      q = mc[i,j]
      r = md[i,j]
      mn[i,j] = compute.n(o,p,q,r)
      
      # barra de progresso
      pb$tick()
      Sys.sleep(1/u)
      
      gc()
    } # end intern for
    #j = j + 1
    gc()
  } # enf extern for    
  
  # valores a serem retornados
  retorno$mab = mab
  retorno$mac = mac
  retorno$mad = mad
  retorno$mbc = mbc
  retorno$mbd = mbd
  retorno$mcd = mcd
  retorno$mn = mn
  return(retorno)
  
  gc()
}

Usando a função

# obtendo os resultados de a, b, c e d que foram calculados na função anterior
ma = res1$ma # matriz a
mb = res1$mb # matriz b
mc = res1$mc # matriz c
md = res1$md # matriz d
res2 = compute.marg.probs(labels, num.labels, ma, mb, mc, md)
res2
## $mab
##        Label1 Label2 Label3 Label4
## Label1    139     15    167     98
## Label2    139     15    167     98
## Label3    139     15    167     98
## Label4    139     15    167     98
## 
## $mac
##        Label1 Label2 Label3 Label4
## Label1    139    139    139    139
## Label2     15     15     15     15
## Label3    167    167    167    167
## Label4     98     98     98     98
## 
## $mad
##        Label1 Label2 Label3 Label4
## Label1    415    263    109    180
## Label2    263    415    233    302
## Label3    109    233    415    154
## Label4    180    302    154    415
## 
## $mbc
##        Label1 Label2 Label3 Label4
## Label1      0    152    306    235
## Label2    152      0    182    113
## Label3    306    182      0    261
## Label4    235    113    261      0
## 
## $mbd
##        Label1 Label2 Label3 Label4
## Label1    276    276    276    276
## Label2    400    400    400    400
## Label3    248    248    248    248
## Label4    317    317    317    317
## 
## $mcd
##        Label1 Label2 Label3 Label4
## Label1    276    400    248    317
## Label2    276    400    248    317
## Label3    276    400    248    317
## Label4    276    400    248    317
## 
## $mn
##        Label1 Label2 Label3 Label4
## Label1    415    415    415    415
## Label2    415    415    415    415
## Label3    415    415    415    415
## Label4    415    415    415    415

4.4 Calculando a covariância para todos os rótulos

# função para calcular a covariância
# retorna 0 se (ad - bc) != 0
# retorna 1 se (ad - bc) == 0
covariance <- function(x,y){
  return((x-y)==0)
}

# num.labels = número de rótulos do espaço de rótulos
# labels = espaço de rótulos
# ad, bc = matrizes
compute.covar <- function(labels, num.labels, mad, mbc){
  
  mco <- build.matrix.corr(labels, num.labels) # matriz covariância
  u = (num.labels*num.labels) # tamanho da matriz
  pb <- progress_bar$new(total = u) # barra de progresso
  
  # linha
  for (i in 1:num.labels){
    
    # coluna
    for (j in 1:num.labels){
      
      # calcula a covariância para cada posição
      x = mad[i,j] 
      y = mbc[i,j] 
      mco[i,j] = covariance(x,y) 
      
      # barra de progresso
      pb$tick()
      Sys.sleep(1/u)
      gc()
    } # fim do for interno
    gc()
  } # fim do for externo
  return(mco)
  gc()
}

Usando a função

mad = res2$mad # matriz ad
mbc = res2$mbc # matriz bc
res3 = compute.covar(labels, num.labels, mad, mbc)
res3
##        Label1 Label2 Label3 Label4
## Label1      0      0      0      0
## Label2      0      0      0      0
## Label3      0      0      0      0
## Label4      0      0      0      0

Não temos covariância neste dataset.

5 Medidas de Similaridade

Agora que já aprendemos sobre a tabela de contingência e todos os cálculos e informações básicas que podemos obter dela, vamos dar um passo adiante. Nesta seção mostrarei 76 medidas de similaridade as quais converti em funções para calcular similaridades para todos os rótulos do dataset multirrótulo. Ao final do tutorial vocês encontrarão as referências nas quais eu me baseei para escrever este tutorial. Para diferenciar as minhas funções de outras existentens em outros pacotes, eu adicionei “.e” ao final do nome de todas elas.

5.1 Ample

\[ ample = \Bigg| \frac{a(c+d)}{c(a+b)} \Bigg|\\ \]

ample.e <- function(a,b,c,d){
  return(abs((a*(c+d))/(c*(a+b))))
}

5.2 Anderberg

\[ delta = max(a,b) + max(c,d) + max(a,c) + max(b,d) \\ delta' = max((a+b),(b+d)) + max((a+b),(c+d) \\ anderberg = \frac{delta - delta'}{2n} \]

anderberg.e <- function(a,b,c,d,n){
  z = max(a,b)+max(c,d)+max(a,c)+max(b,c)
  w = max((a+c),(b+d))+max((a+b),(c+d))
  p = (z-w)/(2*n)
  return(p)
}

5.3 Baroni urbani buser 1

\[ baroni.1 = \frac{\sqrt{ad}+a}{\sqrt{ad} + a + b + c} \]

baroni.urbani.buser.1.e <- function(a,b,c){
  return((sqrt((a*d)) + a)/((sqrt((a*d))) + a + b + c))
}

5.4 Baroni urbani buser 2

\[ baroni.2 = \frac{\sqrt{ad}+a-(b+c)}{\sqrt{ad} + a + b + c} \]

baroni.urbani.buser.2.e <- function(a,b,c,d){
  return((sqrt((a*d))+a-(b+c))/((sqrt((a*d))) + a + b + c))
}

5.5 Braun banquet

\[ braun.banquet = \frac{a}{max((a+b),(a+c))} \]

braun.banquet.e <- function(a,b,c){
  return(a/max((a+b),(a+c)))
}

5.6 Bray curtis

\[ bray.curtis = \frac{b+c}{(2a+b+c)} \]

bray.curtis.e <- function(a,b,c){
  return((b+c)/((2*a)+b+c))
}

5.7 Canberra

\[ canberra = (b+c)^{\frac{2}{2}} \]

canberra.e <- function(b,c){
  return((b+c)^(2/2))
}

5.8 Chord

\[ chord = \sqrt{2 \Bigg( 1 - \frac{a}{\sqrt( (a+b) + (a+c) )} \Bigg)} \]

chord.e <- function(a,b,c){
  return(sqrt(2*(1-((a)/(sqrt((a+b)*(a+c)))))))
}

5.9 Cityblock

\[ cityblock = b + c \]

cityblock.e <- function(b,c){
  return(b+c)
}

5.10 Cole

\[ cole = \frac{ \sqrt{2}(ad - bc)}{\sqrt{(ad-bc)^2-(a+b)(a+c)(b+d)(c+d)}} \]

cole.e <- function(a,b,c,d){
  d1 = sqrt(2) * ((a*d)-(b*c))
  d2 = (((a*d)-(b*c))^2) - ((a+b)*(a+c)*(b+d)*(c+d))
  d3 = sqrt(d2)
  d4 = d1/d3
  return(d4)
}

5.11 Cosine

\[ cosine = \frac{a}{\sqrt{(a+b)(a+c)}^2} \]

cosine.e <- function(a,b,c){
  return(a / sqrt((((a+b) * (a+c))))^2)
}

5.12 Czekanowski

\[ czekanowski = \frac{2a}{2a+b+c} \]

czekanowski.e <- function(a,b,c){
  return((2*a)/((2*a)+b+c))
}

5.13 Dennis

\[ dennis = \frac{ad-bc}{\sqrt{n(a+b)(a+c)}} \]

dennis.e <- function(a,b,c,n){
  return(((a*d)-(b*c))/sqrt(n*(a+b)*(a+c)))
}

5.14 Dice

\[ dice = \frac{2a}{2a+b+c} \]

dice.e <- function(a,b,c){
  return((2*a)/((2*a)+b+c))
}

5.15 Disperson

\[ dispersion = \frac{ad-bc}{(a+b+c+d)^2} \]

disperson.e <- function(a,b,c,d){
  return(((a+d)-(b+c))/((a+b+c+d)^2))
}

5.16 Driver kroeber

\[ driver.kroeber = \frac{a}{2} * \Big( \frac{1}{a+b} + \frac{1}{a+c} \Big) \]

driver.kroeber.e <- function(a,b,c){
  return((a/2) * ((1/(a+b)) + (1/(a+c))))
}

5.17 Euclidean

\[ euclidean = \sqrt{b+c} \]

euclidean.e <- function(b,c){
  return(sqrt(b+c))
}

5.18 Eyraud

\[ eyraud = \frac{n^2(na-(a+b)(a+c))}{(a+b)(a+c)(b+d)(c+d)} \]

eyraud.e <- function(a,b,c,d,n){
  return((n^2)*((n*a)-(a+b)*(a+c))/(a+b)*(a+c)*(b+d)*(c+d))
}

5.19 Fager mcgowan

\[ fager.mcgowan = \frac{a}{\sqrt{(a+b)(a+c)}} - \frac{max((a+b),(a+c))}{2} \]

fager.mcgowan.e <- function(a,b,c){
  return((a/sqrt((a+b)+(a+c))) - (max((a+b),(a+c))/2))
}

5.20 Faith

\[ faith = \frac{a+0.5d}{a+b+c+d} \]

faith.e <- function(a,b,c,d){
  return((a+(0.5*d))/(a+b+c+d))
}

5.21 Forbes 2

\[ forbes.2 = \frac{na-(a+b)(a+c)}{n*(min((a+b),(a+c))-((a+b)(a+c))} \]

forbes.2.e <- function(a,b,c,n){
  return((n*a)-((a+b)*(a+c))/n*(min((a+b),(a+c))-((a+b)*(a+c))))
}

5.22 Forbesi

\[ forbesi = \frac{na}{(a+b)(a+c)} \]

forbesi.e <- function(a,b,c,n){
  return((n*a)/((a+b)*(a+c)))
}

5.23 Fossum

\[ fossum = \frac{n(a-0.5)^2}{(a+b)(a+c)} \]

fossum.e <- function(a,b,c,n){
  return((n*(a-0.5)^2)/(a+b)*(a+c))
}

5.24 Gilbert well

\[ gilbert.well = \log a - \log n - \log \Bigg(\frac{(a+b)}{n}\Bigg) - \log \Bigg(\frac{a+c}{n}\Bigg) \]

gilbert.well.e <- function(a,b,c,n){
  return(log(a) - log(n) - log((a+b)/n) - log((a+c)/n))
 }

5.25 Goodman kruskal

\[ delta = max(a,b) + max(c,d) + max(a,c) + max(b,d) \\ delta' = max((a+b),(b+d)) + max((a+b),(c+d) \\ goodman.kruskal = \frac{delta-delta'}{2n-delta'} \]

goodman.kruskal.e <- function(){
  z = max(a,b)+max(c,d)+max(a,c)+max(b,c)
  w = max((a+c),(b+d))+max((a+b),(c+d))
  p = (z-w)/((2*n)-w)
  return(p)
}

5.26 Gower

\[ gower = \frac{a+d}{\sqrt{(a+b)+(a+c)+(b+d)+(c+d)}} \]

gower.e <- function(a,b,c,d){
  return((a+d)/sqrt((a+b)*(a+c)*(b+d)*(c+d)))
}

5.27 Gower legendre

\[ gower.legendre = \frac{a+d}{a+0.5(b+c)+d} \]

gower.legendre.e <- function(a,b,c,d){
  return((a+d)/(a+(0.5*(b+c))+d))
}

5.28 Hamann

\[ hamann = \frac{(a+d)-(b+c)}{a+b+c+d} \]

hamann.e <- function(a,b,c,d){
  return(((a+d)-(b+c))/(a+b+c+d))
}

5.29 Hamming

\[ hamming = b + c \]

hamming.e <- function(b,c){
  return(b+c)
}

5.30 Hellinger

\[ hellinger = 2\sqrt{ \Bigg( 1 - \frac{a}{\sqrt{(a+b)(a+c)}} \Bigg) } \]

hellinger.e <- function(a,b,c){
  return(2 * sqrt(1 - ((a)/(sqrt((a+b)*(a+c))))))
}

5.31 Inner product

\[ inner.product = a + d \]

inner.product.e <- function(a,d){
  return(a+d)
}

5.32 Intersection

\[ intersection = a \]

intersection.e <- function(a){
  return(a)
}

5.33 Jaccard

\[ jaccard = \frac{a}{a+b+c} \]

jaccard.e <- function(a,b,c){
  return(a/(a+b+c))
}

5.34 Johnson

\[ johnson = \frac{a}{a+b} + \frac{a}{a+c} \]

johnson.e <- function(a,b,c){
  return((a/(a+b)) + (a/(a+c)))
}

5.35 Kulczynski 1

\[ kulczynski.1 = \frac{a}{b+c} \]

kulczynski.1.e <- function(a,b,c){
  return(a/(b+c))
}

5.36 Kulczynski 2

\[ kulczynski.2 = \frac{ \frac{a}{2}(2a+b+c)}{(a+b)(a+c)} \]

kulczynski.2.e <- function(a,b,c){
  return((a/2) * ((2*a)+b+c))/(a+b)*(a+c)
}

5.37 Lance Williams

\[ lance.williams = \frac{b+c}{2a+b+c} \]

lance.williams.e <- function(a,b,c){
  return((b+c)/((2*a)+b+c))
}

5.38 Manhattan

\[ manhattan = b + c \]

manhattan.e <- function(b,c){
  return(b+c)
}

5.39 Mcconnaughey

\[ mcconnaughey = \frac{a^2 - bc}{(a+b)(a+c)} \]

mcconnaughey.e <- function(a,b,c){
  return(((a^2) - (b-c))/(a+b)*(a+c))
}

5.40 Mean manhattan

\[ mean.manhanttan = \frac{b+c}{a+b+c+d} \]

mean.manhattan.e <- function(b,c,d){
  return((b+c)/(a+b+c+d))
}

5.41 Michael

\[ michael = \frac{4(ad - bc)}{(a+d)^2 + (b+c)^2} \]

michael.e <- function(a,b,c,d){
  return(4*((a*d)-(b*c))/((a+d)^2)  + ((b+c)^2))
}

5.42 Minowski

\[ minowski = (b+c)^{\frac{1}{1}} \]

minowski.e <- function(b,c){
  return((b+c)^(1/1))
}

5.43 Mountford

\[ mountford = \frac{a}{0.5(ab+ac)+bc} \]

mountford.e <- function(a,b,c){
  return(a/(0.5*(((a*b)+(a*c))+(b*c))))
}

5.44 Nei li

\[ nei.li = \frac{20}{(a+b)+(a+c)} \]

nei.li.e <- function(a,b,c){
  return((2*a)/((a+b)+(a+c)))
}

5.45 Ochiai 1

\[ ochiai.1 = \frac{a}{\sqrt{(a+b)(a+c)}} \]

ochiai.e <- function(a,b,c){
  return(a/(sqrt((a+b)*(a+c))))
}

5.46 Ochiai 2

\[ ochiai.2 = \frac{ad}{\sqrt{(a+b)(a+c)(b+d)(c+d)}} \]

ochiai.2.e <- function(a,b,c,d){
  return((a*d)/sqrt((a+b)*(a+c)*(b+d)*(c+d)))
}

5.47 Otsuka

\[ otsuka = \frac{a}{((a+b)(a+c))^{0.5}} \]

otsuka.e <- function(a,b,c){
  return(a/((a+b)*(a+c))^0.5)
}

5.48 Pattern Difference

\[ pattern.difference = \frac{4bc}{(a+b+c+d)^2} \]

pattern.difference.e <- function(a,b,c,d){
  return((4*b*c)/((a+b+c+d)^2))
}

5.49 Pearson 1

\[ pearson.1 = \frac{n(ad-bc)^2}{(a+b)(a+c)(c+d)(b+d)} \]

pearson.1.e <- function(a,b,c,d,n){
  return(n*(((a*d)-(b*c))^2)/(a+b)*(a+c)*(c+d)*(b+d))
}

5.50 Pearson 2

\[ pearson.2 = \Big( \frac{pearson.1}{n+pearson.1} \Big)^{1/2} \]

pearson.2.e <- function(a,b,c,d,n){
  z = pearson.1.e(a,b,c,d,n)
  w = (z/(n*z))^(1/2)
  return(w)
}

5.51 Pearson 3

\[ p = \frac{ad-bc}{\sqrt{(a+b)(a+c)(b+d)(c+d)}} \\ pearson.3 = \Big( \frac{p}{n+p} \Big)^{1/2} \]

pearson.3.e <- function(a,b,c,d){
  z = ((a*d)-(b*c))/sqrt((a+b)*(a+c)*(b+d)*(c+d))
  w = (z/(n+p))^(1/2)
  return(w)
}

5.52 Pearson heron 1

\[ pearson.heron.1 = \frac{ad-bc}{\sqrt{(a+b)(a+c)(b+d)(c+d)}} \]

pearson.heron.1.e <- function(a,b,c,d){
  return((a*d)-(b*c)/(a+b)*(a+c)*(b+d)*(c+d))
}

5.53 Pearson heron 2

\[ pearson.heron.2 = \cos\Bigg( \frac{\pi\sqrt{bc}}{\sqrt{ad} + \sqrt{bc}} \Bigg) \]

pearson.heron.2.e <- function(a,b,c){
  return(cos(pi*(sqrt(b*c))/sqrt(a*d)+sqrt(b*c)))
}

5.54 Peirce

\[ pierce = \frac{ab+bc}{ab+2bc+cd} \]

peirce.e <- function(a,b,c,d){
  return((a*b)+(b*c)/(a*b)+(2*b*c)+(c*d))
}

5.55 Roger tanimoto

\[ roger.tanimoto = \frac{a+d}{a+2(b+c)+d} \]

roger.tanimoto.e <- function(a,b,c,d){
  return((a+d)/(2*(b+c)+d))
}

5.56 Russel rao

\[ russel.rao = \frac{a}{a+b=c+d} \]

russel.rao.e <- function(a,b,c,d){
  return(a/(a+b+c+d))
}

5.57 Shape Differnece

\[ shape.difference = \frac{n(b+c) - (b-c)^2}{(a+b+c+d)^2} \]

shape.differnece.e <- function(a,b,c,d){
  return((n*(b+c)-((b-c)^2))/((a+b+c+d)^2))
}

5.58 Simpson

\[ simpson = \frac{a}{min(a+b, a+c)} \]

simpson.e <- function(a,b,c){
  return(a/min((a+b),(a+c)))
}

5.59 Size Difference

\[ size.difference = \frac{(b+c)^2}{(a+b+c+d)^2} \]

size.difference.e <- function(a,b,c,d){
  return(((b+c)^2)/((a+b+c+d)^2))
}

5.60 Sokal michener

\[ sokal.michener = \frac{a+d}{a+b+c+d} \]

sokal.michener.e <- function(a,b,c,d){
  return((a+d)/(a+b+c+d))
}

5.61 Sokal sneath 1

\[ sokal.sneath.1 = \frac{a}{a+2b+2c} \]

sokal.sneath.1.e <- function(a,b,c){
  return(a/(a+(2*b)+(2*c)))
}

5.62 Sokal sneath 2

\[ sokal.sneath.2 = \frac{2(a+d)}{2a+b+c+2d} \]

sokal.sneath.2.e <- function(a,b,c,d){
  return(2*(a+d)/((2*a)+b+c+(2*d)))
}

5.63 Sokal sneath 3

\[ sokal.sneath.3 = \frac{a+d}{b+c} \]

sokal.sneath.3.e <- function(a,b,c,d){
  return((a+d)/(b+c))
}

5.64 Sokal sneath 4

\[ sokal.sneath.4 = \frac{ \frac{a}{(a+b)} + \frac{a}{(a+c)} + \frac{d}{(b+b)} + \frac{d}{(b+d)}}{4} \]

sokal.sneath.4.e <- function(a,b,c,d){
  return(((a/(a+b))+(a/(a+c))+(d/(b+d))+(d/(b+d)))/4)
}

5.65 Sokal sneath 5

\[ sokal.sneath.5 = \frac{ad}{(a+d)(a+c)(b+d)(c+d)^{0.5}} \]

sokal.sneath.5.e <- function(a,b,c,d){
  return((a*d)/(a+b)*(a+c)*(b+d)*((c*d)^0.5))
}

5.66 Sorgenfrei

\[ sorgenfrei = \frac{a^2}{(a+b)(a+c)} \]

sorgenfrei.e <- function(a,b,c){
  return((a^2)/(a+b)*(a+c))
}

5.67 Square euclidean

\[ square.euclidean = \sqrt{(b+c)^2} \]

square.euclidean.e <- function(b,c){
  return(sqrt((b+c)^2))
}

5.68 Stiles

\[ stiles = log_{10} * \frac{n\Big(\Big|ad-bc\Big|-\frac{n}{2}\Big)^2\\}{(a+b)(a+c)(b+d)(c+d)} \]

stiles.e <- function(a,b,c,d,n){
  return(log10((n*(abs((a*d)-(b*c))-(n/2))^2) /((a+b)*(a+c)*(b+d)*(c+d))))
}

5.69 Tanimoto

\[ tanimoto = \frac{a}{(a+b)+(a+c)-a} \]

tanimoto.e <- function(a,b,c){
  return(a/((a+b)+(a+c)-a))
}

5.70 Tarantula

\[ tarantula = \frac{a(c+d)}{c(a+d)} \]

tarantula.e <- function(a,b,c){
  return((a*(c+d))/(c*(a+b)))
}

5.71 Tarwid

\[ tarwid = \frac{na-(a+b)(a+c)}{na+(a+b)(a+c))} \]

tarwid.e <- function(a,b,c,n){
  return((n*a) - (a+b) * (a+c) / (n*a) + (a+b) * (a+c))
}

5.72 3W Jaccard

\[ 3w.jaccard = \frac{3a}{3a+b+c} \]

three.w.jaccard.e <- function(a,b,c){
  return((3*a)/((3*a)+b+c))
}

5.73 Vari

\[ vari = \frac{(b+c)}{4(a+b+c+d)} \]

vari.e <- function(a,b,c,d){
  return((b+c)/(4*(a+b+c+d)))
}

5.74 Yule w

\[ yule.w = \frac{\sqrt{ad} - \sqrt{bc}}{\sqrt{ad} - \sqrt{bc}} \]

yule.w.e <- function(a,b,c,d){
  return(sqrt((a*d))-sqrt((b*c))/sqrt((a*d))+sqrt((b*c)))
}

5.75 Yuleq 1

\[ yuleq.1 = \frac{ad-bc}{ad+bc} \]

yuleq.1.e <- function(a,b,c,d){
  return(((a*d)-(b*c))/((a*d)+(b*c)))
}

5.76 Yuleq 2

\[ yuleq.2 = \frac{2bc}{ad+bc} \]

yuleq.2.e <- function(a,b,c,d){
  return((2*b*c)/(a*d) + (b*c))
}

6 Calculando as medidas de similaridades para todos os rótulos

Como temos muitas funções, ao invés de criar uma nova função para cada uma delas para preencher a matriz de correlação, nós vamos criar uma única função que aceitará como parâmetro o nome da medida de similariade (função) que queremos calcular. Para isto, usamos FUN o qual será substituido pela função que desejamos.

No entanto, para isto funcionar, precisaremos alterar todas as funções das medidas de similaridade para aceitar a, b, c, d e n como parâmetros. Como exemplo, a medida euclidiana está assim

euclidean.e <- function(b,c){
  return(sqrt(b+c))
}

Precisaremos mudar para:

euclidean.e <- function(a,b,c,d,n){
  return(sqrt(b+c))
}

Essa foi a forma mais objetiva que encontrei para automatizar o processo, mas existem outras maneiras. No entanto, não é escopo aqui para estudarmos como criar funções avançadas no R. Deixo por conta de vocês procurarem a respeito e tentar melhorar o código aqui disponibilizado. Bem, depois de modificar todas as funções das medidas de similariade, a função abaixo funcionará sem problemas:

compute.measure <- function(labels, num.labels, a, b, c, d, n, FUN){
  
  retorno = list()
  
  m <- build.matrix.corr(labels, num.labels) # matriz de correlação
  u = (num.labels*num.labels) # tamanho da matriz 
  pb <- progress_bar$new(total = u) # barra de progresso
  
  for (i in 1:num.labels){
    for (j in 1:num.labels){
      x = as.numeric(a[i,j]) # matriz a
      y = as.numeric(b[i,j]) # matriz b
      w = as.numeric(c[i,j]) # matriz d
      z = as.numeric(d[i,j]) # matriz d
      k = as.numeric(n[i,j]) # matriz n
      m[i,j] = FUN(x,y,w,z,k) # chama a função passada como parâmetro
      pb$tick()
      Sys.sleep(1/u)
      gc()
    } # end intern for
    gc()
  } # enf extern for  
  return(m)
  gc()
}

Observe que FUN é usado na chamada da função compute.measure e depois ele também é usado na linha onde prenchemos a matriz de correlação. FUN será substituido pela função que passarmos como parâmetro.

Usando a função:

ma = res1$ma # matriz a
mb = res1$mb # matriz b
mc = res1$mc # matriz c
md = res1$md # matriz d
mn = res2$mn # matriz n
res4 = compute.measure(labels, num.labels, ma, mb, mc, md, mn, stiles.e)
res4
##           Label1    Label2    Label3    Label4
## Label1 2.6133374 0.5861647 2.1406194 1.7696922
## Label2 0.5861647 2.5874777 0.9452397 0.5500743
## Label3 2.1406194 0.9452397 2.6136854 1.8795939
## Label4 1.7696922 0.5500743 1.8795939 2.6122270

Além de analisar o espaço de rótulos a partir dessas funções, você também pode usar o resultado da função compute.measure para construir um grafo e, em seguida aplicar métodos de detecção de comunidades (redes complexas).

É isto pessoal. Por favor, se houver algo errado em alguma parte do texto, não importa o que seja, entrem em contato: . Por favor, sigam-me também em minhas redes sociais:

https://twitch.com/cissagatto

https://www.instagram.com/professoracissa/

https://twitter.com/professoracissa

https://www.facebook.com/ProfessoraCissa/

https://www.youtube.com/channel/UCAdow7a1SHwwWyePjLto1cg

https://www.linkedin.com/in/elainececiliagatto/

https://www.linkedin.com/company/professoracissa

https://www.embarcados.com.br/membro/elaine-cec%C3%ADlia-gatto/

7 Referências

Cha, Sung-Hyuk. “Comprehensive Survey on Distance/Similarity Measures between Probability Density Functions.” (2007). Disponível em: http://www.fisica.edu.uy/~cris/teaching/Cha_pdf_distances_2007.pdf

Irani, Jasmine Khushro et al. “Clustering Techniques and the Similarity Measures used in Clustering: A Survey.” International Journal of Computer Applications 134 (2016): 9-14. Disponível em: https://www.ijcaonline.org/research/volume134/number7/irani-2016-ijca-907841.pdf

Choi, Seung-Seok et al. “A Survey of Binary Similarity and Distance Measures.” Journal on Systemics, Cybernetics and Informatics 8 (2010): 43-48. Disponível em: http://www.iiisci.org/Journal/PDV/sci/pdfs/GS315JG.pdf

Gjorgjioski, Valentin et al. “Comparison of Distances for Multi-Label Classification with PCTs.” (2011). Disponível em: https://ailab.ijs.si/Dunja/SiKDD2011/Papers/Gjorgjioski_Multilabel.pdf

Garg, Ankit et al. “On Asymmetric Similarity Search.” 2015 IEEE 14th International Conference on Machine Learning and Applications (ICMLA) (2015): 649-654. Disponível em : https://ieeexplore.ieee.org/document/7424392

Warrens, Matthijs Joost. “Similarity Coefficients for Binary Data. Properties of Coefficients, Coefficient Matrices, Multi-way Metrics and Multivariate Coefficients.” Dissertation Leiden University. ISBN 978-90-8891-0524. 2008. Disponível em: https://www.researchgate.net/publication/28649906_Similarity_coefficients_for_binary_data_Properties_of_coefficients_coefficient_matrices_multi-way_metrics_and_multivariate_coefficients