1. 머신러닝
컴퓨터가 명시작으로 프로그래밍 되지 않아도 데이터를 통해 예측할 수 있도록 하는 기능
머신러닝 구성요소
1. 데이터 셋
2. Feature (특징)
3. 레이블
4. 모델
5. 학습
머신러닝의 학습
데이터 수집 -> 데이터 전처리 -> 특징 선택 -> 모델 선택 -> 모델 훈련 -> 모델 평가 -> 모델 배포
모델 평가 후 성능을 높이기 위해 사이클적으로 개선하는 과정을 거치게 된다.
즉 계속해서 학습을 통해 개선되는 시스템임
학습 방법
2. 비지도 학습
레이블 (정답)이 없는 데이터셋을 이용하여 모델을 학습시키는 방법
3. 앙상블 학습
여러개의 머신러닝 모델을 결합하여 더 나은 성능을 얻는 방법
배깅 : 여러 모델을 독립적으로 학습시키고, 예측을 평균내거나 다수결 투표로 최종 예측
- ex. 랜덤포레스트
부스팅 : 여러 모델을 순차적으로 학습시키고, 이진 모델의 오차를 보완하여 최종 예측을 수행
- ex. 그래디언트 부스팅, XGBoost
스태킹 (Stacking) : 여러 모델을 학습시키고 예측 결과를 새로운 데이터로 사용하여 메타 모델을 학습
여러 개의 지도 학습을 모아놓은 것도 앙상블 기법에 해당함
PREPARE
# 가상환경 만들기
conda create --name myenv
# 가상환경 활성화
conda activate myenv
# 필요 패키지 설치
conda install jupyter numpy pandas
# 가상환경과 Jupyter 연결
python -m ipykernel install --user --name={연결할 가상환경} --display-name "가상환경에서부를 이름"
Numpy 주요 기능 : 다차원 배열 객체를 생성하고 조작할 수 있음, 벡터와 연산을 가능하게 해줌, 수학 함수를 제공함
Pandas 주요 기능 : 데이터 프레임 (테이블) 형태의 데이터를 생성하고 조작할 수 있음, 데이터 불러오기 및 저장, 데이터 조작 (그룹화, 병합 등)
근데 seaborn은 Jupyter Notebook에서 %pip install seaborn을 해야 함
# 데이터를 확인할 수 있는 유용한 코드 (데이터를 불러온 후에 사용하면 좋겠음)
# 1. 데이터 프레임의 첫 5행 출력
df.head()
# 2. 데이터 프레임의 컬럼명 확인
df.columns
# 3. 데이터 프레임의 데이터 타입 확인
df.dtypes
# 4. 데이터 프레임의 컬럼명 확인
df.columns
# 5. 특정 컬럼 선택
df['특정 컬럼명']
Scikit-learn 라이브러리 : 머신러닝을 위한 Python 라이브러리, 이미 내부적으로 알고리즘이 결정되어 있는 것이 특정 (머신러닝에 적합, 직접 구조화를 해야 하는 딥러닝에는 부적합)
Pandas는 데이터 전처리를 할 때 주로 사용하며, Scikit-learn은 ML에서의 전처리를 할 때 주로 사용한다. 즉, 둘 다 사용한다는 말이다.
1. Kaggle 사용한 방법
pip install kaggle
!kaggle datasets download -d <dataset-indentifier>
# 예시 데이터셋
!kaggle competitions download -c titanic
# 압축해제 + 데이터 해당 디렉터리로 옮기기 + 압축 전 zip 파일 삭제
# 그렇다면 해당 디렉터리 하위에 파일들이 생성된 것을 확인할 수 있다.
!mkdir target_directory && unzip titanic.zip -d target_directory && rm titanic.zip
2. seaborn 사용한 방법 (내장 데이터 셋 로드)
- train 데이터와 test 데이터를 직접 나눠줄 필요가 있는지 확인해야 한다.
import seaborn as sns
# 데이터 로드
titanic = sns.load_dataset('titanic')
# 필요한 열 선택 및 결측값 처리
titanic = titanic[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare', 'embarked']].dropna()
# 인코딩 (성별과 탑승한 곳) : 각자 다른 범위로 인코딩을 해주었기 때문에 나중에 문제가 생길 수도 있으니 주의할 것
titanic['sex'] = titanic['sex'].map({'male': 0, 'female' : 1})
titanic['embarked'] = titanic['embarked'].map({'C': 0, 'Q': 1, 'S': 2})
# 특성과 타겟 분리
# surivived를 예측할 종속변수이기 때문에 훈련할 데이터 셋인 X에서 분리를 한다
X = titanic.drop('survived', axis=1)
y = titanic['survived']
# 여기서부터는 모델 선택만 제외하고는 반복되는 부분이라고 생각하면 된다.
# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 데이터 스케일링
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 회귀 모델 생성 및 학습
model = LogisticRegression()
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
# 평가
print(f"Accuracy: {accuracy_score(y_test, y_pred)}")
print(f"Classification Report:\n{classification_report(y_test, y_pred)}")
print(f"Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}")
데이터 전처리
결측치 처리
결측치는 데이터셋에 누락된 값을 의미함
결측치를 처리하지 않으면 모델의 성능이 저하될 수 있음
# 삭제 (dropna) : NaN이 포함되어 있는 행이 있을 때 삭제해버림 / 열 단위로 하고 싶다면 axis=1로 설정
df_dropped_cols = df.dropna(axis=1)
# 대체 (fillna) : 평균 값으로 대체 / 주의해야 할 점은 바꾸려는 값의 type이 일치하는지 확인해야 한다는 점이다.
df_filled_mean = df.fillna(df.mean())
# 결측값을 각 열의 최빈값으로 대체
df_filled_mode = df.fillna(df.mode().iloc[0])
이상치 처리
이상치는 데이터에서 비정상적으로 크거나 작은 값을 의미함
이상치는 모델의 성능을 저하시킬 수 있음
# 제거
# 중복된 행 확인
print(df.duplicated().sum())
# 중복된 행 제거
df_no_duplicates = df.drop_duplicates()
# 변환
# 평균으로 대체
mean_value = df['column_name'].mean()
df['column_name'] = df['column_name'].apply(lambda x: mean_value if x < lower_bound or x > upper_bound else x)
# 실제로는 타입변환보다는 인코딩을 사용한다고 함
# IQR
# 사용하는 실제 방법은
# 1. lower_bound & upper_bound 확인
# 2. print
# 3. outlier 확인
Q1 = df['C'].quantile(0.25)
Q3 = df['C'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
print(lower_bound)
print(upper_bound)
outliers = df[(df['C'] < lower_bound) | (df['C'] > upper_bound)]
# print(outliers)
df_no_outliers = df[(df['C'] >= lower_bound) & (df['C'] <= upper_bound)]
df_no_outliers
데이터 정규화
정규화는 데이터를 일정한 범위로 스케일링하는 과정임
일반적으로 [0,1] 범위로 변환함
데이터 표준화
표준화는 데이터를 평균 0, 분산 1로 변환하는 과정임
-> 데이터가 안정된 상태에서 믿을 수 있는 범위에 있어서 머신러닝 모델이 학습이 잘되게 이끔
ex. z-점수 표준화
특성공학
특성 공학은 데이터로부터 새로운 유용한 특성을 생성하는 과정임
데이터 인코딩
비정형 데이터를 모델이 이해할 수 있는 형태로 변환함
데이터 분할
데이터를 학습용(train), 검증용(validation), 테스트용(test) 으로 분할함
이를 통해 모델의 일반화 성능을 평가할 수 있음
# 데이터셋에서 50% 샘플 추출
df_sampled = df.sample(frac=0.5)
# 데이터셋에서 100개의 샘플 추출
df_sampled_n = df.sample(n=100)
회귀 모델 : 연속적인 값을 예측하는 모델, 주로 숫자 값을 예측하는 데 사용됨
선형 회귀
- 선형 회귀는 종속 변수와 하나 이상의 독립 변수 간의 선형 관계를 모델링하는 방법임
- 독립 변수의 수에 따라 단순 선형회귀 (독립 변수의 수는 1개)와 다중 선형회귀 (독립 변수의 수가 2개 이상)으로 나뉨
선형 회귀 - 다항 회귀
- 다항 회귀는 종속 변수와 독립 변수 간의 비선형 관계를 모델링하는 방법임
- 독립변수의 다항식을 사용하여 관계를 모델링 함
- 차수 선택 : 차수가 높을수록 복잡해지며 과적합이 발생할 가능성이 높아지게 됨
# 필요한 모듈
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
# 선형 회귀
from sklearn.linear_model import LinearRegression
# 모델 평가를 위함
from sklearn.metrics import mean_squared_error, r2_score
# 단순 선형 회귀 데이터 생성
X = np.array([[1, 1], [2, 2], [3, 3], [4, 4], [5, 5],[6,6]])
y = np.array([1, 2, 3, 4, 5, 6])
# 데이터 분할 (훈련 데이터와 테스트 데이터)
# 독립 변수인 x는 대문자로 표기하고 종속 변수인 y는 소문자로 표시하는 것이 관습인 것 같음
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 선형 회귀 모델 생성 -> skikit - learn 을 이용함
model = LinearRegression()
# 모델 학습 : 독립변수 (X)와 종속 변수 (y)의 관계를 파악하는 것이 최종 목적임에 잊지 말자
model.fit(X_train, y_train)
# 예측 -> 독립변수를 인자로 넣어줘 그에 따른 종속 변수를 내뱉게 함
y_pred = model.predict(X_test)
# 모델 평가 -> pred한 값과 종속변수의 test 데이터와 비교함
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f'Mean Squared Error: {mse}')
print(f'R^2 Score: {r2}')
# 다항 회귀
# 1. import 문에 다항 특징 생성을 위한 PolynomialFeatures import
from sklearn.preprocessing import PolynomialFeatures
# 2. 다항 특징 생성 (차수 2)
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)
# 데이터 분할 (X_poly로 해줘야...), 다항 회귀 모델 생성 및 학습, 예측, 모델 평가
# 선형 회귀 모델 생성 및 학습
# 예측
# 모델 평가
로지스틱 회귀는 데이터를 학습하여 각 데이터 포인트가 특정 클래스에 속할 확률을 예측함
예를 들어, 유방암 데이터에서는 환자가 암에 걸렸을 확률, 타이타닉 데이터에서는 승객이 생존할 확률을 예측함
import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# 데이터 로드
data = load_breast_cancer()
X = data.data
y = data.target
# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 이러고 X_train과 X_test의 값들을 살펴보았는데
[[9.029e+00 1.733e+01 5.879e+01 ... 1.750e-01 4.228e-01 1.175e-01]
[2.109e+01 2.657e+01 1.427e+02 ... 2.903e-01 4.098e-01 1.284e-01]
[9.173e+00 1.386e+01 5.920e+01 ... 5.087e-02 3.282e-01 8.490e-02]
...
[1.429e+01 1.682e+01 9.030e+01 ... 3.333e-02 2.458e-01 6.120e-02]
[1.398e+01 1.962e+01 9.112e+01 ... 1.827e-01 3.179e-01 1.055e-01]
[1.218e+01 2.052e+01 7.722e+01 ... 7.431e-02 2.694e-01 6.878e-02]]
[[1.247e+01 1.860e+01 8.109e+01 ... 1.015e-01 3.014e-01 8.750e-02]
[1.894e+01 2.131e+01 1.236e+02 ... 1.789e-01 2.551e-01 6.589e-02]
[1.546e+01 1.948e+01 1.017e+02 ... 1.514e-01 2.837e-01 8.019e-02]
...
[1.152e+01 1.493e+01 7.387e+01 ... 9.608e-02 2.664e-01 7.809e-02]
[1.422e+01 2.785e+01 9.255e+01 ... 8.219e-02 1.890e-01 7.796e-02]
[2.073e+01 3.112e+01 1.357e+02 ... 1.659e-01 2.868e-01 8.218e-02]]
# 이 처럼 그 차이가 꽤나 있음을 확인할 -> Scaling으로 범위 차이를 줄어주어야 함
# 데이터 스케일링
scaler = StandardScaler()
# 학습 데이터에 한해서는 "학습"이 변환과 함께 들어가야 하기 때문에 fit_transform이 쓰인 것이고
# 테스트 데이터에 한해서는 변환만 시도되어도 괜찮기 때문에 transform만 쓰이게 된다.
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 회귀모델 학습
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 모델 생성 및 학습
model = LogisticRegression()
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
# 평가
# accuracy_score : 정확도 계산
print(f"Accuracy: {accuracy_score(y_test, y_pred)}")
# classificaton_report : 분류 보고서 생성
# 정확도, 정밀도, 재현율 등의 매트릭을 포함한 보고서를 출력함
print(f"Classification Report:\n{classification_report(y_test, y_pred)}")
# confusion_matrix : 혼동 행렬 생성 (실제 값과 예측 값 간의)
print(f"Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}")
헷갈렸던 개념
Clustering? : 군집화를 말함
Scaling? : 범위가 다른 두 데이터를 범위를 맞춰주는 작업을 말함
- 처음에는 학습과 테스트 데이터의 결과가 차이가 많이 날 때 사용하나 했으나 그게 아니라
학습 데이터 내에서 이상치가 많은 경우일 때 많이 사용한다고 한다