diff --git a/benchmarks/bench_sgd_regression.py b/benchmarks/bench_sgd_regression.py
new file mode 100644
index 0000000000000000000000000000000000000000..98351e07d4429bf1d589b19b06c4a4e3beaab8f2
--- /dev/null
+++ b/benchmarks/bench_sgd_regression.py
@@ -0,0 +1,124 @@
+"""
+Benchmark for SGD regression
+
+Compares SGD regression against coordinate descent and Ridge
+on synthetik data.
+"""
+
+print __doc__
+
+# Author: Peter Prettenhofer <peter.prettenhofer@gmail.com>
+# License: BSD Style.
+
+import numpy as np
+import pylab as pl
+
+import gc
+
+from time import time
+
+from scikits.learn.linear_model import Ridge, SGDRegressor, ElasticNet
+from scikits.learn.metrics import mean_square_error
+from scikits.learn.datasets.samples_generator import make_regression_dataset
+
+if __name__ == "__main__":
+    list_n_samples = np.linspace(100, 10000, 5).astype(np.int)
+    list_n_features = [10, 100, 1000]
+    n_test = 1000
+    noise = 0.1
+    alpha = 0.01
+    sgd_results = np.zeros((len(list_n_samples), len(list_n_features), 2))
+    elnet_results = np.zeros((len(list_n_samples), len(list_n_features), 2))
+    ridge_results = np.zeros((len(list_n_samples), len(list_n_features), 2))
+    for i, n_train in enumerate(list_n_samples):
+        for j, n_features in enumerate(list_n_features):
+            X_train, y_train, X_test, y_test, coef = make_regression_dataset(
+                n_train_samples=n_train, n_test_samples=n_test,
+                n_features=n_features, noise=noise)
+            print "======================="
+            print "Round %d %d" % (i, j)
+            print "n_features:", n_features
+            print "n_samples:", n_train
+
+            # Shuffle data
+            idx = np.arange(n_train)
+            np.random.seed(13)
+            np.random.shuffle(idx)
+            X_train = X_train[idx]
+            y_train = y_train[idx]
+
+            std = X_train.std(axis=0)
+            mean = X_train.mean(axis=0)
+            X_train = (X_train - mean) / std
+            X_test = (X_test - mean) / std
+
+            std = y_train.std(axis=0)
+            mean = y_train.mean(axis=0)
+            y_train = (y_train - mean) / std
+            y_test = (y_test - mean) / std
+
+            gc.collect()
+            print "- benching ElasticNet"
+            clf = ElasticNet(alpha=alpha, rho=0.5, fit_intercept=False)
+            tstart = time()
+            clf.fit(X_train, y_train)
+            elnet_results[i, j, 0] = mean_square_error(clf.predict(X_test),
+                                                       y_test)
+            elnet_results[i, j, 1] = time() - tstart
+
+            gc.collect()
+            print "- benching SGD"
+            n_iter = np.ceil(10 ** 4.0 / n_train)
+            clf = SGDRegressor(alpha=alpha, fit_intercept=False,
+                               n_iter=n_iter, learning_rate="invscaling",
+                               eta0=.01, power_t=0.25)
+
+            tstart = time()
+            clf.fit(X_train, y_train)
+            sgd_results[i, j, 0] = mean_square_error(clf.predict(X_test),
+                                                     y_test)
+            sgd_results[i, j, 1] = time() - tstart
+
+            gc.collect()
+            print "- benching RidgeRegression"
+            clf = Ridge(alpha=alpha, fit_intercept=False)
+            tstart = time()
+            clf.fit(X_train, y_train)
+            ridge_results[i, j, 0] = mean_square_error(clf.predict(X_test),
+                                                       y_test)
+            ridge_results[i, j, 1] = time() - tstart
+
+    # Plot results
+    i = 0
+    m = len(list_n_features)
+    pl.figure(figsize=(5 * 2, 4 * m))
+    for j in range(m):
+        pl.subplot(m, 2, i + 1)
+        pl.plot(list_n_samples, np.sqrt(elnet_results[:, j, 0]),
+                label="ElasticNet")
+        pl.plot(list_n_samples, np.sqrt(sgd_results[:, j, 0]),
+                label="SGDRegressor")
+        pl.plot(list_n_samples, np.sqrt(ridge_results[:, j, 0]),
+                label="Ridge")
+        pl.legend(prop={"size": 10})
+        pl.xlabel("n_train")
+        pl.ylabel("RMSE")
+        pl.title("Test error - %d features" % list_n_features[j])
+        i += 1
+
+        pl.subplot(m, 2, i + 1)
+        pl.plot(list_n_samples, np.sqrt(elnet_results[:, j, 1]),
+                label="ElasticNet")
+        pl.plot(list_n_samples, np.sqrt(sgd_results[:, j, 1]),
+                label="SGDRegressor")
+        pl.plot(list_n_samples, np.sqrt(ridge_results[:, j, 1]),
+                label="Ridge")
+        pl.legend(prop={"size": 10})
+        pl.xlabel("n_train")
+        pl.ylabel("Time [sec]")
+        pl.title("Training time - %d features" % list_n_features[j])
+        i += 1
+
+    pl.subplots_adjust(hspace=.30)
+
+    pl.show()
diff --git a/doc/modules/sgd.rst b/doc/modules/sgd.rst
index df654d70995d206ab949679e63edb2475a36fb0a..33bee892f477cd152169875516396fe2bb683009 100644
--- a/doc/modules/sgd.rst
+++ b/doc/modules/sgd.rst
@@ -20,7 +20,7 @@ SGD has been successfully applied to large-scale and sparse machine
 learning problems often encountered in text classification and natural
 language processing.  Given that the data is sparse, the classifiers
 in this module easily scale to problems with more than 10^5 training
-examples and more than 10^4 features.
+examples and more than 10^5 features.
 
 The advantages of Stochastic Gradient Descent are:
 
@@ -30,7 +30,7 @@ The advantages of Stochastic Gradient Descent are:
 
 The disadvantages of Stochastic Gradient Descent include:
 
-    - SGD requires a number of hyperparameters including the regularization
+    - SGD requires a number of hyperparameters such as the regularization
       parameter and the number of iterations.
 
     - SGD is sensitive to feature scaling.
@@ -60,7 +60,8 @@ for the training samples::
     >>> clf = SGDClassifier(loss="hinge", penalty="l2")
     >>> clf.fit(X, y)
     SGDClassifier(loss='hinge', n_jobs=1, shuffle=False, verbose=0, n_iter=5,
-           fit_intercept=True, penalty='l2', seed=0, rho=1.0, alpha=0.0001)
+           learning_rate='optimal', fit_intercept=True, penalty='l2',
+           power_t=0.5, seed=0, eta0=0.0, rho=1.0, alpha=0.0001)
 
 After being fitted, the model can then be used to predict new values::
 
@@ -249,6 +250,11 @@ Tips on Practical Use
     for the number of iterations is `n_iter = np.ceil(10**6 / n)`,
     where `n` is the size of the training set.
 
+  * If you apply SGD to features extracted using PCA we found that
+    it is often wise to scale the feature values by some constant `c`
+    such that the average L2 norm of the training data equals one.
+    
+
 .. topic:: References:
 
  * `"Efficient BackProp" <yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf>`_
@@ -324,6 +330,29 @@ where :math:`\eta` is the learning rate which controls the step-size in
 the parameter space.  The intercept :math:`b` is updated similarly but
 without regularization.
 
+The learning rate :math:`\eta` can be either constant or gradually decaying. For
+classification, the default learning rate schedule (`learning_rate='optimal'`) 
+is given by
+
+.. math::
+
+    \eta^{(t)} = \frac {1.0}{t+t0}
+
+where :math:`t0` is the time step (there are a total of `n_samples*epochs` 
+time steps), :math:`t0` is choosen automatically assuming that the norm of
+the training samples is approx. 1. 
+For regression, the default learning rate schedule, inverse scaling 
+(`learning_rate='invscaling'`), is given by
+
+.. math::
+
+    \eta^{(t)} = \frac{eta_0}{t^{power\_t}}
+
+where :math:`eta_0` and :math:`power\_t` are hyperparameters choosen by the
+user.
+For a constant learning rate use `learning_rate='constant'` and use `eta0`
+to specify the learning rate. 
+
 The model parameters can be accessed through the members coef\_ and
 intercept\_:
 
diff --git a/scikits/learn/linear_model/base.py b/scikits/learn/linear_model/base.py
index ab41efccde23fe9cc0e4d62abbe9b59d90b403a0..ab9192620d89c076e7e21ceb463724b5620cac90 100644
--- a/scikits/learn/linear_model/base.py
+++ b/scikits/learn/linear_model/base.py
@@ -53,7 +53,7 @@ class LinearModel(BaseEstimator, RegressorMixin):
         because nearly all Linear Models will want it's data to be
         centered.
         """
-        import scipy.sparse # importing scipy.sparse just for this is overkill
+        import scipy.sparse  # importing scipy.sparse just for this is overkill
         if fit_intercept:
             if scipy.sparse.issparse(X):
                 Xmean = np.zeros(X.shape[1])
@@ -132,8 +132,6 @@ class LinearRegression(LinearModel):
 ##
 ## Stochastic Gradient Descent (SGD) abstract base classes
 ##
-## TODO add sample_weights to signature (see LibSVM)
-## TODO adher to svm signature (return values of score etc.)
 
 
 class BaseSGD(BaseEstimator):
@@ -141,7 +139,8 @@ class BaseSGD(BaseEstimator):
 
     def __init__(self, loss, penalty='l2', alpha=0.0001,
                  rho=0.85, fit_intercept=True, n_iter=5, shuffle=False,
-                 verbose=0, seed=0):
+                 verbose=0, seed=0, learning_rate="optimal", eta0=0.0,
+                 power_t=0.5):
         self.loss = str(loss)
         self.penalty = str(penalty)
         self.alpha = float(alpha)
@@ -158,6 +157,22 @@ class BaseSGD(BaseEstimator):
         self._set_loss_function(self.loss)
         self._set_penalty_type(self.penalty)
 
+        self.learning_rate = str(learning_rate)
+        self._set_learning_rate(self.learning_rate)
+        self.eta0 = float(eta0)
+        self.power_t = float(power_t)
+        if self.learning_rate != "optimal":
+            if eta0 <= 0.0:
+                raise ValueError("eta0 must be greater than 0.0")
+
+    def _set_learning_rate(self, learning_rate):
+        learning_rate_codes = {"constant": 1, "optimal": 2, "invscaling": 3}
+        try:
+            self.learning_rate_code = learning_rate_codes[learning_rate]
+        except KeyError:
+            raise ValueError("learning rate %s"
+            "is not supported. " % learning_rate)
+
     def _set_loss_function(self, loss):
         """Get concrete LossFunction"""
         raise NotImplementedError("BaseSGD is an abstract class.")
@@ -171,7 +186,7 @@ class BaseSGD(BaseEstimator):
             elif self.penalty_type == 1:
                 self.rho = 0.0
         except KeyError:
-            raise ValueError("Penalty %s is not supported. " % self.penalty)
+            raise ValueError("Penalty %s is not supported. " % penalty)
 
     def _set_sample_weight(self, sample_weight, n_samples):
         """Set the sample weight array."""
@@ -239,13 +254,15 @@ class BaseSGDClassifier(BaseSGD, ClassifierMixin):
 
     def __init__(self, loss="hinge", penalty='l2', alpha=0.0001,
                  rho=0.85, fit_intercept=True, n_iter=5, shuffle=False,
-                 verbose=0, n_jobs=1, seed=0):
+                 verbose=0, n_jobs=1, seed=0, learning_rate="optimal",
+                 eta0=0.0, power_t=0.5):
         super(BaseSGDClassifier, self).__init__(loss=loss, penalty=penalty,
                                                 alpha=alpha, rho=rho,
                                                 fit_intercept=fit_intercept,
                                                 n_iter=n_iter, shuffle=shuffle,
-                                                verbose=verbose,
-                                                seed=seed)
+                                                verbose=verbose, seed=seed,
+                                                learning_rate=learning_rate,
+                                                eta0=eta0, power_t=power_t)
         self.n_jobs = int(n_jobs)
 
     def _set_loss_function(self, loss):
@@ -404,13 +421,16 @@ class BaseSGDRegressor(BaseSGD, RegressorMixin):
     """
     def __init__(self, loss="squared_loss", penalty="l2", alpha=0.0001,
                  rho=0.85, fit_intercept=True, n_iter=5, shuffle=False,
-                 verbose=0, p=0.1, seed=0):
+                 verbose=0, p=0.1, seed=0, learning_rate="invscaling",
+                 eta0=0.01, power_t=0.25):
         self.p = float(p)
         super(BaseSGDRegressor, self).__init__(loss=loss, penalty=penalty,
                                                alpha=alpha, rho=rho,
                                                fit_intercept=fit_intercept,
                                                n_iter=n_iter, shuffle=shuffle,
-                                               verbose=verbose, seed=seed)
+                                               verbose=verbose, seed=seed,
+                                               learning_rate=learning_rate,
+                                               eta0=eta0, power_t=power_t)
 
     def _set_loss_function(self, loss):
         """Get concrete LossFunction"""
diff --git a/scikits/learn/linear_model/sgd_fast.c b/scikits/learn/linear_model/sgd_fast.c
index 6063b6b4e60ba394fd2448d58eeb4e129850a1fc..39a2aabf02dd6a7e94a78e3950f456bec92968f8 100644
--- a/scikits/learn/linear_model/sgd_fast.c
+++ b/scikits/learn/linear_model/sgd_fast.c
@@ -1,4 +1,4 @@
-/* Generated by Cython 0.14.1 on Wed Apr  6 09:47:42 2011 */
+/* Generated by Cython 0.14.1 on Wed May  4 20:08:16 2011 */
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
@@ -402,7 +402,7 @@ typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
 
 typedef npy_cdouble __pyx_t_5numpy_complex_t;
 
-/* "scikits/learn/linear_model/sgd_fast.pxd":19
+/* "scikits/learn/linear_model/sgd_fast.pxd":20
  * # -----------------------------------------
  * 
  * cdef class LossFunction:             # <<<<<<<<<<<<<<
@@ -415,7 +415,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction {
   struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *__pyx_vtab;
 };
 
-/* "scikits/learn/linear_model/sgd_fast.pxd":23
+/* "scikits/learn/linear_model/sgd_fast.pxd":24
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Regression(LossFunction):             # <<<<<<<<<<<<<<
@@ -427,7 +427,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Regression {
   struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction __pyx_base;
 };
 
-/* "scikits/learn/linear_model/sgd_fast.pxd":43
+/* "scikits/learn/linear_model/sgd_fast.pxd":44
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class SquaredLoss(Regression):             # <<<<<<<<<<<<<<
@@ -439,7 +439,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss {
   struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Regression __pyx_base;
 };
 
-/* "scikits/learn/linear_model/sgd_fast.pxd":27
+/* "scikits/learn/linear_model/sgd_fast.pxd":28
  *     cpdef double dloss(self,double p, double y)
  * 
  * cdef class Classification(LossFunction):             # <<<<<<<<<<<<<<
@@ -451,7 +451,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification {
   struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction __pyx_base;
 };
 
-/* "scikits/learn/linear_model/sgd_fast.pxd":35
+/* "scikits/learn/linear_model/sgd_fast.pxd":36
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Hinge(Classification):             # <<<<<<<<<<<<<<
@@ -463,7 +463,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Hinge {
   struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification __pyx_base;
 };
 
-/* "scikits/learn/linear_model/sgd_fast.pxd":47
+/* "scikits/learn/linear_model/sgd_fast.pxd":48
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Huber(Regression):             # <<<<<<<<<<<<<<
@@ -476,7 +476,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber {
   double c;
 };
 
-/* "scikits/learn/linear_model/sgd_fast.pxd":31
+/* "scikits/learn/linear_model/sgd_fast.pxd":32
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class ModifiedHuber(Classification):             # <<<<<<<<<<<<<<
@@ -488,7 +488,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber {
   struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification __pyx_base;
 };
 
-/* "scikits/learn/linear_model/sgd_fast.pxd":39
+/* "scikits/learn/linear_model/sgd_fast.pxd":40
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Log(Classification):             # <<<<<<<<<<<<<<
@@ -501,7 +501,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Log {
 };
 
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":25
+/* "scikits/learn/linear_model/sgd_fast.pyx":31
  * # ----------------------------------------
  * 
  * cdef class LossFunction:             # <<<<<<<<<<<<<<
@@ -516,7 +516,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction;
 
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":49
+/* "scikits/learn/linear_model/sgd_fast.pyx":55
  * 
  * 
  * cdef class Regression(LossFunction):             # <<<<<<<<<<<<<<
@@ -530,7 +530,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Regression {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Regression *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression;
 
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":154
+/* "scikits/learn/linear_model/sgd_fast.pyx":160
  * 
  * 
  * cdef class Huber(Regression):             # <<<<<<<<<<<<<<
@@ -544,7 +544,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Huber {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Huber *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Huber;
 
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":59
+/* "scikits/learn/linear_model/sgd_fast.pyx":65
  * 
  * 
  * cdef class Classification(LossFunction):             # <<<<<<<<<<<<<<
@@ -558,7 +558,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Classification
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Classification *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification;
 
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":99
+/* "scikits/learn/linear_model/sgd_fast.pyx":105
  * 
  * 
  * cdef class Hinge(Classification):             # <<<<<<<<<<<<<<
@@ -572,7 +572,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Hinge {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Hinge *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Hinge;
 
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":117
+/* "scikits/learn/linear_model/sgd_fast.pyx":123
  * 
  * 
  * cdef class Log(Classification):             # <<<<<<<<<<<<<<
@@ -586,7 +586,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Log {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Log *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Log;
 
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":69
+/* "scikits/learn/linear_model/sgd_fast.pyx":75
  * 
  * 
  * cdef class ModifiedHuber(Classification):             # <<<<<<<<<<<<<<
@@ -600,7 +600,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber;
 
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":142
+/* "scikits/learn/linear_model/sgd_fast.pyx":148
  * 
  * 
  * cdef class SquaredLoss(Regression):             # <<<<<<<<<<<<<<
@@ -995,6 +995,7 @@ static double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_dot(double *, dou
 static double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(double *, double, double *, int, unsigned int, double); /*proto*/
 static void __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_l1penalty(double *, double, double *, unsigned int, double); /*proto*/
 static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t = { "float64_t", NULL, sizeof(__pyx_t_5numpy_float64_t), 'R' };
+static __Pyx_TypeInfo __Pyx_TypeInfo_double = { "double", NULL, sizeof(double), 'R' };
 static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t = { "int32_t", NULL, sizeof(__pyx_t_5numpy_int32_t), 'I' };
 #define __Pyx_MODULE_NAME "scikits.learn.linear_model.sgd_fast"
 static int __pyx_module_is_main_scikits__learn__linear_model__sgd_fast = 0;
@@ -1047,6 +1048,7 @@ static char __pyx_k__rho[] = "rho";
 static char __pyx_k__sys[] = "sys";
 static char __pyx_k__base[] = "base";
 static char __pyx_k__data[] = "data";
+static char __pyx_k__eta0[] = "eta0";
 static char __pyx_k__loss[] = "loss";
 static char __pyx_k__ndim[] = "ndim";
 static char __pyx_k__seed[] = "seed";
@@ -1071,6 +1073,7 @@ static char __pyx_k__n_iter[] = "n_iter";
 static char __pyx_k__random[] = "random";
 static char __pyx_k__float64[] = "float64";
 static char __pyx_k__nonzero[] = "nonzero";
+static char __pyx_k__power_t[] = "power_t";
 static char __pyx_k__shuffle[] = "shuffle";
 static char __pyx_k__strides[] = "strides";
 static char __pyx_k__verbose[] = "verbose";
@@ -1090,6 +1093,7 @@ static char __pyx_k__RandomState[] = "RandomState";
 static char __pyx_k__RuntimeError[] = "RuntimeError";
 static char __pyx_k__penalty_type[] = "penalty_type";
 static char __pyx_k__fit_intercept[] = "fit_intercept";
+static char __pyx_k__learning_rate[] = "learning_rate";
 static char __pyx_k__sample_weight[] = "sample_weight";
 static char __pyx_k__NotImplementedError[] = "NotImplementedError";
 static PyObject *__pyx_kp_s_1;
@@ -1123,6 +1127,7 @@ static PyObject *__pyx_n_s__descr;
 static PyObject *__pyx_n_s__dloss;
 static PyObject *__pyx_n_s__dot;
 static PyObject *__pyx_n_s__dtype;
+static PyObject *__pyx_n_s__eta0;
 static PyObject *__pyx_n_s__fields;
 static PyObject *__pyx_n_s__fit_intercept;
 static PyObject *__pyx_n_s__float64;
@@ -1132,6 +1137,7 @@ static PyObject *__pyx_n_s__intercept;
 static PyObject *__pyx_n_s__isinf;
 static PyObject *__pyx_n_s__isnan;
 static PyObject *__pyx_n_s__itemsize;
+static PyObject *__pyx_n_s__learning_rate;
 static PyObject *__pyx_n_s__loss;
 static PyObject *__pyx_n_s__n_iter;
 static PyObject *__pyx_n_s__names;
@@ -1144,6 +1150,7 @@ static PyObject *__pyx_n_s__order;
 static PyObject *__pyx_n_s__p;
 static PyObject *__pyx_n_s__penalty_type;
 static PyObject *__pyx_n_s__plain_sgd;
+static PyObject *__pyx_n_s__power_t;
 static PyObject *__pyx_n_s__random;
 static PyObject *__pyx_n_s__range;
 static PyObject *__pyx_n_s__readonly;
@@ -1172,7 +1179,7 @@ static PyObject *__pyx_k_tuple_14;
 static PyObject *__pyx_k_tuple_15;
 static PyObject *__pyx_k_tuple_17;
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":28
+/* "scikits/learn/linear_model/sgd_fast.pyx":34
  *     """Base class for convex loss functions"""
  * 
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -1193,14 +1200,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_l
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_loss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -1208,10 +1215,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_l
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -1220,18 +1227,18 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_l
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":36
+  /* "scikits/learn/linear_model/sgd_fast.pyx":42
  *         :type y: double
  *         :returns: double"""
  *         raise NotImplementedError()             # <<<<<<<<<<<<<<
  * 
  *     cpdef double dloss(self, double p, double y):
  */
-  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -1247,7 +1254,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_l
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":28
+/* "scikits/learn/linear_model/sgd_fast.pyx":34
  *     """Base class for convex loss functions"""
  * 
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -1282,30 +1289,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_12LossFunctio
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.LossFunction.loss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self)->__pyx_vtab)->loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self)->__pyx_vtab)->loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -1323,7 +1330,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_12LossFunctio
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":38
+/* "scikits/learn/linear_model/sgd_fast.pyx":44
  *         raise NotImplementedError()
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -1344,14 +1351,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_d
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_1dloss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -1359,10 +1366,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_d
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -1371,18 +1378,18 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_d
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":46
+  /* "scikits/learn/linear_model/sgd_fast.pyx":52
  *         :type y: double
  *         :returns: double"""
  *         raise NotImplementedError()             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -1398,7 +1405,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_d
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":38
+/* "scikits/learn/linear_model/sgd_fast.pyx":44
  *         raise NotImplementedError()
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -1433,30 +1440,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_12LossFunctio
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.LossFunction.dloss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self)->__pyx_vtab)->dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self)->__pyx_vtab)->dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -1474,10 +1481,10 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_12LossFunctio
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":52
+/* "scikits/learn/linear_model/sgd_fast.pyx":58
  *     """Base class for loss functions for regression"""
  * 
- *     cpdef double loss(self,double p, double y):             # <<<<<<<<<<<<<<
+ *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
  *         raise NotImplementedError()
  * 
  */
@@ -1495,14 +1502,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_10Regression_los
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_10Regression_loss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -1510,10 +1517,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_10Regression_los
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -1522,18 +1529,18 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_10Regression_los
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":53
+  /* "scikits/learn/linear_model/sgd_fast.pyx":59
  * 
- *     cpdef double loss(self,double p, double y):
+ *     cpdef double loss(self, double p, double y):
  *         raise NotImplementedError()             # <<<<<<<<<<<<<<
  * 
- *     cpdef double dloss(self,double p, double y):
+ *     cpdef double dloss(self, double p, double y):
  */
-  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -1549,10 +1556,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_10Regression_los
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":52
+/* "scikits/learn/linear_model/sgd_fast.pyx":58
  *     """Base class for loss functions for regression"""
  * 
- *     cpdef double loss(self,double p, double y):             # <<<<<<<<<<<<<<
+ *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
  *         raise NotImplementedError()
  * 
  */
@@ -1583,30 +1590,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_10Regression_
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Regression.loss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Regression *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Regression *)__pyx_v_self)->__pyx_base.__pyx_vtab)->__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Regression *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Regression *)__pyx_v_self)->__pyx_base.__pyx_vtab)->__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -1624,10 +1631,10 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_10Regression_
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":55
+/* "scikits/learn/linear_model/sgd_fast.pyx":61
  *         raise NotImplementedError()
  * 
- *     cpdef double dloss(self,double p, double y):             # <<<<<<<<<<<<<<
+ *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
  *         raise NotImplementedError()
  * 
  */
@@ -1645,14 +1652,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_10Regression_dlo
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_10Regression_1dloss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -1660,10 +1667,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_10Regression_dlo
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -1672,18 +1679,18 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_10Regression_dlo
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":56
+  /* "scikits/learn/linear_model/sgd_fast.pyx":62
  * 
- *     cpdef double dloss(self,double p, double y):
+ *     cpdef double dloss(self, double p, double y):
  *         raise NotImplementedError()             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -1699,10 +1706,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_10Regression_dlo
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":55
+/* "scikits/learn/linear_model/sgd_fast.pyx":61
  *         raise NotImplementedError()
  * 
- *     cpdef double dloss(self,double p, double y):             # <<<<<<<<<<<<<<
+ *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
  *         raise NotImplementedError()
  * 
  */
@@ -1733,30 +1740,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_10Regression_
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Regression.dloss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Regression *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Regression *)__pyx_v_self)->__pyx_base.__pyx_vtab)->__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Regression *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Regression *)__pyx_v_self)->__pyx_base.__pyx_vtab)->__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -1774,7 +1781,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_10Regression_
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":62
+/* "scikits/learn/linear_model/sgd_fast.pyx":68
  *     """Base class for loss functions for classification"""
  * 
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -1795,14 +1802,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_14Classification
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_14Classification_loss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -1810,10 +1817,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_14Classification
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -1822,18 +1829,18 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_14Classification
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":63
+  /* "scikits/learn/linear_model/sgd_fast.pyx":69
  * 
  *     cpdef double loss(self, double p, double y):
  *         raise NotImplementedError()             # <<<<<<<<<<<<<<
  * 
  *     cpdef double dloss(self, double p, double y):
  */
-  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -1849,7 +1856,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_14Classification
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":62
+/* "scikits/learn/linear_model/sgd_fast.pyx":68
  *     """Base class for loss functions for classification"""
  * 
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -1883,30 +1890,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_14Classificat
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Classification.loss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Classification *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification *)__pyx_v_self)->__pyx_base.__pyx_vtab)->__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Classification *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification *)__pyx_v_self)->__pyx_base.__pyx_vtab)->__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -1924,7 +1931,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_14Classificat
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":65
+/* "scikits/learn/linear_model/sgd_fast.pyx":71
  *         raise NotImplementedError()
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -1945,14 +1952,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_14Classification
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_14Classification_1dloss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -1960,10 +1967,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_14Classification
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -1972,18 +1979,18 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_14Classification
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":66
+  /* "scikits/learn/linear_model/sgd_fast.pyx":72
  * 
  *     cpdef double dloss(self, double p, double y):
  *         raise NotImplementedError()             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_builtin_NotImplementedError, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   __pyx_r = 0;
   goto __pyx_L0;
@@ -1999,7 +2006,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_14Classification
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":65
+/* "scikits/learn/linear_model/sgd_fast.pyx":71
  *         raise NotImplementedError()
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -2033,30 +2040,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_14Classificat
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Classification.dloss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Classification *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification *)__pyx_v_self)->__pyx_base.__pyx_vtab)->__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Classification *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification *)__pyx_v_self)->__pyx_base.__pyx_vtab)->__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -2074,7 +2081,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_14Classificat
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":77
+/* "scikits/learn/linear_model/sgd_fast.pyx":83
  *     Stochastic Gradient Descent', ICML'04.
  *     """
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -2097,14 +2104,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_loss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -2112,10 +2119,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -2124,7 +2131,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":78
+  /* "scikits/learn/linear_model/sgd_fast.pyx":84
  *     """
  *     cpdef double loss(self, double p, double y):
  *         cdef double z = p * y             # <<<<<<<<<<<<<<
@@ -2133,7 +2140,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
  */
   __pyx_v_z = (__pyx_v_p * __pyx_v_y);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":79
