文本向量化是文本表示的一种重要方式,其中词袋 Bag of Words(BOW) 和词向量Word Embedding是最常见的两种类型。
词袋模型:
是n-gram语法模型的特例1元模型。该模型忽略掉文本的语法和语序等要素,将其仅仅看作是若干个词汇的集合,文档中每个单词的出现都是独立的。BOW使用一组无序的单词(words)来表达一段文字或一个文档。常见表示方法:one-hot,词频,tf-idf 等
import jieba
from gensim import corpora
from pprint import pprint
text = ['我喜欢吃苹果',
'我爱吃香蕉,不喜欢吃苹果',
'他不想吃桃子',
'我想去上海玩',
'她游玩的地点在重庆',
'他正在北京玩']
category = [1,1,1,2,2,2]
corpus = []
for t in text:
corpus.append(list(jieba.cut(t)))
print('分词后 :')
pprint(corpus)
print()
# 构造词典
dic = corpora.Dictionary(corpus)
print('词典: ',dic)
print('词典token2id: ',dic.token2id)
print()
#向量化
corpus_vec= [dic.doc2bow(word) for word in corpus]
print('向量化:')
pprint(corpus_vec)
print()
outpt:
分词后 :
[['我', '喜欢', '吃', '苹果'],
['我', '爱', '吃', '香蕉', ',', '不', '喜欢', '吃', '苹果'],
['他', '不想', '吃', '桃子'],
['我', '想', '去', '上海', '玩'],
['她', '游玩', '的', '地点', '在', '重庆'],
['他', '正在', '北京', '玩']]
词典: Dictionary(23 unique tokens: ['吃', '喜欢', '我', '苹果', ',']...)
词典token2id: {'吃': 0, '喜欢': 1, '我': 2, '苹果': 3, ',': 4, '不': 5, '爱': 6, '香蕉': 7, '不想': 8, '他': 9, '桃子': 10, '上海': 11, '去': 12, '想': 13, '玩': 14, '在': 15, '地点': 16, '她': 17, '游玩': 18, '的': 19, '重庆': 20, '北京': 21, '正在': 22}
向量化:
[[(0, 1), (1, 1), (2, 1), (3, 1)],
[(0, 2), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)],
[(0, 1), (8, 1), (9, 1), (10, 1)],
[(2, 1), (11, 1), (12, 1), (13, 1), (14, 1)],
[(15, 1), (16, 1), (17, 1), (18, 1), (19, 1), (20, 1)],
[(9, 1), (14, 1), (21, 1), (22, 1)]]
从上面的例子,可以看到:
- 向量中每个元素顺序与原来文本中单词出现的顺序没有关系,与词典中的顺序一一对应
- 每个元组中的第一个元素对应字典中的词汇ID,第二个元素对应该词汇的计数
- 向量的维度根据词典中不重复词的个数确定
One Hot表示,可以使用keras进行处理
from keras.preprocessing.text import Tokenizer
import jieba
from pprint import pprint
text = ['我喜欢吃苹果',
'我爱吃香蕉,不喜欢吃苹果',
'他不想吃桃子',
'我想去上海玩',
'她游玩的地点在重庆',
'他正在北京玩']
category = [1,1,1,2,2,2]
corpus = []
for t in text:
corpus.append(" ".join(list(jieba.cut(t))))
tokenizer = Tokenizer() # 创建一个分词器(tokenizer),设置为只考虑前1000个最常见的单词
tokenizer.fit_on_texts(corpus) # 构建索引单词
sequences = tokenizer.texts_to_sequences(corpus) # 将字符串转换为整数索引组成的列表
print('sequences :')
pprint(sequences)
print()
one_hot_results = tokenizer.texts_to_matrix(corpus, mode='binary')
print('one hot :')
pprint(one_hot_results)
print()
word_index = tokenizer.word_index
print('word index : ')
print(sorted(word_index.items(),key=lambda item:item[1]))
从上面的例子可知,一旦数据量上来了,词袋模型的高维、稀疏、离散性,就会给模型的造成很大的困扰,矩阵的计算量非常庞大。改进的方式:采用词的分布式表示,如word2vec,Glove等
word2vec
word2vec作为神经概率语言模型的输入,其本身其实是神经概率模型的副产品,是为了通过神经网络学习某个语言模型而产生的中间结果。具体来说,“某个语言模型”指的是“CBOW”和“Skip-gram”。
详情原理,请参考一下链接
https://blog.csdn.net/itplus/article/details/37969979
实现
from gensim.models.word2vec import Word2Vec
import jieba
from pprint import pprint
text = ['我喜欢吃苹果',
'我爱吃香蕉,不喜欢吃苹果',
'他不想吃桃子',
'我想去上海玩',
'她游玩的地点在重庆',
'他正在北京玩']
corpus = []
for t in text:
corpus.append(list(jieba.cut(t)))
cbow_model = Word2Vec(corpus,min_count=1,sg=0,iter=5,hs=1)
skip_gram_model = Word2Vec(corpus,min_count=1,sg=1,iter=5,hs=1)
推荐文章:
https://zhuanlan.zhihu.com/p/53302305
推荐理由:深入浅出,一步步引导