我正在尝试使用这个 1000 维维基百科 word2vec 模型来分析一些文档。
使用自省我发现一个单词的向量表示是一个 1000 维的 numpy.ndarray,但是每当我尝试创建一个 ndarray 来查找最近的单词时,我都会得到一个值错误:
1
|
ValueError: maximum supported dimension for an ndarray is 32, found 1000
|
我可以通过在线查看 32 确实是 ndarray 支持的最大维数 - 那么给出了什么? gensim 如何能够输出 1000 维的 ndarray?
这里是一些示例代码:
1 2 3 4 5 6 7 8 9 10 11 12
|
doc = [model[word] for word in text if word in model.vocab]
out = []
n = len(doc[0]) print(n) print(len(model["hello"])) print(type(doc[0])) for i in range(n):
sum = 0
for d in doc:
sum += d[i]
out.append(sum/n)
out = np.ndarray(out)
|
输出:
1 2 3 4
|
1000 1000 <class 'numpy.ndarray'> ValueError: maximum supported dimension for an ndarray is 32, found 1000
|
这里的目标是计算语料库中所有单词的平均向量,其格式可用于在模型中查找附近的单词,因此欢迎提出任何替代建议。
您正在调用 numpy 的 ndarray() 构造函数,其中包含一个包含 1000 个数字的列表——您手动计算的 1000 个维度中每个维度的平均值。
ndarray() 函数期望它的参数是构造的矩阵的形状,所以它试图创建一个形状为 (d[0], d[1], ..., d[999]) 的新矩阵——然后该矩阵中的每个单独的值都将用1000-int 坐标集。而且,确实 numpy 数组只能有 32 个独立维度。
但是,即使您将提供给 ndarray() 的列表减少到只有 32 个数字,您仍然会遇到问题,因为您的 32 个数字是浮点值,而 ndarray() 期望整数计数。 (你会得到一个 TypeError。)
沿着您尝试采用的方法——这不是我们将在下面介绍的最佳方法——你真的想创建一个具有 1000 个浮点维度的单个向量。也就是说,1000 个类似单元格的值 - 不是 d[0] * d[1] * ... * d[999] 单独的类似单元格的值。
因此,按照您最初的方法的粗略解决方法可能是将您的最后一行替换为:
1 2 3
|
result = np.ndarray(len(d)) for i in range(len(d)):
result[i] = d[i]
|
但是有很多方法可以逐步提高效率、紧凑性和惯用性——我将在下面提到其中的一些方法,尽管最好的方法从根本上来说是不必要的。
首先,您可以使用 Python 的括号索引赋值选项,而不是上面代码中的赋值循环:
1 2
|
result = np.ndarray(len(d))
result[:] = d # same result as previous 3-lines w/ loop
|
但实际上,numpy\\的array()函数本质上可以从给定的列表中创建必要的numpy-native ndarray,所以完全不用ndarray(),你可以只使用array():
1
|
result = np.array(d) # same result as previous 2-lines
|
但进一步,numpy 的许多原生处理数组(和类似数组的列表)的函数已经包括在一个步骤中执行多个向量的平均值的事情(甚至循环都隐藏在里面非常高效的编译代码或 CPU 大容量向量操作)。例如,有一个 mean() 函数可以平均数字列表、数字的多维数组或对齐的向量集等等。
这允许更快、更清晰、单行的方法,可以将整个原始代码替换为以下内容:
1 2 3 4
|
# get a list of available word-vetors
doc = [model[word] for word in text if word in model.vocab] # average all those vectors
out = np.mean(doc, axis=0)
|
(如果没有 axis 参数,它会将所有插槽中的所有单个维度值平均在一起,形成一个最终的平均数。)
- 你是对的,我误解了构造函数的使用。我确实知道 np.mean 但由于我不确定数据类型发生了什么,我尝试手动进行以减少未知数。