Xgboost: feature_names no coinciden al usar matrices dispersas en Python

Creado en 31 may. 2016  ·  51Comentarios  ·  Fuente: dmlc/xgboost

Recibo ValueError: feature_names no coinciden mientras entreno xgboost con matrices dispersas en python.
La versión de xgboost es la última de git. Las versiones anteriores no dan este error. El error se devuelve durante el tiempo de predicción.

código

from scipy import sparse
import xgboost as xgb
from random import *
randBinList = lambda n: [randint(0,1) for b in range(1,n+1)]

train = sparse.rand(100,500)
test = sparse.rand(10, 500)
y = randBinList(100)
clf = xgb.XGBClassifier()
clf.fit(train,y)
preds = clf.predict_proba(test)

Rastreo completo:

ValueError                                Traceback (most recent call last)
<ipython-input-15-e03f10289bf1> in <module>()
----> 1 preds = clf.predict_proba(test)

/usr/local/lib/python2.7/dist-packages/xgboost-0.4-py2.7.egg/xgboost/sklearn.pyc in predict_proba(self, data, output_margin, ntree_limit)
    471         class_probs = self.booster().predict(test_dmatrix,
    472                                              output_margin=output_margin,
--> 473                                              ntree_limit=ntree_limit)
    474         if self.objective == "multi:softprob":
    475             return class_probs

/usr/local/lib/python2.7/dist-packages/xgboost-0.4-py2.7.egg/xgboost/core.pyc in predict(self, data, output_margin, ntree_limit, pred_leaf)
    937             option_mask |= 0x02
    938 
--> 939         self._validate_features(data)
    940 
    941         length = ctypes.c_ulong()

/usr/local/lib/python2.7/dist-packages/xgboost-0.4-py2.7.egg/xgboost/core.pyc in _validate_features(self, data)
   1177 
   1178                 raise ValueError(msg.format(self.feature_names,
-> 1179                                             data.feature_names))
   1180 
   1181     def get_split_value_histogram(self, feature, fmap='', bins=None, as_pandas=True):

