在做分类时常常需要估算不同样本之间的相似性度量(Similarity Measurement),这时通常采用的方法就是计算样本间的“距离”(Distance)。采用什么样的方法计算距离是很讲究,甚至关系到分类的正确与否。 本文的目的就是对常用的相似性度量作一个总结。
1. 欧氏距离(Euclidean Distance)
欧氏距离是最易于理解的一种距离计算方法,源自欧氏空间中两点间的距离公式。
(1)二维平面上两点a(x1,y1)与b(x2,y2)间的欧氏距离:
<ignore_js_op>
(2)三维空间两点a(x1,y1,z1)与b(x2,y2,z2)间的欧氏距离:
<ignore_js_op>
(3)两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的欧氏距离:
<ignore_js_op>
也可以用表示成向量运算的形式:
<ignore_js_op>
(4)Matlab计算欧氏距离
2. 曼哈顿距离(Manhattan Distance)
从名字就可以猜出这种距离的计算方法了。想象你在曼哈顿要从一个十字路口开车到另外一个十字路口,驾驶距离是两点间的直线距离吗?显然不是,除非你能穿越大楼。实际驾驶距离就是这个“曼哈顿距离”。而这也是曼哈顿距离名称的来源, 曼哈顿距离也称为城市街区距离(City Block distance)。
(1)二维平面两点a(x1,y1)与b(x2,y2)间的曼哈顿距离
<ignore_js_op>
(2)两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的曼哈顿距离
<ignore_js_op>
(3) Matlab计算曼哈顿距离
3. 切比雪夫距离 ( Chebyshev Distance )
国际象棋玩过么?国王走一步能够移动到相邻的8个方格中的任意一个。那么国王从格子(x1,y1)走到格子(x2,y2)最少需要多少步?自己走走试试。你会发现最少步数总是max( | x2-x1 | , | y2-y1 | ) 步。有一种类似的一种距离度量方法叫切比雪夫距离。
(1)二维平面两点a(x1,y1)与b(x2,y2)间的切比雪夫距离
(2)两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的切比雪夫距离
<ignore_js_op>
这个公式的另一种等价形式是
<ignore_js_op>
看不出两个公式是等价的?提示一下:试试用放缩法和夹逼法则来证明。
(3)Matlab计算切比雪夫距离
4. 闵可夫斯基距离(Minkowski Distance)
闵氏距离不是一种距离,而是一组距离的定义。
(1) 闵氏距离的定义
两个n维变量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的闵可夫斯基距离定义为:
<ignore_js_op>
根据变参数的不同,闵氏距离可以表示一类的距离。
(2)闵氏距离的缺点
闵氏距离,包括曼哈顿距离、欧氏距离和切比雪夫距离都存在明显的缺点。
举个例子:二维样本(身高,体重),其中身高范围是150~190,体重范围是50~60,有三个样本:a(180,50),b(190,50),c(180,60)。那么a与b之间的闵氏距离(无论是曼哈顿距离、欧氏距离或切比雪夫距离)等于a与c之间的闵氏距离,但是身高的10cm真的等价于体重的10kg么?因此用闵氏距离来衡量这些样本间的相似度很有问题。
简单说来,闵氏距离的缺点主要有两个:(1)将各个分量的量纲(scale),也就是“单位”当作相同的看待了。(2)没有考虑各个分量的分布(期望,方差等)可能是不同的。
(3)Matlab计算闵氏距离
5. 标准化欧氏距离 (Standardized Euclidean distance )
(1)标准欧氏距离的定义
标准化欧氏距离是针对简单欧氏距离的缺点而作的一种改进方案。标准欧氏距离的思路:既然数据各维分量的分布不一样,好吧!那我先将各个分量都“标准化”到均值、方差相等吧。均值和方差标准化到多少呢?这里先复习点统计学知识吧,假设样本集X的均值(mean)为m,标准差(standard deviation)为s,那么X的“标准化变量”表示为:
而且标准化变量的数学期望为0,方差为1。因此样本集的标准化过程(standardization)用公式描述就是:
<ignore_js_op>
标准化后的值 = ( 标准化前的值 - 分量的均值 ) /分量的标准差
经过简单的推导就可以得到两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的标准化欧氏距离的公式:
<ignore_js_op>
如果将方差的倒数看成是一个权重,这个公式可以看成是一种加权欧氏距离(Weighted Euclidean distance)。
(2)Matlab计算标准化欧氏距离
6. 马氏距离(Mahalanobis Distance)
(1)马氏距离定义
有M个样本向量X1~Xm,协方差矩阵记为S,均值记为向量μ,则其中样本向量X到u的马氏距离表示为:
<ignore_js_op>
而其中向量Xi与Xj之间的马氏距离定义为:
<ignore_js_op>
若协方差矩阵是单位矩阵(各个样本向量之间独立同分布),则公式就成了:
<ignore_js_op>
也就是欧氏距离了。
若协方差矩阵是对角矩阵,公式变成了标准化欧氏距离。
(2)马氏距离的优缺点:量纲无关,排除变量之间的相关性的干扰。
(3) Matlab计算(1 2),( 1 3),( 2 2),( 3 1)两两之间的马氏距离
7. 夹角余弦(Cosine)
有没有搞错,又不是学几何,怎么扯到夹角余弦了?各位看官稍安勿躁。几何中夹角余弦可用来衡量两个向量方向的差异,机器学习中借用这一概念来衡量样本向量之间的差异。
(1)在二维空间中向量A(x1,y1)与向量B(x2,y2)的夹角余弦公式:
<ignore_js_op>
(2) 两个n维样本点a(x11,x12,…,x1n)和b(x21,x22,…,x2n)的夹角余弦
类似的,对于两个n维样本点a(x11,x12,…,x1n)和b(x21,x22,…,x2n),可以使用类似于夹角余弦的概念来衡量它们间的相似程度。
<ignore_js_op>
即:
<ignore_js_op>
夹角余弦取值范围为[-1,1]。夹角余弦越大表示两个向量的夹角越小,夹角余弦越小表示两向量的夹角越大。当两个向量的方向重合时夹角余弦取最大值1,当两个向量的方向完全相反夹角余弦取最小值-1。
夹角余弦的具体应用可以参阅参考文献[1]。
(3)Matlab计算夹角余弦
8. 汉明距离(Hamming distance)
(1)汉明距离的定义
两个等长字符串s1与s2之间的汉明距离定义为将其中一个变为另外一个所需要作的最小替换次数。例如字符串“1111”与“1001”之间的汉明距离为2。
应用:信息编码(为了增强容错性,应使得编码间的最小汉明距离尽可能大)。
(2)Matlab计算汉明距离
Matlab中2个向量之间的汉明距离的定义为2个向量不同的分量所占的百分比。
例子:计算向量(0,0)、(1,0)、(0,2)两两间的汉明距离
9. 杰卡德相似系数(Jaccard similarity coefficient)
(1) 杰卡德相似系数
两个集合A和B的交集元素在A,B的并集中所占的比例,称为两个集合的杰卡德相似系数,用符号J(A,B)表示。
<ignore_js_op>
杰卡德相似系数是衡量两个集合的相似度一种指标。
(2) 杰卡德距离
与杰卡德相似系数相反的概念是杰卡德距离(Jaccard distance)。杰卡德距离可用如下公式表示:
<ignore_js_op>
杰卡德距离用两个集合中不同元素占所有元素的比例来衡量两个集合的区分度。
(3) 杰卡德相似系数与杰卡德距离的应用
可将杰卡德相似系数用在衡量样本的相似度上。
样本A与样本B是两个n维向量,而且所有维度的取值都是0或1。例如:A(0111)和B(1011)。我们将样本看成是一个集合,1表示集合包含该元素,0表示集合不包含该元素。
<ignore_js_op>
(4)Matlab 计算杰卡德距离
10. 相关系数 ( Correlation coefficient )与相关距离(Correlation distance)
(1) 相关系数的定义
<ignore_js_op>
相关系数是衡量随机变量X与Y相关程度的一种方法,相关系数的取值范围是[-1,1]。相关系数的绝对值越大,则表明X与Y相关度越高。当X与Y线性相关时,相关系数取值为1(正线性相关)或-1(负线性相关)。
(2)相关距离的定义
<ignore_js_op>
其中0.4781就是相关系数,0.5219是相关距离。
11. 信息熵(Information Entropy)
信息熵并不属于一种相似性度量。那为什么放在这篇文章中啊?这个。。。我也不知道。 (╯▽╰)
信息熵是衡量分布的混乱程度或分散程度的一种度量。分布越分散(或者说分布越平均),信息熵就越大。分布越有序(或者说分布越集中),信息熵就越小。
计算给定的样本集X的信息熵的公式:
<ignore_js_op>
参数的含义:
n:样本集X的分类数
pi:X中第i类元素出现的概率
信息熵越大表明样本集S分类越分散,信息熵越小则表明样本集X分类越集中。。当S中n个分类出现的概率一样大时(都是1/n),信息熵取最大值log2(n)。当X只有一个分类时,信息熵取最小值0
参考资料:
[1]吴军. 数学之美 系列 12 - 余弦定理和新闻的分类.
http://www.google.com.hk/ggblog/googlechinablog/2006/07/12_4010.html
[2] Wikipedia. Jaccard index.
http://en.wikipedia.org/wiki/Jaccard_index
[3] Wikipedia. Hamming distance
http://en.wikipedia.org/wiki/Hamming_distance
[4] 求马氏距离(Mahalanobis distance )matlab版
http://junjun0595.blog.163.com/blog/static/969561420100633351210/
[5] Pearson product-moment correlation coefficient
http://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient
---------------------------------------
http://stblog.baidu-tech.com/?p=1846
相似度计算常用方法综述
引言 相似度计算用于衡量对象之间的相似程度,在数据挖掘、自然语言处理中是一个基础性计算。其中的关键技术主要是两个部分,对象的特征表示,特征集合之间的相似关系。在信息检索、网页判重、推荐系统等,都涉及到对象之间或者对象和对象集合的相似性的计算。而针对不同的应用场景,受限于数据规模、时空开销等的限制,相似度计算方法的选择又会有所区别和不同。下面章节会针对不同特点的应用,进行一些常用的相似度计算方法进行介绍。
2向量空间模型向量空间模型(Vector space model)是应用最广泛的一个基础相似度计算模型,在该模型中,每个对象映射为一个特征向量:
<ignore_js_op>
<ignore_js_op>
作为一个应用广泛的模型,向量空间模型在现有的很多应用中仍然起着至关重要的作用,也是很多扩展方法的基础。
3 基于hash方法的相似计算 基于hash的相似度计算方法,是一种基于概率的高维度数据的维度削减的方法,主要用于大规模数据的压缩与实时或者快速的计算场景下,基于hash方法的相似度计算经常用于高维度大数据量的情况下,将利用原始信息不可存储与计算的问题转化为映射空间的可存储计算问题,在海量文本重复性判断方面,近似文本查询方面有比较多的应用,google的网页去重[1],google news的协同过滤[2,3]等都是采用hash方法进行近似相似度的计算,比较常见的应用场景Near-duplicate detection、Image similarity identification、nearest neighbor search,常用的一些方法包括I-match,Shingling、Locality-Sensitive Hashing族等方法,下面针对几种常见的hash方法进行介绍。
3.1 minhash方法介绍 Minhash方法是Locality-sensitive hashing[4,5]算法族里的一个常用方法,基本的思想是,对于每一个对象的itemlist,将输入的item进行hash,这样相似的item具有很高的相似度被映射到相同的buckets里面,这样尽量保证了hash之后两个对象之间的相似程度和原来是高相似的,而buckets的数量是远远小于输入的item的,因此又达到降低复杂度的目的。
minhash方法用Jaccard进行相似度的计算方法,则对于两个集合和 <ignore_js_op> , 和 <ignore_js_op> 的相似性的计算方法为:
当两个集合越相似,则该值越接近1,否则越接近0。用minhash方法,将一个集合映射到[0-R-1]之间的值,以相同的概率随机的抽取一个[0-R-1[的一个排列,依次排列查找第一次出现1的行。
<ignore_js_op>
设随机排列为43201(edcab),对于C1列,第一次出现1的行是R4,所以h(C1) = 3,同理有h(C2)=2, h(C3)=4, h(C4)=3。
通过多次抽取随机排列得到n个minhash函数h1,h2,…,hn,依此对每一列都计算n个minhash值。对于两个集合,看看n个值里面对应相等的比例,即可估计出两集合的Jaccard相似度。可以把每个集合的n个minhash值列为一列,得到一个n行C列的签名矩阵。因为n可远小于R,这样在压缩了数据规模的同时,并且仍能近似计算出相似度。
3.2 simhash方法介绍simhash方法是在大文本重复识别常用的一个方法,该方法主要是通过将对象的原始特征集合映射为一个固定长度的签名,将对象之间的相似度的度量转化为签名的汉明距离,通过这样的方式,极大限度地进行了降低了计算和存储的消耗。
3.2.1 签名计算过程 该方法通过对输入特征集合的计算步骤可以描述如下:
- 将一个f维的向量V初始化为0;f位的二进制数S初始化为0;
- 对每一个特征:用传统的hash算法对该特征产生一个f位的签名b。对i=1到f:
如果b的第i位为1,则V的第i个元素加上该特征的权重;
否则,V的第i个元素减去该特征的权重。
- 如果V的第i个元素大于0,则S的第i位为1,否则为0;
- 输出S作为签名。
通过上述步骤将输入的表示对象的特征集合转化为该对象的一个签名,在完成签名之后,度量两个对象的相似度的差异即变成了对量二者的指纹的K位的差异情况。
3.2.2 汉明距离查找优化对于如何快速查找出某一个签名是否与其存在最大差异不超过K个bit的指纹,Detecting Near-Duplicates for Web Crawling这篇论文中进行了介绍。该查找方法的基本思想是利用空间换时间的方法,该方法的依据是需要查找的两个指纹的差异很小,这样可以通过将原始指纹进行分块索引,如果两个指纹的差异很小,则合理的分块后,根据鸽笼原理,其中存在一定数量的块是一致的,通过利用相同的块进行相似的指纹的召回,只需要比对召回的块中有差异的块的bit差异,这样减少了需要比对的数量,节省了比对的时间开销。
3.3 小结 hash方法的相似度计算的主要应用场景,一般是针对大规模数据进行压缩,在保证效果损失可接受的情况下,节省存储空间,加快运算速度,针对该方法的应用,在目前的大规模的互联网处理中,很多相似度的计算都是基于这种近似性的计算,并取得了比较好的效果。
通过多次抽取随机排列得到n个minhash函数h1,h2,…,hn,依此对每一列都计算n个minhash值。对于两个集合,看看n个值里面对应相等的比例,即可估计出两集合的Jaccard相似度。可以把每个集合的n个minhash值列为一列,得到一个n行C列的签名矩阵。因为n可远小于R,这样在压缩了数据规模的同时,并且仍能近似计算出相似度。
4 基于主题的相似度计算 传统的BOW(bag-of_words)模型,一般都会建立在特征独立假设的基础上,按照特征向量的匹配情况来度量对象之间的相似度,但是在实际的应用中,很多时候特征之间存在着很多的关联关系,二者在传统的BOW模型中无法解决,在这个基础上,引入了主题的概念,通过主题的思想,建立起基本特征与对象的中间层的关联关系,主题的概念的引入,主要是在原有的基本特征粒度的基础上,引入了更为丰富的隐含层特征,提高了相似性计算的效果,常用的主题分析方法包括Latent Semantic Analysis (LSA) 、 Probabilitistic Latent Semantic Analysis (PLSA)、Latent Dirichlet Allocation ( LDA)。这些方法在分类,聚类、检索、推荐等领域都有着很多的应用,并取得了比较好的效果。下面就LSA及PLSA方法进行简要介绍。
4.1 LSA简介 LSA[6,7]模型认为特征之间存在某种潜在的关联结构,通过特征-对象矩阵进行统计计算,将高维空间映射到低纬的潜在语义结构上,构建出LSA空间模型,从而提取出潜在的语义结构,并用该结构表示特征和对象,消除了词汇之间的相关性影响,并降低了数据维度。增强了特征的鲁棒性
LSA利用奇异值分解来进行计算,数学过程可以表述如下:
对于 的矩阵A,其中m为特征数,n为样本数。令 <ignore_js_op> ,经过奇异值分解,矩阵A可分解成3个矩阵的乘积:
其中,U、V是 <ignore_js_op> 和 <ignore_js_op> 的正交矩阵,分别称为矩阵A的奇异值对应的左、右奇异向量, <ignore_js_op> 是 <ignore_js_op> 的对角矩阵,称为A的奇异标准形,其对角元素为矩阵A的奇异值。奇异值按照递减的排列构成对角矩阵 <ignore_js_op> ,取 <ignore_js_op> 中前k个最大奇异值构成 的,取U和V最前面的k列构成 <ignore_js_op> 的Uk和 <ignore_js_op> 的Vk,构建A的k-秩矩阵 <ignore_js_op>
<ignore_js_op> (6)
其中,Uk和Vk 中的行向量分别作为特征向量和对象向量,k是降维后的维数。
4.2 plas介绍 PLSA[8,9]模型是由Hofmann提出的用于文本检索的概率生成模型,与相比较于LSA,PLSA是基于概率模型的,并直接引入了潜在class变量 ,下面的用文本处理语言来描述该模型。
选定一篇文档的概率p(d),每篇文档以概率 属于一个主题,而给定一个主题,每一个词以概率 产生。将这个过程形成联合的概率模型表达式:
(7)
(8)
则:
(9)
在PLSA实际的使用过程中,存在着overfit的风险,一般训练过程是通过EM算法,进行模型参数训练,获得p(z|d)、p(w|z)概率。
PLSA和其相关的变形,在分类、聚类、检索等方面,特征相关性计算等方面,获得了广泛的应用,并取得了比较好的效果。
4.2 plas介绍 PLSA[8,9]模型是由Hofmann提出的用于文本检索的概率生成模型,与相比较于LSA,PLSA是基于概率模型的,并直接引入了潜在class变量 z∈Z={Z1…Zk },下面的用文本处理语言来描述该模型。
<ignore_js_op>
选定一篇文档的概率p(d),每篇文档以概率p(z|d)属于一个主题,而给定一个主题,每一个词以概率p(w|z) 产生。将这个过程形成联合的概率模型表达式:
<ignore_js_op>
在PLSA实际的使用过程中,存在着overfit的风险,一般训练过程是通过EM算法,进行模型参数训练,获得p(z|d)、p(w|z)概率。
PLSA和其相关的变形,在分类、聚类、检索等方面,特征相关性计算等方面,获得了广泛的应用,并取得了比较好的效果。
.3 小结 主题方法的引入,在一定程度上弥补了BOW的假设的独立性,在工业中,主题的方法也越来越多的应用到实际的机器学习中,包括在图像处理领域、传统的分类、聚类、检索等方面,都取得了比较好的效果。
总结 相似度的计算在数据挖掘方面有着广泛的应用,根据不同的应用场景,各种方法各有其优劣特点,对于相似度效果的影响,除了方法本身之外,合理有效的特征的选择和使用也是至关重要的,同时,根据应用场景的不同,选择合理的方法,对于解决问题,有着重要的作用。
参考文献:
1. G.S. Manku, A. Jain, A.D. Sarma. Detecting Near-Duplicates for Web Crawling. WWW2007, 2007
2. A. Das, M. Datar, A.Garg. Google News Personalization: Scalable Online Collaborative Filtering. WWW2007, 2007
3. http://en.wikipedia.org/wiki/MinHash
4. M. S. Charikar. Similarity estimation techniques from rounding algorithms. STOC’02. 2002
5. http://en.wikipedia.org/wiki/Locality-sensitive_hashing
6. K. Dave, S. Lawrence, and D. Pennock. Mining the peanut gallery: opinion extraction and semantic classification of product reviews. In Proceedings of the 22th International World Wide Web Conference, Budapest, Hungary, 2003
7. http://en.wikipedia.org/wiki/Latent_semantic_analysis
8. T. Hofmann. Probabilistic Latent Semantic Analysis. In Proceedings of the 15th Conference on Uncertainty in AI(1999).
9. Y. M kim, J. F. Pressiot M. R.Amini etc. An Extension of PLSA for Document Clustering. CIKM’08
---------------------------------------
字符串相似度算法(编辑距离算法 Levenshtein Distance)
在搞验证码识别的时候需要比较字符代码的相似度用到“编辑距离算法”,关于原理和C#实现做个记录。
据百度百科介绍:
编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数,如果它们的距离越大,说明它们越是不同。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
例如将kitten一字转成sitting:
sitten (k→s)
sittin (e→i)
sitting (→g)
俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。因此也叫Levenshtein Distance。
例如
- 如果str1="ivan",str2="ivan",那么经过计算后等于 0。没有经过转换。相似度=1-0/Math.Max(str1.length,str2.length)=1
- 如果str1="ivan1",str2="ivan2",那么经过计算后等于1。str1的"1"转换"2",转换了一个字符,所以距离是1,相似度=1-1/Math.Max(str1.length,str2.length)=0.8
应用 DNA分析
拼字检查
语音辨识
抄袭侦测
感谢大石头在评论中给出一个很好的关于此方法应用的连接 补充在此:
小规模的字符串近似搜索,需求类似于搜索引擎中输入关键字,出现类似的结果列表,文章连接:【算法】字符串近似搜索
算法过程
- str1或str2的长度为0返回另一个字符串的长度。 if(str1.length==0) return str2.length; if(str2.length==0) return str1.length;
- 初始化(n+1)*(m+1)的矩阵d,并让第一行和列的值从0开始增长。
- 扫描两字符串(n*m级的),如果:str1 == str2[j],用temp记录它,为0。否则temp记为1。然后在矩阵d[i,j]赋于d[i-1,j]+1 、d[i,j-1]+1、d[i-1,j-1]+temp三者的最小值。
- 扫描完后,返回矩阵的最后一个值d[n][m]即是它们的距离。
计算相似度公式:1-它们的距离/两个字符串长度的最大值。
为了直观表现,我将两个字符串分别写到行和列中,实际计算中不需要。我们用字符串“ivan1”和“ivan2”举例来看看矩阵中值的状况:
1、第一行和第一列的值从0开始增长
i | v | a | n | 1 | ||
0 | 1 | 2 | 3 | 4 | 5 | |
i | 1 | |||||
v | 2 | |||||
a | 3 | |||||
n | 4 | |||||
2 | 5 |
2、i列值的产生 Matrix[i - 1, j] + 1 ; Matrix[i, j - 1] + 1 ; Matrix[i - 1, j - 1] + t
i | v | a | n | 1 | ||
0+t=0 | 1+1=2 | 2 | 3 | 4 | 5 | |
i | 1+1=2 | 取三者最小值=0 | ||||
v | 2 | 依次类推:1 | ||||
a | 3 | 2 | ||||
n | 4 | 3 | ||||
2 | 5 | 4 |
3、V列值的产生
i | v | a | n | 1 | ||
0 | 1 | 2 | ||||
i | 1 | 0 | 1 | |||
v | 2 | 1 | 0 | |||
a | 3 | 2 | 1 | |||
n | 4 | 3 | 2 | |||
2 | 5 | 4 | 3 |
依次类推直到矩阵全部生成
i | v | a | n | 1 | ||
0 | 1 | 2 | 3 | 4 | 5 | |
i | 1 | 0 | 1 | 2 | 3 | 4 |
v | 2 | 1 | 0 | 1 | 2 | 3 |
a | 3 | 2 | 1 | 0 | 1 | 2 |
n | 4 | 3 | 2 | 1 | 0 | 1 |
2 | 5 | 4 | 3 | 2 | 1 | 1 |
最后得到它们的距离=1
相似度:1-1/Math.Max(“ivan1”.length,“ivan2”.length) =0.8
算法用C#实现
showpublic class LevenshteinDistance { /// <summary> /// 取最小的一位数 /// </summary> /// <param name="first"></param> /// <param name="second"></param> /// <param name="third"></param> /// <returns></returns> private int LowerOfThree(int first, int second, int third) { int min = Math.Min(first, second); return Math.Min(min, third); } private int Levenshtein_Distance(string str1, string str2) { int[,] Matrix; int n = str1.Length; int m = str2.Length; int temp = 0; char ch1; char ch2; int i = 0; int j = 0; if (n == 0) { return m; } if (m == 0) { return n; } Matrix = new int[n + 1, m + 1]; for (i = 0; i <= n; i++) { //初始化第一列 Matrix[i, 0] = i; } for (j = 0; j <= m; j++) { //初始化第一行 Matrix[0, j] = j; } for (i = 1; i <= n; i++) { ch1 = str1[i - 1]; for (j = 1; j <= m; j++) { ch2 = str2[j - 1]; if (ch1.Equals(ch2)) { temp = 0; } else { temp = 1; } Matrix[i, j] = LowerOfThree(Matrix[i - 1, j] + 1, Matrix[i, j - 1] + 1, Matrix[i - 1, j - 1] + temp); } } for (i = 0; i <= n; i++) { for (j = 0; j <= m; j++) { Console.Write(" {0} ", Matrix[i, j]); } Console.WriteLine(""); } return Matrix[n, m]; } /// <summary> /// 计算字符串相似度 /// </summary> /// <param name="str1"></param> /// <param name="str2"></param> /// <returns></returns> public decimal LevenshteinDistancePercent(string str1, string str2) { //int maxLenth = str1.Length > str2.Length ? str1.Length : str2.Length; int val = Levenshtein_Distance(str1, str2); return 1 - (decimal)val / Math.Max(str1.Length, str2.Length); } }
?
1 |
<STRONG>调用</STRONG> |
showstatic void Main(string[] args) { string str1 = "ivan1"; string str2 = "ivan2"; Console.WriteLine("字符串1 {0}", str1); Console.WriteLine("字符串2 {0}", str2); Console.WriteLine("相似度 {0} %", new LevenshteinDistance().LevenshteinDistancePercent(str1, str2) * 100); Console.ReadLine(); }
?
1 |
<STRONG>结果</STRONG> |
<ignore_js_op>
------------------------------
动态时间弯曲距离 dynamic time warping
1.What is 动态时间弯曲距离 <ignore_js_op>
在日常的生活中我们最经常使用的距离毫无疑问应该是欧式距离,但是对于一些特殊情况,欧氏距离存在着其很明显的缺陷,比如说时间序列,举个比较简单的例子,序列A:1,1,1,10,2,3,序列B:1,1,1,2,10,3,如果用欧氏距离,也就是distance[j]=(b[j]-a)*(b[j]-a)来计算的话,总的距离和应该是128,应该说这个距离是非常大的,而实际上这个序列的图像是十分相似的,这种情况下就有人开始考虑寻找新的时间序列距离的计算方法,然后提出了DTW算法,这种方法在语音识别,机器学习方便有着很重要的作用。
这个算法是基于动态规划(DP)的思想,解决了发音长短不一的模板匹配问题,简单来说,就是通过构建一个邻接矩阵,寻找最短路径和。
还以上面的2个序列作为例子,A中的10和B中的2对应以及A中的2和B中的10对应的时候,distance[3]以及distance[4]肯定是非常大的,这就直接导致了最后距离和的膨胀,这种时候,我们需要来调整下时间序列,如果我们让A中的10和B中的10 对应 ,A中的1和B中的2对应,那么最后的距离和就将大大缩短,这种方式可以看做是一种时间扭曲,看到这里的时候,我相信应该会有人提出来,为什么不能使用A中的2与B中的2对应的问题,那样的话距离和肯定是0了啊,距离应该是最小的吧,但这种情况是不允许的,因为A中的10是发生在2的前面,而B中的2则发生在10的前面,如果对应方式交叉的话会导致时间上的混乱,不符合因果关系。
接下来,以output[6][6](所有的记录下标从1开始,开始的时候全部置0)记录A,B之间的DTW距离,简单的介绍一下具体的算法,这个算法其实就是一个简单的DP,状态转移公式是output[j]=Min(Min(output[i-1][j],output[j-1]),output[i-1][j-1])+distance[j];最后得到的output[5][5]就是我们所需要的DTW距离.
2.动态时间弯曲距离程序Matlab C++
3.在金融工程中的应用根据动态时间距离方法预测市场走势 理论基础:历史重复,使用模式匹配方法,寻找历史中与现在最接近的时段!!
(1)基于日线--动态时间距离方法预测市场走势(每日自动更新)
(2)基于日线列出最相似T0p5--动态时间距离方法预测市场走势(每日自动发送)
(3)基于交易量与价格等等。。。。