본문 바로가기
Programming/Python

파이썬 넘파이 numpy 기초 문법

by Renechoi 2022. 10. 14.

 

부스트코스의 "머신러닝을 위한 파이썬" 강좌 필기 내용 

 

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) 함수를 써서 쓸 수도 있다. 

 

 

 

 

 

 

 

 

반응형