Skip to content

Commit

Permalink
Add 1 vs k prediction
Browse files Browse the repository at this point in the history
  • Loading branch information
shuix007 authored Oct 29, 2019
1 parent a0a8175 commit 50f5eba
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 1 deletion.
62 changes: 62 additions & 0 deletions src/libslim/predict.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,65 @@ int32_t GetRecommendations(params_t *params, gk_csr_t *smat, int32_t nratings,

return nrcmds;
}


/**************************************************************************/
/*! Get the top-N recommendations given the provided historical data */
/**************************************************************************/
int32_t GetRec_1vsk(params_t *params, gk_csr_t *smat, int32_t nratings,
int32_t *itemids, float *ratings, int32_t nrcmds,
int32_t *rids, float *rscores, int32_t nnegs,
int32_t *negitems) {
ssize_t j;
int32_t iR, i, k, ncols, ncand;
ssize_t *rowptr;
int32_t *rowind, *marker;
float *rowval, rating;
gk_fkv_t *cand;

ncols = smat->ncols;
rowptr = smat->rowptr;
rowind = smat->rowind;
rowval = smat->rowval;

marker = gk_i32smalloc(ncols, -2, "marker");
cand = gk_fkvmalloc(ncols, "cand");

ncand = 0;
for (iR = 0; iR < nnegs; iR++) {
cand[ncand].val = negitems[iR];
cand[ncand].key = 0.0;
if (negitems[iR] >= 0 && negitems[iR] < ncols) {
marker[negitems[iR]] = ncand++;
}
else {
ncand++;
}
}

for (iR = 0; iR < nratings; iR++) {
i = itemids[iR];
if (i >= ncols && i < 0)
continue;

rating = (ratings ? ratings[iR] : 1.0);
for (j = rowptr[i]; j < rowptr[i + 1]; j++) {
k = rowind[j];
if (marker[k] == -2)
continue; /* part of the history */

cand[marker[k]].key += rating * rowval[j];
}
}

gk_fkvsortd(ncand, cand);

nrcmds = gk_min(ncand, nrcmds);
for (iR = 0; iR < nrcmds; iR++) {
rids[iR] = cand[iR].val;
rscores[iR] = cand[iR].key;
}

gk_free((void **)&marker, &cand, LTERM);
return nrcmds;
}
4 changes: 4 additions & 0 deletions src/libslim/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ double ComputeAvgZeroScore(gk_csr_t *mat, double *x, double *y, int32_t ntop);
int32_t GetRecommendations(params_t *params, gk_csr_t *smat, int32_t nratings,
int32_t *itemids, float *ratings, int32_t nrcmds, int32_t *rids,
float *rscores);
int32_t GetRec_1vsk(params_t *params, gk_csr_t *smat, int32_t nratings,
int32_t *itemids, float *ratings, int32_t nrcmds,
int32_t *rids, float *rscores, int32_t nnegs,
int32_t *negitems);

/* timing.c */
void InitTimers(params_t *params);
Expand Down
82 changes: 81 additions & 1 deletion src/libslim/pyapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,17 +392,96 @@ int32_t Py_SLIM_GetTopN(slim_t *model, int32_t nratings, int32_t *itemids,
return nrcmds;
}

int32_t Py_SLIM_GetTopN_1vsk(slim_t *model, int32_t nratings, int32_t *itemids,
float *ratings, int32_t nrcmds, int32_t *rids,
float *rscores, int32_t nnegs, int32_t *negitems,
int32_t dbglvl) {
params_t params;
gk_csr_t *smat;

/* setup params */
memset((void *)&params, 0, sizeof(params_t));

params.dbglvl = dbglvl;

InitTimers(&params);

/* get the model in the internal form */
smat = (gk_csr_t *)model;

/* get the recommendations */
gk_startwctimer(params.TotalTmr);
nrcmds = GetRec_1vsk(&params, smat, nratings, itemids, ratings, nrcmds,
rids, rscores, nnegs, negitems);
gk_stopwctimer(params.TotalTmr);

if (nrcmds < 0)
return SLIM_ERROR;
else
return nrcmds;
}

/**************************************************************************/
/*! @brief predict topn lists
@param nrcmds number of items to be recommended
nnegs number of negative items
slimhandle handle to the training matrix
trnhandle integer training options
negitems pointer to the negative items
output pointer to the output lists
scores pointer to the output scores
@return a flag indicating whether the function succeed
*/
/**************************************************************************/
int32_t Py_SLIM_Predict_1vsk(int32_t nrcmds, int32_t nnegs, slim_t *slimhandle, slim_t *trnhandle,
int32_t *negitems, int32_t *output, float *scores) {
int32_t iU, iR, n, nvalid = 0;
int32_t *rids;
float *rscores;
gk_csr_t *model, *trnmat;

model = (gk_csr_t *)slimhandle;
trnmat = (gk_csr_t *)trnhandle;

rids = gk_i32malloc(nrcmds, "rids");
rscores = gk_fmalloc(nrcmds, "rscores");

for (iU = 0; iU < trnmat->nrows; iU++) {
n = Py_SLIM_GetTopN_1vsk(
model, trnmat->rowptr[iU + 1] - trnmat->rowptr[iU],
trnmat->rowind + trnmat->rowptr[iU],
(trnmat->rowval ? trnmat->rowval + trnmat->rowptr[iU] : NULL), nrcmds,
rids, rscores, nnegs, negitems + iU * nnegs, 0);

if (n != SLIM_ERROR) {
for (iR = 0; iR < n; iR++) {
output[iU * nrcmds + iR] = rids[iR];
scores[iU * nrcmds + iR] = rscores[iR];
// printf("id: %d", rids[iR]);
}
nvalid += 1;
// printf("---\n");
}
}
if (nvalid < 1) {
return SLIM_ERROR;
} else {
return SLIM_OK;
}
}

/**************************************************************************/
/*! @brief predict topn lists
@param nrcmds number of items to be recommended
slimhandle handle to the training matrix
trnhandle integer training options
output pointer to the output lists
scores pointer to the output scores
@return a flag indicating whether the function succeed
*/
/**************************************************************************/
int32_t Py_SLIM_Predict(int32_t nrcmds, slim_t *slimhandle, slim_t *trnhandle,
int32_t *output) {
int32_t *output, float *scores) {
int32_t iU, iR, n, nvalid = 0;
int32_t *rids;
float *rscores;
Expand All @@ -424,6 +503,7 @@ int32_t Py_SLIM_Predict(int32_t nrcmds, slim_t *slimhandle, slim_t *trnhandle,
if (n != SLIM_ERROR) {
for (iR = 0; iR < n; iR++) {
output[iU * nrcmds + iR] = rids[iR];
scores[iU * nrcmds + iR] = rscores[iR];
}
nvalid += 1;
}
Expand Down

0 comments on commit 50f5eba

Please sign in to comment.