Published on

常见的 similarity 比较

similarity

Python实现常见相似性计算

下面是表格中提到的各种相似性/距离度量的Python实现示例,包括余弦相似度、欧氏距离(L2)、点积、汉明距离和曼哈顿距离(L1)。

1. 余弦相似度 (Cosine Similarity)

import numpy as np
from numpy.linalg import norm

def cosine_similarity(a, b):
    """计算两个向量之间的余弦相似度"""
    return np.dot(a, b) / (norm(a) * norm(b))

# 示例:文档向量相似性
doc1 = np.array([1, 2, 0, 1, 0])  # 文档1的TF-IDF向量
doc2 = np.array([0, 2, 1, 0, 1])  # 文档2的TF-IDF向量
print(f"余弦相似度: {cosine_similarity(doc1, doc2):.4f}")

2. 平方欧氏距离 (Squared Euclidean/L2 Distance)

def squared_euclidean_distance(a, b):
    """计算两个向量之间的平方欧氏距离"""
    return np.sum((a - b) ** 2)

# 示例:图像特征比较
img_feat1 = np.array([0.1, 0.5, 0.8])  # 图像1的特征向量
img_feat2 = np.array([0.2, 0.4, 0.7])  # 图像2的特征向量
print(f"平方欧氏距离: {squared_euclidean_distance(img_feat1, img_feat2):.4f}")

3. 点积 (Dot Product)

def dot_product(a, b):
    """计算两个向量的点积"""
    return np.dot(a, b)

# 示例:推荐系统中的用户-物品匹配
user_pref = np.array([0.9, 0.1, 0.3])  # 用户偏好向量
item_feat = np.array([0.8, 0.2, 0.5])  # 物品特征向量
print(f"点积相似度: {dot_product(user_pref, item_feat):.4f}")

4. 汉明距离 (Hamming Distance)

def hamming_distance(a, b):
    """计算两个等长序列的汉明距离"""
    if len(a) != len(b):
        raise ValueError("输入序列长度必须相同")
    return np.sum(a != b)

# 示例:DNA序列比较
dna1 = np.array([1, 0, 1, 0, 1])  # 二进制编码的DNA序列1
dna2 = np.array([1, 1, 0, 0, 1])  # 二进制编码的DNA序列2
print(f"汉明距离: {hamming_distance(dna1, dna2)}")

5. 曼哈顿距离 (Manhattan/L1 Distance)

def manhattan_distance(a, b):
    """计算两个向量之间的曼哈顿距离"""
    return np.sum(np.abs(a - b))

# 示例:城市网格路径距离
point1 = np.array([3, 7])  # 点1坐标(x,y)
point2 = np.array([5, 2])  # 点2坐标(x,y)
print(f"曼哈顿距离: {manhattan_distance(point1, point2)}")

批量计算版本(适用于多个向量)

# 批量计算余弦相似度(矩阵形式)
def batch_cosine_similarity(X, Y):
    """计算矩阵X和Y中向量之间的余弦相似度"""
    norms_X = np.linalg.norm(X, axis=1, keepdims=True)
    norms_Y = np.linalg.norm(Y, axis=1, keepdims=True)
    return np.dot(X, Y.T) / (norms_X * norms_Y.T)

# 示例:批量文档相似性
docs = np.array([
    [1, 2, 0, 1, 0],
    [0, 2, 1, 0, 1],
    [1, 1, 1, 1, 0]
])
query = np.array([1, 0, 1, 0, 1])
similarities = batch_cosine_similarity(docs, query.reshape(1, -1))
print("批量余弦相似度:", similarities.flatten())

使用Scipy和Sklearn的优化实现

对于生产环境,建议使用优化过的库函数:

from scipy.spatial.distance import cosine, euclidean, hamming, cityblock
from sklearn.metrics.pairwise import cosine_similarity, pairwise_distances

# Scipy版本
print("Scipy余弦距离:", 1 - cosine(doc1, doc2))  # 注意scipy返回的是余弦距离(1-相似度)
print("Scipy欧氏距离:", euclidean(img_feat1, img_feat2))
print("Scipy汉明距离:", hamming(dna1, dna2))
print("Scipy曼哈顿距离:", cityblock(point1, point2))

# Sklearn版本(适合批量计算)
print("Sklearn余弦相似度:\n", cosine_similarity(docs, query.reshape(1, -1)))

THE END