【文字挖掘】(三)文字表示

txmmy發表於2024-05-20

文字表示的概念

  • 核心:將字串以計算機形式進行表示出來,如向量化。
  • 分類
  • 離散/向量表示:詞袋模型(獨熱編碼、TF-IDF、N-gram)
  • 分散式表示:詞嵌入word embedding,包括word2vec、Glove、ELMO、GPT、BERT等。
  • 基於矩陣:基於降維表示和基於聚類表示
  • 基於神經網路:CBOW、Skip-gram、NNLM、C&W

文字預處理

一般過程:
image

  1. 刪除段前後空格
  2. 文字分段
  3. 識別斷句符號,如", \ !"等,用斷句符號標記句子
  4. 分詞
  5. 詞性標註
  6. 特徵選取
  7. 設定特徵詞彙權重
  8. 形成向量空間模型

向量空間模型VSM: vector space model

權重計算

  • 布林權重
  • 詞頻權重
  • TF-IDF

向量相似度量

向量內積

  • 普通形式

\[Sim(D_i,D_j)=\sum^n_k=1({t_ik}\times{t_jk}) \]

  • 歸一化形式

\[Sim(D_i,D_j)=cos\theta=\frac{\sum^n_k=1({t_ik}\times{t_jk})}{ \sqrt{ \sum^n_{k=1}{t_{ik}} } \times \sqrt{ \sum^n_{k=1}{t_{jk}} } } \]

向量間的距離

  • 絕對值距離
  • 歐幾里得距離
  • 切比雪夫距離

程式碼案例

案例1 計算文件Di=(0.2,0.4,0.11,0.06)和Dj=(0.14,0.21,0.026,0.34)的餘弦相似度。

  • 使用內積函式dot()和正規化函式linalg.norm()
import numpy as np
di=[0.2,0.4,0.11,0.06]
dj=[0.14,0.21,0.026,0.34]
dist1=np.dot(Di,Dj)/np.linalg.norm(Di)*np.linalg.norm(Dj)
  • 使用scipy
from scipy import spatial
dist1=1-spatial.distance.cosine(Di,Dj)
  • 使用sklearn
dfrom sklarn.metrics.pairwise import cosine_similarity
dist1=cosine_similar(Di.reshape(1,-1),Dj.reshape(1,-1))

案例2 計算兩個句子的相似度

D1='我喜歡看電視,不喜歡看電影'
D2='我不喜歡看電視,也不喜歡看電影'

# 分詞
split1=[ word for word in jieba.cut(D1) if word not in [',','。']]
split1=[ word for word in jieba.cut(D2) if word not in [',','。']]
# 列出所有的詞
wordset=set(split1).union(split2)
# 統計詞頻
def computeTF(wordSet,split):
	tf=dict.fromkeys(wordSet,0)
	for word in split:
		tf[word]+=1
	return tf

tf1=computeTF(wordSet,split1)
tf2=computeTF(wordSet,split2)
# 詞頻向量
s1=list(tf1.values())
s2=list(tf2.values())

#計算餘弦相似性
dist1=np.dot(s1,s2)/(np.linalg.norm(s1)*np.linalg.norm(s2))

文字表示方法

離散/向量表示

TF-IDF

\[詞頻(Term Frequency)=\frac{某個詞在文章出現總次數}{文章的總詞數}=\frac{某個詞在文章出現總次數}{該訓練文字出現最多次的詞數} \]

\[逆文件頻率(Inverse Document Frequency)=\log\frac{總樣本數}{包含該詞的文件數+1},其中,+1為了避免分母為0。 \]

詞袋模型Big of Words

  • 基於BOW計算文件相似度的gensim實現
1.建立字典
from gensim.corpora import Dictionary
import jieba
str01='大魚吃小魚也吃蝦米,小魚吃蝦米'
text01=[ [for word in jieba.cut(str,cut_all=Ture) if word note in [",","。","大魚吃","大魚吃小魚"]]]

# Dictionary類用於建立word<->id對映關係,把所有單詞取一個set(),並對set中每個單詞分配一個id號的map。
dict01=Dictionary(text01)
dict01.dfs          # 字典{單詞id,在多少文件中出現}
dict01.num_docs     # 文件數目
dict01.num_nnz      # 每個檔案中不重複詞個數的和
dict01.num_pos      # 所有詞的個數
dict01.token2id     # 字典,{單詞,對應id}
dict01.id2token()     #字典,{單詞id,對應的單詞}
# 向字典新增詞條
dict01.add_documents([['貓','愛']])
dict01.token2id.keys()
# 轉換為BOW稀疏向量
'''allow_update = False : 是否直接更新所用字典
   return_missing = False : 是否返回新出現的(不在字典中的)詞'''
print(sum(text01,[]))
dict01_cp=dict01.doc2bow(sum(text01,[]),return_missing=True)

輸出結果

[(0, 2), (1, 2)],表明在文件中id為0,1的詞彙各出現了2次,至於其他詞彙則沒有出現
return_missing = True時,輸出list of (int, int), dict of (str, int)
# 轉換為BOW長向量 doc2idx
#doc2idx( # 轉換為list of token_id
#    document : 用於轉換的詞條list
#    unknown_word_index = -1 : 為不在字典中的詞條準備的程式碼
#輸出結果:按照輸入list的順序列出所出現的各詞條#ID
str="小魚吃蝦米"
text=[  word for word in jieba.cut(str)]
dict01.doc2idx(text)

輸出結果

[3,1,4]
  • Sklearn.CountVectorizer
'''
class sklearn.feature_extraction.text.CountVectorizer(

    input = 'content' : {'filename', 'file', 'content'}filename為所需讀入的檔案列表, file則為具體的檔名稱。

    encoding='utf-8' : 文件編碼

    stop_words = None : 停用詞列表,當analyzer == 'word'時才生效

    min_df / max_df : float in range [0.0, 1.0] or int, default = 1 / 1.0

    詞頻絕對值/比例的閾值,在此範圍之外的將被剔除小數格式說明提供的是百分比,如0.05指的就是5%的閾值)

CountVectorizer.build_analyzer()   # 返回文字預處理和分詞的可呼叫函式
'''

image
image
image

分散式表示

Word2Vec

Doc2Vec

相關文章