+  /* "scikits/learn/linear_model/sgd_fast.pyx":85
  *     cpdef double loss(self, double p, double y):
  *         cdef double z = p * y
  *         if z >= 1.0:             # <<<<<<<<<<<<<<
@@ -2143,7 +2150,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
   __pyx_t_6 = (__pyx_v_z >= 1.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":80
+    /* "scikits/learn/linear_model/sgd_fast.pyx":86
  *         cdef double z = p * y
  *         if z >= 1.0:
  *             return 0.0             # <<<<<<<<<<<<<<
@@ -2155,7 +2162,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
     goto __pyx_L3;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":81
+  /* "scikits/learn/linear_model/sgd_fast.pyx":87
  *         if z >= 1.0:
  *             return 0.0
  *         elif z >= -1.0:             # <<<<<<<<<<<<<<
@@ -2165,7 +2172,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
   __pyx_t_6 = (__pyx_v_z >= -1.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":82
+    /* "scikits/learn/linear_model/sgd_fast.pyx":88
  *             return 0.0
  *         elif z >= -1.0:
  *             return (1.0 - z) * (1.0 - z)             # <<<<<<<<<<<<<<
@@ -2178,7 +2185,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
   }
   /*else*/ {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":84
+    /* "scikits/learn/linear_model/sgd_fast.pyx":90
  *             return (1.0 - z) * (1.0 - z)
  *         else:
  *             return -4.0 * z             # <<<<<<<<<<<<<<
@@ -2204,7 +2211,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":77
+/* "scikits/learn/linear_model/sgd_fast.pyx":83
  *     Stochastic Gradient Descent', ICML'04.
  *     """
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -2238,30 +2245,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHub
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.ModifiedHuber.loss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -2279,7 +2286,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHub
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":86
+/* "scikits/learn/linear_model/sgd_fast.pyx":92
  *             return -4.0 * z
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -2302,14 +2309,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_1dloss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -2317,10 +2324,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -2329,7 +2336,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":87
+  /* "scikits/learn/linear_model/sgd_fast.pyx":93
  * 
  *     cpdef double dloss(self, double p, double y):
  *         cdef double z = p * y             # <<<<<<<<<<<<<<
@@ -2338,7 +2345,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
  */
   __pyx_v_z = (__pyx_v_p * __pyx_v_y);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":88
+  /* "scikits/learn/linear_model/sgd_fast.pyx":94
  *     cpdef double dloss(self, double p, double y):
  *         cdef double z = p * y
  *         if z >= 1.0:             # <<<<<<<<<<<<<<
@@ -2348,7 +2355,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
   __pyx_t_6 = (__pyx_v_z >= 1.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":89
+    /* "scikits/learn/linear_model/sgd_fast.pyx":95
  *         cdef double z = p * y
  *         if z >= 1.0:
  *             return 0.0             # <<<<<<<<<<<<<<
@@ -2360,7 +2367,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
     goto __pyx_L3;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":90
+  /* "scikits/learn/linear_model/sgd_fast.pyx":96
  *         if z >= 1.0:
  *             return 0.0
  *         elif z >= -1.0:             # <<<<<<<<<<<<<<
@@ -2370,7 +2377,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
   __pyx_t_6 = (__pyx_v_z >= -1.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":91
+    /* "scikits/learn/linear_model/sgd_fast.pyx":97
  *             return 0.0
  *         elif z >= -1.0:
  *             return 2.0 * (1.0 - z) * y             # <<<<<<<<<<<<<<
@@ -2383,7 +2390,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
   }
   /*else*/ {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":93
+    /* "scikits/learn/linear_model/sgd_fast.pyx":99
  *             return 2.0 * (1.0 - z) * y
  *         else:
  *             return 4.0 * y             # <<<<<<<<<<<<<<
@@ -2409,7 +2416,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":86
+/* "scikits/learn/linear_model/sgd_fast.pyx":92
  *             return -4.0 * z
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -2443,30 +2450,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHub
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.ModifiedHuber.dloss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -2484,7 +2491,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHub
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":95
+/* "scikits/learn/linear_model/sgd_fast.pyx":101
  *             return 4.0 * y
  * 
  *     def __reduce__(self):             # <<<<<<<<<<<<<<
@@ -2498,7 +2505,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHub
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__reduce__");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":96
+  /* "scikits/learn/linear_model/sgd_fast.pyx":102
  * 
  *     def __reduce__(self):
  *         return ModifiedHuber, ()             # <<<<<<<<<<<<<<
@@ -2506,7 +2513,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHub
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __Pyx_INCREF(((PyObject *)((PyObject*)__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber)));
   PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)((PyObject*)__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber)));
@@ -2530,7 +2537,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHub
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":101
+/* "scikits/learn/linear_model/sgd_fast.pyx":107
  * cdef class Hinge(Classification):
  *     """SVM loss for binary classification tasks with y in {-1,1}"""
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -2553,14 +2560,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss(stru
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -2568,10 +2575,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss(stru
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -2580,7 +2587,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss(stru
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":102
+  /* "scikits/learn/linear_model/sgd_fast.pyx":108
  *     """SVM loss for binary classification tasks with y in {-1,1}"""
  *     cpdef double loss(self, double p, double y):
  *         cdef double z = p * y             # <<<<<<<<<<<<<<
@@ -2589,7 +2596,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss(stru
  */
   __pyx_v_z = (__pyx_v_p * __pyx_v_y);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":103
+  /* "scikits/learn/linear_model/sgd_fast.pyx":109
  *     cpdef double loss(self, double p, double y):
  *         cdef double z = p * y
  *         if z < 1.0:             # <<<<<<<<<<<<<<
@@ -2599,7 +2606,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss(stru
   __pyx_t_6 = (__pyx_v_z < 1.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":104
+    /* "scikits/learn/linear_model/sgd_fast.pyx":110
  *         cdef double z = p * y
  *         if z < 1.0:
  *             return (1 - z)             # <<<<<<<<<<<<<<
@@ -2612,7 +2619,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss(stru
   }
   __pyx_L3:;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":105
+  /* "scikits/learn/linear_model/sgd_fast.pyx":111
  *         if z < 1.0:
  *             return (1 - z)
  *         return 0.0             # <<<<<<<<<<<<<<
@@ -2636,7 +2643,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss(stru
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":101
+/* "scikits/learn/linear_model/sgd_fast.pyx":107
  * cdef class Hinge(Classification):
  *     """SVM loss for binary classification tasks with y in {-1,1}"""
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -2670,30 +2677,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss(P
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Hinge.loss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Hinge *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Hinge *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Hinge *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Hinge *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -2711,7 +2718,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss(P
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":107
+/* "scikits/learn/linear_model/sgd_fast.pyx":113
  *         return 0.0
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -2734,14 +2741,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_dloss(str
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_1dloss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -2749,10 +2756,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_dloss(str
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -2761,7 +2768,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_dloss(str
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":108
+  /* "scikits/learn/linear_model/sgd_fast.pyx":114
  * 
  *     cpdef double dloss(self, double p, double y):
  *         cdef double z = p * y             # <<<<<<<<<<<<<<
@@ -2770,7 +2777,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_dloss(str
  */
   __pyx_v_z = (__pyx_v_p * __pyx_v_y);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":109
+  /* "scikits/learn/linear_model/sgd_fast.pyx":115
  *     cpdef double dloss(self, double p, double y):
  *         cdef double z = p * y
  *         if z < 1.0:             # <<<<<<<<<<<<<<
@@ -2780,7 +2787,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_dloss(str
   __pyx_t_6 = (__pyx_v_z < 1.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":110
+    /* "scikits/learn/linear_model/sgd_fast.pyx":116
  *         cdef double z = p * y
  *         if z < 1.0:
  *             return y             # <<<<<<<<<<<<<<
@@ -2793,7 +2800,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_dloss(str
   }
   __pyx_L3:;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":111
+  /* "scikits/learn/linear_model/sgd_fast.pyx":117
  *         if z < 1.0:
  *             return y
  *         return 0.0             # <<<<<<<<<<<<<<
@@ -2817,7 +2824,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_dloss(str
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":107
+/* "scikits/learn/linear_model/sgd_fast.pyx":113
  *         return 0.0
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -2851,30 +2858,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_1dloss
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Hinge.dloss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Hinge *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Hinge *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Hinge *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Hinge *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -2892,7 +2899,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_1dloss
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":113
+/* "scikits/learn/linear_model/sgd_fast.pyx":119
  *         return 0.0
  * 
  *     def __reduce__(self):             # <<<<<<<<<<<<<<
@@ -2906,7 +2913,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_2__red
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__reduce__");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":114
+  /* "scikits/learn/linear_model/sgd_fast.pyx":120
  * 
  *     def __reduce__(self):
  *         return Hinge, ()             # <<<<<<<<<<<<<<
@@ -2914,7 +2921,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_2__red
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __Pyx_INCREF(((PyObject *)((PyObject*)__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Hinge)));
   PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)((PyObject*)__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Hinge)));
@@ -2938,7 +2945,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_2__red
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":120
+/* "scikits/learn/linear_model/sgd_fast.pyx":126
  *     """Logistic regression loss for binary classification with y in {-1, 1}"""
  * 
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -2961,14 +2968,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(struct
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -2976,10 +2983,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(struct
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -2988,7 +2995,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(struct
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":121
+  /* "scikits/learn/linear_model/sgd_fast.pyx":127
  * 
  *     cpdef double loss(self, double p, double y):
  *         cdef double z = p * y             # <<<<<<<<<<<<<<
@@ -2997,7 +3004,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(struct
  */
   __pyx_v_z = (__pyx_v_p * __pyx_v_y);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":123
+  /* "scikits/learn/linear_model/sgd_fast.pyx":129
  *         cdef double z = p * y
  *         # approximately equal and saves the computation of the log
  *         if z > 18:             # <<<<<<<<<<<<<<
@@ -3007,7 +3014,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(struct
   __pyx_t_6 = (__pyx_v_z > 18.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":124
+    /* "scikits/learn/linear_model/sgd_fast.pyx":130
  *         # approximately equal and saves the computation of the log
  *         if z > 18:
  *             return exp(-z)             # <<<<<<<<<<<<<<
@@ -3020,7 +3027,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(struct
   }
   __pyx_L3:;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":125
+  /* "scikits/learn/linear_model/sgd_fast.pyx":131
  *         if z > 18:
  *             return exp(-z)
  *         if z < -18:             # <<<<<<<<<<<<<<
@@ -3030,7 +3037,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(struct
   __pyx_t_6 = (__pyx_v_z < -18.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":126
+    /* "scikits/learn/linear_model/sgd_fast.pyx":132
  *             return exp(-z)
  *         if z < -18:
  *             return -z * y             # <<<<<<<<<<<<<<
@@ -3043,7 +3050,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(struct
   }
   __pyx_L4:;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":127
+  /* "scikits/learn/linear_model/sgd_fast.pyx":133
  *         if z < -18:
  *             return -z * y
  *         return log(1.0 + exp(-z))             # <<<<<<<<<<<<<<
@@ -3067,7 +3074,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(struct
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":120
+/* "scikits/learn/linear_model/sgd_fast.pyx":126
  *     """Logistic regression loss for binary classification with y in {-1, 1}"""
  * 
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -3101,30 +3108,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(PyO
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Log.loss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Log *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Log *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Log *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Log *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -3142,7 +3149,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss(PyO
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":129
+/* "scikits/learn/linear_model/sgd_fast.pyx":135
  *         return log(1.0 + exp(-z))
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -3165,14 +3172,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_dloss(struc
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_3Log_1dloss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -3180,10 +3187,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_dloss(struc
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -3192,7 +3199,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_dloss(struc
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":130
+  /* "scikits/learn/linear_model/sgd_fast.pyx":136
  * 
  *     cpdef double dloss(self, double p, double y):
  *         cdef double z = p * y             # <<<<<<<<<<<<<<
@@ -3201,7 +3208,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_dloss(struc
  */
   __pyx_v_z = (__pyx_v_p * __pyx_v_y);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":132
+  /* "scikits/learn/linear_model/sgd_fast.pyx":138
  *         cdef double z = p * y
  *         # approximately equal and saves the computation of the log
  *         if z > 18.0:             # <<<<<<<<<<<<<<
@@ -3211,7 +3218,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_dloss(struc
   __pyx_t_6 = (__pyx_v_z > 18.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":133
+    /* "scikits/learn/linear_model/sgd_fast.pyx":139
  *         # approximately equal and saves the computation of the log
  *         if z > 18.0:
  *             return exp(-z) * y             # <<<<<<<<<<<<<<
@@ -3224,7 +3231,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_dloss(struc
   }
   __pyx_L3:;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":134
+  /* "scikits/learn/linear_model/sgd_fast.pyx":140
  *         if z > 18.0:
  *             return exp(-z) * y
  *         if z < -18.0:             # <<<<<<<<<<<<<<
@@ -3234,7 +3241,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_dloss(struc
   __pyx_t_6 = (__pyx_v_z < -18.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":135
+    /* "scikits/learn/linear_model/sgd_fast.pyx":141
  *             return exp(-z) * y
  *         if z < -18.0:
  *             return y             # <<<<<<<<<<<<<<
@@ -3247,7 +3254,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_dloss(struc
   }
   __pyx_L4:;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":136
+  /* "scikits/learn/linear_model/sgd_fast.pyx":142
  *         if z < -18.0:
  *             return y
  *         return y / (exp(z) + 1.0)             # <<<<<<<<<<<<<<
@@ -3271,7 +3278,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_dloss(struc
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":129
+/* "scikits/learn/linear_model/sgd_fast.pyx":135
  *         return log(1.0 + exp(-z))
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -3305,30 +3312,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_3Log_1dloss(P
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Log.dloss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Log *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Log *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Log *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Log *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -3346,7 +3353,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_3Log_1dloss(P
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":138
+/* "scikits/learn/linear_model/sgd_fast.pyx":144
  *         return y / (exp(z) + 1.0)
  * 
  *     def __reduce__(self):             # <<<<<<<<<<<<<<
@@ -3360,7 +3367,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_3Log_2__reduc
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__reduce__");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":139
+  /* "scikits/learn/linear_model/sgd_fast.pyx":145
  * 
  *     def __reduce__(self):
  *         return Log, ()             # <<<<<<<<<<<<<<
@@ -3368,7 +3375,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_3Log_2__reduc
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __Pyx_INCREF(((PyObject *)((PyObject*)__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Log)));
   PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)((PyObject*)__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Log)));
@@ -3392,7 +3399,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_3Log_2__reduc
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":144
+/* "scikits/learn/linear_model/sgd_fast.pyx":150
  * cdef class SquaredLoss(Regression):
  *     """Squared loss traditional used in linear regression."""
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -3413,14 +3420,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_lo
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_loss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -3428,10 +3435,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_lo
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -3440,7 +3447,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_lo
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":145
+  /* "scikits/learn/linear_model/sgd_fast.pyx":151
  *     """Squared loss traditional used in linear regression."""
  *     cpdef double loss(self, double p, double y):
  *         return 0.5 * (p - y) * (p - y)             # <<<<<<<<<<<<<<
@@ -3464,7 +3471,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_lo
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":144
+/* "scikits/learn/linear_model/sgd_fast.pyx":150
  * cdef class SquaredLoss(Regression):
  *     """Squared loss traditional used in linear regression."""
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -3498,30 +3505,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.SquaredLoss.loss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -3539,7 +3546,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":147
+/* "scikits/learn/linear_model/sgd_fast.pyx":153
  *         return 0.5 * (p - y) * (p - y)
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -3560,14 +3567,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_dl
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_1dloss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -3575,10 +3582,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_dl
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -3587,7 +3594,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_dl
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":148
+  /* "scikits/learn/linear_model/sgd_fast.pyx":154
  * 
  *     cpdef double dloss(self, double p, double y):
  *         return y - p             # <<<<<<<<<<<<<<
@@ -3611,7 +3618,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_dl
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":147
+/* "scikits/learn/linear_model/sgd_fast.pyx":153
  *         return 0.5 * (p - y) * (p - y)
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -3645,30 +3652,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.SquaredLoss.dloss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -3686,7 +3693,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":150
+/* "scikits/learn/linear_model/sgd_fast.pyx":156
  *         return y - p
  * 
  *     def __reduce__(self):             # <<<<<<<<<<<<<<
@@ -3700,7 +3707,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__reduce__");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":151
+  /* "scikits/learn/linear_model/sgd_fast.pyx":157
  * 
  *     def __reduce__(self):
  *         return SquaredLoss, ()             # <<<<<<<<<<<<<<
@@ -3708,7 +3715,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __Pyx_INCREF(((PyObject *)((PyObject*)__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss)));
   PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)((PyObject*)__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss)));
@@ -3732,10 +3739,10 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":166
+/* "scikits/learn/linear_model/sgd_fast.pyx":172
  *     """
  * 
- *     def __init__(self,c):             # <<<<<<<<<<<<<<
+ *     def __init__(self, c):             # <<<<<<<<<<<<<<
  *         self.c = c
  * 
  */
@@ -3762,7 +3769,7 @@ static int __pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber___init__(PyO
       else goto __pyx_L5_argtuple_error;
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
     __pyx_v_c = values[0];
   } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
@@ -3772,21 +3779,21 @@ static int __pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber___init__(PyO
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Huber.__init__");
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":167
+  /* "scikits/learn/linear_model/sgd_fast.pyx":173
  * 
- *     def __init__(self,c):
+ *     def __init__(self, c):
  *         self.c = c             # <<<<<<<<<<<<<<
  * 
  *     cpdef double loss(self, double p, double y):
  */
-  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_c); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 167; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_c); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   ((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber *)__pyx_v_self)->c = __pyx_t_1;
 
   __pyx_r = 0;
@@ -3799,7 +3806,7 @@ static int __pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber___init__(PyO
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":169
+/* "scikits/learn/linear_model/sgd_fast.pyx":175
  *         self.c = c
  * 
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -3823,14 +3830,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_loss(stru
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__loss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber_1loss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -3838,10 +3845,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_loss(stru
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -3850,7 +3857,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_loss(stru
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":170
+  /* "scikits/learn/linear_model/sgd_fast.pyx":176
  * 
  *     cpdef double loss(self, double p, double y):
  *         cdef double r = p - y             # <<<<<<<<<<<<<<
@@ -3859,23 +3866,23 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_loss(stru
  */
   __pyx_v_r = (__pyx_v_p - __pyx_v_y);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":171
+  /* "scikits/learn/linear_model/sgd_fast.pyx":177
  *     cpdef double loss(self, double p, double y):
  *         cdef double r = p - y
  *         cdef double abs_r = abs(r)             # <<<<<<<<<<<<<<
  *         if abs_r <= self.c:
  *             return 0.5 * r * r
  */
-  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_r); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_r); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = PyNumber_Absolute(__pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyNumber_Absolute(__pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __pyx_v_abs_r = __pyx_t_5;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":172
+  /* "scikits/learn/linear_model/sgd_fast.pyx":178
  *         cdef double r = p - y
  *         cdef double abs_r = abs(r)
  *         if abs_r <= self.c:             # <<<<<<<<<<<<<<
@@ -3885,7 +3892,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_loss(stru
   __pyx_t_6 = (__pyx_v_abs_r <= __pyx_v_self->c);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":173
+    /* "scikits/learn/linear_model/sgd_fast.pyx":179
  *         cdef double abs_r = abs(r)
  *         if abs_r <= self.c:
  *             return 0.5 * r * r             # <<<<<<<<<<<<<<
@@ -3898,7 +3905,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_loss(stru
   }
   /*else*/ {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":175
+    /* "scikits/learn/linear_model/sgd_fast.pyx":181
  *             return 0.5 * r * r
  *         else:
  *             return self.c * abs_r - (0.5 * self.c * self.c)             # <<<<<<<<<<<<<<
@@ -3924,7 +3931,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_loss(stru
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":169
+/* "scikits/learn/linear_model/sgd_fast.pyx":175
  *         self.c = c
  * 
  *     cpdef double loss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -3958,30 +3965,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber_1loss(
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "loss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("loss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Huber.loss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Huber *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Huber *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.loss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -3999,7 +4006,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber_1loss(
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":177
+/* "scikits/learn/linear_model/sgd_fast.pyx":183
  *             return self.c * abs_r - (0.5 * self.c * self.c)
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -4023,14 +4030,14 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_dloss(str
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overriden in Python */
   else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__dloss); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (void *)&__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber_2dloss)) {
-      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
@@ -4038,10 +4045,10 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_dloss(str
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_2 = 0;
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_r = __pyx_t_5;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -4050,7 +4057,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_dloss(str
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":178
+  /* "scikits/learn/linear_model/sgd_fast.pyx":184
  * 
  *     cpdef double dloss(self, double p, double y):
  *         cdef double r = y - p             # <<<<<<<<<<<<<<
@@ -4059,23 +4066,23 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_dloss(str
  */
   __pyx_v_r = (__pyx_v_y - __pyx_v_p);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":179
+  /* "scikits/learn/linear_model/sgd_fast.pyx":185
  *     cpdef double dloss(self, double p, double y):
  *         cdef double r = y - p
  *         cdef double abs_r = abs(r)             # <<<<<<<<<<<<<<
  *         if abs_r <= self.c:
  *             return r
  */
-  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_r); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_r); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = PyNumber_Absolute(__pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyNumber_Absolute(__pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __pyx_v_abs_r = __pyx_t_5;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":180
+  /* "scikits/learn/linear_model/sgd_fast.pyx":186
  *         cdef double r = y - p
  *         cdef double abs_r = abs(r)
  *         if abs_r <= self.c:             # <<<<<<<<<<<<<<
@@ -4085,7 +4092,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_dloss(str
   __pyx_t_6 = (__pyx_v_abs_r <= __pyx_v_self->c);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":181
+    /* "scikits/learn/linear_model/sgd_fast.pyx":187
  *         cdef double abs_r = abs(r)
  *         if abs_r <= self.c:
  *             return r             # <<<<<<<<<<<<<<
@@ -4097,7 +4104,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_dloss(str
     goto __pyx_L3;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":182
+  /* "scikits/learn/linear_model/sgd_fast.pyx":188
  *         if abs_r <= self.c:
  *             return r
  *         elif r > 0.0:             # <<<<<<<<<<<<<<
@@ -4107,7 +4114,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_dloss(str
   __pyx_t_6 = (__pyx_v_r > 0.0);
   if (__pyx_t_6) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":183
+    /* "scikits/learn/linear_model/sgd_fast.pyx":189
  *             return r
  *         elif r > 0.0:
  *             return self.c             # <<<<<<<<<<<<<<
@@ -4120,7 +4127,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_dloss(str
   }
   /*else*/ {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":185
+    /* "scikits/learn/linear_model/sgd_fast.pyx":191
  *             return self.c
  *         else:
  *             return -self.c             # <<<<<<<<<<<<<<
@@ -4146,7 +4153,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_dloss(str
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":177
+/* "scikits/learn/linear_model/sgd_fast.pyx":183
  *             return self.c * abs_r - (0.5 * self.c * self.c)
  * 
  *     cpdef double dloss(self, double p, double y):             # <<<<<<<<<<<<<<
@@ -4180,30 +4187,30 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber_2dloss
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "dloss") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
-    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
     goto __pyx_L5_argtuple_error;
   } else {
-    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_p = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_p == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_y = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("dloss", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.Huber.dloss");
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Huber *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Huber *)((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber *)__pyx_v_self)->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.dloss(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_self), __pyx_v_p, __pyx_v_y, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -4221,11 +4228,11 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber_2dloss
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":187
+/* "scikits/learn/linear_model/sgd_fast.pyx":193
  *             return -self.c
  * 
  *     def __reduce__(self):             # <<<<<<<<<<<<<<
- *         return Huber,(self.c,)
+ *         return Huber, (self.c,)
  * 
  */
 
@@ -4236,22 +4243,22 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber_3__red
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("__reduce__");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":188
+  /* "scikits/learn/linear_model/sgd_fast.pyx":194
  * 
  *     def __reduce__(self):
- *         return Huber,(self.c,)             # <<<<<<<<<<<<<<
+ *         return Huber, (self.c,)             # <<<<<<<<<<<<<<
  * 
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber *)__pyx_v_self)->c); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber *)__pyx_v_self)->c); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __Pyx_INCREF(((PyObject *)((PyObject*)__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Huber)));
   PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)((PyObject*)__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Huber)));
@@ -4276,7 +4283,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber_3__red
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":194
+/* "scikits/learn/linear_model/sgd_fast.pyx":200
  * @cython.wraparound(False)
  * @cython.cdivision(True)
  * def plain_sgd(np.ndarray[np.float64_t, ndim=1, mode='c'] w,             # <<<<<<<<<<<<<<
@@ -4285,7 +4292,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_5Huber_3__red
  */
 
 static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd[] = "Cython impl. of SGD for generic loss functions and penalties\n\n    This implementation assumes X represented as a dense array of floats.\n\n    Parameters\n    ----------\n    w : ndarray[double, ndim=1]\n        The allocated coef_ vector.\n    intercept : double\n        The initial intercept\n    loss : LossFunction\n        A concrete LossFunction object.\n    penalty_type : int\n        The penalty 2 for L2, 1 for L1, and 3 for Elastic-Net.\n    alpha : float\n        The regularization parameter.\n    rho : float\n        The elastic net hyperparameter.\n    X : ndarray[double, ndim=2]\n        The dataset as a dense numpy array.\n    Y : ndarray[double, ndim=1]\n        The labels.\n    n_iter : int\n        The number of iterations (epochs).\n    fit_intercept : int\n        Whether or not to fit the intercept (1 or 0).\n    verbose : int\n        Print verbose output; 0 for quite.\n    shuffle : int\n        Whether to shuffle the training data before each epoch.\n    weight_pos : float\n        The weight of the positive class.\n    weight_neg : float\n        The weight of the negative class. \n    seed : int\n        The seed of the pseudo random number generator to use when\n        shuffling the data\n    sample_weight : array, shape = [n_samples]\n        The importance weight of each sample.\n\n    Returns\n    -------\n    w : array, shape [n_features]\n        The fitted weight vector. \n    intercept : float\n        The fitted intercept term. \n\n    \n    ";
+static char __pyx_doc_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd[] = "Cython impl. of SGD for generic loss functions and penalties\n\n    This implementation assumes X represented as a dense array of floats.\n\n    Parameters\n    ----------\n    w : ndarray[double, ndim=1]\n        The allocated coef_ vector.\n    intercept : double\n        The initial intercept\n    loss : LossFunction\n        A concrete LossFunction object.\n    penalty_type : int\n        The penalty 2 for L2, 1 for L1, and 3 for Elastic-Net.\n    alpha : float\n        The regularization parameter.\n    rho : float\n        The elastic net hyperparameter.\n    X : ndarray[double, ndim=2]\n        The dataset as a dense numpy array.\n    Y : ndarray[double, ndim=1]\n        The labels.\n    n_iter : int\n        The number of iterations (epochs).\n    fit_intercept : int\n        Whether or not to fit the intercept (1 or 0).\n    verbose : int\n        Print verbose output; 0 for quite.\n    shuffle : int\n        Whether to shuffle the training data before each epoch.\n    weight_pos : float\n        The weight of the positive class.\n    weight_neg : float\n        The weight of the negative class.\n    seed : int\n        The seed of the pseudo random number generator to use when\n        shuffling the data\n    sample_weight : array, shape = [n_samples]\n        The importance weight of each sample.\n    learning_rate : int\n        The learning rate:\n        (1) constant, eta = eta0\n        (2) optimal, eta = 1.0/(t+t0)\n        (3) inverse scaling, eta = eta0 / pow(t, power_t)\n    eta0 : double\n        The initial learning rate.\n    power_t : double\n        The exponent for inverse scaling learning rate.\n\n    Returns\n    -------\n    w : array, shape [n_features]\n        The fitted weight vector.\n    intercept : float\n        The fitted intercept term.\n\n    ";
 static PyMethodDef __pyx_mdef_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd = {__Pyx_NAMESTR("plain_sgd"), (PyCFunction)__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd)};
 static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyArrayObject *__pyx_v_w = 0;
@@ -4304,6 +4311,9 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
   double __pyx_v_weight_pos;
   double __pyx_v_weight_neg;
   PyArrayObject *__pyx_v_sample_weight = 0;
+  int __pyx_v_learning_rate;
+  double __pyx_v_eta0;
+  double __pyx_v_power_t;
   unsigned int __pyx_v_n_samples;
   unsigned int __pyx_v_n_features;
   int __pyx_v_row_stride;
@@ -4332,7 +4342,6 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
   double *__pyx_v_q_data_ptr;
   double __pyx_v_u;
   double __pyx_v_typw;
-  double __pyx_v_eta0;
   PyObject *__pyx_v_t_start;
   Py_buffer __pyx_bstruct_X;
   Py_ssize_t __pyx_bstride_0_X = 0;
@@ -4376,13 +4385,16 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
   int __pyx_t_19;
   int __pyx_t_20;
   int __pyx_t_21;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__w,&__pyx_n_s__intercept,&__pyx_n_s__loss,&__pyx_n_s__penalty_type,&__pyx_n_s__alpha,&__pyx_n_s__rho,&__pyx_n_s__X,&__pyx_n_s__Y,&__pyx_n_s__n_iter,&__pyx_n_s__fit_intercept,&__pyx_n_s__verbose,&__pyx_n_s__shuffle,&__pyx_n_s__seed,&__pyx_n_s__weight_pos,&__pyx_n_s__weight_neg,&__pyx_n_s__sample_weight,0};
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__w,&__pyx_n_s__intercept,&__pyx_n_s__loss,&__pyx_n_s__penalty_type,&__pyx_n_s__alpha,&__pyx_n_s__rho,&__pyx_n_s__X,&__pyx_n_s__Y,&__pyx_n_s__n_iter,&__pyx_n_s__fit_intercept,&__pyx_n_s__verbose,&__pyx_n_s__shuffle,&__pyx_n_s__seed,&__pyx_n_s__weight_pos,&__pyx_n_s__weight_neg,&__pyx_n_s__sample_weight,&__pyx_n_s__learning_rate,&__pyx_n_s__eta0,&__pyx_n_s__power_t,0};
   __Pyx_RefNannySetupContext("plain_sgd");
   __pyx_self = __pyx_self;
   if (unlikely(__pyx_kwds)) {
     Py_ssize_t kw_args = PyDict_Size(__pyx_kwds);
-    PyObject* values[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+    PyObject* values[19] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
     switch (PyTuple_GET_SIZE(__pyx_args)) {
+      case 19: values[18] = PyTuple_GET_ITEM(__pyx_args, 18);
+      case 18: values[17] = PyTuple_GET_ITEM(__pyx_args, 17);
+      case 17: values[16] = PyTuple_GET_ITEM(__pyx_args, 16);
       case 16: values[15] = PyTuple_GET_ITEM(__pyx_args, 15);
       case 15: values[14] = PyTuple_GET_ITEM(__pyx_args, 14);
       case 14: values[13] = PyTuple_GET_ITEM(__pyx_args, 13);
@@ -4411,135 +4423,159 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__intercept);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  2:
       values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__loss);
       if (likely(values[2])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  3:
       values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__penalty_type);
       if (likely(values[3])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  4:
       values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__alpha);
       if (likely(values[4])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  5:
       values[5] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__rho);
       if (likely(values[5])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 5); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 5); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  6:
       values[6] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__X);
       if (likely(values[6])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 6); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 6); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  7:
       values[7] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__Y);
       if (likely(values[7])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 7); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 7); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  8:
       values[8] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__n_iter);
       if (likely(values[8])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 8); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 8); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  9:
       values[9] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fit_intercept);
       if (likely(values[9])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 9); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 9); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 10:
       values[10] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__verbose);
       if (likely(values[10])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 10); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 10); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 11:
       values[11] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__shuffle);
       if (likely(values[11])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 11); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 11); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 12:
       values[12] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__seed);
       if (likely(values[12])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 12); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 12); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 13:
       values[13] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__weight_pos);
       if (likely(values[13])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 13); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 13); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 14:
       values[14] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__weight_neg);
       if (likely(values[14])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 14); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 14); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 15:
       values[15] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__sample_weight);
       if (likely(values[15])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, 15); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 15); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+      case 16:
+      values[16] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__learning_rate);
+      if (likely(values[16])) kw_args--;
+      else {
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 16); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+      case 17:
+      values[17] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__eta0);
+      if (likely(values[17])) kw_args--;
+      else {
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 17); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+      case 18:
+      values[18] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__power_t);
+      if (likely(values[18])) kw_args--;
+      else {
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, 18); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "plain_sgd") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "plain_sgd") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
     __pyx_v_w = ((PyArrayObject *)values[0]);
