본 포스트팅은 인하대학교 컴퓨터공학과 오픈소스 SW 개론 수업자료에 기반하고 있습니다. 개인적인 학습을 위한 정리여서 설명이 다소 미흡할 수 있으니, 간단히 참고하실 분들만 포스팅을 참고해주세요 😎
- Numpy 에서 문제 출제시, BroadCasting 하고 Fancy Indexing 만 시험에 출제하지 좋다!!!!! (by 교수님)
array(n차원 리스트) : n차원짜리 배열(행렬) 생성
arr2.ndim : 해당 배열(행렬)의 차원을 리턴 (2차원 배열일 경우 2를 리턴)
np.zeros : 인자값으로 받은 크기를 가지는 0으로 채워진 배열생성
np.empty(a, b, c) : a x b x c 짜리의 쓰레기값이 채워진 3차원짜리 배열 생성
np.arange(n) : 파이썬의 range() 함수의 numpy 버전이다. 즉, arange(n) 은 0 ~ n-1 사이의 정수 리스트를 생성
dtype : array() 로 배열 객체를 생성시 dtype 옵션을 사용하면 배열의 타입을 지정해줄 수 있다.
astype : 배열의 타입 바꾸기(casting)
=> dtype 옵션을 활용해서, 다른 배열 객체의 타입을 dtype 으로 가져와서 astype() 의 인자값으로 할당할 수 있다.
dtype 예제
import numpy as np
arr1 = np.array([1,2,3], dtype = np.float64) # float형 배열 생성
arr2 = np.array([1,2,3], dtype = np.int32) # int형 배열 생성
print(arr1.dtype) # dtype('float64')
astype 예제
import numpy as np
arr1 = np.array([1,2,3], dtype = np.float64) # float형 배열 생성
arr2 = np.array([1,2,3], dtype = np.int32) # int형 배열 생성
# int형 -> float형
arr = np.array([1,2,3,4,5])
new_arr = arr.astype(np.float64)
# string형 -> float형
new_arr2 = arr = np.array(['1.25', '-9.6', '420'], dtype = np.string_)
print(new_arr2)
# dtype 옵션을 활용해서 배열 타입 변환
new_arr2.astype(new_arr.dtype)
print(new_arr2.dtype)
numpy 기능중 하나이다.
대치연산을 한방에 진행함 => 두 배열끼리 매칭되는 원소들에 대해서 각각 따로 연산을 천천히 진행하는것이 아니라, 빠르게 한방에 연산을 진행해버리는 것
예를들어 아래와 같은 두 배열의 곱셈연산이 일어날떄, 6개의 원소에 대해 각 매칭되는 원소에 대해 곱셈을 총 6번 하는것이 아니라, 그냥 한번에 6번의 연산을 빠르게 진행하는 것
numpy 의 Vectorization 기능 중 하나
배열의 크기 및 형태(shape) 가 다른 배열들끼리 연산을 가능하게 해주는 기능
크기 및 차원이 작은 배열과, 더 큰 배열간에 연산이 일어날때 크기 및 차원이 작은 배열쪽에서 더 큰 배열쪽에 맞춰서 동일하게 크기와 형태가 변형된다.
=> ex) 1x3 과 4x3 배열간에 연산이 일어날때 1x3 배열이 4x3 배열로 자동 변환되서 연산이 4x3 과 4x3 배열간에 일어나도록 한다,
print(arr * 4)
=> 둘은 배열과 스칼라로써 shape 가 다름에도 불구하고, 연산이 가능하다.
import numpy as np
arr = np.random.randn(4, 3) # 4x3 형태의 랜덤값이 채워진 2차원 배열생성
print(arr.mean(0)) # 각 컬럼에 대한 평균을 리턴 => 1x3 형태의 배열객체를 리턴
demeaned = arr - arr.mean(0) # 4x3 배열에서 1x3 배열을 빼는 연산진행
print(demeaned) # => 크기가 다른 배열끼리 연산을 진행했음에도 불구하고, 에러가 발생하지 않고 연산이 진행된다.
# 연산 상세과정
# 1. 1x3 짜리 배열이 4x3 배열로 변환된다.
# => 배열(arr.mean(0)) 에 나머지 빈 행(2행, 3행, 4행) 에 1행에 있는 내용을 싹다 그대로 카피해준다.
# => 예를들어 arr.mean(0) = [1,2,3] 이라면 [[1,2,3], [1,2,3], [1,2,3], [1,2,3]] 이 생성된다.
# 2. 생성된 배열을 가지고 연산 (arr - arr.mean(0)) 을 수행한다.
배열의 특정 부분을 인덱싱 or 슬라이딩했을때 나온 조각은 원본 배열의 view 가 된다.
예제
원본배열 arr 로부터 부분 배열 arr_slice 를 추출해와서 arr_slice[1] = 12345 와 같이 값을 변경해주면, 원본배열 arr 의 해당 원소의 값(arr[6]) 도 값이 변경된다.
arr_slice[:] = 64 => arr_slice 배열의 모든 원소의 값들을 64로 변경
예를들어 아래처럼 2 x 2 x 3 짜리의 3차원배열 arr3d를 선언하고
arr3d[0] 으로 인덱싱을하면 가장 상위차원인 2가 생략되고 2x3 형태의 배열이 출력된다.
예시
print(arr2d)
# 출력 : array([[1,2,3],
[4,5,6],
[7,8,9]])
print(arr2d[:2])
# 출력 : array([1,2,3]
[4,5,6])
arr2d[:2, 1:] = 0
# 출력 : array([[1,0,0],
[4,0,0],
[7,8,9]])
import numpy as np
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
data = np.random.randn(7, 4)
print(names == 'Bob') # vecotirized 대치연산 (비교연산) => array의 모든 원소들에 대해 'Bob' 문자열과 동일한지를 True 또는 False 로 리턴
# Boolean 값으로 인덱싱하기
# 배열에 인덱싱으로 Boolean 결과값을 할당 => True 가 있는 인덱스에 대해서만 데이터 조회
print(data[names == 'Bob']) # 이름이 Bob 인 경우에 데이터를 출력
# 슾라이싱 기능도 추가가능
print(data[names == 'Bob', 2: ])
# != 연산자를 통해서도 인덱싱 가능
print(names != 'Bob')
print(data[names != 'Bob']) # Bob 과 다른 경우를 찾아서 인덱싱 가능하다.
# Boolean 결과값에 "~" 을 붙여서 True 를 False 로, False 를 True 로 변환가능
print(data[~(names == 'Bob')])
# Boolean 값을 새로운 변수에 대입시켜서 활용가능
cond = names == 'Bob' # names == 'Bob' 을 진행한 결과를 cond 리스트에 저장하고
print(data[~cond]) # 리스트에서 활용함. 이름이 Bob 이 아닌 경우에 데이터를 출력
# AND 나 OR 연산자 등을 활용해서도 다양한 Boolean 연산후 그 결과값을 인덱싱에 활용가능
mask = (names == 'Bob') | (names == 'Will')
print(mask)
print(data[mask])
# 조건식의 Boolean 결과값도 인덱싱에 활용가능
data[data < 0] = 0 # 0보다 작은값들에 대해 모두 0으로 바꿈 (= 데이터들 중에 음수인 데이터들을 모두 0으로 바꿈)
data[names != 'Joe'] = 7 # names 가 Joe 가 아닌 인덱스들을 찾아서, 해당 인덱스의 모든 값들을 7로 바꿈
Numpy 에서 문제 출제시, BroadCasting 하고 Fancy Indexing 만 시험에 출제하지 좋다!!!!! (by 교수님)
예를들어 아래처럼 for문을 돌려서 2차원 배열 원소를 채웠다고하자.
i번쨰 행에는 정수 i를 할당하는 방식으로, 8x4 짜리 2차원배열을 생성했다.
그러고 아래처럼 Fancy Indexing을 활용해보자.
=> 분석 : 우선 arr [ [1,5,7,2] ] 부분에서 1행, 5헹, 7행, 2행에 해당하는 행 데이터들을 가져온다. 가져온 각 행에대한 데이터간의 위치를 변환시켜보자. 해당 행 데이터들의 각각의 열의 위치를 변환시키고 싶은경우 " : , [변경시키고 싶은 배열] " 의 형태를 이 뒤에 넣어주면된다.
아래 예제의 경우 2x2x4 배열에서 2와 4 부분의 축을 변경시켜주는 것이다. 그래서 2x4x2 형태의 배열이 출력된다.
배열의 각각의 원소를 빠르게 처리해줄 수 있는 함수
줄여서 ufunc 라고도 부름
ndarray 배열 객체 안에있는 데이터를 원소별로 연산을 진행한다.
하나의 스칼라값을 인자로 받아서, 그 스칼라값을 배열의 모든 원소에 연동을 시켜서 한번에 대치연산을 진행한다.
이에 해당하는 함수는 Unary, Binary ufuncs 등이 있다.
1개의 인자를 받아서 element-wise 연산을 수행하는 Universal 함수
2개의 인자를 받는 Universal 함수
아래 예제의 경우, 첫번째 원소를 보면 0.8626 이 -0.0119 보다 더 크므로 0.8636 이 추가된다. 이렇게 0번쨰 인덱스, 1번쨰 인덱스, .... 에 해당하는 데이터들을 비교하고 더 큰값을 가지고 새로운 배열을 구성한다.
- universal 함수에는 out 이라는 옵션이 있다.
- out 이라는 argument 에 연산의 결과값을 저장할 수 있다.
- out 을 사용하려면 2개의 인자를 받아야한다.
다양한 선형대수 함수를 보유하고 있는 모듈
numpy 에서 난수를 생성해주는 모듈
그냥 단순하게 난수를 추출하는 기능에 이어서, 확률분포를 기반으로해서 랜덤값을 추출해주는게 가능하다.
np.random.normal(size=(4,4)) : 4x4 형태의 행렬(배열)을 정규분포로 랜덤값을 출력해준다.