我正在为稀疏向量计算余弦相似矩阵,而预期为浮点数的元素似乎是'nan'。
'visits'是一个稀疏矩阵,显示每个用户访问过每个网站的次数。这个矩阵的形状为1 500 000 x 1500,但我使用coo_matrix()。tocsc()将其转换为稀疏矩阵。
任务是找出网站有多相似,所以我决定计算每两个网站之间的余弦指标。
这是我的代码:
cosine_distance_matrix = np.ndarray(shape = (visits.shape[1], visits.shape[1]))
def norm(x):
return np.sqrt(
x.T.dot(x)
)
for i in range(0, visits.shape[1]):
for k in range(0, i + 1):
normi_normk = norm(visits[:,i]) * norm(visits[:,k])
cosine_distance_matrix[i,k] = visits[:,i].T.dot(visits[:, k])/normi_normk
cosine_distance_matrix[k, i] = cosine_distance_matrix[i, k]
print cosine_distance_matrix
这就是我的成就! O_O
[[ 1. nan nan ..., nan nan nan]
[ nan 1. nan ..., nan nan nan]
[ nan nan 1. ..., nan nan nan]
...,
[ nan nan nan ..., 1. nan nan]
[ nan nan nan ..., nan 1. nan]
[ nan nan nan ..., nan nan 1.]]
这个程序运行了3个小时......这样的垃圾是什么原因而不是漂浮数?
答案 0 :(得分:0)
尝试:
def norm(x):
return np.sqrt((x.T*x).A)
我构建了一个较小的样本visits
矩阵,并使用您的代码计算cosine_distance_matrix
。我的对角线为1s,对角线上有很多nan
。我选择其中一个nan
项,并查看相应的i,k
计算。
In [690]: normi_normk = norm(visits[:,i]) * norm(visits[:,k])
In [691]: normi_normk
Out[691]:
<1x1 sparse matrix of type '<class 'numpy.float64'>'
with 1 stored elements in Compressed Sparse Column format>
In [692]: normi_normk.A
Out[692]: array([[ 18707.57953344]])
visits
是一个稀疏矩阵,因此visits[:,i]
也是稀疏矩阵(1列)。您的norm
函数返回1x1稀疏矩阵。
对于这一对,此dot
为0,但它仍然是1x1稀疏矩阵:
In [718]: visits[:,i].T.dot(visits[:, k])
Out[718]:
<1x1 sparse matrix of type '<class 'numpy.int32'>'
with 0 stored elements in Compressed Sparse Column format>
这些稀疏矩阵的划分也很稀疏 - nan
。
In [717]: visits[:,i].T.dot(visits[:, k])/normi_normk
Out[717]: matrix([[ nan]])
但如果我将normi_normk
更改为标量或密集数组,我会得到0
In [722]: visits[:,i].T.dot(visits[:, k])/normi_normk.A
Out[722]: matrix([[ 0.]])
所以我们必须将它从matrix/matrix
除法改为涉及密集数组或标量的东西。它可以通过各种方式进行更改。重写norm
以正确处理稀疏矩阵是一个。
另外我建议使用:
(visits[:,i].T*visits[:, k]).A/normi_normk
这样两个部门的条款都很密集。
另一种可能性是使用visits[:,i].A
和visits[:,k].A
,因此内循环计算是使用密集数组而不是这些矩阵完成的。
请注意,我没有做任何高级或特殊的事情。我刚刚详细检查了一个问题计算,并找到了nan
的来源。
我还建议使用np.zeros
来初始化数组。我只在正常ndarray
,zeros
,ones
不起作用时才使用empty
。
cosine_distance_matrix = np.zeros((visits.shape[1], visits.shape[1]))
总体而言,最好避免在i
和k
上进行循环,使用矩阵产品等做任何事情。但是这个修复程序可以帮助你。