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?
---