-    __pyx_v_intercept = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_intercept == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 195; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_intercept = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_intercept == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_loss = ((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)values[2]);
-    __pyx_v_penalty_type = __Pyx_PyInt_AsInt(values[3]); if (unlikely((__pyx_v_penalty_type == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_alpha = __pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_alpha == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 198; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_rho = __pyx_PyFloat_AsDouble(values[5]); if (unlikely((__pyx_v_rho == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 198; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_penalty_type = __Pyx_PyInt_AsInt(values[3]); if (unlikely((__pyx_v_penalty_type == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_alpha = __pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_alpha == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_rho = __pyx_PyFloat_AsDouble(values[5]); if (unlikely((__pyx_v_rho == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_X = ((PyArrayObject *)values[6]);
     __pyx_v_Y = ((PyArrayObject *)values[7]);
-    __pyx_v_n_iter = __Pyx_PyInt_AsInt(values[8]); if (unlikely((__pyx_v_n_iter == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_fit_intercept = __Pyx_PyInt_AsInt(values[9]); if (unlikely((__pyx_v_fit_intercept == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_verbose = __Pyx_PyInt_AsInt(values[10]); if (unlikely((__pyx_v_verbose == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_shuffle = __Pyx_PyInt_AsInt(values[11]); if (unlikely((__pyx_v_shuffle == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_seed = __Pyx_PyInt_AsInt(values[12]); if (unlikely((__pyx_v_seed == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_weight_pos = __pyx_PyFloat_AsDouble(values[13]); if (unlikely((__pyx_v_weight_pos == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_weight_neg = __pyx_PyFloat_AsDouble(values[14]); if (unlikely((__pyx_v_weight_neg == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_n_iter = __Pyx_PyInt_AsInt(values[8]); if (unlikely((__pyx_v_n_iter == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_fit_intercept = __Pyx_PyInt_AsInt(values[9]); if (unlikely((__pyx_v_fit_intercept == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_verbose = __Pyx_PyInt_AsInt(values[10]); if (unlikely((__pyx_v_verbose == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_shuffle = __Pyx_PyInt_AsInt(values[11]); if (unlikely((__pyx_v_shuffle == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_seed = __Pyx_PyInt_AsInt(values[12]); if (unlikely((__pyx_v_seed == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_weight_pos = __pyx_PyFloat_AsDouble(values[13]); if (unlikely((__pyx_v_weight_pos == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_weight_neg = __pyx_PyFloat_AsDouble(values[14]); if (unlikely((__pyx_v_weight_neg == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_sample_weight = ((PyArrayObject *)values[15]);
-  } else if (PyTuple_GET_SIZE(__pyx_args) != 16) {
+    __pyx_v_learning_rate = __Pyx_PyInt_AsInt(values[16]); if (unlikely((__pyx_v_learning_rate == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_eta0 = __pyx_PyFloat_AsDouble(values[17]); if (unlikely((__pyx_v_eta0 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_power_t = __pyx_PyFloat_AsDouble(values[18]); if (unlikely((__pyx_v_power_t == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  } else if (PyTuple_GET_SIZE(__pyx_args) != 19) {
     goto __pyx_L5_argtuple_error;
   } else {
     __pyx_v_w = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 0));
-    __pyx_v_intercept = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_intercept == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 195; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_intercept = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_intercept == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_loss = ((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)PyTuple_GET_ITEM(__pyx_args, 2));
-    __pyx_v_penalty_type = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 3)); if (unlikely((__pyx_v_penalty_type == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_alpha = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 4)); if (unlikely((__pyx_v_alpha == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 198; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_rho = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 5)); if (unlikely((__pyx_v_rho == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 198; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_penalty_type = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 3)); if (unlikely((__pyx_v_penalty_type == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_alpha = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 4)); if (unlikely((__pyx_v_alpha == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_rho = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 5)); if (unlikely((__pyx_v_rho == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_X = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 6));
     __pyx_v_Y = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 7));
-    __pyx_v_n_iter = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 8)); if (unlikely((__pyx_v_n_iter == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_fit_intercept = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 9)); if (unlikely((__pyx_v_fit_intercept == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_verbose = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 10)); if (unlikely((__pyx_v_verbose == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_shuffle = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 11)); if (unlikely((__pyx_v_shuffle == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_seed = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 12)); if (unlikely((__pyx_v_seed == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_weight_pos = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 13)); if (unlikely((__pyx_v_weight_pos == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_weight_neg = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 14)); if (unlikely((__pyx_v_weight_neg == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_n_iter = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 8)); if (unlikely((__pyx_v_n_iter == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_fit_intercept = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 9)); if (unlikely((__pyx_v_fit_intercept == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_verbose = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 10)); if (unlikely((__pyx_v_verbose == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_shuffle = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 11)); if (unlikely((__pyx_v_shuffle == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_seed = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 12)); if (unlikely((__pyx_v_seed == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_weight_pos = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 13)); if (unlikely((__pyx_v_weight_pos == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_weight_neg = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 14)); if (unlikely((__pyx_v_weight_neg == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_sample_weight = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 15));
+    __pyx_v_learning_rate = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 16)); if (unlikely((__pyx_v_learning_rate == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_eta0 = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 17)); if (unlikely((__pyx_v_eta0 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_power_t = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 18)); if (unlikely((__pyx_v_power_t == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 16, 16, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 19, 19, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast.plain_sgd");
   __Pyx_RefNannyFinishContext();
@@ -4553,37 +4589,37 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
   __pyx_bstruct_X.buf = NULL;
   __pyx_bstruct_Y.buf = NULL;
   __pyx_bstruct_sample_weight.buf = NULL;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_w), __pyx_ptype_5numpy_ndarray, 1, "w", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_loss), __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction, 1, "loss", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_X), __pyx_ptype_5numpy_ndarray, 1, "X", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_Y), __pyx_ptype_5numpy_ndarray, 1, "Y", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sample_weight), __pyx_ptype_5numpy_ndarray, 1, "sample_weight", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_w), __pyx_ptype_5numpy_ndarray, 1, "w", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_loss), __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction, 1, "loss", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_X), __pyx_ptype_5numpy_ndarray, 1, "X", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_Y), __pyx_ptype_5numpy_ndarray, 1, "Y", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sample_weight), __pyx_ptype_5numpy_ndarray, 1, "sample_weight", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_w, (PyObject*)__pyx_v_w, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_w, (PyObject*)__pyx_v_w, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_bstride_0_w = __pyx_bstruct_w.strides[0];
   __pyx_bshape_0_w = __pyx_bstruct_w.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_X, (PyObject*)__pyx_v_X, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_X, (PyObject*)__pyx_v_X, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_bstride_0_X = __pyx_bstruct_X.strides[0]; __pyx_bstride_1_X = __pyx_bstruct_X.strides[1];
   __pyx_bshape_0_X = __pyx_bstruct_X.shape[0]; __pyx_bshape_1_X = __pyx_bstruct_X.shape[1];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_Y, (PyObject*)__pyx_v_Y, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_Y, (PyObject*)__pyx_v_Y, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_bstride_0_Y = __pyx_bstruct_Y.strides[0];
   __pyx_bshape_0_Y = __pyx_bstruct_Y.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_sample_weight, (PyObject*)__pyx_v_sample_weight, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_sample_weight, (PyObject*)__pyx_v_sample_weight, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_bstride_0_sample_weight = __pyx_bstruct_sample_weight.strides[0];
   __pyx_bshape_0_sample_weight = __pyx_bstruct_sample_weight.shape[0];
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":256
+  /* "scikits/learn/linear_model/sgd_fast.pyx":272
  * 
  *     # get the data information into easy vars
  *     cdef unsigned int n_samples = Y.shape[0]             # <<<<<<<<<<<<<<
@@ -4592,7 +4628,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_n_samples = (__pyx_v_Y->dimensions[0]);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":257
+  /* "scikits/learn/linear_model/sgd_fast.pyx":273
  *     # get the data information into easy vars
  *     cdef unsigned int n_samples = Y.shape[0]
  *     cdef unsigned int n_features = w.shape[0]             # <<<<<<<<<<<<<<
@@ -4601,7 +4637,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_n_features = (__pyx_v_w->dimensions[0]);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":260
+  /* "scikits/learn/linear_model/sgd_fast.pyx":276
  * 
  *     # Array strides to get to next feature or example
  *     cdef int row_stride = X.strides[0]             # <<<<<<<<<<<<<<
@@ -4610,7 +4646,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_row_stride = (__pyx_v_X->strides[0]);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":261
+  /* "scikits/learn/linear_model/sgd_fast.pyx":277
  *     # Array strides to get to next feature or example
  *     cdef int row_stride = X.strides[0]
  *     cdef int elem_stride = X.strides[1]             # <<<<<<<<<<<<<<
@@ -4619,7 +4655,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_elem_stride = (__pyx_v_X->strides[1]);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":263
+  /* "scikits/learn/linear_model/sgd_fast.pyx":279
  *     cdef int elem_stride = X.strides[1]
  * 
  *     cdef double *w_data_ptr = <double *>w.data             # <<<<<<<<<<<<<<
@@ -4628,7 +4664,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_w_data_ptr = ((double *)__pyx_v_w->data);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":264
+  /* "scikits/learn/linear_model/sgd_fast.pyx":280
  * 
  *     cdef double *w_data_ptr = <double *>w.data
  *     cdef double *X_data_ptr = <double *>X.data             # <<<<<<<<<<<<<<
@@ -4637,7 +4673,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_X_data_ptr = ((double *)__pyx_v_X->data);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":265
+  /* "scikits/learn/linear_model/sgd_fast.pyx":281
  *     cdef double *w_data_ptr = <double *>w.data
  *     cdef double *X_data_ptr = <double *>X.data
  *     cdef double *Y_data_ptr = <double *>Y.data             # <<<<<<<<<<<<<<
@@ -4646,7 +4682,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_Y_data_ptr = ((double *)__pyx_v_Y->data);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":267
+  /* "scikits/learn/linear_model/sgd_fast.pyx":283
  *     cdef double *Y_data_ptr = <double *>Y.data
  * 
  *     cdef double *sample_weight_data = <double *>sample_weight.data             # <<<<<<<<<<<<<<
@@ -4655,54 +4691,54 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_sample_weight_data = ((double *)__pyx_v_sample_weight->data);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":270
- * 
+  /* "scikits/learn/linear_model/sgd_fast.pyx":287
  *     # Use index array for fast shuffling
- *     cdef np.ndarray[np.int32_t, ndim=1, mode="c"] index = np.arange(n_samples,             # <<<<<<<<<<<<<<
- *                                                                     dtype=np.int32)
+ *     cdef np.ndarray[np.int32_t, ndim=1,
+ *                     mode="c"] index = np.arange(n_samples,             # <<<<<<<<<<<<<<
+ *                                                 dtype=np.int32)
  *     cdef int *index_data_ptr = <int *>index.data
  */
-  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__arange); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__arange); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n_samples); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n_samples); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_3));
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":271
- *     # Use index array for fast shuffling
- *     cdef np.ndarray[np.int32_t, ndim=1, mode="c"] index = np.arange(n_samples,
- *                                                                     dtype=np.int32)             # <<<<<<<<<<<<<<
+  /* "scikits/learn/linear_model/sgd_fast.pyx":288
+ *     cdef np.ndarray[np.int32_t, ndim=1,
+ *                     mode="c"] index = np.arange(n_samples,
+ *                                                 dtype=np.int32)             # <<<<<<<<<<<<<<
  *     cdef int *index_data_ptr = <int *>index.data
  * 
  */
-  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__int32); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__int32); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
     if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_index, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
       __pyx_v_index = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_index.buf = NULL;
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 286; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     } else {__pyx_bstride_0_index = __pyx_bstruct_index.strides[0];
       __pyx_bshape_0_index = __pyx_bstruct_index.shape[0];
     }
@@ -4711,16 +4747,16 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
   __pyx_v_index = ((PyArrayObject *)__pyx_t_5);
   __pyx_t_5 = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":272
- *     cdef np.ndarray[np.int32_t, ndim=1, mode="c"] index = np.arange(n_samples,
- *                                                                     dtype=np.int32)
+  /* "scikits/learn/linear_model/sgd_fast.pyx":289
+ *                     mode="c"] index = np.arange(n_samples,
+ *                                                 dtype=np.int32)
  *     cdef int *index_data_ptr = <int *>index.data             # <<<<<<<<<<<<<<
  * 
  *     # helper variable
  */
   __pyx_v_index_data_ptr = ((int *)__pyx_v_index->data);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":275
+  /* "scikits/learn/linear_model/sgd_fast.pyx":292
  * 
  *     # helper variable
  *     cdef int offset = 0             # <<<<<<<<<<<<<<
@@ -4729,7 +4765,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_offset = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":276
+  /* "scikits/learn/linear_model/sgd_fast.pyx":293
  *     # helper variable
  *     cdef int offset = 0
  *     cdef double wscale = 1.0             # <<<<<<<<<<<<<<
@@ -4738,7 +4774,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_wscale = 1.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":277
+  /* "scikits/learn/linear_model/sgd_fast.pyx":294
  *     cdef int offset = 0
  *     cdef double wscale = 1.0
  *     cdef double eta = 0.0             # <<<<<<<<<<<<<<
@@ -4747,7 +4783,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_eta = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":278
+  /* "scikits/learn/linear_model/sgd_fast.pyx":295
  *     cdef double wscale = 1.0
  *     cdef double eta = 0.0
  *     cdef double p = 0.0             # <<<<<<<<<<<<<<
@@ -4756,7 +4792,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_p = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":279
+  /* "scikits/learn/linear_model/sgd_fast.pyx":296
  *     cdef double eta = 0.0
  *     cdef double p = 0.0
  *     cdef double update = 0.0             # <<<<<<<<<<<<<<
@@ -4765,7 +4801,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_update = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":280
+  /* "scikits/learn/linear_model/sgd_fast.pyx":297
  *     cdef double p = 0.0
  *     cdef double update = 0.0
  *     cdef double sumloss = 0.0             # <<<<<<<<<<<<<<
@@ -4774,7 +4810,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_sumloss = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":281
+  /* "scikits/learn/linear_model/sgd_fast.pyx":298
  *     cdef double update = 0.0
  *     cdef double sumloss = 0.0
  *     cdef double wnorm = 0.0             # <<<<<<<<<<<<<<
@@ -4783,7 +4819,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_wnorm = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":282
+  /* "scikits/learn/linear_model/sgd_fast.pyx":299
  *     cdef double sumloss = 0.0
  *     cdef double wnorm = 0.0
  *     cdef double t = 0.0             # <<<<<<<<<<<<<<
@@ -4792,7 +4828,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_t = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":283
+  /* "scikits/learn/linear_model/sgd_fast.pyx":300
  *     cdef double wnorm = 0.0
  *     cdef double t = 0.0
  *     cdef double y = 0.0             # <<<<<<<<<<<<<<
@@ -4801,7 +4837,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_y = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":284
+  /* "scikits/learn/linear_model/sgd_fast.pyx":301
  *     cdef double t = 0.0
  *     cdef double y = 0.0
  *     cdef double class_weight = 1.0             # <<<<<<<<<<<<<<
@@ -4810,7 +4846,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_class_weight = 1.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":285
+  /* "scikits/learn/linear_model/sgd_fast.pyx":302
  *     cdef double y = 0.0
  *     cdef double class_weight = 1.0
  *     cdef unsigned int count = 0             # <<<<<<<<<<<<<<
@@ -4819,7 +4855,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_count = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":286
+  /* "scikits/learn/linear_model/sgd_fast.pyx":303
  *     cdef double class_weight = 1.0
  *     cdef unsigned int count = 0
  *     cdef unsigned int epoch = 0             # <<<<<<<<<<<<<<
@@ -4828,7 +4864,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_epoch = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":287
+  /* "scikits/learn/linear_model/sgd_fast.pyx":304
  *     cdef unsigned int count = 0
  *     cdef unsigned int epoch = 0
  *     cdef unsigned int i = 0             # <<<<<<<<<<<<<<
@@ -4837,7 +4873,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_i = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":288
+  /* "scikits/learn/linear_model/sgd_fast.pyx":305
  *     cdef unsigned int epoch = 0
  *     cdef unsigned int i = 0
  *     cdef int sample_idx = 0             # <<<<<<<<<<<<<<
@@ -4846,7 +4882,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
   __pyx_v_sample_idx = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":291
+  /* "scikits/learn/linear_model/sgd_fast.pyx":308
  * 
  *     # q vector is only used for L1 regularization
  *     cdef np.ndarray[np.float64_t, ndim=1, mode="c"] q = None             # <<<<<<<<<<<<<<
@@ -4858,7 +4894,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
     __Pyx_BufFmt_StackElem __pyx_stack[1];
     if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_q, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
       __pyx_v_q = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_q.buf = NULL;
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 291; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 308; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     } else {__pyx_bstride_0_q = __pyx_bstruct_q.strides[0];
       __pyx_bshape_0_q = __pyx_bstruct_q.shape[0];
     }
@@ -4867,7 +4903,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
   __Pyx_INCREF(Py_None);
   __pyx_v_q = ((PyArrayObject *)Py_None);
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":293
+  /* "scikits/learn/linear_model/sgd_fast.pyx":310
  *     cdef np.ndarray[np.float64_t, ndim=1, mode="c"] q = None
  *     cdef double *q_data_ptr
  *     if penalty_type != L2:             # <<<<<<<<<<<<<<
@@ -4877,46 +4913,46 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
   __pyx_t_8 = (__pyx_v_penalty_type != 2);
   if (__pyx_t_8) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":294
+    /* "scikits/learn/linear_model/sgd_fast.pyx":311
  *     cdef double *q_data_ptr
  *     if penalty_type != L2:
  *         q = np.zeros((n_features,), dtype=np.float64, order="c")             # <<<<<<<<<<<<<<
  *         q_data_ptr = <double *> q.data
  *     cdef double u = 0.0
  */
-    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n_features); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n_features); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_3));
     PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
     __Pyx_GIVEREF(__pyx_t_5);
     __pyx_t_5 = 0;
-    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_5));
     PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_t_3));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_3));
     __pyx_t_3 = 0;
-    __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-    __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__float64); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__float64); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__order), ((PyObject *)__pyx_n_s__c)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_5), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__order), ((PyObject *)__pyx_n_s__c)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_5), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
     {
       __Pyx_BufFmt_StackElem __pyx_stack[1];
@@ -4933,14 +4969,14 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
       }
       __pyx_bstride_0_q = __pyx_bstruct_q.strides[0];
       __pyx_bshape_0_q = __pyx_bstruct_q.shape[0];
-      if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
     __pyx_t_7 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_v_q));
     __pyx_v_q = ((PyArrayObject *)__pyx_t_4);
     __pyx_t_4 = 0;
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":295
+    /* "scikits/learn/linear_model/sgd_fast.pyx":312
  *     if penalty_type != L2:
  *         q = np.zeros((n_features,), dtype=np.float64, order="c")
  *         q_data_ptr = <double *> q.data             # <<<<<<<<<<<<<<
@@ -4952,60 +4988,108 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
   }
   __pyx_L6:;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":296
+  /* "scikits/learn/linear_model/sgd_fast.pyx":313
  *         q = np.zeros((n_features,), dtype=np.float64, order="c")
  *         q_data_ptr = <double *> q.data
  *     cdef double u = 0.0             # <<<<<<<<<<<<<<
  * 
- *     # computing eta0, the initial learning rate
+ *     cdef double typw = sqrt(1.0 / sqrt(alpha))
  */
   __pyx_v_u = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":299
+  /* "scikits/learn/linear_model/sgd_fast.pyx":315
+ *     cdef double u = 0.0
  * 
- *     # computing eta0, the initial learning rate
  *     cdef double typw = sqrt(1.0 / sqrt(alpha))             # <<<<<<<<<<<<<<
- *     cdef double eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
  * 
+ *     if learning_rate == OPTIMAL:
  */
   __pyx_v_typw = sqrt((1.0 / sqrt(__pyx_v_alpha)));
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":300
- *     # computing eta0, the initial learning rate
+  /* "scikits/learn/linear_model/sgd_fast.pyx":317
  *     cdef double typw = sqrt(1.0 / sqrt(alpha))
- *     cdef double eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))             # <<<<<<<<<<<<<<
  * 
- *     # initialize the 1 / t learning rate schedule from eta0
+ *     if learning_rate == OPTIMAL:             # <<<<<<<<<<<<<<
+ *         # computing eta0, the initial learning rate
+ *         eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
  */
-  __pyx_v_eta0 = (__pyx_v_typw / __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_max(1.0, ((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_loss->__pyx_vtab)->dloss(__pyx_v_loss, (-__pyx_v_typw), 1.0, 0)));
+  __pyx_t_8 = (__pyx_v_learning_rate == 2);
+  if (__pyx_t_8) {
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":303
+    /* "scikits/learn/linear_model/sgd_fast.pyx":319
+ *     if learning_rate == OPTIMAL:
+ *         # computing eta0, the initial learning rate
+ *         eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))             # <<<<<<<<<<<<<<
+ *     else:
+ *         eta = eta0
+ */
+    __pyx_v_eta0 = (__pyx_v_typw / __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_max(1.0, ((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_loss->__pyx_vtab)->dloss(__pyx_v_loss, (-__pyx_v_typw), 1.0, 0)));
+    goto __pyx_L7;
+  }
+  /*else*/ {
+
+    /* "scikits/learn/linear_model/sgd_fast.pyx":321
+ *         eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
+ *     else:
+ *         eta = eta0             # <<<<<<<<<<<<<<
+ * 
+ *     if learning_rate == OPTIMAL:
+ */
+    __pyx_v_eta = __pyx_v_eta0;
+  }
+  __pyx_L7:;
+
+  /* "scikits/learn/linear_model/sgd_fast.pyx":323
+ *         eta = eta0
+ * 
+ *     if learning_rate == OPTIMAL:             # <<<<<<<<<<<<<<
+ *         # initialize t such that eta at first example equals eta0
+ *         t = 1.0 / (eta0 * alpha)
+ */
+  __pyx_t_8 = (__pyx_v_learning_rate == 2);
+  if (__pyx_t_8) {
+
+    /* "scikits/learn/linear_model/sgd_fast.pyx":325
+ *     if learning_rate == OPTIMAL:
+ *         # initialize t such that eta at first example equals eta0
+ *         t = 1.0 / (eta0 * alpha)             # <<<<<<<<<<<<<<
+ *     else:
+ *         t = 1.0
+ */
+    __pyx_v_t = (1.0 / (__pyx_v_eta0 * __pyx_v_alpha));
+    goto __pyx_L8;
+  }
+  /*else*/ {
+
+    /* "scikits/learn/linear_model/sgd_fast.pyx":327
+ *         t = 1.0 / (eta0 * alpha)
+ *     else:
+ *         t = 1.0             # <<<<<<<<<<<<<<
  * 
- *     # initialize the 1 / t learning rate schedule from eta0
- *     t = 1.0 / (eta0 * alpha)             # <<<<<<<<<<<<<<
  *     t_start = time()
- *     for epoch from 0 <= epoch < n_iter:
  */
-  __pyx_v_t = (1.0 / (__pyx_v_eta0 * __pyx_v_alpha));
+    __pyx_v_t = 1.0;
+  }
+  __pyx_L8:;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":304
- *     # initialize the 1 / t learning rate schedule from eta0
- *     t = 1.0 / (eta0 * alpha)
+  /* "scikits/learn/linear_model/sgd_fast.pyx":329
+ *         t = 1.0
+ * 
  *     t_start = time()             # <<<<<<<<<<<<<<
  *     for epoch from 0 <= epoch < n_iter:
  *         if verbose > 0:
  */
-  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__time); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__time); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_v_t_start);
   __pyx_v_t_start = __pyx_t_3;
   __pyx_t_3 = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":305
- *     t = 1.0 / (eta0 * alpha)
+  /* "scikits/learn/linear_model/sgd_fast.pyx":330
+ * 
  *     t_start = time()
  *     for epoch from 0 <= epoch < n_iter:             # <<<<<<<<<<<<<<
  *         if verbose > 0:
@@ -5014,7 +5098,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
   __pyx_t_9 = __pyx_v_n_iter;
   for (__pyx_v_epoch = 0; __pyx_v_epoch < __pyx_t_9; __pyx_v_epoch++) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":306
+    /* "scikits/learn/linear_model/sgd_fast.pyx":331
  *     t_start = time()
  *     for epoch from 0 <= epoch < n_iter:
  *         if verbose > 0:             # <<<<<<<<<<<<<<
@@ -5024,25 +5108,25 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
     __pyx_t_8 = (__pyx_v_verbose > 0);
     if (__pyx_t_8) {
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":307
+      /* "scikits/learn/linear_model/sgd_fast.pyx":332
  *     for epoch from 0 <= epoch < n_iter:
  *         if verbose > 0:
  *             print("-- Epoch %d" % (epoch + 1))             # <<<<<<<<<<<<<<
  *         if shuffle:
  *             np.random.RandomState(seed).shuffle(index)
  */
-      __pyx_t_3 = PyInt_FromLong((__pyx_v_epoch + 1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 307; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong((__pyx_v_epoch + 1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 332; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_1), __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 307; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_1), __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 332; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_4)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 307; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_4)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 332; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      goto __pyx_L9;
+      goto __pyx_L11;
     }
-    __pyx_L9:;
+    __pyx_L11:;
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":308
+    /* "scikits/learn/linear_model/sgd_fast.pyx":333
  *         if verbose > 0:
  *             print("-- Epoch %d" % (epoch + 1))
  *         if shuffle:             # <<<<<<<<<<<<<<
@@ -5051,97 +5135,136 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
     if (__pyx_v_shuffle) {
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":309
+      /* "scikits/learn/linear_model/sgd_fast.pyx":334
  *             print("-- Epoch %d" % (epoch + 1))
  *         if shuffle:
  *             np.random.RandomState(seed).shuffle(index)             # <<<<<<<<<<<<<<
  *         for i from 0 <= i < n_samples:
  *             sample_idx = index_data_ptr[i]
  */
-      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_3 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__random); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__random); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__RandomState); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__RandomState); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = PyInt_FromLong(__pyx_v_seed); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(__pyx_v_seed); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_5));
       PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3);
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
-      __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__shuffle); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__shuffle); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_3));
       __Pyx_INCREF(((PyObject *)__pyx_v_index));
       PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_v_index));
       __Pyx_GIVEREF(((PyObject *)__pyx_v_index));
-      __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      goto __pyx_L10;
+      goto __pyx_L12;
     }
-    __pyx_L10:;
+    __pyx_L12:;
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":310
+    /* "scikits/learn/linear_model/sgd_fast.pyx":335
  *         if shuffle:
  *             np.random.RandomState(seed).shuffle(index)
  *         for i from 0 <= i < n_samples:             # <<<<<<<<<<<<<<
  *             sample_idx = index_data_ptr[i]
- *             offset = row_stride * sample_idx / elem_stride # row offset in elem
+ * 
  */
     __pyx_t_13 = __pyx_v_n_samples;
     for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_13; __pyx_v_i++) {
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":311
+      /* "scikits/learn/linear_model/sgd_fast.pyx":336
  *             np.random.RandomState(seed).shuffle(index)
  *         for i from 0 <= i < n_samples:
  *             sample_idx = index_data_ptr[i]             # <<<<<<<<<<<<<<
- *             offset = row_stride * sample_idx / elem_stride # row offset in elem
- *             y = Y_data_ptr[sample_idx]
+ * 
+ *             # row offset in elem
  */
       __pyx_v_sample_idx = (__pyx_v_index_data_ptr[__pyx_v_i]);
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":312
- *         for i from 0 <= i < n_samples:
- *             sample_idx = index_data_ptr[i]
- *             offset = row_stride * sample_idx / elem_stride # row offset in elem             # <<<<<<<<<<<<<<
+      /* "scikits/learn/linear_model/sgd_fast.pyx":339
+ * 
+ *             # row offset in elem
+ *             offset = row_stride * sample_idx / elem_stride             # <<<<<<<<<<<<<<
  *             y = Y_data_ptr[sample_idx]
- *             eta = 1.0 / (alpha * t)
+ *             if learning_rate == OPTIMAL:
  */
       __pyx_v_offset = ((__pyx_v_row_stride * __pyx_v_sample_idx) / __pyx_v_elem_stride);
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":313
- *             sample_idx = index_data_ptr[i]
- *             offset = row_stride * sample_idx / elem_stride # row offset in elem
+      /* "scikits/learn/linear_model/sgd_fast.pyx":340
+ *             # row offset in elem
+ *             offset = row_stride * sample_idx / elem_stride
  *             y = Y_data_ptr[sample_idx]             # <<<<<<<<<<<<<<
- *             eta = 1.0 / (alpha * t)
- *             p = (dot(w_data_ptr, X_data_ptr, offset, n_features) * wscale
+ *             if learning_rate == OPTIMAL:
+ *                 eta = 1.0 / (alpha * t)
  */
       __pyx_v_y = (__pyx_v_Y_data_ptr[__pyx_v_sample_idx]);
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":314
- *             offset = row_stride * sample_idx / elem_stride # row offset in elem
+      /* "scikits/learn/linear_model/sgd_fast.pyx":343
+ *             if learning_rate == OPTIMAL:
+ *                 eta = 1.0 / (alpha * t)
+ *             elif learning_rate == INVSCALING:             # <<<<<<<<<<<<<<
+ *                 eta = eta0 / pow(t, power_t)
+ *             p = (dot(w_data_ptr, X_data_ptr, offset, n_features) * wscale
+ */
+      switch (__pyx_v_learning_rate) {
+
+        /* "scikits/learn/linear_model/sgd_fast.pyx":341
+ *             offset = row_stride * sample_idx / elem_stride
+ *             y = Y_data_ptr[sample_idx]
+ *             if learning_rate == OPTIMAL:             # <<<<<<<<<<<<<<
+ *                 eta = 1.0 / (alpha * t)
+ *             elif learning_rate == INVSCALING:
+ */
+        case 2:
+
+        /* "scikits/learn/linear_model/sgd_fast.pyx":342
  *             y = Y_data_ptr[sample_idx]
- *             eta = 1.0 / (alpha * t)             # <<<<<<<<<<<<<<
+ *             if learning_rate == OPTIMAL:
+ *                 eta = 1.0 / (alpha * t)             # <<<<<<<<<<<<<<
+ *             elif learning_rate == INVSCALING:
+ *                 eta = eta0 / pow(t, power_t)
+ */
+        __pyx_v_eta = (1.0 / (__pyx_v_alpha * __pyx_v_t));
+        break;
+
+        /* "scikits/learn/linear_model/sgd_fast.pyx":343
+ *             if learning_rate == OPTIMAL:
+ *                 eta = 1.0 / (alpha * t)
+ *             elif learning_rate == INVSCALING:             # <<<<<<<<<<<<<<
+ *                 eta = eta0 / pow(t, power_t)
+ *             p = (dot(w_data_ptr, X_data_ptr, offset, n_features) * wscale
+ */
+        case 3:
+
+        /* "scikits/learn/linear_model/sgd_fast.pyx":344
+ *                 eta = 1.0 / (alpha * t)
+ *             elif learning_rate == INVSCALING:
+ *                 eta = eta0 / pow(t, power_t)             # <<<<<<<<<<<<<<
  *             p = (dot(w_data_ptr, X_data_ptr, offset, n_features) * wscale
  *                 ) + intercept
  */
-      __pyx_v_eta = (1.0 / (__pyx_v_alpha * __pyx_v_t));
+        __pyx_v_eta = (__pyx_v_eta0 / pow(__pyx_v_t, __pyx_v_power_t));
+        break;
+      }
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":316
- *             eta = 1.0 / (alpha * t)
+      /* "scikits/learn/linear_model/sgd_fast.pyx":346
+ *                 eta = eta0 / pow(t, power_t)
  *             p = (dot(w_data_ptr, X_data_ptr, offset, n_features) * wscale
  *                 ) + intercept             # <<<<<<<<<<<<<<
  *             sumloss += loss.loss(p, y)
@@ -5149,7 +5272,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
       __pyx_v_p = ((__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_dot(__pyx_v_w_data_ptr, __pyx_v_X_data_ptr, __pyx_v_offset, __pyx_v_n_features) * __pyx_v_wscale) + __pyx_v_intercept);
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":317
+      /* "scikits/learn/linear_model/sgd_fast.pyx":347
  *             p = (dot(w_data_ptr, X_data_ptr, offset, n_features) * wscale
  *                 ) + intercept
  *             sumloss += loss.loss(p, y)             # <<<<<<<<<<<<<<
@@ -5158,7 +5281,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
       __pyx_v_sumloss = (__pyx_v_sumloss + ((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_loss->__pyx_vtab)->loss(__pyx_v_loss, __pyx_v_p, __pyx_v_y, 0));
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":318
+      /* "scikits/learn/linear_model/sgd_fast.pyx":348
  *                 ) + intercept
  *             sumloss += loss.loss(p, y)
  *             if y > 0:             # <<<<<<<<<<<<<<
@@ -5168,7 +5291,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
       __pyx_t_8 = (__pyx_v_y > 0.0);
       if (__pyx_t_8) {
 
-        /* "scikits/learn/linear_model/sgd_fast.pyx":319
+        /* "scikits/learn/linear_model/sgd_fast.pyx":349
  *             sumloss += loss.loss(p, y)
  *             if y > 0:
  *                 class_weight = weight_pos             # <<<<<<<<<<<<<<
@@ -5176,11 +5299,11 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  *                 class_weight = weight_neg
  */
         __pyx_v_class_weight = __pyx_v_weight_pos;
-        goto __pyx_L13;
+        goto __pyx_L15;
       }
       /*else*/ {
 
-        /* "scikits/learn/linear_model/sgd_fast.pyx":321
+        /* "scikits/learn/linear_model/sgd_fast.pyx":351
  *                 class_weight = weight_pos
  *             else:
  *                 class_weight = weight_neg             # <<<<<<<<<<<<<<
@@ -5189,9 +5312,9 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
         __pyx_v_class_weight = __pyx_v_weight_neg;
       }
-      __pyx_L13:;
+      __pyx_L15:;
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":323
+      /* "scikits/learn/linear_model/sgd_fast.pyx":353
  *                 class_weight = weight_neg
  *             update = eta * loss.dloss(p, y) * class_weight * \
  *                 sample_weight_data[sample_idx]             # <<<<<<<<<<<<<<
@@ -5200,7 +5323,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
       __pyx_v_update = (((__pyx_v_eta * ((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_loss->__pyx_vtab)->dloss(__pyx_v_loss, __pyx_v_p, __pyx_v_y, 0)) * __pyx_v_class_weight) * (__pyx_v_sample_weight_data[__pyx_v_sample_idx]));
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":324
+      /* "scikits/learn/linear_model/sgd_fast.pyx":354
  *             update = eta * loss.dloss(p, y) * class_weight * \
  *                 sample_weight_data[sample_idx]
  *             if update != 0.0:             # <<<<<<<<<<<<<<
@@ -5210,7 +5333,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
       __pyx_t_8 = (__pyx_v_update != 0.0);
       if (__pyx_t_8) {
 
-        /* "scikits/learn/linear_model/sgd_fast.pyx":325
+        /* "scikits/learn/linear_model/sgd_fast.pyx":355
  *                 sample_weight_data[sample_idx]
  *             if update != 0.0:
  *                 add(w_data_ptr, wscale, X_data_ptr, offset, n_features, update)             # <<<<<<<<<<<<<<
@@ -5219,7 +5342,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
         __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(__pyx_v_w_data_ptr, __pyx_v_wscale, __pyx_v_X_data_ptr, __pyx_v_offset, __pyx_v_n_features, __pyx_v_update);
 
-        /* "scikits/learn/linear_model/sgd_fast.pyx":326
+        /* "scikits/learn/linear_model/sgd_fast.pyx":356
  *             if update != 0.0:
  *                 add(w_data_ptr, wscale, X_data_ptr, offset, n_features, update)
  *                 if fit_intercept == 1:             # <<<<<<<<<<<<<<
@@ -5229,7 +5352,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
         __pyx_t_8 = (__pyx_v_fit_intercept == 1);
         if (__pyx_t_8) {
 
-          /* "scikits/learn/linear_model/sgd_fast.pyx":327
+          /* "scikits/learn/linear_model/sgd_fast.pyx":357
  *                 add(w_data_ptr, wscale, X_data_ptr, offset, n_features, update)
  *                 if fit_intercept == 1:
  *                     intercept += update             # <<<<<<<<<<<<<<
@@ -5237,14 +5360,14 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  *                 wscale *= (1.0 - (rho * eta * alpha))
  */
           __pyx_v_intercept = (__pyx_v_intercept + __pyx_v_update);
-          goto __pyx_L15;
+          goto __pyx_L17;
         }
-        __pyx_L15:;
-        goto __pyx_L14;
+        __pyx_L17:;
+        goto __pyx_L16;
       }
-      __pyx_L14:;
+      __pyx_L16:;
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":328
+      /* "scikits/learn/linear_model/sgd_fast.pyx":358
  *                 if fit_intercept == 1:
  *                     intercept += update
  *             if penalty_type != L1:             # <<<<<<<<<<<<<<
@@ -5254,7 +5377,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
       __pyx_t_8 = (__pyx_v_penalty_type != 1);
       if (__pyx_t_8) {
 
-        /* "scikits/learn/linear_model/sgd_fast.pyx":329
+        /* "scikits/learn/linear_model/sgd_fast.pyx":359
  *                     intercept += update
  *             if penalty_type != L1:
  *                 wscale *= (1.0 - (rho * eta * alpha))             # <<<<<<<<<<<<<<
@@ -5263,7 +5386,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
         __pyx_v_wscale = (__pyx_v_wscale * (1.0 - ((__pyx_v_rho * __pyx_v_eta) * __pyx_v_alpha)));
 
-        /* "scikits/learn/linear_model/sgd_fast.pyx":330
+        /* "scikits/learn/linear_model/sgd_fast.pyx":360
  *             if penalty_type != L1:
  *                 wscale *= (1.0 - (rho * eta * alpha))
  *                 if wscale < 1e-9:             # <<<<<<<<<<<<<<
@@ -5273,19 +5396,19 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
         __pyx_t_8 = (__pyx_v_wscale < 1e-9);
         if (__pyx_t_8) {
 
-          /* "scikits/learn/linear_model/sgd_fast.pyx":331
+          /* "scikits/learn/linear_model/sgd_fast.pyx":361
  *                 wscale *= (1.0 - (rho * eta * alpha))
  *                 if wscale < 1e-9:
  *                     w *= wscale             # <<<<<<<<<<<<<<
  *                     wscale = 1.0
  *             if penalty_type == L1 or penalty_type == ELASTICNET:
  */
-          __pyx_t_4 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_4 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 361; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_3 = PyNumber_InPlaceMultiply(((PyObject *)__pyx_v_w), __pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PyNumber_InPlaceMultiply(((PyObject *)__pyx_v_w), __pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 361; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_3);
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 361; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __pyx_t_14 = ((PyArrayObject *)__pyx_t_3);
           {
             __Pyx_BufFmt_StackElem __pyx_stack[1];
@@ -5302,14 +5425,14 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
             }
             __pyx_bstride_0_w = __pyx_bstruct_w.strides[0];
             __pyx_bshape_0_w = __pyx_bstruct_w.shape[0];
-            if (unlikely(__pyx_t_15 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            if (unlikely(__pyx_t_15 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 361; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           }
           __pyx_t_14 = 0;
           __Pyx_DECREF(((PyObject *)__pyx_v_w));
           __pyx_v_w = ((PyArrayObject *)__pyx_t_3);
           __pyx_t_3 = 0;
 
-          /* "scikits/learn/linear_model/sgd_fast.pyx":332
+          /* "scikits/learn/linear_model/sgd_fast.pyx":362
  *                 if wscale < 1e-9:
  *                     w *= wscale
  *                     wscale = 1.0             # <<<<<<<<<<<<<<
@@ -5317,14 +5440,14 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  *                 u += ((1.0 - rho) * eta * alpha)
  */
           __pyx_v_wscale = 1.0;
-          goto __pyx_L17;
+          goto __pyx_L19;
         }
-        __pyx_L17:;
-        goto __pyx_L16;
+        __pyx_L19:;
+        goto __pyx_L18;
       }
-      __pyx_L16:;
+      __pyx_L18:;
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":333
+      /* "scikits/learn/linear_model/sgd_fast.pyx":363
  *                     w *= wscale
  *                     wscale = 1.0
  *             if penalty_type == L1 or penalty_type == ELASTICNET:             # <<<<<<<<<<<<<<
@@ -5335,7 +5458,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
         case 1:
         case 3:
 
-        /* "scikits/learn/linear_model/sgd_fast.pyx":334
+        /* "scikits/learn/linear_model/sgd_fast.pyx":364
  *                     wscale = 1.0
  *             if penalty_type == L1 or penalty_type == ELASTICNET:
  *                 u += ((1.0 - rho) * eta * alpha)             # <<<<<<<<<<<<<<
@@ -5344,7 +5467,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
         __pyx_v_u = (__pyx_v_u + (((1.0 - __pyx_v_rho) * __pyx_v_eta) * __pyx_v_alpha));
 
-        /* "scikits/learn/linear_model/sgd_fast.pyx":335
+        /* "scikits/learn/linear_model/sgd_fast.pyx":365
  *             if penalty_type == L1 or penalty_type == ELASTICNET:
  *                 u += ((1.0 - rho) * eta * alpha)
  *                 l1penalty(w_data_ptr, wscale, q_data_ptr, n_features, u)             # <<<<<<<<<<<<<<
@@ -5355,7 +5478,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
         break;
       }
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":336
+      /* "scikits/learn/linear_model/sgd_fast.pyx":366
  *                 u += ((1.0 - rho) * eta * alpha)
  *                 l1penalty(w_data_ptr, wscale, q_data_ptr, n_features, u)
  *             t += 1             # <<<<<<<<<<<<<<
@@ -5364,7 +5487,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  */
       __pyx_v_t = (__pyx_v_t + 1.0);
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":337
+      /* "scikits/learn/linear_model/sgd_fast.pyx":367
  *                 l1penalty(w_data_ptr, wscale, q_data_ptr, n_features, u)
  *             t += 1
  *             count += 1             # <<<<<<<<<<<<<<
@@ -5374,7 +5497,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
       __pyx_v_count = (__pyx_v_count + 1);
     }
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":340
+    /* "scikits/learn/linear_model/sgd_fast.pyx":370
  * 
  *         # report epoche information
  *         if verbose > 0:             # <<<<<<<<<<<<<<
@@ -5384,19 +5507,19 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
     __pyx_t_8 = (__pyx_v_verbose > 0);
     if (__pyx_t_8) {
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":341
+      /* "scikits/learn/linear_model/sgd_fast.pyx":371
  *         # report epoche information
  *         if verbose > 0:
  *             wnorm = sqrt(np.dot(w, w) * wscale * wscale)             # <<<<<<<<<<<<<<
  *             print("Norm: %.2f, NNZs: %d, "\
  *             "Bias: %.6f, T: %d, Avg. loss: %.6f" % (wnorm,
  */
-      __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__dot); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__dot); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_3));
       __Pyx_INCREF(((PyObject *)__pyx_v_w));
       PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_v_w));
@@ -5404,80 +5527,80 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
       __Pyx_INCREF(((PyObject *)__pyx_v_w));
       PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_v_w));
       __Pyx_GIVEREF(((PyObject *)__pyx_v_w));
-      __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyNumber_Multiply(__pyx_t_5, __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyNumber_Multiply(__pyx_t_5, __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyNumber_Multiply(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyNumber_Multiply(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_16 = __pyx_PyFloat_AsDouble(__pyx_t_5); if (unlikely((__pyx_t_16 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_16 = __pyx_PyFloat_AsDouble(__pyx_t_5); if (unlikely((__pyx_t_16 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __pyx_v_wnorm = sqrt(__pyx_t_16);
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":343
+      /* "scikits/learn/linear_model/sgd_fast.pyx":373
  *             wnorm = sqrt(np.dot(w, w) * wscale * wscale)
  *             print("Norm: %.2f, NNZs: %d, "\
  *             "Bias: %.6f, T: %d, Avg. loss: %.6f" % (wnorm,             # <<<<<<<<<<<<<<
  *                                                     w.nonzero()[0].shape[0],
  *                                                     intercept, count,
  */
-      __pyx_t_5 = PyFloat_FromDouble(__pyx_v_wnorm); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyFloat_FromDouble(__pyx_v_wnorm); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":344
+      /* "scikits/learn/linear_model/sgd_fast.pyx":374
  *             print("Norm: %.2f, NNZs: %d, "\
  *             "Bias: %.6f, T: %d, Avg. loss: %.6f" % (wnorm,
  *                                                     w.nonzero()[0].shape[0],             # <<<<<<<<<<<<<<
  *                                                     intercept, count,
  *                                                     sumloss / count))
  */
-      __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_w), __pyx_n_s__nonzero); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 344; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_w), __pyx_n_s__nonzero); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 344; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_4, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 344; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_4, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__shape); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 344; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__shape); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_4, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 344; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_4, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":345
+      /* "scikits/learn/linear_model/sgd_fast.pyx":375
  *             "Bias: %.6f, T: %d, Avg. loss: %.6f" % (wnorm,
  *                                                     w.nonzero()[0].shape[0],
  *                                                     intercept, count,             # <<<<<<<<<<<<<<
  *                                                     sumloss / count))
- *             print("Total training time: %.2f seconds." % (time()-t_start))
+ *             print("Total training time: %.2f seconds." % (time() - t_start))
  */
-      __pyx_t_4 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 345; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 375; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_count); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 345; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_count); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 375; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":346
+      /* "scikits/learn/linear_model/sgd_fast.pyx":376
  *                                                     w.nonzero()[0].shape[0],
  *                                                     intercept, count,
  *                                                     sumloss / count))             # <<<<<<<<<<<<<<
- *             print("Total training time: %.2f seconds." % (time()-t_start))
+ *             print("Total training time: %.2f seconds." % (time() - t_start))
  * 
  */
-      __pyx_t_2 = PyFloat_FromDouble((__pyx_v_sumloss / __pyx_v_count)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble((__pyx_v_sumloss / __pyx_v_count)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 376; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_17 = PyTuple_New(5); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_17 = PyTuple_New(5); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_17));
       PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_5);
       __Pyx_GIVEREF(__pyx_t_5);
@@ -5494,165 +5617,165 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
       __pyx_t_4 = 0;
       __pyx_t_1 = 0;
       __pyx_t_2 = 0;
-      __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_2), ((PyObject *)__pyx_t_17)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_2), ((PyObject *)__pyx_t_17)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_2));
       __Pyx_DECREF(((PyObject *)__pyx_t_17)); __pyx_t_17 = 0;
-      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_2)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 342; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_2)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 372; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":347
+      /* "scikits/learn/linear_model/sgd_fast.pyx":377
  *                                                     intercept, count,
  *                                                     sumloss / count))
- *             print("Total training time: %.2f seconds." % (time()-t_start))             # <<<<<<<<<<<<<<
+ *             print("Total training time: %.2f seconds." % (time() - t_start))             # <<<<<<<<<<<<<<
  * 
  *         # floating-point under-/overflow check.
  */
-      __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__time); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__time); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 377; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_17 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_17 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 377; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_17);
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_t_2 = PyNumber_Subtract(__pyx_t_17, __pyx_v_t_start); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyNumber_Subtract(__pyx_t_17, __pyx_v_t_start); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 377; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
       __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
-      __pyx_t_17 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_3), __pyx_t_2); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_17 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_3), __pyx_t_2); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 377; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_17));
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_17)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_17)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 377; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(((PyObject *)__pyx_t_17)); __pyx_t_17 = 0;
-      goto __pyx_L18;
+      goto __pyx_L20;
     }
