본문 바로가기

멀티캠퍼스 프로젝트형 AI 서비스 개발 5회차/ML

3/15 화

728x90

화요일!
우오오오 드디어 전공인 머신러닝 학습 시작!

 

수업 후엔 현업 개발자(무려 엔씨소프트, 넥슨코리아를 거쳐 직방)의 취업특강이 있다~

'커리어패스 가이드' : 커리어 맵, 기업별 장단점, 현업 개발자의 조언

 

데이터의 수집 · 가공(Data Handling)이 Machine Learning의 60~80%를 차지함
정제된 데이터 → 정확한 결과

1. Anaconda Prompt에서 Jupyter notebook 실행

2022.01.18 - [멀티캠퍼스 프로젝트형 AI 서비스 개발 5회차/Python] - 1/18 화

Jupyter notebook config 설정

2. Python module 중 Pandas가 data handling에 사용됨 ← data를 사용하기에 요긴하게 만들어줌
Pandas의 data-type을 구성하고 있는 Numpy module(외장)

Numpy(Numerixal Python)는 ndarray라는 하나의 자료구조(list, dict)를 제공함 ← 수치 계산을 용이하게 함, 대용량의 다차원 배열과 matrix(행렬) 연산을 쉽게 하기 위함

ndarray(n-dimensional array)는 python의 list와 상당히 유사하지만, 차원의 개념이 있고 list와 달리 무조건 같은 데이터 타입만 저장됨

Anaconda Prompt 새로 열어서 Numpy module 설치!

conda activate machine
conda install numpy

Jupyter Notebook에서 Numpy 제대로 설치되었는지 확인. alias는 np로 통일

3. list는 ','로 인자들이 구분되지만, ndarray는 공백으로 구분됨

import numpy as np

a = [1, 2, 3, 4]
print(a, type(a))            # [1, 2, 3, 4] <class 'list'>

# Numpy의 ndarray
arr = np.array([1, 2, 3, 4]) # list로 ndarray 만들기
print(arr, type(arr))        # [1 2 3 4] <class 'numpy.ndarray'> → 1차원

print(arr.dtype)             # int32 ← 정수
arr1 = np.array([1., 2.3, 3., 4.])
print(arr1.dtype)            # float64 ← 실수
arr2 = np.array([1, 2, 3, 4, "Hello"])
print(arr2.dtype)            # <U11 ← 문자

4. 다차원 배열 ndarray

# 중첩리스트
my_list = [[1, 2, 3], [4, 5, 6]] # [[1, 2, 3], [4, 5, 6]]
print(my_list)
print(my_list[1][1])             # 5

# 다차원 배열 (2차원) ndarray
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr)                       # [[1 2 3] : 0번째 행
                                 # [4 5 6]] : 1번째 행
print(arr[1, 1])                 # 5 : 1번째 행의 1번째 열. 이렇게 하는게 통속적
print(arr[1])                    # [4 5 6] : 1번째 행
print(arr[1][1])                 # 5 : 1번째 행의 1번째 인자

print(arr.dtype)                 # int32 : ndarray는 요소의 데이터 타입을 이용해서 dtype을 설정함
arr = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float64) # 데이터 타입을 지정하여 ndarray를 생성할 수 있음
print(arr, arr.dtype)            # float64

5. ndarray의 차원 관련 속성

my_list = [1, 2, 3, 4]
arr = np.array(my_list)
print(arr, arr.dtype)
print(arr.ndim)              # 1 : ndim은 차원을 숫자로 알려줌
print(arr.shape)             # (4,) : shape은 차원과 요소 수를 tuple로 알려줌

my_list = [[1, 2, 3], [4, 5, 6]]
arr = np.array(my_list)
print(arr.ndim)              # 2 : 2차원
print(arr.shape)             # (2, 3) : 2차원, 2행 3열

my_list = [[[1,2,3], 
            [1,2,3]], 
          [[1,2,3], 
          [1,2,3]]]
arr = np.array(my_list)
print(arr.ndim, arr.shape) # 2면 2행 3열. 3차원 12개의 요소들, (2, 2, 3)

6. astype 메서드로 원하는 데이터 타입으로 바꿀 수 있음

arr = np.array([1.2, 2.3, 3, 4, 5.7])
print(arr.dtype) # float64
new_arr = arr.astype(np.int32) # astype 메서드로 원하는 데이터 타입으로 바꿀 수 있음
print(new_arr, new_arr.dtype) # [1 2 3 4 5] int32

new_arr = arr.astype(np.str_) # 문자
print(new_arr, new_arr.dtype) # ['1.2' '2.3' '3.0' '4.0' '5.7'] <U32

7. ndarray를 만드는 다양한 함수들

