likely.js
function train(inputMatrix, bias)
{
  N = inputMatrix.rows();    // number of rows 
  M = inputMatrix.cols(); // number of columns
  
  // Generate random P and Q based on the dimensions of inputMatrix
  var P_model = generateRandomMatrix(N, K);
  var Q_model = generateRandomMatrix(K, M);
  
  var i = 0
  for(i = 0; i < DESCENT_STEPS; i++)
  {
  	//console.log('------------------ Iteration --------------------');
    // Calculate error
    var error = calculateError(P_model.x(Q_model), inputMatrix, bias);

	P_prime = P_model.elements;
	Q_prime = Q_model.elements;
	
	// For debugging
	//console.log('P: ' + JSON.stringify(P_prime));
	//console.log('Q: ' + JSON.stringify(Q_prime));
	
	// Update P and Q to reduce error
    for (var row = 0; row < N; row++)
    {
    	for (var col = 0; col < M; col++)
    	{
    		for(var feature = 0; feature < K; feature++)
    		{
    			// update formulas will change values in the opposite direction of the gradient.
    			
    			// P Update Formula
    			// p_ik = p_ik + alpha * (e_ij * q_kj - beta * p_ik)
    			// Reverse Gradient: alpha * e_ij * q_kj   -- Note that we omit the 2* factor since it's not necessary for convergence.
    			// Regularization factor: alpha * beta * p_ik 
    			var p_prev = P_prime[row][feature];
    			P_prime[row][feature] = P_prime[row][feature] + 
    									  ALPHA*(error.e(row+1, col+1)*Q_prime[feature][col] -
    									  	    BETA * P_prime[row][feature]);
    			//console.log('P['+row+']['+feature+'] ('+p_prev+') <- ('+P_prime[row][feature]+')');
    									  	   
    			// Q Update Formula
    			// q_kj = q_kj + alpha x (e_ij x p_ik - beta x q_kj)
    			// Reverse Gradient: alpha * e_ij * p_ik   -- Note that we omit the 2* factor since it's not necessary for convergence.
    			// Regularization factor: alpha * beta * q_kj  
    			var q_prev = Q_prime[feature][col];
  				Q_prime[feature][col] = Q_prime[feature][col] +
  											 ALPHA *(error.e(row+1, col+1)*P_prime[row][feature] -
  											 		BETA * Q_prime[feature][col]);  	
    			//console.log('Q['+feature+']['+col+'] ('+q_prev+') <- ('+Q_prime[feature][col]+')');								  	    
    									  	
            }
    	}
    }
    
    // if we've already reached the error threshold, no need to descend further
    var totError = calculateTotalError(error);
    if(totError < MAX_ERROR)
    {
    	//console.log('Reached error threshold early, no more descent needed.');
	    break;
    }
  }
  
  //console.log('Descent steps used: ' + i);
  
  // produce the final estimation by multiplying P and Q
  var finalModel = P_model.x(Q_model); 
  
  // if we were considering bias, we have to add it back in
  if(bias)
  {
  		// add back the overall average
  		finalModel = finalModel.map(function(x) { return x + bias.average; });
  	
		var finalElements = finalModel.elements;
		
		// add back the row bias from each row
		for(var i = 1; i <= finalModel.rows(); i++)
		{
			for(var j = 1; j <= finalModel.cols(); j++)
			{
				finalElements[i-1][j-1] += bias.rowBiases.e(i);
			}
		}
		
		// add back the column bias from each column
		for(var i = 1; i <= finalModel.rows(); i++)
		{
			for(var j = 1; j <= finalModel.cols(); j++)
			{
				finalElements[i-1][j-1] += bias.colBiases.e(j);
			}
		}
  }
  
  return finalModel;
}
function train(inputMatrix, bias)
{
  N = inputMatrix.rows();    // number of rows 
  M = inputMatrix.cols(); // number of columns
  
  // Generate random P and Q based on the dimensions of inputMatrix
  var P_model = generateRandomMatrix(N, K);
  var Q_model = generateRandomMatrix(K, M);
  
  var i = 0
  for(i = 0; i < DESCENT_STEPS; i++)
  {
  	//console.log('------------------ Iteration --------------------');
    // Calculate error
    var error = calculateError(P_model.x(Q_model), inputMatrix, bias);

	P_prime = P_model.elements;
	Q_prime = Q_model.elements;
	
	// For debugging
	//console.log('P: ' + JSON.stringify(P_prime));
	//console.log('Q: ' + JSON.stringify(Q_prime));
	
	// Update P and Q to reduce error
    for (var row = 0; row < N; row++)
    {
    	for (var col = 0; col < M; col++)
    	{
    		for(var feature = 0; feature < K; feature++)
    		{
    			// update formulas will change values in the opposite direction of the gradient.
    			
    			// P Update Formula
    			// p_ik = p_ik + alpha * (e_ij * q_kj - beta * p_ik)
    			// Reverse Gradient: alpha * e_ij * q_kj   -- Note that we omit the 2* factor since it's not necessary for convergence.
    			// Regularization factor: alpha * beta * p_ik 
    			var p_prev = P_prime[row][feature];
    			P_prime[row][feature] = P_prime[row][feature] + 
    									  ALPHA*(error.e(row+1, col+1)*Q_prime[feature][col] -
    									  	    BETA * P_prime[row][feature]);
    			//console.log('P['+row+']['+feature+'] ('+p_prev+') <- ('+P_prime[row][feature]+')');
    									  	   
    			// Q Update Formula
    			// q_kj = q_kj + alpha x (e_ij x p_ik - beta x q_kj)
    			// Reverse Gradient: alpha * e_ij * p_ik   -- Note that we omit the 2* factor since it's not necessary for convergence.
    			// Regularization factor: alpha * beta * q_kj  
    			var q_prev = Q_prime[feature][col];
  				Q_prime[feature][col] = Q_prime[feature][col] +
  											 ALPHA *(error.e(row+1, col+1)*P_prime[row][feature] -
  											 		BETA * Q_prime[feature][col]);  	
    			//console.log('Q['+feature+']['+col+'] ('+q_prev+') <- ('+Q_prime[feature][col]+')');								  	    
    									  	
            }
    	}
    }
    
    // if we've already reached the error threshold, no need to descend further
    var totError = calculateTotalError(error);
    if(totError < MAX_ERROR)
    {
    	//console.log('Reached error threshold early, no more descent needed.');
	    break;
    }
  }
  
  //console.log('Descent steps used: ' + i);
  
  // produce the final estimation by multiplying P and Q
  var finalModel = P_model.x(Q_model); 
  
  // if we were considering bias, we have to add it back in
  if(bias)
  {
  		// add back the overall average
  		finalModel = finalModel.map(function(x) { return x + bias.average; });
  	
		var finalElements = finalModel.elements;
		
		// add back the row bias from each row
		for(var i = 1; i <= finalModel.rows(); i++)
		{
			for(var j = 1; j <= finalModel.cols(); j++)
			{
				finalElements[i-1][j-1] += bias.rowBiases.e(i);
			}
		}
		
		// add back the column bias from each column
		for(var i = 1; i <= finalModel.rows(); i++)
		{
			for(var j = 1; j <= finalModel.cols(); j++)
			{
				finalElements[i-1][j-1] += bias.colBiases.e(j);
			}
		}
  }
  
  return finalModel;
}
function train ( inputMatrix , bias ) { N = inputMatrix . rows ( ) ; // number of rows  M = inputMatrix . cols ( ) ; // number of columns // Generate random P and Q based on the dimensions of inputMatrix var P_model = generateRandomMatrix ( N , K ) ; var Q_model = generateRandomMatrix ( K , M ) ; var i = 0 for ( i = 0 ; i < DESCENT_STEPS ; i ++ ) { //console.log('------------------ Iteration --------------------'); // Calculate error var error = calculateError ( P_model . x ( Q_model ) , inputMatrix , bias ) ; P_prime = P_model . elements ; Q_prime = Q_model . elements ; // For debugging //console.log('P: ' + JSON.stringify(P_prime)); //console.log('Q: ' + JSON.stringify(Q_prime)); // Update P and Q to reduce error for ( var row = 0 ; row < N ; row ++ ) { for ( var col = 0 ; col < M ; col ++ ) { for ( var feature = 0 ; feature < K ; feature ++ ) { // update formulas will change values in the opposite direction of the gradient. // P Update Formula // p_ik = p_ik + alpha * (e_ij * q_kj - beta * p_ik) // Reverse Gradient: alpha * e_ij * q_kj   -- Note that we omit the 2* factor since it's not necessary for convergence. // Regularization factor: alpha * beta * p_ik  var p_prev = P_prime [ row ] [ feature ] ; P_prime [ row ] [ feature ] = P_prime [ row ] [ feature ] + ALPHA * ( error . e ( row + 1 , col + 1 ) * Q_prime [ feature ] [ col ] - BETA * P_prime [ row ] [ feature ] ) ; //console.log('P['+row+']['+feature+'] ('+p_prev+') <- ('+P_prime[row][feature]+')'); // Q Update Formula // q_kj = q_kj + alpha x (e_ij x p_ik - beta x q_kj) // Reverse Gradient: alpha * e_ij * p_ik   -- Note that we omit the 2* factor since it's not necessary for convergence. // Regularization factor: alpha * beta * q_kj   var q_prev = Q_prime [ feature ] [ col ] ; Q_prime [ feature ] [ col ] = Q_prime [ feature ] [ col ] + ALPHA * ( error . e ( row + 1 , col + 1 ) * P_prime [ row ] [ feature ] - BETA * Q_prime [ feature ] [ col ] ) ; //console.log('Q['+feature+']['+col+'] ('+q_prev+') <- ('+Q_prime[feature][col]+')');								  	     } } } // if we've already reached the error threshold, no need to descend further var totError = calculateTotalError ( error ) ; if ( totError < MAX_ERROR ) { //console.log('Reached error threshold early, no more descent needed.'); break ; } } //console.log('Descent steps used: ' + i); // produce the final estimation by multiplying P and Q var finalModel = P_model . x ( Q_model ) ; // if we were considering bias, we have to add it back in if ( bias ) { // add back the overall average finalModel = finalModel . map ( function ( x ) { return x + bias . average ; } ) ; var finalElements = finalModel . elements ; // add back the row bias from each row for ( var i = 1 ; i <= finalModel . rows ( ) ; i ++ ) { for ( var j = 1 ; j <= finalModel . cols ( ) ; j ++ ) { finalElements [ i - 1 ] [ j - 1 ] += bias . rowBiases . e ( i ) ; } } // add back the column bias from each column for ( var i = 1 ; i <= finalModel . rows ( ) ; i ++ ) { for ( var j = 1 ; j <= finalModel . cols ( ) ; j ++ ) { finalElements [ i - 1 ] [ j - 1 ] += bias . colBiases . e ( j ) ; } } } return finalModel ; }
Trains the model on the given input by composing two matrices P and Q which
approximate the input through their product.
@param inputMatrix A two dimensional array representing input values
@returns Model A model entity, with estimated values based on the input
Trains the model on the given input by composing two matrices P and Q which approximate the input through their product .