src/modules/convex/mlp_igd.cpp
/**
 * @brief Perform the multilayer perceptron minibatch transition step
 *
 * Called for each tuple.
 */
@brief Perform the multilayer perceptron minibatch transition step
Called for each tuple.
@brief Perform the multilayer perceptron minibatch transition step Called for each tuple .
AnyType
mlp_minibatch_transition::run(AnyType &args) {
    MLPMiniBatchState<MutableArrayHandle<double> > state = args[0];
    if (state.algo.numRows == 0) {
        if (!args[3].isNull()) {
            MLPMiniBatchState<ArrayHandle<double> > previousState = args[3];
            state.allocate(*this, previousState.task.numberOfStages,
                           previousState.task.numbersOfUnits);
            state = previousState;
        } else {
            ArrayHandle<double> numbersOfUnits = args[4].getAs<ArrayHandle<double> >();
            int numberOfStages = numbersOfUnits.size() - 1;
            double stepsize = args[5].getAs<double>();
            state.allocate(*this, numberOfStages,
                           reinterpret_cast<const double *>(numbersOfUnits.ptr()));
            state.task.stepsize = stepsize;
            const int activation = args[6].getAs<int>();
            const int is_classification = args[7].getAs<int>();
            const bool warm_start = args[9].getAs<bool>();
            const double lambda = args[11].getAs<double>();
            state.algo.batchSize = args[12].getAs<int>();
            state.algo.nEpochs = args[13].getAs<int>();
            state.task.lambda = lambda;
            MLPTask::lambda = lambda;
            state.task.model.is_classification =
                static_cast<double>(is_classification);
            state.task.model.activation = static_cast<double>(activation);
            MappedColumnVector initial_coeff = args[10].getAs<MappedColumnVector>();
            Index fan_in, fan_out, layer_start = 0;
            for (size_t k = 0; k < numberOfStages; ++k){
                fan_in = numbersOfUnits[k];
                fan_out = numbersOfUnits[k+1];
                state.task.model.u[k] << initial_coeff.segment(layer_start, (fan_in+1)*fan_out);
                layer_start = (fan_in + 1) * fan_out;
            }
        }
        state.reset();
    }
    Matrix indVar;
    Matrix depVar;
    try {
        indVar = args[1].getAs<MappedMatrix>();
        depVar = args[2].getAs<MappedMatrix>();
    } catch (const ArrayWithNullException &e) {
        return args[0];
    }
    MiniBatchTuple tuple;
    tuple.indVar = trans(indVar);
    tuple.depVar = trans(depVar);
    tuple.weight = args[8].getAs<double>();
    MLPMiniBatchAlgorithm::transitionInMiniBatch(state, tuple);
    state.algo.numRows += tuple.indVar.rows();
    return state;
}
AnyType mlp_minibatch_transition :: run ( AnyType & args ) { MLPMiniBatchState < MutableArrayHandle < double > > state = args [ 0 ] ; if ( state . algo . numRows == 0 ) { if ( ! args [ 3 ] . isNull ( ) ) { MLPMiniBatchState < ArrayHandle < double > > previousState = args [ 3 ] ; state . allocate ( * this , previousState . task . numberOfStages , previousState . task . numbersOfUnits ) ; state = previousState ; } else { ArrayHandle < double > numbersOfUnits = args [ 4 ] . getAs < ArrayHandle < double > > ( ) ; int numberOfStages = numbersOfUnits . size ( ) - 1 ; double stepsize = args [ 5 ] . getAs < double > ( ) ; state . allocate ( * this , numberOfStages , reinterpret_cast < const double * > ( numbersOfUnits . ptr ( ) ) ) ; state . task . stepsize = stepsize ; const int activation = args [ 6 ] . getAs < int > ( ) ; const int is_classification = args [ 7 ] . getAs < int > ( ) ; const bool warm_start = args [ 9 ] . getAs < bool > ( ) ; const double lambda = args [ 11 ] . getAs < double > ( ) ; state . algo . batchSize = args [ 12 ] . getAs < int > ( ) ; state . algo . nEpochs = args [ 13 ] . getAs < int > ( ) ; state . task . lambda = lambda ; MLPTask :: lambda = lambda ; state . task . model . is_classification = static_cast < double > ( is_classification ) ; state . task . model . activation = static_cast < double > ( activation ) ; MappedColumnVector initial_coeff = args [ 10 ] . getAs < MappedColumnVector > ( ) ; Index fan_in , fan_out , layer_start = 0 ; for ( size_t k = 0 ; k < numberOfStages ; ++ k ) { fan_in = numbersOfUnits [ k ] ; fan_out = numbersOfUnits [ k + 1 ] ; state . task . model . u [ k ] << initial_coeff . segment ( layer_start , ( fan_in + 1 ) * fan_out ) ; layer_start = ( fan_in + 1 ) * fan_out ; } } state . reset ( ) ; } Matrix indVar ; Matrix depVar ; try { indVar = args [ 1 ] . getAs < MappedMatrix > ( ) ; depVar = args [ 2 ] . getAs < MappedMatrix > ( ) ; } catch ( const ArrayWithNullException & e ) { return args [ 0 ] ; } MiniBatchTuple tuple ; tuple . indVar = trans ( indVar ) ; tuple . depVar = trans ( depVar ) ; tuple . weight = args [ 8 ] . getAs < double > ( ) ; MLPMiniBatchAlgorithm :: transitionInMiniBatch ( state , tuple ) ; state . algo . numRows += tuple . indVar . rows ( ) ; return state ; }
@brief Perform the multilayer perceptron minibatch transition step
 Called for each tuple.
@brief Perform the multilayer perceptron minibatch transition step Called for each tuple .
// For the first tuple: args[0] is nothing more than a marker that // indicates that we should do some initial operations. // For other tuples: args[0] holds the computation state until last tuple // initilize the state if first tuple // configuration parameters // args[8] is for weighting the input row, which is populated later. /* FIXME: The state is set back to zero for second row onwards if
               initialized as in IGD. The following avoids that, but there is
               some failure with debug build that must be fixed.
            */ // copy initial_coeff into the model // resetting in either case // tuple // Ideally there should be no NULLs in the pre-processed input data, // but keep it in a try block in case the user has modified the // pre-processed data in any way. // The matrices are by default read as column-major. We will have to // transpose it to get back the matrix like how it is in the database. /*
        Note that the IGD version uses the model in Task (model from the
        previous iteration) to compute the loss.
        Minibatch uses the model from Algo (the model based on current
        iteration) to compute the loss. The difference in loss based on one
        iteration is not too much, hence doing so here. We therefore don't
        need to maintain another copy of the model (from previous iteration)
        in the state. The model for the current iteration, and the loss are
        both computed in one function now.
    */