【问题标题】:Concise way to declare a numpy matrix声明 numpy 矩阵的简洁方法
【发布时间】:2019-01-07 05:16:59
【问题描述】:

什么是声明每行为[1,2,3,...,999] 的 999x999 numpy 矩阵的简短易读的方法?最终的矩阵应该是:

[[1,2,3,...,999]
[1,2,3,...,999]
...
[1,2,3,...,999]]

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    @jpp 答案很优雅,但以下解决方案更有效:

    res = np.empty((nrows, ncols))
    res[:, :] = np.arange(ncols)
    

    时间:

    %timeit a = np.empty((1000,1000)); a[:, :] = np.arange(1000)
    445 µs ± 9.08 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    %timeit np.tile(range(1000), (1000, 1))
    1.43 ms ± 15.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    进一步的计时测试:

    在@jpp cmets 之后,我直接在 Python 解释器中添加了一项测试(与在 Jupyter 笔记本中运行的原始测试不同,因为它当时已启动并运行):

    >>> import sys
    >>> print(sys.version)
    3.6.5 |Anaconda, Inc.| (default, Apr 26 2018, 08:42:37) 
    [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]
    >>> import numpy as np
    >>> print(np.__version__)
    1.13.3
    >>> import timeit
    >>> t = timeit.repeat('res = np.empty((nrows, ncols)); res[:, :] = np.arange(ncols)', setup='import numpy as np; nrows=ncols=1000', number=100, repeat=50)
    >>> print(min(t), max(t), np.mean(t), np.std(t))
    0.04336756598786451 0.053294404002372175 0.0459639201409 0.00240180447219
    >>> t = timeit.repeat('res = np.tile(range(ncols), (nrows, 1))', setup='import numpy as np; nrows=ncols=1000', number=100, repeat=50)
    >>> print(min(t), max(t), np.mean(t), np.std(t))
    0.05032560401014052 0.05859642301220447 0.0530669655403 0.00225117881195
    

    numpy 1.14.5 的结果几乎相同:

    >>> import sys
    >>> print(sys.version)
    3.6.6 |Anaconda, Inc.| (default, Jun 28 2018, 11:07:29) 
    [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]
    >>> import numpy as np
    >>> print(np.__version__)
    1.14.5
    >>> import timeit
    >>> t = timeit.repeat('res = np.empty((nrows, ncols)); res[:, :] = np.arange(ncols)', setup='import numpy as np; nrows=ncols=1000', number=100, repeat=50)
    >>> print(min(t), max(t), np.mean(t), np.std(t))
    0.04360878499574028 0.05562149798788596 0.04657964294136036 0.0025253372244474614
    >>> t = timeit.repeat('res = np.tile(range(ncols), (nrows, 1))', setup='import numpy as np; nrows=ncols=1000', number=100, repeat=50)
    >>> print(min(t), max(t), np.mean(t), np.std(t))
    0.05024543400213588 0.06169128899637144 0.05339125283906469 0.00276210097759817
    

    【讨论】:

    • 我实际上看到 np.tile 的速度是使用 np.empty (Python 3.6.5 / NumPy 1.14.3) 初始化的版本的两倍。你能建议你的版本吗?
    • empty 版本为 1.41 毫秒,tile 版本为 1.46 毫秒(NumPy 1.15.0、CPython 3.7.0、64 位、python.org macOS 安装程序)。这只是表明,任何关心性能的人都真的需要用他们的实际数据在他们的实际系统上进行测试,而不是把互联网上某些人所说的普遍正确。
    • 为了获得更多乐趣,请尝试使用原生 NumPy 与 NumPyPy 的 PyPy;在其他条件相同的情况下,他们似乎在这里给出了相反的结果。
    • 奇怪的是,你的 Jupyter notebook 需要 3 倍的时间来运行与第二个实现的纯 REPL 相同的代码,特别是因为它与其他实现几乎相同。与其试图猜测原因,我只会坚持“如果重要的话,OP 最好自己测试一下。”
    • @abarnert 我同意
    【解决方案2】:

    你可以使用numpy.tile:

    import numpy as np
    
    res = np.tile(range(10), (5, 1))
    
    print(res)
    
    array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
           [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
           [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
           [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
           [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
    

    或者,您可以添加到零数组:

    res = np.zeros((5, 10)) + range(10)
    

    【讨论】:

    • 哦,这个语法似乎也有效:np.array([[x + 1 for x in range(999)] for y in range (999)]),我只是对print 方法如何输出结果感到困惑,所以我认为我错了(应该检查形状)
    • @riqitang,语法有效,但不推荐。列表推导不是向量化的。您会发现该方法与 NumPy 方法相比效率低下。
    • 这不仅仅是没有向量化的问题:你正在构建一个包含 999 个元素的列表,只需将其转换为数组并将其丢弃。构建这样一个大列表需要时间和内存分配。在非 numpy Python 中,您通常会通过编写代码来使用迭代器来避免这种情况,该迭代器只根据需要一次生成一个新行甚至新单元格。在 numpy 中,您通常通过直接使用 numpy 操作创建数组来避免它。
    • @abarnert,是的,同意了。矢量化是错误的术语。 NumPy 通过预先分配内存来工作,而列表推导会逐渐增加内存分配。 This is a good question 深入了解列表理解内存分配。当然,在构造 NumPy 数组之前需要创建的任何列表都会导致效率低下。
    • @jpp 问题真的不是逐渐增加——分配呈几何级数增加,所以总分配最终只会增加一个很小的常数因子。它首先建立了不必要的列表,这比不做任何事情要慢O(infinity)。 :)
    猜你喜欢
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    相关资源
    最近更新 更多