我有一个字典列表,其值始终为整数,并为一些字符串加键。我们可以将其解释为一个矩阵,其中每个字典都是一行,每列对应于至少属于一个字典的键。字典代表多项式,其中键是单项式,值是系数。
例如,[{'x':1, 'y':1, 'z':2}, {'x': 2}, {'y':1, 'z':3}]
对应于矩阵:
[ 1 1 2,
2 0 0,
0 1 3 ]
我经常执行此操作,因此需要高性能的解决方案。矩阵不是很大,因此我需要一个最小化开销的解决方案。当前,一些计算在字典的向量化上花费了大约三分之一的时间。
这基本上对应于sklearn.feature_extraction.DictVectorizer
。我正在使用sagemath,它不随sci-kit learning一起提供,因此使用它不是理想的选择。此外,DictVectorizer
建立一个稀疏矩阵,然后将其变成一个密集矩阵。我自己尝试了这种方法,但由于额外的大量开销,结果证明它比较慢。
我当前的算法如下:
def dictionary_vectorizer(list_of_dicts):
# Make a list of all the keys occurring in the dictionaries
keys = set()
for dic in list_of_dicts:
for key in dic.keys():
keys.add(key)
# Create a mapping keys -> column_index
key_map = {key: index for index, key in enumerate(keys)}
output = np.zeros((len(list_of_dicts), len(keys)))
for row_number, dic in enumerate(list_of_dicts):
for key, value in dic.items():
output[row_number, key_map[key]] = value
return output
在我的实际代码中,我使用了sagemath的matrix
构造函数,而不是np.zeros,但是它并没有太大变化。似乎初始化一个零矩阵,然后编辑行并不是最快的方法。逐行计算矩阵,然后将结果连接在一起,速度相同。
是否有明显的方法可以加快此过程(同时保持较低的开销)?
答案 0 :(得分:0)
根据问题的这一部分,是否:
这基本上对应于
sklearn.feature_extraction.DictVectorizer
。 我正在使用sagemath,它不随sci-kit learning一起提供,所以使用 这不理想。
希望将scikit-learn安装到SageMath中,然后根据 关于Sage的安装方式,可以在终端上运行就足够了:
$ sage --pip install scikit-learn
然后可以在Sage中执行以下操作:
sage: data = [{'x':1, 'y':1, 'z':2}, {'x':2}, {'y':1, 'z':3}]
sage: data
[{'x': 1, 'y': 1, 'z': 2}, {'x': 2}, {'y': 1, 'z': 3}]
sage: from sklearn.feature_extraction import DictVectorizer
sage: v = DictVectorizer(dtype=int, sparse=False)
sage: X = v.fit_transform(data)
sage: print(X)
[[1 1 2]
[2 0 0]
[0 1 3]]
如果目标只是为了加快问题代码的速度, 跳过键到列索引映射的创建 可能会使速度稍快一些,尽管速度不是很大。
def dictionary_vectorizer(list_of_dicts):
# List all keys occurring in the dictionaries
keys = set(key for dic in list_of_dicts for key in dic)
# Initialize zero array of correct shape
output = np.zeros((len(list_of_dicts), len(keys)))
# Set nonzero entries
for row_number, dic in enumerate(list_of_dicts):
for col_number, key in enumerate(keys):
if key in dic:
output[row_number, col_number] = dic[key]
return output
如果该函数应用于大量数据 共享相同的单项式命题,这可能对 分开检测按键。
可以想到重用相同的数组,并将其传递 作为参数,以节省创建新产品的成本 numpy数组。不确定是否会有所帮助。
如果限制使用词典列表,则可能 还可以考虑更改数据生产步骤。
Cython或Pythran可能有助于进一步加快速度。