my_list = [1, 2, 3]
arr = np.array(my_list)

arr = np.zeros((3,4))   # 주어진 shape에 대한 ndarray를 생성하고 0으로 채움
print(arr)

arr = np.ones((2,3))    # 주어진 shape에 대한 ndarray를 생성하고 1으로 채움
print(arr)

arr = np.empty((2,3,3)) # 주어진 shape에 대한 ndarray를 생성하고 값을 채우지 않음. garbage 값이 들어갈 수 있음. 초기화 하지 않기 때문에 빠르게 만들 수 있음
print(arr)

arr = np.full((2,3),    # 2행 3열을 7이라는 요소를 채워서 ndarray를 생성하라
              7,
              dtype=np.float64)
print(arr)
print(arr.dtype)

8. like() 의 shape과 같은 형태로 ndarray를 생성하고 값을 채워라

arr = np.array([[1,2,3], [4,5,6]],
              dtype=np.int32)
print(arr)                     # [[1 2 3]
                               # [4 5 6]]

new_arr = np.zeros_like(arr) # arr의 shape과 같은 형태로 ndarray를 생성하고 값을 0으로 채워라. 데이터 타입도 따라서 정수. 0은 원래 실수
print(new_arr)                 # [[0 0 0]
                               # [0 0 0]]
    
new_arr = np.ones_like(arr)    # [[1 1 1]
print(new_arr)                 #  [1 1 1]]

new_arr = np.full_like(arr, 5) # [[5 5 5]
print(new_arr)                 #  [5 5 5]]

9. numpy의 arange

a = range(1, 10)      # python의 range
print(a)

arr = np.arange(1,10) # numpy의 arange. 1부터 10까지(10은 포함 안 함). 1씩 증가하는 값으로 구성된 ndarray
print(arr)            # [1 2 3 4 5 6 7 8 9]

arr = np.arange(1.3, 10.1, 2) # 1.3부터 10.1까지 2씩 증가하는 값으로 구성된 ndarray
print(arr)            # [1.3 3.3 5.3 7.3 9.3]

10. np.linspace(start, stop, num) : 시작과 끝을 모두 포함, num은 그 안에 균일한 간격으로 몇 개의 숫자가 들어갈지 (start - stop) / (num - 1). 균일한 간격의 데이터를 생성해서 ndarray를 만들어내는 함수.

arr = np.linspace(0, 10, 11) # 0부터 10까지 11개의 요소가 동일한 간격으로 구성된 ndarray
print(arr)                   # [ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9. 10.]

arr = np.linspace(0, 10, 6) # (start - stop) / (num - 1) = 간격이 2
print(arr)                  # [ 0.  2.  4.  6.  8. 10.]

arr = np.linspace(0, 120, 31)
print(arr)                  # [  0.   4.   8.  12.  16.  20.  24.  28.  32.  36.  40.  44.  48.  52. 56.  60.  64.  68.  72.  76.  80.  84.  88.  92.  96. 100. 104. 108. 112. 116. 120.]

11. 랜덤 값을 이용해서 ndarray 만들어 내는 함수 5개

np.random.normal() : 그 안에 데이터는 실수형 난수로 채워짐. 정규분포 표본을 추출. 평균(mean) · 표준편차(std) 값을 줘야 함. 일단 난수를 추출하고 그 난수가 정규분포를 따르는지 확인

Anaconda Prompt로 matplotlib 외장 모듈 설치. 그래프 라이브러리!

conda activate machine
conda install matplotlib

 

import numpy as np
import matplotlib.pyplot as plt # matplotlib 외장 모듈의 pyplot sub module은 그래프를 그려줌

mean = 50 # 평균
std = 2 # 표준편차

arr = np.random.normal(mean,
                      std,
                      (100000,)) # shape. 평균이 59이고 표준편차가 2인 정규분포도를 출력. 실수 형태
print(arr)
plt.hist(arr,bins=100) # bin은 간격
plt.show()

np.random.normal(), 정규분포, 실수형 난수

12. np.random.rand() : 그 안에 데이터는 실수형 난수로 채워짐. 균등분포 표본을 추출. [0, 1) 0부터 1사이(0은 포함, 1은 불포함)의 실수형 난수

arr = np.random.rand(100000) # 인자가 하나면 일차원. (d1, d2, d3). 0 ~ 1 사이. 균등분포 표본
print(arr)
plt.hist(arr, bins=100)
plt.show()

arr = np.random.rand(1000000) # 요소가 더 많은 경우 편차가 적음
print(arr)
plt.hist(arr, bins=100)
plt.show()

np.random.rand(), 균등분포, 실수형 난수

