0

J'ai commencé à utiliser scikit learn pour l'extraction de texte. Lorsque j'utilise la fonction standard CountVectorizer et TfidfTransformer dans un pipeline et lorsque j'essaie de combiner avec de nouvelles fonctionnalités (une concaténation de matrice), j'ai un problème de dimension de ligne.FeatureUnion dans scikit klearn et dimension de ligne incompatible

Ceci est mon pipeline:

pipeline = Pipeline([('feats', FeatureUnion([ 
('ngram_tfidf', Pipeline([('vect', CountVectorizer()),'tfidf', TfidfTransformer())])), 
('addned', AddNed()),])), ('clf', SGDClassifier()),]) 

Ceci est ma classe AddNEd qui ajoutent 30 nouvelles fonctionnalités sur chaque document (échantillon).

class AddNed(BaseEstimator, TransformerMixin): 
def __init__(self): 
    pass 

def transform (self, X, **transform_params): 
    do_something 
    x_new_feat = np.array(list_feat) 
    print(type(X)) 
    X_np = np.array(X) 
    print(X_np.shape, x_new_feat.shape) 
    return np.concatenate((X_np, x_new_feat), axis = 1) 

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

Et la première partie de mon programm principal

data = load_files('HO_without_tag') 
grid_search = GridSearchCV(pipeline, parameters, n_jobs = 1, verbose = 20) 
print(len(data.data), len(data.target)) 
grid_search.fit(X, Y).transform(X) 

Mais j'obtenir ce résultat:

486 486 
Fitting 3 folds for each of 3456 candidates, totalling 10368 fits 
[CV]feats__ngram_tfidf__vect__max_features=3000.... 
323 
<class 'list'> 
(323,) (486, 30) 

Et bien sûr, une exception IndexError

return np.concatenate((X_np, x_new_feat), axis = 1) 
IndexError: axis 1 out of bounds [0, 1 

Quand je avoir les params X dans la fonction de transformation n (classe AddNed) pourquoi je n'ai pas une forme de tableau numpy (486, 3000) pour X. Je n'ai que (323,) forme. Je ne comprends pas parce que si je supprime Feature Union et AddNed() pipeline, CountVectorizer et tf_idf fonctionnent correctement avec les bonnes fonctionnalités et la bonne forme. Si quelqu'un a une idée? Merci beaucoup.

+0

Vous ne pouvez pas supprimer des lignes dans un Pipeline parce que vos transformations affectent seulement 'X', pas' y'. – David

+0

Désolé, peut-être que je manque quelque chose mais je ne supprime pas les lignes ... je pense. Je souhaite ajouter une nouvelle matrice (486, 30) avec une nouvelle fonctionnalité (AddNed Pipeline) à une matrice (486,3000) (Pipeline countizer vectorizer + tdf_idf). Le problème est que je charge 486 fichiers (load_files), je les traite (vectorizer + tdf_idf) mais je n'ai pas 486 samples (seulement 323). – mathieu

+0

Je ne comprends pas ce qui se passe, surtout dans 'do_something'. Si vous pouvez créer un exemple reproductible, je suis sûr que nous pouvons aider. – David

Répondre

0

OK, je vais essayer de donner plus d'explications. Quand je dis do_something, dis-je do_nothing avec X. Dans la classe AddNed si je réécris:

def transform (self, X, **transform_params): 
    print(X.shape) #Print X shape on first line before do anything 
    print(type(X)) #For information 
    do_nothing_withX #Construct a new matrix with a shape (number of samples, 30 new features) 
    x_new_feat = np.array(list_feat) #Get my new matrix in numpy array 
    print(x_new_feat.shape) 
    return x_new_feat 

Dans cette transformation cas ci-dessus, je ne concaténer matrice X et nouvelle matrice. Je présume que les caractéristiques SYNDICAT que ... Et mon résultat:

486 486 #Here it is a print (data.data, data.target) 
Fitting 3 folds for each of 3456 candidates, totalling 10368 fits 
[CV] clf__alpha=1e-05, vect__max_df=0.1, clf__penalty=l2, feats__tfidf__use_idf=True, feats__tfidf__norm=l1, clf__loss=hinge, vect__ngram_range=(1, 1), clf__n_iter=10, vect__max_features=3000 
(323, 3000) # X shape Matrix 
<class 'scipy.sparse.csr.csr_matrix'> 
(486, 30) # My new matrix shape 
Traceback (most recent call last): 
File "pipe_line_learning_union.py", line 134, in <module> 
grid_search.fit(X, Y).transform(X) 
..... 
File "/data/maclearnVE/lib/python3.4/site-packages/scipy/sparse/construct.py", line 581, in bmat 
raise ValueError('blocks[%d,:] has incompatible row dimensions' % i) 
ValueError: blocks[0,:] has incompatible row dimensions 

Pour aller plus loin, juste pour voir, si si je mets une validation croisée sur gridsearchCV, pour modifier la taille de l'échantillon:

grid_search = GridSearchCV(pipeline, parameters, cv=2, n_jobs = 1, verbose = 20) 

J'ai ce résultat:

486 486 
Fitting 2 folds for each of 3456 candidates, totalling 6912 fits 
[CV] ...... 
(242, 3000) #This a new sample size due to cross validation 
<class 'scipy.sparse.csr.csr_matrix'> 
(486, 30) 
.......... 
ValueError: blocks[0,:] has incompatible row dimensions 

Bien sûr, s'il est nécessaire, je peux donner tout le code de do_nothing_withX. Mais ce que je ne comprends pas, c'est pourquoi la taille de l'échantillon avec le pipeline countvectorizer + tdf_idf il n'est pas égal au nombre de fichiers charger avec la fonction sklearn.datasets.load_files().

0

Vous ai probablement résolu il maintenant, mais quelqu'un d'autre peut avoir le même problème:

(323, 3000) # X shape Matrix 
<class 'scipy.sparse.csr.csr_matrix'> 

AddNed tente de concaténer une matrice avec une matrice creuse , la matrice clairsemée doit être transformée à matrice dense d'abord. J'ai trouvé la même erreur en essayant d'utiliser le résultat de CountVectorizer