Classificação Multirrótulo: Calculando Similaridades entre Rótulos - Parte 7
Iai galera? Estão curtindo a série de artigos? Espero que estejam aprendendo bastante! Hoje vamos continuar então vem comigo ver como que fica o cálculo das outras matrizes que precisamos.
Calculando as outras matrizes da tabela de contingência
Assim como fizemos uma função para os cálculos de a, b, c e d, também vamos fazer outra função para os outros cálculos, os quais também serão matrizes. Vamos dar uma olhada na função que criei e então vou explicá-la:
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.sim(labels, num.labels) # matriz ab
mac <- build.matrix.sim(labels, num.labels) # matriz ac
mad <- build.matrix.sim(labels, num.labels) # matriz ad
mbc <- build.matrix.sim(labels, num.labels) # matriz bc
mbd <- build.matrix.sim(labels, num.labels) # matriz bd
mcd <- build.matrix.sim(labels, num.labels) # matriz cd
mn <- build.matrix.sim(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
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()
}
O nome da função é compute.marg.probs pois o cálculo de ab, ac, ad, bc, bd e cd são considerados probabilidades marginais. A função recebe como parâmetros o espaço de rótulos (labels), o número total de rótulos no espaço de rótulos (num.labels), e as matrizes a, b, c e d que calculamos anteriormente.
Novamente, a primeira linha dentro da função é a correspondente ao retorno da função. Eu uso literalmente retorno pois assim não me confundo! Você pode usar outro nome se desejar.
Logo em seguida, temos a construção das matrizes para cada um desses cálculos, exatamente como eu fiz no artigo anterior. Portanto, chamo a função build.matrix.sim para cada cálculo que resultará em uma matriz diferente.
Uso novamente o recurso de progress bar para imprimir no console o progresso do cálculo. Isto aqui é opcional tá ok?! Se você não quiser usar, basta retira os trechos correspondentes do código.
Chegamos no for encadeado, que é onde a mágica acontece de fato! O processo aqui é igual ao que eu expliquei no artigo anterior. O que muda agora é o que estamos calculando. Observe estas linhas:
x = ma[i,j]
y = mb[i,j]
mab[i,j] = compute.ab(x,y)
O que estou fazendo aqui é pegando o valor da primeira célula da matriz ma e passando-a para a variável x. Depois, pego a primeira célula da matriz mb e passo o valor dela para y. Agora x e y serão os valores das células das matrizes calculadas anteriormente. Por fim, o comando mab[i,j] = compute.ab(x,y) chama a função para calcular ab e o seu resultado é armazenado na matriz mab.
Vamos relembrar os valores que obtemos para as matrizes a, b, c e d no artigo passado:
Vamos pensar agora na primeira passagem pelo for. Nesse momento tanto i quanto j valem 1, então, nós vamos pegar o valor da linha 1 com a coluna 1 das matrizes em questão, que serão:
ma[1,1] = 4
mb[1,1] = 0
mc[1,1] = 0
md[1,1] = 1
Esses valores serão então passados como parâmetros para a função das probabilidades. O que teremos é algo assim:
mab[1,1] = compute.ab(ma[1,1], mb[1,1])
mac[1,1] = compute.ac(ma[1,1], mc[1,1])
mad[1,1] = compute.ad(ma[1,1], md[1,1])
mbc[1,1] = compute.bc(mb[1,1], mc[1,1])
mbd[1,1] = compute.bd(mb[1,1], md[1,1])
mcd[1,1] = compute.cd(mc[1,1], md[1,1])
Que é o mesmo que:
mab[1,1] = compute.ab(4, 0)
mac[1,1] = compute.ac(4, 0)
mad[1,1] = compute.ad(4, 1)
mbc[1,1] = compute.bc(0, 0)
mbd[1,1] = compute.bd(0, 1)
mcd[1,1] = compute.cd(0, 1)
Este processo vai se repetir para todas as linhas e colunas até que toda a matrizes resultantes estejam preenchidas! Antes de prosseguir, confira este vídeo que mostra a execução deste código.
O meu código está mais didático para a aprendizagem, isto é, eu separei todos os valores em variáveis diferentes para que você entenda o que está acontecendo, mas na prática, é bom ser direto. Meu código então pode ser melhorado, ele pode se transformar no seguinte:
# 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.sim(labels, num.labels) # matriz ab
mac <- build.matrix.sim(labels, num.labels) # matriz ac
mad <- build.matrix.sim(labels, num.labels) # matriz ad
mbc <- build.matrix.sim(labels, num.labels) # matriz bc
mbd <- build.matrix.sim(labels, num.labels) # matriz bd
mcd <- build.matrix.sim(labels, num.labels) # matriz cd
mn <- build.matrix.sim(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
for (i in 1:num.labels){
for (j in 1:num.labels){
mab[i,j] = compute.ab(ma[i,j], mb[i,j]) # matriz ab
mac[i,j] = compute.ac(ma[i,j], mc[i,j]) # matriz ac
mad[i,j] = compute.ad(ma[i,j], md[i,j]) # matriz ad
mbc[i,j] = compute.bc(mb[i,j], mc[i,j]) # matriz bc
mbd[i,j] = compute.bd(mb[i,j], md[i,j]) # matriz bd
mcd[i,j] = compute.cd(mc[i,j], md[i,j]) # matriz cd
mn[i,j] = compute.n(ma[i,j], mb[i,j], mc[i,j], md[i,j]) # matriz n
pb$tick() # barra de progresso
Sys.sleep(1/u) # barra de progresso
gc() # limpa
} # fim do for interno
gc() # limpa
} # fim do for externo
# 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() # limpa
}
Note que o código ficou enxuto! Tem como melhorar ainda mais? Sim, tem, mas não entrarei nos detalhes pois não é o escopo do artigo. Com isso finalizamos as funções para calcular todas as matrizes de que precisamos. Vamos chamar a função:
res = compute.marg.probs(dataset_2, 5, ma, mb, mc, md)
E agora vamos olhar o resultado da execução:
Mais uma vez, podemos usar o resultado da função como quisermos e é isso o que vamos fazer! Os valores em mn devem ser obrigatoriamente o número total de rótulos, já que ele é resultado de a + b + c + d. Se ali der um valor diferente, então tem alguma coisa errada!
Finalizando
Ufa! Acho que terminarmos as prelimares com relação às medidas de similaridade. O que vem agora são elas de fato. Até o momento calculamos coisas relativas à tabela de contingência que são essenciais para estas medidas. A partir de agora, usaremos todas as funções criadas para calcular estas medidas. Baixe aqui o projeto atualizado. Te vejo no próximo artigo.
Este artigo foi escrito por Elaine Cecília Gatto - Cissa e publicado originalmente em Prensa.li.