01 머신러닝의 개념
머신러닝: 어플리케이션을 수정하지 않고, 데이터 기반으로 패턴을 학습하며 결과를 예측하는 알고리즘 기법. 소스의 코드가 복잡해지면서 예측의 정확성 향상을 위해 데이터를 기반으로 패턴을 인지해 해결.통계적인 신뢰도 강화하며 예측 오류를 최소화하기 위해 데이터 분석 영역에 새로운 혁신을 가져다줌.
머신러닝의 분류
1. 지도학습(Supervised Learning)
분류(Classification), 회귀(Regression)이 대표적
2. 비지도학습(Unsupervised Learning)
클러스터링, 차원 축소가 대표적
3. 강화학습(Reinforcement Learning)
데이터의 단점: 매우 의존적, 좋은 품질의 데이터를 갖추지 못하면 수행결과 또한 좋을 수 없음. 따라서 최적의 알고리즘과 모델 파라미터를 구축해야하고, 데이터를 이해하며 효율적으로 가공 처리 추출해야하는 것이 중요함.
R - 통계 프로그램 언어, 전통적인 통계 및 마이닝을 개선하고자 만든 프로그램, 통계 분석에 특화되어있음.
파이썬 - 다양한 영역에서 사용되며, 객체지향과 함수형 프로그래밍을 모두 포괄한다는 강점.
쉽고 뛰어난 개발 생산성
• 오픈소스 계열의 전폭적인 지원, 많은 라이브러리의 높은생산성을보장
• 뛰어난 확장성,유연성,호환성으로 다양한 영역 사용
• 머신러닝 애플리케이션과 결합해 다양한애플리케이션 개발 가능
• 엔터프라이즈 아키텍처 확장 및 마이크로서비스 기반의 실시간 연계
02 파이썬 머신러닝 생태계를 구성하는 주요 패키지
- 머신러닝 패키지: 사이킷 런, 데이터 마이닝 기반의 머신러닝에서 독보적 위치
- 행렬/선형대수/통계 패키지: 파이썬의 대표적인 행렬과 선형대수를 다루는 패키지는 넘파이, 사이파이패키지
- 데이터 핸들링: 판다스, 대표적인 처리 패키지이며 2차원 데이터 처리에 특화되어 편리하게 데이터 처리 가능, 맥플롭립 - 쉽게 시각화 가능
- 시각화: 맷플롯립, 파이썬 기반이며 대표적 시각화 라이버리지만 세분화되었으며 시각적인 디자인에서 투박해 효율이 떨어짐
- 시본: 맷플롯립 기반이며 파이썬과 쉬운 연동, 맷플롯립에 대한 기본 정보 필요
- 서드파티 라이브러리 : 머신러닝을 편리하게 지원함, 오픈 소스로 존재
- 아이파이썬: 대화형 파이썬 툴, 주비터 노트북
파이썬 머신러닝을 위한 S/W 설치에 대한 설명, 책 참조
03 넘파이
넘파이: 선형대수 기반의 프로그램을 쉽게 만드는 패키지, 루프 사용 X, 빠른 배열 연산 속도, 저수준 언어의 호환 API 제공
넘파이 모듈 임포트 : import numpy as np
ndarray() - 넘파이 다차원 배열 생성
array 1= np.array([1,2,3])
print('array1 type:'), type(array1))
print('array1 array 형태:', array1.shape)
out: array1 array 형태: (3,)
ndarray로 객체 인자 입력하면 ndarray 반환해서 ndarray.shape로 차원과 크기를 알려줌
print('array1: {:0},array2: ,{:1}, array3:, {:2}'.format(array1.ndim, array2.ndim, array3.ndim))
out: array1: 1차원, array2: 2차원, array3: 2차원
ndarray의 데이터 타입
데이터 값은 숫자, 문자열, 불값 가능하나 같은 데이터 타입만 가능해서 한개의 객체에 다른 데이터 타입이 있을 수 없음
list1 = [1,2,3]
print(type(list1))
array1 = np.array(list1)
print(type(array1))
print(array1, array1.dtype)
dtype로 속성 확인 가능.
ndarray의 내의 데이터 타입은 같은 특성만 가능해서, 변경하면 데이터 크기가 더 큰 타입으로 형 변환을 일괄 적용.
list2 = [1, 2, 'test']
array2 = np.array(list2)
print(array2, array2.dtype)
list3 = [1, 2, 3.0]
array3 = np.array(list3)
print(array3, array3.dtype)
print('float형으로 데이터가 변환되었음')
out)
['1' '2' 'test'] <U21
[1. 2. 3.] float64
ndarray 생성 - arange, zeros, ones
sequence_array = np.arange(10)
print(sequence_array)
print(sequence_array.dtype)
print(sequence_array.shape
arrange: 0부터 -1까지의 값을 순차적으로 변환
out: [0 1 2 3 4 5 6 7 8 9 ] int 32 (10,)
zero_array = np.zeros((3, 2), dtype='int32')
print(zero_array)
print(zero_array.dtype)
print(zero_array.shape)
one_array = np.ones((3,2))
print(one_array)
print(one_array.dtype,one_array.shape)
zeros( ) : 튜플형태의 shape 값을 입력하면, 모든 값을 0으로 채운 ndarray를 반환
ones( ) : 튜플형태의 shape 값을 입력하면, 모든 값을 1으로 채운 ndarray를 반환
-> dtype 정해주지 않을 경우 float 64형으로 채움.
ndarray의 차원과 크기를 변경하는 reshape()
reshape()는 ndarray 특정 차원과 크기로 변환, 변환을 원하는 크기로 함수 인자 부여, 지정된 사이즈로 변경 불가능할시 오류 발생, 인자로 -1을 사용시 새로운 shape로 변환
array1 = np.arange(10)
print('array1: \n', array1)
array2 = array1.reshape(2, 5)
print('array2: \n', array2)
array3 = array1.reshape(5, 2)
print('array3: \n', array3)
array1 = np.arange(10)
print(array1)
print('--------------------')
array2 = array1.reshape(-1, 5)
print(array2, ' --> shape : ', array2.shape)
print('--------------------')
array3 = array1.reshape(5, -1)
print(array3, ' --> shape: ', array3.shape)
-1을 인자로 사용하더라도, 호환될 수 없는 형태로는 변환X
array1 = np.arange(8)
print('1차원 array: \n', array1)
# 1차원 ndarray를 3차원으로 변환
array3d = array1.reshape((2,2,2))
print('\n3차원 array: \n', array3d)
print('\nlist로 변환된 array3d: \n', array3d.tolist()) # tolist() : list 형태로 변환
# 3차원의 ndarray를 2차원으로 변환
array5 = array3d.reshape(-1, 1)
print('\narray5: \n', array5)
print('array5 shape: ', array5.shape)
# 1차원의 ndarray를 2차원으로 변환
array6 = array1.reshape(-1,1)
print('\narray6: \n', array6
넘파이의 ndarray의 데이터 세트 선택하기 - 인덱싱
- 특정 데이터만 추출 : 원하는 위치의 인덱스 값을 지정하면 해당 위치의 데이터가 반환
- 슬라이싱(slicing) : 연속된 인덱스 상의 ndarray를 추출하는 방식
- 팬시 인덱싱(fancy indexing) : 일정한 인덱싱 집합을 리스트 또는 ndarray 형태로 지정해 해당 위치에 있는 데이터의 ndarray를 반환
- 불린 인덱싱(boolean indexing) : True/False 값 인덱싱 집합을 기반으로 True에 해당하는 인덱스 위치에 있는 데이터의 ndarray를 반환
- 단일값 추출, 원하는 위치의 인덱스 값 지정시 해당 위치 데이터 변환
# 1부터 9까지의 1차원 ndarray 생성
array1 = np.arange(start=1, stop=10)
array1
# index는 0부터 시작하므로 array1[2]는 3번째 index 위치의 데이터 값을 의미
value = array1[2]
print('value: ', value)
print(type(value))
- 슬라이싱 추출, 연속한 데이터를 슬라이싱해서 추출
array1 = np.arange(start = 1, stop = 10)
print(array1)
array3 = array1[0:3]
print(array3)
print(type(array3))
array1 = np.arange(start = 1, stop = 10)
array4 = array1[:3]
print(array4)
array5 = array1[3:]
print(array5)
array6 = array1[:]
print(array6)
array1d = np.arange(start = 1, stop = 10)
array2d = array1d.reshape(3, 3)
print('array2d:\n', array2d)
print()
print('array2d[0:2, 0:2] \n', array2d[0:2, 0:2])
print('array2d[1:3, 0:3] \n', array2d[1:3, 0:3])
print('array2d[1:3, :] \n', array2d[1:3, :])
print('array2d[:, :] \n', array2d[:, :])
print('array2d[:2, 1:] \n', array2d[:2, 1:])
print('array2d[:2, 0] \n', array2d[:2, 0])
# 2차원 ndarray에서 뒤에 오는 인덱스를 없애면, 1차원 ndarray를 반환
# 즉, array2d[0]과 같이 2차원에서 뒤에 오는 인덱스를 없애면, row 축(axis = 0)의 첫 번째 row ndarray를 반환
print('array2d[0] \n', array2d[0])
- start 생략: array[:stop] -> 자동으로 0으로 간주.
- stop 생략: array[start:] -> 자동으로 배열의 마지막 인덱스로 간주.
- 둘 다 생략: array[:] -> 전체 배열을 반환.
- 팬시 인덱싱, 일정한 인덱싱 집합을 리스트 또는 ndarray 형태로 지정하고 해당 위치의 인덱스에 해당하는 ndarry 반환
array1d = np.arange(start = 1, stop = 10)
array2d = array1d.reshape(3, 3)
print(array2d)
array3 = array2d[[0, 1], 2]
print('array2d[[0, 1], 2] => ', array3.tolist())
array4 = array2d[[0, 2], 0:2]
print('array2d[[0, 2], 0:2] => ', array4.tolist())
array5 = array2d[[0, 1]]
print('array2d[[0, 1]] => ', array5.tolist())
- 불린 인덱싱, 조건과 필터링과 검색을 동시에 하는 반환
- Step 1: 조건을 설정 (예: array1d > 5).
- Step 2: 조건에 따라 True/False 배열 생성 (예: [False, False, False, False, False, True, True, True, True]).
- Step 3: True 값의 인덱스를 사용해 원래 배열에서 데이터 조회.
array1d = np.arange(start = 1, stop = 10)
print(array1d)
print(array1d > 5)
var1 = array1d > 5
print("var1:", var1)
print(type(var1))
# [ ] 안에 array1d > 5 Boolean indexing을 적용
print(array1d)
array3 = array1d[array1d > 5]
print('array1d > 5 불린 인덱싱 결과 값 :', array3)
boolean_indexes = np.array([False, False, False, False, False, True, True, True, True])
array3 = array1d[boolean_indexes]
print('불린 인덱스로 필터링 결과 :', array3)
행렬의 정렬 – sort( )와 argsort( )
행렬 정렬
- np.sort(): 원 행렬은 그대로 유지한 채, 원 행렬의 정렬된 행렬을 반환
- ndarray.sort(): 원 행렬 자체를 정렬한 형태로 반환, 반환 값은 None
org_array = np.array([3, 1, 9, 5])
print('원본 행렬:', org_array)
# np.sort( )로 정렬
sort_array1 = np.sort(org_array)
print ('np.sort( ) 호출 후 반환된 정렬 행렬:', sort_array1)
print('np.sort( ) 호출 후 원본 행렬:', org_array)
# ndarray.sort( )로 정렬
sort_array2 = org_array.sort()
org_array.sort()
print('org_array.sort( ) 호출 후 반환된 행렬:', sort_array2)
print('org_array.sort( ) 호출 후 원본 행렬:', org_array)
- np.sort() 와 ndarray.sort() 모두 기본적으로 '오름차순'으로 정렬
- '내림차순'으로 정렬하기 위해서는 [::-1]을 적용.
sort_array1_desc = np.sort(org_array)[::-1]
print ('내림차순으로 정렬:', sort_array1_desc)
행렬이 2차원 이상일 경우, axis 축 값 설정을 통해 row 방향 또는 column 방향으로 정렬을 수행
array2d = np.array([[8, 12],
[7, 1]])
sort_array2d_axis0 = np.sort(array2d, axis = 0)
print('로우 방향으로 정렬:\n', sort_array2d_axis0)
sort_array2d_axis1 = np.sort(array2d, axis = 1)
print('컬럼 방향으로 정렬:\n', sort_array2d_axis1)
- np.argsort(): 정렬된 행렬의 '원본 행렬 인덱스'를 ndarray 형으로 반환
org_array = np.array([3, 1, 9, 5])
print(np.sort(org_array))
sort_indices = np.argsort(org_array)
print(type(sort_indices))
print('행렬 정렬 시 원본 행렬의 인덱스:', sort_indices)
# [::-1] 를 사용해서 '내림차순' 정렬된 행렬의 '원본 행렬 인덱스'를 반환하기
org_array = np.array([3, 1, 9, 5])
print(np.sort(org_array)[::-1])
sort_indices_desc = np.argsort(org_array)[::-1]
print('행렬 내림차순 정렬 시 원본 행렬의 인덱스:', sort_indices_desc)
agscort()는 넘파이에서 활용도가 높음. 메타 데이터는 별도의 ndarray로 각각 가져야함
name_array = np.array(['John', 'Mike', 'Sarah', 'Kate', 'Samuel'])
score_array = np.array([78, 95, 84, 98, 88])
# score_array의 정렬된 값에 해당하는 '원본 행렬 위치 인덱스' 반환하고, 이를 이용하여 name_array에서 name 값 추출
sort_indices = np.argsort(score_array)
print('성적 오름차순 정렬시 score_array의 인덱스:', sort_indices)
name_array_sort = name_array[sort_indices]
score_array_sort = score_array[sort_indices]
print('성적 오름차순으로 name_array의 이름 출력:', name_array_sort)
print('성적 오름차순으로 score_array의 점수 출력:', score_array_sort)
선형대수 연산 – 행렬 내적과 전치 행렬 구하기
행렬 내적
- 두 행렬 A와 B의 내적은 np.dot() 왼쪽 행렬의 행과 오른쪽 행렬의 칼럼을 순차적으로 곱한뒤 더한값
A = np.array([[1, 2, 3],
[4, 5, 6]])
B = np.array([[7, 8],
[9, 10],
[11, 12]])
dot_product = np.dot(A, B)
print('행렬 내적 결과:\n', dot_product)
전치 행렬
- transpose() 원 행렬에서 행과 열의 위치를 교환한 원소로 구성한 행렬
A = np.array([[1, 2],
[3, 4]])
transpose_mat = np.transpose(A)
print('A의 전치 행렬:\n', transpose_mat)
04 데이터 핸들링 - 판다스
주요 구조: 2차원 데이터인 DataFrame (행 x 열)
- 장점:
- 이해하기 쉬운 데이터 구조
- 넘파이보다 유연하고 직관적인 API 제공
- 다양한 데이터 소스(CSV 등)에서 쉽게 로드 가능
- 핵심 객체:
- DataFrame: 여러 개의 Series로 구성
- Series: 단일 열 데이터 구조
- Index: 데이터의 고유 식별자
판다스 시작
- 판다스는 파이썬의 데이터 처리 라이브러리로, 핵심 객체는 DataFrame.
- DataFrame은 행과 열로 구성된 2차원 데이터 구조.
파일 로딩 및 기본 API
- 다양한 포맷의 파일을 DataFrame으로 불러오는 방법을 제공. 예: read_csv(), read_table().
- read_csv()는 기본적으로 ,를 필드 구분자로 사용, sep 인자를 통해 다른 구분자도 설정할 수 있음.
데이터 확인
- head(), tail(): DataFrame의 처음 또는 마지막 몇 개의 행을 확인.
- shape: DataFrame의 행과 열 크기를 반환.
- info(): 데이터의 전체 정보, 각 열의 데이터 타입과 null 개수를 보여줌.
- describe(): 숫자형 데이터의 통계 정보를 제공.
데이터 변환
- DataFrame과 리스트, 딕셔너리, 넘파이 ndarray 간의 변환이 가능.
- DataFrame을 생성할 때 열 이름을 직접 지정할 수 있음.
데이터 수정 및 삭제
- [] 연산자를 사용해 새로운 열을 추가하거나 기존 열의 값을 수정할 수 있음.
- drop(): 특정 행 또는 열을 삭제할 수 있는 메서드.
인덱스 객체
- Pandas의 인덱스는 데이터를 식별하는 고유 객체.
- reset_index(): 인덱스를 재설정하고 기존 인덱스를 열로 이동.
데이터 셀렉션 및 필터링
- 판다스에서 데이터 선택은 `.iloc[]`와 `.loc[]`를 사용하여 수행함.
- `[ ]` 연산자는 특정 컬럼을 지정하는 데 사용되며, 단일 숫자 인덱스는 오류를 발생시킴.
DataFrame iloc[]
- **iloc**: 위치 기반 인덱싱
- 정수 또는 정수 슬라이싱을 사용하여 데이터에 접근함.
- 예: `data_df.iloc[0, 0]`는 첫 번째 행, 첫 번째 열의 데이터를 반환함.
DataFrame loc[]
- **loc**: 명칭 기반 인덱싱
- 인덱스 이름 또는 컬럼 이름으로 데이터에 접근함.
- 예: `data_df.loc['one', 'Name']`는 'one' 인덱스의 'Name' 컬럼 값을 반환함.
- 슬라이싱 시 끝 값을 포함함.
불린 인덱싱
- 특정 조건에 맞는 데이터만 선택함.
- 예: `titanic_df.loc[titanic_df['Age'] > 60, ['Name', 'Age']]`
정렬, Aggregation 함수, Groupby
DataFrame, Series의 정렬 - sort_values()
- `sort_values(by='컬럼명', ascending=True/False, inplace=True/False)` 형태로 사용함.
- 예: `df.sort_values(by='Name')`
Aggregation 함수 적용
- `min()`, `max()`, `sum()`, `count()` 등을 사용하여 통계 계산함.
groupby() 적용
- 특정 컬럼을 기준으로 그룹화하여 다양한 통계값을 확인할 수 있음.
- 예: `df.groupby('Pclass')['Age'].agg(['max', 'min'])`
결손 데이터 처리
- 결손 데이터는 NaN으로 표시되며, 이를 처리하는 함수는 `isna()`와 `fillna()`임.
- 결손 데이터 확인: `df.isna().sum()`
- 결손 데이터 대체: `df.fillna(value)`
apply와 lambda를 이용한 데이터 가공
- `apply()` 함수에 lambda식을 결합하여 데이터 가공함.
df['Name_len'] = df['Name'].apply(lambda x: len(x))
'머신러닝' 카테고리의 다른 글
[ECC 스터디] 7장 군집화 (0) | 2024.11.29 |
---|---|
[ECC 머신러닝 스터디] 6장 차원 축소 (0) | 2024.11.22 |
[ECC 머신러닝 스터디] 5장 리뷰 (1) | 2024.11.15 |
[ECC 파이썬 머신러닝 완벽가이드] 4.7-4.11 (1) | 2024.11.09 |
[파이썬 머신러닝 완벽 가이드] 3장 평가 (1) | 2024.10.10 |