相關性與相似度

該文章爲筆記

在前文中記錄了方差表示的是一組數據相對於平均數μ\mu的離散程度的博客,一個班的學生成績方差很大,說明這個班的學生成績波動很厲害,有的特別好,有的特別差。這裏描述的是某一個變量所體現背後的含義(維度或者稱爲指標)。

相似度與相關性不是一種產物,不能被他們的名字搞混淆;比如兩個文本的相似度,在考察兩個文本的相似度時,需要分別文本進行分詞計算每個詞語的詞頻,形成詞頻向量。再計算兩個詞頻向量的餘弦夾角,根據夾角的值域得出兩個文本的相似度。

詞頻向量中有多個詞,每一個詞就是向量中的一個維度;而下圖中的菜品銷售量,某個菜品的銷售量是一個維度下含有多個值,不是多個維度。某兩個菜品的相關性,是指兩個維度的進行比較;而相似度是若干個維度進行比較。

在一個菜館中,會有一個菜品的銷量,關於這個銷量。我們想要得出,某個客人點了百合醬蒸風爪,要給他做一個推薦。推薦的規則是與百合醬蒸風爪銷量有相關性的菜品。
在這裏插入圖片描述

相關性係數方式計算

樣本協方差 Sαβ2S_{\alpha\beta}^2 = 1n1\frac{1}{n-1}in(αiμα)(βiμβ)\sum_i^n{(\alpha_i-\mu_\alpha)(\beta_i-\mu_\beta)}
樣本協方差的是表示兩個指標之間的親疏關係,比如α\alpha指標β\beta指標的值成正相關的關係,你增加我也增加,你減少我也減少。

相關性係數的計算公式 rαβr_{\alpha\beta}=SαβSαSβ\frac{S_{\alpha\beta}}{S_{\alpha}S_{\beta}}SαS_{\alpha}表示的是α\alpha向量的標準差SβS_\beta同理。

相關係數展開式子:rαβr_{\alpha\beta} = i=1n(αiμi)(βiμβ)i=1n(αiμα)2i=1n(βiμβ)2\frac{\sum_{i=1}^n(\alpha_i - \mu_i)(\beta_i-\mu_\beta)} {\sqrt{\sum_{i=1}^n(\alpha_i - \mu_\alpha)^2 \sum_{i=1}^n(\beta_i - \mu_\beta)^2}}

相關性係數方式的代碼實現

rαβr_{\alpha\beta} = i=1n(αiμi)(βiμβ)i=1n(αiμα)2i=1n(βiμβ)2\frac{\sum_{i=1}^n(\alpha_i - \mu_i)(\beta_i-\mu_\beta)} {\sqrt{\sum_{i=1}^n(\alpha_i - \mu_\alpha)^2 \sum_{i=1}^n(\beta_i - \mu_\beta)^2}}

private double[] alpha;
private double[] beta;

public double correlate() {
    if ((alpha == null || alpha.length == 0) 
    	|| (beta == null || beta.length == 0)) {
        throw new Exception("alpha或者beta沒有初始化");
    }

    int length = alpha.length;
    if (length != beta.length) {
        throw new Exception("向量維度必須相等");
    }
	//向量平均數,平均數求法很簡單,就不貼了
    double alphaMean = mean(alpha);
    double betaMean = mean(beta);

    double numerator = 0;
    double alphaDenominatorSum = 0;
    double betaDenominatorSum = 0;
    
    for (int i = 0; i < length; i++) {
        double numericX = Math.pow((alpha[i] - alphaMean), 2d);
        double numericY = Math.pow((beta[i] - betaMean), 2d);

        alphaDenominatorSum += numericX;
        betaDenominatorSum += numericY;

        double alphaDeviation = alpha[i] - alphaMean;
        double betaDeviation = beta[i] - betaMean;

        numerator += alphaDeviation * betaDeviation;
    }

    return numerator / Math.sqrt(alphaDenominatorSum * betaDenominatorSum);
}
相似度

兩個向量之間的相似就是這兩個向量之間的夾角

cosθ\cos \theta = αβαβ\frac{\alpha \cdot \beta} {|\alpha||\beta|} 計算方式 α\alpha=(x1,x2,x3,x4)(x_1, x_2, x_3, x_4)β\beta=(y1,y2,y3,y4)(y_1, y_2, y_3, y_4)αβ\alpha\cdot\beta = x1y1+x2y2+x3y3+x4y4x_1*y_1+x_2*y_2+x_3*y_3+x_4*y_4

α|\alpha| = x12+x22+x33+x42\sqrt{x_1^2 + x_2^2 + x_3^3 + x_4^2};同理β|\beta|也是這種計算方式

cosθ\cos \theta得出結果值就是兩個向量的相似度,而且他們的相關性不會超過 [-1, 1] 這個區間(cosθ\cos \theta的值域爲[-1, 1]);-1意味着兩個向量指向的方向正好截然相反,1表示它們的指向是完全相同的,0通常表示它們之間是獨立的。

文本A:陳瑞是一個歌手,也是一個男人
分詞結果:陳瑞 1,是 2,一個 2,歌手 1,也是 1,男人 1,女人 0
詞頻向量α\alpha: [1, 2, 2, 1, 1, 1, 0]

文本B:陳瑞是一個男人,也是一個女人
分詞結果:陳瑞 1,是 2,一個 2,歌手 0,也是 1,男人 1,女人 1
詞頻向量β\beta: [1, 2, 2, 0, 1, 1, 1]

通過計算詞頻向量α\alphaβ\beta得出兩文本內容的相似度

