【问题标题】:sklearn CountVectorizer.transform() returns different results with the same inputsklearn CountVectorizer.transform() 使用相同的输入返回不同的结果
【发布时间】:2021-06-02 08:03:05
【问题描述】:

我目前在 python 中实现 TFIDF,在测试余弦距离函数时,我得到了相当令人费解的结果。它看起来像这样:

    def cosSim(self, doc1,doc2):
        docList = [doc1, doc2]
        count_vector = self.cv.transform(docList)
        tf_idf_vector = self.tfidfTrans.transform(count_vector)
        cos_sim = cosine_similarity(tf_idf_vector)
        return cos_sim[0][1]

问题是 self.cv.transform(docList) 会返回不同的结果,有时看起来像这样

  (0, 720)  1
  (0, 824)  1
  (0, 864)  1
  (0, 1456) 1
  (0, 1762) 1
  (0, 1890) 1
  (0, 2406) 1
  (0, 2593) 1
  (0, 3244) 1
  (0, 4258) 1
  (0, 4414) 1
  (1, 969)  1
  (1, 2416) 1
  (1, 2661) 1
  (1, 4075) 1
  (1, 4258) 1

and sometimes (wrong) like this
  (0, 720)  1
  (0, 824)  1
  (0, 864)  1
  (0, 1456) 1
  (0, 1762) 1
  (0, 1890) 1
  (0, 2406) 1
  (0, 2593) 1
  (0, 3244) 1
  (0, 4258) 1
  (0, 4414) 1

所以它似乎在“吃掉”第二份文件。这在程序执行之间甚至不一致,在循环中调用函数,同时看似随机返回两个结果。知道是什么原因造成的吗?

编辑: 我像这样构建我的模型:


    def build_tfidf(self, docList):
        self.cv = CountVectorizer(stop_words=self.stop_words, strip_accents='ascii', tokenizer=tokenize)
        word_count_vector = self.cv.fit_transform(docList)
        self.tfidfTrans = TfidfTransformer(use_idf=True)
        self.tfidfTrans.fit(word_count_vector)
        self.vocab = self.cv.get_feature_names()

我调用了类似的函数,但仍然得到奇怪的结果:

tfidf = TFIDF()
tfidf.build_tfidf(data)
doc1 = "However, a few cooperative transaction models have been proposed to facilitate collaboration, usually while maintaining some guarantees of consistency."
doc2 = "Transaction Management in Multidatabase Systems Databases."
for i in range(0,10):
    sim = tfidf.cosSim(doc1, doc2)
    print(sim)

Edit2:经过一番修修补补,我找到了一个解决方案,但没有找到解决方案:如果我不通过 CountVectorizer() 一个标记器,我就会开始工作。问题是我需要那个标记器,但这仍然不能解释为什么它不能用它。这是标记化代码以防万一,尽管它可能无关:

def tokenize(doc):
    tokens = regex_tokenize(doc)
    stemmed = porter_stem(tokens)
    return stemmed

def regex_tokenize(doc, reg=u'(?u)\\b\\w\\w+\\b'):
    words = []
    token_pattern = re.compile(reg)
    lan = ""
    try:
        lan = detect(doc)
    except :
        pass
    if lan == "en":
        words = token_pattern.findall(doc)
    return words

def porter_stem(doc):
    porter_stemmer = PorterStemmer()
    stemmed_words = []
    for word in doc:
        match = re.match("[0-9]+", word)
        if match is None: #& match.group() != word:
            stemmed_words.append(porter_stemmer.stem(word))
    return stemmed_words

在我的cosSim函数中,也尝试过拆分

count_vector = cv.transform([doc1, doc2]) 

进入

count_vector1 = cv.transform([doc1])
count_vector2 = cv.transform([doc2])
print(f"vec1: {count_vector1}")
print(f"vec2: {count_vector2}")

但即使在那之后它有时仍然不计算第二个向量:

vec1:   (0, 266)    1
  (0, 294)  1
  (0, 527)  1
  (0, 603)  1
  (0, 743)  2
  (0, 1022) 1
vec2:   (0, 266)    1
  (0, 656)  1
  (0, 709)  1
  (0, 1068) 1
  (0, 1122) 1
0.09454412899652256


vec1:   (0, 266)    1
  (0, 294)  1
  (0, 527)  1
  (0, 603)  1
  (0, 743)  2
  (0, 1022) 1
vec2: 

【问题讨论】:

  • 这里最可能的情况是由于调用cosSim() 的代码中的错误,输入实际上并不相同。请发布该代码。
  • 将代码添加到问题中

标签: python scikit-learn countvectorizer


【解决方案1】:

所以问题实际上是 标记器。我使用的 langdetect 模块似乎是不确定的,所以我会在同一段文本上得到不同的结果。

【讨论】:

    猜你喜欢
    • 2022-01-16
    • 1970-01-01
    • 2016-08-02
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 2019-12-10
    • 2017-11-08
    • 1970-01-01
    相关资源
    最近更新 更多