@Override
	protected void buildModel() throws Exception {
		last_loss = 0;

		// number of iteration cycles
		for (int iter = 1; iter <= numIters; iter++) {

			loss = 0;

			// each cycle iterates through one coordinate direction
			for (int j = 0; j < numItems; j++) {

				// find k-nearest neighbors
				Collection<Integer> nns = knn > 0 ? itemNNs.get(j) : allItems;

				// for each nearest neighbor i, update wij by the coordinate descent update rule
				// it is OK if i==j, since wjj = 0; 
				for (Integer i : nns) {

					double gradSum = 0, rateSum = 0, errs = 0;

					SparseVector Ri = trainMatrix.column(i);
					int N = Ri.getCount();
					for (VectorEntry ve : Ri) {
						int u = ve.index();
						double rui = ve.get();
						double ruj = trainMatrix.get(u, j);
						double euj = ruj - predict(u, j, i);

						gradSum += rui * euj;
						rateSum += rui * rui;

						errs += euj * euj;
					}
					gradSum /= N;
					rateSum /= N;
					errs /= N;

					double wij = W.get(i, j);
					loss += errs + 0.5 * regL2 * wij * wij + regL1 * wij;

					if (regL1 < Math.abs(gradSum)) {
						if (gradSum > 0) {
							double update = (gradSum - regL1) / (regL2 + rateSum);
							W.set(i, j, update);
						} else {
							// One doubt: in this case, wij<0, however, the paper says wij>=0. How to gaurantee that?
							double update = (gradSum + regL1) / (regL2 + rateSum);
							W.set(i, j, update);
						}
					} else {
						W.set(i, j, 0.0);
					}
				}
			}

			if (isConverged(iter))
				break;
		}
	}