ValueError: feature_names mismatch: ['f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'f11', 'f12', 'f13', 'f14', 'f15', 'f16', 'f17', 'f18', 'f19', 'f20', 'f21', 'f22', 'f23', 'f24', 'f25', 'f26', 'f27', 'f28', 'f29', 'f30', 'f31', 'f32', 'f33', 'f34', 'f35', 'f36', 'f37', 'f38', 'f39', 'f40', 'f41', 'f42', 'f43', 'f44', 'f45', 'f46', 'f47', 'f48', 'f49', 'f50', 'f51', 'f52', 'f53', 'f54', 'f55', 'f56', 'f57', 'f58', 'f59', 'f60', 'f61', 'f62', 'f63', 'f64', 'f65', 'f66', 'f67', 'f68', 'f69', 'f70', 'f71', 'f72', 'f73', 'f74', 'f75', 'f76', 'f77', 'f78', 'f79', 'f80', 'f81', 'f82', 'f83', 'f84', 'f85', 'f86', 'f87', 'f88', 'f89', 'f90', 'f91', 'f92', 'f93', 'f94', 'f95', 'f96', 'f97', 'f98', 'f99', 'f100', 'f101', 'f102', 'f103', 'f104', 'f105', 'f106', 'f107', 'f108', 'f109', 'f110', 'f111', 'f112', 'f113', 'f114', 'f115', 'f116', 'f117', 'f118', 'f119', 'f120', 'f121', 'f122', 'f123', 'f124', 'f125', 'f126', 'f127', 'f128', 'f129', 'f130', 'f131', 'f132', 'f133', 'f134', 'f135', 'f136', 'f137', 'f138', 'f139', 'f140', 'f141', 'f142', 'f143', 'f144', 'f145', 'f146', 'f147', 'f148', 'f149', 'f150', 'f151', 'f152', 'f153', 'f154', 'f155', 'f156', 'f157', 'f158', 'f159', 'f160', 'f161', 'f162', 'f163', 'f164', 'f165', 'f166', 'f167', 'f168', 'f169', 'f170', 'f171', 'f172', 'f173', 'f174', 'f175', 'f176', 'f177', 'f178', 'f179', 'f180', 'f181', 'f182', 'f183', 'f184', 'f185', 'f186', 'f187', 'f188', 'f189', 'f190', 'f191', 'f192', 'f193', 'f194', 'f195', 'f196', 'f197', 'f198', 'f199', 'f200', 'f201', 'f202', 'f203', 'f204', 'f205', 'f206', 'f207', 'f208', 'f209', 'f210', 'f211', 'f212', 'f213', 'f214', 'f215', 'f216', 'f217', 'f218', 'f219', 'f220', 'f221', 'f222', 'f223', 'f224', 'f225', 'f226', 'f227', 'f228', 'f229', 'f230', 'f231', 'f232', 'f233', 'f234', 'f235', 'f236', 'f237', 'f238', 'f239', 'f240', 'f241', 'f242', 'f243', 'f244', 'f245', 'f246', 'f247', 'f248', 'f249', 'f250', 'f251', 'f252', 'f253', 'f254', 'f255', 'f256', 'f257', 'f258', 'f259', 'f260', 'f261', 'f262', 'f263', 'f264', 'f265', 'f266', 'f267', 'f268', 'f269', 'f270', 'f271', 'f272', 'f273', 'f274', 'f275', 'f276', 'f277', 'f278', 'f279', 'f280', 'f281', 'f282', 'f283', 'f284', 'f285', 'f286', 'f287', 'f288', 'f289', 'f290', 'f291', 'f292', 'f293', 'f294', 'f295', 'f296', 'f297', 'f298', 'f299', 'f300', 'f301', 'f302', 'f303', 'f304', 'f305', 'f306', 'f307', 'f308', 'f309', 'f310', 'f311', 'f312', 'f313', 'f314', 'f315', 'f316', 'f317', 'f318', 'f319', 'f320', 'f321', 'f322', 'f323', 'f324', 'f325', 'f326', 'f327', 'f328', 'f329', 'f330', 'f331', 'f332', 'f333', 'f334', 'f335', 'f336', 'f337', 'f338', 'f339', 'f340', 'f341', 'f342', 'f343', 'f344', 'f345', 'f346', 'f347', 'f348', 'f349', 'f350', 'f351', 'f352', 'f353', 'f354', 'f355', 'f356', 'f357', 'f358', 'f359', 'f360', 'f361', 'f362', 'f363', 'f364', 'f365', 'f366', 'f367', 'f368', 'f369', 'f370', 'f371', 'f372', 'f373', 'f374', 'f375', 'f376', 'f377', 'f378', 'f379', 'f380', 'f381', 'f382', 'f383', 'f384', 'f385', 'f386', 'f387', 'f388', 'f389', 'f390', 'f391', 'f392', 'f393', 'f394', 'f395', 'f396', 'f397', 'f398', 'f399', 'f400', 'f401', 'f402', 'f403', 'f404', 'f405', 'f406', 'f407', 'f408', 'f409', 'f410', 'f411', 'f412', 'f413', 'f414', 'f415', 'f416', 'f417', 'f418', 'f419', 'f420', 'f421', 'f422', 'f423', 'f424', 'f425', 'f426', 'f427', 'f428', 'f429', 'f430', 'f431', 'f432', 'f433', 'f434', 'f435', 'f436', 'f437', 'f438', 'f439', 'f440', 'f441', 'f442', 'f443', 'f444', 'f445', 'f446', 'f447', 'f448', 'f449', 'f450', 'f451', 'f452', 'f453', 'f454', 'f455', 'f456', 'f457', 'f458', 'f459', 'f460', 'f461', 'f462', 'f463', 'f464', 'f465', 'f466', 'f467', 'f468', 'f469', 'f470', 'f471', 'f472', 'f473', 'f474', 'f475', 'f476', 'f477', 'f478', 'f479', 'f480', 'f481', 'f482', 'f483', 'f484', 'f485', 'f486', 'f487', 'f488', 'f489', 'f490', 'f491', 'f492', 'f493', 'f494', 'f495', 'f496', 'f497', 'f498'] ['f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'f11', 'f12', 'f13', 'f14', 'f15', 'f16', 'f17', 'f18', 'f19', 'f20', 'f21', 'f22', 'f23', 'f24', 'f25', 'f26', 'f27', 'f28', 'f29', 'f30', 'f31', 'f32', 'f33', 'f34', 'f35', 'f36', 'f37', 'f38', 'f39', 'f40', 'f41', 'f42', 'f43', 'f44', 'f45', 'f46', 'f47', 'f48', 'f49', 'f50', 'f51', 'f52', 'f53', 'f54', 'f55', 'f56', 'f57', 'f58', 'f59', 'f60', 'f61', 'f62', 'f63', 'f64', 'f65', 'f66', 'f67', 'f68', 'f69', 'f70', 'f71', 'f72', 'f73', 'f74', 'f75', 'f76', 'f77', 'f78', 'f79', 'f80', 'f81', 'f82', 'f83', 'f84', 'f85', 'f86', 'f87', 'f88', 'f89', 'f90', 'f91', 'f92', 'f93', 'f94', 'f95', 'f96', 'f97', 'f98', 'f99', 'f100', 'f101', 'f102', 'f103', 'f104', 'f105', 'f106', 'f107', 'f108', 'f109', 'f110', 'f111', 'f112', 'f113', 'f114', 'f115', 'f116', 'f117', 'f118', 'f119', 'f120', 'f121', 'f122', 'f123', 'f124', 'f125', 'f126', 'f127', 'f128', 'f129', 'f130', 'f131', 'f132', 'f133', 'f134', 'f135', 'f136', 'f137', 'f138', 'f139', 'f140', 'f141', 'f142', 'f143', 'f144', 'f145', 'f146', 'f147', 'f148', 'f149', 'f150', 'f151', 'f152', 'f153', 'f154', 'f155', 'f156', 'f157', 'f158', 'f159', 'f160', 'f161', 'f162', 'f163', 'f164', 'f165', 'f166', 'f167', 'f168', 'f169', 'f170', 'f171', 'f172', 'f173', 'f174', 'f175', 'f176', 'f177', 'f178', 'f179', 'f180', 'f181', 'f182', 'f183', 'f184', 'f185', 'f186', 'f187', 'f188', 'f189', 'f190', 'f191', 'f192', 'f193', 'f194', 'f195', 'f196', 'f197', 'f198', 'f199', 'f200', 'f201', 'f202', 'f203', 'f204', 'f205', 'f206', 'f207', 'f208', 'f209', 'f210', 'f211', 'f212', 'f213', 'f214', 'f215', 'f216', 'f217', 'f218', 'f219', 'f220', 'f221', 'f222', 'f223', 'f224', 'f225', 'f226', 'f227', 'f228', 'f229', 'f230', 'f231', 'f232', 'f233', 'f234', 'f235', 'f236', 'f237', 'f238', 'f239', 'f240', 'f241', 'f242', 'f243', 'f244', 'f245', 'f246', 'f247', 'f248', 'f249', 'f250', 'f251', 'f252', 'f253', 'f254', 'f255', 'f256', 'f257', 'f258', 'f259', 'f260', 'f261', 'f262', 'f263', 'f264', 'f265', 'f266', 'f267', 'f268', 'f269', 'f270', 'f271', 'f272', 'f273', 'f274', 'f275', 'f276', 'f277', 'f278', 'f279', 'f280', 'f281', 'f282', 'f283', 'f284', 'f285', 'f286', 'f287', 'f288', 'f289', 'f290', 'f291', 'f292', 'f293', 'f294', 'f295', 'f296', 'f297', 'f298', 'f299', 'f300', 'f301', 'f302', 'f303', 'f304', 'f305', 'f306', 'f307', 'f308', 'f309', 'f310', 'f311', 'f312', 'f313', 'f314', 'f315', 'f316', 'f317', 'f318', 'f319', 'f320', 'f321', 'f322', 'f323', 'f324', 'f325', 'f326', 'f327', 'f328', 'f329', 'f330', 'f331', 'f332', 'f333', 'f334', 'f335', 'f336', 'f337', 'f338', 'f339', 'f340', 'f341', 'f342', 'f343', 'f344', 'f345', 'f346', 'f347', 'f348', 'f349', 'f350', 'f351', 'f352', 'f353', 'f354', 'f355', 'f356', 'f357', 'f358', 'f359', 'f360', 'f361', 'f362', 'f363', 'f364', 'f365', 'f366', 'f367', 'f368', 'f369', 'f370', 'f371', 'f372', 'f373', 'f374', 'f375', 'f376', 'f377', 'f378', 'f379', 'f380', 'f381', 'f382', 'f383', 'f384', 'f385', 'f386', 'f387', 'f388', 'f389', 'f390', 'f391', 'f392', 'f393', 'f394', 'f395', 'f396', 'f397', 'f398', 'f399', 'f400', 'f401', 'f402', 'f403', 'f404', 'f405', 'f406', 'f407', 'f408', 'f409', 'f410', 'f411', 'f412', 'f413', 'f414', 'f415', 'f416', 'f417', 'f418', 'f419', 'f420', 'f421', 'f422', 'f423', 'f424', 'f425', 'f426', 'f427', 'f428', 'f429', 'f430', 'f431', 'f432', 'f433', 'f434', 'f435', 'f436', 'f437', 'f438', 'f439', 'f440', 'f441', 'f442', 'f443', 'f444', 'f445', 'f446', 'f447', 'f448', 'f449', 'f450', 'f451', 'f452', 'f453', 'f454', 'f455', 'f456', 'f457', 'f458', 'f459', 'f460', 'f461', 'f462', 'f463', 'f464', 'f465', 'f466', 'f467', 'f468', 'f469', 'f470', 'f471', 'f472', 'f473', 'f474', 'f475', 'f476', 'f477', 'f478', 'f479', 'f480', 'f481', 'f482', 'f483', 'f484', 'f485', 'f486', 'f487', 'f488', 'f489', 'f490', 'f491', 'f492', 'f493', 'f494', 'f495', 'f496', 'f497', 'f498', 'f499']
training data did not have the following fields: f499

