투명한 기부를 하고싶다면 이 링크로 와보세요! 🥰 (클릭!)
바이낸스(₿) 수수료 평생 20% 할인받는 링크로 가입하기! 🔥 (클릭!)
아직 assignment 1 까지만 커버되고 2 3 용은 충분히 둘러보지 못했어요.
그치만 아래 함수들만 가지고도 기본적인 부분은 충분히 커버 될 것 같아요.
힘든 함수를 써야하면 assignment에 HINT!! 라고 되어 있으니까 그부분 참고하시면 좋지 않을까 싶습니다.
기본 함수들
* 과 dot
matrix a와 matrix b가 있다고 하자
이때, a*b는 element-wise product를 반환하며,
a.dot(b) 혹은 np.dot(a,b)는 둘간의 내적을 반환한다.
linalg.norm (norm 구해주는 함수)
numpy array of shape (DY, D) 가 있고 (이 변수는 X)
numpy array of shape (DX, D) 가 있고 (이 변수는 X_train)
X와 X_train간의 차이를 구하고 싶다면 어떻게 하면 될까?
dists[i , j] 에 i번째 y와 j번째 x에 대한 pairwise distance를 넣어주자.
for i in range(DY):
for j in range(DX):
dists[i , j] = np.linalg.norm(X_train[j] - X[i])

모든 element마다 차이를 계산 해 주었고, 이를 유클리디안 거리를 자동으로 구한 결과가 착 착 들어간다.
(ord라는 옵션은 차수라서 L1 norm을 구하고 싶으면 ord = 1 을 써주면 된다)
이것을 1차 for문으로 줄여보자
for i in range(DY):
dists[i, :] = np.linalg.norm( (X_train - X[i]) , axis = -1 )
이것은 axis = -1인 이유가, X_train의 경우 DX, D를 가지고 있고
X[i]는 D를 가지고 있기 때문에 numpy가 알아서 빼주기 때문에 뺄셈 후의 결과는 DX, D가 된다.
이 상태에서 np.linalg.norm을 적용시켜주면 D라는 차원을 (axis = -1인 이유는 맨 마지막 차원인 D를 합쳐버리란 뜻) 합쳐서 DX차원만 남게 된다.
결국, DX 차원의 배열을 DY번 착착 쌓아놓음으로 인해서 결론적으로 예쁘게 구현할 수 있게 된다.
그럼 포문 없이도 될까?
a-b = sqrt(a*a+b*b-2ab) 임을 사용해서
dists = np.sqrt(np.sum(X**2, axis=1).reshape(DY, 1) + np.sum(X_train**2, axis=1) - 2 * X.dot(self.X_train.T))
식으로 된다.
행렬 차원에 관한 이야기를 안 할 수 없는데,
우선 axis = 1인 차원을 합해서 줄여버렸으니까 (DY,1)
그리고 X_train도 reshape은 안했으니까 (DX)이 된다. (사실 얘도 1,DX로 reshape하는게 더 직관적이지 않았을까?)
마지막으로 (DY,DX)를 빼니까 딱 예뻐진다.
argsort (원소의 등수 리턴해주는 함수)
어떤 행렬의 집합에서 해당 원소가 몇등인지 알고싶다면 어떻게 하면 될까?
>>> x = np.array([3, 1, 2])
>>> np.argsort(x)
array([1, 2, 0])
1등은 x[1]
2등은 x[2]
3등은 x[0] 이라는 뜻이다. (오름차순 기준이고 order이라는 파라미터를 넘겨서 바꿀 수 있다)
이 링크에 자세한 예시가 더 있다.
https://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
np.random.choice(range,num) ( 범위의 랜덤 인덱스 생성기 )
np.random.choice(10,5) # 자동 0~9
-> array([6, 9, 7, 5, 5])
np.random.choice(range(1,10),5) # 가능
범위의 랜덤 인덱스를 싹 num개만큼 뽑아 준다.
np.argmin() , np.argmax() ( 가장 큰 / 작은 값의 인덱스 뽑기 )
np.argmax(np.array([3,4,5,2,1]))
-> 2
가장 큰 값 / 가장 작은값의 인덱스를 뽑아줌.
응용하면 2차원 배열 각각에서 제일 큰 값도 뽑을 수 있음
x = np.array([[1,2,3,4],[2,5,4,3]])
y = x[np.arange(0,2),np.argmax(x,axis=1)]
y
-> array[4,5]
np.where() ( 조건에 맞는 값의 위치 리턴 )
np.where(np.array([3,4,2,5,1])>=3)
->(array([0, 1, 3], dtype=int64),)
조건에 맞는 값의 위치
응용하면 조건에 맞는 값 자체를 리턴할 수도 있다.
x = np.array([5,4,3,2,1,0])
x[np.where(x >= 3)]
->array([5,4,3])
np.where() ( 조건에 맞는 값을 특정 다른 값으로 변환하기 )
x = np.array([5,4,3,2,1,0])
np.where(x >= 3, 3, x)
-> array([3, 3, 3, 2, 1, 0])
조건에 맞는 값을 변경하는 것도 가능
np.maximum() , np.minimum() ( 두개의 array 혹은 수에 대해서 최대 / 최소값 리턴 )
np.maximum(np.array([1,2,3]),np.array([3,2,1]))
->array([3, 2, 3])
np.maximum(np.array([1,2,3]),2)
->array([2, 2, 3])
두개의 array에 대해 (혹은 단일 숫자)최대값만 리턴하기.
np.log() ( 자연 로그 )
기본적으로는 자연 로그를 리턴
np.log([1, np.e, np.e**2, 0])
array([ 0., 1., 2., -Inf])
np.log2() np.log10()등의 함수도 있음
np.copy() ( 복사 )
y = np.copy(x)
-> x가 y에 복사
np.exp() ( e의 거듭제곱 )
np.exp(np.array([1,2,3]))
-> array([ 2.71828183, 7.3890561 , 20.08553692])
e의 거듭제곱으로 바꿔줌.
np.shape() ( array의 모양 )
np.shape(np.array([[3,2,4],[3,2,3]]))
->2,3
numpy array의 shape을 알려줌
np.reshape() ( array의 모양 바꾸기 )
np.reshape(np.array([[3,2,4],[3,2,3]]),(3,2))
->
array([[3, 2],
[4, 3],
[2, 3]])
numpy array의 shape을 바꿔줌
참고한 링크들
https://leebaro.tistory.com/entry/numpylinalgnorm