-    __pyx_L18:;
+    __pyx_L20:;
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":350
+    /* "scikits/learn/linear_model/sgd_fast.pyx":380
  * 
  *         # floating-point under-/overflow check.
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \             # <<<<<<<<<<<<<<
  *            or np.isnan(intercept) or np.isinf(intercept):
  *             raise ValueError("floating-point under-/overflow occured.")
  */
-    __pyx_t_17 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_17 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_17);
-    __pyx_t_2 = PyObject_GetAttr(__pyx_t_17, __pyx_n_s__any); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyObject_GetAttr(__pyx_t_17, __pyx_n_s__any); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
-    __pyx_t_17 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_17 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_17);
-    __pyx_t_1 = PyObject_GetAttr(__pyx_t_17, __pyx_n_s__isinf); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_17, __pyx_n_s__isinf); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
-    __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_17));
     __Pyx_INCREF(((PyObject *)__pyx_v_w));
     PyTuple_SET_ITEM(__pyx_t_17, 0, ((PyObject *)__pyx_v_w));
     __Pyx_GIVEREF(((PyObject *)__pyx_v_w));
-    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_17)); __pyx_t_17 = 0;
-    __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_17));
     PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_4);
     __Pyx_GIVEREF(__pyx_t_4);
     __pyx_t_4 = 0;
-    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_17)); __pyx_t_17 = 0;
-    __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     if (!__pyx_t_8) {
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":351
+      /* "scikits/learn/linear_model/sgd_fast.pyx":381
  *         # floating-point under-/overflow check.
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \
  *            or np.isnan(intercept) or np.isinf(intercept):             # <<<<<<<<<<<<<<
  *             raise ValueError("floating-point under-/overflow occured.")
  * 
  */
-      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_17 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__any); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_17 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__any); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_17);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":350
+      /* "scikits/learn/linear_model/sgd_fast.pyx":380
  * 
  *         # floating-point under-/overflow check.
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \             # <<<<<<<<<<<<<<
  *            or np.isnan(intercept) or np.isinf(intercept):
  *             raise ValueError("floating-point under-/overflow occured.")
  */
-      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_2 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__isnan); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__isnan); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       __Pyx_INCREF(((PyObject *)__pyx_v_w));
       PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_v_w));
       __Pyx_GIVEREF(((PyObject *)__pyx_v_w));
-      __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
       __Pyx_GIVEREF(__pyx_t_1);
       __pyx_t_1 = 0;
-      __pyx_t_1 = PyObject_Call(__pyx_t_17, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyObject_Call(__pyx_t_17, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
       __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_18 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_18 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_18 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_18 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
       if (!__pyx_t_18) {
 
-        /* "scikits/learn/linear_model/sgd_fast.pyx":351
+        /* "scikits/learn/linear_model/sgd_fast.pyx":381
  *         # floating-point under-/overflow check.
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \
  *            or np.isnan(intercept) or np.isinf(intercept):             # <<<<<<<<<<<<<<
  *             raise ValueError("floating-point under-/overflow occured.")
  * 
  */
-        __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
-        __pyx_t_4 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__isnan); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_4 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__isnan); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_4);
         __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-        __pyx_t_1 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
-        __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(((PyObject *)__pyx_t_17));
         PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_1);
         __Pyx_GIVEREF(__pyx_t_1);
         __pyx_t_1 = 0;
-        __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
         __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
         __Pyx_DECREF(((PyObject *)__pyx_t_17)); __pyx_t_17 = 0;
-        __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
         if (!__pyx_t_19) {
-          __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_17 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__isinf); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_17 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__isinf); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_17);
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-          __pyx_t_1 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_1 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(((PyObject *)__pyx_t_4));
           PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
           __Pyx_GIVEREF(__pyx_t_1);
           __pyx_t_1 = 0;
-          __pyx_t_1 = PyObject_Call(__pyx_t_17, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_1 = PyObject_Call(__pyx_t_17, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_1);
           __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
           __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-          __pyx_t_20 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_20 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_20 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_20 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           __pyx_t_21 = __pyx_t_20;
         } else {
@@ -5668,36 +5791,36 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
     }
     if (__pyx_t_18) {
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":352
+      /* "scikits/learn/linear_model/sgd_fast.pyx":382
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \
  *            or np.isnan(intercept) or np.isinf(intercept):
  *             raise ValueError("floating-point under-/overflow occured.")             # <<<<<<<<<<<<<<
  * 
  *     w *= wscale
  */
-      __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_5), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_5), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 382; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
       __Pyx_Raise(__pyx_t_1, 0, 0);
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      goto __pyx_L19;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 382; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      goto __pyx_L21;
     }
-    __pyx_L19:;
+    __pyx_L21:;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":354
+  /* "scikits/learn/linear_model/sgd_fast.pyx":384
  *             raise ValueError("floating-point under-/overflow occured.")
  * 
  *     w *= wscale             # <<<<<<<<<<<<<<
  *     return w, intercept
  * 
  */
-  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 384; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_4 = PyNumber_InPlaceMultiply(((PyObject *)__pyx_v_w), __pyx_t_1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyNumber_InPlaceMultiply(((PyObject *)__pyx_v_w), __pyx_t_1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 384; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 384; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_t_14 = ((PyArrayObject *)__pyx_t_4);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
@@ -5714,14 +5837,14 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
     }
     __pyx_bstride_0_w = __pyx_bstruct_w.strides[0];
     __pyx_bshape_0_w = __pyx_bstruct_w.shape[0];
-    if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 384; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_14 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_v_w));
   __pyx_v_w = ((PyArrayObject *)__pyx_t_4);
   __pyx_t_4 = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":355
+  /* "scikits/learn/linear_model/sgd_fast.pyx":385
  * 
  *     w *= wscale
  *     return w, intercept             # <<<<<<<<<<<<<<
@@ -5729,9 +5852,9 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_4 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 355; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 355; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __Pyx_INCREF(((PyObject *)__pyx_v_w));
   PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_w));
@@ -5781,7 +5904,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd(PyO
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":358
+/* "scikits/learn/linear_model/sgd_fast.pyx":388
  * 
  * 
  * cdef inline double max(double a, double b):             # <<<<<<<<<<<<<<
@@ -5794,7 +5917,7 @@ static CYTHON_INLINE double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_max
   double __pyx_t_1;
   __Pyx_RefNannySetupContext("max");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":359
+  /* "scikits/learn/linear_model/sgd_fast.pyx":389
  * 
  * cdef inline double max(double a, double b):
  *     return a if a >= b else b             # <<<<<<<<<<<<<<
@@ -5815,7 +5938,7 @@ static CYTHON_INLINE double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_max
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":362
+/* "scikits/learn/linear_model/sgd_fast.pyx":392
  * 
  * 
  * cdef inline double min(double a, double b):             # <<<<<<<<<<<<<<
@@ -5828,7 +5951,7 @@ static CYTHON_INLINE double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_min
   double __pyx_t_1;
   __Pyx_RefNannySetupContext("min");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":363
+  /* "scikits/learn/linear_model/sgd_fast.pyx":393
  * 
  * cdef inline double min(double a, double b):
  *     return a if a <= b else b             # <<<<<<<<<<<<<<
@@ -5849,7 +5972,7 @@ static CYTHON_INLINE double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_min
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":366
+/* "scikits/learn/linear_model/sgd_fast.pyx":396
  * 
  * 
  * cdef double dot(double *w_data_ptr, double *X_data_ptr,             # <<<<<<<<<<<<<<
@@ -5864,7 +5987,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_dot(double *__py
   unsigned int __pyx_t_1;
   __Pyx_RefNannySetupContext("dot");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":368
+  /* "scikits/learn/linear_model/sgd_fast.pyx":398
  * cdef double dot(double *w_data_ptr, double *X_data_ptr,
  *                 int offset, unsigned int n_features):
  *     cdef double sum = 0.0             # <<<<<<<<<<<<<<
@@ -5873,7 +5996,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_dot(double *__py
  */
   __pyx_v_sum = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":370
+  /* "scikits/learn/linear_model/sgd_fast.pyx":400
  *     cdef double sum = 0.0
  *     cdef int j
  *     for j from 0 <= j < n_features:             # <<<<<<<<<<<<<<
@@ -5883,7 +6006,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_dot(double *__py
   __pyx_t_1 = __pyx_v_n_features;
   for (__pyx_v_j = 0; __pyx_v_j < __pyx_t_1; __pyx_v_j++) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":371
+    /* "scikits/learn/linear_model/sgd_fast.pyx":401
  *     cdef int j
  *     for j from 0 <= j < n_features:
  *         sum += w_data_ptr[j] * X_data_ptr[offset + j]             # <<<<<<<<<<<<<<
@@ -5893,7 +6016,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_dot(double *__py
     __pyx_v_sum = (__pyx_v_sum + ((__pyx_v_w_data_ptr[__pyx_v_j]) * (__pyx_v_X_data_ptr[(__pyx_v_offset + __pyx_v_j)])));
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":372
+  /* "scikits/learn/linear_model/sgd_fast.pyx":402
  *     for j from 0 <= j < n_features:
  *         sum += w_data_ptr[j] * X_data_ptr[offset + j]
  *     return sum             # <<<<<<<<<<<<<<
@@ -5909,7 +6032,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_dot(double *__py
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":375
+/* "scikits/learn/linear_model/sgd_fast.pyx":405
  * 
  * 
  * cdef double add(double *w_data_ptr, double wscale, double *X_data_ptr,             # <<<<<<<<<<<<<<
@@ -5927,7 +6050,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(double *__py
   int __pyx_t_2;
   __Pyx_RefNannySetupContext("add");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":381
+  /* "scikits/learn/linear_model/sgd_fast.pyx":411
  *     cdef int idx
  *     cdef double val
  *     cdef double innerprod = 0.0             # <<<<<<<<<<<<<<
@@ -5936,7 +6059,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(double *__py
  */
   __pyx_v_innerprod = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":382
+  /* "scikits/learn/linear_model/sgd_fast.pyx":412
  *     cdef double val
  *     cdef double innerprod = 0.0
  *     cdef double xsqnorm = 0.0             # <<<<<<<<<<<<<<
@@ -5945,7 +6068,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(double *__py
  */
   __pyx_v_xsqnorm = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":383
+  /* "scikits/learn/linear_model/sgd_fast.pyx":413
  *     cdef double innerprod = 0.0
  *     cdef double xsqnorm = 0.0
  *     for j from 0 <= j < n_features:             # <<<<<<<<<<<<<<
@@ -5955,7 +6078,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(double *__py
   __pyx_t_1 = __pyx_v_n_features;
   for (__pyx_v_j = 0; __pyx_v_j < __pyx_t_1; __pyx_v_j++) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":384
+    /* "scikits/learn/linear_model/sgd_fast.pyx":414
  *     cdef double xsqnorm = 0.0
  *     for j from 0 <= j < n_features:
  *         val = X_data_ptr[offset + j]             # <<<<<<<<<<<<<<
@@ -5964,7 +6087,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(double *__py
  */
     __pyx_v_val = (__pyx_v_X_data_ptr[(__pyx_v_offset + __pyx_v_j)]);
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":385
+    /* "scikits/learn/linear_model/sgd_fast.pyx":415
  *     for j from 0 <= j < n_features:
  *         val = X_data_ptr[offset + j]
  *         innerprod += (w_data_ptr[j] * val)             # <<<<<<<<<<<<<<
@@ -5973,7 +6096,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(double *__py
  */
     __pyx_v_innerprod = (__pyx_v_innerprod + ((__pyx_v_w_data_ptr[__pyx_v_j]) * __pyx_v_val));
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":386
+    /* "scikits/learn/linear_model/sgd_fast.pyx":416
  *         val = X_data_ptr[offset + j]
  *         innerprod += (w_data_ptr[j] * val)
  *         xsqnorm += (val * val)             # <<<<<<<<<<<<<<
@@ -5982,7 +6105,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(double *__py
  */
     __pyx_v_xsqnorm = (__pyx_v_xsqnorm + (__pyx_v_val * __pyx_v_val));
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":387
+    /* "scikits/learn/linear_model/sgd_fast.pyx":417
  *         innerprod += (w_data_ptr[j] * val)
  *         xsqnorm += (val * val)
  *         w_data_ptr[j] += val * (c / wscale)             # <<<<<<<<<<<<<<
@@ -5993,7 +6116,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(double *__py
     (__pyx_v_w_data_ptr[__pyx_t_2]) = ((__pyx_v_w_data_ptr[__pyx_t_2]) + (__pyx_v_val * (__pyx_v_c / __pyx_v_wscale)));
   }
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":390
+  /* "scikits/learn/linear_model/sgd_fast.pyx":420
  * 
  *     # TODO this is needed for PEGASOS only
  *     return (xsqnorm * c * c) + (2.0 * innerprod * wscale * c)             # <<<<<<<<<<<<<<
@@ -6009,7 +6132,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_add(double *__py
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast.pyx":393
+/* "scikits/learn/linear_model/sgd_fast.pyx":423
  * 
  * 
  * cdef void l1penalty(double *w_data_ptr, double wscale, double *q_data_ptr,             # <<<<<<<<<<<<<<
@@ -6026,7 +6149,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_l1penalty(double *
   int __pyx_t_3;
   __Pyx_RefNannySetupContext("l1penalty");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":403
+  /* "scikits/learn/linear_model/sgd_fast.pyx":433
  *     Empirical results look better this way...
  *     """
  *     cdef double z = 0.0             # <<<<<<<<<<<<<<
@@ -6035,7 +6158,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_l1penalty(double *
  */
   __pyx_v_z = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":404
+  /* "scikits/learn/linear_model/sgd_fast.pyx":434
  *     """
  *     cdef double z = 0.0
  *     cdef int j = 0             # <<<<<<<<<<<<<<
@@ -6044,7 +6167,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_l1penalty(double *
  */
   __pyx_v_j = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":405
+  /* "scikits/learn/linear_model/sgd_fast.pyx":435
  *     cdef double z = 0.0
  *     cdef int j = 0
  *     cdef int idx = 0             # <<<<<<<<<<<<<<
@@ -6053,7 +6176,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_l1penalty(double *
  */
   __pyx_v_idx = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":406
