“距离”这个词经常在用到,在初中几何上,它指两点间直线的长度,想要测量它很容易,然而果真如此吗?乘坐出租车从家到公司,下车后计价表显示30公里,这可不是两点间的直线。《三国》里,探马回报:“袁军距我军30里处的官渡处下寨,绵延百里”,到底是30里还是百里,怎样才算30里?2018年法国队赢得世界杯冠军,距离他们上次夺冠,已经过去了20年,这里的距离又是时间的跨度。一对单身男女相亲,在一顿无聊的晚餐后得出彼此“距离太远”的结论,人心的距离又该如何测量?

距离的多种度量

  先来看一个简单的例子,平坦的地面上有一个边长为1的正方形凹陷,AB两点位于凹陷的边缘处,如下图所示,AB两点间的距离是多少?

  暂且不考虑边长的单位,假设一个成年人正好可以一步跨越,那么这个人从A到B所经过的距离是1,如下图所示:

  一个身材矮小的少年来了,他把凹陷当作楼梯,先下后上,于是有了这样的行进路线:

  少年经过的实际距离是两个三角形的斜边,具体数值是:

  又来了一个幼儿园的小朋友,他需要手脚并用,爬上爬下,行进距离是3:

  现在有意思了,一个简单的行进,只因为有了一个小小的凹陷就导致了三种不同的行进距离。实际上也许有更多距离,比如一个文艺青年用大跳跨越了一个优美的弧线:

  也许有人会说,反正结果都是从A到B,简单的计算为1不就好了?从空间转移来说这没错,但是在自然状态下,各种运动所消耗的能量不同,小朋友爬上爬下的消耗一定比成年人一步跨越要多。类似的例子很多,比如盘山路,更没办法算成两点间的直线了。

  其实例子中的几种测量都有道理,根据实际需要和条件的变化,改变距离的计算方法才能得到相对靠谱的数值,接下来将要介绍的就是几种常见的距离计算方法。

一维空间的距离

  一维空间可以看作一把带有刻度的直尺,在一维空间上计算距离是最简单的,只需要取两点间数值差的绝对值就可以了,如下图所示:

  常见的时间轴就是典型的一维距离,此时距离代表时间的跨度:

欧几里德距离

  欧几里得距离(Euclidean Distance)又称欧式距离或欧几里得度量,是以空间为基准的两点之间最短距离,简单地说,就是两点之间直线最短的概念。

  二维空间内的算比较简单,主要是点到点和点到直线,如下图所示:

  AB两点间的距离:

  所有与原点的欧几里德距离为1的点可以构成一个半径为1的圆:

  计算A点与直线的距离前,需要先把直线的表达式做个转化,变成ax + by + c = 0的形式:

  A(xA, yA)到直线 2x – y – 3 = 0的距离:

  三维空间内,主要是点到点和点到平面的距离,如下图所示,Q是平面ax + by + cz = d上的一点,P是平面外的另一点,PQ垂直于平面:

  PQ间距离的计算公式与二维空间相同,只是多了一个分量:

  计算P到平面的距离同样需要先把平面转化一下,变成ax + by + cz – d = 0,这样就和二维空间内的计算相同:

  类似的公式也可以推广到多维空间。P和Q是n维空间内的两点,PQ间的距离:

  在第1章已经讲过,n维空间的超平面可以写成:

  点到超平面的距离公式:

  将P点代入到公式中,点P到超平面的距离:

  Python可以很方便地计算欧氏距离,代码如下:

import numpy as npx1 = [1, 1]
x2 = [2, 2]
np_x1 = np.array(x1)
np_x2 = np.array(x2)# 直接使用公式计算
d1 = np.sqrt(np.sum((np_x1 - np_x2) ** 2))
# 使用内置的范数函数计算
d2 = np.linalg.norm(np_x1 - np_x2)

  代码中两种方式的计算结果相同。

曼哈顿距离

  想象一下在曼哈顿街头的一个路口坐出租车到另一个路口,司机会按照两个路口的直线距离行进吗?大多数时候不会,除非无视交通规则并且能穿越大楼。下图中的AB两点间的直线是欧几里德距离,折线是出租车行的实际行进距离。早在十九世纪,赫尔曼·闵可夫斯基就在曼哈顿街区研究过,将其命名为“曼哈顿距离(Manhattan Distance)”(如果在今天,可能被命名为“导航距离”)。

  城市街区大多数是在地势平缓的二维平面,两点A(x1, y1)和B(x2, y2)间曼哈顿距离的计算公式是:

  在AB间曼哈顿距离相同的情况下,可能有多种行进路线:

  所有与原点的曼哈顿距离为1的点可以构成一个边长为根号2的正方形:

  n维空间中的两点P和Q间的曼哈顿距离:

  Python计算曼哈顿距离:

