복붙노트

[PYTHON] 수십 개의 배열을 가로 지르는 곱셈

PYTHON

수십 개의 배열을 가로 지르는 곱셈

저는 2D 배열의 각 항에 1D 배열의 해당 항을 곱하려고합니다. numpy.multiply 함수에서 볼 수 있듯이 모든 열에 1D 배열을 곱하면 매우 쉽습니다. 그러나 나는 그 반대를하고 행의 각 단어를 곱하고 싶다. 다른 말로하면 나는 번식하고 싶다.

[1,2,3]   [0]
[4,5,6] * [1]
[7,8,9]   [2]

그리고 얻다

[0,0,0]
[4,5,6]
[14,16,18]

하지만 대신 나는

[0,2,6]
[0,5,12]
[0,8,18]

numpy로 할 수있는 우아한 방법이 있는지 아는 사람 있습니까? 고마워. 알렉스

해결법

  1. ==============================

    1.당신이 보여준 것과 같은 일반적인 곱셈은 :

    당신이 보여준 것과 같은 일반적인 곱셈은 :

    >>> import numpy as np
    >>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
    >>> c = np.array([0,1,2])
    >>> m * c
    array([[ 0,  2,  6],
           [ 0,  5, 12],
           [ 0,  8, 18]])
    

    축을 추가하면 원하는 방식으로 축이 확대됩니다.

    >>> m * c[:, np.newaxis]
    array([[ 0,  0,  0],
           [ 4,  5,  6],
           [14, 16, 18]])
    

    두 번 트랜스 포즈 할 수도 있습니다.

    >>> (m.T * c).T
    array([[ 0,  0,  0],
           [ 4,  5,  6],
           [14, 16, 18]])
    
  2. ==============================

    2.행렬 곱셈 (일명 곱법)을 사용할 수도 있습니다.

    행렬 곱셈 (일명 곱법)을 사용할 수도 있습니다.

    a = [[1,2,3],[4,5,6],[7,8,9]]
    b = [0,1,2]
    c = numpy.diag(b)
    
    numpy.dot(c,a)
    

    어느 쪽이 더 우아한가는 아마도 맛의 문제 일 것입니다.

  3. ==============================

    3.또 다른 트릭 (v1.6 현재)

    또 다른 트릭 (v1.6 현재)

    A=np.arange(1,10).reshape(3,3)
    b=np.arange(3)
    
    np.einsum('ij,i->ij',A,b)
    

    나는 numpy 방송 (newaxis)에 능숙하지만, 나는이 새로운 einsum 도구에 대한 나의 길을 찾고있다. 그래서이 해결책을 찾기 위해 조금 놀았습니다.

    타이밍 (Ipython timeit 사용) :

    einsum: 4.9 micro
    transpose: 8.1 micro
    newaxis: 8.35 micro
    dot-diag: 10.5 micro
    

    덧붙여서, i를 j로 변경하면, np.einsum ( 'ij, j-> ij', A, b)은 Alex가 원하지 않는 행렬을 생성합니다. 그리고 np.einsum ( 'ji, j-> ji', A, b)은 사실상 이중 전치 연산자입니다.

  4. ==============================

    4.나는 스피드에 대한 다른 옵션들을 비교해 보았는데 놀랍게도 많은 것들이 (diag를 제외하고) 똑같이 빠르다는 것을 알았다. 나는 개인적으로 사용한다.

    나는 스피드에 대한 다른 옵션들을 비교해 보았는데 놀랍게도 많은 것들이 (diag를 제외하고) 똑같이 빠르다는 것을 알았다. 나는 개인적으로 사용한다.

    A * b[:, None]
    

    (또는 (A.T * b) .T) 짧습니다.

    플롯을 재현하는 코드 :

    import numpy
    import perfplot
    
    
    def newaxis(data):
        A, b = data
        return A * b[:, numpy.newaxis]
    
    
    def none(data):
        A, b = data
        return A * b[:, None]
    
    
    def double_transpose(data):
        A, b = data
        return (A.T * b).T
    
    
    def double_transpose_contiguous(data):
        A, b = data
        return numpy.ascontiguousarray((A.T * b).T)
    
    
    def diag_dot(data):
        A, b = data
        return numpy.dot(numpy.diag(b), A)
    
    
    def einsum(data):
        A, b = data
        return numpy.einsum("ij,i->ij", A, b)
    
    
    perfplot.save(
        "p.png",
        setup=lambda n: (numpy.random.rand(n, n), numpy.random.rand(n)),
        kernels=[
            newaxis,
            none,
            double_transpose,
            double_transpose_contiguous,
            diag_dot,
            einsum,
        ],
        n_range=[2 ** k for k in range(14)],
        logx=True,
        logy=True,
        xlabel="len(A), len(b)",
    )
    
  5. ==============================

    5.너 왜 그래?

    너 왜 그래?

    >>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
    >>> c = np.array([0,1,2])
    >>> (m.T * c).T
    

    ??

  6. from https://stackoverflow.com/questions/18522216/multiplying-across-in-a-numpy-array by cc-by-sa and MIT license