package happy.research.tp;
import happy.coding.io.Logs;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
/**
* Implement Kim and Phalak's approach in "information sciences 2012":
*
* A trust prediction framework in rating-based experience sharing social
* networks without a web of trust
*
* @author guoguibing
*
*/
public class EPT extends TrustModel {
public int Nmin = 4;
public EPT() {
model = "EPT";
}
@Override
protected void global() throws Exception {
// compute global expertise
// initialize review qualities
for (String rw : rws)
rqs.put(rw, 0.0f);
// global ability using Digg's algorithm
int iter = 0;
while (true) {
float err = 0;
// compute review's quality
for (String rv : rws) {
Map<String, Float> rts = ratings.column(rv);
if (rts.size() == 0) {
// if no one rated this review
continue;
}
float den = 0.0f, num = 0.0f;
for (Entry<String, Float> en : rts.entrySet()) {
String u = en.getKey();
float rate = en.getValue();
if (!rbs.containsKey(u))
rbs.put(u, (float) Math.random()); // lazy initialization
float rb = rbs.get(u);
num += rb * rate;
den += rb;
}
float rq = num / den;
float rq_last = rqs.get(rv);
float e = rq_last - rq;
rqs.put(rv, rq);
err += e * e;
}
// update users' rbs
for (String u : users) {
Map<String, Float> rts = ratings.row(u);
if (rts.size() == 0)
continue; // if user has rated nothing
float sum = 0.0f;
int cnt = 0;
for (Entry<String, Float> en : rts.entrySet()) {
String rv = en.getKey();
float rate = en.getValue();
float diff = rqs.get(rv) - rate;
sum += 1 - Math.abs(diff);
cnt++;
}
float rb = weight(cnt) * (sum / cnt);
float rb_last = rbs.containsKey(u) ? rbs.get(u) : 0f;
float e = rb_last - rb;
rbs.put(u, rb);
err += e * e;
}
Logs.debug("Iteration: {}, errors: {}", ++iter, err);
// check if converged
if (err < 1e-5)
break;
}
// global ability as a writer/i.e., expertise: wbs
for (String u : users) {
Collection<String> rvs = reviews.get(u);
if (rvs.size() == 0)
continue;
float sum = 0f;
int cnt = rvs.size();
for (String rv : rvs)
sum += rqs.get(rv);
float wb = weight(cnt) * (sum / cnt);
wbs.put(u, wb);
}
}
@Override
protected float local(String u, String v) throws Exception {
Collection<String> rvs = reviews.get(v);
Map<String, Float> rts = ratings.row(u);
float sum = 0f;
int cnt = 0;
for (String rv : rvs) {
if (rts.containsKey(rv)) {
float rate = rts.get(rv);
sum += rate;
cnt++;
}
}
return cnt > 0 ? sum / cnt : 0f;
}
@Override
protected float predict(String u, String v) throws Exception {
float lt = local(u, v);
float gt = wbs.containsKey(v) ? wbs.get(v) : 0f;
// int n = userWrites.contains(v, u) ? userWrites.get(v, u) : 0;
Collection<String> rvs = reviews.get(v);
Map<String, Float> rts = ratings.row(u);
int n = 0;
for (String rv : rvs) {
if (rts.containsKey(rv))
n++;
}
float a = alpha(n, Nmin);
return a * lt + (1 - a) * gt;
}
}