13. np.random.randn() : 그 안에 데이터는 실수형 난수로 채워짐. 표준 정규분포(평균이 0이고 표준편차가 1인 정규분포) 표본을 추출

arr = np.random.randn(100000) # 표준정규분포에서 난수를 추출
print(arr)
plt.hist(arr, bins=100)
plt.show()

np.random.randn(), 표준정규분포, 실수형 난수

14. np.random.randint() : 그 안에 데이터는 수형 난수로 채워짐. 균등분포 표본을 추출. low와 high 값을 줘야 함

arr = np.random.randint(1, 100, (10000,)) # low, high, shape
print(arr)
plt.hist(arr, bins=99)
plt.show()

np.random.randint(), 균등분포, 정수형 난수

15. np.random.random() : 그 안에 데이터는 실수형 난수로 채워짐. 균등분포 표본을 추출. [0, 1) 0부터 1사이(0은 포함, 1은 불포함)의 실수형 난수. rand()와 표현 방식이 다름

arr = np.random.random((100000,))
print(arr)
plt.hist(arr, bins=100)
plt.show()

np.random.random(), 균등분포, 실수형 난수

16. 기억해야 하는 random 관련 함수들

1. seed() : random 값도 사실은 프로그램 알고리즘에 의해서 추출되는 값. 이를 도출하는 초기 값(seed)을 고정하면 항상 같은 값을 얻을 수 있음. 난수(랜덤 값)의 재현성 확보

np.random.seed(1)    # 초기 값 = 1
arr = np.random.randint(1, 10, (5,))
print(arr) # [6 9 6 1 1]

np.random.seed(None) # 초기 값 = None
arr = np.random.randint(1, 10, (5,))
print(arr) # 난수(랜덤 값)

17. 기억해야 하는 random 관련 함수들

2. shuffle() : 원본 data의 순서를 바꿈. 초기 값(seed)을 고정하면 항상 같은 값을 얻을 수 있음

arr = np.arange(1, 10)
print(arr) # suffle은 원본을 섞어버림 [1 2 3 4 5 6 7 8 9]

np.random.shuffle(arr)
print(arr) # [7 1 4 2 3 5 6 9 8]

18. 기억해야 하는 random 관련 함수들

3. choice() : sampling에서 사용할 수 있음. np.random.choice(a, size, replace, p)

a는 모집단이자 배열, size는 숫자 몇 개를 뽑을 건지, replace가 True이면 뽑았던 것 다시 뽑을 수 있음, p는 각 데이터가 뽑힐 수 있는 확률

# np.random.choice(a, size, replace, p)
arr = np.random.choice(np.array([1,2,3,4,5]), 3)
arr = np.random.choice(np.array([1,2,3,4,5]), 3, replace=True)
arr = np.random.choice(np.array([1,2,3,4,5]), 3, replace=False)
arr = np.random.choice(np.array([1,2,3,4,5]), 3, p=[0.1, 0.2, 0.2, 0.5, 0]) # 5는 0%의 확률
print(arr)

19. ndarray의 shape과 관련된 중요한 함수들

1. reshape() : shape을 바꿔서 새로운 ndarray를 만드는 것이 아니고, 원래 ndarray의 데이터를 다르게 보여주는 view를 생성

arr = np.array([[1,2,3,4,5,6],[7,8,9,10,11,12]])
print(arr)
print(arr.shape) # 2행 6열 [[ 1  2  3  4  5  6]
                          # [ 7  8  9 10 11 12]]

new_arr = arr.reshape(3, 4)
print(new_arr)            # [[ 1  2  3  4]
                          # [ 5  6  7  8]
                          # [ 9 10 11 12]]
        
new_arr1 = arr.reshape(1,2,3,2) # 4차원, 1면, 2면, 3행, 2열
print(new_arr1)             # [[[[ 1  2]
                            #   [ 3  4]
                            #   [ 5  6]]
                            #
                            #  [[ 7  8]
                            #   [ 9 10]
                            #   [11 12]]]]

new_arr[0,0] = 100
print(new_arr)
print(arr)                  # 사본도 원본도 data의 0번째 인자도 바뀌었다! 원래 ndarray의 view
                            # [[100   2   3   4]
                            #  [  5   6   7   8]
                            #  [  9  10  11  12]]
                            # [[100   2   3   4   5   6]
                            #  [  7   8   9  10  11  12]]

 

20. ndarray의 shape과 관련된 중요한 함수들
2. ravel() : reshape는 내가 원하는 shape의 view를 만들 수 있고, ravel은 무조건 1차원의 view를 만듦

arr = np.array([[1,2,3,4,5,6],[7,8,9,10,11,12]])
print(arr)
print(arr.shape)

