相关性与相似度

该文章为笔记

在前文中记录了方差表示的是一组数据相对于平均数 μ \mu μ的离散程度的博客,一个班的学生成绩方差很大,说明这个班的学生成绩波动很厉害,有的特别好,有的特别差。这里描述的是某一个变量所体现背后的含义(维度或者称为指标)。

相似度与相关性不是一种产物,不能被他们的名字搞混淆;比如两个文本的相似度,在考察两个文本的相似度时,需要分别文本进行分词计算每个词语的词频,形成词频向量。再计算两个词频向量的余弦夹角,根据夹角的值域得出两个文本的相似度。

词频向量中有多个词,每一个词就是向量中的一个维度;而下图中的菜品销售量,某个菜品的销售量是一个维度下含有多个值,不是多个维度。某两个菜品的相关性,是指两个维度的进行比较;而相似度是若干个维度进行比较。

在一个菜馆中,会有一个菜品的销量,关于这个销量。我们想要得出,某个客人点了百合酱蒸风爪,要给他做一个推荐。推荐的规则是与百合酱蒸风爪销量有相关性的菜品。
在这里插入图片描述

相关性系数方式计算

样本协方差 S α β 2 S_{\alpha\beta}^2 Sαβ2 = 1 n − 1 \frac{1}{n-1} n11 ∑ i n ( α i − μ α ) ( β i − μ β ) \sum_i^n{(\alpha_i-\mu_\alpha)(\beta_i-\mu_\beta)} in(αiμα)(βiμβ)
样本协方差的是表示两个指标之间的亲疏关系,比如 α \alpha α指标 β \beta β指标的值成正相关的关系,你增加我也增加,你减少我也减少。

相关性系数的计算公式 r α β r_{\alpha\beta} rαβ= S α β S α S β \frac{S_{\alpha\beta}}{S_{\alpha}S_{\beta}} SαSβSαβ S α S_{\alpha} Sα表示的是 α \alpha α向量的标准差 S β S_\beta Sβ同理。

相关系数展开式子: r α β r_{\alpha\beta} rαβ = ∑ i = 1 n ( α i − μ i ) ( β i − μ β ) ∑ i = 1 n ( α i − μ α ) 2 ∑ i = 1 n ( β 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}} i=1n(αiμα)2i=1n(βiμβ)2 i=1n(αiμi)(βiμβ)

相关性系数方式的代码实现

r α β r_{\alpha\beta} rαβ = ∑ i = 1 n ( α i − μ i ) ( β i − μ β ) ∑ i = 1 n ( α i − μ α ) 2 ∑ i = 1 n ( β 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}} i=1n(αiμα)2i=1n(βiμβ)2 i=1n(αiμi)(βiμβ)

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 cosθ = α ⋅ β ∣ α ∣ ∣ β ∣ \frac{\alpha \cdot \beta} {|\alpha||\beta|} αβαβ 计算方式 α \alpha α= ( x 1 , x 2 , x 3 , x 4 ) (x_1, x_2, x_3, x_4) (x1,x2,x3,x4) β \beta β= ( y 1 , y 2 , y 3 , y 4 ) (y_1, y_2, y_3, y_4) (y1,y2,y3,y4) α ⋅ β \alpha\cdot\beta αβ = x 1 ∗ y 1 + x 2 ∗ y 2 + x 3 ∗ y 3 + x 4 ∗ y 4 x_1*y_1+x_2*y_2+x_3*y_3+x_4*y_4 x1y1+x2y2+x3y3+x4y4

∣ α ∣ |\alpha| α = x 1 2 + x 2 2 + x 3 3 + x 4 2 \sqrt{x_1^2 + x_2^2 + x_3^3 + x_4^2} x12+x22+x33+x42 ;同理 ∣ β ∣ |\beta| β也是这种计算方式

cos ⁡ θ \cos \theta cosθ得出结果值就是两个向量的相似度,而且他们的相关性不会超过 [-1, 1] 这个区间( cos ⁡ θ \cos \theta cosθ的值域为[-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(term frequency–inverse document frequency)是一种用于资讯检索与资讯探勘的常用加权技术, TFIDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。

依据上面的内容,我们已经可以求出两篇文章的相似度了,但是有一些缺点的。比如根据中文分词选择词频较大的, 然而得出是的 这些词都是一些语气词或者明显不能表示出意思的词;会对两篇文章的相似度行程干扰。

所以需要做的是,使用一个规则性的方法能够避免这些词选入词频向量中,这个规则性的方法就是TF-IDF算法。TF-IDF算法意义是:某个词其他文章比较少见,然而它在这篇文章中词频很高,那么它很可能就反映了这篇文章的特性,正是我们所需要的关键词。

TF-IDF算法:词频率逆文档频率 相乘得来。

词频率(TF)= 某 个 词 出 现 该 文 章 中 次 数 该 文 章 总 词 数 \frac{某个词出现该文章中次数}{该文章总词数}

逆文档频率(IDF)= log ⁡ ( 文 档 数 量 包 含 该 词 的 文 档 数 量 + 1 ) \log(\frac{文档数量}{包含该词的文档数量+1}) log(+1)分母加1 是要避免没有文档有这个词,不然分母就为0了。

TF-IDF = TF * IDF

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

猜你喜欢

转载自blog.csdn.net/Hello_Ray/article/details/104535532
今日推荐