【问题标题】:Fastest way to fill a scipy.sparse.dok_matrix填充 scipy.sparse.dok_matrix 的最快方法
【发布时间】:2020-12-11 12:00:57
【问题描述】:

根据输入列表填充 scipy.sparse.dok_matrix 的最有效方法是什么?

dok_matrix 中的列数或行数都不知道。

行数是输入列表的长度,列数取决于输入列表中的值。

显而易见的:

def get_dok_matrix(values: List[Any]) -> scipy.sparse.dok_matrix:
    max_cols = 0
    datas = []
    for value in values:
        data = get_data(values)
        datas.append(data)
        if len(data) > max_cols:
            max_cols = len(data)
    dok_matrix = scipy.sparse.dok_matrix((len(values), max_cols))
    for i, data in enumerate(datas):
        for j, datum in enumerate(data):
            dok_matrix[i, j] = datum
    return dok_matrix

有两个 for 循环,一个嵌套 for 循环,还有许多 len() 检查。我无法想象这会非常有效。

我也考虑过:

def get_dok_matrix(values: List[Any]) -> scipy.sparse.dok_matrix:
    cols = 0
    dok_matrix = scipy.sparse.dok_matrix((0, 0))
    for row, value in enumerate(values):
        dok_matrix.resize(row + 1, cols)
        data = get_data(values)
        for col, datum in enumerate(data):
            if col + 1 > cols:
                cols = col + 1
                dok_matrix.resize(row + 1, cols)
            dok_matrix[row, col] = datum
    return dok_matrix

这在很大程度上取决于scipy.sparse.dok_matrix.resize 的效率,我在文档中找不到。

哪一个最有效?

有没有更好的方法让我错过(也许我可以 O(1) 一次设置一整行?)?

【问题讨论】:

  • 改用coo 格式怎么样?
  • @hpaulj 为什么会更好?
  • dok 可以迭代赋值(lil 也是如此),coo 是原始输入格式,如果您可以从数组或列表构建 data, row, col 数组,则效果很好.使用coo 格式,您可以创建 3 个数组,并且只需调用一次coo_matrix(或csr)。它还负责识别最大行和列值。
  • 我对矩阵的布局感到困惑。你说values是一个列表;什么清单?你迭代values,但不要使用value。相反,您使用data = get_data(values)。每行有多少个数据值? j 枚举建议您填充该行的第一个 n 元素。

标签: python python-3.x numpy scipy


【解决方案1】:

与:

def get_dok_matrix(values):
    max_cols = 0
    datas = []
    for value in values:
        data = value         # changed
        datas.append(data)
        if len(data) > max_cols:
            max_cols = len(data)
    dok_matrix = sparse.dok_matrix((len(values), max_cols))
    for i, data in enumerate(datas):
        for j, datum in enumerate(data):
            dok_matrix[i, j] = datum
    return dok_matrix

In [13]: values = [[1],[1,2],[1,2,3],[4,5,6,7],[8,9,10,11,12]]
In [14]: dd = get_dok_matrix(values)
In [15]: dd
Out[15]: 
<5x5 sparse matrix of type '<class 'numpy.float64'>'
    with 15 stored elements in Dictionary Of Keys format>
In [16]: dd.A
Out[16]: 
array([[ 1.,  0.,  0.,  0.,  0.],
       [ 1.,  2.,  0.,  0.,  0.],
       [ 1.,  2.,  3.,  0.,  0.],
       [ 4.,  5.,  6.,  7.,  0.],
       [ 8.,  9., 10., 11., 12.]])

我希望您提供一个 values 示例,这样我就不必研究您的代码并创建一个可以使用它的代码。

制作coo 格式:

def get_coo_matrix(values):
    data, row, col = [],[],[]
    for i,value in enumerate(values):
        n = len(value)
        data.extend(value)
        row.extend([i]*n)
        col.extend(list(range(n)))
    return sparse.coo_matrix((data,(row,col)))

In [18]: M = get_coo_matrix(values)
In [19]: M
Out[19]: 
<5x5 sparse matrix of type '<class 'numpy.int64'>'
    with 15 stored elements in COOrdinate format>
In [20]: M.A
Out[20]: 
array([[ 1,  0,  0,  0,  0],
       [ 1,  2,  0,  0,  0],
       [ 1,  2,  3,  0,  0],
       [ 4,  5,  6,  7,  0],
       [ 8,  9, 10, 11, 12]])

次:

In [22]: timeit dd = get_dok_matrix(values)
431 µs ± 10.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [23]: timeit M = get_coo_matrix(values)
152 µs ± 524 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    • 2019-12-25
    • 2011-02-23
    • 2013-11-18
    • 1970-01-01
    相关资源
    最近更新 更多