分布的相似度(距离)用啥模型比较好?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布的相似度(距离)用啥模型比较好?相关的知识,希望对你有一定的参考价值。

首先,向量也可以认为有多个维度,每一个向量的元素对应一维。其次,参考其他答案,你可以根据需求选择多种相似度,推荐先用KL散度再比较使用Wasserstein距离。最后,介绍下我现在做的研究,metric learning(距离度量学习)。首先要明确的是,metric learning是半监督学习,所以在没有已有的supervised information数据库的支持下,请不用继续看了。metric learning的核心是指,运用机器学习的手段,根据已有的supervised information学习一个新的自定义metric,使new metric比original distance更好更符合数据特征。其中运用的手段就是最小化损失函数。以Euclideandistance为例,d(x,y)=||x-y||2,新的metric可以表示为d(f(x),f(y))=||Gx-Gy||2,G为映射矩阵,也就是我们需要学习的对不同特征维度的偏移权重。求两个或者多个形如[1,3,4,5,0]之类的vector的similarity。可以选择的方法很多,关键看楼主的关于“好”的标准是什么。如楼主所言,其实,在很多case中,横坐标可能有重要的物理,金融或者商业意义。所以,衡量“好”的时候,必须要对其背景知识有理解才行。比如,发动机转速在3000-5000转可能是正常,过了8000可能就不正常;因此每个element的权重很可能不同。另外,某些值向某个方向变化可能正常,而向另外方向的变化可能是指示重大不同。如果缺少背景知识,很难给出所谓的“好”的方法。对于1 dimentional sequence,可以用做similarity比较的方法也很多,欧式距离,weighted欧式距离,变异罚分,相关性比较等等,在bioinformatics和search engine等很多领域都有应用。建议先了解更多的需求背景知识,定义“好”的标准,再由易到难尝试各种方法的效果。从engineering和business的角度来看,简单好用是王道,复杂花哨的数学工具在一些特定场合不一定真的好用。

参考技术A

最近在看巴氏距离,也是用来度量两个分布之间的距离。虽然我没有弄清题主的问题究竟是要说啥,但是我觉得两个分布之间的距离用巴氏距离来衡量应该是可以的。再补充一点自己的想法,巴氏距离再图像处理里面用在了直方图的匹配上,可以计算出两个直方图的相似程度。再回头想,直方图在某种程度上和概率密度函数是类似的。所以,我大胆猜想,在描述两个分布的距离(也就是相似性)的时候,是否可以借鉴直方图匹配种的方法呢?我是真的没有看懂题主的问的问题的意思。讲这么多纯属自己自己对于关于两个概率密度函数之间相似性的理解!!!

参考技术B

K-L Divergence实际上并不是一个真正的距离度量,因为它不满足距离定义中的对称性、三角不等式等性质。题主可以参考一下目前学界比较火的信息几何学(Information Geometry),这一学科将概率分布处理为流形上的点,然后利用流形上的测地线来表征不同分布之间的距离。这一测地距离叫做Fisher Information Distance,是一个真正的距离度量,相比K-L散度更为精准,但由于涉及到变分问题的求解,计算量也非常巨大。目前信息几何方兴未艾,但仅仅引入了微分几何的一些基本概念,更深一层的东西比如李群、纤维丛在其中如何体现还有待研究,个人感觉是未来发展潜力巨大的一门学科。

借助余弦相似度辅助背单词

0 背景

无他,唯背单词而已。

1 余弦相似度

提到余弦相似度,不得不先说下欧几里得距离,这两个容易搞混淆。

1.1 欧几里得距离

欧几里得距离与余弦相似度

距离度量衡量的是空间各点间的绝对距离,跟各个点所在的位置坐标(即个体特征维度的数值)直接相关;而余弦相似度衡量的是空间向量的夹角,更加的是体现在方向上的差异,而不是位置。如果保持A点的位置不变,B点朝原方向远离坐标轴原点,那么这个时候余弦相似度cosθ是保持不变的,因为夹角不变,而A、B两点的距离显然在发生改变,这就是欧氏距离和余弦相似度的不同之处。
参考自 余弦相似度与欧几里得距离1

1.2 余弦相似度计算公式

计算公式
Wikipedia 官方解读2

1.3 图例理解

二维特征的余弦相似度示意图
二维特征的余弦相似度结果

1.4 简单示意

# coding: utf8
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
import math
"""
arr1 = [[1, 2]]
arr2 = [[4, 5]]
"""

arr1 = np.arange(2).reshape(1, 2)
arr1[0] = [100 * 1 / math.sqrt(5), 100 * 2 / math.sqrt(5)]
arr2 = np.arange(2).reshape(1, 2)
arr2[0] = [100 * 4 / math.sqrt(41), 100 * 5 / math.sqrt(41)]
print(arr1)
print(arr2)

ret = cosine_similarity(arr1, arr2)
print(ret)

"""
[[44 89]]
[[62 78]]
[[0.97751451]]
"""

在 sklearn 中,有如下代码