Comentario más útil

El problema ocurre debido a que DMatrix..num_col () solo devuelve la cantidad de columnas distintas de cero en una matriz dispersa. Por lo tanto, si tanto los datos de entrenamiento como los de prueba tienen la misma cantidad de columnas distintas de cero, todo funciona bien.
De lo contrario, terminará con listas de nombres de funciones diferentes, porque las funciones de validación llaman:

    <strong i="7">@property</strong>
    def feature_names(self):
        """Get feature names (column labels).

        Returns
        -------
        feature_names : list or None
        """
        if self._feature_names is None:
            return ['f{0}'.format(i) for i in range(self.num_col())]
        else:
            return self._feature_names

self._feature_names es None para matrices dispersas, y debido a que self.num_col () devuelve solo la cantidad de columnas distintas de cero, la validación falla tan pronto como la cantidad de columnas distintas de cero en el "to-be- Los datos predichos "difieren de la cantidad de columnas distintas de cero en los datos de entrenamiento.

Sin embargo, todavía no sé dónde es el mejor lugar para arreglar eso.

Todos 51 comentarios

Parece que esto solo funciona si las matrices dispersas son CSC. No funciona para matrices CSR o COO como versiones anteriores.

¿No ocurre un problema aleatorio cuando las columnas de la derecha son 0 o 1? Quizás lo mismo que el # 1091 y el # 1221.

