2009-06-20 3 views
7

다른 사용자로부터 항목 등급을 받아야한다고 생각한 Weighted slope one algorithm (이상 공식적으로는 here (PDF))에 대해 읽었으며 적어도 1 개의 평가와 1 개의 누락 값을 포함하는 사용자 벡터가있는 경우 누락 된 등급.가중 기울기 알고리즘 하나? (Python에서 R로 이식)

나는 Python implementation of the algorithm을 찾았지만 R (나는 더 편안함)으로 이식하는 데 어려움을 겪고 있습니다. 아래는 나의 시도입니다. 어떻게 작동 시키는가에 대한 제안?

미리 감사드립니다.

# take a 'training' set, tr.set and a vector with some missing ratings, d 
pred=function(tr.set,d) { 
    tr.set=rbind(tr.set,d) 
    n.items=ncol(tr.set) 

    # tally frequencies to use as weights 
    freqs=sapply(1:n.items, function(i) { 
     unlist(lapply(1:n.items, function(j) { 
      sum(!(i==j)&!is.na(tr.set[,i])&!is.na(tr.set[,j])) })) }) 

    # estimate product-by-product mean differences in ratings 
    diffs=array(NA, dim=c(n.items,n.items)) 
    diffs=sapply(1:n.items, function(i) { 
     unlist(lapply(1:n.items, function(j) { 
      diffs[j,i]=mean(tr.set[,i]-tr.set[,j],na.rm=T) })) }) 

    # create an output vector with NAs for all the items the user has already rated 
    pred.out=as.numeric(is.na(d)) 
    pred.out[!is.na(d)]=NA 

    a=which(!is.na(pred.out)) 
    b=which(is.na(pred.out)) 

    # calculated the weighted slope one estimate 
    pred.out[a]=sapply(a, function(i) { 
     sum(unlist(lapply(b,function (j) { 
      sum((d[j]+diffs[j,i])*freqs[j,i])/rowSums(freqs)[i] }))) }) 

    names(pred.out)=colnames(tr.set) 
    return(pred.out) } 
# end function 

# test, using example from [3] 
alice=c(squid=1.0, octopus=0.2, cuttlefish=0.5, nautilus=NA) 
bob=c(squid=1.0, octopus=0.5, cuttlefish=NA, nautilus=0.2) 
carole=c(squid=0.2, octopus=1.0, cuttlefish=0.4, nautilus=0.4) 
dave=c(squid=NA, octopus=0.4, cuttlefish=0.9, nautilus=0.5) 
tr.set2=rbind(alice,bob,carole,dave) 
lucy2=c(squid=0.4, octopus=NA, cuttlefish=NA, nautilus=NA) 
pred(tr.set2,lucy2) 
# not correct 
# correct(?): {'nautilus': 0.10, 'octopus': 0.23, 'cuttlefish': 0.25} 
+0

나는 더 읽기 쉽도록 코드를 포맷하려고했지만 R은 나에게 익숙하지 않다. 좋은 스타일이 아니라면 미안 해요. – ephemient

답변

9

나는 슬로프 1의 R 버전을 작성하는 동안 동일한 참조 (Bryan O'Sullivan의 파이썬 코드)를 사용했습니다. 도움이 필요한 경우 아래 코드를 붙여 넣습니다.

predict <- function(userprefs, data.freqs, data.diffs) { 
    seen <- names(userprefs) 

    preds <- sweep(data.diffs[ , seen, drop=FALSE], 2, userprefs, '+') 
    preds <- preds * data.freqs[ , seen] 
    preds <- apply(preds, 1, sum) 

    freqs <- apply(data.freqs[ , seen, drop=FALSE], 1, sum) 

    unseen <- setdiff(names(preds), seen) 
    result <- preds[unseen]/freqs[unseen] 
    return(result[is.finite(result)]) 
} 

update <- function(userdata, freqs, diffs) { 
    for (ratings in userdata) { 
     items <- names(ratings) 
     n <- length(ratings) 

     ratdiff <- rep(ratings, n) - rep(ratings, rep(n, n)) 
     diffs[items, items] <- diffs[items, items] + ratdiff 

     freqs[items, items] <- freqs[items, items] + 1 
    } 
    diffs <- diffs/freqs 
    return(list(freqs=freqs, diffs=diffs)) 
} 


userdata <- list(alice=c(squid=1.0, cuttlefish=0.5, octopus=0.2), 
       bob=c(squid=1.0, octopus=0.5, nautilus=0.2), 
       carole=c(squid=0.2, octopus=1.0, cuttlefish=0.4, nautilus=0.4), 
       dave=c(cuttlefish=0.9, octopus=0.4, nautilus=0.5)) 

items <- c('squid', 'cuttlefish', 'nautilus', 'octopus') 
n.items <- length(items) 
freqs <- diffs <- matrix(0, nrow=n.items, ncol=n.items, dimnames=list(items, items)) 

result <- update(userdata, freqs, diffs) 
print(result$freqs) 
print(result$diffs) 

userprefs <- c(squid=.4) 
predresult <- predict(userprefs, result$freqs, result$diffs) 
print(predresult)