diff --git a/sklearn/linear_model/logistic.py b/sklearn/linear_model/logistic.py index b567a3aa4d827..db43c58c2f83d 100644 --- a/sklearn/linear_model/logistic.py +++ b/sklearn/linear_model/logistic.py @@ -639,6 +639,10 @@ class LogisticRegression(BaseLibLinear, LinearClassifierMixin, Intercept (a.k.a. bias) added to the decision function. If `fit_intercept` is set to False, the intercept is set to zero. + `n_iter_` : int | array, shape (n_classes,) + Number of iterations run per class. Valid only for the liblinear + solver. + See also -------- SGDClassifier : incrementally trained logistic regression (when given diff --git a/sklearn/svm/base.py b/sklearn/svm/base.py index 3d8b225ea6054..ec1891ca99a90 100644 --- a/sklearn/svm/base.py +++ b/sklearn/svm/base.py @@ -716,17 +716,21 @@ def fit(self, X, y): # LibLinear wants targets as doubles, even for classification y_ind = np.asarray(y_ind, dtype=np.float64).ravel() - raw_coef_ = liblinear.train_wrap(X, y_ind, - sp.isspmatrix(X), - self._get_solver_type(), - self.tol, self._get_bias(), - self.C, self.class_weight_, - self.max_iter, - rnd.randint(np.iinfo('i').max)) + raw_coef_, self.n_iter_ = liblinear.train_wrap( + X, y_ind, sp.isspmatrix(X), self._get_solver_type(), + self.tol, self._get_bias(), self.C, self.class_weight_, + self.max_iter, rnd.randint(np.iinfo('i').max) + ) # Regarding rnd.randint(..) in the above signature: # seed for srand in range [0..INT_MAX); due to limitations in Numpy # on 32-bit platforms, we can't get to the UINT_MAX limit that # srand supports + for n_iter in self.n_iter_: + if n_iter >= self.max_iter: + warnings.warn("Liblinear failed to converge, increase " + "the number of iterations.", ConvergenceWarning) + if len(self.classes_) == 2: + self.n_iter_ = self.n_iter_[0] if self.fit_intercept: self.coef_ = raw_coef_[:, :-1] diff --git a/sklearn/svm/liblinear.c b/sklearn/svm/liblinear.c index a32895a1641b6..cf0171f27b95e 100644 --- a/sklearn/svm/liblinear.c +++ b/sklearn/svm/liblinear.c @@ -1,4 +1,4 @@ -/* Generated by Cython 0.20.1post0 (Debian 0.20.1+git90-g0e6e38e-1ubuntu2) on Tue Jul 29 18:02:03 2014 */ +/* Generated by Cython 0.20.1post0 (Debian 0.20.1+git90-g0e6e38e-1ubuntu2) on Thu Jul 31 17:11:18 2014 */ #define PY_SSIZE_T_CLEAN #ifndef CYTHON_USE_PYLONG_INTERNALS @@ -1235,9 +1235,12 @@ static char __pyx_k_order[] = "order"; static char __pyx_k_param[] = "param"; static char __pyx_k_range[] = "range"; static char __pyx_k_shape[] = "shape"; +static char __pyx_k_zeros[] = "zeros"; static char __pyx_k_arange[] = "arange"; static char __pyx_k_import[] = "__import__"; static char __pyx_k_indptr[] = "indptr"; +static char __pyx_k_labels[] = "labels_"; +static char __pyx_k_n_iter[] = "n_iter"; static char __pyx_k_indices[] = "indices"; static char __pyx_k_problem[] = "problem"; static char __pyx_k_max_iter[] = "max_iter"; @@ -1289,10 +1292,12 @@ static PyObject *__pyx_n_s_indices; static PyObject *__pyx_n_s_indptr; static PyObject *__pyx_n_s_int32; static PyObject *__pyx_n_s_is_sparse; +static PyObject *__pyx_n_s_labels; static PyObject *__pyx_n_s_len_w; static PyObject *__pyx_n_s_main; static PyObject *__pyx_n_s_max_iter; static PyObject *__pyx_n_s_model; +static PyObject *__pyx_n_s_n_iter; static PyObject *__pyx_kp_u_ndarray_is_not_C_contiguous; static PyObject *__pyx_kp_u_ndarray_is_not_Fortran_contiguou; static PyObject *__pyx_n_s_np; @@ -1315,6 +1320,7 @@ static PyObject *__pyx_n_s_train_wrap; static PyObject *__pyx_kp_u_unknown_dtype_code_in_numpy_pxd; static PyObject *__pyx_n_s_verbosity; static PyObject *__pyx_n_s_w; +static PyObject *__pyx_n_s_zeros; static PyObject *__pyx_int_1; static PyObject *__pyx_tuple_; static PyObject *__pyx_tuple__2; @@ -1484,6 +1490,8 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb PyArrayObject *__pyx_v_class_weight_label = 0; PyArrayObject *__pyx_v_w = 0; int __pyx_v_nr_class; + int __pyx_v_labels_; + PyArrayObject *__pyx_v_n_iter = 0; int __pyx_v_nr_feature; __Pyx_LocalBuf_ND __pyx_pybuffernd_Y; __Pyx_Buffer __pyx_pybuffer_Y; @@ -1491,6 +1499,8 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb __Pyx_Buffer __pyx_pybuffer_class_weight; __Pyx_LocalBuf_ND __pyx_pybuffernd_class_weight_label; __Pyx_Buffer __pyx_pybuffer_class_weight_label; + __Pyx_LocalBuf_ND __pyx_pybuffernd_n_iter; + __Pyx_Buffer __pyx_pybuffer_n_iter; __Pyx_LocalBuf_ND __pyx_pybuffernd_w; __Pyx_Buffer __pyx_pybuffer_w; PyObject *__pyx_r = NULL; @@ -1505,13 +1515,14 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb PyObject *__pyx_t_8 = NULL; __pyx_t_5numpy_int32_t __pyx_t_9; PyArrayObject *__pyx_t_10 = NULL; - int __pyx_t_11; + PyArrayObject *__pyx_t_11 = NULL; int __pyx_t_12; - PyArrayObject *__pyx_t_13 = NULL; - int __pyx_t_14; - PyObject *__pyx_t_15 = NULL; + int __pyx_t_13; + PyArrayObject *__pyx_t_14 = NULL; + int __pyx_t_15; PyObject *__pyx_t_16 = NULL; PyObject *__pyx_t_17 = NULL; + PyObject *__pyx_t_18 = NULL; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; @@ -1524,6 +1535,10 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb __pyx_pybuffer_w.refcount = 0; __pyx_pybuffernd_w.data = NULL; __pyx_pybuffernd_w.rcbuffer = &__pyx_pybuffer_w; + __pyx_pybuffer_n_iter.pybuffer.buf = NULL; + __pyx_pybuffer_n_iter.refcount = 0; + __pyx_pybuffernd_n_iter.data = NULL; + __pyx_pybuffernd_n_iter.rcbuffer = &__pyx_pybuffer_n_iter; __pyx_pybuffer_Y.pybuffer.buf = NULL; __pyx_pybuffer_Y.refcount = 0; __pyx_pybuffernd_Y.data = NULL; @@ -1807,22 +1822,109 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb * # coef matrix holder created as fortran since that's what's used in liblinear * cdef np.ndarray[np.float64_t, ndim=2, mode='fortran'] w * cdef int nr_class = get_nr_class(model) # <<<<<<<<<<<<<< - * cdef int nr_feature = get_nr_feature(model) - * if bias > 0: nr_feature = nr_feature + 1 + * + * cdef int labels_ = nr_class */ __pyx_v_nr_class = get_nr_class(__pyx_v_model); - /* "sklearn/svm/liblinear.pyx":58 - * cdef np.ndarray[np.float64_t, ndim=2, mode='fortran'] w + /* "sklearn/svm/liblinear.pyx":59 * cdef int nr_class = get_nr_class(model) + * + * cdef int labels_ = nr_class # <<<<<<<<<<<<<< + * if nr_class == 2: + * labels_ = 1 + */ + __pyx_v_labels_ = __pyx_v_nr_class; + + /* "sklearn/svm/liblinear.pyx":60 + * + * cdef int labels_ = nr_class + * if nr_class == 2: # <<<<<<<<<<<<<< + * labels_ = 1 + * cdef np.ndarray[np.int32_t, ndim=1, mode='c'] n_iter = np.zeros(labels_, dtype=np.int32) + */ + __pyx_t_1 = ((__pyx_v_nr_class == 2) != 0); + if (__pyx_t_1) { + + /* "sklearn/svm/liblinear.pyx":61 + * cdef int labels_ = nr_class + * if nr_class == 2: + * labels_ = 1 # <<<<<<<<<<<<<< + * cdef np.ndarray[np.int32_t, ndim=1, mode='c'] n_iter = np.zeros(labels_, dtype=np.int32) + * get_n_iter(model, n_iter.data) + */ + __pyx_v_labels_ = 1; + goto __pyx_L8; + } + __pyx_L8:; + + /* "sklearn/svm/liblinear.pyx":62 + * if nr_class == 2: + * labels_ = 1 + * cdef np.ndarray[np.int32_t, ndim=1, mode='c'] n_iter = np.zeros(labels_, dtype=np.int32) # <<<<<<<<<<<<<< + * get_n_iter(model, n_iter.data) + * + */ + __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_zeros); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_labels_); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_int32); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_dtype, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_4, __pyx_t_2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 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 = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_11 = ((PyArrayObject *)__pyx_t_3); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_n_iter.rcbuffer->pybuffer, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) { + __pyx_v_n_iter = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_n_iter.rcbuffer->pybuffer.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_pybuffernd_n_iter.diminfo[0].strides = __pyx_pybuffernd_n_iter.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_n_iter.diminfo[0].shape = __pyx_pybuffernd_n_iter.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_11 = 0; + __pyx_v_n_iter = ((PyArrayObject *)__pyx_t_3); + __pyx_t_3 = 0; + + /* "sklearn/svm/liblinear.pyx":63 + * labels_ = 1 + * cdef np.ndarray[np.int32_t, ndim=1, mode='c'] n_iter = np.zeros(labels_, dtype=np.int32) + * get_n_iter(model, n_iter.data) # <<<<<<<<<<<<<< + * + * cdef int nr_feature = get_nr_feature(model) + */ + get_n_iter(__pyx_v_model, ((int *)__pyx_v_n_iter->data)); + + /* "sklearn/svm/liblinear.pyx":65 + * get_n_iter(model, n_iter.data) + * * cdef int nr_feature = get_nr_feature(model) # <<<<<<<<<<<<<< * if bias > 0: nr_feature = nr_feature + 1 * if nr_class == 2 and solver_type != 4: # solver is not Crammer-Singer */ __pyx_v_nr_feature = get_nr_feature(__pyx_v_model); - /* "sklearn/svm/liblinear.pyx":59 - * cdef int nr_class = get_nr_class(model) + /* "sklearn/svm/liblinear.pyx":66 + * * cdef int nr_feature = get_nr_feature(model) * if bias > 0: nr_feature = nr_feature + 1 # <<<<<<<<<<<<<< * if nr_class == 2 and solver_type != 4: # solver is not Crammer-Singer @@ -1831,11 +1933,11 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb __pyx_t_1 = ((__pyx_v_bias > 0.0) != 0); if (__pyx_t_1) { __pyx_v_nr_feature = (__pyx_v_nr_feature + 1); - goto __pyx_L8; + goto __pyx_L9; } - __pyx_L8:; + __pyx_L9:; - /* "sklearn/svm/liblinear.pyx":60 + /* "sklearn/svm/liblinear.pyx":67 * cdef int nr_feature = get_nr_feature(model) * if bias > 0: nr_feature = nr_feature + 1 * if nr_class == 2 and solver_type != 4: # solver is not Crammer-Singer # <<<<<<<<<<<<<< @@ -1844,71 +1946,71 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb */ __pyx_t_1 = ((__pyx_v_nr_class == 2) != 0); if (__pyx_t_1) { - __pyx_t_11 = ((__pyx_v_solver_type != 4) != 0); - __pyx_t_12 = __pyx_t_11; + __pyx_t_12 = ((__pyx_v_solver_type != 4) != 0); + __pyx_t_13 = __pyx_t_12; } else { - __pyx_t_12 = __pyx_t_1; + __pyx_t_13 = __pyx_t_1; } - if (__pyx_t_12) { + if (__pyx_t_13) { - /* "sklearn/svm/liblinear.pyx":61 + /* "sklearn/svm/liblinear.pyx":68 * if bias > 0: nr_feature = nr_feature + 1 * if nr_class == 2 and solver_type != 4: # solver is not Crammer-Singer * w = np.empty((1, nr_feature),order='F') # <<<<<<<<<<<<<< * copy_w(w.data, model, nr_feature) * else: */ - __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); 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_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_empty); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_nr_feature); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); 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_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_empty); 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_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_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_nr_feature); 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 = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_4); __Pyx_INCREF(__pyx_int_1); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_int_1); __Pyx_GIVEREF(__pyx_int_1); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_2); - __pyx_t_2 = 0; - __pyx_t_2 = PyTuple_New(1); 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); - PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_3); + __Pyx_GIVEREF(__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 = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); __Pyx_GIVEREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_4); - if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_order, __pyx_n_s_F) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_2, __pyx_t_4); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_order, __pyx_n_s_F) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 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 = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_13 = ((PyArrayObject *)__pyx_t_5); + if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_14 = ((PyArrayObject *)__pyx_t_6); { __Pyx_BufFmt_StackElem __pyx_stack[1]; __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_w.rcbuffer->pybuffer); - __pyx_t_14 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_w.rcbuffer->pybuffer, (PyObject*)__pyx_t_13, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_F_CONTIGUOUS, 2, 0, __pyx_stack); - if (unlikely(__pyx_t_14 < 0)) { - PyErr_Fetch(&__pyx_t_15, &__pyx_t_16, &__pyx_t_17); + __pyx_t_15 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_w.rcbuffer->pybuffer, (PyObject*)__pyx_t_14, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_F_CONTIGUOUS, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_15 < 0)) { + PyErr_Fetch(&__pyx_t_16, &__pyx_t_17, &__pyx_t_18); if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_w.rcbuffer->pybuffer, (PyObject*)__pyx_v_w, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_F_CONTIGUOUS, 2, 0, __pyx_stack) == -1)) { - Py_XDECREF(__pyx_t_15); Py_XDECREF(__pyx_t_16); Py_XDECREF(__pyx_t_17); + Py_XDECREF(__pyx_t_16); Py_XDECREF(__pyx_t_17); Py_XDECREF(__pyx_t_18); __Pyx_RaiseBufferFallbackError(); } else { - PyErr_Restore(__pyx_t_15, __pyx_t_16, __pyx_t_17); + PyErr_Restore(__pyx_t_16, __pyx_t_17, __pyx_t_18); } } __pyx_pybuffernd_w.diminfo[0].strides = __pyx_pybuffernd_w.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_w.diminfo[0].shape = __pyx_pybuffernd_w.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_w.diminfo[1].strides = __pyx_pybuffernd_w.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_w.diminfo[1].shape = __pyx_pybuffernd_w.rcbuffer->pybuffer.shape[1]; - if (unlikely(__pyx_t_14 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (unlikely(__pyx_t_15 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} } - __pyx_t_13 = 0; - __pyx_v_w = ((PyArrayObject *)__pyx_t_5); - __pyx_t_5 = 0; + __pyx_t_14 = 0; + __pyx_v_w = ((PyArrayObject *)__pyx_t_6); + __pyx_t_6 = 0; - /* "sklearn/svm/liblinear.pyx":62 + /* "sklearn/svm/liblinear.pyx":69 * if nr_class == 2 and solver_type != 4: # solver is not Crammer-Singer * w = np.empty((1, nr_feature),order='F') * copy_w(w.data, model, nr_feature) # <<<<<<<<<<<<<< @@ -1916,11 +2018,11 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb * len_w = (nr_class) * nr_feature */ copy_w(__pyx_v_w->data, __pyx_v_model, __pyx_v_nr_feature); - goto __pyx_L9; + goto __pyx_L10; } /*else*/ { - /* "sklearn/svm/liblinear.pyx":64 + /* "sklearn/svm/liblinear.pyx":71 * copy_w(w.data, model, nr_feature) * else: * len_w = (nr_class) * nr_feature # <<<<<<<<<<<<<< @@ -1929,66 +2031,66 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb */ __pyx_v_len_w = (__pyx_v_nr_class * __pyx_v_nr_feature); - /* "sklearn/svm/liblinear.pyx":65 + /* "sklearn/svm/liblinear.pyx":72 * else: * len_w = (nr_class) * nr_feature * w = np.empty((nr_class, nr_feature),order='F') # <<<<<<<<<<<<<< * copy_w(w.data, model, len_w) * */ - __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_empty); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_empty); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_nr_class); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_nr_feature); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = __Pyx_PyInt_From_int(__pyx_v_nr_class); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_6); - PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); - __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_2); - __pyx_t_5 = 0; - __pyx_t_2 = 0; - __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_nr_feature); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_6); __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); __pyx_t_6 = 0; - __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_order, __pyx_n_s_F) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_3, __pyx_t_2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_6); - if (PyDict_SetItem(__pyx_t_6, __pyx_n_s_order, __pyx_n_s_F) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_2, __pyx_t_6); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __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_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 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 = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_t_13 = ((PyArrayObject *)__pyx_t_5); + if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_14 = ((PyArrayObject *)__pyx_t_6); { __Pyx_BufFmt_StackElem __pyx_stack[1]; __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_w.rcbuffer->pybuffer); - __pyx_t_14 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_w.rcbuffer->pybuffer, (PyObject*)__pyx_t_13, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_F_CONTIGUOUS, 2, 0, __pyx_stack); - if (unlikely(__pyx_t_14 < 0)) { - PyErr_Fetch(&__pyx_t_17, &__pyx_t_16, &__pyx_t_15); + __pyx_t_15 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_w.rcbuffer->pybuffer, (PyObject*)__pyx_t_14, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_F_CONTIGUOUS, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_15 < 0)) { + PyErr_Fetch(&__pyx_t_18, &__pyx_t_17, &__pyx_t_16); if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_w.rcbuffer->pybuffer, (PyObject*)__pyx_v_w, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_F_CONTIGUOUS, 2, 0, __pyx_stack) == -1)) { - Py_XDECREF(__pyx_t_17); Py_XDECREF(__pyx_t_16); Py_XDECREF(__pyx_t_15); + Py_XDECREF(__pyx_t_18); Py_XDECREF(__pyx_t_17); Py_XDECREF(__pyx_t_16); __Pyx_RaiseBufferFallbackError(); } else { - PyErr_Restore(__pyx_t_17, __pyx_t_16, __pyx_t_15); + PyErr_Restore(__pyx_t_18, __pyx_t_17, __pyx_t_16); } } __pyx_pybuffernd_w.diminfo[0].strides = __pyx_pybuffernd_w.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_w.diminfo[0].shape = __pyx_pybuffernd_w.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_w.diminfo[1].strides = __pyx_pybuffernd_w.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_w.diminfo[1].shape = __pyx_pybuffernd_w.rcbuffer->pybuffer.shape[1]; - if (unlikely(__pyx_t_14 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (unlikely(__pyx_t_15 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} } - __pyx_t_13 = 0; - __pyx_v_w = ((PyArrayObject *)__pyx_t_5); - __pyx_t_5 = 0; + __pyx_t_14 = 0; + __pyx_v_w = ((PyArrayObject *)__pyx_t_6); + __pyx_t_6 = 0; - /* "sklearn/svm/liblinear.pyx":66 + /* "sklearn/svm/liblinear.pyx":73 * len_w = (nr_class) * nr_feature * w = np.empty((nr_class, nr_feature),order='F') * copy_w(w.data, model, len_w) # <<<<<<<<<<<<<< @@ -1997,9 +2099,9 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb */ copy_w(__pyx_v_w->data, __pyx_v_model, __pyx_v_len_w); } - __pyx_L9:; + __pyx_L10:; - /* "sklearn/svm/liblinear.pyx":69 + /* "sklearn/svm/liblinear.pyx":76 * * ### FREE * free_and_destroy_model(&model) # <<<<<<<<<<<<<< @@ -2008,7 +2110,7 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb */ free_and_destroy_model((&__pyx_v_model)); - /* "sklearn/svm/liblinear.pyx":70 + /* "sklearn/svm/liblinear.pyx":77 * ### FREE * free_and_destroy_model(&model) * free_problem(problem) # <<<<<<<<<<<<<< @@ -2017,7 +2119,7 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb */ free_problem(__pyx_v_problem); - /* "sklearn/svm/liblinear.pyx":71 + /* "sklearn/svm/liblinear.pyx":78 * free_and_destroy_model(&model) * free_problem(problem) * free_parameter(param) # <<<<<<<<<<<<<< @@ -2026,16 +2128,24 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb */ free_parameter(__pyx_v_param); - /* "sklearn/svm/liblinear.pyx":74 + /* "sklearn/svm/liblinear.pyx":81 * # destroy_param(param) don't call this or it will destroy class_weight_label and class_weight * - * return w # <<<<<<<<<<<<<< + * return w, n_iter # <<<<<<<<<<<<<< * * */ __Pyx_XDECREF(__pyx_r); + __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); __Pyx_INCREF(((PyObject *)__pyx_v_w)); - __pyx_r = ((PyObject *)__pyx_v_w); + PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_v_w)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_w)); + __Pyx_INCREF(((PyObject *)__pyx_v_n_iter)); + PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_n_iter)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_n_iter)); + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; goto __pyx_L0; /* "sklearn/svm/liblinear.pyx":14 @@ -2060,6 +2170,7 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Y.rcbuffer->pybuffer); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_class_weight.rcbuffer->pybuffer); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_class_weight_label.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_n_iter.rcbuffer->pybuffer); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_w.rcbuffer->pybuffer); __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} __Pyx_AddTraceback("sklearn.svm.liblinear.train_wrap", __pyx_clineno, __pyx_lineno, __pyx_filename); @@ -2069,16 +2180,18 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_train_wrap(CYTHON_UNUSED PyOb __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Y.rcbuffer->pybuffer); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_class_weight.rcbuffer->pybuffer); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_class_weight_label.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_n_iter.rcbuffer->pybuffer); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_w.rcbuffer->pybuffer); __pyx_L2:; __Pyx_XDECREF((PyObject *)__pyx_v_class_weight_label); __Pyx_XDECREF((PyObject *)__pyx_v_w); + __Pyx_XDECREF((PyObject *)__pyx_v_n_iter); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "sklearn/svm/liblinear.pyx":77 +/* "sklearn/svm/liblinear.pyx":84 * * * def set_verbosity_wrap(int verbosity): # <<<<<<<<<<<<<< @@ -2099,7 +2212,7 @@ static PyObject *__pyx_pw_7sklearn_3svm_9liblinear_3set_verbosity_wrap(PyObject __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("set_verbosity_wrap (wrapper)", 0); assert(__pyx_arg_verbosity); { - __pyx_v_verbosity = __Pyx_PyInt_As_int(__pyx_arg_verbosity); if (unlikely((__pyx_v_verbosity == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_verbosity = __Pyx_PyInt_As_int(__pyx_arg_verbosity); if (unlikely((__pyx_v_verbosity == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } goto __pyx_L4_argument_unpacking_done; __pyx_L3_error:; @@ -2119,14 +2232,14 @@ static PyObject *__pyx_pf_7sklearn_3svm_9liblinear_2set_verbosity_wrap(CYTHON_UN __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("set_verbosity_wrap", 0); - /* "sklearn/svm/liblinear.pyx":81 + /* "sklearn/svm/liblinear.pyx":88 * Control verbosity of libsvm library * """ * set_verbosity(verbosity) # <<<<<<<<<<<<<< */ set_verbosity(__pyx_v_verbosity); - /* "sklearn/svm/liblinear.pyx":77 + /* "sklearn/svm/liblinear.pyx":84 * * * def set_verbosity_wrap(int verbosity): # <<<<<<<<<<<<<< @@ -4170,10 +4283,12 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_indptr, __pyx_k_indptr, sizeof(__pyx_k_indptr), 0, 0, 1, 1}, {&__pyx_n_s_int32, __pyx_k_int32, sizeof(__pyx_k_int32), 0, 0, 1, 1}, {&__pyx_n_s_is_sparse, __pyx_k_is_sparse, sizeof(__pyx_k_is_sparse), 0, 0, 1, 1}, + {&__pyx_n_s_labels, __pyx_k_labels, sizeof(__pyx_k_labels), 0, 0, 1, 1}, {&__pyx_n_s_len_w, __pyx_k_len_w, sizeof(__pyx_k_len_w), 0, 0, 1, 1}, {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, {&__pyx_n_s_max_iter, __pyx_k_max_iter, sizeof(__pyx_k_max_iter), 0, 0, 1, 1}, {&__pyx_n_s_model, __pyx_k_model, sizeof(__pyx_k_model), 0, 0, 1, 1}, + {&__pyx_n_s_n_iter, __pyx_k_n_iter, sizeof(__pyx_k_n_iter), 0, 0, 1, 1}, {&__pyx_kp_u_ndarray_is_not_C_contiguous, __pyx_k_ndarray_is_not_C_contiguous, sizeof(__pyx_k_ndarray_is_not_C_contiguous), 0, 1, 0, 0}, {&__pyx_kp_u_ndarray_is_not_Fortran_contiguou, __pyx_k_ndarray_is_not_Fortran_contiguou, sizeof(__pyx_k_ndarray_is_not_Fortran_contiguou), 0, 1, 0, 0}, {&__pyx_n_s_np, __pyx_k_np, sizeof(__pyx_k_np), 0, 0, 1, 1}, @@ -4196,6 +4311,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_k_unknown_dtype_code_in_numpy_pxd, sizeof(__pyx_k_unknown_dtype_code_in_numpy_pxd), 0, 1, 0, 0}, {&__pyx_n_s_verbosity, __pyx_k_verbosity, sizeof(__pyx_k_verbosity), 0, 0, 1, 1}, {&__pyx_n_s_w, __pyx_k_w, sizeof(__pyx_k_w), 0, 0, 1, 1}, + {&__pyx_n_s_zeros, __pyx_k_zeros, sizeof(__pyx_k_zeros), 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0} }; static int __Pyx_InitCachedBuiltins(void) { @@ -4284,22 +4400,22 @@ static int __Pyx_InitCachedConstants(void) { * bint is_sparse, int solver_type, double eps, double bias, * double C, np.ndarray[np.float64_t, ndim=1] class_weight, */ - __pyx_tuple__7 = PyTuple_Pack(19, __pyx_n_s_X, __pyx_n_s_Y, __pyx_n_s_is_sparse, __pyx_n_s_solver_type, __pyx_n_s_eps, __pyx_n_s_bias, __pyx_n_s_C, __pyx_n_s_class_weight, __pyx_n_s_max_iter, __pyx_n_s_random_seed, __pyx_n_s_param, __pyx_n_s_problem, __pyx_n_s_model, __pyx_n_s_error_msg, __pyx_n_s_len_w, __pyx_n_s_class_weight_label, __pyx_n_s_w, __pyx_n_s_nr_class, __pyx_n_s_nr_feature); if (unlikely(!__pyx_tuple__7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_tuple__7 = PyTuple_Pack(21, __pyx_n_s_X, __pyx_n_s_Y, __pyx_n_s_is_sparse, __pyx_n_s_solver_type, __pyx_n_s_eps, __pyx_n_s_bias, __pyx_n_s_C, __pyx_n_s_class_weight, __pyx_n_s_max_iter, __pyx_n_s_random_seed, __pyx_n_s_param, __pyx_n_s_problem, __pyx_n_s_model, __pyx_n_s_error_msg, __pyx_n_s_len_w, __pyx_n_s_class_weight_label, __pyx_n_s_w, __pyx_n_s_nr_class, __pyx_n_s_labels, __pyx_n_s_n_iter, __pyx_n_s_nr_feature); if (unlikely(!__pyx_tuple__7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_tuple__7); __Pyx_GIVEREF(__pyx_tuple__7); - __pyx_codeobj__8 = (PyObject*)__Pyx_PyCode_New(10, 0, 19, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__7, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_manoj_scikit_learn_sklearn, __pyx_n_s_train_wrap, 14, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_codeobj__8 = (PyObject*)__Pyx_PyCode_New(10, 0, 21, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__7, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_manoj_scikit_learn_sklearn, __pyx_n_s_train_wrap, 14, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /* "sklearn/svm/liblinear.pyx":77 + /* "sklearn/svm/liblinear.pyx":84 * * * def set_verbosity_wrap(int verbosity): # <<<<<<<<<<<<<< * """ * Control verbosity of libsvm library */ - __pyx_tuple__9 = PyTuple_Pack(2, __pyx_n_s_verbosity, __pyx_n_s_verbosity); if (unlikely(!__pyx_tuple__9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_tuple__9 = PyTuple_Pack(2, __pyx_n_s_verbosity, __pyx_n_s_verbosity); if (unlikely(!__pyx_tuple__9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_tuple__9); __Pyx_GIVEREF(__pyx_tuple__9); - __pyx_codeobj__10 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__9, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_manoj_scikit_learn_sklearn, __pyx_n_s_set_verbosity_wrap, 77, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_codeobj__10 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__9, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_manoj_scikit_learn_sklearn, __pyx_n_s_set_verbosity_wrap, 84, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; @@ -4445,16 +4561,16 @@ PyMODINIT_FUNC PyInit_liblinear(void) if (PyDict_SetItem(__pyx_d, __pyx_n_s_train_wrap, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "sklearn/svm/liblinear.pyx":77 + /* "sklearn/svm/liblinear.pyx":84 * * * def set_verbosity_wrap(int verbosity): # <<<<<<<<<<<<<< * """ * Control verbosity of libsvm library */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7sklearn_3svm_9liblinear_3set_verbosity_wrap, NULL, __pyx_n_s_sklearn_svm_liblinear); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7sklearn_3svm_9liblinear_3set_verbosity_wrap, NULL, __pyx_n_s_sklearn_svm_liblinear); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_set_verbosity_wrap, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyDict_SetItem(__pyx_d, __pyx_n_s_set_verbosity_wrap, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "sklearn/svm/liblinear.pyx":1 diff --git a/sklearn/svm/liblinear.pxd b/sklearn/svm/liblinear.pxd index 8ac78b594c753..878323762a1bb 100644 --- a/sklearn/svm/liblinear.pxd +++ b/sklearn/svm/liblinear.pxd @@ -13,6 +13,7 @@ cdef extern from "src/liblinear/linear.h": model *train(problem_const_ptr prob, parameter_const_ptr param) nogil int get_nr_feature (model *model) int get_nr_class (model *model) + void get_n_iter (model *model, int *n_iter) void free_and_destroy_model (model **) void destroy_param (parameter *) diff --git a/sklearn/svm/liblinear.pyx b/sklearn/svm/liblinear.pyx index 289024ead87c1..1e970b9b19dae 100644 --- a/sklearn/svm/liblinear.pyx +++ b/sklearn/svm/liblinear.pyx @@ -55,6 +55,13 @@ def train_wrap(X, np.ndarray[np.float64_t, ndim=1, mode='c'] Y, # coef matrix holder created as fortran since that's what's used in liblinear cdef np.ndarray[np.float64_t, ndim=2, mode='fortran'] w cdef int nr_class = get_nr_class(model) + + cdef int labels_ = nr_class + if nr_class == 2: + labels_ = 1 + cdef np.ndarray[np.int32_t, ndim=1, mode='c'] n_iter = np.zeros(labels_, dtype=np.int32) + get_n_iter(model, n_iter.data) + cdef int nr_feature = get_nr_feature(model) if bias > 0: nr_feature = nr_feature + 1 if nr_class == 2 and solver_type != 4: # solver is not Crammer-Singer @@ -71,7 +78,7 @@ def train_wrap(X, np.ndarray[np.float64_t, ndim=1, mode='c'] Y, free_parameter(param) # destroy_param(param) don't call this or it will destroy class_weight_label and class_weight - return w + return w, n_iter def set_verbosity_wrap(int verbosity): diff --git a/sklearn/svm/src/liblinear/linear.cpp b/sklearn/svm/src/liblinear/linear.cpp index 761edc669e3bc..383c301e6634b 100644 --- a/sklearn/svm/src/liblinear/linear.cpp +++ b/sklearn/svm/src/liblinear/linear.cpp @@ -480,7 +480,7 @@ class Solver_MCSVM_CS public: Solver_MCSVM_CS(const problem *prob, int nr_class, double *C, double eps=0.1, int max_iter=100000); ~Solver_MCSVM_CS(); - void Solve(double *w); + int Solve(double *w); private: void solve_sub_problem(double A_i, int yi, double C_yi, int active_i, double *alpha_new); bool be_shrunk(int i, int m, int yi, double alpha_i, double minG); @@ -555,7 +555,7 @@ bool Solver_MCSVM_CS::be_shrunk(int i, int m, int yi, double alpha_i, double min return false; } -void Solver_MCSVM_CS::Solve(double *w) +int Solver_MCSVM_CS::Solve(double *w) { int i, m, s; int iter = 0; @@ -765,6 +765,7 @@ void Solver_MCSVM_CS::Solve(double *w) delete [] alpha_index; delete [] y_index; delete [] active_size_i; + return iter; } // A coordinate descent algorithm for @@ -797,7 +798,7 @@ void Solver_MCSVM_CS::Solve(double *w) #define GETI(i) (y[i]+1) // To support weights for instances, use GETI(i) (i) -static void solve_l2r_l1l2_svc( +static int solve_l2r_l1l2_svc( const problem *prob, double *w, double eps, double Cp, double Cn, int solver_type, int max_iter) { @@ -983,6 +984,7 @@ static void solve_l2r_l1l2_svc( delete [] alpha; delete [] y; delete [] index; + return iter; } @@ -1014,7 +1016,7 @@ static void solve_l2r_l1l2_svc( #define GETI(i) (0) // To support weights for instances, use GETI(i) (i) -static void solve_l2r_l1l2_svr( +static int solve_l2r_l1l2_svr( const problem *prob, double *w, const parameter *param, int solver_type, int max_iter) { @@ -1215,6 +1217,7 @@ static void solve_l2r_l1l2_svr( delete [] beta; delete [] QD; delete [] index; + return iter; } @@ -1240,7 +1243,7 @@ static void solve_l2r_l1l2_svr( #define GETI(i) (y[i]+1) // To support weights for instances, use GETI(i) (i) -void solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, double Cn, +int solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, double Cn, int max_iter) { int l = prob->l; @@ -1395,6 +1398,7 @@ void solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, do delete [] alpha; delete [] y; delete [] index; + return iter; } // A coordinate descent algorithm for @@ -1414,7 +1418,7 @@ void solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, do #define GETI(i) (y[i]+1) // To support weights for instances, use GETI(i) (i) -static void solve_l1r_l2_svc( +static int solve_l1r_l2_svc( problem *prob_col, double *w, double eps, double Cp, double Cn, int max_iter) { @@ -1681,6 +1685,7 @@ static void solve_l1r_l2_svc( delete [] y; delete [] b; delete [] xj_sq; + return iter; } // A coordinate descent algorithm for @@ -1700,7 +1705,7 @@ static void solve_l1r_l2_svc( #define GETI(i) (y[i]+1) // To support weights for instances, use GETI(i) (i) -static void solve_l1r_lr( +static int solve_l1r_lr( const problem *prob_col, double *w, double eps, double Cp, double Cn, int max_newton_iter) { @@ -2061,6 +2066,7 @@ static void solve_l1r_lr( delete [] exp_wTx_new; delete [] tau; delete [] D; + return newton_iter; } // transpose matrix X from row format to column format @@ -2211,12 +2217,13 @@ static void group_classes(const problem *prob, int *nr_class_ret, int **label_re free(data_label); } -static void train_one(const problem *prob, const parameter *param, double *w, double Cp, double Cn) +static int train_one(const problem *prob, const parameter *param, double *w, double Cp, double Cn) { double eps=param->eps; int max_iter=param->max_iter; int pos = 0; int neg = 0; + int n_iter; for(int i=0;il;i++) if(prob->y[i] > 0) pos++; @@ -2240,7 +2247,7 @@ static void train_one(const problem *prob, const parameter *param, double *w, do fun_obj=new l2r_lr_fun(prob, C); TRON tron_obj(fun_obj, primal_solver_tol, max_iter); tron_obj.set_print_string(liblinear_print_string); - tron_obj.tron(w); + n_iter=tron_obj.tron(w); delete fun_obj; delete [] C; break; @@ -2258,23 +2265,23 @@ static void train_one(const problem *prob, const parameter *param, double *w, do fun_obj=new l2r_l2_svc_fun(prob, C); TRON tron_obj(fun_obj, primal_solver_tol, max_iter); tron_obj.set_print_string(liblinear_print_string); - tron_obj.tron(w); + n_iter=tron_obj.tron(w); delete fun_obj; delete [] C; break; } case L2R_L2LOSS_SVC_DUAL: - solve_l2r_l1l2_svc(prob, w, eps, Cp, Cn, L2R_L2LOSS_SVC_DUAL, max_iter); + n_iter=solve_l2r_l1l2_svc(prob, w, eps, Cp, Cn, L2R_L2LOSS_SVC_DUAL, max_iter); break; case L2R_L1LOSS_SVC_DUAL: - solve_l2r_l1l2_svc(prob, w, eps, Cp, Cn, L2R_L1LOSS_SVC_DUAL, max_iter); + n_iter=solve_l2r_l1l2_svc(prob, w, eps, Cp, Cn, L2R_L1LOSS_SVC_DUAL, max_iter); break; case L1R_L2LOSS_SVC: { problem prob_col; feature_node *x_space = NULL; transpose(prob, &x_space ,&prob_col); - solve_l1r_l2_svc(&prob_col, w, primal_solver_tol, Cp, Cn, max_iter); + n_iter=solve_l1r_l2_svc(&prob_col, w, primal_solver_tol, Cp, Cn, max_iter); delete [] prob_col.y; delete [] prob_col.x; delete [] x_space; @@ -2285,14 +2292,14 @@ static void train_one(const problem *prob, const parameter *param, double *w, do problem prob_col; feature_node *x_space = NULL; transpose(prob, &x_space ,&prob_col); - solve_l1r_lr(&prob_col, w, primal_solver_tol, Cp, Cn, max_iter); + n_iter=solve_l1r_lr(&prob_col, w, primal_solver_tol, Cp, Cn, max_iter); delete [] prob_col.y; delete [] prob_col.x; delete [] x_space; break; } case L2R_LR_DUAL: - solve_l2r_lr_dual(prob, w, eps, Cp, Cn, max_iter); + n_iter=solve_l2r_lr_dual(prob, w, eps, Cp, Cn, max_iter); break; case L2R_L2LOSS_SVR: { @@ -2303,22 +2310,23 @@ static void train_one(const problem *prob, const parameter *param, double *w, do fun_obj=new l2r_l2_svr_fun(prob, C, param->p); TRON tron_obj(fun_obj, param->eps, max_iter); tron_obj.set_print_string(liblinear_print_string); - tron_obj.tron(w); + n_iter=tron_obj.tron(w); delete fun_obj; delete [] C; break; } case L2R_L1LOSS_SVR_DUAL: - solve_l2r_l1l2_svr(prob, w, param, L2R_L1LOSS_SVR_DUAL, max_iter); + n_iter=solve_l2r_l1l2_svr(prob, w, param, L2R_L1LOSS_SVR_DUAL, max_iter); break; case L2R_L2LOSS_SVR_DUAL: - solve_l2r_l1l2_svr(prob, w, param, L2R_L2LOSS_SVR_DUAL, max_iter); + n_iter=solve_l2r_l1l2_svr(prob, w, param, L2R_L2LOSS_SVR_DUAL, max_iter); break; default: fprintf(stderr, "ERROR: unknown solver_type\n"); break; } + return n_iter; } // @@ -2330,6 +2338,7 @@ model* train(const problem *prob, const parameter *param) int l = prob->l; int n = prob->n; int w_size = prob->n; + int n_iter; model *model_ = Malloc(model,1); if(prob->bias>=0) @@ -2344,9 +2353,10 @@ model* train(const problem *prob, const parameter *param) param->solver_type == L2R_L2LOSS_SVR_DUAL) { model_->w = Malloc(double, w_size); + model_->n_iter = Malloc(int, 1); model_->nr_class = 2; model_->label = NULL; - train_one(prob, param, &model_->w[0], 0, 0); + model_->n_iter[0] =train_one(prob, param, &model_->w[0], 0, 0); } else { @@ -2398,18 +2408,19 @@ model* train(const problem *prob, const parameter *param) if(param->solver_type == MCSVM_CS) { model_->w=Malloc(double, n*nr_class); + model_->n_iter=Malloc(int, 1); for(i=0;ieps); - Solver.Solve(model_->w); + model_->n_iter[0]=Solver.Solve(model_->w); } else { if(nr_class == 2) { model_->w=Malloc(double, w_size); - + model_->n_iter=Malloc(int, 1); int e0 = start[0]+count[0]; k=0; for(; kw[0], weighted_C[1], weighted_C[0]); + model_->n_iter[0]=train_one(&sub_prob, param, &model_->w[0], weighted_C[1], weighted_C[0]); } else { model_->w=Malloc(double, w_size*nr_class); double *w=Malloc(double, w_size); + model_->n_iter=Malloc(int, nr_class); for(i=0;iC); + model_->n_iter[i]=train_one(&sub_prob, param, w, weighted_C[i], param->C); for(int j=0;jw[j*nr_class+i] = w[j]; @@ -2795,6 +2807,17 @@ void get_labels(const model *model_, int* label) label[i] = model_->label[i]; } +void get_n_iter(const model *model_, int* n_iter) +{ + int labels; + labels = model_->nr_class; + if (labels == 2) + labels = 1; + if (model_->n_iter != NULL) + for(int i=0;in_iter[i]; +} + void free_model_content(struct model *model_ptr) { if(model_ptr->w != NULL) diff --git a/sklearn/svm/src/liblinear/linear.h b/sklearn/svm/src/liblinear/linear.h index 1392ad9e285f9..489cce25ce822 100644 --- a/sklearn/svm/src/liblinear/linear.h +++ b/sklearn/svm/src/liblinear/linear.h @@ -43,6 +43,7 @@ struct model double *w; int *label; /* label of each class */ double bias; + int *n_iter; /* no. of iterations of each class */ }; struct model* train(const struct problem *prob, const struct parameter *param); @@ -58,6 +59,7 @@ struct model *load_model(const char *model_file_name); int get_nr_feature(const struct model *model_); int get_nr_class(const struct model *model_); void get_labels(const struct model *model_, int* label); +void get_n_iter(const struct model *model_, int* n_iter); void free_model_content(struct model *model_ptr); void free_and_destroy_model(struct model **model_ptr_ptr); diff --git a/sklearn/svm/src/liblinear/tron.cpp b/sklearn/svm/src/liblinear/tron.cpp index a35c1023d7bc8..38dd921bc8e38 100644 --- a/sklearn/svm/src/liblinear/tron.cpp +++ b/sklearn/svm/src/liblinear/tron.cpp @@ -44,7 +44,7 @@ TRON::~TRON() { } -void TRON::tron(double *w) +int TRON::tron(double *w) { // Parameters for updating the iterates. double eta0 = 1e-4, eta1 = 0.25, eta2 = 0.75; @@ -146,6 +146,7 @@ void TRON::tron(double *w) delete[] r; delete[] w_new; delete[] s; + return --iter; } int TRON::trcg(double delta, double *g, double *s, double *r) diff --git a/sklearn/svm/src/liblinear/tron.h b/sklearn/svm/src/liblinear/tron.h index 3045c2e83a133..3349b83f6418a 100644 --- a/sklearn/svm/src/liblinear/tron.h +++ b/sklearn/svm/src/liblinear/tron.h @@ -18,7 +18,7 @@ class TRON TRON(const function *fun_obj, double eps = 0.1, int max_iter = 1000); ~TRON(); - void tron(double *w); + int tron(double *w); void set_print_string(void (*i_print) (const char *buf)); private: diff --git a/sklearn/tests/test_common.py b/sklearn/tests/test_common.py index 920aab6bba2be..d290992735dfe 100644 --- a/sklearn/tests/test_common.py +++ b/sklearn/tests/test_common.py @@ -320,12 +320,13 @@ def test_non_transformer_estimators_n_iter(): # libsvm and accessing the iter parameter is non-trivial. if name in (['Ridge', 'SVR', 'NuSVR', 'NuSVC', 'RidgeClassifier', 'SVC', 'RandomizedLasso', - 'LogisticRegressionCV', 'LogisticRegression', - 'LinearSVC']): + 'LogisticRegressionCV']): continue # Tested in test_transformer_n_iter below - elif name in CROSS_DECOMPOSITION: + elif name in CROSS_DECOMPOSITION or ( + name in ['LinearSVC', 'LogisticRegression'] + ): continue else: @@ -342,7 +343,6 @@ def test_transformer_n_iter(): # Dependent on external solvers and hence accessing the iter # param is non-trivial. external_solver = ['Isomap', 'KernelPCA', 'LocallyLinearEmbedding', - 'RandomizedLasso', 'LogisticRegression', - 'LogisticRegressionCV', 'LinearSVC'] + 'RandomizedLasso','LogisticRegressionCV'] if hasattr(estimator, "max_iter") and name not in external_solver: yield check_transformer_n_iter, name, estimator