SLIM  1.0
Sparse Linear Methods (SLIM) for top-n recommender systems
 All Data Structures Files Functions Variables Typedefs Macros Pages
Functions
slim_learn.c File Reference

This file contains all the routines for SLIM learning. More...

#include <slim.h>

Go to the source code of this file.

Functions

void slim_learn (ctrl_t *ctrl, gk_csr_t *train)
 SLIM learning.
 

Detailed Description

This file contains all the routines for SLIM learning.

Definition in file slim_learn.c.

Function Documentation

void slim_learn ( ctrl_t ctrl,
gk_csr_t *  train 
)

SLIM learning.

This routine contains the learning algorithm for SLIM

Parameters
[in]ctrlA ctrl structure which contains all the parameters for SLIM learning
[in]trainThe training data

Definition at line 22 of file slim_learn.c.

References worksp::A, worksp::acol, bcsol(), ctrl_t::beta, ctrl_t::bl, ctrl_t::bsize, ctrl_t::bu, csr_Write(), display_timer(), end_timer(), ctrl_t::endi, EPSILON, ctrl_t::fs, ctrl_t::fs_file, get_column(), cs_sparse::i, ctrl_t::lambda, cs_sparse::m, ctrl_t::max_bcls_niters, worksp::max_bcls_niters, ctrl_t::model_file, cs_sparse::n, cs_sparse::nz, cs_sparse::nzmax, cs_sparse::p, read_constraint(), slim_fs_learn(), start_timer(), ctrl_t::starti, and cs_sparse::x.

Referenced by main().

