我试图Kmeans
在python中实现算法,它将使用cosine distance
而不是欧几里德距离作为距离度量.
我知道使用不同的距离函数可能是致命的,应该仔细进行.使用余弦距离作为度量迫使我改变平均函数(根据余弦距离的平均值必须是归一化向量的元素平均值的元素).
我已经看到了这种手动覆盖sklearn的距离函数的优雅解决方案,我想使用相同的技术来覆盖代码的平均部分,但我找不到它.
有谁知道怎么做?
距离度量不满足三角不等式有多重要?
如果有人知道kmeans的不同有效实现,我使用余弦度量或满足距离和平均函数,它也将是真正有用的.
非常感谢你!
编辑:
使用角距离而不是余弦距离后,代码看起来像这样:
def KMeans_cosine_fit(sparse_data, nclust = 10, njobs=-1, randomstate=None):
# Manually override euclidean
def euc_dist(X, Y = None, Y_norm_squared = None, squared = False):
#return pairwise_distances(X, Y, metric = 'cosine', n_jobs = 10)
return np.arccos(cosine_similarity(X, Y))/np.pi
k_means_.euclidean_distances = euc_dist
kmeans = k_means_.KMeans(n_clusters = nclust, n_jobs = njobs, random_state = randomstate)
_ = kmeans.fit(sparse_data)
return kmeans
Run Code Online (Sandbox Code Playgroud)
我注意到(通过数学计算)如果向量被归一化,则标准平均值适用于角度量.据我了解,我必须改变_mini_batch_step()
在k_means_.py.但功能非常复杂,我无法理解如何做到这一点.
有谁知道替代解决方案?
或许,有没有人知道我怎么能用一个总是迫使质心标准化的功能来编辑这个功能?
python k-means cosine-similarity scikit-learn sklearn-pandas
两个相等大小的矢量(实数)之间的余弦相似性被定义为点积乘以规范的乘积.
为了表示向量,我有一个大型float
数组表,例如CREATE TABLE foo(vec float[])'
.给定一个特定的float
数组,我需要快速(使用索引,而不是seqscan)通过余弦相似性找到该表中最接近的数组,例如SELECT * FROM foo ORDER BY cos_sim(vec, ARRAY[1.0, 4.5, 2.2]) DESC LIMIT 10;
但我该怎么用?
pg_trgm
余弦相似度的支持是不同的.它比较文本,我不确定它究竟是做什么的.称为smlar
(此处)的扩展也对浮点数组具有余弦相似性支持,但是又做了不同的事情.我所描述的通常用于数据分析以比较文档的特征,所以我认为Postgres会支持它.
我想在matlab中计算矩阵的不同行之间的余弦相似度.我在matlab中编写了以下代码:
for i = 1:n_row
for j = i:n_row
S2(i,j) = dot(S1(i,:), S1(j,:)) / (norm_r(i) * norm_r(j));
S2(j,i) = S2(i,j);
Run Code Online (Sandbox Code Playgroud)
矩阵S1为11000*11000,代码执行非常耗时.所以,我想知道matlab中是否有任何函数可以比上面的代码更快地计算矩阵行之间的余弦相似度?
我正在阅读 Levy 等人的论文“Improving Distributional Comparison\nwith Lessons Learned from Word Embeddings”,在讨论他们的超参数时,他们说:
\n\n\n\n\n向量归一化 (nrm)正如第 2 节中提到的,所有向量(即 W\xe2\x80\x99s 行)都归一化为单位长度(L2 归一化),使点积运算等效于余弦相似度。
\n
然后我想起sim2
Rtext2vec
包中向量相似度函数的默认值首先是 L2 范数向量:
sim2(x, y = NULL, method = c("cosine", "jaccard"), norm = c("l2", "none"))\n
Run Code Online (Sandbox Code Playgroud)\n\n所以我想知道,归一化和余弦(无论是在 text2vec 方面还是一般情况下)的动机可能是什么。我尝试阅读 L2 范数,但大多数情况下它是在使用欧几里德距离之前进行标准化的背景下出现的。我(令人惊讶地)找不到任何关于在词向量空间/嵌入的余弦相似性的情况下是否推荐或反对 L2 范数的任何信息。而且我不太具备计算分析差异的数学技能。
\n\n所以这里有一个问题,意味着在从文本数据学习的词向量空间的背景下(要么只是可能由 tfidf、ppmi 等加权的共现矩阵;或者像 GloVe 这样的嵌入),并计算词相似度(目标是当然使用最能反映现实世界单词相似性的向量空间+度量)。
简而言之,在计算向量/单词之间的余弦相似度之前,是否有任何理由(不)在单词特征矩阵/术语共现矩阵上使用 L2 范数?
我需要计算列表中字符串之间的余弦相似度.例如,我有一个超过1000万个字符串的列表,每个字符串必须确定它自己与列表中的每个其他字符串之间的相似性.什么是我可以用来有效和快速完成这项任务的最佳算法?分而治之算法是否适用?
编辑
我想确定哪些字符串与给定字符串最相似,并且能够获得与相似性相关的度量/分数.我认为我想做的事情与群集相符合,群集的数量最初并不为人所知.
User has many Profiles
(Limit - no more than one of each profile type per user, no duplicates)
Profiles has many Attribute Values
(A user can have as many or few attribute values as they like)
Attributes belong to a category
(No overlap. This controls which attribute values a profile can have)
Run Code Online (Sandbox Code Playgroud)
我相信通过堆栈交换,您可以为一个用户提供许多配置文件,因为它们因交换站点不同而不同?在这个问题:
配置文件和属性只是在两个级别上对属性值进行分组的方法.如果没有分组(在2.之后加权需要),关系就是User hasMany Attribute Values.
为每个用户提供与其他用户相似的评级.
我使用word2vec来表示一个小短语(3到4个单词)作为一个独特的向量,通过添加每个单独的嵌入或通过计算单词嵌入的平均值.
从我做过的实验中,我总是得到相同的余弦相似度.我怀疑它与训练后word2vec生成的单词长度(单位长度(Euclidean norm))有关吗?或者我在代码中有BUG,或者我遗漏了一些东西.
这是代码:
import numpy as np
from nltk import PunktWordTokenizer
from gensim.models import Word2Vec
from numpy.linalg import norm
from scipy.spatial.distance import cosine
def pattern2vector(tokens, word2vec, AVG=False):
pattern_vector = np.zeros(word2vec.layer1_size)
n_words = 0
if len(tokens) > 1:
for t in tokens:
try:
vector = word2vec[t.strip()]
pattern_vector = np.add(pattern_vector,vector)
n_words += 1
except KeyError, e:
continue
if AVG is True:
pattern_vector = np.divide(pattern_vector,n_words)
elif len(tokens) == 1:
try:
pattern_vector = word2vec[tokens[0].strip()]
except KeyError:
pass
return pattern_vector
def main():
print "Loading …
Run Code Online (Sandbox Code Playgroud) 根据我在 stackoverflow 上找到的几篇文章(例如,为什么 word2Vec 使用余弦相似度?),通常的做法是在我们训练好 word2vec(CBOW 或 Skip-gram)模型后计算两个词向量之间的余弦相似度。然而,这对我来说似乎有点奇怪,因为该模型实际上是用点积作为相似性分数进行训练的。一个证据是我们训练后得到的词向量的范数实际上是有意义的。那么为什么人们在计算两个词之间的相似度时仍然使用余弦相似度而不是点积呢?
我对计算向量之间的相似度很感兴趣,但是这种相似度必须是 0 到 1 之间的数字。关于 tf-idf 和余弦相似度有很多问题,都表明该值介于 0 和 1 之间。来自维基百科:
在信息检索的情况下,两个文档的余弦相似度将在 0 到 1 的范围内,因为术语频率(使用 tf-idf 权重)不能为负。两个词频向量之间的夹角不能大于 90°。
特殊之处在于我希望计算来自两个不同 word2vec 模型的两个向量之间的相似性。但是,这些模型已经对齐,因此它们实际上应该在相同的向量空间中表示它们的单词。我可以像这样计算单词 inmodel_a
和单词 in之间的相似度model_b
import gensim as gs
from sklearn.metrics.pairwise import cosine_similarity
model_a = gs.models.KeyedVectors.load_word2vec_format(model_a_path, binary=False)
model_b = gs.models.KeyedVectors.load_word2vec_format(model_b_path, binary=False)
vector_a = model_a[word_a].reshape(1, -1)
vector_b = model_b[word_b].reshape(1, -1)
sim = cosine_similarity(vector_a, vector_b).item(0)
Run Code Online (Sandbox Code Playgroud)
但是sim
是 [-1,1] 范围内的相似性度量。是否有科学合理的方法将其映射到 [0,1] 范围?直觉上我会认为像
norm_sim = (sim + 1) / 2
Run Code Online (Sandbox Code Playgroud)
没关系,但我不确定这对于余弦相似度的实际含义是否是好的做法。如果没有,是否建议使用其他相似性指标?
我试图让值介于 0 和 1 之间的原因是因为数据将传输给一位同事,该同事将使用它作为她的机器学习系统的特征,该系统期望所有值都在 0 和 1 …
algorithm ×3
python ×3
scikit-learn ×2
similarity ×2
word2vec ×2
dot-product ×1
gensim ×1
java ×1
k-means ×1
match ×1
math ×1
matlab ×1
matrix ×1
nlp ×1
postgresql ×1
text2vec ×1
vector-space ×1
weighted ×1