web-dev-qa-db-fra.com

Enregistrez et réutilisez TfidfVectorizer dans Scikit Learn

J'utilise TfidfVectorizer dans scikit apprendre à créer une matrice à partir de données texte. Maintenant, je dois enregistrer cet objet pour le réutiliser plus tard. J'ai essayé d'utiliser des cornichons, mais cela a donné l'erreur suivante.

loc=open('vectorizer.obj','w')
pickle.dump(self.vectorizer,loc)
*** TypeError: can't pickle instancemethod objects

J'ai essayé d'utiliser joblib dans sklearn.externals, ce qui a de nouveau donné une erreur similaire. Existe-t-il un moyen de sauvegarder cet objet afin de pouvoir le réutiliser plus tard?

Voici mon objet complet:

class changeToMatrix(object):
def __init__(self,ngram_range=(1,1),tokenizer=StemTokenizer()):
    from sklearn.feature_extraction.text import TfidfVectorizer
    self.vectorizer = TfidfVectorizer(ngram_range=ngram_range,analyzer='Word',lowercase=True,\
                                          token_pattern='[a-zA-Z0-9]+',strip_accents='unicode',tokenizer=tokenizer)

def load_ref_text(self,text_file):
    textfile = open(text_file,'r')
    lines=textfile.readlines()
    textfile.close()
    lines = ' '.join(lines)
    sent_tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
    sentences = [ sent_tokenizer.tokenize(lines.strip()) ]
    sentences1 = [item.strip().strip('.') for sublist in sentences for item in sublist]      
    chk2=pd.DataFrame(self.vectorizer.fit_transform(sentences1).toarray()) #vectorizer is transformed in this step 
    return sentences1,[chk2]

def get_processed_data(self,data_loc):
    ref_sentences,ref_dataframes=self.load_ref_text(data_loc)
    loc=open("indexedData/vectorizer.obj","w")
    pickle.dump(self.vectorizer,loc) #getting error here
    loc.close()
    return ref_sentences,ref_dataframes
15
Joswin K J

Tout d'abord, il est préférable de laisser l'importation en haut de votre code plutôt que dans votre classe:

from sklearn.feature_extraction.text import TfidfVectorizer
class changeToMatrix(object):
  def __init__(self,ngram_range=(1,1),tokenizer=StemTokenizer()):
    ...

StemTokenizer ne semble pas être une classe canonique. Vous l'avez peut-être obtenu de http://sahandsaba.com/visualizing-philosophers-and-scientists-by-the-words-they-used-with-d3js-and-python.html ou peut-être ailleurs donc nous supposerons qu'il retourne une liste de chaînes.

class StemTokenizer(object):
    def __init__(self):
        self.ignore_set = {'footnote', 'nietzsche', 'plato', 'mr.'}

    def __call__(self, doc):
        words = []
        for Word in Word_tokenize(doc):
            Word = Word.lower()
            w = wn.morphy(Word)
            if w and len(w) > 1 and w not in self.ignore_set:
                words.append(w)
        return words

Maintenant, pour répondre à votre question, il est possible que vous deviez ouvrir un fichier en mode octet avant de vider un cornichon, c'est-à-dire:

>>> from sklearn.feature_extraction.text import TfidfVectorizer
>>> from nltk import Word_tokenize
>>> import cPickle as pickle
>>> vectorizer = TfidfVectorizer(ngram_range=(0,2),analyzer='Word',lowercase=True, token_pattern='[a-zA-Z0-9]+',strip_accents='unicode',tokenizer=Word_tokenize)
>>> vectorizer
TfidfVectorizer(analyzer='Word', binary=False, decode_error=u'strict',
        dtype=<type 'numpy.int64'>, encoding=u'utf-8', input=u'content',
        lowercase=True, max_df=1.0, max_features=None, min_df=1,
        ngram_range=(0, 2), norm=u'l2', preprocessor=None, smooth_idf=True,
        stop_words=None, strip_accents='unicode', sublinear_tf=False,
        token_pattern='[a-zA-Z0-9]+',
        tokenizer=<function Word_tokenize at 0x7f5ea68e88c0>, use_idf=True,
        vocabulary=None)
>>> with open('vectorizer.pk', 'wb') as fin:
...     pickle.dump(vectorizer, fin)
... 
>>> exit()
alvas@ubi:~$ ls -lah vectorizer.pk 
-rw-rw-r-- 1 alvas alvas 763 Jun 15 14:18 vectorizer.pk

Remarque : L'utilisation de l'idiome with pour l'accès aux fichiers d'E/S ferme automatiquement le fichier une fois que vous sortez du with portée.

En ce qui concerne le problème avec SnowballStemmer(), notez que SnowballStemmer('english') est un objet tandis que la fonction stemming est SnowballStemmer('english').stem.

[~ # ~] important [~ # ~] :

  • Le paramètre tokenizer de TfidfVectorizer s'attend à prendre une chaîne et à renvoyer une liste de chaînes
  • Mais Snowball stemmer ne prend pas de chaîne en entrée et ne renvoie pas de liste de chaînes.

Vous devrez donc faire ceci:

>>> from nltk.stem import SnowballStemmer
>>> from nltk import Word_tokenize
>>> stemmer = SnowballStemmer('english').stem
>>> def stem_tokenize(text):
...     return [stemmer(i) for i in Word_tokenize(text)]
... 
>>> vectorizer = TfidfVectorizer(ngram_range=(0,2),analyzer='Word',lowercase=True, token_pattern='[a-zA-Z0-9]+',strip_accents='unicode',tokenizer=stem_tokenize)
>>> with open('vectorizer.pk', 'wb') as fin:
...     pickle.dump(vectorizer, fin)
...
>>> exit()
alvas@ubi:~$ ls -lah vectorizer.pk 
-rw-rw-r-- 1 alvas alvas 758 Jun 15 15:55 vectorizer.pk
8
alvas