一、分詞
1、采用jieba分詞
安裝:全自動(dòng)安裝:pip install jieba / pip3 install jieba
https://blog.csdn.net/flysky1991/article/details/73948971
http://www.itdecent.cn/p/e8b5d01ca073
https://www.cnblogs.com/echo-cheng/p/7967221.html
https://www.cnblogs.com/Denise-hzf/p/6612212.html
三種分詞模式:
-精確模式:試圖將句子最精確地切開,適合文本分析;(選擇)
-全模式:把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義;
-搜索引擎模式:在精確模式的基礎(chǔ)上,對(duì)長詞再次切分,提高召回率,適合用于搜索引擎分詞。
主要涉及如下幾種算法:
(1)基于前綴詞典實(shí)現(xiàn)高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構(gòu)成的有向無環(huán)圖 (DAG);
DAG分詞過程:對(duì)待分詞句子, 根據(jù)給定的詞典進(jìn)行查詞典操作, 生成幾種可能的句子切分。dag記錄的是句子中某個(gè)詞的開始位置, 從0到n-1(n為句子的長度), 每個(gè)開始位置作為字典的鍵, value是個(gè)list, 其中保存了可能的詞語的結(jié)束位置(通過查字典得到詞, 開始位置+詞語的長度得到結(jié)束位置)。
例如:{0:[1,2,3]} 這樣一個(gè)簡單的DAG, 就是表示0位置開始, 在1,2,3位置都是詞, 就是說0~1, 02,03這三個(gè)起始位置之間的字符, 在dict.txt中是詞語。
比如 sentence 是 "國慶節(jié)我在研究結(jié)巴分詞",對(duì)應(yīng)生成的DAG是這樣的:{0: [0, 1, 2], 1: [1], 2: [2], 3: [3], 4: [4], 5: [5, 6], 6: [6], 7: [7, 8], 8: [8], 9: [9, 10], 10: [10]} 其中的數(shù)字表示每個(gè)漢字在sentence中的位置,所以0:[0,1,2] 表示 在trie 樹中,"國"開頭的詞語中對(duì)應(yīng)于該 sentence 有三種匹配情況:國,國慶,國慶節(jié)。
(2)采用了動(dòng)態(tài)規(guī)劃查找最大概率路徑, 找出基于詞頻的最大切分組合;
(3)對(duì)于未登錄詞,采用了基于漢字成詞能力的 HMM 模型,采用Viterbi 算法(動(dòng)態(tài)規(guī)劃)進(jìn)行計(jì)算==>HMM五元組中(觀察值(句子),狀態(tài)轉(zhuǎn)移矩陣(BMES 4X4),發(fā)射矩陣(4Xn(好多漢字)),初始狀態(tài)值(BMES))求解狀態(tài)值(BMES),根據(jù)狀態(tài)值分詞
https://blog.csdn.net/riverflowrand/article/details/50057323
(4)基于Viterbi算法做詞性標(biāo)注;(計(jì)算概率)

http://www.cnblogs.com/bottlebox/archive/2011/11/21/2256644.html
(5)基于tf-idf和textrank模型抽取關(guān)鍵詞;
textrank與tf-idf不同,不再依賴語料環(huán)境(通過語料環(huán)境求idf)
textrank公式:

其中,d是阻尼系數(shù),防止結(jié)果為0,一般取0.85
程序步驟:
1、文章分詞: 對(duì)每一篇文章進(jìn)行分詞,分詞系統(tǒng)主要由坤雁分詞系統(tǒng)、ansj分詞,結(jié)巴分詞等。
2、分詞結(jié)果數(shù)據(jù)清洗: 主要包括去停用詞、去除符號(hào)字母數(shù)字等。
3、構(gòu)建候選關(guān)鍵詞圖: 根據(jù)設(shè)定的詞語選擇窗口截取文本的分詞結(jié)果,將每個(gè)詞語作為候選關(guān)鍵詞圖的節(jié)點(diǎn),截取的每一段文本中的詞語作為相鄰的邊,以此構(gòu)建候選關(guān)鍵詞圖。
4、關(guān)鍵詞提?。?利用pagerank思想循環(huán)迭代候選關(guān)鍵詞圖, 每個(gè)節(jié)點(diǎn)的權(quán)重初始化化為1.0f,通過設(shè)定的迭代次數(shù)達(dá)到穩(wěn)定后,對(duì)節(jié)點(diǎn)權(quán)重進(jìn)行倒序排序,從而得到最重要的num個(gè)單詞,作為候選關(guān)鍵詞。
程序主要包含兩大部分,第一部分為候選關(guān)鍵詞圖構(gòu)件。第二部分為關(guān)鍵詞提取
1.依賴語料
tf-idf的idf值依賴于語料環(huán)境,這給他帶來了統(tǒng)計(jì)上的優(yōu)勢,即它能夠預(yù)先知道一個(gè)詞的重要程度.這是它優(yōu)于textrank的地方。
而textrank只依賴文章本身,它認(rèn)為一開始每個(gè)詞的重要程度是一樣的。
2.詞語的互相關(guān)聯(lián)性
tf-idf是純粹用詞頻的思想(無論是tf還是idf都是)來計(jì)算一個(gè)詞的得分,最終來提取關(guān)鍵詞,完全沒有用到詞之間的關(guān)聯(lián)性。
而textrank用到了詞之間的關(guān)聯(lián)性(將相鄰的詞鏈接起來),這是其優(yōu)于tf-idf的地方。
https://blog.csdn.net/u013041398/article/details/52473994
https://blog.csdn.net/gzt940726/article/details/80256011
例子:
# encoding=utf-8
import jieba
seg_list = jieba.cut("滄州渤海新區(qū)金龍渤海新城三期B幢401號(hào)英泰麗斯科技發(fā)展有限公司2015年11月16日", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list)) # 全模式
Full Mode: 滄州/ 渤海/ 新區(qū)/ 金/ 龍/ 渤海/ 新城/ 三期/ B/ 幢/ 401/ 號(hào)/ 英/ 泰/ 麗斯/ 科技/ 發(fā)展/ 有限/ 有限公司/ 公司/ 2015/ 年/ 11/ 月/ 16/ 日
seg_list = jieba.cut("滄州渤海新區(qū)金龍渤海新城三期B幢401號(hào)英泰麗斯科技發(fā)展有限公司2015年11月16日", cut_all=False) #cut_all=False可以不寫
print("Default Mode: " + "/ ".join(seg_list)) # 精確模式 默認(rèn)
Default Mode: 滄州/ 渤海/ 新區(qū)/ 金龍/ 渤海/ 新城/ 三期/ B/ 幢/ 401/ 號(hào)/ 英泰/ 麗斯/ 科技/ 發(fā)展/ 有限公司/ 2015/ 年/ 11/ 月/ 16/ 日
seg_list = jieba.cut_for_search("滄州渤海新區(qū)金龍渤海新城三期B幢401號(hào)英泰麗斯科技發(fā)展有限公司2015年11月16日") # 搜索引擎模式
print("Search Mode: ".join(seg_list))
Search Mode: 滄州/ 渤海/ 新區(qū)/ 金龍/ 渤海/ 新城/ 三期/ B/ 幢/ 401/ 號(hào)/ 英泰/ 麗斯/ 科技/ 發(fā)展/ 有限/ 公司/ 有限公司/ 2015/ 年/ 11/ 月/ 16/ 日
二、建立自己字典
分詞后,針對(duì)自己當(dāng)前的分類目的需要對(duì)自己的數(shù)據(jù)集建立詞典(word_dict),通常train.txt,test.txt,val.txt(能得到的所有文件)都用來建立字典,字典就是一個(gè)word_dict.txt文件,里面存有所有出現(xiàn)過的詞。
在應(yīng)用的時(shí)候,每一個(gè)詞會(huì)對(duì)應(yīng)一個(gè)index,可以通過文本中單詞順序定義為0,1,2...也可以根據(jù)建詞典時(shí)的詞頻降序標(biāo)為0,1,2,3...
full_feature_set = set([key for key in full_feature_set])
# ensure <unk> is 0
word_dict = {v:(k+1) for (k,v) in enumerate(full_feature_set - set(['<unk>']))}
word_dict['<unk>'] = 0
word_dict得到字典key:word, value:index
對(duì)于一個(gè)輸入的句子,每一個(gè)詞通過word_dict對(duì)應(yīng)一個(gè)index,最后會(huì)得到一個(gè)列表作為網(wǎng)絡(luò)輸入,例如,你好:1,世界:2,則句子"你好 世界"對(duì)應(yīng)網(wǎng)絡(luò)輸入[1, 2]
out of vocabulary未登錄詞:如果對(duì)于測試集出現(xiàn)了word_dict中沒有的詞,則可以用<unk>代替,或者更新word_dict(在數(shù)據(jù)量較大生成word_dict時(shí)頻率小于5的詞一般不計(jì)入)
三、embedding layer
https://www.zhihu.com/question/45027109?sort=created
embedding layer是網(wǎng)絡(luò)的第一層,經(jīng)過該層可以產(chǎn)生詞向量
詞匯是語料庫的基本元素, 所以, 使用embedding layer來學(xué)習(xí)詞嵌入, 將一個(gè)詞映射成為固定維度的稠密向量. 有了這一步, 才能構(gòu)造矩陣, 實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)的前向傳播.
如何使用?
- 從頭訓(xùn)練
就像word2vec一樣, 這一層是可學(xué)習(xí)的, 用隨機(jī)數(shù)initialize , 通過BP去調(diào)整. - pre-trained + fine tuning
用其他網(wǎng)絡(luò)(如 word2vec、glove) 訓(xùn)練好的現(xiàn)成的詞向量, 作為初始化參數(shù), 然后繼續(xù)學(xué)習(xí). - pre-trained + static
用其他網(wǎng)絡(luò)(如 word2vec、glove) 訓(xùn)練好的現(xiàn)成的詞向量, 作為初始化參數(shù), 并且這些參數(shù)保持固定, 不參與網(wǎng)絡(luò)的學(xué)習(xí).
keras 的 Embedding
Embedding(Layer) 類.
- 將索引映射為固定維度的稠密的向量.
eg. [[4], [20]] -> [[0.25, 0.1], [0.6, -0.2]]
This layer can only be used as the first layer in a model.
__init__(self, input_dim, output_dim,input_length,...)
- 構(gòu)造函數(shù),三個(gè)參數(shù)分別代表vocab_size、vector_dimension、fixed_word_number.
- 繼承自父類的weights、trainable參數(shù).
如一個(gè)語料庫, 詞匯量為20萬, word representation vector is 200d, 文章的截?cái)嚅L度為250個(gè)單詞, 那么
embedding_layer=Embedding(input_dim=20E4,output_dim=200,input_length=250,weights=embedding_matrix,trainable=is_trainable)
實(shí)現(xiàn)過程
輸入是word2index得到的第一個(gè)句子列表[1, 33, 55, 3]四個(gè)詞,第二個(gè)句子[33, 56]兩個(gè)詞,對(duì)于每一個(gè)句子要設(shè)置成相同的維數(shù),不夠補(bǔ)零,大于截?cái)?br>
pad_sequence 函數(shù)
對(duì)于word2vec得到的.bin文件,他的主要作用是用來對(duì)embedding layer進(jìn)行初始化,因?yàn)殡S機(jī)初始化訓(xùn)練時(shí)間較長,將訓(xùn)練集中的詞在.bin文件中查找,如果存在就得到它的詞向量。
pretrain_embed = 'path'
pre_vocab = 'path1'
pretrain_embedding = loadPretrain(pretrain_embed)
vocab = loadVocab(pre_vocab) # all word in embedding word2index
word_embeds = np.random.uniform(-np.sqrt(0.01), np.sqrt(0.01), (len(word_dict), emb_dim))
n = 0
for w in word_dict:
if w in vocab:
word_embeds[word_dict[w]] = pretrain_embeding[vocab[w]]
n +=1
else:
print(w)
其中pre_vocab和pretrain_embed是由.bin文件得到的,得到的方式:
pip install torchwordemb
import torchwordemb
torchwordemb.load_word2vec_bin(path)
read word2vec binary-format model from path.
return(vocab, vec)
- vocab is a dict mapping a word to its index
- vec is a torch.FloatTensor of size V x D, which V is teh vocabulary size and D is the dimension of wordd2vec.
vocab, vec = torchwordemb.load_word2vec_bin("***.bin")
print(vrc.size())
print(vec[w2v.vocab["apple"]])
torchwordemb.load_word2vec_text(path)
read word2vec text-format model from path.
torchwordemb.load_glove_text(path)
read glove text-format model from path.
其實(shí)就是One hot representation?。?gt; Distributed representation
四、神經(jīng)網(wǎng)絡(luò)
embedding層后就開始接神經(jīng)網(wǎng)絡(luò),CNN/RNN/LSTM/RCNN
以RNN為例:
self.loss_val = self.loss() # -->self.loss_nce()
self.train_op = self.train()
self.predictions = tf.argmax(self.logits, axis=1, name="predictions") # shape:[None,]
correct_prediction = tf.equal(tf.cast(self.predictions, tf.int32), self.input_y) # tf.argmax(self.logits, 1)-->[batch_size]
self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name="Accuracy") # shape=()
loss ==> 交叉熵?fù)p失+l2損失
(可選:nce_loss ==> nce_loss + l2損失)
學(xué)習(xí)率:
通過tf.train.exponential_decay函數(shù)實(shí)現(xiàn)指數(shù)衰減學(xué)習(xí)率。
步驟:
1.首先使用較大學(xué)習(xí)率(目的:為快速得到一個(gè)比較優(yōu)的解);
2.然后通過迭代逐步減小學(xué)習(xí)率(目的:為使模型在訓(xùn)練后期更加穩(wěn)定);
tf.train.exponential_decay(learning_rate, global_step, decay_steps, decay_rate, staircase=True/False)
公式:decayed_learning_rate=learining_rate*decay_rate^(global_step/decay_steps)
- decayed_learning_rate為每一輪優(yōu)化時(shí)使用的學(xué)習(xí)率;
- learning_rate為事先設(shè)定的初始學(xué)習(xí)率;
- decay_rate為衰減系數(shù);
- decay_steps為衰減速度。
- tf.train.exponential_decay函數(shù)則可以通過staircase(默認(rèn)值為False,當(dāng)為True時(shí),(global_step/decay_steps)則被轉(zhuǎn)化為整數(shù)) ,選擇不同的衰減方式。
初始的學(xué)習(xí)速率是learining_rate,如果staircase=True,那就表明每decay_steps次計(jì)算學(xué)習(xí)速率變化,更新原始學(xué)習(xí)速率,如果是False,那就是每一步都更新學(xué)習(xí)速率。學(xué)習(xí)速率第一次訓(xùn)練開始變化,global_steps每次自動(dòng)加1。