def cosine_similarity(X, Y=None, dense_output=True):
    """Compute cosine similarity between samples in X and Y.

    Cosine similarity, or the cosine kernel, computes similarity as the
    normalized dot product of X and Y:

        K(X, Y) = <X, Y> / (||X||*||Y||)

    On L2-normalized data, this function is equivalent to linear_kernel.

    Read more in the :ref:`User Guide <cosine_similarity>`.

    Parameters
    ----------
    X : {ndarray, sparse matrix} of shape (n_samples_X, n_features)
        Input data.

    Y : {ndarray, sparse matrix} of shape (n_samples_Y, n_features), \\
            default=None
        Input data. If ``None``, the output will be the pairwise
        similarities between all samples in ``X``.

    dense_output : bool, default=True
        Whether to return dense output even when the input is sparse. If
        ``False``, the output is sparse if both input arrays are sparse.

        .. versionadded:: 0.17
           parameter ``dense_output`` for dense output.

    Returns
    -------
    kernel matrix : ndarray of shape (n_samples_X, n_samples_Y)
    """
    # to avoid recursive import

    X, Y = check_pairwise_arrays(X, Y)

    X_normalized = normalize(X, copy=True)
    if X is Y:
        Y_normalized = X_normalized
    else:
        Y_normalized = normalize(Y, copy=True)

    K = safe_sparse_dot(X_normalized, Y_normalized.T,
                        dense_output=dense_output)

    return K

2 word2vec

关于 word2vec 的定义就不过多描述了,我对于 word2vec 的认知也不是很深,但是给我的第一印象就是,它能用来背单词。

2.1 经典示意图

word2vec 经典案例

The resulting vector from “king-man+woman” doesn’t exactly equal “queen”, but “queen” is the closest word to it from the 400,000 word embeddings we have in this collection.

2.2 方案选择

不管是中文和英文,都是有一定的语义相关性的。可能我提到张三,你就能想到李四。提到狮子就能想到老虎一样。而 word2vec 恰恰是能将此特性通过词向量的形式进行具象化的一种技术手段。因此,在语义相关的众多候选单词中,通过 word2vec 的牵引,往往能起到“举一反三”的功效,不仅背单词的效率更高了,速度也会有提升。

2.3 了解更多

想了解更多关于 word2vec 的内容,可以点击下面两篇文章,个人感觉降得很好。
神级解读3
word2Vec 是如何得到词向量的4

3 vocabulary

写了这么多,都是铺垫,下面进入正题,怎么样把它应用到“背单词”这个应用上,才是本次需求的目的。

3.1 收集物料

物料的选取,从根本上决定了后期模型的准确度。
哈利波特英文文档
我这里选取的不是很好,需求的目的是背单词,但是哈利波特更多的是稍偏情景化的内容,因此不太适合用来做目标物料。

相对来讲,较为合适的就是维基百科英语 46 级雅思等内容相关的文本。这样的内容天生就是适合的。收集物料的过程很繁琐,需要针对性的写一些爬虫脚本,我这里目前还不需要做到如此精准,就先用哈利波特英文剧本代替了。

3.2 清洗数据

清洗数据是为了下一步训练模型使用,收集到的物料全部粘连在一起了。而训练模型时用的是行分隔模式,因此需要先将文本转换为行式结构

sentences = word2vec.LineSentence("haripoter.txt")

3.3 训练模型

这里借助 gensim 库进行模型的训练与构建,方便快捷。


from gensim.models import word2vec

sentences = word2vec.LineSentence("haripoter.txt")
model = word2vec.Word2Vec(
    sentences,
    sg=0,
    # size=100,
    # window=2,
    # negative=3,
    # sample=0,
    # hs=1,
    # workers=4,
    size=250,
)

model.save("haripoter.model")

3.4 模型应用

from gensim.models import word2vec

model = word2vec.Word2Vec.load("haripoter.model")
print(model.most_similar("kitchen", topn=3))

"""
[('hall', 0.9646997451782227), ('corridor,', 0.9580787420272827), ('hole', 0.9575302600860596)]
"""

将此模型应用到单词抽取阶段,来代替现有的随机抽取算法,定能起到画龙点睛的功效。
现有抽取方式

半成品背单词应用 https://github.com/guoruibiao/vocabulary
半成品模型应用

3.5 后期规划

1 爬取更多物料,构筑更精准的模型
2 针对错误单词的“组词成句”需求跟进,在我看来,这也是一个 NLP 的热点。

4 总结

本文主要从一个数学公式(余弦相似度)说起,再到 word2vec 算法,再应用到具体的工具中(物料不全,暂未使用)。整体思路还是蛮清晰的,后续其实可以投入精力去好好优化下,时间有限,就写到这里了。

参考链接:


  1. https://blog.csdn.net/robbyo/article/details/43588357 ↩︎

  2. https://en.wikipedia.org/wiki/Cosine_similarity ↩︎

  3. https://jalammar.github.io/illustrated-word2vec/ ↩︎

  4. https://www.zhihu.com/question/44832436 ↩︎

以上是关于分布的相似度(距离)用啥模型比较好?的主要内容,如果未能解决你的问题,请参考以下文章

500份的数据0-1分布用啥模型好

文本相似度计算(一):距离方法

常见相似度衡量方法

使用 TF-IDF 加权的空间向量模型实现句子相似度计算

文本、语音相似度算法

借助余弦相似度辅助背单词