1.词袋模型
1.1 理解词袋模型
所谓词袋模型就是,首先将训练样本中所有不重复的词放到这个袋子中构成一个词表(字典);然后再以这个词表为标准来遍历每一个样本,如果词表中对应位置的词出现在了样本中,那么词表对应位置就用1来表示,没有出现就用0来表示;最后,对于每个样本来说都将其向量化成了一个和词表长度一样的只含有0和1的向量。
具体的实现步骤:
- 文本分词:将原始数据的每个样本都进行分词处理,(英文语料可以跳过这步)
- 构造词表:在所有的分词结果中去掉重复的部分,保证每个词语只出现一次,且同时要以任意一种顺序来固定词表中每个词的位置。
- 文本向量化:遍历每个数据样本,若词表中的词出现在该样本中,则对应位置为1,没出现则为0。(维度灾难:在分词结束后通常还会进行词频统计这一步,即统计每个词在数据集中出现的次数,然后只选择其中出现频率最高的前K个词作为最终的词表。最后,通常也会将一些无意义的虚词,即停用词(Stop Words)去掉,例如“的,啊,了,”等。)
1.1.1 文本分词
pip install jieba
普通分词模式:
import jieba,re
def cutWords(s, cut_all=False):
cut_words = []
s = re.sub("[A-Za-z0-9\:\·\—\,\。\“ \”]", "", s)
seg_list = jieba.cut(s, cut_all=cut_all)
cut_words.append(" ".join(seg_list))
print(cut_words)
全分词模式:当把上面代码中cut_all
=True
后,便可以开启全分词模式,
1.1.2 构造词表
分词后通常还会先进行词频统计,以选取出现频率最高的前K个词来构造词表。对词频统计需要用到另外一个包collection中的Counter计数器。
def wordsCount(s):
cut_words = ""
s = re.sub("[A-Za-z0-9\:\·\—\,\。\“ \”]", "", s)
seg_list = jieba.cut(s, cut_all=False)
cut_words += (" ".join(seg_list))
all_words = cut_words.split() #对文本进行分词处理
#词频统计
c = Counter()
for x in all_words:
if len(x) > 1 and x != '\r\n':
c[x] += 1
#构建词表
vocab = []
print('\n词频统计结果:')
for (k, v) in c.most_common(5): # 输出词频最高的前5个词
print("%s:%d" % (k, v))
vocab.append(k)
print("词表:", vocab)
1.1.3 文本向量化
向量化工作则是遍历每个样本,查看词表中每个词是否出现在当前样本中,如果出现则词表对应维度用1表示,没出现用0表示。
def vetorization(s):
# #此处接文本分词和词频统计代码
x_vec = [] #
for item in x_text: #表示原始文本分词后的结果
tmp = [0] * len(vocab) #tmp表示先初始化一个长度为词表长度的全0向量
#遍历每一句文本中的每一个词,判断其是否存在于词表中,如果存在则将tmp向量对应处置为1
for i, w in enumerate(vocab):
if w in item:
tmp[i] = 1
x_vec.append(tmp)
print("词表:", vocab)
print("文本:", x_text)
print(x_vec)
根据vetorization
函数便能够对输入的文本进行向量化表示。
s=['文本分词工具可用于对文本进行分词处理','常见的用于处理文本的分词处理工具有很多']
vetorization(s)
词表: ['文本', '分词', '处理', '工具', '用于', '进行', '常见', '很多']
文本:[['文本','分词','工具','可','用于', '对','文本','进行', '分词', '处理'], ['常见', '的', '用于', '处理', '文本', '的', '分词', '处理', '工具', '有','很多']]
[[1, 1, 1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 0, 1, 1]]
但是,这样做的弊端之一就是没有考虑到词的出现频率,即不管一个词出现了多少次,最后都仅仅用1来表示其出现过。
考虑词频的文本向量化
def vectorization_with_freq(s):
#此处接文本分词和词频统计代码
x_vec = []
for item in x_text:
tmp = dict(zip(vocab, [0] * len(vocab)))
for w in item:
if w in vocab:
tmp[w] += 1
x_vec.append(list(tmp.values()))
print("词表:", vocab)
print("文本:", x_text)
print(x_vec)
根据vetorization_with_freq函数便能够对输入的文本进行向量化表示,
s =['文本分词工具可用于对文本进行分词处理', '常见的用于处理文本的分词处理工具有很多']
vectorization_with_freq(s)
词表: ['文本', '分词', '处理', '工具', '用于', '进行', '常见', '很多']
文本: [['文本', '分词', '工具', '可', '用于', '对', '文本', '进行', '分词', '处理'], ['常见','的','用于', '处理','文本','的','分词','处理','工具','有','很多']]
[[2, 2, 1, 1, 1, 1, 0, 0], [1, 1, 2, 1, 1, 0, 1, 1]]
from sklearn.feature_extraction.text import CountVectorizer
count_vec = CountVectorizer(max_features=8, token_pattern=r"(?u)\b\w\w+\b")
x = count_vec.fit_transform(s).toarray()
vocab = count_vec.vocabulary_
vocab = sorted(vocab.items(), key=lambda x: x[1])
print(vocab)
print(x)
2.考虑权重的词袋模型
2.1 TF-IDF模型
F-IDF为词频-逆文档频率(Term Frequence - Inverse Document Frequence)的简称。首先需要明白的是TF-IDF实际上是TF与IDF两者的乘积。同时,出现TF-IDF的原因在于,通常来说在一个样本中一次词出现的频率越高,其重要性应该对应越高,即考虑到词频对文本向量的影响;但是如果仅仅只是考虑到这一个因素则同样会带来一个新的弊端,即有的词不只是在某个样本中出现的频率高,其实它在整个数据集中的出现频率都很高,而这样的词往往也是没有意义的。因此,TF-IDF的做法是通过词的逆文档频率来加以修正调整。
2.2 TF-IDF计算原理
TF-IDF的计算过程总体上可以分为两步,先统计词频,然后计算逆文档频率,最后将两者相乘得到TF-IDF值。
案例
四个样本:
1 corpus = ['this is the first document',
2 'this document is the second document',
3 'and this is the third one',
4 'is this the first document']
对应的词表:
1 vocabulary = ['this', 'document', 'first', 'is', 'second', 'the',
2 'and', 'one']
1 from sklearn.feature_extraction.text import TfidfTransformer
2 from sklearn.feature_extraction.text import CountVectorizer
3
4 if __name__ == '__main__':
5 count = CountVectorizer(vocabulary=vocabulary)
6 count_matrix = count.fit_transform(corpus).toarray()
7 tfidf_trans = TfidfTransformer(norm=None)
8 tfidf_matrix = tfidf_trans.fit_transform(count_matrix)
9 idf_vec = tfidf_trans.idf_
10 print(tfidf_matrix.toarray())
3.词云图
载入原始文本
1 def load_data_and_cut(file_path='./data/QuanSongCi.txt'):
2 cut_words = ""
3 with open(file_path, encoding='utf-8') as f:
4 for line in f:
5 line = line.strip('\n')
6 if len(line) < 20:
7 continue
8 seg_list = jieba.cut(clean_str(line), cut_all=False)
9 cut_words += (" ".join(seg_list))
10 all_words = cut_words.split()
11 return all_words
统计词频:
1 def get_words_freq(all_words, top_k=500):
2 c = Counter()
3 for x in all_words:
4 if len(x) > 1 and x != '\r\n':
5 c[x] += 1
6 vocab = {}
7 for (k, v) in c.most_common(top_k):
8 vocab[k] = v
9 return vocab
生成词云图:
1 def show_word_cloud(word_fre):
2 word_cloud = WordCloud(font_path='./data/simhei.ttf',
3 background_color='white', max_font_size=70)
4 word_cloud.fit_words(word_fre)
5 plt.imshow(word_cloud)
6 plt.xticks([]) # 去掉横坐标
7 plt.yticks([]) # 去掉纵坐标
8 plt.tight_layout()
9 plt.show()
自定义样式:
1 def show_word_cloud(word_fre):
2 from PIL import Image
3 img = Image.open('./data/dufu.png')
4 img_array = np.array(img)
5 word_cloud = WordCloud(font_path='./data/simhei.ttf',
6 background_color='white', max_font_size=70, mask=img_array)
7 word_cloud.fit_words(word_fre)
8 plt.imshow(word_cloud)
9 plt.xticks([]) # 去掉横坐标
10 plt.yticks([]) # 去掉纵坐标
11 plt.tight_layout()
12 plt.show()
本学习笔记来源于月来客栈
如有侵权,请联系删除!!!