+  /* "scikits/learn/linear_model/sgd_fast.pyx":436
  *     cdef int j = 0
  *     cdef int idx = 0
  *     for j from 0 <= j < n_features:             # <<<<<<<<<<<<<<
@@ -6063,7 +6186,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_l1penalty(double *
   __pyx_t_1 = __pyx_v_n_features;
   for (__pyx_v_j = 0; __pyx_v_j < __pyx_t_1; __pyx_v_j++) {
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":407
+    /* "scikits/learn/linear_model/sgd_fast.pyx":437
  *     cdef int idx = 0
  *     for j from 0 <= j < n_features:
  *         z = w_data_ptr[j]             # <<<<<<<<<<<<<<
@@ -6072,42 +6195,42 @@ static  void __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_l1penalty(double *
  */
     __pyx_v_z = (__pyx_v_w_data_ptr[__pyx_v_j]);
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":408
+    /* "scikits/learn/linear_model/sgd_fast.pyx":438
  *     for j from 0 <= j < n_features:
  *         z = w_data_ptr[j]
  *         if (wscale * w_data_ptr[j]) > 0.0:             # <<<<<<<<<<<<<<
  *             w_data_ptr[j] = max(0.0, w_data_ptr[j] - ((u + q_data_ptr[j])
- *                                                         / wscale) )
+ *                                                         / wscale))
  */
     __pyx_t_2 = ((__pyx_v_wscale * (__pyx_v_w_data_ptr[__pyx_v_j])) > 0.0);
     if (__pyx_t_2) {
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":409
+      /* "scikits/learn/linear_model/sgd_fast.pyx":439
  *         z = w_data_ptr[j]
  *         if (wscale * w_data_ptr[j]) > 0.0:
  *             w_data_ptr[j] = max(0.0, w_data_ptr[j] - ((u + q_data_ptr[j])             # <<<<<<<<<<<<<<
- *                                                         / wscale) )
+ *                                                         / wscale))
  *         elif (wscale * w_data_ptr[j]) < 0.0:
  */
       (__pyx_v_w_data_ptr[__pyx_v_j]) = __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_max(0.0, ((__pyx_v_w_data_ptr[__pyx_v_j]) - ((__pyx_v_u + (__pyx_v_q_data_ptr[__pyx_v_j])) / __pyx_v_wscale)));
       goto __pyx_L5;
     }
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":411
+    /* "scikits/learn/linear_model/sgd_fast.pyx":441
  *             w_data_ptr[j] = max(0.0, w_data_ptr[j] - ((u + q_data_ptr[j])
- *                                                         / wscale) )
+ *                                                         / wscale))
  *         elif (wscale * w_data_ptr[j]) < 0.0:             # <<<<<<<<<<<<<<
  *             w_data_ptr[j] = min(0.0, w_data_ptr[j] + ((u - q_data_ptr[j])
- *                                                         / wscale) )
+ *                                                         / wscale))
  */
     __pyx_t_2 = ((__pyx_v_wscale * (__pyx_v_w_data_ptr[__pyx_v_j])) < 0.0);
     if (__pyx_t_2) {
 
-      /* "scikits/learn/linear_model/sgd_fast.pyx":412
- *                                                         / wscale) )
+      /* "scikits/learn/linear_model/sgd_fast.pyx":442
+ *                                                         / wscale))
  *         elif (wscale * w_data_ptr[j]) < 0.0:
  *             w_data_ptr[j] = min(0.0, w_data_ptr[j] + ((u - q_data_ptr[j])             # <<<<<<<<<<<<<<
- *                                                         / wscale) )
+ *                                                         / wscale))
  *         q_data_ptr[j] += (wscale * (w_data_ptr[j] - z))
  */
       (__pyx_v_w_data_ptr[__pyx_v_j]) = __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_min(0.0, ((__pyx_v_w_data_ptr[__pyx_v_j]) + ((__pyx_v_u - (__pyx_v_q_data_ptr[__pyx_v_j])) / __pyx_v_wscale)));
@@ -6115,12 +6238,10 @@ static  void __pyx_f_7scikits_5learn_12linear_model_8sgd_fast_l1penalty(double *
     }
     __pyx_L5:;
 
-    /* "scikits/learn/linear_model/sgd_fast.pyx":414
+    /* "scikits/learn/linear_model/sgd_fast.pyx":444
  *             w_data_ptr[j] = min(0.0, w_data_ptr[j] + ((u - q_data_ptr[j])
- *                                                         / wscale) )
+ *                                                         / wscale))
  *         q_data_ptr[j] += (wscale * (w_data_ptr[j] - z))             # <<<<<<<<<<<<<<
- * 
- * 
  */
     __pyx_t_3 = __pyx_v_j;
     (__pyx_v_q_data_ptr[__pyx_t_3]) = ((__pyx_v_q_data_ptr[__pyx_t_3]) + (__pyx_v_wscale * ((__pyx_v_w_data_ptr[__pyx_v_j]) - __pyx_v_z)));
@@ -9471,6 +9592,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__dloss, __pyx_k__dloss, sizeof(__pyx_k__dloss), 0, 0, 1, 1},
   {&__pyx_n_s__dot, __pyx_k__dot, sizeof(__pyx_k__dot), 0, 0, 1, 1},
   {&__pyx_n_s__dtype, __pyx_k__dtype, sizeof(__pyx_k__dtype), 0, 0, 1, 1},
+  {&__pyx_n_s__eta0, __pyx_k__eta0, sizeof(__pyx_k__eta0), 0, 0, 1, 1},
   {&__pyx_n_s__fields, __pyx_k__fields, sizeof(__pyx_k__fields), 0, 0, 1, 1},
   {&__pyx_n_s__fit_intercept, __pyx_k__fit_intercept, sizeof(__pyx_k__fit_intercept), 0, 0, 1, 1},
   {&__pyx_n_s__float64, __pyx_k__float64, sizeof(__pyx_k__float64), 0, 0, 1, 1},
@@ -9480,6 +9602,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__isinf, __pyx_k__isinf, sizeof(__pyx_k__isinf), 0, 0, 1, 1},
   {&__pyx_n_s__isnan, __pyx_k__isnan, sizeof(__pyx_k__isnan), 0, 0, 1, 1},
   {&__pyx_n_s__itemsize, __pyx_k__itemsize, sizeof(__pyx_k__itemsize), 0, 0, 1, 1},
+  {&__pyx_n_s__learning_rate, __pyx_k__learning_rate, sizeof(__pyx_k__learning_rate), 0, 0, 1, 1},
   {&__pyx_n_s__loss, __pyx_k__loss, sizeof(__pyx_k__loss), 0, 0, 1, 1},
   {&__pyx_n_s__n_iter, __pyx_k__n_iter, sizeof(__pyx_k__n_iter), 0, 0, 1, 1},
   {&__pyx_n_s__names, __pyx_k__names, sizeof(__pyx_k__names), 0, 0, 1, 1},
@@ -9492,6 +9615,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__p, __pyx_k__p, sizeof(__pyx_k__p), 0, 0, 1, 1},
   {&__pyx_n_s__penalty_type, __pyx_k__penalty_type, sizeof(__pyx_k__penalty_type), 0, 0, 1, 1},
   {&__pyx_n_s__plain_sgd, __pyx_k__plain_sgd, sizeof(__pyx_k__plain_sgd), 0, 0, 1, 1},
+  {&__pyx_n_s__power_t, __pyx_k__power_t, sizeof(__pyx_k__power_t), 0, 0, 1, 1},
   {&__pyx_n_s__random, __pyx_k__random, sizeof(__pyx_k__random), 0, 0, 1, 1},
   {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1},
   {&__pyx_n_s__readonly, __pyx_k__readonly, sizeof(__pyx_k__readonly), 0, 0, 1, 1},
@@ -9514,8 +9638,8 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {0, 0, 0, 0, 0, 0, 0}
 };
 static int __Pyx_InitCachedBuiltins(void) {
-  __pyx_builtin_NotImplementedError = __Pyx_GetName(__pyx_b, __pyx_n_s__NotImplementedError); if (!__pyx_builtin_NotImplementedError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_NotImplementedError = __Pyx_GetName(__pyx_b, __pyx_n_s__NotImplementedError); if (!__pyx_builtin_NotImplementedError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 382; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   return 0;
@@ -9526,14 +9650,14 @@ static int __Pyx_InitCachedBuiltins(void) {
 static int __Pyx_InitCachedConstants(void) {
   __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants");
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":352
+  /* "scikits/learn/linear_model/sgd_fast.pyx":382
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \
  *            or np.isnan(intercept) or np.isinf(intercept):
  *             raise ValueError("floating-point under-/overflow occured.")             # <<<<<<<<<<<<<<
  * 
  *     w *= wscale
  */
-  __pyx_k_tuple_5 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_5 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 382; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_5));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_4));
   PyTuple_SET_ITEM(__pyx_k_tuple_5, 0, ((PyObject *)__pyx_kp_s_4));
@@ -9699,72 +9823,72 @@ PyMODINIT_FUNC PyInit_sgd_fast(void)
   __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction = &__pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_LossFunction;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_LossFunction.loss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_loss;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_LossFunction.dloss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_12LossFunction_dloss;
-  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_LossFunction) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_LossFunction.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "LossFunction", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_LossFunction) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_LossFunction) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_LossFunction.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "LossFunction", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_LossFunction) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction = &__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_LossFunction;
   __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression = &__pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Regression;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Regression.__pyx_base = *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Regression.__pyx_base.loss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_10Regression_loss;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Regression.__pyx_base.dloss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_10Regression_dloss;
   __pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Regression.tp_base = __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction;
-  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Regression) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Regression.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "Regression", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Regression) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Regression) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Regression.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Regression", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Regression) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Regression = &__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Regression;
   __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification = &__pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Classification;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Classification.__pyx_base = *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Classification.__pyx_base.loss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_14Classification_loss;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Classification.__pyx_base.dloss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_14Classification_dloss;
   __pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Classification.tp_base = __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction;
-  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Classification) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Classification.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "Classification", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Classification) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Classification) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Classification.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Classification", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Classification) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Classification = &__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Classification;
   __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber = &__pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber.__pyx_base = *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber.__pyx_base.__pyx_base.loss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_loss;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber.__pyx_base.__pyx_base.dloss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_13ModifiedHuber_dloss;
   __pyx_type_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber.tp_base = __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Classification;
-  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "ModifiedHuber", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "ModifiedHuber", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber = &__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber;
   __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Hinge = &__pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Hinge;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Hinge.__pyx_base = *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Hinge.__pyx_base.__pyx_base.loss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_loss;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Hinge.__pyx_base.__pyx_base.dloss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Hinge_dloss;
   __pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Hinge.tp_base = __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Classification;
-  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Hinge) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Hinge.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Hinge) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "Hinge", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Hinge) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Hinge) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Hinge.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Hinge) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Hinge", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Hinge) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Hinge = &__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Hinge;
   __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Log = &__pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Log;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Log.__pyx_base = *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Log.__pyx_base.__pyx_base.loss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_loss;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Log.__pyx_base.__pyx_base.dloss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_3Log_dloss;
   __pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Log.tp_base = __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Classification;
-  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Log) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Log.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Log) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "Log", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Log) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Log) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Log.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Log) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Log", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Log) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Log = &__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Log;
   __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss = &__pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss.__pyx_base = *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss.__pyx_base.__pyx_base.loss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_loss;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss.__pyx_base.__pyx_base.dloss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_11SquaredLoss_dloss;
   __pyx_type_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss.tp_base = __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Regression;
-  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "SquaredLoss", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "SquaredLoss", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss = &__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss;
   __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Huber = &__pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Huber;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Huber.__pyx_base = *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Huber.__pyx_base.__pyx_base.loss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_loss;
   __pyx_vtable_7scikits_5learn_12linear_model_8sgd_fast_Huber.__pyx_base.__pyx_base.dloss = (double (*)(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *, double, double, int __pyx_skip_dispatch))__pyx_f_7scikits_5learn_12linear_model_8sgd_fast_5Huber_dloss;
   __pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Huber.tp_base = __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Regression;
-  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Huber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Huber.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Huber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "Huber", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Huber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Huber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Huber.tp_dict, __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Huber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Huber", (PyObject *)&__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Huber) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Huber = &__pyx_type_7scikits_5learn_12linear_model_8sgd_fast_Huber;
   /*--- Type import code ---*/
   __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -9820,16 +9944,16 @@ PyMODINIT_FUNC PyInit_sgd_fast(void)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast.pyx":194
+  /* "scikits/learn/linear_model/sgd_fast.pyx":200
  * @cython.wraparound(False)
  * @cython.cdivision(True)
  * def plain_sgd(np.ndarray[np.float64_t, ndim=1, mode='c'] w,             # <<<<<<<<<<<<<<
  *               double intercept,
  *               LossFunction loss,
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd, NULL, __pyx_n_s_18); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7scikits_5learn_12linear_model_8sgd_fast_plain_sgd, NULL, __pyx_n_s_18); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__plain_sgd, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__plain_sgd, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "scikits/learn/linear_model/sgd_fast.pyx":1
diff --git a/scikits/learn/linear_model/sgd_fast.pxd b/scikits/learn/linear_model/sgd_fast.pxd
index 289104e64999be6d16cb2f5b2c3bdced97acc919..fd37774da19185c883dad24e50c7b949471f54cb 100644
--- a/scikits/learn/linear_model/sgd_fast.pxd
+++ b/scikits/learn/linear_model/sgd_fast.pxd
@@ -8,6 +8,7 @@ cdef extern from "math.h":
     cdef extern double exp(double x)
     cdef extern double log(double x)
     cdef extern double sqrt(double x)
+    cdef extern double pow(double x, double y)
 
 ctypedef np.float64_t DOUBLE
 ctypedef np.int32_t INTEGER
diff --git a/scikits/learn/linear_model/sgd_fast.pyx b/scikits/learn/linear_model/sgd_fast.pyx
index 480542d70fb5966df0e55dcead5ca1fecf287006..3bf07c3828a4eb636e854a27f71a67ad8e6b8493 100644
--- a/scikits/learn/linear_model/sgd_fast.pyx
+++ b/scikits/learn/linear_model/sgd_fast.pyx
@@ -14,10 +14,16 @@ from time import time
 cimport numpy as np
 cimport cython
 
+# Penalty constans
 DEF L1 = 1
 DEF L2 = 2
 DEF ELASTICNET = 3
 
+# Learning rate constants
+DEF CONSTANT = 1
+DEF OPTIMAL = 2
+DEF INVSCALING = 3
+
 # ----------------------------------------
 # Extension Types for Loss Functions
 # ----------------------------------------
@@ -49,10 +55,10 @@ cdef class LossFunction:
 cdef class Regression(LossFunction):
     """Base class for loss functions for regression"""
 
-    cpdef double loss(self,double p, double y):
+    cpdef double loss(self, double p, double y):
         raise NotImplementedError()
 
-    cpdef double dloss(self,double p, double y):
+    cpdef double dloss(self, double p, double y):
         raise NotImplementedError()
 
 
@@ -163,7 +169,7 @@ cdef class Huber(Regression):
     http://en.wikipedia.org/wiki/Huber_Loss_Function
     """
 
-    def __init__(self,c):
+    def __init__(self, c):
         self.c = c
 
     cpdef double loss(self, double p, double y):
@@ -185,7 +191,7 @@ cdef class Huber(Regression):
             return -self.c
 
     def __reduce__(self):
-        return Huber,(self.c,)
+        return Huber, (self.c,)
 
 
 @cython.boundscheck(False)
@@ -201,7 +207,9 @@ def plain_sgd(np.ndarray[np.float64_t, ndim=1, mode='c'] w,
               int n_iter, int fit_intercept,
               int verbose, int shuffle, int seed,
               double weight_pos, double weight_neg,
-              np.ndarray[np.float64_t, ndim=1, mode='c'] sample_weight):
+              np.ndarray[double, ndim=1] sample_weight,
+              int learning_rate, double eta0,
+              double power_t):
     """Cython impl. of SGD for generic loss functions and penalties
 
     This implementation assumes X represented as a dense array of floats.
@@ -235,21 +243,29 @@ def plain_sgd(np.ndarray[np.float64_t, ndim=1, mode='c'] w,
     weight_pos : float
         The weight of the positive class.
     weight_neg : float
-        The weight of the negative class. 
+        The weight of the negative class.
     seed : int
         The seed of the pseudo random number generator to use when
         shuffling the data
     sample_weight : array, shape = [n_samples]
         The importance weight of each sample.
+    learning_rate : int
+        The learning rate:
+        (1) constant, eta = eta0
+        (2) optimal, eta = 1.0/(t+t0)
+        (3) inverse scaling, eta = eta0 / pow(t, power_t)
+    eta0 : double
+        The initial learning rate.
+    power_t : double
+        The exponent for inverse scaling learning rate.
 
     Returns
     -------
     w : array, shape [n_features]
-        The fitted weight vector. 
+        The fitted weight vector.
     intercept : float
-        The fitted intercept term. 
+        The fitted intercept term.
 
-    
     """
 
     # get the data information into easy vars
@@ -267,8 +283,9 @@ def plain_sgd(np.ndarray[np.float64_t, ndim=1, mode='c'] w,
     cdef double *sample_weight_data = <double *>sample_weight.data
 
     # Use index array for fast shuffling
-    cdef np.ndarray[np.int32_t, ndim=1, mode="c"] index = np.arange(n_samples,
-                                                                    dtype=np.int32)
+    cdef np.ndarray[np.int32_t, ndim=1,
+                    mode="c"] index = np.arange(n_samples,
+                                                dtype=np.int32)
     cdef int *index_data_ptr = <int *>index.data
 
     # helper variable
@@ -295,12 +312,20 @@ def plain_sgd(np.ndarray[np.float64_t, ndim=1, mode='c'] w,
         q_data_ptr = <double *> q.data
     cdef double u = 0.0
 
-    # computing eta0, the initial learning rate
     cdef double typw = sqrt(1.0 / sqrt(alpha))
-    cdef double eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
 
-    # initialize the 1 / t learning rate schedule from eta0
-    t = 1.0 / (eta0 * alpha)
+    if learning_rate == OPTIMAL:
+        # computing eta0, the initial learning rate
+        eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
+    else:
+        eta = eta0
+
+    if learning_rate == OPTIMAL:
+        # initialize t such that eta at first example equals eta0
+        t = 1.0 / (eta0 * alpha)
+    else:
+        t = 1.0
+
     t_start = time()
     for epoch from 0 <= epoch < n_iter:
         if verbose > 0:
@@ -309,9 +334,14 @@ def plain_sgd(np.ndarray[np.float64_t, ndim=1, mode='c'] w,
             np.random.RandomState(seed).shuffle(index)
         for i from 0 <= i < n_samples:
             sample_idx = index_data_ptr[i]
-            offset = row_stride * sample_idx / elem_stride # row offset in elem
+
+            # row offset in elem
+            offset = row_stride * sample_idx / elem_stride
             y = Y_data_ptr[sample_idx]
-            eta = 1.0 / (alpha * t)
+            if learning_rate == OPTIMAL:
+                eta = 1.0 / (alpha * t)
+            elif learning_rate == INVSCALING:
+                eta = eta0 / pow(t, power_t)
             p = (dot(w_data_ptr, X_data_ptr, offset, n_features) * wscale
                 ) + intercept
             sumloss += loss.loss(p, y)
@@ -344,7 +374,7 @@ def plain_sgd(np.ndarray[np.float64_t, ndim=1, mode='c'] w,
                                                     w.nonzero()[0].shape[0],
                                                     intercept, count,
                                                     sumloss / count))
-            print("Total training time: %.2f seconds." % (time()-t_start))
+            print("Total training time: %.2f seconds." % (time() - t_start))
 
         # floating-point under-/overflow check.
         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \
@@ -407,10 +437,8 @@ cdef void l1penalty(double *w_data_ptr, double wscale, double *q_data_ptr,
         z = w_data_ptr[j]
         if (wscale * w_data_ptr[j]) > 0.0:
             w_data_ptr[j] = max(0.0, w_data_ptr[j] - ((u + q_data_ptr[j])
-                                                        / wscale) )
+                                                        / wscale))
         elif (wscale * w_data_ptr[j]) < 0.0:
             w_data_ptr[j] = min(0.0, w_data_ptr[j] + ((u - q_data_ptr[j])
-                                                        / wscale) )
+                                                        / wscale))
         q_data_ptr[j] += (wscale * (w_data_ptr[j] - z))
-
-
diff --git a/scikits/learn/linear_model/sgd_fast_sparse.c b/scikits/learn/linear_model/sgd_fast_sparse.c
index ec2b6a3993f605fba463c7f43e752720f37650d3..6f8364a2606fffca4de3c5d389693d0f1cdb14f7 100644
--- a/scikits/learn/linear_model/sgd_fast_sparse.c
+++ b/scikits/learn/linear_model/sgd_fast_sparse.c
@@ -1,4 +1,4 @@
-/* Generated by Cython 0.14.1 on Tue Mar 15 16:49:14 2011 */
+/* Generated by Cython 0.14.1 on Wed May  4 20:09:35 2011 */
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
@@ -403,7 +403,7 @@ typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t;
 
 typedef npy_cdouble __pyx_t_5numpy_complex_t;
 
-/* "sgd_fast.pxd":19
+/* "sgd_fast.pxd":20
  * # -----------------------------------------
  * 
  * cdef class LossFunction:             # <<<<<<<<<<<<<<
@@ -416,7 +416,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction {
   struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *__pyx_vtab;
 };
 
-/* "sgd_fast.pxd":23
+/* "sgd_fast.pxd":24
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Regression(LossFunction):             # <<<<<<<<<<<<<<
@@ -428,7 +428,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Regression {
   struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction __pyx_base;
 };
 
-/* "sgd_fast.pxd":43
+/* "sgd_fast.pxd":44
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class SquaredLoss(Regression):             # <<<<<<<<<<<<<<
@@ -440,7 +440,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss {
   struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Regression __pyx_base;
 };
 
-/* "sgd_fast.pxd":27
+/* "sgd_fast.pxd":28
  *     cpdef double dloss(self,double p, double y)
  * 
  * cdef class Classification(LossFunction):             # <<<<<<<<<<<<<<
@@ -452,7 +452,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification {
   struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction __pyx_base;
 };
 
-/* "sgd_fast.pxd":35
+/* "sgd_fast.pxd":36
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Hinge(Classification):             # <<<<<<<<<<<<<<
@@ -464,7 +464,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Hinge {
   struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification __pyx_base;
 };
 
-/* "sgd_fast.pxd":47
+/* "sgd_fast.pxd":48
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Huber(Regression):             # <<<<<<<<<<<<<<
@@ -477,7 +477,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber {
   double c;
 };
 
-/* "sgd_fast.pxd":31
+/* "sgd_fast.pxd":32
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class ModifiedHuber(Classification):             # <<<<<<<<<<<<<<
@@ -489,7 +489,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber {
   struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification __pyx_base;
 };
 
-/* "sgd_fast.pxd":39
+/* "sgd_fast.pxd":40
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Log(Classification):             # <<<<<<<<<<<<<<
@@ -502,7 +502,7 @@ struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Log {
 };
 
 
-/* "sgd_fast.pxd":19
+/* "sgd_fast.pxd":20
  * # -----------------------------------------
  * 
  * cdef class LossFunction:             # <<<<<<<<<<<<<<
@@ -517,7 +517,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction;
 
 
-/* "sgd_fast.pxd":23
+/* "sgd_fast.pxd":24
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Regression(LossFunction):             # <<<<<<<<<<<<<<
@@ -531,7 +531,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Regression {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Regression *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression;
 
 
-/* "sgd_fast.pxd":47
+/* "sgd_fast.pxd":48
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Huber(Regression):             # <<<<<<<<<<<<<<
@@ -545,7 +545,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Huber {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Huber *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Huber;
 
 
-/* "sgd_fast.pxd":27
+/* "sgd_fast.pxd":28
  *     cpdef double dloss(self,double p, double y)
  * 
  * cdef class Classification(LossFunction):             # <<<<<<<<<<<<<<
@@ -559,7 +559,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Classification
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Classification *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification;
 
 
-/* "sgd_fast.pxd":35
+/* "sgd_fast.pxd":36
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Hinge(Classification):             # <<<<<<<<<<<<<<
@@ -573,7 +573,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Hinge {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Hinge *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Hinge;
 
 
-/* "sgd_fast.pxd":39
+/* "sgd_fast.pxd":40
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class Log(Classification):             # <<<<<<<<<<<<<<
@@ -587,7 +587,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Log {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Log *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Log;
 
 
-/* "sgd_fast.pxd":31
+/* "sgd_fast.pxd":32
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class ModifiedHuber(Classification):             # <<<<<<<<<<<<<<
@@ -601,7 +601,7 @@ struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber {
 static struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber *__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber;
 
 
-/* "sgd_fast.pxd":43
+/* "sgd_fast.pxd":44
  *     cpdef double dloss(self, double p, double y)
  * 
  * cdef class SquaredLoss(Regression):             # <<<<<<<<<<<<<<
@@ -1044,6 +1044,7 @@ static char __pyx_k__rho[] = "rho";
 static char __pyx_k__sys[] = "sys";
 static char __pyx_k__base[] = "base";
 static char __pyx_k__data[] = "data";
+static char __pyx_k__eta0[] = "eta0";
 static char __pyx_k__loss[] = "loss";
 static char __pyx_k__ndim[] = "ndim";
 static char __pyx_k__seed[] = "seed";
@@ -1069,6 +1070,7 @@ static char __pyx_k__n_iter[] = "n_iter";
 static char __pyx_k__random[] = "random";
 static char __pyx_k__float64[] = "float64";
 static char __pyx_k__nonzero[] = "nonzero";
+static char __pyx_k__power_t[] = "power_t";
 static char __pyx_k__shuffle[] = "shuffle";
 static char __pyx_k__strides[] = "strides";
 static char __pyx_k__verbose[] = "verbose";
@@ -1090,6 +1092,7 @@ static char __pyx_k__RandomState[] = "RandomState";
 static char __pyx_k__RuntimeError[] = "RuntimeError";
 static char __pyx_k__penalty_type[] = "penalty_type";
 static char __pyx_k__fit_intercept[] = "fit_intercept";
+static char __pyx_k__learning_rate[] = "learning_rate";
 static char __pyx_k__sample_weight[] = "sample_weight";
 static PyObject *__pyx_kp_s_1;
 static PyObject *__pyx_kp_u_10;
@@ -1123,6 +1126,7 @@ static PyObject *__pyx_n_s__descr;
 static PyObject *__pyx_n_s__dloss;
 static PyObject *__pyx_n_s__dot;
 static PyObject *__pyx_n_s__dtype;
+static PyObject *__pyx_n_s__eta0;
 static PyObject *__pyx_n_s__fields;
 static PyObject *__pyx_n_s__fit_intercept;
 static PyObject *__pyx_n_s__float64;
@@ -1132,6 +1136,7 @@ static PyObject *__pyx_n_s__intercept;
 static PyObject *__pyx_n_s__isinf;
 static PyObject *__pyx_n_s__isnan;
 static PyObject *__pyx_n_s__itemsize;
+static PyObject *__pyx_n_s__learning_rate;
 static PyObject *__pyx_n_s__loss;
 static PyObject *__pyx_n_s__n_iter;
 static PyObject *__pyx_n_s__names;
@@ -1143,6 +1148,7 @@ static PyObject *__pyx_n_s__obj;
 static PyObject *__pyx_n_s__order;
 static PyObject *__pyx_n_s__penalty_type;
 static PyObject *__pyx_n_s__plain_sgd;
+static PyObject *__pyx_n_s__power_t;
 static PyObject *__pyx_n_s__random;
 static PyObject *__pyx_n_s__range;
 static PyObject *__pyx_n_s__readonly;
@@ -1170,7 +1176,7 @@ static PyObject *__pyx_k_tuple_14;
 static PyObject *__pyx_k_tuple_15;
 static PyObject *__pyx_k_tuple_17;
 
-/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":27
+/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":34
  * @cython.wraparound(False)
  * @cython.cdivision(True)
  * def plain_sgd(np.ndarray[double, ndim=1] w,             # <<<<<<<<<<<<<<
@@ -1179,7 +1185,7 @@ static PyObject *__pyx_k_tuple_17;
  */
 
 static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain_sgd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain_sgd[] = "Cython impl. of SGD with different loss functions and penalties\n\n    This representation assumes X represented using the Compressed Sparse Row\n    representation of scipy.sparse.\n\n    Parameters\n    ----------\n    w : ndarray[double, ndim=1]\n        The allocated coef_ vector.\n    intercept : double\n        The initial intercept\n    loss : LossFunction\n        A concrete LossFunction object.\n    penalty_type : int\n        The penalty 2 for L2, 1 for L1, and 3 for Elastic-Net.\n    alpha : float\n        The regularization parameter.\n    rho : float\n        The elastic net hyperparameter.\n    X : csr_matrix[double, ndim=2]\n        The dataset as a Compressed Sparse Row matrix \n        (see scipy.sparse.csr_matrix).\n    Y : ndarray[double, ndim=1]\n        The labels.\n    n_iter : int\n        The number of iterations (epochs).\n    fit_intercept : int\n        Whether or not to fit the intercept (1 or 0).\n    verbose : int\n        Print verbose output; 0 for quite.\n    shuffle : int\n        Whether to shuffle the training data before each epoch.\n    weight_pos : float\n        The weight of the positive class.\n    weight_neg : float\n        The weight of the negative class. \n    seed : int\n        The seed of the pseudo random number generator to use when\n        shuffling the data\n    sample_weight : array, shape = [n_samples]\n        The importance weight of each sample.\n\n    Returns\n    -------\n    w : array, shape [n_features]\n        The fitted weight vector. \n    intercept : float\n        The fitted intercept term. \n    ";
+static char __pyx_doc_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain_sgd[] = "Cython impl. of SGD with different loss functions and penalties\n\n    This representation assumes X represented using the Compressed Sparse Row\n    representation of scipy.sparse.\n\n    Parameters\n    ----------\n    w : ndarray[double, ndim=1]\n        The allocated coef_ vector.\n    intercept : double\n        The initial intercept\n    loss : LossFunction\n        A concrete LossFunction object.\n    penalty_type : int\n        The penalty 2 for L2, 1 for L1, and 3 for Elastic-Net.\n    alpha : float\n        The regularization parameter.\n    rho : float\n        The elastic net hyperparameter.\n    X : csr_matrix[double, ndim=2]\n        The dataset as a Compressed Sparse Row matrix\n        (see scipy.sparse.csr_matrix).\n    Y : ndarray[double, ndim=1]\n        The labels.\n    n_iter : int\n        The number of iterations (epochs).\n    fit_intercept : int\n        Whether or not to fit the intercept (1 or 0).\n    verbose : int\n        Print verbose output; 0 for quite.\n    shuffle : int\n        Whether to shuffle the training data before each epoch.\n    weight_pos : float\n        The weight of the positive class.\n    weight_neg : float\n        The weight of the negative class.\n    seed : int\n        The seed of the pseudo random number generator to use when\n        shuffling the data\n    sample_weight : array, shape = [n_samples]\n        The importance weight of each sample.\n    learning_rate : int\n        The learning rate:\n        (1) constant, eta = eta0\n        (2) optimal, eta = 1.0/(t+t0)\n        (3) inverse scaling, eta = eta0 / pow(t, power_t)\n    eta0 : double\n        The initial learning rate.\n    power_t : double\n        The exponent for inverse scaling learning rate.\n\n    Returns\n    -------\n    w : array, shape [n_features]\n        The fitted weight vector.\n    intercept : float\n        The fitted intercept term.\n    ";
 static PyMethodDef __pyx_mdef_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain_sgd = {__Pyx_NAMESTR("plain_sgd"), (PyCFunction)__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain_sgd, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain_sgd)};
 static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain_sgd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyArrayObject *__pyx_v_w = 0;
@@ -1200,6 +1206,9 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   double __pyx_v_weight_pos;
   double __pyx_v_weight_neg;
   PyArrayObject *__pyx_v_sample_weight = 0;
+  int __pyx_v_learning_rate;
+  double __pyx_v_eta0;
+  double __pyx_v_power_t;
   unsigned int __pyx_v_n_samples;
   unsigned int __pyx_v_n_features;
   double *__pyx_v_w_data_ptr;
@@ -1229,11 +1238,13 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   double *__pyx_v_q_data_ptr;
   double __pyx_v_u;
   double __pyx_v_typw;
-  double __pyx_v_eta0;
   PyObject *__pyx_v_t_start;
   Py_buffer __pyx_bstruct_index;
   Py_ssize_t __pyx_bstride_0_index = 0;
   Py_ssize_t __pyx_bshape_0_index = 0;
+  Py_buffer __pyx_bstruct_X_data;
+  Py_ssize_t __pyx_bstride_0_X_data = 0;
+  Py_ssize_t __pyx_bshape_0_X_data = 0;
   Py_buffer __pyx_bstruct_sample_weight;
   Py_ssize_t __pyx_bstride_0_sample_weight = 0;
   Py_ssize_t __pyx_bshape_0_sample_weight = 0;
