2015-02-07 11 views
14

gereklidir (okuyun: büyük ölçüde öğretici yapıştırılan). Bu piton 3.4.2 var:Scikit-bilgi en Boru Hattı: Bir seyrek matris geçirildi, ancak yoğun veri Zor Oluşturduğum bir Boru Hattı düzeltmek için nasıl anlamaya buluyorum

df = pd.DataFrame 
df = DataFrame.from_records(train) 

test = [blah1, blah2, blah3] 

pipeline = Pipeline([('vectorizer', CountVectorizer()), ('classifier', RandomForestClassifier())]) 

pipeline.fit(numpy.asarray(df[0]), numpy.asarray(df[1])) 
predicted = pipeline.predict(test) 

bunu çalıştırdığınızda, alıyorum:

TypeError: A sparse matrix was passed, but dense data is required. Use X.toarray() to convert to a dense numpy array. 

Bu hat pipeline.fit(numpy.asarray(df[0]), numpy.asarray(df[1])) içindir.

Ben numpy, SciPy yoluyla çözümler ile çok tecrübe ettik ve benzeri, ama yine de bunu düzeltmek için nasıl bilmiyorum. Ve evet, benzer sorular daha önce ortaya çıktı, ama bir boru hattının içinde değil. toarray veya todense'u uygulamak zorunda mıyım?

cevap

31

Maalesef bu iki uyumsuz çok uzundur, metin sınıflandırma için rastgele ormanlar kullanmak boyut indirgeme çeşit yapmanız gereken genellikle söyledi. CountVectorizer, seyrek bir matris üretir ve RandomForestClassifier yoğun bir matris gerektirir. X.todense()'u kullanarak dönüştürmek mümkündür. Bunu yapmak bellek ayak izinizi büyük ölçüde artıracaktır. Aşağıda

Sana bir boru hattı aşamasında() .todense çağırmak için izin veren http://zacstewart.com/2014/08/05/pipelines-of-featureunions-of-pipelines.html bulunan bu bunu yapmak için örnek kod verilmiştir. Eğer DenseTransformer sahip olduktan sonra

class DenseTransformer(TransformerMixin): 

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

    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 

, bir boru hattı adım olarak ekleyebilirsiniz.

pipeline = Pipeline([ 
    ('vectorizer', CountVectorizer()), 
    ('to_dense', DenseTransformer()), 
    ('classifier', RandomForestClassifier()) 
]) 

Diğer bir seçenek LinearSVC gibi seyrek veriler için geliyordu bir sınıflandırıcı kullanmak olacaktır.

from sklearn.svm import LinearSVC 
pipeline = Pipeline([('vectorizer', CountVectorizer()), ('classifier', LinearSVC())]) 
+0

Çok teşekkürler! Farklı sınıflandırıcılar ile, kısmen öğrenmek ve kısmen en iyi neyin işe yaradığını bulmak için deneylerim. Gerçeği söylemek gerekirse, benim durumum için multinomial NB ile en iyi sonuçları elde ederim. Kodunuzu deneyeceğim, kapsamlı cevap için çok teşekkürler. –

+0

Kulağa eğlenceli geliyor. RandomForest, yoğun sayısal veriler için iyidir. Seyrek metin özellikleri için bu kadar iyi ölçeklemediğini buldum.Metin üzerinde denemek istiyorsanız, önce bir özellik seçimi aşaması eklemeyi deneyebilirsiniz. Bu bazen iyi çalışır. Metinler için favorilerim, LinearSVC ve SGD Sınıflandırıcısı olarak, loss = 'modified_huber' veya loss = 'log' kullanıyordu. –

+0

SGD kullanarak klavuz tabanlı bir POS tagger uygulaması için hangi parametreler kullanılır? – stackit

3

Eğer .values yöntemi kullanarak diziler için pandalar Series değiştirebilir.

pipeline.fit(df[0].values, df[1].values) 

Ancak CountVectorizer() varsayılan olarak seyrek matris verir ve RF sınıflandırıcı yöneltilen olamaz çünkü mesele burada olur düşünüyorum. CountVectorizer(), döndürülen dizinin türünü belirtmek için dtype parametresine sahip. Yani kelimelerin torba vektörleri özelliği çünkü

+1

görüyorum sayesinde bir sürü, şimdi mantıklı. Seni kurtarmayı denedim ama yeterince itibarım yok mu? –

15

Artık 0,6-dev alanındaki rasgele ormanlar seyrek verileri kabul eder.

9

en temiz çözüm yoğun dönüştürmek için FunctionTransformer kullanmak olacaktır: Bu otomatik David'in cevap olarak fit, transform ve fit_transform yöntemleri uygulayacaktır. Benim boru hattı adımları için özel isimler gerekmez Ayrıca, ben modelini tarif etmek için daha minimalist bir dil etkinleştirmek için sklearn.pipeline.make_pipeline kolaylık fonksiyonunu kullanmak ister:

pipeline = make_pipeline(
    CountVectorizer(), 
    FunctionTransformer(lambda x: x.todense(), accept_sparse=True), 
    RandomForestClassifier() 
) 
+0

Bunu denedim ve 'FunctionTransformer'ın' accept_sparse' parametresini gördüm. Bunu 'Doğru' olarak ayarlamanız gerekir. – statueofmike

+0

oh cool i cevabını düzenlerim – maxymoo

+0

Yaptığımın kadar @ maxymoo çözümünü kullananlar için, FunctionTransformer 'sklearn.preprocessing import FunctionTransformer' konumundan içe aktarılabilir – Jarad

İlgili konular