@sinhrks : Para mí, eso no es "aleatorio". Con frecuencia entreno XGBoost con datos muy escasos (¡y es increíble! Normalmente supera a todos los demás modelos, y por un margen bastante amplio).

Luego, una vez que tenga el modelo entrenado ejecutándose en producción, por supuesto, querré hacer predicciones sobre una nueva pieza de datos entrantes. Es muy probable que esos datos, por supuesto, sean escasos y no tengan un valor para cualquier columna que sea la última. Entonces, XGBoost ahora se rompe con frecuencia para mí, y me encontré cambiando a otros modelos (menos precisos), simplemente porque tienen un mejor soporte para datos escasos.

¿Alguien sabe exactamente por qué surge este error y cómo solucionarlo? Este es un punto doloroso para mí, ya que mis scripts existentes están fallando.

Estoy probando xgboost como parte de una canalización de sklearn y encontré el mismo problema. ¿Existe una solución alternativa hasta que se solucione?

Sí, cuando llame a predecir, use la función toarray () de la matriz dispersa. Es terriblemente ineficaz con la memoria, pero se puede trabajar con porciones pequeñas.

Enviado desde mi iPhone

El 26 de agosto de 2016, a las 10:44 p.m., Pedro Rodríguez [email protected] escribió:

Estoy probando xgboost como parte de una canalización de sklearn y encontré el mismo problema. ¿Existe una solución alternativa hasta que se solucione?

-
Estás recibiendo esto porque hiciste un comentario.
Responda a este correo electrónico directamente, véalo en GitHub o silencie el hilo.

Por alguna razón, el error no se produce si guardo y cargo el modelo entrenado:

    bst = xgb.train(param, dtrain, num_round)

    # predict is not working without this code
    bst.save_model(model_file_name)
    bst = xgb.Booster(param)
    bst.load_model(model_file_name)

    preds = bst.predict(dtest)

@ bryan-woods Pude encontrar un trabajo mejor con tocsc . Probablemente haya alguna penalización en el rendimiento, pero no tan mala como convertirla en una matriz densa.

Incluyendo esto en mi canalización de sklearn justo antes de que xgboost funcionara

class CSCTransformer(TransformerMixin):
    def transform(self, X, y=None, **fit_params):
        return X.tocsc()

    def fit_transform(self, X, y=None, **fit_params):
        self.fit(X, y, **fit_params)
        return self.transform(X)

    def fit(self, X, y=None, **fit_params):
        return self

    def get_params(self, deep=True):
        return {}

Ni el formato CSC ni la adición de entradas distintas de cero en la última columna solucionan el problema en la versión más reciente de xgboost. Volver a la versión 0.4a30 es lo único que puedo hacer que funcione, considere el siguiente ajuste (con una semilla reproducible) en el ejemplo original:

>>> import xgboost as xgb
>>> import numpy as np
>>> from scipy import sparse
>>> 
>>> np.random.seed(10)
>>> X = sparse.rand(100,10).tocsr()
>>> test = sparse.rand(10, 500).tocsr()
>>> y = np.random.randint(2,size=100)
>>> 
>>> clf = xgb.XGBClassifier()
>>> clf.fit(X,y)
XGBClassifier(base_score=0.5, colsample_bylevel=1, colsample_bytree=1,
       gamma=0, learning_rate=0.1, max_delta_step=0, max_depth=3,
       min_child_weight=1, missing=None, n_estimators=100, nthread=-1,
       objective='binary:logistic', reg_alpha=0, reg_lambda=1,
       scale_pos_weight=1, seed=0, silent=True, subsample=1)