import numpy as npx1 = [1, 3]
x2 = [4, 9]
np_x1 = np.array(x1)
np_x2 = np.array(x2)d = np.sum(np.abs(np_x1 – np_x2))

  现在来看看《三国》中哨骑的探报,如果把军队变成团伙,将官渡战场的大战变成曼哈顿街头的火拼,就可以看出,哨骑回报的距离是袁军先头部队到曹军的曼哈顿距离。

切比雪夫距离

国际象棋中,国王走一步可以直行、横行、斜行移动到相邻八个方格中的任意一个,如下图所示:

如果把两个相邻方格的距离记为1,国王从方格A(x1, y1)走到方格B(x2, y2)最少需要的最短距离,就是切比雪夫距离(Chebyshev distance),下图展示了国王从棋盘某一方格处,到达其它方格的距离:

  在二维空间内,A(x1, y1)和B(x2, y2)两点间的切比雪夫距离是两点横坐标差的绝对值与纵坐标差的绝对值中较大的那个:

  扩展到多维空间,PQ间的切比雪夫距离:

  棋盘上格子是距离的离散表示,在真正的二维坐标中,与原点距离为1的点会构成一个边长为2的正方形:

  对比上一节同为正方形的曼哈顿距离,发现它们应该可以互相转换。实际上,在二维空间内曼哈顿距离与切比雪夫距离的坐标转换关系是:

  Python计算切比雪夫距离:

import numpy as npx1 = [1, 3]
x2 = [4, 9]
np_x1 = np.array(x1)
np_x2 = np.array(x2)d = np.max(np.abs(np_x1 – np_x2))

夹角余弦

  夹角余弦(Cosine Similarity)测量的是两个样本间的相似性,样本间的距离越近,相似度越高。

  夹角余弦来源于向量点积的几何意义,两个向量AB的点积等于AB的模乘以二者的夹角余玄:

  可以看出,cosθ表示的是AB方向的相似度,与它们的大小无关,虽然下图中A’ 的模长远小于A的模长,但AB的夹角余弦和等于A’B的相等:

  扩展到多维空间,PQ间的夹角余弦:

  Python能够方便地使用向量计算夹角余弦,下面给出了两种计算方式:

# 使除法变成精确除法
from __future__ import division
import numpy as npx1 = [1, 2, 3, 5]
x2 = [2, 3, 4, 6]
np_x1 = np.array(x1)
np_x2 = np.array(x2)result1 = np.dot(np_x1, np_x2) / np.sqrt(np.dot(np_x1, np_x1) *  np.dot(np_x2, np_x2))
result2 = np.dot(np_x1, np_x2) / (np.linalg.norm(np_x1) * np.linalg.norm(np_x2))
theta = np.arccos(result1)print('result1 = %f, result2 = %f, theta = %f' % (result1, result2, theta))
# result1 = 0.993073, result2 = 0.993073, theta = 0.117774

  夹角余弦取值范围是[-1,1],它提供了以下几个信息:

  • 余弦越大,两个向量的夹角越小,相似度越高;余弦越小,两个向量的夹角越大,相似度越低。
  • 两个向量的方向重合时余弦等于1;两个向量的方向完全相反余弦等于-1;两个向量垂直是,余弦值等于0。
  • θ < 90°,A·B > 0;θ > 90°,A·B < 0;θ = 90°,A·B = 0。

其它度量方法

  还有很多种方法用于度量距离,比如经常在推荐系统用来度量偏好习惯,但看起来不那么直观的的皮尔逊相关度;度量符号或布尔值个体间相似度的Jaccard系数和谷本系数;在信息论中,度量两个等长字符串之间对应位置的不同字符个数的汉明距离;还有马氏距离,闵可夫斯基距离,以及判断整个系统内部样本分布集中程度的信息熵等等。这些度量方法各有优缺点,不同的度量方法有些时候对于算法的结果差异很大,在实践中,可能要在不同的方法中反复切换,根据实际效果进行对比,最终选取效果最好的一个。

人心的距离

  也许是为了摆脱单身状态,也许是为了应付长辈的特意安排,许多年轻的单身男女都参加过相亲,但是大多数相亲都是以“三观不合”或“距离太远”为由而没有下文。人与人之间的距离似乎是一个文学词汇,并非物理意义上的距离,真的能够测量吗?怎么才算三观基本一致?接下来,我们就用本章的知识去尝试度量人与人之间的距离。

