-
[numpy] axis, rank 이해. (n,)와(n,1)의 차이. keepdimsMachine Learning/numpy & pandas & maplotlib 2023. 9. 5. 19:35
이전 글에서 선형대수 관련 강의 영상을 정리했었는데, 기본 용어들이 헷갈려서 정리해봤다.
* Rank (=basis의 개수)
더보기"랭크(Rank)"는 행렬의 중요한 개념 중 하나입니다. 랭크는 주어진 행렬의 열 벡터(또는 행 벡터)들 중 독립적인 벡터의 최대 개수를 나타내며, 이 개수는 해당 행렬의 열(또는 행) 공간의 차원을 나타냅니다.
- 독립적인 벡터의 최대 개수: 랭크는 행렬 내의 열 벡터(또는 행 벡터) 중 서로 독립적인 벡터의 최대 개수를 나타냅니다. 벡터가 서로 독립적이라는 것은 어떤 한 벡터를 다른 벡터들의 선형 조합으로 나타낼 수 없다는 것을 의미합니다.
- 열 공간의 차원: 랭크는 해당 행렬의 열 벡터가 구성하는 열 공간(column space)의 차원을 나타냅니다. 열 공간은 벡터들이 생성하는 부분 공간(subspace)이며, 행렬의 랭크는 이 부분 공간의 차원을 나타냅니다.
- 행 공간의 차원: 랭크는 행렬의 행 벡터들 중 독립적인 행 벡터의 최대 개수를 나타내며, 이는 행렬의 행 공간(row space)의 차원을 나타냅니다. 행 공간은 열 공간과 동일한 차원을 가지며, 따라서 랭크는 열과 행 모두에 대한 중요한 정보를 제공합니다.
- 가우스 소거법과의 관련: 랭크는 가우스 소거법을 사용하여 행렬을 간단하게 변환하고 해를 찾는 데 사용됩니다. 랭크가 행렬 내의 영(zero)인 행이나 열의 개수와 관련이 있습니다.
랭크는 다양한 수학적 응용 분야에서 중요한 역할을 합니다. 예를 들어 선형 방정식의 해를 찾는 데, 데이터의 차원 축소에 사용되며, 행렬의 특성을 분석하는 데 도움이 됩니다.
-chatGPT-
* 행벡터와 열벡터의 Rank는 항상 같다. ( 간단한 증명)
더보기정리 증명:
주어진 행렬 A와 그 전치 행렬 A^T에 대한 랭크를 비교하기 위해 우리는 다음 세 가지 사실을 이용합니다:
- 열 랭크(column rank): 행렬 A와 전치 행렬 A^T는 동일한 열 랭크를 갖습니다. 즉, A의 열 랭크와 A^T의 열 랭크는 같습니다.
- 행 랭크(row rank): 행렬 A와 전치 행렬 A^T는 동일한 행 랭크를 갖습니다. 즉, A의 행 랭크와 A^T의 행 랭크는 같습니다.
- 행과 열 랭크 관계: 어떤 행렬의 열 랭크는 항상 그 행렬의 행 랭크와 같거나 작을 수 있지만, 랭크의 경우 열과 행 사이의 랭크에 대한 관계는 바뀌지 않습니다. 따라서 A의 열 랭크와 A^T의 행 랭크는 같습니다.
이 세 가지 사실을 종합하면 행렬 A의 랭크와 A^T의 랭크가 동일함을 알 수 있습니다. 따라서 "행렬의 랭크는 그 전치 행렬의 랭크와 같다"라는 정리가 성립합니다.
좀 더 자세한 증명은 아래 참고:
* vector space(벡터 공간)에 대한 설명
더보기벡터 공간(Vector Space), 또는 벡터 공간은 선형 대수학에서 다음과 같이 정의되는 수학적인 구조입니다:
벡터 공간(또는 벡터 공간)은 두 개의 연산, 즉 벡터 덧셈과 스칼라 곱셈에 대한 다음의 조건을 만족하는 벡터들의 집합입니다.
벡터 공간의 정의는 다음과 같은 요소로 구성됩니다:
- 벡터 집합: 벡터 공간은 벡터들의 집합입니다. 이러한 벡터들은 다양한 수의 구성 요소를 가질 수 있으며, 이러한 구성 요소를 사용하여 벡터를 나타냅니다. 예를 들어, 2차원 벡터 (x, y)는 두 개의 구성 요소 x와 y로 구성됩니다.
- 벡터 덧셈(Addition): 벡터 공간 내의 모든 벡터는 다른 벡터와 더할 수 있어야 합니다. 벡터 덧셈은 벡터 공간 내의 두 벡터를 합치는 연산입니다.
- 스칼라 곱셈(Scalar Multiplication): 벡터 공간 내의 모든 벡터는 스칼라(실수나 복소수)와 곱할 수 있어야 합니다. 스칼라 곱셈은 벡터에 스칼라를 곱하는 연산입니다.
- 연산에 대한 폐쇄성(Closure under Operations): 벡터 덧셈과 스칼라 곱셈 연산은 벡터 공간 내에서 닫혀 있어야 합니다. 즉, 두 벡터를 더하거나 스칼라와 곱한 결과는 여전히 같은 벡터 공간에 속해야 합니다.
- 영 벡터(Zero Vector): 벡터 공간은 영 벡터(원점)를 포함해야 합니다. 영 벡터는 어떤 벡터에 더하면 그 벡터를 변화시키지 않는 벡터입니다.
- 역원(Additive Inverse): 각 벡터는 벡터 덧셈에 대한 역원(역 벡터 또는 부정 벡터)을 가져야 합니다. 이것은 어떤 벡터에 더했을 때 영 벡터를 생성하는 벡터를 의미합니다.
* basis(기저 벡터)와 dimension(차원)
기저벡터는 한 공간을 구성할 수 있는 벡터 집합이고, 기저 벡터의 개수를 차원(dimension)이라고 부른다. 4차원 공간을 구성하는데 4개의 기저벡터가 필요하다는 의미.
* vector subspace(부분공간)
부분공간(vector subspace)는 전체 공간(vector space)의 일부분. 예를 들어 4개의 기저벡터가 있다면, 4개의 기저벡터로 만들 수 있는 공간을 전체 벡터공간이라고 하고, 기저 벡터 4개 중 4,3,2,1개로 만들 수 있는 공간을 부분 공간이라고 한다.(자기 자신도 포함)
Ax=0을 만족하는 벡터 x의 집합이다.
* span(생성)
전체 dimension이 5차원이고, 3개의 기저 벡터의 unique집합을 S라고 하고, 집합 S에 속하는 기저 벡터들로 구성되는 3차원 부분 공간을 W라고 했을 때, S는 부분 공간 W를 span한다고 말하고, W=span(S)라고 표현한다.
S = {w1, w2, ..., wn}가 벡터공간 V내의 공집합이 아닌 벡터 집합이라면
(a) S 내의 벡터들의 가능한 모든 일차결합의 집합 W는 V의 부분공간이다.
(b) 위의 집합 W는 S내의 모든 벡터를 포함하는 V의 가장 작은 부분공간이다. 즉, 이들 벡터를 포함하는 또 다른 임의의 부분공간은 W를 포함한다.
공집합이 아닌 집합 S내의 벡터들의 가능한 모든 일차결합으로 이루어진, 벡터공간 V의 부분공간을 S의 생성(span of S)이라 부르며, S 내의 벡터는 부분공간을 생성(span)한다고 합니다.
즉, S={w1, w2, ..., wn}이면, S의 생성은 다음과 같이 표현합니다.
span(S) 또는 각 원소들을 표시하면 span{w1, w2,..., wn}
출처 링크* Rank
- Rank : 어떤 행렬 A의 랭크는 해당 행렬의 열벡터에 의해 span된 벡터공간의 차원
- A가 n by m 행렬이라고 하면 아래가 성립한다.(n은 열 수, m은 행 수)
n=rank(A)+nullity(A)
m=rank(A.T)+nullity(A.T) - n=rank(A), 혹은 m=rank(A.T)일때 풀 랭크(full rank)라고 한다.
* (n,)와 (n,1)의 차이
넘파이에서 shape을 찍어보면 (n,)와 (n,1)의 형태가 나오는데, 리스트 형태에 따른 해석과, 선형대수학적인 관점에서의 해석으로 나누어서 설명하겠다.
먼저 선형대수학적 관점으로 보면,
(n,)은 vector space(전체 공간)이 1차원인 공간의 벡터이다.
(n,1)은 vector space(전체 공간)이 2차원인 공간의 1차원인 vector subspace(부분 공간)에 있는 벡터이다.
리스트 표현식으로 보면,
(n,)은 1중 리스트이다. 예 ) arr = [ 1, 2, 3]
(n,1)은 2중 리스트이다. 예) arr = [[1, 2, 3]]
* axis
axis(축)은 vector subspace가 아닌 vector space(전체 공간)의 축들을 말한다.
axis(축)은 standard basis(표준기저벡터)들의 방향과 일치한다고 말할 수 있다.
y=np.array([[1,2,3]]) print(y) print("sahpe:",y.shape) print("rank:",np.linalg.matrix_rank(y)) print("axis=0, sum:",np.sum(y,axis=0)) print("axis=1, sum:",np.sum(y,axis=1)) ------------------------------------- [[1 2 3]] sahpe: (1, 3) rank: 1 axis=0, sum: [1 2 3] # y축 axis=1, sum: [6] # x축
arr1=np.array([[[1,2,3]], [[4,5,6]], [[7,8,9]], [[6,5,4]]]) arr2=np.array([[[1,2,3]], [[6,5,4]], [[7,8,9]], [[6,5,5]]]) print((arr1==arr2).shape) print(np.all(arr1==arr2, axis=0)) print(np.all(arr1==arr2, axis=1)) print(np.all(arr1==arr2, axis=2)) ------------------------------------- (4, 1, 3) # axis=0 [[False True False]] # axis=1 [[ True True True] [False True False] [ True True True] [ True True False]] # axis=2 [[ True] [False] [ True] [False]]
x,y,z축 개념으로 이해하는 영상이긴 하지만, 고차원으로 가면 상상이 안 되므로 아래와 같은 방식을 함께 고려하자.
* keepdims
sum과 같은 연산에서 axis 파라미터를 사용하게 되면, vector space가 줄어든다. 차원을 유지하기 위해 사용하는 파라미터가 keepdims=True이다. 차원을 유지하는 것은 딥러닝에서 중요하다. 예를들어 2차원에 경우 sum의 축 연산시 1차원 스칼라 값으로 바뀌게 된다. 이후 np.dot() 내적을 수행하게 되면 차원이 달라서 오류가 발생할 수 있기 때문에, 차원을 유지해주는 것이 중요하다.
# 예시1) arr=np.array([[[1,2,3]], [[1,2,3]], [[1,2,3]], [[1,2,3]]]) print(np.sum(arr, axis=0)) print(np.sum(arr, axis=1)) print(np.sum(arr, axis=2)) print(np.sum(arr, axis=2, keepdims=True)) ---------------------------------- # axis=0, z축 [[ 4 8 12]] # axis=1, y축 [[1 2 3] [1 2 3] [1 2 3] [1 2 3]] # axis=2, x축 [[6] [6] [6] [6]] # axis=2, x축, keepdims=True [[[6]] [[6]] [[6]] [[6]]]
# 예시2) arr1=np.array([[[1,1,1], [2,2,2]], [[3,3,3], [4,4,4]], [[5,5,5], [6,6,6]], [[7,7,7], [8,8,8]]]) print(np.sum(arr, axis=0)) print(np.sum(arr, axis=1)) print(np.sum(arr, axis=2)) print(np.sum(arr, axis=2, keepdims=True)) print(np.linalg.matrix_rank(arr)) ------------------------------------------- # axis=0, z축 [[16 16 16] [20 20 20]] # axis=1, y축 [[ 3 3 3] [ 7 7 7] [11 11 11] [15 15 15]] # axis=2, x축 [[ 3 6] [ 9 12] [15 18] [21 24]] # axis=2, x축, keepdims=True [[[ 3] [ 6]] [[ 9] [12]] [[15] [18]] [[21] [24]]]
* axis=0
더보기# z축 sum() print(['B', 'G', 'R']) x=np.full((4, 5, 3), 255, dtype=np.uint8) print(x) print(np.sum(x, axis=0)) print(x.shape) ------------------------------------------------- ['B', 'G', 'R'] [[[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]] [[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]] [[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]] [[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]]] # axis=0, sum [[1020 1020 1020] [1020 1020 1020] [1020 1020 1020] [1020 1020 1020] [1020 1020 1020]] (4, 5, 3)
* axis=1
더보기print(['B', 'G', 'R']) x=np.full((4, 5, 3), 255, dtype=np.uint8) print(x) print(np.sum(x, axis=1)) print(x.shape) ---------------------------------------- ['B', 'G', 'R'] [[[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]] [[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]] [[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]] [[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]]] # axis=1, sum [[1275 1275 1275] [1275 1275 1275] [1275 1275 1275] [1275 1275 1275]] (4, 5, 3)
* axis=2
더보기print(['B', 'G', 'R']) x=np.full((4, 5, 3), 255, dtype=np.uint8) print(x) print(np.sum(x, axis=2)) print(x.shape) ---------------------------------------- ['B', 'G', 'R'] [[[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]] [[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]] [[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]] [[255 255 255] [255 255 255] [255 255 255] [255 255 255] [255 255 255]]] # axis=2, sum [[765 765 765 765 765] [765 765 765 765 765] [765 765 765 765 765] [765 765 765 765 765]] (4, 5, 3)
axis가 커질수록 계산 구역이 리스트의 안쪽으로 들어간다. 리스트의 가장 안쪽이 x축 가장 바깥쪽이 z축이다.
* 참고
'Machine Learning > numpy & pandas & maplotlib' 카테고리의 다른 글
[NumPy] type()과 dtype, np.sum()과 np.multiply() (0) 2023.10.03 [NumPy] np.pad에 대한 이해 (0) 2023.10.03 [Pandas#1] Pandas 기초 (0) 2023.08.05 [NumPy] np.where() (0) 2023.08.04 [NumPy] np.random.rand(), RandomState(), randn(), randint(), random(), normal()정리 (0) 2023.08.04