>>> 
>>> try:
...     pred = clf.predict_proba(test)
...     print "Works when csr with version %s" %xgb.__version__
... except ValueError:
...     "Broken when csr with version %s" %xgb.__version__
... 
'Broken when csr with version 0.6'
>>> try:
...     pred = clf.predict_proba(test.tocsc())
...     print "Works when csc with version %s" %xgb.__version__
... except ValueError:
...     "Still broken when csc with version %s" %xgb.__version__
... 
'Still broken when csc with version 0.6'
>>> try:
...     test[0,(test.shape[1]-1)] = 1.0
...     pred = clf.predict_proba(test)
...     print "Works when adding non-zero entries to last column with version %s" %xgb.__version__
... except ValueError:
...     "Still broken when adding non-zero entries to last column with version %s" %xgb.__version__
... 
/home/david.mcgarry/.conda/envs/ml/lib/python2.7/site-packages/scipy/sparse/compressed.py:730: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.
  SparseEfficiencyWarning)
'Still broken when adding non-zero entries to last column with version 0.6'
>>> import xgboost as xgb
>>> import numpy as np
>>> from scipy import sparse
>>> 
>>> np.random.seed(10)
>>> X = sparse.rand(100,10).tocsr()
>>> test = sparse.rand(10, 500).tocsr()
>>> y = np.random.randint(2,size=100)
>>> 
>>> clf = xgb.XGBClassifier()
>>> clf.fit(X,y)
XGBClassifier(base_score=0.5, colsample_bylevel=1, colsample_bytree=1,
       gamma=0, learning_rate=0.1, max_delta_step=0, max_depth=3,
       min_child_weight=1, missing=None, n_estimators=100, nthread=-1,
       objective='binary:logistic', reg_alpha=0, reg_lambda=1,
       scale_pos_weight=1, seed=0, silent=True, subsample=1)
>>> 
>>> try:
...     pred = clf.predict_proba(test)
...     print "Works when csr with version %s" %xgb.__version__
... except ValueError:
...     "Broken when csr with version %s" %xgb.__version__
... 
Works when csr with version 0.4
>>> try:
...     pred = clf.predict_proba(test.tocsc())
...     print "Works when csc with version %s" %xgb.__version__
... except ValueError:
...     "Still broken when csc with version %s" %xgb.__version__
... 
Works when csc with version 0.4
>>> try:
...     test[0,(test.shape[1]-1)] = 1.0
...     pred = clf.predict_proba(test)
...     print "Works when adding non-zero entries to last column with version %s" %xgb.__version__
... except ValueError:
...     "Still broken when adding non-zero entries to last column with version %s" %xgb.__version__
... 
/Users/david.mcgarry/anaconda/envs/ml/lib/python2.7/site-packages/scipy/sparse/compressed.py:739: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.
  SparseEfficiencyWarning)
Works when adding non-zero entries to last column with version 0.4

El mismo problema aquí, algo definitivamente se rompió en la última versión. No tuve este problema antes con el mismo conjunto de datos y procesamiento. Puede que esté equivocado, pero parece que actualmente no hay pruebas unitarias con matrices csr dispersas en Python usando la API sklearn. ¿Sería posible agregar el ejemplo de @dmcgarry anterior a tests/python/tests_with_sklearn.py ?

Intenté solucionarlo usando .toarray () con matrices dispersas CSR, pero algo está seriamente roto. Si cargo un modelo guardado e intento usarlo para hacer predicciones con .toarray (), no recibo un mensaje de error pero los resultados son incorrectos. Volví a 0.4a30 y funciona bien. No he tenido tiempo de buscar la causa raíz, pero no es bueno.

El problema ocurre debido a que DMatrix..num_col () solo devuelve la cantidad de columnas distintas de cero en una matriz dispersa. Por lo tanto, si tanto los datos de entrenamiento como los de prueba tienen la misma cantidad de columnas distintas de cero, todo funciona bien.
De lo contrario, terminará con listas de nombres de funciones diferentes, porque las funciones de validación llaman:

    <strong i="7">@property</strong>
    def feature_names(self):
        """Get feature names (column labels).

        Returns
        -------
        feature_names : list or None
        """
        if self._feature_names is None:
            return ['f{0}'.format(i) for i in range(self.num_col())]
        else:
            return self._feature_names

self._feature_names es None para matrices dispersas, y debido a que self.num_col () devuelve solo la cantidad de columnas distintas de cero, la validación falla tan pronto como la cantidad de columnas distintas de cero en el "to-be- Los datos predichos "difieren de la cantidad de columnas distintas de cero en los datos de entrenamiento.

Sin embargo, todavía no sé dónde es el mejor lugar para arreglar eso.

También me temo que hay un problema fundamental con el manejo de matrices dispersas, debido a lo que informó @ bryan-woods: digamos, tenemos x columnas cero tanto en el tren como en la prueba, pero con índices diferentes => Habrá No hay error, porque "feature_names (self)" devuelve la misma lista de características para ambos conjuntos, pero las predicciones pueden ser incorrectas, debido a que los índices de columna distintos de cero no coinciden entre el tren y la prueba.