相亲

  小明是个28岁的城市白领,国庆期间在老妈的安排下分别见了可可、乐乐、小枫和小柔四个女孩。经过逛街吃饭后,小明对四个个女孩有了初步的了解,觉得她们都十分可爱,四个女孩似乎也想进一步发展。“你喜欢哪一个呢?”老妈问,“这个……”小明犯了难,不能脚踏四只船啊。“对了,就选和自己距离最近的!”小明想,于是他根据自己最关心的问题绘制了这样一个表格:

  小明觉得文字对比不够直观,所以他的第一步是把文字转换为数字。

数据预处理

  为了方便比较,先将非数值属性量化。小明有三个爱好,所以设自己的爱好值是3,同时设女孩们的初始爱好值是0,如果一个女孩有一个爱好与自己相同,则该女孩的爱好值加1,例如可可与小明都喜欢读书,所以可可的爱好值是1。同时小明也注意到,有些爱好虽然不同,但及其相近,比如音乐与唱歌,所以把二者看作同一爱好。于是,小明得到了下面的数据:

  其中年龄的数值较大,直接使用会占据较大的权重,所以小明对它们做了进一步处理,他以自己的数据为标准,将女孩的数据与自己相减。此外,他对是否要小孩看的很重要,对年龄差距并不十分看中,所以分别增加和缩减了两个维度的权重。现在数据数值都在一个较小的范围内:

度量距离

  现在终于可以测量了,看看那个女孩和小明最般配。不妨先将学历和爱好拿出来,在平面上看看距离,如下图所示:

  看起来小枫和自己最近,乐乐相对较远。当所有维度都参与计算时,小明使用下面的代码帮助计算:

# 使除法变成精确除法
from __future__ import division
import numpy as np# 欧几里德距离
def d_euclidean(x1, x2):return np.linalg.norm(x1 - x2)# 曼哈顿距离
def d_manhattan(x1, x2):return np.sum(np.abs(x1 - x2))# 切比雪夫距离
def d_chebyshev(x1, x2):return np.max(np.abs(x1 - x2))# 计算距离
def d_compute(x, d_name, d_fun):''':param x: 样本的特征集:param d_name: 距离算法名称:param d_fun: 距离算法'''print('%s:\t%f\t%f\t%f\t%f' %(d_name, d_fun(x[0], x[1]), d_fun(x[0], x[2]), d_fun(x[0], x[3]), d_fun(x[0], x[4])))
if __name__ == '__main__':    # 初始数据    data_set = [[0, 2, 3, 3],  [-2, 1, 1, 3],  [-1, 2, 0, 3], [-0.5, 3, 2, -3], [2, 4, 3, 3]]    # 将数据转换为numpy向量    x = np.array(data_set)

    d_compute(x, 'euclidean', d_euclidean)    d_compute(x, 'manhattan', d_manhattan)    d_compute(x, 'chebyshev', d_chebyshev)    d_compute(x, '\tcos', d_cos)

  由于夹角余弦仅与向量的方向有关,与向量的大小无关,在这里又希望更多地考虑向量的大小,所以只使用两位三种距离度量,最终得到这样的结果:

  三种度量得到了三种不同的结果,而且每种结果中排在第一位的女孩都不同,综合考虑后,似乎小柔排在前面的次数较多,所以小明觉得明天应该重点发展一下小柔。

人心可测吗

  问题似乎圆满解决了,然而这样真的合理吗?想想儿时的小伙伴们,今天,他们的学历、爱好、收入甚至三观都与自己极为不同,但似乎并没有影响我们的矫情,时隔多年大家仍然有相同的话题,仍然可以一起喝上一杯,距离的长度似乎并不影响我们成为朋友。相反,身边的同事无论学历、经历还是工作目标都与自己接近,然而一道浅浅的隔断就阻断了大多数交流,彼此封闭起内心。人心真的可测吗?还是留给大家去思考吧。


  作者:我是8位的

  出处:http://www.cnblogs.com/bigmonkey

  本文以学习、研究和分享为主,如需转载,请联系本人,标明作者和出处,非商业用途!

  扫描二维码关注公众号“我是8位的”

转载于:https://www.cnblogs.com/bigmonkey/p/9610964.html

