文字表示的概念
- 核心:將字串以計算機形式進行表示出來,如向量化。
- 分類
- 離散/向量表示:詞袋模型(獨熱編碼、TF-IDF、N-gram)
- 分散式表示:詞嵌入word embedding,包括word2vec、Glove、ELMO、GPT、BERT等。
- 基於矩陣:基於降維表示和基於聚類表示
- 基於神經網路:CBOW、Skip-gram、NNLM、C&W
文字預處理
一般過程:
- 刪除段前後空格
- 文字分段
- 識別斷句符號,如", \ !"等,用斷句符號標記句子
- 分詞
- 詞性標註
- 特徵選取
- 設定特徵詞彙權重
- 形成向量空間模型
向量空間模型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() # 返回文字預處理和分詞的可呼叫函式
'''