文本向量化是文本表示的一種重要方式,其中詞袋 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
推薦理由:深入淺出,一步步引導