寻找“最好”(6)——心的距离相关推荐

  1. 轨迹跟踪_预描点寻找

    1 原理 当所有点到后轴中心的距离都大于预瞄距离时,选择最近的点: 当所有点到后轴中心的距离都小于预瞄距离时,选择最远的点: 否则,选择一个点满足要求: 即,该点与车辆后轴中心在车辆纵轴上的距离小于预 ...

  2. TPAMI 2022 | 寻找属于你的影子,港中文等提出实例阴影检测任务

    本文转载自机器之心,作者王天宇.胡枭玮 来自香港中文大学与上海人工智能实验室的王天宇与胡枭玮等作者提出了一种实例阴影检测任务,旨在查找阴影与物体之间的关系. 阴影是由光线被物体遮挡而产生,阴影与物体密 ...

  3. Redis 笔记(13)— scan 和 keys 寻找特定前缀key 字段(命令格式、使用示例、定位大key)

    1. keys Redis 提供了一个简单暴力的指令 keys 用来列出所有满足特定正则字符串规则的 key. 127.0.0.1:6379> keys * (empty array) 127. ...

  4. 寻找一个字符串的重复子串 后缀数组

    什么是后缀数组 令字符串 S=S[1]S[2]...S[n]S=S[1]S[2]...S[n]{\displaystyle S=S[1]S[2]...S[n]} , S[i,j]S[i,j]{\dis ...

  5. LeetCode简单题之寻找比目标字母大的最小字母

    题目 给你一个排序后的字符列表 letters ,列表中只包含小写英文字母.另给出一个目标字母 target,请你寻找在这一有序列表里比目标字母大的最小字母. 在比较时,字母是依序循环出现的.举个例子 ...

  6. 交换机应用寻找10个完美的因素

    交换机应用寻找10个完美的因素 10 factors for finding the perfect switch for your application 选择开关的过程并不总是值得注意的.考虑到大 ...

  7. 寻找汽车连接的解决方案

    寻找汽车连接的解决方案 Finding solutions for automotive vehicle connectivity 汽车制造商正在增加完全依赖于连通性的功能,汽车也开始联网.这是件好事 ...

  8. 《OpenCV3编程入门》学习笔记8 图像轮廓与图像分割修复(二)寻找物体的凸包

    8.2 寻找物体的凸包 8.2.1 概念 1.给定二维平面上的点集,将最外层点连接起来构成的凸多边形. 2.理解物体形状或轮廓的一种比较有用的方法是计算一个物体的凸包,然后计算其凸缺陷(convexi ...

  9. 数据存储方式_寻找要操作数据的存储地址的过程称为寻址,几种寻址的方式分享...

    单片机工作时,在程序指令的控制下,对数据进行各种操作(如存取数据.对数据进行运算等),然后输出控制信号.指令要对数据进行操作,必须先找到操作的数据,数据存放在存储器中,只有找到要操作数据的存储地址,才 ...

最新文章

  1. RDKit | 将rdMolDraw2D和RDKit生成的结构图输出到Excel
  2. docker hub 国内镜像_Mac设置docker国内镜像源
  3. 浅谈多进程多线程的选择(转)
  4. 互联网1分钟 | 0920
  5. [翻译] DoImagePickerController
  6. Android,EditText,InuputType
  7. Jar 包依赖冲突排查思路和解决方法(logback + slf4j-log4j12)
  8. php中的try语句,PHP Try-catch 语句使用技巧
  9. 以太网驱动详解之 MAC、MII、PHY 详解
  10. spring原理面试题总结
  11. 英语六级口语 计算机,英语六级口语
  12. 生成13位条形码Ean-13码规则:第十三位数字是前十二位数字经过计算得到的校验码。
  13. SM4算法大文件加密与字符串加密
  14. CVPR 2022 | Accuracy和F1-score真的能代表车道线检测网络性能吗?
  15. 阿里内核数据库文章-目录
  16. 如何修改win7上的mac地址
  17. 构造方法--带参构造方法
  18. 病毒木马查杀实战第009篇:QQ盗号木马之手动查杀
  19. nested exception is java.lang.NoSuchMethodError
  20. StatusBarUtil 状态栏工具类(实现沉浸式状态栏/变色状态栏)

热门文章

  1. 利用java统计每天用户升级手机App信息
  2. iOS时间戳与北京时间的转换
  3. STM32+PN532写UltraLight标签
  4. 有关汽车仪表的LED与LCD识别
  5. iOS封装相册API的tips
  6. 微信小程序授权登录取消授权重新授权处理方法 附可用代码
  7. “远香烟·近健康”乡风文明之禁烟活动
  8. html5新标签 figure 和 figcaption
  9. Python Requests:两个例子说明get和post方法+用谷歌浏览器查看网络请求
  10. 计算机考试运用的数学知识点,计算器的使用知识点