[python] numpy.array 모양 (R, 1)과 (R,)의 차이점

에서은 numpy, 작업 중 일부는 형태로 반환 (R, 1)하지만 일부 반환 (R,). 이것은 명시 적 reshape으로 요구 되기 때문에 행렬 곱셈을 더 지루하게 만듭니다 . 예를 들어, 행렬이 주어진 M경우 행 수를 numpy.dot(M[:,0], numpy.ones((1, R)))어디 에서 수행 R하려면 열 방향으로 동일한 문제가 발생합니다. 우리는 얻을 것이다 matrices are not aligned이후 오류 M[:,0]모양입니다 (R,)numpy.ones((1, R))모양이다 (1, R).

그래서 내 질문은 :

  1. 모양의 차이 무엇 (R, 1)(R,). 문자 그대로 숫자 목록과 모든 목록에 숫자 만 포함 된 목록 목록이라는 것을 알고 있습니다. 더 쉬운 행렬 곱셈 대신 numpy모양 (R, 1)을 선호하도록 디자인하지 않는 이유가 궁금 (R,)합니다.

  2. 위의 예에 더 좋은 방법이 있습니까? 명시 적으로 다음과 같이 재구성하지 마십시오.numpy.dot(M[:,0].reshape(R, 1), numpy.ones((1, R)))



답변

1. NumPy에서 도형의 의미

“말 그대로 숫자 목록과 모든 목록에 숫자 만 포함되어있는 목록의 목록이라는 것을 알고 있습니다.”라고 생각하면 약간 도움이되지 않습니다.

NumPy와 배열에 대해 생각하는 가장 좋은 방법은 두 부분으로 구성되어 있다는 점이다 데이터 버퍼 단지 원시 요소의 블록 및 인 데이터 버퍼를 해석하는 방법에 대해 설명합니다.

예를 들어, 12 개의 정수 배열을 만드는 경우 :

>>> a = numpy.arange(12)
>>> a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

그런 다음 a데이터 버퍼로 구성되며 다음과 같이 정렬됩니다.

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

데이터를 해석하는 방법을 설명하는보기 :

>>> a.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
>>> a.dtype
dtype('int64')
>>> a.itemsize
8
>>> a.strides
(8,)
>>> a.shape
(12,)

여기서 모양 (12,) 은 배열이 0에서 11까지 실행되는 단일 색인으로 색인화됨을 의미합니다. 개념적으로이 단일 색인에 레이블을 지정 i하면 배열 a은 다음과 같습니다.

i= 0    1    2    3    4    5    6    7    8    9   10   11
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

우리가하면 바꿀 배열을,이 데이터 버퍼를 변경하지 않습니다. 대신, 데이터를 해석하는 다른 방법을 설명하는 새보기를 작성합니다. 그래서 후 :

>>> b = a.reshape((3, 4))

배열은와 b동일한 데이터 버퍼를 a갖지만 이제는 각각 0에서 2, 0에서 3까지 실행 되는 두 개의 인덱스로 인덱스됩니다. 우리는 두 개의 인덱스 라벨 경우 ij, 배열 b과 같은 모양을 :

i= 0    0    0    0    1    1    1    1    2    2    2    2
j= 0    1    2    3    0    1    2    3    0    1    2    3
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

의미하는 것은:

>>> b[2,1]
9

두 번째 인덱스가 빠르게 변경되고 첫 번째 인덱스가 느리게 변경되는 것을 볼 수 있습니다. 이것을 다른 방식으로 선호하는 경우 order매개 변수를 지정할 수 있습니다 .

>>> c = a.reshape((3, 4), order='F')

그러면 다음과 같이 색인이 생성 된 배열이 생성됩니다.

i= 0    1    2    0    1    2    0    1    2    0    1    2
j= 0    0    0    1    1    1    2    2    2    3    3    3
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

의미하는 것은:

>>> c[2,1]
5

이제 배열의 크기가 1 이상인 모양을 갖는 것이 무엇을 의미하는지 분명해야합니다.

>>> d = a.reshape((12, 1))

배열 d은 두 개의 인덱스로 인덱스되며 첫 번째 인덱스는 0에서 11까지이며 두 번째 인덱스는 항상 0입니다.

i= 0    1    2    3    4    5    6    7    8    9   10   11
j= 0    0    0    0    0    0    0    0    0    0    0    0
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

그래서 :

>>> d[10,0]
10

길이 1의 차원은 “무료”(어떤 의미에서), 그래서 당신이 도시에가는 것을 막을 수있는 것은 없습니다 :

>>> e = a.reshape((1, 2, 1, 6, 1))

다음과 같이 색인이 생성 된 배열을 제공합니다.

i= 0    0    0    0    0    0    0    0    0    0    0    0
j= 0    0    0    0    0    0    1    1    1    1    1    1
k= 0    0    0    0    0    0    0    0    0    0    0    0
l= 0    1    2    3    4    5    0    1    2    3    4    5
m= 0    0    0    0    0    0    0    0    0    0    0    0
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

그래서 :

>>> e[0,1,0,0,0]
6

참고 항목 NumPy와 내부 문서 배열 구현하는 방법에 대한 자세한 내용을.

2. 무엇을해야합니까?

때문에 numpy.reshape단지 새로운 뷰를 작성, 당신은 필요할 때마다 그것을 사용하는 방법에 대해 두려워해서는 안된다. 배열을 다른 방식으로 인덱싱하려는 경우 사용하는 올바른 도구입니다.

그러나 계산 시간이 길면 일반적으로 처음에 “올바른”모양으로 배열을 구성 할 수 있으므로 모양 변경 및 조옮김 횟수를 최소화 할 수 있습니다. 그러나 실제 상황을 보지 않으면 서 재구성해야 할 필요성이 무엇인지, 변경해야 할 것을 말하기는 어렵습니다.