new_arr = arr.ravel() # 무조건 1차원의 view를 만듦
new_arr1 = arr.reshape(12).copy()
print(new_arr)
print(new_arr1)
print(arr)

21. ndarray의 shape과 관련된 중요한 함수들

3. resize() : reshape()는 요소 개수가 맞지 않을 경우 에러! view를 만들지 않고 원본을 바꿈. 요소 개수가 적으면 추가, 많으면 버려서 데이터 유실이 발생할 수 있음

arr = np.array([[1,2,3,4,5,6],[7,8,9,10,11,12]])
print(arr)
print(arr.shape)

# new_arr = arr.reshape(3,5) # 12 != 15. 요소 갯수가 맞지 않기 때문에 에러!
# new_arr = arr.resize(3,5) # None. 사본을 만들지 않고, 원본을 변경
# print(new_arr)
# print(arr)
# [[ 1  2  3  4  5]
#  [ 6  7  8  9 10]
#  [11 12  0  0  0]]

new_arr = arr.resize(3,2)
print(new_arr)
print(arr)
# [[1 2]
#  [3 4]
#  [5 6]]

22. ndarray의 indexing과 slicing은 python의 list와 동일

arr = np.arange(10,15,1)
print(arr)              # [10 11 12 13 14]
print(arr[0])           # 10
print(arr[1:3])         # [11 12]
print(arr[1:-1])        # [11 12 13]
print(arr[3:], arr[:2]) # [13 14] [10 11]

 

arr = np.arange(0,12).reshape(3,4)
print(arr)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
print(arr[1,2])               # 6. [행,열]
print(arr[1])                 # [4 5 6 7]. 1번째 행
print(arr[1,:])               # [4 5 6 7]. 1번째 행의 열을 모두 가져와라
print(arr[1, 2:], arr[2, 2:]) # [6 7] [10 11]
print(arr[1:, 2:])            # [[ 6  7]
                              # [10 11]]

23. ◈ 중요 ndarray의 Boolean indexing. mask를 이용! 반복/조건문 보다 연산이 빠름

ndarray의 사칙연산 : +, -, *, /, %. 같은 shape에 대해서만 연산 가능!

shape을 맞출 수 있으면 broadcasting(차원 맞추기)이 진행됨!

np.random.seed(1)
arr = np.random.randint(0, 10, (10,)) # 0 ~ 10. 1차원의 요소 10개
print(arr)               # [5 8 9 5 0 0 1 7 6 9]
print(arr + 10)          # [15 18 19 15 10 10 11 17 16 19] broadcasting
print(arr % 2)           # [1 0 1 1 0 0 1 1 0 1]
print(arr % 2 == 0)      # [False  True False False  True  True False False  True False] 나머지가 0과 같은가? Boolean Mask
my_mask = (arr % 2 == 0)
print(arr[my_mask])      # [8 0 0 6] arr 요소들이 True인 것만 가져옮. 짝수만

arr1 = np.array([1,2,3]) # python의 list 연산과 다름. 같은 위치의 요소들끼리 연산
arr2 = np.array([4,5,6])
print(arr1 + arr2)       # [5 7 9]

arr3 = np.array([1,2,3])
arr3 + 4                 # 연산해준 정수는 0차원(scala). [1,2,3] + [4 4 4]
print(arr3 + 4)          # [5 6 7]

24. ◈ 중요  ndarray의 Fancy indexing

ndarray에 index 배열을 전달해서 indexing 함

arr = np.arange(0, 12, 1).reshape(3,4)
print(arr)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

print(arr[0:2, 1:])         # [행에 대한 slicing, 열에 대한 slicing]
print(arr[0:2, [1,3]])      # Fancy Indexing
                            # [[1 3]
                            #  [5 7]]
print(arr[[0,2], [1,3]])    # [ 1 11] Numpy 내부구조 때문에 Fancy Indexing이 안 되는 경우, np.ix_() 함수 이용
print(arr[np.ix_([0,2], [1,3])])
                            # [[ 1  3]
                            #  [ 9 11]]

 

1. 3/15 화 2. 3/16 수 3. 3/17 목 4. 3/18 금 5. 3/21 월
ML
환경 설정
(아나콘다, 주피터 노트북),
Pandas,
Numpy,
ndarray
ML
Numpy,
ML

ML

ML

* 다시 힘차게 시작! ndarray과 차원(shape)에 대한 이해!

728x90

'멀티캠퍼스 프로젝트형 AI 서비스 개발 5회차 > ML' 카테고리의 다른 글

3/22 화  (0) 2022.03.22
3/21 월  (0) 2022.03.21
3/18 금  (0) 2022.03.18
3/17 목  (0) 2022.03.17
3/16 수  (0) 2022.03.16