SLIM  1.0
Sparse Linear Methods (SLIM) for top-n recommender systems
 All Data Structures Files Functions Variables Typedefs Macros Pages
slim_learn.c
Go to the documentation of this file.
1 /**************************************************************/
2 /*! \file
3 
4  \brief This file contains all the routines for SLIM learning
5 
6 */
7 /**************************************************************/
8 
9 #include<slim.h>
10 
11 
12 /**************************************************************/
13 /*! \brief SLIM learning
14 
15  \details This routine contains the learning algorithm for SLIM
16 
17  \param[in] ctrl A ctrl structure which contains all the parameters
18  for SLIM learning
19  \param[in] train The training data
20  */
21 /**************************************************************/
22 void slim_learn(ctrl_t * ctrl, gk_csr_t * train){
23 
24  /* set up timers */
25  ctimer_t * timer = gk_malloc(sizeof(ctimer_t), "malloc timer");
26  ctimer_t * timer0 = gk_malloc(sizeof(ctimer_t), "malloc timer");
27  start_timer(timer0);
28 
29 
30 
31  /* constants used across all problems */
32  int nr = train->nrows;
33  int ni = train->ncols;
34 
35  /* lower/upper bound */
36  double * bl = gk_malloc(sizeof(double)*ni, "malloc bl");
37  gk_dset(ni, ctrl->bl, bl);
38  double * bu = gk_malloc(sizeof(double)*ni, "malloc bu");
39  gk_dset(ni, ctrl->bu, bu);
40 
41  /* RHS vector for all problems */
42  double * b = gk_malloc(sizeof(double)*nr, "malloc b");
43  gk_dset(nr, 0, b);
44  /* c, linear vector */
45  double * c = gk_malloc(sizeof(double)*ni, "malloc c");
46  gk_dset(ni, ctrl->lambda, c);
47 
48  /* solution vector */
49  double * w = gk_malloc(sizeof(double)*ni, "malloc w");
50  gk_dset(ni, 0, w);
51 
52  /* the A matrix */
53  gk_csr_t * A = train;
54  cs * csA = gk_malloc(sizeof(cs), "malloc csA");
55 
56  /* Workspace for BCLS */
57  worksp * Wrk = gk_malloc(sizeof(worksp), "malloc Wrk");
58  Wrk->A = csA;
59  csA->p = A->colptr;
60  csA->i = A->colind;
61  csA->x = A->colval;
62  csA->m = A->nrows;
63  csA->n = A->ncols;
64  csA->nzmax = *(A->rowptr + A->nrows);
65  csA->nz = -1; /* column-view */
66  Wrk->max_bcls_niters = ctrl->max_bcls_niters;
67  Wrk->acol = gk_malloc(sizeof(int)*ni, "malloc acol");
68  gk_iset(ni, 1, Wrk->acol);
69 
70  /* temporary space for a column */
71  float * A_colval = NULL;
72 
73 
74  /* output data */
75  int bsize = ctrl->bsize; /* output block size */
76  gk_csr_t * mat = gk_csr_Create();
77  mat->nrows = 0;
78  mat->ncols = train->ncols;
79  mat->rowptr = gk_malloc(sizeof(int)*(ni+1), "malloc mat->rowptr");
80  mat->rowptr[0] = 0;
81  mat->rowind = gk_malloc(sizeof(int)*ni*bsize, "malloc mat->rowind");
82  gk_iset(ni*bsize, 0, mat->rowind);
83  mat->rowval = gk_malloc(sizeof(float)*ni*bsize, "malloc mat->rowval");
84  gk_fset(ni*bsize, 0, mat->rowval);
85 
86 
87 
88 
89  /* constraint data */
90  gk_csr_t * constraint = NULL;
91  if (ctrl->fs){
92  constraint = read_constraint(ctrl, ctrl->fs_file);
93  }
94 
95 
96  /* starting and ending columns */
97  int starti = (ctrl->starti >= 0)? ctrl->starti:0;
98  int endi = (ctrl->endi >= 0)? ctrl->endi:ni;
99 
100  /* go through all columns */
101  for (int i = starti; i < endi; i ++){
102 
103  start_timer(timer);
104  printf("column %8d: ", i);
105 
106  /* the index is beyond the true boundary; this may happen due to cold start */
107  if (i >= train->ncols){
108  *(mat->rowptr + mat->nrows + 1) = *(mat->rowptr + mat->nrows);
109  mat->nrows ++;
110  end_timer(timer);
111  display_timer(timer, "empty iter ");
112  continue;
113  }
114 
115  /* this column is totally empty */
116  if (train->colptr[i+1] - train->colptr[i] == 0){
117  *(mat->rowptr + mat->nrows + 1) = *(mat->rowptr + mat->nrows);
118  mat->nrows ++;
119  end_timer(timer);
120  display_timer(timer, "empty iter ");
121  continue;
122  }
123  /* in case in csr format, there are 0s recored */
124  int allzeros = 1;
125  for (int j = train->colptr[i]; j < train->colptr[i+1]; j ++){
126  if (train->colval[j] != 0) {
127  allzeros = 0; break;
128  }
129  }
130  if (allzeros == 1){
131  *(mat->rowptr + mat->nrows + 1) = *(mat->rowptr + mat->nrows);
132  mat->nrows ++;
133  end_timer(timer);
134  display_timer(timer, "empty iter ");
135  continue;
136  }
137 
138 
139  /**********************************************************/
140  /* BCLS learning */
141  /**********************************************************/
142  /* get the i-th column from A */
143  gk_dset(nr, 0, b);
144  get_column(A, i, b);
145  /* /\* 0 <= w[i] <= 0 => w[i] = 0 *\/ */
146  /* bu[i] = 0; */
147  gk_dset(ni, 0, w);
148  /* disable */
149  Wrk->acol[i] = 0;
150 
151  if (!ctrl->fs){
152  bcsol(ctrl, A, b, w, Wrk, bl, bu, ctrl->beta, c);
153  }
154  else{
155  get_column(constraint, i, w);
156  slim_fs_learn(ctrl, A, b, w, &A_colval, Wrk, bl, bu, ctrl->beta, c);
157  }
158 
159 
160  /* timing for this run */
161  end_timer(timer);
162  display_timer(timer, "iter ");
163 
164 
165 
166  /**********************************************************/
167  /* dump the data */
168  /**********************************************************/
169  /* many enough, dump the data */
170  if (mat->nrows >= ctrl->bsize){
171  printf("Dumping data...\n");
172  csr_Write(mat, ctrl->model_file, "a", GK_CSR_FMT_CSR, 1, 1);
173  mat->nrows = 0;
174  }
175 
176  /* fill out the matrix */
177  *(mat->rowptr + mat->nrows + 1) = *(mat->rowptr + mat->nrows);
178  for (int j = 0, k = 0; j < ni; j ++){
179  if (w[j] > EPSILON){
180  *(mat->rowind + mat->rowptr[mat->nrows] + k) = j;
181  *(mat->rowval + mat->rowptr[mat->nrows] + k) = w[j];
182  (*(mat->rowptr + mat->nrows + 1)) ++;
183  k ++;
184  }
185  }
186  mat->nrows ++;
187 
188  /* reset for the next run */
189  Wrk->acol[i] = 1;
190  /* bu[i] = ctrl->bu; */
191 
192 
193  } /* end of starti - endi */
194 
195  end_timer(timer0);
196  display_timer(timer0, "BCLS");
197 
198  /* left-over data dump */
199  printf("Dumping data...\n");
200  csr_Write(mat, ctrl->model_file, "a", GK_CSR_FMT_CSR, 1, 1);
201 
202 
203 
204  /* finish up */
205  gk_free((void **)&timer, LTERM); gk_free((void **)&timer0, LTERM);
206  gk_csr_Free(&mat); gk_free((void **)&w, LTERM);
207  gk_free((void **)&bl, &bu, &b, &c, LTERM);
208  gk_csr_Free(&constraint);
209  gk_free((void **)&csA, LTERM);
210  gk_free((void **)&Wrk->acol, LTERM); gk_free((void **)&Wrk, LTERM);
211  gk_free((void **)&A_colval, LTERM);
212 
213 
214 }
215