전편에 이어서 이번 편에는 다양한 numpy 함수들에 대해 알아보자.
기본적인 함수와 동작 원리에 대해 알고 싶다면 전편을 보고오는 것을 추천한다.
링크 -> Numpy(1)
numpy는 다양한 범용함수들이 있고 다음 함수들은 성분별 연산을 한 ndarray를 return한다.
print(np.sqrt(a)) #-> square root (제곱근)
print(np.exp(a)) # -> 성분별 지수표현
print(np.maximum(a,b)) # 두 배열의 성분별 가장 큰 성분 ndarray return
# 범용함수는 out 이라는 인자에 원본이 수정되길 원하는 ndarray를 주어 원본을 수정할 수 있다.
# 이 외에 sign, mod등의 함수등이 있다.
출력
[[1. 1.41421356 1.73205081]
[2. 2.23606798 2.44948974]]
[[ 2.71828183 7.3890561 20.08553692]
[ 54.59815003 148.4131591 403.42879349]]
[[2 5 4]
[4 5 6]]
meshgrid 함수는 2차원 격자점을 생성하는 함수로 x축 좌표범위를 포함하는 1차원 배열과 y축 좌표범위를 나타내는 1차원 배열을 입력하면 격자점을 의미하는 2차원 배열을 2개 return한다.
# meshgrid
# x_scale (x좌표 범위) 1차원배열, y_scale (y좌표 범위) 1차원 배열을 전달받아
# 2차원 격자점을 구성하는 x범위 * y범위의 2차원 배열(x범위의 원소 하나당 y범위 원소 개수 만큼의 원소가 필요) 과, y범위 * x범위의 2차원 배열을 튜플로 return한다.
arr1 = np.linspace(1,10,10)
arr2 = np.linspace(-10,-1,10)
x,y = np.meshgrid(arr1,arr2)
print(x,y,sep ='\n')
**출력
[[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]]
[[-10. -10. -10. -10. -10. -10. -10. -10. -10. -10.]
[ -9. -9. -9. -9. -9. -9. -9. -9. -9. -9.]
[ -8. -8. -8. -8. -8. -8. -8. -8. -8. -8.]
[ -7. -7. -7. -7. -7. -7. -7. -7. -7. -7.]
[ -6. -6. -6. -6. -6. -6. -6. -6. -6. -6.]
[ -5. -5. -5. -5. -5. -5. -5. -5. -5. -5.]
[ -4. -4. -4. -4. -4. -4. -4. -4. -4. -4.]
[ -3. -3. -3. -3. -3. -3. -3. -3. -3. -3.]
[ -2. -2. -2. -2. -2. -2. -2. -2. -2. -2.]
[ -1. -1. -1. -1. -1. -1. -1. -1. -1. -1.]]
3항 연산을 해주는 함수로 예시를 통해 알아보자.
arr = np.random.randn(10)
np.where(arr>0,1,0) # 인자별로 condition, true expression, false expression이다
출력
array([1, 1, 1, 1, 0, 0, 0, 1, 1, 1])
고속 연산 및 행렬 연산에 특화된 numpy의 수학 함수들이다.
#수학 통계 논리 정렬 method
arr = np.random.normal(10,1,(5,4))
print(arr,end='\n\n')
print(f"평균:{arr.mean()},표준편차:{arr.std()},분산:{arr.var()},합:{arr.sum()},최댓값:{arr.max()},최솟값:{arr.min()}",end='\n\n')
print(arr.cumsum(),arr.cumprod(),sep='\n',end='\n\n') #각각 누적합이 표현된 배열과 누적곱이 표현된 배열 return
# 이외에도 argmax,argmin함수 -> index별 최대,최소 return
#논리 연산 활용
arr = np.array([ True, True, True, True, True, False, False, True, False,
True])
print((arr>0).sum(),any(arr>0),all(arr>0),end='\n\n')
#정렬 method
arr = np.random.randn(2,3)
print(arr,end='\n\n')
arr.sort()
print(arr) #axis = default(0)이어서 행별로 정렬된 모습
출력
[[10.03343893 10.68056724 8.43650331 9.43330238]
[ 9.75785049 11.51439128 9.6669426 10.04736482]
[11.46274045 11.53502913 10.56644004 10.14926509]
[ 8.921722 11.39547227 11.78748405 9.43048274]
[10.17538653 9.53749446 8.9141994 10.63973599]]
평균:10.204290659802984,표준편차:0.9529397491647639,분산:0.9080941655382031,합:204.0858131960597,최댓값:11.787484045563003,최솟값:8.436503309900058
[ 10.03343893 20.71400617 29.15050948 38.58381186 48.34166235
59.85605363 69.52299623 79.57036105 91.0331015 102.56813062
113.13457066 123.28383575 132.20555775 143.60103002 155.38851407
164.8189968 174.99438334 184.5318778 193.4460772 204.0858132 ]
[1.00334389e+01 1.07162819e+02 9.04079479e+02 8.52845510e+03
8.32193897e+04 9.58220616e+05 9.26306369e+06 9.30693802e+07
1.06683015e+09 1.23059168e+10 1.30029732e+11 1.31970622e+12
1.17740520e+13 1.34170884e+14 1.58153715e+15 1.49146588e+16
1.51762418e+17 1.44743322e+18 1.29027084e+19 1.37281411e+20]
7 True False
[[-0.38586334 -0.77576235 0.99571135]
[-1.93320478 0.24853063 -0.03124534]]
[[-0.77576235 -0.38586334 0.99571135]
[-1.93320478 -0.03124534 0.24853063]]
선형대수의 행렬식, 행렬곱, 역행렬구하기, 행렬분해등의 복잡한 수식을 numpy.linalg 라이브러리를 import하여 사용할 수 있다.
# 선형대수 함수
# 행렬곱 연산 dot 함수 (python 3.5 이상 부터는 @라는 연산자로 dot 대체가능 ex)a @ b)
a = np.random.randn(3,4)
b= np.random.randn(4,3)
print(a.dot(b),np.dot(a,b),sep='\n',end='\n\n')
# numpy.linalg -> 역행렬, 행렬식, 분해 함수 등 포함
from numpy.linalg import inv, det
X = np.random.randn(3, 3)
print(det(X),end='\n\n') # 행렬식 return
print(inv(X),end='\n\n') # 역행렬 return
출력
[[ 1.71361706 -1.39846694 1.44384403]
[-0.2764774 -0.23821622 -1.096304 ]
[-3.18230161 2.8214342 1.39753731]]
[[ 1.71361706 -1.39846694 1.44384403]
[-0.2764774 -0.23821622 -1.096304 ]
[-3.18230161 2.8214342 1.39753731]]
-0.5407583180361959
[[ 3.56730319 -0.38978817 -0.17305708]
[-0.18910906 0.3522893 -0.50529179]
[-0.77080427 -0.77348985 -0.19517602]]
numpy의 random 모듈은 특히나 자주 쓰이는 모듈로서, 관련함수들을 잘 알아두는 것이 좋다. 1편에서 다뤘던, normal함수, randn함수도 numpy.random 모듈 안의 함수이다.
#numpy.random
np.random.seed(0)
# 난수 생성 -> 이후 항상 같은 난수 사용
#np.random.RandomState(123) 국소적 난수 생성
# shuffle과 permutation
# shuffle은 원본 배열의 순서를 변경, permutation은 수정된 객체 반환
arr = np.linspace(1,10,10)
print(np.random.permutation(arr))
np.random.shuffle(arr)
print(arr)
# rand와 randint
print(np.random.rand(3,2),np.random.randint(5),sep='\n') # rand는 0~1의 uniform dist에서 인자 사이즈의 배열 return, randint는 0~4의 uniform 정수 dist에서 정수 한개 return
# binomial, gamma,uniform
print(np.random.binomial(n=1,p=0.5,size=10)) #n->trial, p->probability
출력
[ 3. 9. 5. 10. 2. 7. 8. 4. 1. 6.]
[ 4. 6. 2. 3. 10. 9. 1. 7. 8. 5.]
[[0.81216873 0.47997717]
[0.3927848 0.83607876]
[0.33739616 0.64817187]]
0
[1 1 1 1 1 0 1 0 1 0]
numpy의 배열은 바이너리 파일로 원하는 경로에 저장할 수 있고, 단일 배열의 경우 .npy라는 확장자, 복수 배열 저장의 경우 .npz라는 확장자를 가진다.
save,savez 함수를 통해 저장하고, load함수를 통해 불러온다.
예시를 통해 자세히 알아보자.
# numpy array file
arr = np.arange(10)
np.save('./f1',arr) #경로에 배열을 바이너리 파일로 저장 .npy확장자
arr1 = np.load('./f1.npy') #load
# 여러 배열 저장
np.savez('./f2',a =arr, b = arr1)
#a와 b라는 key지정 가능, npz라는 확장자로 저장
arr2 = np.load('./f2.npz')
arr['a'] # key로 호출
References
https://compmath.korea.ac.kr/appmath/NumpyBasics.html
https://velog.io/@euisuk-chung/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%8B%9C%EA%B0%81%ED%99%94-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EA%B8%B0-Numpy