madlib-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From orhankislal <...@git.apache.org>
Subject [GitHub] madlib pull request #229: SVM: Add minibatch as a new solver
Date Wed, 24 Jan 2018 21:59:02 GMT
Github user orhankislal commented on a diff in the pull request:

    https://github.com/apache/madlib/pull/229#discussion_r163690557
  
    --- Diff: src/modules/convex/linear_svm_igd.cpp ---
    @@ -120,6 +124,98 @@ linear_svm_igd_transition::run(AnyType &args) {
         return state;
     }
     
    +/**
    + * @brief Perform the linear support vector machine transition step
    + *
    + * Called for each tuple.
    + */
    +AnyType
    +linear_svm_igd_minibatch_transition::run(AnyType &args) {
    +    // The real state.
    +    // 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
    +    SVMMinibatchState<MutableArrayHandle<double> > state = args[0];
    +
    +    // initialize the state if first tuple
    +    if (state.algo.numRows == 0) {
    +
    +        LinearSVM<GLMModel, GLMTuple >::epsilon = args[9].getAs<double>();;
    +        LinearSVM<GLMModel, GLMTuple >::is_svc = args[10].getAs<bool>();;
    +        if (!args[3].isNull()) {
    +            SVMMinibatchState<ArrayHandle<double> > previousState = args[3];
    +            state.allocate(*this, previousState.task.nFeatures);
    +            state = previousState;
    +        } else {
    +            // configuration parameters
    +            uint32_t dimension = args[4].getAs<uint32_t>();
    +            state.allocate(*this, dimension); // with zeros
    +        }
    +        // resetting in either case
    +        // state.reset();
    +        state.task.stepsize = args[5].getAs<double>();
    +        const double lambda = args[6].getAs<double>();
    +        const bool isL2 = args[7].getAs<bool>();
    +        const int nTuples = args[8].getAs<int>();
    +
    +        // The regularization operations called below (scaling and clipping)
    +        // need these class variables to be set.
    +        L1<GLMModel>::n_tuples = nTuples;
    +        L2<GLMModel>::n_tuples = nTuples;
    +        if (isL2)
    +            L2<GLMModel>::lambda = lambda;
    +        else
    +            L1<GLMModel>::lambda = lambda;
    +    }
    +
    +    state.algo.nEpochs = args[12].getAs<int>();
    +    state.algo.batchSize = args[13].getAs<int>();
    +
    +    // Skip the current record if args[1] (features) contains NULL values,
    +    // or args[2] is NULL
    +    try {
    +        args[1].getAs<MappedMatrix>();
    +    } catch (const ArrayWithNullException &e) {
    +        return args[0];
    +    }
    +    if (args[2].isNull())
    +        return args[0];
    +
    +    // tuple
    +    using madlib::dbal::eigen_integration::MappedColumnVector;
    +
    +    MappedMatrix x(NULL);
    +    MappedColumnVector y(NULL);
    +    try {
    +        new (&x) MappedMatrix(args[1].getAs<MappedMatrix>());
    +        new (&y) MappedColumnVector(args[2].getAs<MappedColumnVector>());
    +    } catch (const ArrayWithNullException &e) {
    +        return args[0];
    +    }
    +    SVMMiniBatchTuple tuple;
    +    tuple.indVar = trans(x);
    +    tuple.depVar = y;
    +
    +    // each tuple can be weighted - this can be combination of the sample weight
    +    // and the class weight. Calling function is responsible for combining the two
    +    // into a single tuple weight. The default value for this parameter is 1, set
    +    // into the definition of "tuple".
    +    // The weight is used to increase the value of a particular tuple for the online
    +    // learning. The weight is not used for the loss computation.
    +    tuple.weight = args[11].getAs<double>();
    +
    +
    +    // Now do the transition step
    +    // apply Minibatching with regularization
    +    L2<GLMModel>::scaling(state.task.model, state.task.stepsize);
    +    LinearSVMIGDAlgoMiniBatch::transitionInMiniBatch(state, tuple);
    +    L1<GLMModel>::clipping(state.task.model, state.task.stepsize);
    +
    --- End diff --
    
    Should we leave a comment on why the mini-batching transition step does not call the loss
and gradient algorithms like the regular one?
    On the other hand, I am not sure if we want to explain the lack of something in the comments.
Maybe we can mention this implementation detail in the design docs?


---

Mime
View raw message