본문 바로가기

Programming Project/cs231n

cs231n assignment를 위한 numpy 함수들 정리


투명한 기부를 하고싶다면 이 링크로 와보세요! 🥰 (클릭!)

바이낸스(₿) 수수료 평생 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])

 

 

linalg.norm이 default로 계산하는 식. (유클리디안 거리)

모든 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

https://rfriend.tistory.com/380

https://docs.scipy.org/doc/numpy/