{
/* set up timers */
ctimer_t * timer = gk_malloc(sizeof(ctimer_t), "malloc timer");
ctimer_t * timer0 = gk_malloc(sizeof(ctimer_t), "malloc timer");
start_timer(timer0);
/* constants used across all problems */
int nr = train->nrows;
int ni = train->ncols;
/* lower/upper bound */
double * bl = gk_malloc(sizeof(double)*ni, "malloc bl");
gk_dset(ni, ctrl->bl, bl);
double * bu = gk_malloc(sizeof(double)*ni, "malloc bu");
gk_dset(ni, ctrl->bu, bu);
/* RHS vector for all problems */
double * b = gk_malloc(sizeof(double)*nr, "malloc b");
gk_dset(nr, 0, b);
/* c, linear vector */
double * c = gk_malloc(sizeof(double)*ni, "malloc c");
gk_dset(ni, ctrl->lambda, c);
/* solution vector */
double * w = gk_malloc(sizeof(double)*ni, "malloc w");
gk_dset(ni, 0, w);
/* the A matrix */
gk_csr_t * A = train;
cs * csA = gk_malloc(sizeof(cs), "malloc csA");
/* Workspace for BCLS */
worksp * Wrk = gk_malloc(sizeof(worksp), "malloc Wrk");
Wrk->A = csA;
csA->p = A->colptr;
csA->i = A->colind;
csA->x = A->colval;
csA->m = A->nrows;
csA->n = A->ncols;
csA->nzmax = *(A->rowptr + A->nrows);
csA->nz = -1; /* column-view */
Wrk->acol = gk_malloc(sizeof(int)*ni, "malloc acol");
gk_iset(ni, 1, Wrk->acol);
/* temporary space for a column */
float * A_colval = NULL;
/* output data */
int bsize = ctrl->bsize; /* output block size */
gk_csr_t * mat = gk_csr_Create();
mat->nrows = 0;
mat->ncols = train->ncols;
mat->rowptr = gk_malloc(sizeof(int)*(ni+1), "malloc mat->rowptr");
mat->rowptr[0] = 0;
mat->rowind = gk_malloc(sizeof(int)*ni*bsize, "malloc mat->rowind");
gk_iset(ni*bsize, 0, mat->rowind);
mat->rowval = gk_malloc(sizeof(float)*ni*bsize, "malloc mat->rowval");
gk_fset(ni*bsize, 0, mat->rowval);
/* constraint data */
gk_csr_t * constraint = NULL;
if (ctrl->fs){
constraint = read_constraint(ctrl, ctrl->fs_file);
}
/* starting and ending columns */
int starti = (ctrl->starti >= 0)? ctrl->starti:0;
int endi = (ctrl->endi >= 0)? ctrl->endi:ni;
/* go through all columns */
for (int i = starti; i < endi; i ++){
start_timer(timer);
printf("column %8d: ", i);
/* the index is beyond the true boundary; this may happen due to cold start */
if (i >= train->ncols){
*(mat->rowptr + mat->nrows + 1) = *(mat->rowptr + mat->nrows);
mat->nrows ++;
end_timer(timer);
display_timer(timer, "empty iter ");
continue;
}
/* this column is totally empty */
if (train->colptr[i+1] - train->colptr[i] == 0){
*(mat->rowptr + mat->nrows + 1) = *(mat->rowptr + mat->nrows);
mat->nrows ++;
end_timer(timer);
display_timer(timer, "empty iter ");
continue;
}
/* in case in csr format, there are 0s recored */
int allzeros = 1;
for (int j = train->colptr[i]; j < train->colptr[i+1]; j ++){
if (train->colval[j] != 0) {
allzeros = 0; break;
}
}
if (allzeros == 1){
*(mat->rowptr + mat->nrows + 1) = *(mat->rowptr + mat->nrows);
mat->nrows ++;
end_timer(timer);
display_timer(timer, "empty iter ");
continue;
}
/**********************************************************/
/* BCLS learning */
/**********************************************************/
/* get the i-th column from A */
gk_dset(nr, 0, b);
get_column(A, i, b);
/* /\* 0 <= w[i] <= 0 => w[i] = 0 *\/ */
/* bu[i] = 0; */
gk_dset(ni, 0, w);
/* disable */
Wrk->acol[i] = 0;
if (!ctrl->fs){
bcsol(ctrl, A, b, w, Wrk, bl, bu, ctrl->beta, c);
}
else{
get_column(constraint, i, w);
slim_fs_learn(ctrl, A, b, w, &A_colval, Wrk, bl, bu, ctrl->beta, c);
}
/* timing for this run */
end_timer(timer);
display_timer(timer, "iter ");
/**********************************************************/
/* dump the data */
/**********************************************************/
/* many enough, dump the data */
if (mat->nrows >= ctrl->bsize){
printf("Dumping data...\n");
csr_Write(mat, ctrl->model_file, "a", GK_CSR_FMT_CSR, 1, 1);
mat->nrows = 0;
}
/* fill out the matrix */
*(mat->rowptr + mat->nrows + 1) = *(mat->rowptr + mat->nrows);
for (int j = 0, k = 0; j < ni; j ++){
if (w[j] > EPSILON){
*(mat->rowind + mat->rowptr[mat->nrows] + k) = j;
*(mat->rowval + mat->rowptr[mat->nrows] + k) = w[j];
(*(mat->rowptr + mat->nrows + 1)) ++;
k ++;
}
}
mat->nrows ++;
/* reset for the next run */
Wrk->acol[i] = 1;
/* bu[i] = ctrl->bu; */
} /* end of starti - endi */
end_timer(timer0);
display_timer(timer0, "BCLS");
/* left-over data dump */
printf("Dumping data...\n");
csr_Write(mat, ctrl->model_file, "a", GK_CSR_FMT_CSR, 1, 1);
/* finish up */
gk_free((void **)&timer, LTERM); gk_free((void **)&timer0, LTERM);
gk_csr_Free(&mat); gk_free((void **)&w, LTERM);
gk_free((void **)&bl, &bu, &b, &c, LTERM);
gk_csr_Free(&constraint);
gk_free((void **)&csA, LTERM);
gk_free((void **)&Wrk->acol, LTERM); gk_free((void **)&Wrk, LTERM);
gk_free((void **)&A_colval, LTERM);
}