Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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 30 31
Tags
more
Archives
Today
Total
관리 메뉴

철솜_STUDY

파이썬 머신러닝 완벽 가이드 _ CH.1_(2) 본문

Self-Taught/Machine Learning

파이썬 머신러닝 완벽 가이드 _ CH.1_(2)

CC_flavor.철근 2024. 9. 28. 14:56

CH.1.4 _ NumPy

머신러닝의 알고리즘은 선형대수와 통계에 기반한다. NumPy는 Numerical Python를 의미하며, 루프를 사용하지 않고도 대량 데이터의 배열 연산을 수행한다. 연산 속도의 측면에서는 이점이 있으나, 파이썬 언어 자체의 수행 성능에 제약이 있으므로 C/C++과의 호환 API를 제공한다.

 

그러나 NumPy는 Pandas와 달리 같은 데이터 타입만 배열 데이터로 관리할 수 있다는 단점이 있다.

 

1. ndarray 란?

  • n차원의 배열 객체 - C의 array와 유사하다고 보면 된다.
  • np.array(대상 list, data type)  - 기존의 list를 ndarray 형태로 바꿔주는 함수
  • type(ndarray) - 타입을 알려주는 함수
  • ndarray.shape - ndarray의 구조를 튜플(tuple) 형태로 알려주는 메서드
  • ndarray.ndim - ndarray의 차원을 보여주는 메서드

*tuple - python의 자료형. ( )를 이용해 만든다.

import numpy as np
a = [1, 2, 3, 4, 5]
array1 = np.array(a)
array2 = np.array(a, float)
array3 = np.array([[1, 2, 3], [2, 3, 4]])
array4 = np.array([[1, 2, 3]])

print("array1 type: ", type(array1))
print("array1 array 형태 : ", array1.shape)
print("array1 type: ", type(array2))

print("array3 array 형태 : ", array3.shape)
print("array4 array 형태 : ", array4.shape)


print("array1 : {0}차원, array3 : {1}차원,  array4 : {2}차원".format(array1.ndim, array3.ndim, array4.ndim))

 

 

 

2. ndarray의 data type

ndarray는 숫자형, 문자열, 불 값 모두 올 수 있다.

*숫자형 - signed int형, unsigned int형, float형, complex 타입

 

list의 경우 서로 다른 데이터 타입을 가질 수 있다. 그러나 numPy는 불가능하기 때문에 만약 list 내에 서로 다른 데이터 타입이 존재한다면, 데이터의 크기가 더 큰 데이터 타입으로 형 변환을 적용한다.

  • ndarray.dtype - ndarray 내부 원소의 데이터 타입을 알려주는 메서드
  •  ndarray.astype - ndarray 내부 원소의 데이터 타입을 변경하는 메서드
list2 = [1, 2, 'test']
array5 = np.array(list2)
print(array5, array5.dtype)

list3 = [1, 2, 3.0]
array6 = np.array(list3)
print(array6, array6.dtype)

 

 

3. 특수한 ndarray 생성하기

arange() / zeros() / ones()를 이용해 특수한 ndarray를 쉽게 생성할 수 있다. 

이런 특수한 ndarray는 테스트용 데이터를 만들거나, 대규모의 데이터를 일괄적으로 초기화해야 할 경우 사용된다.

 

  • arange(start=0, stop=, step=1) - 0부터 함수 인자 값 직전까지의 값을 ndarray의 원소로 변환하는 메서드이다. 각 숫자는 해당 옵션의 default 값.
  • zeros(shape, dtype='float64') - 튜플 형태의 shape 값을 갖고 0으로 채워진 ndarray를 반환하는 메서드로, dtype의 default 는 float64.
  • ones(shape, dtype='float64') - 튜플 형태의 shape을 갖고 1로 채워진 ndarray를 반환하는 메서드로, dtype의 default는 float64.
import numpy as np
npp=np.arange(0, 10, step=0.5)
print(npp)

zero_array = np.zeros((3,2))
zero_array2 = np.zeros((3,2), dtype='int32')
print(zero_array)
print(zero_array2)

ones_array = np.ones((3,2))
ones_array2 = np.ones((3,2), dtype='int32')
print(ones_array)
print(ones_array2)

 

 

4. reshape(row = , col = ) _ ndarray의 차원과 크기를 변경하는

이미 존재하는 ndarray의 차원이나 크기를 바꾸고 싶을 때 사용하는 메서드이다.

다만 지정된 사이즈로 변경이 가능해야 한다. 예를 들어 3*4 구조의 ndarray를 5*3 구조로 바꿀 수 없는 것이다.

 

row나 col에 -1을 넣을 경우, 고정돼 있는 다른 옵션의 값에 들어맞는 적절한 새로운 ndarray를 생성하라는 의미이다.

 

*reshape(-1,1) _ 원본 ndarray를 n*1의 형태로 변환해준다.

여러 개의 ndarray를 stack이나 concat으로 결합할 때 ndarray의 형태를 통일해줄 때 유용하다.

*tolist() _ array를 list 자료형으로 변경해주는 메서드

array1 = np.arange(10)
print(array1)
array2 = array1.reshape(-1, 5)

# array1은 1*10 이지만, array2는 2*5가 된다
array1 = np.arange(8)
array3d = array1.reshape((2,2,2))   #1차원을 3차원으로 변경
print("array3d: \n", array3d.tolist())

array2d = array3d.reshape((-1,1))   #3차원을 2차원으로 변경
print("array2d: \n", array2d.tolist())

array2d2 = array1.reshape((-1,1))   #1차원을 2차원으로 변경
print("array2d2: \n", array2d2.tolist())

 

5. Indexing _ ndarray의 데이터 선택하기

