부스트코스의 "머신러닝을 위한 파이썬" 강좌 필기 내용
https://www.boostcourse.org/ai222/lecture/24071?isDesc=false
파이썬은 인터프리터 언어라서 성능이 많이 느리다. 그걸 개선하려면 적절한 패키지를 잘 사용해야함.
Numpy 없이 텐서플로우를 사용하면 많이 막힐 수 있다.
Numpy
- numerical Python
- 고성능 과학 계산용 패키지
- Matrix와 Vector와 같은 Array 연산의 사실상 표준
- 한글로 넘파이로 통칭, 넘피, 늄파이라고 불리기도 함
- 일반 리스트에 비해 빠르고 메모리 효율적임 : for문이나 list comprehension을 쓰지 않고 array 처리를 할 수 있음
- 선형 대수와 관련된 기능
- C와 CPP와 좋은 통합 기능
Numpy에서 가장 기본이 되는 건 ndarray = numpy dimentional array
import numpy as np
test_array = np.array([1,4,5,8], float) # 파이썬의 특징은 다이나믹 타입인데, 넘파이에서는 타입을 선언해주어야 함
# print(test_array)
# [1. 4. 5. 8.]
# print(type(test_array[3]))
# <class 'numpy.float64'> # 저장 메모리 잡는 것 보여줌 => 넘파이는 차례로 데이터를 쌓아서 훨씬 빠르게 연산됨
# print(test_array.dtype)
# float64
# print(test_array.shape) # array의 shape => 현재 저장 되어 있는 1 dimention의 크기를 보여줌
# => 벡터일 경우 아래와 같이 숫자 컴마 형태
# (4,)
# = > 2차원일 경우 (3,4) 형태로 나오게 됨 = 3x4 행렬
# = > 3차원일 경우 (4,3,4) 형태 = 제일 앞에 있는 것이 텐서의 깊이, 그다음이 row, 그다음이 column
# = > 1차원일 경우는 row인데 3차원에서는 맨 끝 = 하나씩 뒤로 밀리는 형식
# np.array(tensor, int).ndim # 텐서의 깊이
# np.array(tensor, int).size # 텐서의 사이즈
# C의 데이터 타입과 호환이 되긴 하지만
# 대부분은 float32나 float64 dtype을 씀
### reshape
# 2차원 디멘션을 벡터 형태로 펴야 하는 경우 = reshape
# (2,4) => (8)
test = [[1,2,3,4], [1,2,5,8]]
# print(np.array(test).shape)
# (2, 4)
# print(np.array(test).reshape(2,2,2)) # 위에도 8개 이거도 8개로 reshape = 3차원으로
# [[[1 2]
# [3 4]]
# [[1 2]
# [5 8]]]
np.array(test).reshape(-1,2).shape # 데이터에 개수에 맞춰서 2 디멘션으로 만들어준다
test_print = np.array(test).flatten() # 다차원 array를 벡터로 쉽게 펴줌
# print(test_print)
# [1 2 3 4 1 2 5 8]
## 인덱싱
index_test = np.array([[1,2,3], [4.5,5,6]], int)
# print(index_test)
# [[1 2 3]
# [4 5 6]]
# print(index_test[0,0])
# 1
# print(index_test[0][0])
# 1
# index_test[0,0] = 12 # => 0,0에 12 할당
## 슬라이싱
slicing_text = np.array([[1,2,3,4,5], [6,7,8,9,10]], int)
# print(slicing_text)
# [[ 1 2 3 4 5]
# [ 6 7 8 9 10]]
# print ( slicing_text[:2:] ) # 전체 row의 2열 이상
# [[ 1 2 3 4 5]
# [ 6 7 8 9 10]]
# print( slicing_text[1,1:3]) # 1Row의 1열 ~ 2열
# [7 8]
# print( slicing_text[1:3]) # 1Row ~ 2Row 의 전체
# [[ 6 7 8 9 10]]
# 넘파이의 슬라이싱은 효율적으로 많이 사용됨 = 일부분 가져올 때
# [:, ::2] # 2칸씩 띄는 데이터 가져오는 방식
### 생성법
## arange
arange_test = np.arange(30)
# print(arange_test)
# [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# 24 25 26 27 28 29]
arange_test_1 = np.arange(0, 5, 0.5) # 시작 끝 스텝 # 파이썬의 list에서는 float 단위로 못 뛰어서 필요하면 tolist()
# print(arange_test_1)
# [0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. 4.5]
# 컬럼을 5개로 고정하고 특정 숫자를 집어넣으려면 ? reshape과 같이 쓴다
arange_test_2 = np.arange(30).reshape(-1,5) # 자동으로 생성시킴
# print(arange_test_2)
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]
# [15 16 17 18 19]
# [20 21 22 23 24]
# [25 26 27 28 29]]
## ones, zeros and empty 모든 값들을 비어있는 값이나 0으로 만들어줌
zeros_test = np.zeros(shape=(10,), dtype=np.int8)
# print(zeros_test)
# [0 0 0 0 0 0 0 0 0 0] # 0으로 초기화 할 때
zeros_test_2 = np.zeros((2,5))
# print(zeros_test_2)
# [[0. 0. 0. 0. 0.]
# [0. 0. 0. 0. 0.]]
# empty 같은 경우 자리만 잡아주는 경우
## Identity 단위 행렬
identity_test = np.identity(n=3, dtype=np.int8)
# print(identity_test)
# [[1 0 0]
# [0 1 0]
# [0 0 1]]
## Eye = 가우스조단 문제 풀 때 / 대각선이 1인 행렬 생성 / k 값 지정해서 start index 해줄 수 있음
## Random sampling => 데이터 분포에 따른 sampling으로 균등분포, 정규분포 등의 값들을 랜덤하게 array 생성할 수 있음
### SUM
test_sum = np.arange(1,11)
# print(test_sum)
# [ 1 2 3 4 5 6 7 8 9 10]
# print ( test_sum.sum(dtype=np.float64) )
# 55.0
# axis 개념이 중요하다 !
# 앞에서 생긴 row가 뒤로 가게 되는 특성
test_array = np.arange(1,13).reshape(3,4)
test_array.sum()
# test_array.sum(axis=1)
# array([10, 26, 42])
Numpy 기능 함수 사용할 때 기준이 되는 축을 지정해줄 수 있다.
처음에 생기는 Shape이 항상 0가 됨
처음 2차원 생성했을 때 axis = 0 => row로 기준, axis =1 => 컬럼 기준
그냥 sum을 하면 모든 element를 더하게 되고, axis를 적어주면 그 기준으로 달라진다.
새로 텐서가 늘어나면 한개씩 밀려서 새로 생기는 축이 axis =0가 된다.
### Concat = 붙이는
# 두개의 벡터 어레이를 축을 기준으로 붙인다
a = np.array([1, 2, 3])
b = np.array([2, 3, 4])
np.vstack((a,b))
# array([[1, 2, 3],
# [2, 3, 4]]) # 2차원으로 생성됨
a = np.array([ [1], [2], [3]])
b = np.array([ [2], [3], [4]])
np.hstack((a,b))
# array([[1, 2],
# [2, 3],
# [3, 4]])
### Operations b/t arrays
### 어레이끼리 계산하는 것 = 벡터나 행렬끼리 연산하는
### 아주 간단하게 해줌
test_a = np.array([[1,2,3],[4,5,6]], float)
test_a + test_a # Matrix + Matrix 연산
# array([[ 2., 4., 6.],
# [ 8., 10., 12.]])
test_a - test_a # Matrix - Matrix 연산
# array([[ 0., 0., 0.],
# [ 0., 0., 0.]])
test_a * test_a # Matrix내 element들 간 같은 위치에 있는 값들끼리 연산
# array([[ 1., 4., 9.],
# [ 16., 25., 36.]])
matrix_a = np.arange(1,13).reshape(3,4)
matrix_a * matrix_a
# array([[ 1, 4, 9, 16],
# [ 25, 36, 49, 64],
# [ 81, 100, 121, 144]])
## 위의 연산이 Wisw 곱 = 같은 행렬끼리 곱
### Dot product
### => 다른 행렬끼리 = 고등학교 때 배운 행렬 곱
test_a = np.arange(1,7).reshape(2,3)
test_b = np.arange(7,13).reshape(3,2)
test_a.dot(test_b)
# array([[ 58, 64],
# [139, 154]])
### Transpose 전치행렬
test_a.transpose()
### Broadcasting : shape이 다른 배열들끼리 연산을 지원하는 기능
# matrix랑 벡터 스칼라의 계산시
# 모든 위치에 더해주는 기능 => 브로드캐스팅이라고 부른다
test_matrix = np.array([[1,2,3],[4,5,6]], float)
scalar = 3
test_matrix + scalar # Matrix - Scalar 덧셈
# array([[ 4., 5., 6.],
# [ 7., 8., 9.]])
test_matrix * 5 # Matrix - Scalar 곱셈 ## 각각의 엘레먼트에다가 연산
# array([[ 5., 10., 15.],
# [ 20., 25., 30.]])
## 매트릭스 끼리도 연산이 되는데 헷갈리므로...
### Numpy가 제일 빠르고 그다음이 list comprehension ###
Concat의 경우에는 예외
Comparison operation
넘파이를 처음 배우게 되면 For문을 쓰려고 하는데 제일 안 좋은 습관 !
### Comparisons
### All & ANY
a = np.arange(10)
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
a>5
# array([False, False, False, False, False, False, True, True, True, True], dtype=bool)
# 5보다 큰 값을 각각 다 비교 => 일종의 Broadcasting
# 스칼라 값과 넘파이 어레이를 비교해줄 때 True / False를 뱉어내준다
np.any(a>5), np.any(a<0)
# (True, False)
np.all(a>5) , np.all(a < 10)
# (False, True)
# All일때 모두다 만족이면 True, Any 일때 하나라도 만족하면 True
### Where : 조건에 맞으면 indext 값을 리턴함
a = np.array([1, 3, 0], float)
np.where(a > 0, 3, 2) # 컨디션에 따라서 True일 경우 3을, False일 경우 2를 리턴한다
# [3 3 2] # 마지막 element는 0보다 크지 않기 때문에 2를 반환함
where_test = np.where(a>0)
# 인덱스 값을 반환한다 = 첫번째 것이 0보다 크다 => 인덱스 값 0 리턴, 두번째 것이 0 보다 크다 => 인덱스 값 1 리턴, 세번째 것은 크지 않으므로 반환이 안됨
# print(where_test)
# (array([0, 1], dtype=int64),)
## Null 값이나 무한 값 찾아내는 기법
a = np.array([1, np.NaN, np.Inf], float)
np.isnan(a)
np.isfinite(a)
### argmax & argmin = 최대값 최소값 찾을 때 많이 쓰는
a = np.array([1,2,4,5,8,78,23,3])
np.argmax(a) , np.argmin(a) # 최고 큰 값의 인덱스 번호 리턴
# (5, 0)
# 축을 넣어주면 축에서 해당 값을 찾아준다
a=np.array([[1,2,4,7],[9,88,6,45],[9,76,3,4]])
np.argmax(a, axis=1) , np.argmin(a, axis=0)
### boolean index
test_array = np.array([1, 4, 0, 2, 3, 8, 9, 7], float)
test_array > 3 # 조건에 따라 반환
# array([False, True, False, False, False, True, True, True], dtype=bool)
test_array[test_array > 3] # 조건이 들어가면 True에 해당하는 값을 뽑아진다 = 불린 인덱스라고 함
# array([ 4., 8., 9., 7.])
condition = test_array < 3
test_array[condition]
# where절에서는 indext를 뽑았는데 boolean index를 쓰면 값을 뽑을 수 있다
A = np.array([
[12, 13, 14, 12, 16, 14, 11, 10, 9],
[11, 14, 12, 15, 15, 16, 10, 12, 11],
[10, 12, 12, 15, 14, 16, 10, 12, 12],
[ 9, 11, 16, 15, 14, 16, 15, 12, 10],
[12, 11, 16, 14, 10, 12, 16, 12, 13],
[10, 15, 16, 14, 14, 14, 16, 15, 12],
[13, 17, 14, 10, 14, 11, 14, 15, 10],
[10, 16, 12, 14, 11, 12, 14, 18, 11],
[10, 19, 12, 14, 11, 12, 14, 18, 10],
[14, 22, 17, 19, 16, 17, 18, 17, 13],
[10, 16, 12, 14, 11, 12, 14, 18, 11],
[10, 16, 12, 14, 11, 12, 14, 18, 11],
[10, 19, 12, 14, 11, 12, 14, 18, 10],
[14, 22, 12, 14, 11, 12, 14, 17, 13],
[10, 16, 12, 14, 11, 12, 14, 18, 11]])
B = A < 15
B.astype(np.int) # astype을 써서 바이너리 형태로 바꿔줄 수 있다.
### Fancy index : 넘파이는 array를 인덱스 밸류로 사용해서 값을 추출하는 방법
a = np.array([2, 4, 6, 8], float) # a와 b는 크기가 다름
b = np.array([0,0,1,3,2,1] ,int) # b에는 인덱스가 들어가 있는 형태
a[b] # 인덱스 값에 해당하는 것을 추출하도록
# array([ 2., 2., 4., 8., 6., 4.])
a.take(b) 함수를 써서 쓸 수도 있다.
'Programming > Python' 카테고리의 다른 글
머신러닝을 위한 파이썬 선형회귀 기본 이론 (0) | 2022.10.15 |
---|---|
파이썬 저장 경로 아주 쉽게 확인하는 법 (0) | 2022.10.14 |
파이썬 내장 모듈로만 벡터 연산 실습 (0) | 2022.10.14 |
파이썬으로 간단한 행렬 연산 / 선형대수 (0) | 2022.10.14 |
파이썬에서 자료구조(data structure)를 간단하게 다루도록 도와주는 모듈 (1) | 2022.10.14 |