¿Alguien ha trabajado en este tema? ¿Alguien tiene al menos una prueba unitaria desarrollada que podamos usar para desarrollar?

No he trabajado en eso, pero el ejemplo anterior de @dmcgarry podría usarse como comienzo de una prueba unitaria, creo,

import xgboost as xgb
import numpy as np
import scipy.sparse


def test_xgbclassifier_sklearn_sparse():
    np.random.seed(10)
    X = scipy.sparse.rand(100,10).tocsr()
    test = scipy.sparse.rand(10, 500).tocsr()
    y = np.random.randint(2,size=100)

    clf = xgb.XGBClassifier()
    clf.fit(X,y)
    pred = clf.predict_proba(test)

Creé un par de nuevas pruebas de matriz dispersa en mi bifurcación del repositorio. Para aquellos que estén interesados:
https://github.com/bryan-woods/xgboost/blob/sparse_test/tests/python/test_scipy_sparse.py

Para ejecutar las pruebas desde el directorio raíz de la caja:
python -m pruebas de nariz / python / test_scipy_sparse.py

Notará que ambas pruebas fallan. Esto al menos proporcionará una prueba contra la que desarrollarse.

También estoy experimentando este problema, pero no puedo averiguar cuál es la mejor manera de solucionarlo hasta que finalmente se resuelva en la biblioteca.

puede agregar una característica a su lista de características con un índice de características máximo, como maxid: 0

pasar un marco de datos resolvió el problema para mí

¿Cómo puedo volver a la versión 0.4?

pip install --upgrade xgboost == 0.4a30

Todos los tipos de matrices dispersas no funcionaron para mí (estoy trabajando con datos tf-idf). Tuve que volver a la versión anterior. ¡Gracias por el consejo!

Todos ustedes que todavía tienen problemas: ¿el código que está utilizando incluye las correcciones en # 1606?

Sí, instalé la última versión de xgboost y sigo teniendo este problema.

Esto todavía existe y es fácilmente reproducible. Si usa un conjunto de datos lo suficientemente grande, es menos probable que esto ocurra, pero si lo envuelve en un objeto de búsqueda de cuadrícula, es casi seguro que ocurra dentro de una división cv donde las características disponibles en los conjuntos de prueba train / cv difieren.

Honestamente, realmente no entiendo por qué DMatrix ignora la sugerencia de forma proporcionada por las matrices dispersas scipy. Debería establecer el tamaño basándose en esa información en lugar de calcularlo.

