本文根據實際項目撰寫,因爲項目保密要求,源代碼將進行必定程度的刪減。
本文撰寫的目的是進行公司培訓,請勿以任何形式進行轉載。
因爲是日語項目,用到的分詞軟件等,在中文任務中須要替換爲相應的中文分詞軟件。例如結巴分詞 : https://github.com/fxsjy/jiebahtml
若是須要得到更多知識,請自行百度,谷歌。中文資料不是不少,有能力請閱讀相關論文資料。java
餘弦類似度,又稱爲餘弦類似性,是經過計算兩個向量的夾角餘弦值來評估他們的類似度。餘弦類似度將向量根據座標值,繪製到向量空間中,如最多見的二維空間。python
將向量根據座標值,繪製到向量空間中。如最多見的二維空間。
求得他們的夾角,並得出夾角對應的餘弦值,此餘弦值就能夠用來表徵,這兩個向量的類似性。夾角越小,餘弦值越接近於1,它們的方向更加吻合,則越類似。git
單位向量是指模等於1的向量。因爲是非零向量,單位向量具備肯定的方向。一個非零向量除以它的模,可得所需單位向量。單位向量有無數個。
(矢量和向量是同一個意思,Vector,這裏習慣用矢量這個詞語)github
gensim.matutils.unitvec(vec, norm='l2')
Scale a vector to unit length. The only exception is the zero vector, which is returned back unchanged.
Output will be in the same format as input (i.e., gensim vector=>gensim vector, or np array=>np array, scipy.sparse=>scipy.sparse).算法
平行四邊形定則解決向量加法的方法:將兩個向量平移至公共起點,以向量的兩條邊做平行四邊形,結果爲公共起點的對角線。
平行四邊形定則解決向量減法的方法:將兩個向量平移至公共起點,以向量的兩條邊做平行四邊形,結果由減向量的終點指向被減向量的終點。數組
代數定義
設二維空間內有兩個向量
和
,定義它們的數量積(又叫內積、點積)爲如下實數:
更通常地,n維向量的內積定義以下:
網絡
TF-IDF是一種統計方法,用以評估一字詞對於一個文件集或一個語料庫中的其中一份文件的重要程度。字詞的重要性隨着它在文件中出現的次數成正比增長,但同時會隨着它在語料庫中出現的頻率成反比降低。TF-IDF加權的各類形式常被搜索引擎應用,做爲文件與用戶查詢之間相關程度的度量或評級。除了TF-IDF之外,因特網上的搜索引擎還會使用基於連接分析的評級方法,以肯定文件在搜尋結果中出現的順序。app
在天然語言處理中,一個很重要的技術手段就是將文檔轉換爲一個矢量,這個過程通常是使用gensim這個庫進行處理的。
gensim官網地址
若是你須要Java版本的Doc2Vec:
https://github.com/NLPchina/Word2VEC_java機器學習
Token在詞法分析中是標記的意思。天然語言處理中,通常來講,Token表明「詞」。天然語言預處理中,一個很重要的步驟就是將你收集的句子進行分詞,將一個句子分解成「詞」的列表。
交叉驗證(Cross validation),有時亦稱循環估計, 是一種統計學上將數據樣本切割成較小子集的實用方法。因而能夠先在一個子集上作分析, 而其它子集則用來作後續對此分析的確認及驗證。 一開始的子集被稱爲訓練集。而其它的子集則被稱爲驗證集或測試集。交叉驗證是一種評估統計分析、機器學習算法對獨立於訓練數據的數據集的泛化能力(generalize)
least-one-out cross-validation(loocv)
假設dataset中有n個樣本,那LOOCV也就是n-CV,意思是每一個樣本單獨做爲一次測試集,剩餘n-1個樣本則作爲訓練集。
優勢:
1)每一回閤中幾乎全部的樣本皆用於訓練model,所以最接近母體樣本的分佈,估測所得的generalization error比較可靠。
2)實驗過程當中沒有隨機因素會影響實驗數據,確保實驗過程是能夠被複制的。
但LOOCV的缺點則是計算成本高,爲須要創建的models數量與總樣本數量相同,當總樣本數量至關多時,LOOCV在實做上便有困難,除非每次訓練model的速度很快,或是能夠用平行化計算減小計算所需的時間。
[sklearn學習]linear_model.LinearRegression
from sklearn.linear_model import LinearRegression
fit(X, y[, n_jobs]) 對訓練集X, y進行訓練。是對scipy.linalg.lstsq的封裝
score(X, y[,]sample_weight) 定義爲(1-u/v),其中u = ((y_true - y_pred)**2).sum(),而v=((y_true-y_true.mean())**2).mean()
最好的得分爲1.0,通常的得分都比1.0低,得分越低表明結果越差。
其中sample_weight爲(samples_n,)形狀的向量,能夠指定對於某些sample的權值,若是以爲某些數據比較重要,能夠將其的權值設置的大一些。
語料庫的準備,就是將你準備好的文章庫,轉換爲一個語料庫。
你的文章通常會被保存爲TaggedDocument,也就是帶有標籤的文檔。
一篇文章對應着一個TaggedDocument對象。
TaggedDocument裏面存放的是Token列表和Tag:
其中Token列表就是將文章經過分詞軟件分紅的詞語的列表,Tag這裏保存着原來文章的編號。
下面這個代碼中 tdocs變量表示一個TaggedDocument數組。
注意:在gensim之前版本中TaggedDocument是LabeledSentence
corpus = Doc2Vec(tdocs, dm=1, dm_mean=1, size=300, window=8, min_count=2, workers=4, iter=20) corpus.save(os.path.join(WORK_DIR, 'base-pv_dm.mdl'))
關於這個函數的參數介紹,能夠參考這裏,全英文很是晦澀難懂的介紹:
https://radimrehurek.com/gensim/models/doc2vec.html
dm defines the training algorithm. By default (dm=1), ‘distributed memory’ (PV-DM) is used. Otherwise, distributed bag of words (PV-DBOW) is employed.
dm:定義了訓練的算法,默認值爲1,使用 ‘distributed memory’方法,否則則使用分佈式的「bag of words」 方法。(dm,應該是doc model的意思,文檔模型,這個須要進一步調查)
size is the dimensionality of the feature vectors.
size:是向量的維度,本項目維度設定是300。維度這個參數也是須要經過大量實驗得到最佳的值。
dm_mean = if 0 (default), use the sum of the context word vectors. If 1, use the mean. Only applies when dm is used in non-concatenative mode.
dm_mean:若是是默認值0,則使用上下文向量的和(SUM),若是是1的話,則使用上下文向量的平均值。這個僅僅在dm使用non-concatenative的模式才發生效果。
workers = use this many worker threads to train the model (=faster training with multicore machines).
若是是多核處理器,這裏能夠指定並行數
iter = number of iterations (epochs) over the corpus. The default inherited from Word2Vec is 5, but values of 10 or 20 are common in published ‘Paragraph Vector’ experiments.
迭代次數:默認的迭代次數是5,可是最佳實踐應該是10或者20.
min_count = ignore all words with total frequency lower than this.
若是出現頻率少於min_count,則忽略
window is the maximum distance between the predicted word and context words used for prediction within a document.
window是被預測詞語和上下文詞語在同一個文檔中的最大的距離。
語料庫也是支持序列化操做的,語料庫能夠保存爲磁盤上的文件:
Save the object to file (also see load).
fname_or_handle is either a string specifying the file name to save to, or an open file-like object which can be written to. If the object is a file handle, no special array handling will be performed; all attributes will be saved to the same file.
語料庫建成以後,就能夠進行一些有趣的檢索了。
例如參考文檔 [Algorithm & NLP] 文本深度表示模型——word2vec&doc2vec詞向量模型 中的句子類似度實驗:
下面是sentence2vec的結果示例。先利用中文sentence語料訓練句向量,而後經過計算句向量之間的cosine值,獲得最類似的句子。能夠看到句向量在對句子的語義表徵上仍是至關驚歎的。
這裏的類似度檢索是指,給定一個正面的句子,而後檢索和其類似度最大的句子。
固然,這裏也能夠指定一個負面的句子,也就是和這個句子越不類似越好。
這裏有一個限制,若是正面的句子和負面的句子,進行分詞以後,沒有一個詞語是被訓練過的(被訓練過的詞語,是指語料庫裏面存在的詞語),則沒法進行操做。
具體在求類似度的操做以前,檢索用向量須要進行一下處理。
假設positive變量是一個數組,數組裏面存放着正面的Token。
corpus[token]表示token的矢量,這裏對矢量進行按列求和,結果是一個和token維度同樣的矢量。換句話說,就是將多個矢量合併爲單個矢量。(Token矢量的求和矢量)
而後將上面那個「Token矢量的求和矢量」,和新的positive的推測矢量進行相加,得到一個新的"求類似度用矢量"。
(Negative和Positive相似)
p = np.array([ corpus[token] for token in positive ]).sum(axis=0) p = p + corpus.infer_vector(positive, steps=20) n = np.array([ corpus[token] for token in negative ]).sum(axis=0) n = n + corpus.infer_vector(negative, steps=20)
在語料庫對象(Document Model)中有一個頗有用的方法infer_vector,這個方法能夠基於當前的文檔模型快速,將一個文檔轉換(按照模型推測)成一個矢量。
infer_vector
(doc_words, alpha=0.1, min_alpha=0.0001, steps=5)
Infer a vector for given post-bulk training document.
Document should be a list of (word) tokens.
在機器學習界,有兩種機器學習方式,一種是Online的,一種是Offline的。Online的方式,模型能夠實時更新,新的樣本會被實時進行訓練,訓練結果也實時反映到模型中去。Offline的方式,若是有新的樣本,則須要將新老樣本放在一塊兒,從新進行訓練。這裏的話,模型沒法進行Online的訓練,因此新的樣本,只是基於訓練好的模型,被轉換(推測 Infer,有些相似於預測Predict)爲一個矢量。
類似度計算的核心方法是most_similar
most_similar
(positive=[], negative=[], topn=10, clip_start=0, clip_end=None, indexer=None)
Find the top-N most similar docvecs known from training. Positive docs contribute positively towards the similarity, negative docs negatively.
This method computes cosine similarity between a simple mean of the projection weight vectors of the given docs. Docs may be specified as vectors, integer indexes of trained docvecs, or if the documents were originally presented with string tags, by the corresponding tags.
The ‘clip_start’ and ‘clip_end’ allow limiting results to a particular contiguous range of the underlying doctag_syn0norm vectors. (This may be useful if the ordering there was chosen to be significant, such as more popular tag IDs in lower indexes.)
尋找最類似的N個文檔。正面(Positive)文檔向類似度貢獻正面的值,負面(Negative)文檔貢獻負面的值。這個方法經過計算給定文章的矢量的加權平均值的餘弦類似度來給出結果。能夠經過矢量,被訓練過的文檔矢量的下標,或者原始的字符串標籤來指定文檔(正面或者負面文檔)。
‘clip_start’ 和 ‘clip_end’則是指定了類似度檢索的範圍。
官方文檔其實說明的不是很清楚,不少地方仍是不容易理解。
topn這個參數應該沒有問題,你想返回最類似的多少個,這裏就指定多少便可。
對於positive和nagative的指定,首先明確一下,這裏必須是一個數組,即便只有一個值,也必須是數組。
positive和nagative數組裏面的值,能夠是:
1.具體的文檔的矢量
2.被訓練過的文檔的下標
3.文檔的Tag字符。(本項目裏面的Tag就是文檔的編號)
具體到這個項目中,Positive則是上文提到的"求類似度用矢量"。
‘clip_start’ 和 ‘clip_end’則是指定了類似度檢索的範圍,這個通常是用來限定檢索範圍,例如只想在1年或者3年的資料中進行檢索。
情感分析是創建在文檔的聚類基礎上的。因爲計算量比較巨大,項目使用的是MiniBatchKMeans。
在有效減小計算時間的同時,也能保證計算偏差在可接受範圍中。
項目中使用的是Leave-One-Out Cross Validation,每次將一個樣本做爲測試集,一共進行n次交叉驗證。
K-Means算法是經常使用的聚類算法,但其算法自己存在必定的問題,例如在大數據量下的計算時間過長就是一個重要問題。爲此,Mini Batch K-Means,這個基於K-Means的變種聚類算法應運而生。
from sklearn.cluster import MiniBatchKMeans X_km_norm = [ unitvec(x) for x in X_km ] #轉爲單位向量 km_all = MiniBatchKMeans(n_clusters=8) #分爲8個簇 km_all.fit(X_km_norm) #計算8個簇的質心
fit(X, y=None)
Compute the centroids on X by chunking it into mini-batches.
fit擬合操做,實際上就是計算每一個簇的質心。
因此說,若是簇只有一個的話,擬合的意義是求出整個數據的質心。
predict(X)
Predict the closest cluster each sample in X belongs to.
predict預測操做,是給出每一個樣本屬於哪一個簇的結果
項目中將全部樣本按照時間分爲:1年期樣本和3年期樣本。同時根據其餘業務規則進行了分類(分類規則須要保密)。因爲收集樣本的渠道不一樣(不一樣的公司,組織提供的樣本數據),全部的樣本還須要進行Remove Common Factor的操做:
1.樣本的分類並無按照渠道進行分類,因此這裏同一收集渠道的樣本,也會被分在不一樣的類中
2.全部分類樣本,例如1年期,3年期的樣本,都必須進行Remove Common Factor
3.同同樣本可能同時存在於不一樣分類組裏面,由於有些是按照時間分類的,有些是按照業務分類的,分類的維度不一樣。
代碼的邏輯以下:
fit:XX[tag]裏面的tag表示收集渠道,XX[tag]表示某個渠道的樣本矢量數組:
_cf[tag]:表示某個渠道的Common Factor矢量,這裏使用np.array(XX[tag]).mean(axis=0)按列求均值得到的。每個渠道有一個Common Factor矢量。
remove代碼則是將某個渠道里面全部的矢量,都剪去Common Factor矢量
(代碼有刪減,原來代碼裏面有對於未知渠道的防護代碼,這裏已經簡化)
class CommonFactor(object): def __init__(self): self._cf = {} def fit(self, XX): for tag in XX: if XX[tag]: shape = XX[tag][0].shape self._cf[tag] = np.array(XX[tag]).mean(axis=0) return self def remove(self, XX): return dict([ (tag, [ x - self._cf[tag] for x in XX[tag] ]) for tag in XX ])
推薦經過網絡上的 廖雪鋒的Python教程 學習python語法
axis:求和的維。
>>> np.sum([0.5, 1.5]) 2.0 >>> np.sum([0.5, 0.7, 0.2, 1.5], dtype=np.int32) 1 >>> np.sum([[0, 1], [0, 5]]) 6 >>> np.sum([[0, 1], [0, 5]], axis=0) array([0, 6]) >>> np.sum([[0, 1], [0, 5]], axis=1) array([1, 5])
axis:求平均的維。
>>> a = np.array([[1, 2], [3, 4]]) >>> np.mean(a) 2.5 >>> np.mean(a, axis=0) array([ 2., 3.]) >>> np.mean(a, axis=1) array([ 1.5, 3.5])
python中使用 .1 表明浮點數 0.1 或者 1. 表明浮點數 1.0。
緣由是要保證結果的精度,防止程序自動強制轉換。
score = lambda X, y: 1.-((y-X)**2).sum()/((y-y.mean())**2).sum()
幾つかの數値データを小さい順に並べたとき、小さい方から數えて全體のX%に位置する値をXパーセンタイルと言います。
(數值按照從小到大進行排列,從小的數字開始計算,全體數字的X%的位置,數值是多少)
例えば10人のクラスがあるとして、各生徒のテストの點數が[40, 50, 60, 70, 75, 80, 83, 86, 89, 95]だったとします。
その時、下から95%に位置する點數(逆に言うと上位5%に位置する點數)が何點なのか示すものが95パーセンタイルになります。
如下、numpyを使ったサンプルです。
>>> import numpy as np >>> a = np.array([40, 50, 60, 70, 75, 80, 83, 86, 89, 95]) >>> np.percentile(a, 95) # 95パーセンタイルを求めます(逆に言うと上位5%に位置する點數) 92.299999999999997 # 95パーセンタイルは約92.3點であることがわかります >>> np.percentile(a, 30) # 30パーセンタイルを求めます(逆に言うと上位70%に位置する點數) 67.0 # 30パーセンタイルは67.0點であることがわかります
數學之美:14章 餘弦定理和新聞的分類 (吳軍,第二版)
TF-IDF與餘弦類似性的應用(一):自動提取關鍵詞
TF-IDF與餘弦類似性的應用(二):找出類似文章
Sentiment Analysis Using Doc2Vec
[Algorithm & NLP] 文本深度表示模型——word2vec&doc2vec詞向量模型
【転職會議】クチコミをword2vecで天然言語処理して會社を分類してみる
適合大數據的聚類算法Mini Batch K-Means
K-means算法及文本聚類實踐
パーセンタイルについて