numpy实现余弦相似度
时间: 2023-07-26 08:03:33 浏览: 81
在NumPy中,可以使用以下代码实现余弦相似度:
```python
import numpy as np
def cosine_similarity(a, b):
dot_product = np.dot(a, b)
norm_a = np.linalg.norm(a)
norm_b = np.linalg.norm(b)
return dot_product / (norm_a * norm_b)
```
其中,`np.dot(a, b)`计算了向量a和b的点积,`np.linalg.norm(a)`计算了向量a的L2范数,即:
$$||a||_2=\sqrt{\sum_{i=1}^n a_i^2}$$
最后,将点积除以两个向量的L2范数的乘积即可得到余弦相似度。
相关问题
Numpy 实现余弦相似度embedding 的NTxent
下面是使用 Numpy 实现余弦相似度的 NTxent 损失的示例代码。
首先,我们需要定义一个嵌入矩阵 $E$,其中每一行代表一个单词的嵌入向量。假设我们有 $N$ 个单词,每个单词的嵌入向量为 $d$ 维,那么 $E$ 的形状将为 $N \times d$。我们可以使用 NumPy 的随机函数生成一个随机的嵌入矩阵:
```python
import numpy as np
N = 10000
d = 300
E = np.random.randn(N, d)
```
接下来,我们需要选择一些中心单词 $c_i$,以及它们对应的正样本单词 $p_i$ 和负样本单词 $n_i$。我们可以使用 NumPy 的随机函数从嵌入矩阵 $E$ 中随机选择这些单词:
```python
batch_size = 32
c_idx = np.random.randint(N, size=batch_size)
e_c = E[c_idx]
p_idx = np.random.randint(N, size=batch_size)
e_p = E[p_idx]
n_idx = np.random.randint(N, size=(batch_size, 5))
for i in range(batch_size):
while p_idx[i] in n_idx[i]:
n_idx[i] = np.random.randint(N, size=5)
e_n = E[n_idx]
```
接下来,我们可以计算每个中心单词 $c_i$ 和对应的正样本单词 $p_i$ 的余弦相似度:
```python
cos_sim = np.sum(e_c * e_p, axis=1) / (np.linalg.norm(e_c, axis=1) * np.linalg.norm(e_p, axis=1))
```
然后,我们可以计算每个中心单词 $c_i$ 和对应的负样本单词 $n_{i,j}$ 的余弦相似度:
```python
cos_sim_neg = np.sum(e_c[:, np.newaxis, :] * e_n, axis=2) / (np.linalg.norm(e_c, axis=1)[:, np.newaxis] * np.linalg.norm(e_n, axis=2))
```
接下来,我们需要将余弦相似度转换为概率分布,并计算 NTxent 损失。假设我们使用 softmax 函数将余弦相似度转换为概率分布,我们可以使用以下代码计算 NTxent 损失:
```python
temperature = 0.1
logit = cos_sim / temperature
logit_neg = cos_sim_neg / temperature
logit_all = np.concatenate([np.array([logit]), logit_neg], axis=0)
logit_all = np.exp(logit_all)
probs = logit_all / np.sum(logit_all, axis=0)
log_prob = np.log(probs[0] / np.sum(probs[1:], axis=0))
loss = -np.mean(log_prob)
```
其中,`temperature` 是一个超参数。我们可以使用类似的方式计算每个中心单词 $c_i$ 和对应的负样本单词 $n_{i,j}$ 的 NTxent 损失。完整的代码示例如下:
```python
import numpy as np
N = 10000
d = 300
temperature = 0.1
# 生成随机嵌入矩阵
E = np.random.randn(N, d)
# 选择中心单词和正样本单词
batch_size = 32
c_idx = np.random.randint(N, size=batch_size)
e_c = E[c_idx]
p_idx = np.random.randint(N, size=batch_size)
e_p = E[p_idx]
# 选择负样本单词
n_idx = np.random.randint(N, size=(batch_size, 5))
for i in range(batch_size):
while p_idx[i] in n_idx[i]:
n_idx[i] = np.random.randint(N, size=5)
e_n = E[n_idx]
# 计算余弦相似度
cos_sim = np.sum(e_c * e_p, axis=1) / (np.linalg.norm(e_c, axis=1) * np.linalg.norm(e_p, axis=1))
cos_sim_neg = np.sum(e_c[:, np.newaxis, :] * e_n, axis=2) / (np.linalg.norm(e_c, axis=1)[:, np.newaxis] * np.linalg.norm(e_n, axis=2))
# 计算 NTxent 损失
logit = cos_sim / temperature
logit_neg = cos_sim_neg / temperature
logit_all = np.concatenate([np.array([logit]), logit_neg], axis=0)
logit_all = np.exp(logit_all)
probs = logit_all / np.sum(logit_all, axis=0)
log_prob = np.log(probs[0] / np.sum(probs[1:], axis=0))
loss = -np.mean(log_prob)
```
numpy 实现embedding 使用余弦相似度的NTxent
下面是一个使用numpy实现embedding使用余弦相似度的NTxent的示例代码:
``` python
import numpy as np
# 定义一些超参数
k = 10 # top-k正样本
T = 0.5 # 温度参数
# 假设我们有n个样本,每个样本有m维特征
n, m = 1000, 128
# 随机初始化嵌入向量
embeddings = np.random.randn(n, m)
# 计算余弦相似度矩阵
norms = np.linalg.norm(embeddings, axis=1, keepdims=True)
similarities = np.dot(embeddings, embeddings.T) / np.dot(norms, norms.T)
# 对于每个样本i,选择top-k个正样本和一组负样本
pos_samples = np.zeros((n, k))
neg_samples = np.zeros((n, k))
for i in range(n):
pos_samples[i] = np.argsort(similarities[i])[::-1][1:k+1]
neg_samples[i] = np.random.choice(np.delete(np.arange(n), pos_samples[i]), k, replace=False)
# 计算交叉熵损失
loss = 0
for i in range(n):
pos_scores = np.sum(embeddings[i] * embeddings[pos_samples[i]], axis=1) / T
neg_scores = np.sum(embeddings[i] * embeddings[neg_samples[i]], axis=1) / T
scores = np.concatenate((pos_scores, neg_scores))
labels = np.zeros(k*2)
labels[:k] = 1
loss += -np.mean(labels * np.log(np.exp(scores) / np.sum(np.exp(scores))))
print('NTxent loss:', loss)
```
在这个示例中,我们首先随机初始化n个样本的m维嵌入向量,然后计算余弦相似度矩阵。接着,对于每个样本i,我们选择top-k个余弦相似度最大的样本作为正样本,随机选择一组与i余弦相似度较小的样本作为负样本。最后,我们计算每个样本i的交叉熵损失,并输出总的NTxent损失。
需要注意的是,这只是一个简单的示例,实际使用时需要根据具体情况进行调整和优化。此外,还需要对嵌入向量进行归一化处理,以保证余弦相似度的取值范围在[-1, 1]之间。
阅读全文