Saltonov kosinus

5-6. januar 2022

Imejmo podatke o anketi zbrane v matriki (tabeli) A razsežnosti n × m

A[k,i] = odgovor anketiranca k na i-to vprašanje

Vprašanja so merjena v isti številski lestvici. Dopuščamo tudi vrednost NA (ni izmerjeno).

Običajni skalarni produkt vektorjev x in y je določen s predpisom x • y = ∑i xi . yi . Velikost vektorja x je |x| = √ (x • x) .

Za dani vektor nenegativnih uteži w lahko vpeljemo uteženi skalarni produkt x ■ y = ∑i wi . xi . yi Velikost vektorja x je |x| = √ (x ■ x) .

Naj bo A matrika dvovrstnega omrežja in W = A • diag(√w) = [ √wi . ai,j ]. Potem velja AT ■ A = WT • W .

Saltonov indeks S(i,j) podobnosti vprašanj i in j je definiran kot kosinus med vektorjema/spremenljivkama A[.,i] in A[.,j] (Cosine similarity)

S(i,j) = cos(A[.,i], A[.,j]) = ∑(k ∈ 1:n : a[k,i] . a[k,j]) / √(∑(k ∈ 1:n : a[k,i]2) . ∑(k ∈ 1:n : a[k,j]2)) = x ■ y / (|x|.|y|)

Na splošno velja S(i,j) ∈ [-1,1] in S(i,i) = 1. S(x,a.x) = 1 za a > 0 .

Saltonov indeks lahko predelamo v različnost (za razvrščanje) na več načinov:

d(i,j) = (1 - S(i,j)) / 2

δ(i,j) = arccos(S(i,j)) / π

Izračun matrike Saltonovih indeksov za vsa vprašanja

Iz matrike A izračunamo (projekcijo na vprašanja) kvadratno matriko ujemanja vprašanj (natančneje, odgovorov na vprašanja)

C = AT • A

razsežnosti m × m. Njen člen

c[i,j] = ∑(k ∈ 1:n : aT[i,k] • a[k,j]) = ∑(k ∈ 1:n : a[k,i] • a[k,j])

je enak skalarnemu produktu v števcu Saltonovega indeksa. Še več

c[i,i] = ∑(k ∈ 1:n : a[k,i] • a[k,i]) = ∑(k ∈ 1:n : a[k,i]2)

je enak izrazu, ki nastopa v imenovalcu. Torej lahko Saltonov indeks izrazimo s členi matrike ujemanja

S(i,j) = c[i,j] / √(c[i,i] • c[j,j])

Lestvica Za / Proti in NA

Poglejmo si poseben primer, ko so možni le trije odgovori: Za, Proti in NA. Podatke takole prekodiramo: Za ↦ 1, Proti ↦ -1, NA ↦ 0. Naj A vsebuje prekodirane podatke. Tedaj iz obrazca za c[i,j] izhaja

c[i,j] = #(1,1|-1,-1) - #(1,-1|-1,1) = # skladnih odgovorov - # nasprotnih odgovorov

in

c[i,i] = # odgovorov na vprašanje i

Torej je S(i,j) enak skladnosti odgovorov deljeni (normalizirani) z geometrijsko sredino števil odgovorov na obe vprašanji.

Razmeroma enostavno lahko pokažemo, da velja

S(i,j) = 1 ⇔ a[.,i] = a[.,j]

S(i,j) = -1 ⇔ a[.,i] = -a[.,j]

Izvedba v R-ju

https://github.com/bavla/NormNet/tree/main/data/natalija ; https://github.com/bavla/NormNet/tree/main/data/davis

> source("https://raw.githubusercontent.com/bavla/Rnet/master/R/Pajek.R")
> library(gplots)
> wdir <- "C:/Users/vlado/work2/koko"
> setwd(wdir)
> A <- read.csv("trust.csv",sep=",",header=TRUE)
> str(A)
> dim(A)
[1] 2052   44
> M <- as.matrix(A[,2:44])
> # nam <- paste("p",1:43,sep="")
> # --------------------------------------------------------------------
> # Names
> L <- read.csv("SIpol.nam",sep="",header=FALSE,skip=2,encoding="UTF-8")
> head(L)
> nam <- L$V2
> Encoding(nam) <- "UTF-8"
> colnames(M) <- nam
> # ----------------------------------------------------------------
> # positive coappearances
> P <- M
> P[is.na(P)] <- 0
> C <- crossprod(P)
> dim(C)
> matrix2net(C,Net="proj.net")
> disC <- as.dist(1/C,diag=FALSE,upper=FALSE)
> h <-hclust(disC,method="complete")
> plot(h,hang=-1,cex=1,main="Coappearance / Complete")
> heatmap.2(C,Rowv=as.dendrogram(h),Colv="Rowv",dendrogram="column",
+       scale="none",revC=TRUE,trace="none",density.info="none",
+       col=colorpanel(30,low="grey95",high="black"),na.color="yellow",      
+       main="Coappearance / Complete",cexRow=0.5,cexCol=0.5)
> D <- C
> diag(D) <- 0
> heatmap.2(D,Rowv=as.dendrogram(h),Colv="Rowv",dendrogram="column",
+       scale="none",revC=TRUE,trace="none",density.info="none",
+       col=colorpanel(30,low="grey95",high="black"),na.color="yellow",      
+       main="Coappearance / Complete, diag=0",cexRow=0.5,cexCol=0.5)
> # ----------------------------------------------------------------
> # Salton cosine of recoded data  (1 -> 1, NA -> 0, 0 -> -1) 
> R <- M
> R[R==0] <- -1
> R[is.na(R)] <- 0
> D <- crossprod(R)
> matrix2net(D,Net="recoded.net")
> d <- sqrt(diag(D))
> Cos <- diag(1/d) %*% D %*% diag(1/d)
> colnames(Cos) <- rownames(Cos) <- nam
> matrix2net(Cos,Net="cos.net")
> Dcos <- (1-Cos)/2
> diag(Dcos) <- 0
> disD <- as.dist(Dcos,diag=FALSE,upper=FALSE)
> t <-hclust(disD,method="complete")
> plot(t,hang=-1,cex=1,main="Salton / Complete")
> heatmap.2(Cos,Rowv=as.dendrogram(t),Colv="Rowv",dendrogram="column",
+       scale="none",revC=TRUE,col = bluered(100),na.color="yellow",
+       trace = "none", density.info = "none",
+       main="Salton / Complete",cexRow=0.5,cexCol=0.5)

