【问题标题】:Save and reuse TfidfVectorizer in scikit learn在 scikit learn 中保存和重用 TfidfVectorizer
【发布时间】:2015-08-30 19:42:44
【问题描述】:

我在 scikit 中使用 TfidfVectorizer 学习从文本数据创建矩阵。现在我需要保存这个对象以供以后重用。我尝试使用pickle,但它给出了以下错误。

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

我尝试在 sklearn.externals 中使用 joblib,但又出现了类似的错误。有什么方法可以保存这个对象,以便我以后可以重用它?

这是我的完整对象:

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

【问题讨论】:

    标签: python nlp scikit-learn pickle text-mining


    【解决方案1】:

    首先,最好将导入放在代码顶部而不是类中:

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

    下一个StemTokenizer 似乎不是一个规范的类。可能您是从 http://sahandsaba.com/visualizing-philosophers-and-scientists-by-the-words-they-used-with-d3js-and-python.html 或其他地方获得的,所以我们假设它返回一个字符串列表

    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
    

    现在回答您的实际问题,您可能需要在转储泡菜之前以字节模式打开文件,即:

    >>> 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
    

    注意:一旦您离开 with 范围,使用 with 习惯用法进行 i/o 文件访问会自动关闭文件。

    关于SnowballStemmer() 的问题,请注意SnowballStemmer('english') 是一个对象,而词干提取函数是SnowballStemmer('english').stem

    重要

    • TfidfVectorizer 的 tokenizer 参数期望接受一个字符串并返回一个字符串列表
    • 但 Snowball 词干分析器不会将字符串作为输入并返回字符串列表。

    所以你需要这样做:

    >>> 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
    

    【讨论】:

    • 以字节模式打开文件不起作用。但我发现了这个问题。是 StemTokenizer 类造成了问题。在初始化该类时,我给出了 "self.snowball_stemmer = SnowballStemmer('english')" 。当我将此部分更改为 call 部分时,它起作用了。我不确定它为什么会起作用。
    • 您需要确保无论分词器函数是什么,它都会返回一个字符串列表。
    • 它只返回一个字符串列表。当我将self.snowball_stemmer = SnowballStemmer('english') 更改为snowball_stemmer = SnowballStemmer('english') 时,该错误已消除。基本上我从类的属性中删除了它并且错误已修复。
    • 啊。这是因为 SnowballStemmer('english') 是一个对象,你需要的是一个使用 SnowballStemmer('english').stem 的可迭代对象
    • 嗨!我正在尝试保存一个用于使用 TfidfVectorizer 转换文本的 Pickle,它的大小为 76MB,我需要将其减小到 10MB。参数 dtype= 是否有助于减小尺寸?
    猜你喜欢
    • 2018-01-23
    • 2014-08-22
    • 2015-12-22
    • 2014-11-12
    • 2017-05-26
    • 2019-04-03
    • 1970-01-01
    • 2017-01-08
    相关资源
    最近更新 更多