中文分詞的文章請參考 https://blog.csdn.net/Hello_Ray/article/details/104139024

TF-IDF 相似度優化
TF-IDF算法介紹

依據上面的內容,我們已經可以求出兩篇文章的相似度了,但是有一些缺點的。比如根據中文分詞選擇詞頻較大的, 然而得出是的 這些詞都是一些語氣詞或者明顯不能表示出意思的詞;會對兩篇文章的相似度行程干擾。

所以需要做的是,使用一個規則性的方法能夠避免這些詞選入詞頻向量中,這個規則性的方法就是TF-IDF算法。TF-IDF算法意義是:某個詞其他文章比較少見,然而它在這篇文章中詞頻很高,那麼它很可能就反映了這篇文章的特性,正是我們所需要的關鍵詞。

TF-IDF算法:詞頻率逆文檔頻率 相乘得來。

詞頻率(TF)=\frac{某個詞出現該文章中次數}{該文章總詞數}

逆文檔頻率(IDF)=log(+1)\log(\frac{文檔數量}{包含該詞的文檔數量+1})分母加1 是要避免沒有文檔有這個詞,不然分母就爲0了。



TF-IDF與餘弦夾角結合計算文章的相似度

第一步:選擇文章
在真正的環境下可能是多篇文章,那麼我們選擇多篇文章,然後提取摘要(一般文章都有摘要,如果沒有就選擇前幾段和後幾段)形成語料文章。

第二步:分詞
對這些文章進行分詞,去重;形成一個詞向量。比如
文章A:我/喜歡/看/小說
文章B:我/不/喜歡/看/電視,也/不/喜歡/看/電影
那麼變成詞向量是 [ 我,喜歡,看,小說,電視,電影,不,也 ] 。例子是兩篇文章,詞向量比較短,如果是多篇文章詞向量會變得特別長。

統計每個文章的詞頻向量:
文章A:我 1,喜歡 1,看 1,小說 1,電視 0,電影 0,不 0,也 0。
文章B:我 1,喜歡 2,看 2,小說 0,電視 1,電影 1,不 2,也 1。

第三步:計算每個文檔中各個詞的詞頻率TF

第四步:計算各個詞的逆文檔頻率IDF
我 log(2/2)=0,喜歡 log(2/2)=0,看 log(2/2)=0,小說 log(2/1)=1,電視 log(2/1)=1,電影 log(2/1)=1,不log(2/1)=1,也 log(2/1)=1。

第五步:計算每個文檔中各個詞的TF-IDF值
文章A:我 0,喜歡 0,看 0,小說 1,電視 0,電影 0,不 0,也 0。
文章B:我 0,喜歡 0,看 0,小說 0,電視 1,電影 1,不 1,也 1。

第六步:每篇文章根據詞向量的TF-IDF選擇靠前的N個詞
文章A:我 0,喜歡 0,小說 1
文章B:電視 1,電影 1,不 1

第七步: 根據每篇文章選擇的 N個詞構造詞頻向量;如 [ 我,喜歡,小說,電視,電影,不 ]
文檔新的詞頻向量
文章A:[1 1 1 0 0 0]
文章B: [1 2 0 1 1 2]
注意:這時構造出來的詞頻向量中的詞頻或者詞頻率,是原來所在文章的詞頻或者詞頻率。TF-IDF所做工作是選擇一些精簡有用的詞參與餘弦夾角計算。

第八步:計算餘弦值,形成一個兩兩相似度的餘弦矩陣(有點類似於協方差矩陣)

第九步: 取出某一篇文章時,提取大小前幾位的相似度文章就形成了 推薦 文章

餘弦夾角的代碼實現

public double cdot() {
    if ((alpha == null || alpha.length == 0) 
    	|| (beta == null || beta.length == 0)) {
        throw new Exception("alpha或者beta沒有初始化");
    }

    int length = alpha.length;
    if (length != beta.length) {
        throw new Exception("向量維度必須相等");
    }

    double sum = 0;
    for (int i = 0; i < length; i++) {
        double alphaIndex = alpha[i];
        double betaIndex = beta[i];

        double mult = alphaIndex * betaIndex;

        sum += mult;
    }
    return sum;
}

public double vectorDistence(double[] arr) {
    if (arr == null || arr.length == 0) {
        throw new Exception("alpha或者beta沒有初始化");
    }

    double sum = 0;
    for (int i = 0, len = arr.length; i < len; i++) {
        double mult = arr[i] * arr[i];
        throws sum += mult;
    }

    return Math.sqrt(sum);
}
圖中部分測試數據

百合醬蒸鳳爪:17,11,10,9,4,13,9,9,6,9,6,5,9,10,13,4,6,9,3,8,11,11,4,7,8,4,6,8,8
翡翠蒸香茜餃:6,15,8,6,10,10,7,12,8,11,7,9,7,8,12,8,12,15,10,7,6,6,7,5,8,10,7,5,6
金銀蒜汁蒸排骨:8,14,12,6,13,13,13,13,8,13,8,4,11,10,12,12,10,4,13,9,11,5,10,6,12,12,7,11,7
樂膳真味雞:24,13,13,3,8,16,8,6,3,6,9,7,9,6,10,11,9,12,13,20,8,15,7,7,14,9,11,10,9
蜜汁焗餐包:13,9,8,10,12,8,5,7,8,4,8,11,14,9,9,11,7,13,5,7,7,6,12,8,7,7,8,6
生炒菜心:13,10,3,9,10,9,7,8,4,7,7,9,8,13,11,7,4,9,8,12,8,14,10,15,11,8,7,11,4

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章