Poskusi še

Jaccard

Jaccardovo podobnost lahko posplošimo na lestvico (Za, Proti, NA) takole:

S prekodiranjem ustvarimo matriki Ap = A(Za ↦ 1, Proti ↦ 0, NA ↦ 0) in An = A(Za ↦ 0, Proti ↦ 1, NA ↦ 0) ter izračunamo matriko ujemanja

C = ApT • Ap + AnT • An

s členi

c[i,j] = #(1,1|-1,-1) = # skladnih odgovorov

in

c[i,i] = # odgovorov na vprašanje i

ter od tu Jaccardova podobnost

J(i,j) = c[i,j] / (c[i,i] + c[j,j] - c[i,j])

in Jaccardova različnost dJ(i,j) = 1 - J(i,j) (domnevam, da je razdalja).

Poskusil 6. januar 2022

> # --------------------------------------------------------------------
> # Jaccard
> # positive  (1 -> 1, NA -> 0, 0 -> 0) 
> Ap <- M
> Ap[is.na(Ap)] <- 0
> # negative  (1 -> 0, NA -> 0, 0 -> -1) 
> An <- M
> An[An==0] <- -1
> An[is.na(An)] <- 0
> An[An==1] <- 0
> U <- crossprod(Ap)+crossprod(An)
> sort(diag(U))
> m <- nrow(U)
> E <- matrix(1,nrow=m,ncol=m)
> J <- U / (diag(diag(U)) %*% E + E %*% diag(diag(U)) - U)
> matrix2net(J,Net="Jaccard.net")
> disJ <- as.dist(1-J,diag=FALSE,upper=FALSE)
> g <-hclust(disJ,method="complete")
> plot(g,hang=-1,cex=1,main="Jaccard / Complete")
> heatmap.2(J,Rowv=as.dendrogram(g),Colv="Rowv",dendrogram="column",
+       scale="none",revC=TRUE,trace="none",density.info="none",
+       col=colorpanel(30,low="grey95",high="black"),na.color="yellow",      
+       main="Jaccard / Complete",cexRow=0.5,cexCol=0.5)

Rezultati so podobni Saltonskim.

Uteži

> A <- read.csv("trust_w_feb.csv",sep=",",header=TRUE)
> M <- as.matrix(A[,2:45])
> w <- as.vector(A[,46])
> L <- read.csv("SIpolFeb.nam",sep="",header=FALSE,skip=2,encoding="UTF-8")
> nam <- L$V2
> Encoding(nam) <- "UTF-8"
> colnames(M) <- nam
> P <- M
> P[M==0] <- -1
> P[M==2] <- 0
> W <- P*sqrt(w)
> D <- crossprod(W)
> matrix2net(D,Net="recoded.net")
> d <- sqrt(diag(D))
> Cos <- diag(1/d) %*% D %*% diag(1/d)
> colnames(Cos) <- rownames(Cos) <- nam
> matrix2net(Cos,Net="cos.net")
> Dcos <- (1-Cos)/2
> diag(Dcos) <- 0
> disD <- as.dist(Dcos,diag=FALSE,upper=FALSE)
> t <-hclust(disD,method="complete")
> plot(t,hang=-1,cex=1,main="Salton / weighted / Complete")
> heatmap.2(Cos,Rowv=as.dendrogram(t),Colv="Rowv",dendrogram="column",
+       scale="none",revC=TRUE,col = bluered(100),na.color="yellow",
+       trace = "none", density.info = "none",
+       main="Salton / Complete",cexRow=0.5,cexCol=0.5)
> s <-hclust(disD,method="ward")
> plot(s,hang=-1,cex=1,main="Salton / weighted / Ward")
> z <-hclust(disD,method="single")
> plot(z,hang=-1,cex=1,main="Salton / weighted / Single")

Variacije na Jaccarda

Deležni pristop

Zanimivo bi bilo poskusiti tudi deležni pristop pri katerem bi člene vsake vrstice matrike A delili s številom členov različnih od NA v njej. Za mero podobnosti vzamemo kar matriko ujemanj

C = AT • A

kjer je A tako normalizirana matrika.

Vsak anketiranec ima vrednost 1, ki jo enakomerno porazdeli po svojih odgovorih.

vlado/work/2m/salton.txt · Last modified: 2022/05/10 17:45 by vlado
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki