1. CountVectorizer

CountVectorizer类会将文本中的词语转换为词频矩阵。
例如矩阵中包含一个元素hugging最新的nlp模型_API,它表示hugging最新的nlp模型_词频_02词在hugging最新的nlp模型_权重_03类文本下的词频。它通过fit_transform函数计算各个词语出现的次数,通过get_feature_names()可获取词袋中所有文本的关键字,通过toarray()可看到词频矩阵的结果。

from sklearn.feature_extraction.text import CountVectorizer
#语料
corpus = [
    'This is the first document.',
    'This is the this second second document.',
    'And the third one.',
    'Is this the first document?'
]
#将文本中的词转换成词频矩阵
vectorizer = CountVectorizer()
print(vectorizer)
#计算某个词出现的次数
X = vectorizer.fit_transform(corpus)
print(type(X),X)
#获取词袋中所有文本关键词
word = vectorizer.get_feature_names()
print(word)
#查看词频结果
print(X.toarray())

结果:

(0, 2)	1
  (0, 6)	1
  (0, 3)	1
  (0, 8)	1
  (1, 5)	2
  (1, 1)	1
  (1, 6)	1
  (1, 3)	1
  (1, 8)	2
  (2, 4)	1
  (2, 7)	1
  (2, 0)	1
  (2, 6)	1
  (3, 1)	1
  (3, 2)	1
  (3, 6)	1
  (3, 3)	1
  (3, 8)	1
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
[[0 1 1 1 0 0 1 0 1]
 [0 1 0 1 0 2 1 0 2]
 [1 0 0 0 1 0 1 1 0]
 [0 1 1 1 0 0 1 0 1]]

2. TF-IDF

TF-IDF(term frequency-inverse document frequency)是文本加权方法,采用统计思想,即文本出现的次数和整个语料中文档频率来计算字词的重要度。

优点:过滤一些常见但是无关紧要的字词。
hugging最新的nlp模型_hugging最新的nlp模型_04
TF(Term Frequency)表示某个关键词在整篇文章中出现的频率。(某个词在文章中出现的总次数/文章的总词数);

hugging最新的nlp模型_权重_05

IDF(Inverse Document Frequency)表示计算倒文本频率。文本频率是指某个关键词在整个语料所有文章中出现的次数。倒文档频率又称为逆文档频率,它是文档频率的倒数,主要用于降低所有文档中一些常见却对文档影响不大的词语的作用。

Transformer 官方文档

默认:

hugging最新的nlp模型_词频_06

这里, hugging最新的nlp模型_API_07 为总的文档数, hugging最新的nlp模型_API_08 为包含这个词 hugging最新的nlp模型_API_09

教科书标准的idf定义:

hugging最新的nlp模型_词频_10

其中, hugging最新的nlp模型_API_07代表语料库的文档总数; hugging最新的nlp模型_API_08 代表包含该词hugging最新的nlp模型_API_09的文档数.

Tfidf 实现,一般是先通过countVectorizer, 然后再通过 tfidfTransformer, 转换成 tfidf 向量; 也有现成的 TfidfVectorizer API。

语句:

TfidfTransformer(norm='l2', use_idf=True, smooth_idf=True, sublinear_tf=False)

示例:

from sklearn.feature_extraction.text import TfidfVectorizer, TfidfTransformer, CountVectorizer
import numpy as np
#语料
cc = [
      'aa bb.',
      'aa cc.'
]
# method 1
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(cc)
print('feature',vectorizer.get_feature_names())
print(X.toarray())

结果:

feature ['aa', 'bb', 'cc']
[[0.57973867 0.81480247 0.        ]
 [0.57973867 0.         0.81480247]]

值得注意的是,默认语料会把单个字符当作停止单词(stop_words)进行过滤,如果需要保留单个字符组成的单词,可以修改分词方式:token_pattern='(?u)\\b\\w+\\b'

此外,上面还可实现如下:

# method 2
vectorizer=CountVectorizer()#token_pattern='(?u)\\b\\w+\\b'
transformer = TfidfTransformer()
cntTf = vectorizer.fit_transform(cc)
print('feature', vectorizer.get_feature_names())
print(cntTf)
cnt_array = cntTf.toarray()
X = transformer.fit_transform(cntTf)
print(X.toarray())