귀하의 질문에 예는 다음과 같습니다

numpy.dot(M[:,0], numpy.ones((1, R)))

그러나 이것은 현실적이지 않습니다. 먼저,이 표현은 :

M[:,0].sum()

더 간단하게 결과를 계산합니다. 둘째, 실제로 열 0에 특별한 것이 있습니까? 아마도 실제로 필요한 것은 다음과 같습니다.

M.sum(axis=0)


답변

의 차이 (R,)와는 (1,R)그대로 사용할 필요가 인덱스의 수입니다. ones((1,R))행이 하나만있는 2 차원 배열입니다. ones(R)벡터입니다. 일반적으로 변수에 둘 이상의 행 / 열이있는 것이 이치에 맞지 않으면 단일 크기의 행렬이 아닌 벡터를 사용해야합니다.

특정한 경우에는 몇 가지 옵션이 있습니다.

1) 두 번째 인수를 벡터로 만드십시오. 다음은 잘 작동합니다.

    np.dot(M[:,0], np.ones(R))

2) 매트릭스 작업과 같은 MATLAB을 원하면 matrix대신 클래스 를 사용하십시오 ndarray. 모든 수학은 2 차원 배열이되어야하며 연산자 *는 요소 단위 대신 행렬 곱셈을 수행하므로 점이 필요하지 않습니다. 내 경험상, 이것은 가치가있는 더 많은 문제이지만 matlab에 익숙하다면 좋을 수도 있습니다.


답변

모양은 튜플입니다. 1 차원 만있는 경우 모양은 하나의 숫자이며 쉼표 뒤에 공백이됩니다. 2+ 차원의 경우 모든 쉼표 뒤에 숫자가 있습니다.

# 1 dimension with 2 elements, shape = (2,). 
# Note there's nothing after the comma.
z=np.array([  # start dimension
    10,       # not a dimension
    20        # not a dimension
])            # end dimension
print(z.shape)

(2,)

# 2 dimensions, each with 1 element, shape = (2,1)
w=np.array([  # start outer dimension 
    [10],     # element is in an inner dimension
    [20]      # element is in an inner dimension
])            # end outer dimension
print(w.shape)

(2,1)


답변

기본 배열 클래스의 경우 2d 배열은 1d 또는 3d 배열보다 더 특별하지 않습니다. 치수를 유지하는 일부 작업이 있으며, 일부는 크기를 줄이거 나, 다른 조합을 사용하거나 확장합니다.

M=np.arange(9).reshape(3,3)
M[:,0].shape # (3,) selects one column, returns a 1d array
M[0,:].shape # same, one row, 1d array
M[:,[0]].shape # (3,1), index with a list (or array), returns 2d
M[:,[0,1]].shape # (3,2)

In [20]: np.dot(M[:,0].reshape(3,1),np.ones((1,3)))

Out[20]:
array([[ 0.,  0.,  0.],
       [ 3.,  3.,  3.],
       [ 6.,  6.,  6.]])

In [21]: np.dot(M[:,[0]],np.ones((1,3)))
Out[21]:
array([[ 0.,  0.,  0.],
       [ 3.,  3.,  3.],
       [ 6.,  6.,  6.]])

동일한 배열을 제공하는 다른 표현식

np.dot(M[:,0][:,np.newaxis],np.ones((1,3)))
np.dot(np.atleast_2d(M[:,0]).T,np.ones((1,3)))
np.einsum('i,j',M[:,0],np.ones((3)))
M1=M[:,0]; R=np.ones((3)); np.dot(M1[:,None], R[None,:])

MATLAB은 2D 배열로 시작했습니다. 최신 버전에서는 더 많은 차원이 허용되지만 하한은 2로 유지됩니다. 그러나 행 행렬과 열의 차이 (형상 (1,3)v 와의 차이)에 여전히주의를 기울여야합니다 (3,1). 얼마나 자주 글을 썼 [1,2,3].'습니까? 나는 쓰기로가는 row vectorcolumn vector하지만 2D 제약 조건, MATLAB에서 어떤 벡터가 없습니다 – 이상하지 1D 인 것으로 벡터의 수학적 의미에서.

당신이 봤어 np.atleast_2d(또한 _1d 및 _3d 버전)?


답변

1) (R, 1)오버 형태를 선호하지 않는 이유 (R,)는 불필요하게 복잡하게 만들기 때문입니다. 게다가, (R, 1)길이 -R 벡터 대신에 기본적으로 모양을 갖는 것이 왜 바람직 (1, R)할까요? 추가 치수가 필요할 때 간단하고 명시 적으로 유지하는 것이 좋습니다.

2) 예를 들어 외부 제품을 계산하므로 다음 reshape을 사용하여 전화 하지 않고이 작업을 수행 할 수 있습니다 np.outer.

np.outer(M[:,0], numpy.ones((1, R)))


답변

여기에 이미 많은 좋은 답변이 있습니다. 그러나 나를 위해 모양이나 배열이 모든 프로그램을 중단 할 수있는 몇 가지 예를 찾기가 어려웠습니다.

여기에 하나가 있습니다 :

import numpy as np
a = np.array([1,2,3,4])
b = np.array([10,20,30,40])


from sklearn.linear_model import LinearRegression
regr = LinearRegression()
regr.fit(a,b)

오류와 함께 실패합니다.

ValueError : 예상 2D 배열, 대신 1D 배열을 얻음

그러나 우리가 다음에 추가 reshape하면 a:

a = np.array([1,2,3,4]).reshape(-1,1)

이것은 올바르게 작동합니다!


답변