@@ -1249,9 +1260,6 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   Py_buffer __pyx_bstruct_q;
   Py_ssize_t __pyx_bstride_0_q = 0;
   Py_ssize_t __pyx_bshape_0_q = 0;
-  Py_buffer __pyx_bstruct_X_data;
-  Py_ssize_t __pyx_bstride_0_X_data = 0;
-  Py_ssize_t __pyx_bshape_0_X_data = 0;
   Py_buffer __pyx_bstruct_w;
   Py_ssize_t __pyx_bstride_0_w = 0;
   Py_ssize_t __pyx_bshape_0_w = 0;
@@ -1277,13 +1285,16 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   int __pyx_t_19;
   int __pyx_t_20;
   int __pyx_t_21;
-  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__w,&__pyx_n_s__intercept,&__pyx_n_s__loss,&__pyx_n_s__penalty_type,&__pyx_n_s__alpha,&__pyx_n_s__rho,&__pyx_n_s__X_data,&__pyx_n_s__X_indices,&__pyx_n_s__X_indptr,&__pyx_n_s__Y,&__pyx_n_s__n_iter,&__pyx_n_s__fit_intercept,&__pyx_n_s__verbose,&__pyx_n_s__shuffle,&__pyx_n_s__seed,&__pyx_n_s__weight_pos,&__pyx_n_s__weight_neg,&__pyx_n_s__sample_weight,0};
+  static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__w,&__pyx_n_s__intercept,&__pyx_n_s__loss,&__pyx_n_s__penalty_type,&__pyx_n_s__alpha,&__pyx_n_s__rho,&__pyx_n_s__X_data,&__pyx_n_s__X_indices,&__pyx_n_s__X_indptr,&__pyx_n_s__Y,&__pyx_n_s__n_iter,&__pyx_n_s__fit_intercept,&__pyx_n_s__verbose,&__pyx_n_s__shuffle,&__pyx_n_s__seed,&__pyx_n_s__weight_pos,&__pyx_n_s__weight_neg,&__pyx_n_s__sample_weight,&__pyx_n_s__learning_rate,&__pyx_n_s__eta0,&__pyx_n_s__power_t,0};
   __Pyx_RefNannySetupContext("plain_sgd");
   __pyx_self = __pyx_self;
   if (unlikely(__pyx_kwds)) {
     Py_ssize_t kw_args = PyDict_Size(__pyx_kwds);
-    PyObject* values[18] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+    PyObject* values[21] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
     switch (PyTuple_GET_SIZE(__pyx_args)) {
+      case 21: values[20] = PyTuple_GET_ITEM(__pyx_args, 20);
+      case 20: values[19] = PyTuple_GET_ITEM(__pyx_args, 19);
+      case 19: values[18] = PyTuple_GET_ITEM(__pyx_args, 18);
       case 18: values[17] = PyTuple_GET_ITEM(__pyx_args, 17);
       case 17: values[16] = PyTuple_GET_ITEM(__pyx_args, 16);
       case 16: values[15] = PyTuple_GET_ITEM(__pyx_args, 15);
@@ -1314,151 +1325,175 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
       values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__intercept);
       if (likely(values[1])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  2:
       values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__loss);
       if (likely(values[2])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  3:
       values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__penalty_type);
       if (likely(values[3])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  4:
       values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__alpha);
       if (likely(values[4])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  5:
       values[5] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__rho);
       if (likely(values[5])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 5); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 5); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  6:
       values[6] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__X_data);
       if (likely(values[6])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 6); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 6); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  7:
       values[7] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__X_indices);
       if (likely(values[7])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 7); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 7); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  8:
       values[8] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__X_indptr);
       if (likely(values[8])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 8); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 8); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case  9:
       values[9] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__Y);
       if (likely(values[9])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 9); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 9); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 10:
       values[10] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__n_iter);
       if (likely(values[10])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 10); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 10); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 11:
       values[11] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fit_intercept);
       if (likely(values[11])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 11); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 11); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 12:
       values[12] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__verbose);
       if (likely(values[12])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 12); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 12); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 13:
       values[13] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__shuffle);
       if (likely(values[13])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 13); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 13); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 14:
       values[14] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__seed);
       if (likely(values[14])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 14); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 14); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 15:
       values[15] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__weight_pos);
       if (likely(values[15])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 15); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 15); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 16:
       values[16] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__weight_neg);
       if (likely(values[16])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 16); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 16); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
       case 17:
       values[17] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__sample_weight);
       if (likely(values[17])) kw_args--;
       else {
-        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, 17); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 17); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+      case 18:
+      values[18] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__learning_rate);
+      if (likely(values[18])) kw_args--;
+      else {
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 18); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+      case 19:
+      values[19] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__eta0);
+      if (likely(values[19])) kw_args--;
+      else {
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 19); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+      case 20:
+      values[20] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__power_t);
+      if (likely(values[20])) kw_args--;
+      else {
+        __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, 20); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     }
     if (unlikely(kw_args > 0)) {
-      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "plain_sgd") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "plain_sgd") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     }
     __pyx_v_w = ((PyArrayObject *)values[0]);