结果:

feature ['aa', 'bb', 'cc']
# 第一个数字表示第几个文档;第二个数字表示第几个feature,结果表示相应的词频。
  (0, 1)        1
  (0, 0)        1
  (1, 2)        1
  (1, 0)        1
[[0.57973867 0.81480247 0.        ]
 [0.57973867 0.         0.81480247]]

为了更加明白TfidfTransformer的操作,进行简单分解实现该功能:

# method 3
vectorizer=CountVectorizer()
cntTf = vectorizer.fit_transform(cc)
tf = cnt_array/np.sum(cnt_array, axis = 1, keepdims = True)
print('tf',tf)
idf = np.log((1+len(cnt_array))/(1+np.sum(cnt_array,axis = 0))) + 1
print('idf', idf)
t = tf*idf
print('tfidf',t)
print('norm tfidf', t/np.sqrt(np.sum(t**2, axis = 1, keepdims=True)))

结果:

tf [[0.5 0.5 0. ]
 [0.5 0.  0.5]]
idf [1.         1.40546511 1.40546511]
tfidf [[0.5        0.70273255 0.        ]
 [0.5        0.         0.70273255]]
norm tfidf [[0.57973867 0.81480247 0.        ]
 [0.57973867 0.         0.81480247]]

也就是说,TfidfTransformer 默认会对获得的向量除以2范数进行归一化。

hugging最新的nlp模型_权重_14

TF-IDF的信息论依据

一个查询(Query)中的每个关键词(Key Word)w的权重应该反映这个词查询来讲提供了多少信息。一个简单方法是用每个词的信息量作为他的权重。

hugging最新的nlp模型_API_15

但是,如果两个词出现的频率 TF相同, 一个是某篇特定文章中的常见词,而另外一个词时分散在多篇文章中,显然第一个词有更高的分辨率,权重应该更大。

hugging最新的nlp模型_API_16

3. HashingVectorizer

语法

HashingVectorizer(alternate_sign=True, analyzer='word', binary=False,
         decode_error='strict', dtype=<class 'numpy.float64'>,
         encoding='utf-8', input='content', lowercase=True,
         n_features=1048576, ngram_range=(1, 1), non_negative=False,
         norm='l2', preprocessor=None, stop_words=None, strip_accents=None,
         token_pattern='(?u)\\b\\w\\w+\\b', tokenizer=None)

特点

普通的CountVectorizer存在但词库很大时,占用大内存,因此,使用hash技巧,并用稀疏矩阵存储编译后的矩阵,能很好解决这个问题。

实现的伪代码为:

function hashing_vectorizer(features : array of string, N : integer):
     x := new vector[N]
     for f in features:
         h := hash(f)
         x[h mod N] += 1
     return x

这里伪代码没有考虑到hash冲突的情况,实际实现会更加复杂。

from sklearn.feature_extraction.text import HashingVectorizer
corpus = [
     'This is the first document.',
     'This document is the second document.',
     'And this is the third one.',
     'Is this the first document?',
 ]
vectorizer = HashingVectorizer(n_features=2**4)
X = vectorizer.fit_transform(corpus)
print(X.toarray())
print(X.shape)

结果:

[[-0.57735027  0.          0.          0.          0.          0.
   0.          0.         -0.57735027  0.          0.          0.
   0.          0.57735027  0.          0.        ]
 [-0.81649658  0.          0.          0.          0.          0.
   0.          0.          0.          0.          0.          0.40824829
   0.          0.40824829  0.          0.        ]
 [ 0.          0.          0.          0.         -0.70710678  0.70710678
   0.          0.          0.          0.          0.          0.
   0.          0.          0.          0.        ]
 [-0.57735027  0.          0.          0.          0.          0.
   0.          0.         -0.57735027  0.          0.          0.
   0.          0.57735027  0.          0.        ]]
(4, 16)

4. 总结

总的而言,这三种都是词袋模型的方法,其中,由于tfidfvectorizer这种方法可以降低高频信息量少词语的干扰,应用得更多。