Estoy usando la API nativa de Xgboost Python (0.6) y tengo el mismo error al cargar un DMatrix desde un archivo de formato LIBSVM [disperso], si alguna de las filas contiene tiene definida la última columna. Mi solución fue definir una columna ficticia en la primera fila :(

train_fv_file = 'train_fv_eval.svm'
dtrain = xgb.DMatrix(train_fv_file, feature_names=feature_vector_labels, feature_types=feature_vector_types)

Si es tan fácil de reproducir, ¿alguien se preocupa por proporcionar un ejemplo reproducible? Preferiblemente, sin la capa sklearn (para aislar una posible causa).

@gabrielspmoreira : Veo su punto sobre la carga desde un archivo LIBSVM que tiene las últimas columnas completamente dispersas ... Ese método de construcción DMatrix también se beneficiaría de tener una pista num_col .

In [42]: matrix = xgboost.DMatrix(scipy.sparse.csr_matrix([[0, 2, 3, 0], [0, 2, 2, 0], [1, 0, 5, 0], [0, 1, 0, 0]], shape=(4,4)))
In [43]: matrix.num_col()
Out[43]: 3L

Cada vez que se crea una nueva DMatrix en una submuestra de filas / columnas, existe la posibilidad de que esto suceda (el número de columnas se reduce aunque le dijimos explícitamente a DMatrix cuántas columnas hay). Esto sucede a menudo para conjuntos de datos más pequeños o columnas muy muy dispersas porque es más probable que un subconjunto sea todo ceros.

Una vez que esto sucede entre un tren / conjunto de prueba, el modelo no puede evaluar el conjunto de prueba porque espera un número diferente de características y escupe un ValueError.

Estoy tratando de encontrar una prueba en la que esto funcione / no funcione dentro de xgboost core y sklearn-wrapper, ya que estoy seguro de lo que está sucediendo, pero no sé dónde está sucediendo.

@ l3link : su código parece estar desactualizado. Esto es lo que obtengo:

In [2]: import scipy
   ...: import xgboost
   ...: matrix = xgboost.DMatrix(scipy.sparse.csr_matrix([[0, 2, 3, 0], [0, 2, 2, 0], [1, 0, 5, 0], [0, 1, 0, 0]], shape=(4,4)))
   ...: matrix.num_col()
   ...:
Out[2]: 4L

In [3]: matrix._init_from_csr??
Signature: matrix._init_from_csr(csr)
Source:
    def _init_from_csr(self, csr):
        """
        Initialize data from a CSR matrix.
        """
        if len(csr.indices) != len(csr.data):
            raise ValueError('length mismatch: {} vs {}'.format(len(csr.indices), len(csr.data)))
        self.handle = ctypes.c_void_p()
        _check_call(_LIB.XGDMatrixCreateFromCSREx(c_array(ctypes.c_size_t, csr.indptr),
                                                  c_array(ctypes.c_uint, csr.indices),
                                                  c_array(ctypes.c_float, csr.data),
                                                  len(csr.indptr), len(csr.data),
                                                  csr.shape[1],
                                                  ctypes.byref(self.handle)))
File:      c:\anaconda2\lib\site-packages\xgboost-0.6-py2.7.egg\xgboost\core.py
Type:      instancemethod

Eh,

In [64]: xgboost.__version__ Out[64]: '0.6'

Signature: matrix._init_from_csr(csr) Source: def _init_from_csr(self, csr): """ Initialize data from a CSR matrix. """ if len(csr.indices) != len(csr.data): raise ValueError('length mismatch: {} vs {}'.format(len(csr.indices), len(csr.data))) self.handle = ctypes.c_void_p() _check_call(_LIB.XGDMatrixCreateFromCSR(c_array(ctypes.c_ulong, csr.indptr), c_array(ctypes.c_uint, csr.indices), c_array(ctypes.c_float, csr.data), len(csr.indptr), len(csr.data), ctypes.byref(self.handle))) File: ~/anaconda/lib/python2.7/site-packages/xgboost/core.py Type: instancemethod

Parece extraño que mi versión .6 tenga instrucciones XGDMatrixCreateFromCSR en lugar de XGDMatrixCreateFromCSREx, que no adoptan la forma.
¿Es posible que la distribución de osx sea diferente?

También me temo que hay un problema fundamental con el manejo de matrices dispersas, debido a lo que informó @ bryan-woods: digamos, tenemos x columnas cero tanto en el tren como en la prueba, pero con índices diferentes => Habrá No hay error, porque "feature_names (self)" devuelve la misma lista de características para ambos conjuntos, pero las predicciones pueden ser incorrectas, debido a que los índices de columna distintos de cero no coinciden entre el tren y la prueba.

¿Alguien puede responder esta pregunta? Volví a la versión 0.4 y ahora parece funcionar, pero me temo que funciona correctamente porque todavía estoy usando matrices muy escasas.

@ l3link no https://github.com/dmlc/xgboost/blob/master/python-package/xgboost/VERSION a partir de hoy se modificó por última vez el 29 de julio, y el último paquete de pypi https: //pypi.python. org / pypi / xgboost / tiene fecha del 9 de agosto. Mientras que la corrección se envió el 23 de septiembre de 1606. Consulte el código más reciente de github.

Tuve este problema cuando usé pandas DataFrame (representación no dispersa).
Lo convertí a numpy ndarray través de df.as_matrix() , y me deshice del error.

Yo también me deshice de este error después de convertir el marco de datos en una matriz.

Reordenar las columnas en el conjunto de prueba en el mismo orden que el conjunto de trenes solucionó esto para mí.
Usé marcos de datos de Pandas. Sin esto, usar .as_matrix() arrojaba el mismo problema.

Yo hice:

test = test[train.columns]

Probé la solución

Convertir matrices csr de tren / prueba a csc funcionó para mí

Xtrain = scipy.sparse.csc_matrix(Xtrain)

La conversión a csc_matrix funciona, probado en 0.6a2 :

    X_train = scipy.sparse.csc_matrix(X_train)
    X_test = scipy.sparse.csc_matrix(X_test)

    xgb_train = xgb.DMatrix(X_train, label=y_train)
    xgb_test = xgb.DMatrix(X_test, label=y_test)
type(X_train) <class 'scipy.sparse.csr.csr_matrix'>
type(X_test) <class 'scipy.sparse.csr.csr_matrix'>
type(X_train) <class 'scipy.sparse.csc.csc_matrix'>
type(X_test) <class 'scipy.sparse.csc.csc_matrix'>
type(xgb_train) <class 'xgboost.core.DMatrix'>
type(xgb_test) <class 'xgboost.core.DMatrix'>

Mi matriz dispersa original es la salida del vectorizador sklearn tf-idf en formato csr_matrix .

¿Hay alguna solución todavía?

Acabo de compilar la última versión (0.7.post3) en python3 y puedo confirmar que este problema aún existe. Después de adaptar el ejemplo de @dmcgarry anterior, todavía veo problemas con csr_matrix y csc_matrix .

import xgboost as xgb
import numpy as np
from scipy import sparse

np.random.seed(10)

X_csr = sparse.rand(100, 10).tocsr()
test_csr = sparse.rand(10, 500).tocsr()

X_csc = sparse.rand(100, 10).tocsc()
test_csc = sparse.rand(10, 500).tocsc()

y = np.random.randint(2, size=100)

clf_csr = xgb.XGBClassifier()
clf_csr.fit(X_csr, y)

clf_csc = xgb.XGBClassifier()
clf_csc.fit(X_csc, y)

# Try with csr
try:
    pred = clf_csr.predict_proba(test_csr)
    print("Works when csr with version %s" %xgb.__version__)
except ValueError:
    print("Broken when csr with version %s" %xgb.__version__)

try:
    test_csr[0,(test_csr.shape[1]-1)] = 1.0
    pred = clf_csr.predict_proba(test_csr)
    print("Works when adding non-zero entries to last column with version %s" %xgb.__version__)
except:
    print("Still broken when adding non-zero entries to last column with version %s" %xgb.__version__)

# Try with csc
try:
    pred = clf_csc.predict_proba(test_csc)
    print("Works when csc with version %s" %xgb.__version__)
except ValueError:
    print("Broken when csc with version %s" %xgb.__version__)

try:
    test_csc[0,(test_csc.shape[1]-1)] = 1.0
    pred = clf_csc.predict_proba(test_csc)
    print("Works when adding non-zero entries to last column with version %s" %xgb.__version__)
except:
    print("Still broken when adding non-zero entries to last column with version %s" %xgb.__version__)

El código anterior dio como resultado el siguiente resultado:

Broken when csr with version 0.7
Still broken when adding non-zero entries to last column with version 0.7
Broken when csc with version 0.7
Still broken when adding non-zero entries to last column with version 0.7

ayuda por favor

¿Por qué se ha cerrado este problema?

Me encontré con este problema dos veces recientemente. En un caso, simplemente cambio el marco de datos de entrada a una matriz y funciona. Para el segundo, tengo que realinear los nombres de las columnas del marco de datos de prueba usando test_df = test_df [train_df.columns]. En ambos casos, train_df y test_df tienen exactamente los mismos nombres de columna.

Supongo que no entiendo tu comentario @CathyQian , ¿esos train_df / test_df escasos? Además, ¿qué versión de xgboost estaba ejecutando cuando se encontró con estos problemas?

@CathyQian xgboost se basa en el _orden_ de las columnas, y eso no está relacionado con este problema.

@ewellinger WRT su ejemplo: un modelo entrenado con datos con 10 características no debería aceptar datos con 500 características para la predicción, por lo tanto, se produce el error. Además, crear DMatrices a partir de todas sus matrices e inspeccionar su num_col y num_row produce los resultados esperados.

El estado actual de "problemas de escasez" es:

  • La creación de DMatrix a partir de CSR y su uso en un modelo debería funcionar correctamente. El tema se cerró ya que ese era el tema de este tema.
  • La creación de DMatrix desde CSC produce un objeto con las dimensiones correctas, pero puede dar resultados incorrectos durante el entrenamiento o la predicción cuando las últimas filas están completamente dispersas # 2630. Todavía no tuve tiempo de arreglar correctamente esa pieza.
  • Todavía no se implementó un parámetro para especificar un número predefinido de columnas cuando se cargan datos libsvm en DMatrix. Los voluntarios para contribuir son bienvenidos.

@warpuv me funciona, muchas gracias.

Tenía el mismo error, con matrices densas. (xgboost v.0.6 de la última anaconda).
Se produjo un error cuando ejecuté varias regresiones en diferentes subconjuntos de características de la muestra de entrenamiento.
La creación de una nueva instancia de modelo cada vez antes de ajustar una siguiente regresión solucionó el problema.

  • Todavía no se implementó un parámetro para especificar un número predefinido de columnas cuando se cargan datos libsvm en DMatrix. Los voluntarios para contribuir son bienvenidos.

A partir de 0.8, esto todavía no existe, ¿verdad?

La creación de DMatrix desde CSC produce un objeto con las dimensiones correctas, pero puede dar resultados incorrectos durante el entrenamiento o la predicción cuando las últimas filas están completamente dispersas # 2630. Todavía no tuve tiempo de arreglar correctamente esa pieza.

@khotilov # 3553 solucionó este problema.

Todavía no se implementó un parámetro para especificar un número predefinido de columnas cuando se cargan datos libsvm en DMatrix. Los voluntarios para contribuir son bienvenidos.

@MonsieurWave Para esta función, una pequeña solicitud de extracción a dmlc-core debería ser suficiente. Déjame mirarlo.

@ hcho3 Muchas gracias.

Por ahora, evito este problema al tener la primera línea de mi libsvm no tan escasa, es decir: guardar incluso las columnas con valor 0.

¿Fue útil esta página
0 / 5 - 0 calificaciones