-    __pyx_v_intercept = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_intercept == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_intercept = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_intercept == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_loss = ((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)values[2]);
-    __pyx_v_penalty_type = __Pyx_PyInt_AsInt(values[3]); if (unlikely((__pyx_v_penalty_type == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_alpha = __pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_alpha == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_rho = __pyx_PyFloat_AsDouble(values[5]); if (unlikely((__pyx_v_rho == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_penalty_type = __Pyx_PyInt_AsInt(values[3]); if (unlikely((__pyx_v_penalty_type == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_alpha = __pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_alpha == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_rho = __pyx_PyFloat_AsDouble(values[5]); if (unlikely((__pyx_v_rho == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_X_data = ((PyArrayObject *)values[6]);
     __pyx_v_X_indices = ((PyArrayObject *)values[7]);
     __pyx_v_X_indptr = ((PyArrayObject *)values[8]);
     __pyx_v_Y = ((PyArrayObject *)values[9]);
-    __pyx_v_n_iter = __Pyx_PyInt_AsInt(values[10]); if (unlikely((__pyx_v_n_iter == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_fit_intercept = __Pyx_PyInt_AsInt(values[11]); if (unlikely((__pyx_v_fit_intercept == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_verbose = __Pyx_PyInt_AsInt(values[12]); if (unlikely((__pyx_v_verbose == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_shuffle = __Pyx_PyInt_AsInt(values[13]); if (unlikely((__pyx_v_shuffle == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_seed = __Pyx_PyInt_AsInt(values[14]); if (unlikely((__pyx_v_seed == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_weight_pos = __pyx_PyFloat_AsDouble(values[15]); if (unlikely((__pyx_v_weight_pos == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_weight_neg = __pyx_PyFloat_AsDouble(values[16]); if (unlikely((__pyx_v_weight_neg == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_n_iter = __Pyx_PyInt_AsInt(values[10]); if (unlikely((__pyx_v_n_iter == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_fit_intercept = __Pyx_PyInt_AsInt(values[11]); if (unlikely((__pyx_v_fit_intercept == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_verbose = __Pyx_PyInt_AsInt(values[12]); if (unlikely((__pyx_v_verbose == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_shuffle = __Pyx_PyInt_AsInt(values[13]); if (unlikely((__pyx_v_shuffle == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_seed = __Pyx_PyInt_AsInt(values[14]); if (unlikely((__pyx_v_seed == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_weight_pos = __pyx_PyFloat_AsDouble(values[15]); if (unlikely((__pyx_v_weight_pos == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_weight_neg = __pyx_PyFloat_AsDouble(values[16]); if (unlikely((__pyx_v_weight_neg == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_sample_weight = ((PyArrayObject *)values[17]);
-  } else if (PyTuple_GET_SIZE(__pyx_args) != 18) {
+    __pyx_v_learning_rate = __Pyx_PyInt_AsInt(values[18]); if (unlikely((__pyx_v_learning_rate == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_eta0 = __pyx_PyFloat_AsDouble(values[19]); if (unlikely((__pyx_v_eta0 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_power_t = __pyx_PyFloat_AsDouble(values[20]); if (unlikely((__pyx_v_power_t == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  } else if (PyTuple_GET_SIZE(__pyx_args) != 21) {
     goto __pyx_L5_argtuple_error;
   } else {
     __pyx_v_w = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 0));
-    __pyx_v_intercept = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_intercept == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_intercept = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_intercept == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_loss = ((struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)PyTuple_GET_ITEM(__pyx_args, 2));
-    __pyx_v_penalty_type = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 3)); if (unlikely((__pyx_v_penalty_type == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_alpha = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 4)); if (unlikely((__pyx_v_alpha == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_rho = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 5)); if (unlikely((__pyx_v_rho == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_penalty_type = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 3)); if (unlikely((__pyx_v_penalty_type == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_alpha = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 4)); if (unlikely((__pyx_v_alpha == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_rho = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 5)); if (unlikely((__pyx_v_rho == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_X_data = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 6));
     __pyx_v_X_indices = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 7));
     __pyx_v_X_indptr = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 8));
     __pyx_v_Y = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 9));
-    __pyx_v_n_iter = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 10)); if (unlikely((__pyx_v_n_iter == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_fit_intercept = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 11)); if (unlikely((__pyx_v_fit_intercept == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_verbose = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 12)); if (unlikely((__pyx_v_verbose == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_shuffle = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 13)); if (unlikely((__pyx_v_shuffle == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_seed = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 14)); if (unlikely((__pyx_v_seed == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_weight_pos = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 15)); if (unlikely((__pyx_v_weight_pos == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_weight_neg = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 16)); if (unlikely((__pyx_v_weight_neg == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_n_iter = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 10)); if (unlikely((__pyx_v_n_iter == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_fit_intercept = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 11)); if (unlikely((__pyx_v_fit_intercept == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_verbose = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 12)); if (unlikely((__pyx_v_verbose == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_shuffle = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 13)); if (unlikely((__pyx_v_shuffle == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_seed = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 14)); if (unlikely((__pyx_v_seed == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_weight_pos = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 15)); if (unlikely((__pyx_v_weight_pos == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_weight_neg = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 16)); if (unlikely((__pyx_v_weight_neg == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_sample_weight = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 17));
+    __pyx_v_learning_rate = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 18)); if (unlikely((__pyx_v_learning_rate == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_eta0 = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 19)); if (unlikely((__pyx_v_eta0 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_power_t = __pyx_PyFloat_AsDouble(PyTuple_GET_ITEM(__pyx_args, 20)); if (unlikely((__pyx_v_power_t == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 18, 18, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("plain_sgd", 1, 21, 21, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast_sparse.plain_sgd");
   __Pyx_RefNannyFinishContext();
@@ -1474,51 +1509,51 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   __pyx_bstruct_X_indptr.buf = NULL;
   __pyx_bstruct_Y.buf = NULL;
   __pyx_bstruct_sample_weight.buf = NULL;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_w), __pyx_ptype_5numpy_ndarray, 1, "w", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_loss), __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction, 1, "loss", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_X_data), __pyx_ptype_5numpy_ndarray, 1, "X_data", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_X_indices), __pyx_ptype_5numpy_ndarray, 1, "X_indices", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_X_indptr), __pyx_ptype_5numpy_ndarray, 1, "X_indptr", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_Y), __pyx_ptype_5numpy_ndarray, 1, "Y", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sample_weight), __pyx_ptype_5numpy_ndarray, 1, "sample_weight", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_w), __pyx_ptype_5numpy_ndarray, 1, "w", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_loss), __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction, 1, "loss", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_X_data), __pyx_ptype_5numpy_ndarray, 1, "X_data", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_X_indices), __pyx_ptype_5numpy_ndarray, 1, "X_indices", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_X_indptr), __pyx_ptype_5numpy_ndarray, 1, "X_indptr", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_Y), __pyx_ptype_5numpy_ndarray, 1, "Y", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sample_weight), __pyx_ptype_5numpy_ndarray, 1, "sample_weight", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_w, (PyObject*)__pyx_v_w, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_w, (PyObject*)__pyx_v_w, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_bstride_0_w = __pyx_bstruct_w.strides[0];
   __pyx_bshape_0_w = __pyx_bstruct_w.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_X_data, (PyObject*)__pyx_v_X_data, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_X_data, (PyObject*)__pyx_v_X_data, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_bstride_0_X_data = __pyx_bstruct_X_data.strides[0];
   __pyx_bshape_0_X_data = __pyx_bstruct_X_data.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_X_indices, (PyObject*)__pyx_v_X_indices, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_X_indices, (PyObject*)__pyx_v_X_indices, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_bstride_0_X_indices = __pyx_bstruct_X_indices.strides[0];
   __pyx_bshape_0_X_indices = __pyx_bstruct_X_indices.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_X_indptr, (PyObject*)__pyx_v_X_indptr, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_X_indptr, (PyObject*)__pyx_v_X_indptr, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_bstride_0_X_indptr = __pyx_bstruct_X_indptr.strides[0];
   __pyx_bshape_0_X_indptr = __pyx_bstruct_X_indptr.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_Y, (PyObject*)__pyx_v_Y, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_Y, (PyObject*)__pyx_v_Y, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_bstride_0_Y = __pyx_bstruct_Y.strides[0];
   __pyx_bshape_0_Y = __pyx_bstruct_Y.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_sample_weight, (PyObject*)__pyx_v_sample_weight, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_sample_weight, (PyObject*)__pyx_v_sample_weight, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_bstride_0_sample_weight = __pyx_bstruct_sample_weight.strides[0];
   __pyx_bshape_0_sample_weight = __pyx_bstruct_sample_weight.shape[0];
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":90
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":108
  *     """
  *     # get the data information into easy vars
  *     cdef unsigned int n_samples = Y.shape[0]             # <<<<<<<<<<<<<<
@@ -1527,7 +1562,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_n_samples = (__pyx_v_Y->dimensions[0]);
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":91
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":109
  *     # get the data information into easy vars
  *     cdef unsigned int n_samples = Y.shape[0]
  *     cdef unsigned int n_features = w.shape[0]             # <<<<<<<<<<<<<<
@@ -1536,7 +1571,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_n_features = (__pyx_v_w->dimensions[0]);
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":93
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":111
  *     cdef unsigned int n_features = w.shape[0]
  * 
  *     cdef double *w_data_ptr = <double *>w.data             # <<<<<<<<<<<<<<
@@ -1545,7 +1580,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_w_data_ptr = ((double *)__pyx_v_w->data);
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":94
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":112
  * 
  *     cdef double *w_data_ptr = <double *>w.data
  *     cdef double *X_data_ptr = <double *>X_data.data             # <<<<<<<<<<<<<<
@@ -1554,7 +1589,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_X_data_ptr = ((double *)__pyx_v_X_data->data);
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":95
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":113
  *     cdef double *w_data_ptr = <double *>w.data
  *     cdef double *X_data_ptr = <double *>X_data.data
  *     cdef int *X_indptr_ptr = <int *>X_indptr.data             # <<<<<<<<<<<<<<
@@ -1563,7 +1598,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_X_indptr_ptr = ((int *)__pyx_v_X_indptr->data);
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":96
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":114
  *     cdef double *X_data_ptr = <double *>X_data.data
  *     cdef int *X_indptr_ptr = <int *>X_indptr.data
  *     cdef int *X_indices_ptr = <int *>X_indices.data             # <<<<<<<<<<<<<<
@@ -1572,7 +1607,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_X_indices_ptr = ((int *)__pyx_v_X_indices->data);
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":97
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":115
  *     cdef int *X_indptr_ptr = <int *>X_indptr.data
  *     cdef int *X_indices_ptr = <int *>X_indices.data
  *     cdef double *Y_data_ptr = <double *>Y.data             # <<<<<<<<<<<<<<
@@ -1581,7 +1616,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_Y_data_ptr = ((double *)__pyx_v_Y->data);
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":99
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":117
  *     cdef double *Y_data_ptr = <double *>Y.data
  * 
  *     cdef double *sample_weight_data = <double *>sample_weight.data             # <<<<<<<<<<<<<<
@@ -1590,54 +1625,54 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_sample_weight_data = ((double *)__pyx_v_sample_weight->data);
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":101
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":119
  *     cdef double *sample_weight_data = <double *>sample_weight.data
  * 
  *     cdef np.ndarray[int, ndim=1, mode="c"] index = np.arange(n_samples,             # <<<<<<<<<<<<<<
- *                                                              dtype = np.int32)
+ *                                                              dtype=np.int32)
  *     cdef int *index_data_ptr = <int *>index.data
  */
-  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__arange); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__arange); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n_samples); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_n_samples); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_3));
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":102
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":120
  * 
  *     cdef np.ndarray[int, ndim=1, mode="c"] index = np.arange(n_samples,
- *                                                              dtype = np.int32)             # <<<<<<<<<<<<<<
+ *                                                              dtype=np.int32)             # <<<<<<<<<<<<<<
  *     cdef int *index_data_ptr = <int *>index.data
  *     cdef int offset = 0
  */
-  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__int32); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__int32); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, ((PyObject *)__pyx_t_3), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
     if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_index, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
       __pyx_v_index = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_index.buf = NULL;
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     } else {__pyx_bstride_0_index = __pyx_bstruct_index.strides[0];
       __pyx_bshape_0_index = __pyx_bstruct_index.shape[0];
     }
@@ -1646,17 +1681,17 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   __pyx_v_index = ((PyArrayObject *)__pyx_t_5);
   __pyx_t_5 = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":103
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":121
  *     cdef np.ndarray[int, ndim=1, mode="c"] index = np.arange(n_samples,
- *                                                              dtype = np.int32)
+ *                                                              dtype=np.int32)
  *     cdef int *index_data_ptr = <int *>index.data             # <<<<<<<<<<<<<<
  *     cdef int offset = 0
  *     cdef int xnnz = 0
  */
   __pyx_v_index_data_ptr = ((int *)__pyx_v_index->data);
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":104
- *                                                              dtype = np.int32)
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":122
+ *                                                              dtype=np.int32)
  *     cdef int *index_data_ptr = <int *>index.data
  *     cdef int offset = 0             # <<<<<<<<<<<<<<
  *     cdef int xnnz = 0
@@ -1664,7 +1699,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_offset = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":105
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":123
  *     cdef int *index_data_ptr = <int *>index.data
  *     cdef int offset = 0
  *     cdef int xnnz = 0             # <<<<<<<<<<<<<<
@@ -1673,7 +1708,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_xnnz = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":106
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":124
  *     cdef int offset = 0
  *     cdef int xnnz = 0
  *     cdef double wscale = 1.0             # <<<<<<<<<<<<<<
@@ -1682,7 +1717,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_wscale = 1.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":107
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":125
  *     cdef int xnnz = 0
  *     cdef double wscale = 1.0
  *     cdef double eta = 0.0             # <<<<<<<<<<<<<<
@@ -1691,7 +1726,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_eta = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":108
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":126
  *     cdef double wscale = 1.0
  *     cdef double eta = 0.0
  *     cdef double p = 0.0             # <<<<<<<<<<<<<<
@@ -1700,7 +1735,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_p = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":109
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":127
  *     cdef double eta = 0.0
  *     cdef double p = 0.0
  *     cdef double update = 0.0             # <<<<<<<<<<<<<<
@@ -1709,7 +1744,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_update = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":110
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":128
  *     cdef double p = 0.0
  *     cdef double update = 0.0
  *     cdef double sumloss = 0.0             # <<<<<<<<<<<<<<
@@ -1718,7 +1753,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_sumloss = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":111
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":129
  *     cdef double update = 0.0
  *     cdef double sumloss = 0.0
  *     cdef double wnorm = 0.0             # <<<<<<<<<<<<<<
@@ -1727,7 +1762,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_wnorm = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":112
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":130
  *     cdef double sumloss = 0.0
  *     cdef double wnorm = 0.0
  *     cdef double t = 0.0             # <<<<<<<<<<<<<<
@@ -1736,7 +1771,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_t = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":113
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":131
  *     cdef double wnorm = 0.0
  *     cdef double t = 0.0
  *     cdef double y = 0.0             # <<<<<<<<<<<<<<
@@ -1745,7 +1780,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_y = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":114
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":132
  *     cdef double t = 0.0
  *     cdef double y = 0.0
  *     cdef double class_weight = 1.0             # <<<<<<<<<<<<<<
@@ -1754,7 +1789,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_class_weight = 1.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":115
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":133
  *     cdef double y = 0.0
  *     cdef double class_weight = 1.0
  *     cdef unsigned int count = 0             # <<<<<<<<<<<<<<
@@ -1763,7 +1798,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_count = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":116
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":134
  *     cdef double class_weight = 1.0
  *     cdef unsigned int count = 0
  *     cdef unsigned int epoch = 0             # <<<<<<<<<<<<<<
@@ -1772,7 +1807,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_epoch = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":117
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":135
  *     cdef unsigned int count = 0
  *     cdef unsigned int epoch = 0
  *     cdef unsigned int i = 0             # <<<<<<<<<<<<<<
@@ -1781,7 +1816,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_i = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":118
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":136
  *     cdef unsigned int epoch = 0
  *     cdef unsigned int i = 0
  *     cdef int sample_idx = 0             # <<<<<<<<<<<<<<
@@ -1790,7 +1825,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
   __pyx_v_sample_idx = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":119
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":137
  *     cdef unsigned int i = 0
  *     cdef int sample_idx = 0
  *     cdef np.ndarray[double, ndim=1, mode="c"] q = None             # <<<<<<<<<<<<<<
@@ -1802,7 +1837,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
     __Pyx_BufFmt_StackElem __pyx_stack[1];
     if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_q, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
       __pyx_v_q = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_q.buf = NULL;
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     } else {__pyx_bstride_0_q = __pyx_bstruct_q.strides[0];
       __pyx_bshape_0_q = __pyx_bstruct_q.shape[0];
     }
@@ -1811,56 +1846,56 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   __Pyx_INCREF(Py_None);
   __pyx_v_q = ((PyArrayObject *)Py_None);
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":121
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":139
  *     cdef np.ndarray[double, ndim=1, mode="c"] q = None
  *     cdef double *q_data_ptr
  *     if penalty_type != L2:             # <<<<<<<<<<<<<<
- *         q = np.zeros((n_features,), dtype = np.float64, order = "c")
+ *         q = np.zeros((n_features,), dtype=np.float64, order="c")
  *         q_data_ptr = <double *> q.data
  */
   __pyx_t_8 = (__pyx_v_penalty_type != 2);
   if (__pyx_t_8) {
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":122
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":140
  *     cdef double *q_data_ptr
  *     if penalty_type != L2:
- *         q = np.zeros((n_features,), dtype = np.float64, order = "c")             # <<<<<<<<<<<<<<
+ *         q = np.zeros((n_features,), dtype=np.float64, order="c")             # <<<<<<<<<<<<<<
  *         q_data_ptr = <double *> q.data
  *     cdef double u = 0.0
  */
-    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n_features); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_n_features); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_3));
     PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
     __Pyx_GIVEREF(__pyx_t_5);
     __pyx_t_5 = 0;
-    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_5));
     PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_t_3));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_3));
     __pyx_t_3 = 0;
-    __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-    __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__float64); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__float64); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__order), ((PyObject *)__pyx_n_s__c)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_5), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__order), ((PyObject *)__pyx_n_s__c)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, ((PyObject *)__pyx_t_5), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_t_7 = ((PyArrayObject *)__pyx_t_4);
     {
       __Pyx_BufFmt_StackElem __pyx_stack[1];
@@ -1877,79 +1912,127 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
       }
       __pyx_bstride_0_q = __pyx_bstruct_q.strides[0];
       __pyx_bshape_0_q = __pyx_bstruct_q.shape[0];
-      if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
     __pyx_t_7 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_v_q));
     __pyx_v_q = ((PyArrayObject *)__pyx_t_4);
     __pyx_t_4 = 0;
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":123
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":141
  *     if penalty_type != L2:
- *         q = np.zeros((n_features,), dtype = np.float64, order = "c")
+ *         q = np.zeros((n_features,), dtype=np.float64, order="c")
  *         q_data_ptr = <double *> q.data             # <<<<<<<<<<<<<<
  *     cdef double u = 0.0
- *     # computing eta0
+ *     cdef double typw = sqrt(1.0 / sqrt(alpha))
  */
     __pyx_v_q_data_ptr = ((double *)__pyx_v_q->data);
     goto __pyx_L6;
   }
   __pyx_L6:;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":124
- *         q = np.zeros((n_features,), dtype = np.float64, order = "c")
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":142
+ *         q = np.zeros((n_features,), dtype=np.float64, order="c")
  *         q_data_ptr = <double *> q.data
  *     cdef double u = 0.0             # <<<<<<<<<<<<<<
- *     # computing eta0
  *     cdef double typw = sqrt(1.0 / sqrt(alpha))
+ * 
  */
   __pyx_v_u = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":126
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":143
+ *         q_data_ptr = <double *> q.data
  *     cdef double u = 0.0
- *     # computing eta0
  *     cdef double typw = sqrt(1.0 / sqrt(alpha))             # <<<<<<<<<<<<<<
- *     cdef double eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
- *     t = 1.0 / (eta0 * alpha)
+ * 
+ *     if learning_rate == OPTIMAL:
  */
   __pyx_v_typw = sqrt((1.0 / sqrt(__pyx_v_alpha)));
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":127
- *     # computing eta0
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":145
  *     cdef double typw = sqrt(1.0 / sqrt(alpha))
- *     cdef double eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))             # <<<<<<<<<<<<<<
- *     t = 1.0 / (eta0 * alpha)
- *     t_start = time()
+ * 
+ *     if learning_rate == OPTIMAL:             # <<<<<<<<<<<<<<
+ *         # computing eta0, the initial learning rate
+ *         eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
+ */
+  __pyx_t_8 = (__pyx_v_learning_rate == 2);
+  if (__pyx_t_8) {
+
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":147
+ *     if learning_rate == OPTIMAL:
+ *         # computing eta0, the initial learning rate
+ *         eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))             # <<<<<<<<<<<<<<
+ *     else:
+ *         eta = eta0
  */
-  __pyx_v_eta0 = (__pyx_v_typw / __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_max(1.0, ((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_loss->__pyx_vtab)->dloss(__pyx_v_loss, (-__pyx_v_typw), 1.0, 0)));
+    __pyx_v_eta0 = (__pyx_v_typw / __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_max(1.0, ((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_loss->__pyx_vtab)->dloss(__pyx_v_loss, (-__pyx_v_typw), 1.0, 0)));
+    goto __pyx_L7;
+  }
+  /*else*/ {
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":128
- *     cdef double typw = sqrt(1.0 / sqrt(alpha))
- *     cdef double eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
- *     t = 1.0 / (eta0 * alpha)             # <<<<<<<<<<<<<<
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":149
+ *         eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
+ *     else:
+ *         eta = eta0             # <<<<<<<<<<<<<<
+ * 
+ *     if learning_rate == OPTIMAL:
+ */
+    __pyx_v_eta = __pyx_v_eta0;
+  }
+  __pyx_L7:;
+
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":151
+ *         eta = eta0
+ * 
+ *     if learning_rate == OPTIMAL:             # <<<<<<<<<<<<<<
+ *         # initialize t such that eta at first example equals eta0
+ *         t = 1.0 / (eta0 * alpha)
+ */
+  __pyx_t_8 = (__pyx_v_learning_rate == 2);
+  if (__pyx_t_8) {
+
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":153
+ *     if learning_rate == OPTIMAL:
+ *         # initialize t such that eta at first example equals eta0
+ *         t = 1.0 / (eta0 * alpha)             # <<<<<<<<<<<<<<
+ *     else:
+ *         t = 1.0
+ */
+    __pyx_v_t = (1.0 / (__pyx_v_eta0 * __pyx_v_alpha));
+    goto __pyx_L8;
+  }
+  /*else*/ {
+
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":155
+ *         t = 1.0 / (eta0 * alpha)
+ *     else:
+ *         t = 1.0             # <<<<<<<<<<<<<<
+ * 
  *     t_start = time()
- *     for epoch from 0 <= epoch < n_iter:
  */
-  __pyx_v_t = (1.0 / (__pyx_v_eta0 * __pyx_v_alpha));
+    __pyx_v_t = 1.0;
+  }
+  __pyx_L8:;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":129
- *     cdef double eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
- *     t = 1.0 / (eta0 * alpha)
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":157
+ *         t = 1.0
+ * 
  *     t_start = time()             # <<<<<<<<<<<<<<
  *     for epoch from 0 <= epoch < n_iter:
  *         if verbose > 0:
  */
-  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__time); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__time); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_v_t_start);
   __pyx_v_t_start = __pyx_t_3;
   __pyx_t_3 = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":130
- *     t = 1.0 / (eta0 * alpha)
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":158
+ * 
  *     t_start = time()
  *     for epoch from 0 <= epoch < n_iter:             # <<<<<<<<<<<<<<
  *         if verbose > 0:
@@ -1958,7 +2041,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   __pyx_t_9 = __pyx_v_n_iter;
   for (__pyx_v_epoch = 0; __pyx_v_epoch < __pyx_t_9; __pyx_v_epoch++) {
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":131
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":159
  *     t_start = time()
  *     for epoch from 0 <= epoch < n_iter:
  *         if verbose > 0:             # <<<<<<<<<<<<<<
@@ -1968,25 +2051,25 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
     __pyx_t_8 = (__pyx_v_verbose > 0);
     if (__pyx_t_8) {
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":132
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":160
  *     for epoch from 0 <= epoch < n_iter:
  *         if verbose > 0:
  *             print("-- Epoch %d" % (epoch + 1))             # <<<<<<<<<<<<<<
  *         if shuffle:
  *             np.random.RandomState(seed).shuffle(index)
  */
-      __pyx_t_3 = PyInt_FromLong((__pyx_v_epoch + 1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong((__pyx_v_epoch + 1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_1), __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_1), __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_4)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_4)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      goto __pyx_L9;
+      goto __pyx_L11;
     }
-    __pyx_L9:;
+    __pyx_L11:;
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":133
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":161
  *         if verbose > 0:
  *             print("-- Epoch %d" % (epoch + 1))
  *         if shuffle:             # <<<<<<<<<<<<<<
@@ -1995,50 +2078,50 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
     if (__pyx_v_shuffle) {
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":134
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":162
  *             print("-- Epoch %d" % (epoch + 1))
  *         if shuffle:
  *             np.random.RandomState(seed).shuffle(index)             # <<<<<<<<<<<<<<
  *         for i from 0 <= i < n_samples:
  *             sample_idx = index_data_ptr[i]
  */
-      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_3 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__random); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__random); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__RandomState); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__RandomState); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = PyInt_FromLong(__pyx_v_seed); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(__pyx_v_seed); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_5));
       PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3);
       __Pyx_GIVEREF(__pyx_t_3);
       __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
-      __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__shuffle); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__shuffle); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_3));
       __Pyx_INCREF(((PyObject *)__pyx_v_index));
       PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_v_index));
       __Pyx_GIVEREF(((PyObject *)__pyx_v_index));
-      __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      goto __pyx_L10;
+      goto __pyx_L12;
     }
-    __pyx_L10:;
+    __pyx_L12:;
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":135
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":163
  *         if shuffle:
  *             np.random.RandomState(seed).shuffle(index)
  *         for i from 0 <= i < n_samples:             # <<<<<<<<<<<<<<
@@ -2048,7 +2131,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
     __pyx_t_13 = __pyx_v_n_samples;
     for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_13; __pyx_v_i++) {
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":136
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":164
  *             np.random.RandomState(seed).shuffle(index)
  *         for i from 0 <= i < n_samples:
  *             sample_idx = index_data_ptr[i]             # <<<<<<<<<<<<<<
@@ -2057,7 +2140,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
       __pyx_v_sample_idx = (__pyx_v_index_data_ptr[__pyx_v_i]);
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":137
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":165
  *         for i from 0 <= i < n_samples:
  *             sample_idx = index_data_ptr[i]
  *             offset = X_indptr_ptr[sample_idx]             # <<<<<<<<<<<<<<
@@ -2066,35 +2149,74 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
       __pyx_v_offset = (__pyx_v_X_indptr_ptr[__pyx_v_sample_idx]);
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":138
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":166
  *             sample_idx = index_data_ptr[i]
  *             offset = X_indptr_ptr[sample_idx]
  *             xnnz = X_indptr_ptr[sample_idx + 1] - offset             # <<<<<<<<<<<<<<
  *             y = Y_data_ptr[sample_idx]
- *             eta = 1.0 / (alpha * t)
+ *             if learning_rate == OPTIMAL:
  */
       __pyx_v_xnnz = ((__pyx_v_X_indptr_ptr[(__pyx_v_sample_idx + 1)]) - __pyx_v_offset);
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":139
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":167
  *             offset = X_indptr_ptr[sample_idx]
  *             xnnz = X_indptr_ptr[sample_idx + 1] - offset
  *             y = Y_data_ptr[sample_idx]             # <<<<<<<<<<<<<<
- *             eta = 1.0 / (alpha * t)
- *             p = (dot(w_data_ptr, X_data_ptr, X_indices_ptr,
+ *             if learning_rate == OPTIMAL:
+ *                 eta = 1.0 / (alpha * t)
  */
       __pyx_v_y = (__pyx_v_Y_data_ptr[__pyx_v_sample_idx]);
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":140
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":170
+ *             if learning_rate == OPTIMAL:
+ *                 eta = 1.0 / (alpha * t)
+ *             elif learning_rate == INVSCALING:             # <<<<<<<<<<<<<<
+ *                 eta = eta0 / pow(t, power_t)
+ *             p = (dot(w_data_ptr, X_data_ptr, X_indices_ptr,
+ */
+      switch (__pyx_v_learning_rate) {
+
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":168
  *             xnnz = X_indptr_ptr[sample_idx + 1] - offset
  *             y = Y_data_ptr[sample_idx]
- *             eta = 1.0 / (alpha * t)             # <<<<<<<<<<<<<<
+ *             if learning_rate == OPTIMAL:             # <<<<<<<<<<<<<<
+ *                 eta = 1.0 / (alpha * t)
+ *             elif learning_rate == INVSCALING:
+ */
+        case 2:
+
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":169
+ *             y = Y_data_ptr[sample_idx]
+ *             if learning_rate == OPTIMAL:
+ *                 eta = 1.0 / (alpha * t)             # <<<<<<<<<<<<<<
+ *             elif learning_rate == INVSCALING:
+ *                 eta = eta0 / pow(t, power_t)
+ */
+        __pyx_v_eta = (1.0 / (__pyx_v_alpha * __pyx_v_t));
+        break;
+
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":170
+ *             if learning_rate == OPTIMAL:
+ *                 eta = 1.0 / (alpha * t)
+ *             elif learning_rate == INVSCALING:             # <<<<<<<<<<<<<<
+ *                 eta = eta0 / pow(t, power_t)
+ *             p = (dot(w_data_ptr, X_data_ptr, X_indices_ptr,
+ */
+        case 3:
+
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":171
+ *                 eta = 1.0 / (alpha * t)
+ *             elif learning_rate == INVSCALING:
+ *                 eta = eta0 / pow(t, power_t)             # <<<<<<<<<<<<<<
  *             p = (dot(w_data_ptr, X_data_ptr, X_indices_ptr,
  *                      offset, xnnz) * wscale) + intercept
  */
-      __pyx_v_eta = (1.0 / (__pyx_v_alpha * __pyx_v_t));
+        __pyx_v_eta = (__pyx_v_eta0 / pow(__pyx_v_t, __pyx_v_power_t));
+        break;
+      }
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":142
- *             eta = 1.0 / (alpha * t)
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":173
+ *                 eta = eta0 / pow(t, power_t)
  *             p = (dot(w_data_ptr, X_data_ptr, X_indices_ptr,
  *                      offset, xnnz) * wscale) + intercept             # <<<<<<<<<<<<<<
  *             sumloss += loss.loss(p, y)
@@ -2102,7 +2224,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
       __pyx_v_p = ((__pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_dot(__pyx_v_w_data_ptr, __pyx_v_X_data_ptr, __pyx_v_X_indices_ptr, __pyx_v_offset, __pyx_v_xnnz) * __pyx_v_wscale) + __pyx_v_intercept);
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":143
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":174
  *             p = (dot(w_data_ptr, X_data_ptr, X_indices_ptr,
  *                      offset, xnnz) * wscale) + intercept
  *             sumloss += loss.loss(p, y)             # <<<<<<<<<<<<<<
@@ -2111,7 +2233,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
       __pyx_v_sumloss = (__pyx_v_sumloss + ((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_loss->__pyx_vtab)->loss(__pyx_v_loss, __pyx_v_p, __pyx_v_y, 0));
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":144
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":175
  *                      offset, xnnz) * wscale) + intercept
  *             sumloss += loss.loss(p, y)
  *             if y > 0:             # <<<<<<<<<<<<<<
@@ -2121,7 +2243,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
       __pyx_t_8 = (__pyx_v_y > 0.0);
       if (__pyx_t_8) {
 
-        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":145
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":176
  *             sumloss += loss.loss(p, y)
  *             if y > 0:
  *                 class_weight = weight_pos             # <<<<<<<<<<<<<<
@@ -2129,11 +2251,11 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  *                 class_weight = weight_neg
  */
         __pyx_v_class_weight = __pyx_v_weight_pos;
-        goto __pyx_L13;
+        goto __pyx_L15;
       }
       /*else*/ {
 
-        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":147
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":178
  *                 class_weight = weight_pos
  *             else:
  *                 class_weight = weight_neg             # <<<<<<<<<<<<<<
@@ -2142,9 +2264,9 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
         __pyx_v_class_weight = __pyx_v_weight_neg;
       }
-      __pyx_L13:;
+      __pyx_L15:;
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":149
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":180
  *                 class_weight = weight_neg
  *             update = eta * loss.dloss(p, y) * class_weight * \
  *                 sample_weight_data[sample_idx]             # <<<<<<<<<<<<<<
@@ -2153,7 +2275,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
       __pyx_v_update = (((__pyx_v_eta * ((struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction *)__pyx_v_loss->__pyx_vtab)->dloss(__pyx_v_loss, __pyx_v_p, __pyx_v_y, 0)) * __pyx_v_class_weight) * (__pyx_v_sample_weight_data[__pyx_v_sample_idx]));
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":150
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":181
  *             update = eta * loss.dloss(p, y) * class_weight * \
  *                 sample_weight_data[sample_idx]
  *             if update != 0.0:             # <<<<<<<<<<<<<<
@@ -2163,7 +2285,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
       __pyx_t_8 = (__pyx_v_update != 0.0);
       if (__pyx_t_8) {
 
-        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":152
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":183
  *             if update != 0.0:
  *                 add(w_data_ptr, wscale, X_data_ptr, X_indices_ptr,
  *                     offset, xnnz, update)             # <<<<<<<<<<<<<<
@@ -2172,7 +2294,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
         __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(__pyx_v_w_data_ptr, __pyx_v_wscale, __pyx_v_X_data_ptr, __pyx_v_X_indices_ptr, __pyx_v_offset, __pyx_v_xnnz, __pyx_v_update);
 
-        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":153
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":184
  *                 add(w_data_ptr, wscale, X_data_ptr, X_indices_ptr,
  *                     offset, xnnz, update)
  *                 if fit_intercept == 1:             # <<<<<<<<<<<<<<
@@ -2182,7 +2304,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
         __pyx_t_8 = (__pyx_v_fit_intercept == 1);
         if (__pyx_t_8) {
 
-          /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":154
+          /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":185
  *                     offset, xnnz, update)
  *                 if fit_intercept == 1:
  *                     intercept += update * 0.01             # <<<<<<<<<<<<<<
@@ -2190,14 +2312,14 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  *                 wscale *= (1.0 - (rho * eta * alpha))
  */
           __pyx_v_intercept = (__pyx_v_intercept + (__pyx_v_update * 0.01));
-          goto __pyx_L15;
+          goto __pyx_L17;
         }
-        __pyx_L15:;
-        goto __pyx_L14;
+        __pyx_L17:;
+        goto __pyx_L16;
       }
-      __pyx_L14:;
+      __pyx_L16:;
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":155
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":186
  *                 if fit_intercept == 1:
  *                     intercept += update * 0.01
  *             if penalty_type != L1:             # <<<<<<<<<<<<<<
@@ -2207,7 +2329,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
       __pyx_t_8 = (__pyx_v_penalty_type != 1);
       if (__pyx_t_8) {
 
-        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":156
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":187
  *                     intercept += update * 0.01
  *             if penalty_type != L1:
  *                 wscale *= (1.0 - (rho * eta * alpha))             # <<<<<<<<<<<<<<
@@ -2216,7 +2338,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
         __pyx_v_wscale = (__pyx_v_wscale * (1.0 - ((__pyx_v_rho * __pyx_v_eta) * __pyx_v_alpha)));
 
-        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":157
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":188
  *             if penalty_type != L1:
  *                 wscale *= (1.0 - (rho * eta * alpha))
  *                 if wscale < 1e-9:             # <<<<<<<<<<<<<<
@@ -2226,19 +2348,19 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
         __pyx_t_8 = (__pyx_v_wscale < 1e-9);
         if (__pyx_t_8) {
 
-          /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":158
+          /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":189
  *                 wscale *= (1.0 - (rho * eta * alpha))
  *                 if wscale < 1e-9:
  *                     w *= wscale             # <<<<<<<<<<<<<<
  *                     wscale = 1.0
  *             if penalty_type == L1 or penalty_type == ELASTICNET:
  */
-          __pyx_t_4 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_4 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_3 = PyNumber_InPlaceMultiply(((PyObject *)__pyx_v_w), __pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PyNumber_InPlaceMultiply(((PyObject *)__pyx_v_w), __pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_3);
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __pyx_t_14 = ((PyArrayObject *)__pyx_t_3);
           {
             __Pyx_BufFmt_StackElem __pyx_stack[1];
@@ -2255,14 +2377,14 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
             }
             __pyx_bstride_0_w = __pyx_bstruct_w.strides[0];
             __pyx_bshape_0_w = __pyx_bstruct_w.shape[0];
-            if (unlikely(__pyx_t_15 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            if (unlikely(__pyx_t_15 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           }
           __pyx_t_14 = 0;
           __Pyx_DECREF(((PyObject *)__pyx_v_w));
           __pyx_v_w = ((PyArrayObject *)__pyx_t_3);
           __pyx_t_3 = 0;
 
-          /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":159
+          /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":190
  *                 if wscale < 1e-9:
  *                     w *= wscale
  *                     wscale = 1.0             # <<<<<<<<<<<<<<
@@ -2270,14 +2392,14 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  *                 u += ((1.0 - rho) * eta * alpha)
  */
           __pyx_v_wscale = 1.0;
-          goto __pyx_L17;
+          goto __pyx_L19;
         }
-        __pyx_L17:;
-        goto __pyx_L16;
+        __pyx_L19:;
+        goto __pyx_L18;
       }
-      __pyx_L16:;
+      __pyx_L18:;
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":160
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":191
  *                     w *= wscale
  *                     wscale = 1.0
  *             if penalty_type == L1 or penalty_type == ELASTICNET:             # <<<<<<<<<<<<<<
@@ -2288,7 +2410,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
         case 1:
         case 3:
 
-        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":161
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":192
  *                     wscale = 1.0
  *             if penalty_type == L1 or penalty_type == ELASTICNET:
  *                 u += ((1.0 - rho) * eta * alpha)             # <<<<<<<<<<<<<<
@@ -2297,7 +2419,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
         __pyx_v_u = (__pyx_v_u + (((1.0 - __pyx_v_rho) * __pyx_v_eta) * __pyx_v_alpha));
 
-        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":163
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":194
  *                 u += ((1.0 - rho) * eta * alpha)
  *                 l1penalty(w_data_ptr, wscale, q_data_ptr,
  *                           X_indices_ptr, offset, xnnz, u)             # <<<<<<<<<<<<<<
@@ -2308,7 +2430,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
         break;
       }
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":164
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":195
  *                 l1penalty(w_data_ptr, wscale, q_data_ptr,
  *                           X_indices_ptr, offset, xnnz, u)
  *             t += 1             # <<<<<<<<<<<<<<
@@ -2317,7 +2439,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  */
       __pyx_v_t = (__pyx_v_t + 1.0);
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":165
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":196
  *                           X_indices_ptr, offset, xnnz, u)
  *             t += 1
  *             count += 1             # <<<<<<<<<<<<<<
@@ -2327,7 +2449,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
       __pyx_v_count = (__pyx_v_count + 1);
     }
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":168
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":199
  * 
  *         # report epoche information
  *         if verbose > 0:             # <<<<<<<<<<<<<<
@@ -2337,19 +2459,19 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
     __pyx_t_8 = (__pyx_v_verbose > 0);
     if (__pyx_t_8) {
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":169
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":200
  *         # report epoche information
  *         if verbose > 0:
  *             wnorm = sqrt(np.dot(w, w) * wscale * wscale)             # <<<<<<<<<<<<<<
  *             print("Norm: %.2f, NNZs: %d, "\
  *             "Bias: %.6f, T: %d, Avg. loss: %.6f" % (wnorm,
  */
-      __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__dot); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__dot); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_3));
       __Pyx_INCREF(((PyObject *)__pyx_v_w));
       PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_v_w));
@@ -2357,80 +2479,80 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
       __Pyx_INCREF(((PyObject *)__pyx_v_w));
       PyTuple_SET_ITEM(__pyx_t_3, 1, ((PyObject *)__pyx_v_w));
       __Pyx_GIVEREF(((PyObject *)__pyx_v_w));
-      __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyNumber_Multiply(__pyx_t_5, __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyNumber_Multiply(__pyx_t_5, __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = PyNumber_Multiply(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyNumber_Multiply(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_16 = __pyx_PyFloat_AsDouble(__pyx_t_5); if (unlikely((__pyx_t_16 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_16 = __pyx_PyFloat_AsDouble(__pyx_t_5); if (unlikely((__pyx_t_16 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __pyx_v_wnorm = sqrt(__pyx_t_16);
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":171
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":202
  *             wnorm = sqrt(np.dot(w, w) * wscale * wscale)
  *             print("Norm: %.2f, NNZs: %d, "\
  *             "Bias: %.6f, T: %d, Avg. loss: %.6f" % (wnorm,             # <<<<<<<<<<<<<<
  *                                                     w.nonzero()[0].shape[0],
  *                                                     intercept, count,
  */
-      __pyx_t_5 = PyFloat_FromDouble(__pyx_v_wnorm); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyFloat_FromDouble(__pyx_v_wnorm); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":172
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":203
  *             print("Norm: %.2f, NNZs: %d, "\
  *             "Bias: %.6f, T: %d, Avg. loss: %.6f" % (wnorm,
  *                                                     w.nonzero()[0].shape[0],             # <<<<<<<<<<<<<<
  *                                                     intercept, count,
  *                                                     sumloss / count))
  */
-      __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_w), __pyx_n_s__nonzero); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_w), __pyx_n_s__nonzero); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_4, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_4, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__shape); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__shape); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_4, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_4, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":173
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":204
  *             "Bias: %.6f, T: %d, Avg. loss: %.6f" % (wnorm,
  *                                                     w.nonzero()[0].shape[0],
  *                                                     intercept, count,             # <<<<<<<<<<<<<<
  *                                                     sumloss / count))
- *             print("Total training time: %.2f seconds." % (time()-t_start))
+ *             print("Total training time: %.2f seconds." % (time() - t_start))
  */
-      __pyx_t_4 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_count); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_count); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":174
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":205
  *                                                     w.nonzero()[0].shape[0],
  *                                                     intercept, count,
  *                                                     sumloss / count))             # <<<<<<<<<<<<<<
- *             print("Total training time: %.2f seconds." % (time()-t_start))
+ *             print("Total training time: %.2f seconds." % (time() - t_start))
  * 
  */
-      __pyx_t_2 = PyFloat_FromDouble((__pyx_v_sumloss / __pyx_v_count)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyFloat_FromDouble((__pyx_v_sumloss / __pyx_v_count)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_17 = PyTuple_New(5); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_17 = PyTuple_New(5); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_17));
       PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_5);
       __Pyx_GIVEREF(__pyx_t_5);
@@ -2447,165 +2569,165 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
       __pyx_t_4 = 0;
       __pyx_t_1 = 0;
       __pyx_t_2 = 0;
-      __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_2), ((PyObject *)__pyx_t_17)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_2), ((PyObject *)__pyx_t_17)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_2));
       __Pyx_DECREF(((PyObject *)__pyx_t_17)); __pyx_t_17 = 0;
-      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_2)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_2)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":175
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":206
  *                                                     intercept, count,
  *                                                     sumloss / count))
- *             print("Total training time: %.2f seconds." % (time()-t_start))             # <<<<<<<<<<<<<<
+ *             print("Total training time: %.2f seconds." % (time() - t_start))             # <<<<<<<<<<<<<<
  * 
  *         # floating-point under-/overflow check.
  */
-      __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__time); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__time); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_17 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_17 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_17);
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_t_2 = PyNumber_Subtract(__pyx_t_17, __pyx_v_t_start); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyNumber_Subtract(__pyx_t_17, __pyx_v_t_start); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
       __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
-      __pyx_t_17 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_3), __pyx_t_2); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_17 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_3), __pyx_t_2); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_17));
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_17)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_PrintOne(0, ((PyObject *)__pyx_t_17)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(((PyObject *)__pyx_t_17)); __pyx_t_17 = 0;
-      goto __pyx_L18;
+      goto __pyx_L20;
     }
-    __pyx_L18:;
+    __pyx_L20:;
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":178
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":209
  * 
  *         # floating-point under-/overflow check.
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \             # <<<<<<<<<<<<<<
  *            or np.isnan(intercept) or np.isinf(intercept):
  *             raise ValueError("floating-point under-/overflow occured.")
  */
-    __pyx_t_17 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_17 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_17);
-    __pyx_t_2 = PyObject_GetAttr(__pyx_t_17, __pyx_n_s__any); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyObject_GetAttr(__pyx_t_17, __pyx_n_s__any); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
-    __pyx_t_17 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_17 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_17);
-    __pyx_t_1 = PyObject_GetAttr(__pyx_t_17, __pyx_n_s__isinf); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_17, __pyx_n_s__isinf); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
-    __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_17));
     __Pyx_INCREF(((PyObject *)__pyx_v_w));
     PyTuple_SET_ITEM(__pyx_t_17, 0, ((PyObject *)__pyx_v_w));
     __Pyx_GIVEREF(((PyObject *)__pyx_v_w));
-    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_17)); __pyx_t_17 = 0;
-    __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_17));
     PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_4);
     __Pyx_GIVEREF(__pyx_t_4);
     __pyx_t_4 = 0;
-    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_17)); __pyx_t_17 = 0;
-    __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     if (!__pyx_t_8) {
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":179
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":210
  *         # floating-point under-/overflow check.
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \
  *            or np.isnan(intercept) or np.isinf(intercept):             # <<<<<<<<<<<<<<
  *             raise ValueError("floating-point under-/overflow occured.")
  * 
  */
-      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_17 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__any); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_17 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__any); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_17);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":178
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":209
  * 
  *         # floating-point under-/overflow check.
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \             # <<<<<<<<<<<<<<
  *            or np.isnan(intercept) or np.isinf(intercept):
  *             raise ValueError("floating-point under-/overflow occured.")
  */
-      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_2 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__isnan); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__isnan); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       __Pyx_INCREF(((PyObject *)__pyx_v_w));
       PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_v_w));
       __Pyx_GIVEREF(((PyObject *)__pyx_v_w));
-      __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
       __Pyx_GIVEREF(__pyx_t_1);
       __pyx_t_1 = 0;
-      __pyx_t_1 = PyObject_Call(__pyx_t_17, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyObject_Call(__pyx_t_17, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
       __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-      __pyx_t_18 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_18 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_18 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_18 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
       if (!__pyx_t_18) {
 
-        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":179
+        /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":210
  *         # floating-point under-/overflow check.
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \
  *            or np.isnan(intercept) or np.isinf(intercept):             # <<<<<<<<<<<<<<
  *             raise ValueError("floating-point under-/overflow occured.")
  * 
  */
-        __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
-        __pyx_t_4 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__isnan); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_4 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__isnan); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_4);
         __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-        __pyx_t_1 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
-        __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_17 = PyTuple_New(1); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(((PyObject *)__pyx_t_17));
         PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_1);
         __Pyx_GIVEREF(__pyx_t_1);
         __pyx_t_1 = 0;
-        __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_17), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
         __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
         __Pyx_DECREF(((PyObject *)__pyx_t_17)); __pyx_t_17 = 0;
-        __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
         if (!__pyx_t_19) {
-          __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_17 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__isinf); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_17 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__isinf); if (unlikely(!__pyx_t_17)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_17);
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-          __pyx_t_1 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_1 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(((PyObject *)__pyx_t_4));
           PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
           __Pyx_GIVEREF(__pyx_t_1);
           __pyx_t_1 = 0;
-          __pyx_t_1 = PyObject_Call(__pyx_t_17, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_1 = PyObject_Call(__pyx_t_17, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_1);
           __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
           __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-          __pyx_t_20 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_20 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_20 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_20 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           __pyx_t_21 = __pyx_t_20;
         } else {
@@ -2621,36 +2743,36 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
     }
     if (__pyx_t_18) {
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":180
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":211
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \
  *            or np.isnan(intercept) or np.isinf(intercept):
  *             raise ValueError("floating-point under-/overflow occured.")             # <<<<<<<<<<<<<<
  * 
  *     w *= wscale
  */
-      __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_5), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_k_tuple_5), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
       __Pyx_Raise(__pyx_t_1, 0, 0);
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      goto __pyx_L19;
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      goto __pyx_L21;
     }
-    __pyx_L19:;
+    __pyx_L21:;
   }
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":182
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":213
  *             raise ValueError("floating-point under-/overflow occured.")
  * 
  *     w *= wscale             # <<<<<<<<<<<<<<
  *     return w, intercept
  * 
  */
-  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 182; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_wscale); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_4 = PyNumber_InPlaceMultiply(((PyObject *)__pyx_v_w), __pyx_t_1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 182; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyNumber_InPlaceMultiply(((PyObject *)__pyx_v_w), __pyx_t_1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 182; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_t_14 = ((PyArrayObject *)__pyx_t_4);
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
@@ -2667,14 +2789,14 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
     }
     __pyx_bstride_0_w = __pyx_bstruct_w.strides[0];
     __pyx_bshape_0_w = __pyx_bstruct_w.shape[0];
-    if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 182; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_t_14 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_v_w));
   __pyx_v_w = ((PyArrayObject *)__pyx_t_4);
   __pyx_t_4 = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":183
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":214
  * 
  *     w *= wscale
  *     return w, intercept             # <<<<<<<<<<<<<<
@@ -2682,9 +2804,9 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_4 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyFloat_FromDouble(__pyx_v_intercept); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __Pyx_INCREF(((PyObject *)__pyx_v_w));
   PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_w));
@@ -2708,12 +2830,12 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
     __Pyx_SafeReleaseBuffer(&__pyx_bstruct_index);
+    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_X_data);
     __Pyx_SafeReleaseBuffer(&__pyx_bstruct_sample_weight);
     __Pyx_SafeReleaseBuffer(&__pyx_bstruct_X_indices);
     __Pyx_SafeReleaseBuffer(&__pyx_bstruct_X_indptr);
     __Pyx_SafeReleaseBuffer(&__pyx_bstruct_Y);
     __Pyx_SafeReleaseBuffer(&__pyx_bstruct_q);
-    __Pyx_SafeReleaseBuffer(&__pyx_bstruct_X_data);
     __Pyx_SafeReleaseBuffer(&__pyx_bstruct_w);
   __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
   __Pyx_AddTraceback("scikits.learn.linear_model.sgd_fast_sparse.plain_sgd");
@@ -2721,12 +2843,12 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   goto __pyx_L2;
   __pyx_L0:;
   __Pyx_SafeReleaseBuffer(&__pyx_bstruct_index);
+  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_X_data);
   __Pyx_SafeReleaseBuffer(&__pyx_bstruct_sample_weight);
   __Pyx_SafeReleaseBuffer(&__pyx_bstruct_X_indices);
   __Pyx_SafeReleaseBuffer(&__pyx_bstruct_X_indptr);
   __Pyx_SafeReleaseBuffer(&__pyx_bstruct_Y);
   __Pyx_SafeReleaseBuffer(&__pyx_bstruct_q);
-  __Pyx_SafeReleaseBuffer(&__pyx_bstruct_X_data);
   __Pyx_SafeReleaseBuffer(&__pyx_bstruct_w);
   __pyx_L2:;
   __Pyx_XDECREF((PyObject *)__pyx_v_index);
@@ -2738,7 +2860,7 @@ static PyObject *__pyx_pf_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":186
+/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":217
  * 
  * 
  * cdef inline double max(double a, double b):             # <<<<<<<<<<<<<<
@@ -2751,7 +2873,7 @@ static CYTHON_INLINE double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sp
   double __pyx_t_1;
   __Pyx_RefNannySetupContext("max");
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":187
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":218
  * 
  * cdef inline double max(double a, double b):
  *     return a if a >= b else b             # <<<<<<<<<<<<<<
@@ -2772,7 +2894,7 @@ static CYTHON_INLINE double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sp
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":190
+/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":221
  * 
  * 
  * cdef inline double min(double a, double b):             # <<<<<<<<<<<<<<
@@ -2785,7 +2907,7 @@ static CYTHON_INLINE double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sp
   double __pyx_t_1;
   __Pyx_RefNannySetupContext("min");
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":191
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":222
  * 
  * cdef inline double min(double a, double b):
  *     return a if a <= b else b             # <<<<<<<<<<<<<<
@@ -2806,7 +2928,7 @@ static CYTHON_INLINE double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sp
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":194
+/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":225
  * 
  * 
  * cdef double dot(double *w_data_ptr, double *X_data_ptr, int *X_indices_ptr,             # <<<<<<<<<<<<<<
@@ -2821,7 +2943,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_dot(doub
   int __pyx_t_1;
   __Pyx_RefNannySetupContext("dot");
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":196
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":227
  * cdef double dot(double *w_data_ptr, double *X_data_ptr, int *X_indices_ptr,
  *                 int offset, int xnnz):
  *     cdef double sum = 0.0             # <<<<<<<<<<<<<<
@@ -2830,7 +2952,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_dot(doub
  */
   __pyx_v_sum = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":198
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":229
  *     cdef double sum = 0.0
  *     cdef int j
  *     for j from 0 <= j < xnnz:             # <<<<<<<<<<<<<<
@@ -2840,7 +2962,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_dot(doub
   __pyx_t_1 = __pyx_v_xnnz;
   for (__pyx_v_j = 0; __pyx_v_j < __pyx_t_1; __pyx_v_j++) {
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":199
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":230
  *     cdef int j
  *     for j from 0 <= j < xnnz:
  *         sum += w_data_ptr[X_indices_ptr[offset + j]] * X_data_ptr[offset + j]             # <<<<<<<<<<<<<<
@@ -2850,7 +2972,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_dot(doub
     __pyx_v_sum = (__pyx_v_sum + ((__pyx_v_w_data_ptr[(__pyx_v_X_indices_ptr[(__pyx_v_offset + __pyx_v_j)])]) * (__pyx_v_X_data_ptr[(__pyx_v_offset + __pyx_v_j)])));
   }
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":200
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":231
  *     for j from 0 <= j < xnnz:
  *         sum += w_data_ptr[X_indices_ptr[offset + j]] * X_data_ptr[offset + j]
  *     return sum             # <<<<<<<<<<<<<<
@@ -2866,7 +2988,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_dot(doub
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":203
+/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":234
  * 
  * 
  * cdef double add(double *w_data_ptr, double wscale, double *X_data_ptr,             # <<<<<<<<<<<<<<
@@ -2885,7 +3007,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(doub
   int __pyx_t_2;
   __Pyx_RefNannySetupContext("add");
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":209
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":240
  *     cdef int idx
  *     cdef double val
  *     cdef double innerprod = 0.0             # <<<<<<<<<<<<<<
@@ -2894,7 +3016,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(doub
  */
   __pyx_v_innerprod = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":210
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":241
  *     cdef double val
  *     cdef double innerprod = 0.0
  *     cdef double xsqnorm = 0.0             # <<<<<<<<<<<<<<
@@ -2903,7 +3025,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(doub
  */
   __pyx_v_xsqnorm = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":211
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":242
  *     cdef double innerprod = 0.0
  *     cdef double xsqnorm = 0.0
  *     for j from 0 <= j < xnnz:             # <<<<<<<<<<<<<<
@@ -2913,7 +3035,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(doub
   __pyx_t_1 = __pyx_v_xnnz;
   for (__pyx_v_j = 0; __pyx_v_j < __pyx_t_1; __pyx_v_j++) {
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":212
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":243
  *     cdef double xsqnorm = 0.0
  *     for j from 0 <= j < xnnz:
  *         idx = X_indices_ptr[offset + j]             # <<<<<<<<<<<<<<
@@ -2922,7 +3044,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(doub
  */
     __pyx_v_idx = (__pyx_v_X_indices_ptr[(__pyx_v_offset + __pyx_v_j)]);
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":213
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":244
  *     for j from 0 <= j < xnnz:
  *         idx = X_indices_ptr[offset + j]
  *         val = X_data_ptr[offset + j]             # <<<<<<<<<<<<<<
@@ -2931,7 +3053,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(doub
  */
     __pyx_v_val = (__pyx_v_X_data_ptr[(__pyx_v_offset + __pyx_v_j)]);
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":214
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":245
  *         idx = X_indices_ptr[offset + j]
  *         val = X_data_ptr[offset + j]
  *         innerprod += (w_data_ptr[idx] * val)             # <<<<<<<<<<<<<<
@@ -2940,7 +3062,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(doub
  */
     __pyx_v_innerprod = (__pyx_v_innerprod + ((__pyx_v_w_data_ptr[__pyx_v_idx]) * __pyx_v_val));
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":215
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":246
  *         val = X_data_ptr[offset + j]
  *         innerprod += (w_data_ptr[idx] * val)
  *         xsqnorm += (val * val)             # <<<<<<<<<<<<<<
@@ -2949,7 +3071,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(doub
  */
     __pyx_v_xsqnorm = (__pyx_v_xsqnorm + (__pyx_v_val * __pyx_v_val));
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":216
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":247
  *         innerprod += (w_data_ptr[idx] * val)
  *         xsqnorm += (val * val)
  *         w_data_ptr[idx] += val * (c / wscale)             # <<<<<<<<<<<<<<
@@ -2960,7 +3082,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(doub
     (__pyx_v_w_data_ptr[__pyx_t_2]) = ((__pyx_v_w_data_ptr[__pyx_t_2]) + (__pyx_v_val * (__pyx_v_c / __pyx_v_wscale)));
   }
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":217
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":248
  *         xsqnorm += (val * val)
  *         w_data_ptr[idx] += val * (c / wscale)
  *     return (xsqnorm * c * c) + (2.0 * innerprod * wscale * c)             # <<<<<<<<<<<<<<
@@ -2976,7 +3098,7 @@ static  double __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_add(doub
   return __pyx_r;
 }
 
-/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":220
+/* "scikits/learn/linear_model/sgd_fast_sparse.pyx":251
  * 
  * 
  * cdef void l1penalty(double *w_data_ptr, double wscale, double *q_data_ptr,             # <<<<<<<<<<<<<<
@@ -2993,7 +3115,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
   int __pyx_t_3;
   __Pyx_RefNannySetupContext("l1penalty");
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":227
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":258
  *     [Tsuruoka, Y., Tsujii, J., and Ananiadou, S., 2009].
  *     """
  *     cdef double z = 0.0             # <<<<<<<<<<<<<<
@@ -3002,7 +3124,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
  */
   __pyx_v_z = 0.0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":228
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":259
  *     """
  *     cdef double z = 0.0
  *     cdef int j = 0             # <<<<<<<<<<<<<<
@@ -3011,7 +3133,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
  */
   __pyx_v_j = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":229
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":260
  *     cdef double z = 0.0
  *     cdef int j = 0
  *     cdef int idx = 0             # <<<<<<<<<<<<<<
@@ -3020,7 +3142,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
  */
   __pyx_v_idx = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":230
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":261
  *     cdef int j = 0
  *     cdef int idx = 0
  *     for j from 0 <= j < xnnz:             # <<<<<<<<<<<<<<
@@ -3030,7 +3152,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
   __pyx_t_1 = __pyx_v_xnnz;
   for (__pyx_v_j = 0; __pyx_v_j < __pyx_t_1; __pyx_v_j++) {
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":231
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":262
  *     cdef int idx = 0
  *     for j from 0 <= j < xnnz:
  *         idx = X_indices_ptr[offset + j]             # <<<<<<<<<<<<<<
@@ -3039,7 +3161,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
  */
     __pyx_v_idx = (__pyx_v_X_indices_ptr[(__pyx_v_offset + __pyx_v_j)]);
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":232
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":263
  *     for j from 0 <= j < xnnz:
  *         idx = X_indices_ptr[offset + j]
  *         z = w_data_ptr[idx]             # <<<<<<<<<<<<<<
@@ -3048,7 +3170,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
  */
     __pyx_v_z = (__pyx_v_w_data_ptr[__pyx_v_idx]);
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":233
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":264
  *         idx = X_indices_ptr[offset + j]
  *         z = w_data_ptr[idx]
  *         if (wscale * w_data_ptr[idx]) > 0.0:             # <<<<<<<<<<<<<<
@@ -3058,7 +3180,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
     __pyx_t_2 = ((__pyx_v_wscale * (__pyx_v_w_data_ptr[__pyx_v_idx])) > 0.0);
     if (__pyx_t_2) {
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":234
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":265
  *         z = w_data_ptr[idx]
  *         if (wscale * w_data_ptr[idx]) > 0.0:
  *             w_data_ptr[idx] = max(             # <<<<<<<<<<<<<<
@@ -3069,7 +3191,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
       goto __pyx_L5;
     }
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":237
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":268
  *                 0.0, w_data_ptr[idx] - ((u + q_data_ptr[idx]) / wscale))
  * 
  *         elif (wscale * w_data_ptr[idx]) < 0.0:             # <<<<<<<<<<<<<<
@@ -3079,7 +3201,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
     __pyx_t_2 = ((__pyx_v_wscale * (__pyx_v_w_data_ptr[__pyx_v_idx])) < 0.0);
     if (__pyx_t_2) {
 
-      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":238
+      /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":269
  * 
  *         elif (wscale * w_data_ptr[idx]) < 0.0:
  *             w_data_ptr[idx] = min(             # <<<<<<<<<<<<<<
@@ -3091,7 +3213,7 @@ static  void __pyx_f_7scikits_5learn_12linear_model_15sgd_fast_sparse_l1penalty(
     }
     __pyx_L5:;
 
-    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":241
+    /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":272
  *                 0.0, w_data_ptr[idx] + ((u - q_data_ptr[idx]) / wscale))
  * 
  *         q_data_ptr[idx] += (wscale * (w_data_ptr[idx] - z))             # <<<<<<<<<<<<<<
@@ -5077,6 +5199,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__dloss, __pyx_k__dloss, sizeof(__pyx_k__dloss), 0, 0, 1, 1},
   {&__pyx_n_s__dot, __pyx_k__dot, sizeof(__pyx_k__dot), 0, 0, 1, 1},
   {&__pyx_n_s__dtype, __pyx_k__dtype, sizeof(__pyx_k__dtype), 0, 0, 1, 1},
+  {&__pyx_n_s__eta0, __pyx_k__eta0, sizeof(__pyx_k__eta0), 0, 0, 1, 1},
   {&__pyx_n_s__fields, __pyx_k__fields, sizeof(__pyx_k__fields), 0, 0, 1, 1},
   {&__pyx_n_s__fit_intercept, __pyx_k__fit_intercept, sizeof(__pyx_k__fit_intercept), 0, 0, 1, 1},
   {&__pyx_n_s__float64, __pyx_k__float64, sizeof(__pyx_k__float64), 0, 0, 1, 1},
@@ -5086,6 +5209,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__isinf, __pyx_k__isinf, sizeof(__pyx_k__isinf), 0, 0, 1, 1},
   {&__pyx_n_s__isnan, __pyx_k__isnan, sizeof(__pyx_k__isnan), 0, 0, 1, 1},
   {&__pyx_n_s__itemsize, __pyx_k__itemsize, sizeof(__pyx_k__itemsize), 0, 0, 1, 1},
+  {&__pyx_n_s__learning_rate, __pyx_k__learning_rate, sizeof(__pyx_k__learning_rate), 0, 0, 1, 1},
   {&__pyx_n_s__loss, __pyx_k__loss, sizeof(__pyx_k__loss), 0, 0, 1, 1},
   {&__pyx_n_s__n_iter, __pyx_k__n_iter, sizeof(__pyx_k__n_iter), 0, 0, 1, 1},
   {&__pyx_n_s__names, __pyx_k__names, sizeof(__pyx_k__names), 0, 0, 1, 1},
@@ -5097,6 +5221,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__order, __pyx_k__order, sizeof(__pyx_k__order), 0, 0, 1, 1},
   {&__pyx_n_s__penalty_type, __pyx_k__penalty_type, sizeof(__pyx_k__penalty_type), 0, 0, 1, 1},
   {&__pyx_n_s__plain_sgd, __pyx_k__plain_sgd, sizeof(__pyx_k__plain_sgd), 0, 0, 1, 1},
+  {&__pyx_n_s__power_t, __pyx_k__power_t, sizeof(__pyx_k__power_t), 0, 0, 1, 1},
   {&__pyx_n_s__random, __pyx_k__random, sizeof(__pyx_k__random), 0, 0, 1, 1},
   {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1},
   {&__pyx_n_s__readonly, __pyx_k__readonly, sizeof(__pyx_k__readonly), 0, 0, 1, 1},
@@ -5118,7 +5243,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {0, 0, 0, 0, 0, 0, 0}
 };
 static int __Pyx_InitCachedBuiltins(void) {
-  __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 787; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   return 0;
@@ -5129,14 +5254,14 @@ static int __Pyx_InitCachedBuiltins(void) {
 static int __Pyx_InitCachedConstants(void) {
   __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants");
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":180
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":211
  *         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \
  *            or np.isnan(intercept) or np.isinf(intercept):
  *             raise ValueError("floating-point under-/overflow occured.")             # <<<<<<<<<<<<<<
  * 
  *     w *= wscale
  */
-  __pyx_k_tuple_5 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_5 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_5));
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_4));
   PyTuple_SET_ITEM(__pyx_k_tuple_5, 0, ((PyObject *)__pyx_kp_s_4));
@@ -5305,22 +5430,22 @@ PyMODINIT_FUNC PyInit_sgd_fast_sparse(void)
   __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 163; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 849; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "LossFunction", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Regression = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "Regression", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Regression), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Regression)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Regression*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Regression->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Classification = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "Classification", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Classification)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Classification*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Classification->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "ModifiedHuber", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Hinge = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "Hinge", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Hinge), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Hinge)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Hinge = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Hinge*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Hinge->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Hinge)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Log = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "Log", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Log), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Log)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Log = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Log*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Log->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Log)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "SquaredLoss", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Huber = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "Huber", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Huber)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Huber = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Huber*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Huber->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Huber)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "LossFunction", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_LossFunction), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_LossFunction*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_LossFunction->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_LossFunction)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Regression = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "Regression", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Regression), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Regression)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Regression*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Regression->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Regression)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Classification = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "Classification", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Classification), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Classification)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Classification*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Classification->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Classification)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "ModifiedHuber", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_ModifiedHuber)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Hinge = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "Hinge", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Hinge), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Hinge)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Hinge = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Hinge*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Hinge->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Hinge)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Log = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "Log", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Log), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Log)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Log = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Log*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Log->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Log)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "SquaredLoss", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_SquaredLoss)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Huber = __Pyx_ImportType("scikits.learn.linear_model.sgd_fast", "Huber", sizeof(struct __pyx_obj_7scikits_5learn_12linear_model_8sgd_fast_Huber), 1); if (unlikely(!__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Huber)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Huber = (struct __pyx_vtabstruct_7scikits_5learn_12linear_model_8sgd_fast_Huber*)__Pyx_GetVtable(__pyx_ptype_7scikits_5learn_12linear_model_8sgd_fast_Huber->tp_dict); if (unlikely(!__pyx_vtabptr_7scikits_5learn_12linear_model_8sgd_fast_Huber)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   /*--- Function import code ---*/
   /*--- Execution code ---*/
 
@@ -5369,16 +5494,16 @@ PyMODINIT_FUNC PyInit_sgd_fast_sparse(void)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":27
+  /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":34
  * @cython.wraparound(False)
  * @cython.cdivision(True)
  * def plain_sgd(np.ndarray[double, ndim=1] w,             # <<<<<<<<<<<<<<
  *               double intercept,
  *               LossFunction loss,
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain_sgd, NULL, __pyx_n_s_18); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7scikits_5learn_12linear_model_15sgd_fast_sparse_plain_sgd, NULL, __pyx_n_s_18); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__plain_sgd, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__plain_sgd, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   /* "scikits/learn/linear_model/sgd_fast_sparse.pyx":1
diff --git a/scikits/learn/linear_model/sgd_fast_sparse.pyx b/scikits/learn/linear_model/sgd_fast_sparse.pyx
index 736607127aff044bc9837925e2b7b06122390bc6..6ec69a328b0fb03704f27dfcb8f35df85b5dc65d 100644
--- a/scikits/learn/linear_model/sgd_fast_sparse.pyx
+++ b/scikits/learn/linear_model/sgd_fast_sparse.pyx
@@ -15,12 +15,19 @@ cimport numpy as np
 cimport cython
 cimport sgd_fast
 
-from sgd_fast cimport LossFunction, exp, log, sqrt
+from sgd_fast cimport LossFunction, exp, log, sqrt, pow
 
+# Penalty constants
 DEF L1 = 1
 DEF L2 = 2
 DEF ELASTICNET = 3
 
+# Learning rate constants
+DEF CONSTANT = 1
+DEF OPTIMAL = 2
+DEF INVSCALING = 3
+
+
 @cython.boundscheck(False)
 @cython.wraparound(False)
 @cython.cdivision(True)
@@ -36,7 +43,9 @@ def plain_sgd(np.ndarray[double, ndim=1] w,
               int n_iter, int fit_intercept,
               int verbose, int shuffle, int seed,
               double weight_pos, double weight_neg,
-              np.ndarray[double, ndim=1] sample_weight):
+              np.ndarray[double, ndim=1] sample_weight,
+              int learning_rate, double eta0,
+              double power_t):
     """Cython impl. of SGD with different loss functions and penalties
 
     This representation assumes X represented using the Compressed Sparse Row
@@ -57,7 +66,7 @@ def plain_sgd(np.ndarray[double, ndim=1] w,
     rho : float
         The elastic net hyperparameter.
     X : csr_matrix[double, ndim=2]
-        The dataset as a Compressed Sparse Row matrix 
+        The dataset as a Compressed Sparse Row matrix
         (see scipy.sparse.csr_matrix).
     Y : ndarray[double, ndim=1]
         The labels.
@@ -72,19 +81,28 @@ def plain_sgd(np.ndarray[double, ndim=1] w,
     weight_pos : float
         The weight of the positive class.
     weight_neg : float
-        The weight of the negative class. 
+        The weight of the negative class.
     seed : int
         The seed of the pseudo random number generator to use when
         shuffling the data
     sample_weight : array, shape = [n_samples]
         The importance weight of each sample.
+    learning_rate : int
+        The learning rate:
+        (1) constant, eta = eta0
+        (2) optimal, eta = 1.0/(t+t0)
+        (3) inverse scaling, eta = eta0 / pow(t, power_t)
+    eta0 : double
+        The initial learning rate.
+    power_t : double
+        The exponent for inverse scaling learning rate.
 
     Returns
     -------
     w : array, shape [n_features]
-        The fitted weight vector. 
+        The fitted weight vector.
     intercept : float
-        The fitted intercept term. 
+        The fitted intercept term.
     """
     # get the data information into easy vars
     cdef unsigned int n_samples = Y.shape[0]
@@ -99,7 +117,7 @@ def plain_sgd(np.ndarray[double, ndim=1] w,
     cdef double *sample_weight_data = <double *>sample_weight.data
 
     cdef np.ndarray[int, ndim=1, mode="c"] index = np.arange(n_samples,
-                                                             dtype = np.int32)
+                                                             dtype=np.int32)
     cdef int *index_data_ptr = <int *>index.data
     cdef int offset = 0
     cdef int xnnz = 0
@@ -119,13 +137,23 @@ def plain_sgd(np.ndarray[double, ndim=1] w,
     cdef np.ndarray[double, ndim=1, mode="c"] q = None
     cdef double *q_data_ptr
     if penalty_type != L2:
-        q = np.zeros((n_features,), dtype = np.float64, order = "c")
+        q = np.zeros((n_features,), dtype=np.float64, order="c")
         q_data_ptr = <double *> q.data
     cdef double u = 0.0
-    # computing eta0
     cdef double typw = sqrt(1.0 / sqrt(alpha))
-    cdef double eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
-    t = 1.0 / (eta0 * alpha)
+
+    if learning_rate == OPTIMAL:
+        # computing eta0, the initial learning rate
+        eta0 = typw / max(1.0, loss.dloss(-typw, 1.0))
+    else:
+        eta = eta0
+
+    if learning_rate == OPTIMAL:
+        # initialize t such that eta at first example equals eta0
+        t = 1.0 / (eta0 * alpha)
+    else:
+        t = 1.0
+
     t_start = time()
     for epoch from 0 <= epoch < n_iter:
         if verbose > 0:
@@ -137,7 +165,10 @@ def plain_sgd(np.ndarray[double, ndim=1] w,
             offset = X_indptr_ptr[sample_idx]
             xnnz = X_indptr_ptr[sample_idx + 1] - offset
             y = Y_data_ptr[sample_idx]
-            eta = 1.0 / (alpha * t)
+            if learning_rate == OPTIMAL:
+                eta = 1.0 / (alpha * t)
+            elif learning_rate == INVSCALING:
+                eta = eta0 / pow(t, power_t)
             p = (dot(w_data_ptr, X_data_ptr, X_indices_ptr,
                      offset, xnnz) * wscale) + intercept
             sumloss += loss.loss(p, y)
@@ -172,7 +203,7 @@ def plain_sgd(np.ndarray[double, ndim=1] w,
                                                     w.nonzero()[0].shape[0],
                                                     intercept, count,
                                                     sumloss / count))
-            print("Total training time: %.2f seconds." % (time()-t_start))
+            print("Total training time: %.2f seconds." % (time() - t_start))
 
         # floating-point under-/overflow check.
         if np.any(np.isinf(w)) or np.any(np.isnan(w)) \
diff --git a/scikits/learn/linear_model/sparse/stochastic_gradient.py b/scikits/learn/linear_model/sparse/stochastic_gradient.py
index be8d67282f0ea302fff460ad90589db71178aea9..fd3db80b2953e583a2c5f372be87dadfa8f6ba70 100644
--- a/scikits/learn/linear_model/sparse/stochastic_gradient.py
+++ b/scikits/learn/linear_model/sparse/stochastic_gradient.py
@@ -33,17 +33,17 @@ class SGDClassifier(BaseSGDClassifier):
     Parameters
     ----------
     loss : str, 'hinge' or 'log' or 'modified_huber'
-        The loss function to be used. Defaults to 'hinge'. The hinge loss is a
-        margin loss used by standard linear SVM models. The 'log' loss is the
-        loss of logistic regression models and can be used for probability
+        The loss function to be used. Defaults to 'hinge'. The hinge loss is
+        a margin loss used by standard linear SVM models. The 'log' loss is
+        the loss of logistic regression models and can be used for probability
         estimation in binary classifiers. 'modified_huber' is another smooth
         loss that brings tolerance to outliers.
 
     penalty : str, 'l2' or 'l1' or 'elasticnet'
-        The penalty (aka regularization term) to be used. Defaults to 'l2' which
-        is the standard regularizer for linear SVM models. 'l1' and 'elasticnet'
-        migh bring sparsity to the model (feature selection) not achievable with
-        'l2'.
+        The penalty (aka regularization term) to be used. Defaults to 'l2'
+        which is the standard regularizer for linear SVM models. 'l1' and
+        'elasticnet' migh bring sparsity to the model (feature selection)
+        not achievable with 'l2'.
 
     alpha : float
         Constant that multiplies the regularization term. Defaults to 0.0001
@@ -76,6 +76,19 @@ class SGDClassifier(BaseSGDClassifier):
         multi-class problems) computation. -1 means 'all CPUs'. Defaults
         to 1.
 
+    learning_rate : string, optional
+        The learning rate:
+        constant: eta = eta0
+        optimal: eta = 1.0/(t+t0) [default]
+        invscaling: eta = eta0 / pow(t, power_t)
+
+    eta0 : double, optional
+        The initial learning rate [default 0.01].
+
+    power_t : double, optional
+        The exponent for inverse scaling learning rate [default 0.25].
+
+
     Attributes
     ----------
     `coef_` : array, shape = [1, n_features] if n_classes == 2 else [n_classes,
@@ -98,7 +111,8 @@ class SGDClassifier(BaseSGDClassifier):
     >>> clf = linear_model.sparse.SGDClassifier()
     >>> clf.fit(X, y)
     SGDClassifier(loss='hinge', n_jobs=1, shuffle=False, verbose=0, n_iter=5,
-           fit_intercept=True, penalty='l2', seed=0, rho=1.0, alpha=0.0001)
+           learning_rate='optimal', fit_intercept=True, penalty='l2',
+           power_t=0.5, seed=0, eta0=0.0, rho=1.0, alpha=0.0001)
     >>> print clf.predict([[-0.8, -1]])
     [ 1.]
 
@@ -146,7 +160,9 @@ class SGDClassifier(BaseSGDClassifier):
                                       int(self.seed),
                                       self.class_weight[1],
                                       self.class_weight[0],
-                                      self.sample_weight)
+                                      self.sample_weight,
+                                      self.learning_rate_code,
+                                      self.eta0, self.power_t)
 
         # update self.coef_ and self.sparse_coef_ consistently
         self._set_coef(np.atleast_2d(self.coef_))
@@ -176,7 +192,9 @@ class SGDClassifier(BaseSGDClassifier):
                                                self.verbose, self.shuffle,
                                                self.seed,
                                                self.class_weight[i],
-                                               self.sample_weight)
+                                               self.sample_weight,
+                                               self.learning_rate_code,
+                                               self.eta0, self.power_t)
             for i, c in enumerate(self.classes))
 
         for i, coef, intercept in res:
@@ -195,7 +213,7 @@ class SGDClassifier(BaseSGDClassifier):
 
         Returns
         -------
-        array, shape = [n_samples] if n_classes == 2 else [n_samples, n_classes]
+        array, shape = [n_samples] if n_classes == 2 else [n_samples,n_classes]
           The signed 'distances' to the hyperplane(s).
         """
         # np.dot only works correctly if both arguments are sparse matrices
@@ -212,7 +230,8 @@ class SGDClassifier(BaseSGDClassifier):
 def _train_ova_classifier(i, c, X_data, X_indices, X_indptr, y, coef_,
                           intercept_, loss_function, penalty_type, alpha,
                           rho, n_iter, fit_intercept, verbose, shuffle,
-                          seed, class_weight_pos, sample_weight):
+                          seed, class_weight_pos, sample_weight,
+                          learning_rate, eta0, power_t):
     """Inner loop for One-vs.-All scheme"""
     y_i = np.ones(y.shape, dtype=np.float64, order='C') * -1.0
     y_i[y == c] = 1.0
@@ -223,7 +242,8 @@ def _train_ova_classifier(i, c, X_data, X_indices, X_indptr, y, coef_,
                                 int(fit_intercept), int(verbose),
                                 int(shuffle), int(seed),
                                 class_weight_pos, 1.0,
-                                sample_weight)
+                                sample_weight, learning_rate, eta0,
+                                power_t)
     return (i, coef, intercept)
 
 
@@ -287,6 +307,18 @@ class SGDRegressor(BaseSGDRegressor):
         Epsilon in the epsilon insensitive huber loss function;
         only if `loss=='huber'`.
 
+    learning_rate : string, optional
+        The learning rate:
+        constant: eta = eta0
+        optimal: eta = 1.0/(t+t0)
+        invscaling: eta = eta0 / pow(t, power_t) [default]
+
+    eta0 : double, optional
+        The initial learning rate [default 0.01].
+
+    power_t : double, optional
+        The exponent for inverse scaling learning rate [default 0.25].
+
     Attributes
     ----------
     `coef_` : array, shape = [n_features]
@@ -305,9 +337,9 @@ class SGDRegressor(BaseSGDRegressor):
     >>> X = np.random.randn(n_samples, n_features)
     >>> clf = linear_model.sparse.SGDRegressor()
     >>> clf.fit(X, y)
-    SGDRegressor(loss='squared_loss', shuffle=False, verbose=0, n_iter=5,
-           fit_intercept=True, penalty='l2', p=0.1, seed=0, rho=1.0,
-           alpha=0.0001)
+    SGDRegressor(loss='squared_loss', power_t=0.25, shuffle=False, verbose=0,
+           n_iter=5, learning_rate='invscaling', fit_intercept=True,
+           penalty='l2', p=0.1, seed=0, eta0=0.01, rho=1.0, alpha=0.0001)
 
     See also
     --------
@@ -345,7 +377,9 @@ class SGDRegressor(BaseSGDRegressor):
                                       int(self.shuffle),
                                       int(self.seed),
                                       1.0, 1.0,
-                                      self.sample_weight)
+                                      self.sample_weight,
+                                      self.learning_rate_code,
+                                      self.eta0, self.power_t)
 
         # update self.coef_ and self.sparse_coef_ consistently
         self._set_coef(self.coef_)
diff --git a/scikits/learn/linear_model/stochastic_gradient.py b/scikits/learn/linear_model/stochastic_gradient.py
index faf86604aa71edae13b0797bff50241b064ebb05..1a8d2e767d6c29d11f4c99b2caaaa74135750a5f 100644
--- a/scikits/learn/linear_model/stochastic_gradient.py
+++ b/scikits/learn/linear_model/stochastic_gradient.py
@@ -30,17 +30,17 @@ class SGDClassifier(BaseSGDClassifier):
     Parameters
     ----------
     loss : str, 'hinge' or 'log' or 'modified_huber'
-        The loss function to be used. Defaults to 'hinge'. The hinge loss is a
-        margin loss used by standard linear SVM models. The 'log' loss is the
-        loss of logistic regression models and can be used for probability
-        estimation in binary classifiers. 'modified_huber' is another smooth
-        loss that brings tolerance to outliers.
+        The loss function to be used. Defaults to 'hinge'. The hinge loss is
+        a margin loss used by standard linear SVM models. The 'log' loss is
+        the loss of logistic regression models and can be used for
+        probability estimation in binary classifiers. 'modified_huber'
+        is another smooth loss that brings tolerance to outliers.
 
     penalty : str, 'l2' or 'l1' or 'elasticnet'
-        The penalty (aka regularization term) to be used. Defaults to 'l2' which
-        is the standard regularizer for linear SVM models. 'l1' and 'elasticnet'
-        migh bring sparsity to the model (feature selection) not achievable with
-        'l2'.
+        The penalty (aka regularization term) to be used. Defaults to 'l2'
+        which is the standard regularizer for linear SVM models. 'l1' and
+        'elasticnet' migh bring sparsity to the model (feature selection)
+        not achievable with 'l2'.
 
     alpha : float
         Constant that multiplies the regularization term. Defaults to 0.0001
@@ -73,6 +73,19 @@ class SGDClassifier(BaseSGDClassifier):
         multi-class problems) computation. -1 means 'all CPUs'. Defaults
         to 1.
 
+    learning_rate : int
+        The learning rate:
+        constant: eta = eta0
+        optimal: eta = 1.0/(t+t0) [default]
+        invscaling: eta = eta0 / pow(t, power_t)
+
+    eta0 : double
+        The initial learning rate [default 0.01].
+
+    power_t : double
+        The exponent for inverse scaling learning rate [default 0.25].
+
+
     Attributes
     ----------
     `coef_` : array, shape = [1, n_features] if n_classes == 2 else [n_classes,
@@ -91,7 +104,8 @@ class SGDClassifier(BaseSGDClassifier):
     >>> clf = linear_model.SGDClassifier()
     >>> clf.fit(X, Y)
     SGDClassifier(loss='hinge', n_jobs=1, shuffle=False, verbose=0, n_iter=5,
-           fit_intercept=True, penalty='l2', seed=0, rho=1.0, alpha=0.0001)
+           learning_rate='optimal', fit_intercept=True, penalty='l2',
+           power_t=0.5, seed=0, eta0=0.0, rho=1.0, alpha=0.0001)
     >>> print clf.predict([[-0.8, -1]])
     [ 1.]
 
@@ -124,7 +138,9 @@ class SGDClassifier(BaseSGDClassifier):
                                       self.seed,
                                       self.class_weight[1],
                                       self.class_weight[0],
-                                      self.sample_weight)
+                                      self.sample_weight,
+                                      self.learning_rate_code, self.eta0,
+                                      self.power_t)
 
         self.coef_ = np.atleast_2d(coef_)
         self.intercept_ = np.asarray(intercept_)
@@ -148,7 +164,9 @@ class SGDClassifier(BaseSGDClassifier):
                                                self.verbose, self.shuffle,
                                                self.seed,
                                                self.class_weight[i],
-                                               self.sample_weight)
+                                               self.sample_weight,
+                                               self.learning_rate_code,
+                                               self.eta0, self.power_t)
             for i, c in enumerate(self.classes))
 
         for i, coef, intercept in res:
@@ -164,7 +182,7 @@ class SGDClassifier(BaseSGDClassifier):
 
         Returns
         -------
-        array, shape = [n_samples] if n_classes == 2 else [n_samples, n_classes]
+        array, shape = [n_samples] if n_classes == 2 else [n_samples,n_classes]
           The signed 'distances' to the hyperplane(s).
         """
         X = np.atleast_2d(np.asanyarray(X))
@@ -178,15 +196,16 @@ class SGDClassifier(BaseSGDClassifier):
 def _train_ova_classifier(i, c, X, y, coef_, intercept_, loss_function,
                           penalty_type, alpha, rho, n_iter, fit_intercept,
                           verbose, shuffle, seed, class_weight_pos,
-                          sample_weight):
-    """Inner loop for One-vs.-All scheme"""
+                          sample_weight, learning_rate, eta0, power_t):
+    """Inner loop for one-vs-all scheme."""
     y_i = np.ones(y.shape, dtype=np.float64, order='C') * -1.0
     y_i[y == c] = 1.0
     coef, intercept = plain_sgd(coef_, intercept_, loss_function,
                                 penalty_type, alpha, rho,
                                 X, y_i, n_iter, fit_intercept,
                                 verbose, shuffle, seed, class_weight_pos, 1.0,
-                                sample_weight)
+                                sample_weight, learning_rate, eta0,
+                                power_t)
     return (i, coef, intercept)
 
 
@@ -211,14 +230,14 @@ class SGDRegressor(BaseSGDRegressor):
     ----------
     loss : str, 'squared_loss' or 'huber'
         The loss function to be used. Defaults to 'squared_loss' which refers
-        to the ordinary least squares fit. 'huber' is an epsilon insensitive loss
-        function for robust regression.
+        to the ordinary least squares fit. 'huber' is an epsilon insensitive
+        loss function for robust regression.
 
     penalty : str, 'l2' or 'l1' or 'elasticnet'
-        The penalty (aka regularization term) to be used. Defaults to 'l2' which
-        is the standard regularizer for linear SVM models. 'l1' and 'elasticnet'
-        migh bring sparsity to the model (feature selection) not achievable with
-        'l2'.
+        The penalty (aka regularization term) to be used. Defaults to 'l2'
+        which is the standard regularizer for linear SVM models. 'l1' and
+        'elasticnet' migh bring sparsity to the model (feature selection)
+        not achievable with 'l2'.
 
     alpha : float
         Constant that multiplies the regularization term. Defaults to 0.0001
@@ -250,6 +269,18 @@ class SGDRegressor(BaseSGDRegressor):
         Epsilon in the epsilon-insensitive huber loss function;
         only if `loss=='huber'`.
 
+    learning_rate : string, optional
+        The learning rate:
+        constant: eta = eta0
+        optimal: eta = 1.0/(t+t0)
+        invscaling: eta = eta0 / pow(t, power_t) [default]
+
+    eta0 : double, optional
+        The initial learning rate [default 0.01].
+
+    power_t : double, optional
+        The exponent for inverse scaling learning rate [default 0.25].
+
     Attributes
     ----------
     `coef_` : array, shape = [n_features]
@@ -268,9 +299,9 @@ class SGDRegressor(BaseSGDRegressor):
     >>> X = np.random.randn(n_samples, n_features)
     >>> clf = linear_model.SGDRegressor()
     >>> clf.fit(X, y)
-    SGDRegressor(loss='squared_loss', shuffle=False, verbose=0, n_iter=5,
-           fit_intercept=True, penalty='l2', p=0.1, seed=0, rho=1.0,
-           alpha=0.0001)
+    SGDRegressor(loss='squared_loss', power_t=0.25, shuffle=False, verbose=0,
+           n_iter=5, learning_rate='invscaling', fit_intercept=True,
+           penalty='l2', p=0.1, seed=0, eta0=0.01, rho=1.0, alpha=0.0001)
 
     See also
     --------
@@ -292,7 +323,9 @@ class SGDRegressor(BaseSGDRegressor):
                                       int(self.shuffle),
                                       self.seed,
                                       1.0, 1.0,
-                                      self.sample_weight)
+                                      self.sample_weight,
+                                      self.learning_rate_code,
+                                      self.eta0, self.power_t)
 
         self.coef_ = coef_
         self.intercept_ = np.asarray(intercept_)