NumPy에서 데이터를 선택하는 방법은 크게 4종류이다.

 

index를 이용해 특정한 위치의 단일 값만 추출하는 방법, : 를 이용해연속된 인덱스 상의 ndarray를 추출하는 방법인 Slicing, 일정한 인덱싱 집합을 리스트나 ndarray 형태로 지정해 ndarray를 반환하는 Fancy Indexing, TRUE FALSE를 이용해 특정 조건에 해당하는 ndarray를 반환하는 Boolean Indexing 이 있다. 

 

*axis = 0, axis =1 _ row 와 column을 NumPy에서 나타내는 방법.

차원이 늘어날 수록 axis = 2, 3, 4.. 처럼 숫자를 늘려 표현하게 된다. default 값은 0이다.

 

import numpy as np

array1 = np.arange(1, 10)

# index와 -를 이용해 원소를 추출하는 예시

print("맨 뒤에 있는 값 : ", array1[-1])
print("맨 뒤에서 두 번째 값 : ", array[-2])


# 다차원 ndarray에서 원소를 추출하는 예시
array1_2 = array1.reshape(3,3)
print(array1_2)

print("(row=0, col=0) index가 가리키는 값 : ", array1_2[0,0])

 

 

Slicing은 stop index의 직전 index까지의 값을 반환한다. 또한 1차원과 n차원에서도 적용 가능하다. 

예를 들어 2차원 ndarray에서 첫번째 []만을 채운다면 특정한 row만을 추출할 수 있다.

특정한 col을 추출하고 싶다면 [:, n]이라는 형태의 slicing이 가능하다.

*slicing에도 default 값이 있다.

strat와 stop을 생략하면 자동으로 해당 ndarray 시작과 끝을 default 값으로 가져온다.

 

#slicing 예시 _ 1차원 (n차원에서도 적용 가능하다)
array2 = np.arange(1, 10)
array3 = array3[0:3]
print(array3)

print(array2[:3])
print(array2[1:6])
print(array2[:])


array9 = np.arange(1, 10)
array9 = array9.reshape(3,3)

print(array9)
print(array9[1])
print(array9[:, 1])

 

 

Fancy Indexing은 다음과 같다.

ndarray를 생성한 후 특정 인덱스를 slicing한 결과를 또다른 ndarray로 저장한다.

array1d = np.arange(1, 10)
array2d = array1d.reshape(3,3)

array3 = array2d[[0,1],2]

print("array2d[[0,1],2] => ", array3.tolist())

 

Boolean Indexing은 조건 필터링과 검색을 동시에 할 수 있는 방법이다.

array3 = np.arange(1, 10)
array4= array3[array3 > 5]

array3 > 5
array3[array3>5]

print("array4 => ", array4)

 

 

6. sort() & argsort() _ 행렬의 정렬

 

#sort()

np.sort(ndarray) 와 ndarray.sort는 서로 다르다.

np.sort는 NumPy에서 sort 함수를 호출하는 형식이고, ndarray는 행렬 자체에서 sort를 호출하는 메서드 방식이다.

 

이 둘의 차이점을 간단하게 설명하면

np.sort(ndarray)원본 ndarray 행렬의 형태를 바꾸지 않고, 새로운 행렬을 생성하게 된다.

ndarray.sort()원본 ndarray의 행렬의 형태를 바꾸고, 새로운 행렬을 반환하지 않는다.

 

이 둘 모두 기본적으로 오름차순으로 행렬 내 원소를 정렬한다.

만약 내림차순으로 정렬하고 싶다면 [::-1]라는 옵션을 사용할 수 있다.

 

만약 n차원 행렬이라면 axis 방향을 설정해 정렬할 수 있다.

import numpy as np

org_array = np.array([3, 1, 5, 8, 2])
print(org_array)

sort1 = np.sort(org_array)

print("np.sort(ndarray) 후의 정렬 : ", sort1)
print("np.sort() 후의 내림차순 정렬 : ", np.sort(org_array)[::-1] )
print("np.sort(ndarray) 후의 원본 정렬 : ", org_array)


sort2 = org_array.sort()

print("ndarray.sort() 후의 정렬 : ", sort2)
print("ndarray.sort() 후의 원본 정렬 : ", org_array)

 

array2d2 = np.array([[8,12],[7,1]])

sort_array2d2r = np.sort(array2d2, axis=0)
print("row 방향으로 정렬 : \n", sort_array2d2r)


sort_array2d2c = np.sort(array2d2, axis=1)
print("col 방향으로 정렬 : \n", sort_array2d2c)

 

#argsort(ndarray)

argsort() 는 원본 행렬 원소의 index를 정렬해 나열하는 것이다.

이 함수는 NumPy에서 활용도가 높다. array 속 원소의 data type가 동일해야 하기 때문에 여러 정보를 표현하기 위해서는 여러 개의 ndarray가 필요하다. 이 때 유용하게 사용되는 것이 이 argsort()이다.

 

import numpy as np

name_array = np.array(['John', 'Mike', 'Sarah', 'Kate', 'Samuel'])
score_Array = np.array([78, 89, 29, 70, 68])

sort_index = np.argsort(score_Array)
print('오름차순 정렬 시 성적 array의 index => \n', sort_index)
print('오름차순 정렬 시 성적 array의 index => \n', score_Array[sort_index])
print('오름차순 정렬 시 이름 array의 형태 => \n', name_array[sort_index])

 

7. 행렬 내적 & 전치 행렬 _ 선형대수 연산

행렬의 내적 = 행렬의 곱. np.dot(ndarray1, ndarray2)을 이용한다. 

전치 행렬은 np.transpose(ndarray)를 이용한다.