[에이블런][AI 스타트업 유니버시티] 0805 TIL

2024. 8. 5. 16:50대외활동/ai 유니버시티

데이터마이닝과 머신러닝 

 

데이터마이닝의 목적 (=통찰력)

데이터를 탐색하고 분석하여 유용한 정보나 패턴을 발견하고 이를 통해 유의미한 정보를 추출하여 의사결정에 활용한다. 데이터베이스, 통계, 데이터시각화, 머신러닝 기술 등을 사용

 

 

머신러닝의 목적(=예측모델)

주어진 데이터를 학습하여 예측을 위한 모델을 구축하고 구축된 모델을 통해 자동화된 의사결정 지원

 

데이터 분석 방법론

CRISP-DM(CRoss Industry Standard Process for Data Mining)

 

Modeling  : 데이터에서 패턴을 학습하고 이를 기반으로 예측이나 분류를 수행할 수 있는 수학적 모델을 구축하는 과정

https://www.datascience-pm.com/crisp-dm-2/

 

What is CRISP DM? - Data Science Process Alliance

The CRoss Industry Standard Process for Data Mining (CRISP-DM) is a process model with six phases that describes the data science life cycle.

www.datascience-pm.com

 

1. Business Understanding

비즈니스 관점에서 프로젝트의 목적과 요구사항을 이해하기 위한 단계

 

수행업무

- 데이터분석을 위한 문제정의

- 데이터마이닝 목표 설정

- 초기 프로젝트 계획 수립

 

2. Data Understanding

분석을 위한 데이터를 수집하고 탐색적 데이터 분석(EDA)을 수행하는 단계

 

수행업무

- 초기 데이터 식별 및 수집

- 데이터의 속성 파악 – 속성내용, 자료형, 레코드수 등

- 데이터 품질 확인 – 결측치, 이상치 등

- 데이터 탐색 – 기술통계, 시각화, 상관관계 파악 등

 

3. Data Preparation

모델링을 위하여 데이터를 전처리하는 단계

 

수행업무

- 후보변수 선택, 파생변수 생성

- 데이터 정제 – 결측치 및 이상치 처리 등

- 데이터 변환 - 정규화, 표준화, 인코딩 등

- 데이터 통합 – 여러 소스의 데이터 결합 등

 

4. Modeling

모델링 기법과 알고리즘을 선택하여 모델을 구축하고 모델을 기술적으로 평가하는 단계

 

- 모델링 기법 선택 

- 테스트 설계

- 모델 훈련

- 모델의 기술적 평가 및 파라미터 최적화

 

5. Evaluation

모델링 결과가 비즈니스 목적과 요구사항을 만족하는지 평가하고 다음 수행할 작업을 살펴보는 단계

 

수행업무

- 모델의 적용 적합성 평가

- 모델링 과정 재검토

- 다음 단계 결정 – 반복/배포/새프로젝트

 

6. Deployment

완성된 모델을 실 업무에 적용하기 위한 계획을 세우는 단계

 

수행업무

- 모델 배포계획 수립

- 모니터링 및 유지보수 계획 수립

- 프로젝트 최종보고서 작성 및 프로젝트 리뷰

 

머신러닝

컴퓨터가 명시적으로 프로그래밍되지 않고 데이터를 통해 학습하고 개선할 수 있는 능력을 갖추게 하는 인공지능(AI)의 한 분야

 

지도학습 : 레이블이 있는 훈련 데이터를 사용하여 모델을 학습시키는 방법

비지도학습 : 레이블이 없는 데이터에서 숨겨진 구조를 찾아내는 방법

강화학습 : 에이전트가 환경과 상호작용하여 보상을 최대로 하도록 학습하는 방법

준지도학습 : 레이블이 있는 데이터와 없는 데이터를 함께 사용하는 방법

 

 

 

실습01

 

https://www.kaggle.com/datasets/ashydv/advertising-dataset

 

Advertising Dataset

 

www.kaggle.com

 

[광고 플랫폼에 따른 판매량 예측]

 

문제 정의

광고 플랫폼 별 광고비에 따른 판매량 분석

- TV 광고비에 따른 판매량

- Radio 광고비에 따른 판매량

- Newspaper 광고비에 따른 판매량

 

*(응용)요즘으로 치면?

- SNS 유형에 따른 판매량 예측(인스타, 유튜브, 페이스북, 블로그 등)

- 인스타그램 팔로워 수에 따른 판매량 예측

 

 

 

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use('ggplot')

df = pd.read_csv('https://raw.githubusercontent.com/JayoungKim-ai/ML_dataset/main/advertising.csv')

 

 

# 그래프 크기
plt.figure(figsize=(15,4))

# 첫번째 서브플롯
plt.subplot(1,3,1)
sns.scatterplot(x='TV', y='Sales', data=df)
plt.title('TV_Sales')

# 두번째 서브플롯
plt.subplot(1,3,2)
sns.scatterplot(x='Radio', y='Sales', data=df)
plt.title('Radio_Sales')

# 세번째 서브플롯
plt.subplot(1,3,3)
sns.scatterplot(x='Newspaper', y='Sales', data=df)
plt.title('Newspaper_Sales')

# 그래프 보이기
plt.show()

 

 

sns.heatmap(df.corr(), cmap='Blues', annot=True)
plt.show()

 

X = df['TV']
y = df['Sales']

# 훈련세트, 테스트세트 분할
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)

# 독립변수의 차원 변환(독립변수는 2차원이어야 함)
X_train = X_train.values.reshape(-1,1)
X_test = X_test.values.reshape(-1,1)

print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)

sns.scatterplot(x=X_train.reshape(-1), y=y_train, label="train")
sns.scatterplot(x=X_test.reshape(-1), y=y_test, label="test")
plt.legend()
plt.title("train_test split")
plt.show()

 

# LinearRegression 알고리즘으로 훈련하기 위해 라이브러리 불러오기
from sklearn.linear_model import LinearRegression

# 모델 생성하기
model = LinearRegression()

# 훈련데이터로 모델 훈련하기
model.fit(X_train, y_train)

# 평가 방법 선택 : MSE, R2
from sklearn.metrics import mean_squared_error, r2_score

# 테스트 데이터의 예측값
y_pred = model.predict(X_test)

# 예측값과 실제값의 차이(Loss/Error) 이용한 모델 평가
print('MSE: ', mean_squared_error(y_test, y_pred))
print('R2: ', r2_score(y_test, y_pred))



##MSE:  6.101072906773963
##R2:  0.802561303423698

print(f'기울기:{model.coef_}')
print(f'절편:{model.intercept_}')
print(f'회귀식:{model.coef_[0]} * x + {model.intercept_}')

#기울기:[0.05548294]
#절편:7.007108428241848
#회귀식:0.0554829439314632 * x + 7.007108428241848

plt.figure(figsize=(10,4))

# 테스트데이터 실제값과 예측값 확인
plt.subplot(1,2,1)
sns.scatterplot(x=X_test.reshape(-1), y=y_test, color='gray')# 테스트데이터 실제값
sns.scatterplot(x=X_test.reshape(-1), y=y_pred, color='red') # 테스트데이터 예측값
plt.ylim(0,30)
plt.title('TV_Sales Test')

# 전체 데이터, 회귀선 확인
plt.subplot(1,2,2)
sns.scatterplot(x='TV', y='Sales', data=df, color='gray') # 전체 데이터
x_line = [X.min(), X.max()]
y_line = [model.coef_*X.min()+model.intercept_, model.coef_*X.max()+model.intercept_]
plt.plot(x_line, y_line, color='red') #회귀선
plt.ylim(0,30)
plt.title('TV_Sales regression line')

plt.show()

 

 

# TV 광고비 입력받기
x_tv = float(input('TV 광고비 --> '))
x_tv = np.array(x_tv).reshape(-1,1)

# 모델이 학습한 공식에 대입
print(f'{model.coef_[0] * x_tv[0,0] + model.intercept_}')

# 예측 함수 사용
print(model.predict(x_tv)[0])

 

 

 

 

 

다중회귀

X = df[['TV', 'Radio']]
y = df['Sales']

#데이터 분포의 차이
#큰 범위를 가진 특성이 작은 범위의 특성보다 모델에 더 큰 영향을 미칠 수 있다.
#예: 연봉(수백만 단위)과 나이(수십 단위)를 비교할 때, 스케일링 없이는 연봉이 과도하게 중요시될 수 있다.
#선형 모델이나 신경망은 가중치를 통해 각 특징의 중요성을 평가한다. 값의 범위가 큰 변수는 더 큰 가중치를 가질 가능성이 높고, 이는 모델이 이 변수에 과도하게 의존하게 만들 수 있다. 반면, 값의 범위가 작은 변수는 상대적으로 무시될 수 있다. 이로 인해 모델이 데이터를 제대로 학습하지 못하고 편향된 예측을 할 수 있다.


sns.histplot(df['TV'], bins=20, kde=True, label='TV')
sns.histplot(df['Radio'], bins=20, kde=True, label='Radio')
plt.legend()
plt.show()

 

  • 표준화(Standardization)
    • 값의 범위를 평균이 1이고 표준편차가 1이 되도록 변환
    • 정규 분포를 가정하는 모델: 선형 회귀, 로지스틱 회귀, SVM 등과 같은 모델은 변수들이 정규 분포를 따를 때 더 잘 작동할 수 있다.
# 표준화
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(df[['TV','Radio']])

# 스케일링 한 데이터 확인
print(X_scaled[:,0].mean(), X_scaled[:,1].mean())
print(X_scaled[:,0].std(), X_scaled[:,1].std())


#1.2212453270876723e-16 -4.529709940470639e-16
#1.0 1.0


# 스케일링 후 데이터 분포
sns.histplot(X_scaled[:,0], bins=20, kde=True, label='TV')
sns.histplot(X_scaled[:,1], bins=20, kde=True, label='Radio')
plt.legend()
plt.show()
 

 

 

 

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)

print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)


# LinearRegression 알고리즘으로 훈련하기 위해 라이브러리 불러오기
from sklearn.linear_model import LinearRegression

# 모델 생성하기
model = LinearRegression()

# 훈련데이터로 모델 훈련하기
model.fit(X_train, y_train)

# 평가 방법 선택 : MSE, R2
from sklearn.metrics import mean_squared_error, r2_score

# 테스트 데이터의 예측값
y_pred = model.predict(X_test)

# 예측값과 실제값의 차이(Loss/Error) 이용한 모델 평가
print('MSE: ', mean_squared_error(y_test, y_pred))
print('R2: ', r2_score(y_test, y_pred))

#MSE:  2.8466161221315427
#R2:  0.907879780262465


#과적합 확인하기

# 훈련 데이터의 예측값
y_pred = model.predict(X_train)

# 예측값과 실제값의 차이(Loss/Error) 이용한 모델 평가
print('MSE: ', mean_squared_error(y_train, y_pred))
print('R2: ', r2_score(y_train, y_pred))

#기울기:[4.66797404 1.52920902]
#절편:15.20846608247682
#회귀식:4.6679740362119535 * x_tv + 1.5292090220638832 * x_radio + 15.20846608247682
print(f'기울기:{model.coef_}')
print(f'절편:{model.intercept_}')
print(f'회귀식:{model.coef_[0]} * x_tv + {model.coef_[1]} * x_radio + {model.intercept_}')

 

# TV 광고비 입력받기
x_tv = float(input('TV 광고비 --> '))

# radio 광고비 입력받기
x_radio = float(input('radio 광고비 --> '))

# 입력값 스케일링
x_new = scaler.transform([[x_tv, x_radio]])

# 모델이 학습한 공식에 대입
print(f'{model.coef_[0] * x_new[0,0] + model.coef_[1] * x_new[0,1] + model.intercept_}')

# 예측 함수 사용
print(model.predict([[x_new[0,0],x_new[0,1]]])[0])

 

 

 

#변수를 추가한 경우

print(f'기울기:{model.coef_}')
print(f'절편:{model.intercept_}')
print(f'회귀식:{model.coef_[0]} * x_tv + {model.coef_[1]} * x_radio +{model.coef_[2]}* {model.intercept_}')

 

 

 

 

Logistic Regression

 

로지스틱 회귀 개념

- 종속 변수가 범주형일 때, 수행할 수 있는 회귀분석 기법의 한 종류

- 독립변수들의 선형 결합을 이용하여 개별 관측치가 속하는 집단을 확률로 예측

- 선형회귀의 출력값을 시그모이드 함수에 입력하여 0~1 사이의 확률로변환

 

시그모이드 함수(로지스틱 함수)

결과를 0과 1 사이의 확률로 변환하는 함수

로지스틱 회귀에서는 종속 변수의 값이 0과 1 사이의 확률을 나타내야 하기 때문에, 예측 값이 이 범위 내에 있도록 제한한다.

이를 위해 시그모이드 함수라는 S-형 곡선을 사용한다. 이 함수는 모든 입력값을 0과 1 사이의 값으로 대응시킨다.

 

 

 

 

 

02실습 : 정기예금 가입 여부 예측

문제 정의 : 은행의 마케팅 캠페인 데이터를 사용하여 고객의 가입 여부를 예측

 

- 목표: 고객의 정기예금 가입 여부 예측

- 입력 데이터: 고객의 다양한 특성 정보

- 방법: 분류 모델 개발

- 비즈니스 컨텍스트: 은행의 텔레마케팅 캠페인

 

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 그래프 스타일 설정
plt.style.use('ggplot')

# 사용자 정의 팔레트
custom_palette = {'yes': 'cyan', 'no': 'gray'}


df = pd.read_csv('https://raw.githubusercontent.com/JayoungKim-ai/ML_dataset/main/bank.csv')

# 컬럼 및 독립변수와 종속변수 확인
display(df.head())
display(df.tail())

 

 

데이터 탐색 

- 데이터의 분포 

- 종속변수(deposit)와의 관계

 

plt.pie(df['deposit'].value_counts(), labels=df['deposit'].value_counts().index, autopct='%1.1f%%', colors=['gray','cyan'])
plt.title('Deposit Distribution')
plt.show()

 

비율이 균등하게 나타났지만, 질병 같은 경우 비균등한 결과가 나타날 수 있음(질병 o=1, x=9) 이런 경우 다른 전처리를 진행해야함.

 

# age
# 18세~95세
# 30~59세 : 정기예금 가입율이 낮음
# why?
# 자녀 양육비용? 주택구입으로 인한 대출? 다른 재테크 수단?
plt.figure(figsize=(15,5))
sns.countplot(x='age', data=df, hue='deposit', palette=custom_palette)
plt.xticks(rotation=90)
plt.title('age_deposit')
plt.show()

eda를 통하여 데이터 분포를 파악 -> 차이가 발생한 데이터에 대하여 인과관계를 찾는 과정 필요

 

# job
# 은퇴자, 실직자, 학생 정기예금 가입율이 높음
# 블루컬러 정기예금 가입율 특히 낮음
sns.countplot(x='job', data=df, hue='deposit', palette=custom_palette)
plt.xticks(rotation=90)
plt.title('job_deposit')
plt.show()

# marital
sns.countplot(x='marital', data=df, hue='deposit', palette=custom_palette)
plt.xticks(rotation=90)
plt.title('marital_deposit')
plt.show()

 

 

 

 

 

 

 

 

데이터 전처리

# 독립변수와 종속변수 분리
X = df.drop('deposit', axis=1)
y = df['deposit']

#종속변수의 데이터 변환
y = y.map({'yes': 1, 'no': 0})
y

# 범주형 변수의 레이블 인코딩
# 범주형 변수만 추출하기
objs = X.select_dtypes(include="object").columns.tolist()

# 수치형 변수만 추출하기
nums = df.select_dtypes(exclude="object").columns.tolist()

print(objs)
print(nums)

#['job', 'marital', 'education', 'default', 'housing', 'loan', 'contact', 'month', 'poutcome']
#['age', 'balance', 'day', 'duration', 'campaign', 'pdays', 'previous']



from sklearn.preprocessing import LabelEncoder

# LabelEncoder 객체를 저장할 딕셔너리
encoders = {}

# 원본은 그대로 두고 복사본으로 작업
X_preprocessed = X.copy()

# 각 열에 대해 레이블 인코딩 수행
for obj in objs:
    le = LabelEncoder()
    X_preprocessed[obj] = le.fit_transform(X[obj])
    encoders[obj] = le  # 각 열의 LabelEncoder 저장

# 인코딩된 결과 확인
for obj in objs:
    print(f"Column: {obj}")
    print(f"Classes: {encoders[obj].classes_}")
    print(f"Encoded Values: {X_preprocessed[obj].unique()}")
    print()

display(X.head())
display(X_preprocessed.head())

 

# 수치형데이터의 스케일링
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_preprocessed[nums] = scaler.fit_transform(X[nums])
display(X.head())
display(X_preprocessed.head())

 

 

* 변수 중요도 평가(SelectKBest.. ) 

import numpy as np
import pandas as pd
from sklearn.feature_selection import SelectKBest, f_classif, chi2

# df_preprocessed: 레이블 인코딩된 데이터프레임
# objs: 범주형 변수들의 이름 리스트
# nums: 연속형 변수들의 이름 리스트

# 범주형 변수와 수치형 변후 분리
X_objs = X_preprocessed[objs]
X_nums = X_preprocessed[nums]

# 범주형 변수에 대해 chi2 사용
selector_cat = SelectKBest(score_func=chi2, k='all')
X_new_cat = selector_cat.fit_transform(X_objs, y)
selected_cat_indices = selector_cat.get_support(indices=True)
selected_cat_features = X_objs.columns[selected_cat_indices]
cat_scores = selector_cat.scores_[selected_cat_indices]

# 연속형 변수에 대해 f_classif 사용
selector_cont = SelectKBest(score_func=f_classif, k='all')
X_new_cont = selector_cont.fit_transform(X_nums, y)
selected_cont_indices = selector_cont.get_support(indices=True)
selected_cont_features = X_nums.columns[selected_cont_indices]
cont_scores = selector_cont.scores_[selected_cont_indices]

# 점수와 특성을 데이터프레임으로 결합
selected_features_df = pd.DataFrame({
    'Feature': selected_cat_features.tolist() + selected_cont_features.tolist(),
    'Score': np.concatenate([cat_scores, cont_scores])
})

# 점수 기준으로 정렬
selected_features_df = selected_features_df.sort_values(by='Score', ascending=False)

print("Features sorted by importance:")
print(selected_features_df)

 

도메인 지식 등에 따라 변수 선택 여부가 달라질 수 있음

 

# 다중공선성 : 수치형 변수간의 상관관계 확인
sns.heatmap(abs(X_preprocessed[nums].corr()), cmap='Blues', annot=True)
plt.show()

 

*다중공산성 문제 방지를 위하여 상관관계가 높은 변수를 제거하는 과정을 거치기도 함

 

# 훈련 및 테스트 데이터 분할
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_preprocessed, y, test_size=0.2, random_state=42)
X_train.shape, X_test.shape, y_train.shape, y_test.shape


from sklearn.linear_model import LogisticRegression


#LogisticRegression
# 모델 생성
model_lr = LogisticRegression()

# 훈련데이터로 학습
model_lr.fit(X_train, y_train)

# 예측값
y_pred = model_lr.predict(X_test)

# 정확도
from sklearn.metrics import accuracy_score
print("accuracy_score:", accuracy_score(y_test, y_pred))

# 과적합 확인
print("test accuracy:", model_lr.score(X_test, y_test))
print("train accuracy:", model_lr.score(X_train, y_train))

 

 

정확도 : 전체 데이터 중 몇개를 맞췄는지에 대한 평가지표(= 100개 중 78개를 맞춤)

 

 

# 모델이 학습한 결과

# lr 모델의 계수(coefficients)
print("Coefficients:", model_lr.coef_)

# lr 모델의 절편(intercept)
print("Intercept:", model_lr.intercept_)

 

# 모델의 성능 평가

# 테스트 데이터 예측
y_pred = model_lr.predict(X_test)

# 모델의 평가 지표
from sklearn.metrics import classification_report
print("\nClassification Report:\n", classification_report(y_test, y_pred))

classification_report : 평가지표를 보여주는 함수

 

# 혼동행렬
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(4, 4))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['Predicted 0', 'Predicted 1'], yticklabels=['Actual 0', 'Actual 1'])
plt.xlabel('Predicted Label')
plt.ylabel('Actual Label')
plt.title('Confusion Matrix')
plt.show()

 

# roc_auc
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, roc_auc_score

# 예측 확률 계산
y_pred_proba = model_lr.predict_proba(X_test)[:, 1]

# ROC 곡선 계산
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
roc_auc = roc_auc_score(y_test, y_pred_proba)

# ROC 곡선 그리기
plt.figure()
plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")
plt.show()

점선 : 찍어도 나오는 수치

실선 : 평가값

area = 노란색 실선을 포함하는 면적 (-> 클수록 좋음)

 

# prompt: 모델의 학습 결과 저장

import pandas as pd
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score

# 모델의 학습결과 저장
results = pd.DataFrame(columns=['Model Name','Accuracy','Precision Score','Recall Score','F1-Score','roc_auc'])

y_pred = model_lr.predict(X_test)
model_result = ['Linear Regression',accuracy_score(y_test,y_pred),
              precision_score(y_test,y_pred), recall_score(y_test,y_pred),
              f1_score(y_test,y_pred),roc_auc_score(y_test,y_pred)]
results.loc[len(results)]=model_result
results

 

 

 

 

분류 모델의 성능 평가 지표

F1 Score

- 정밀도와 재현율의 조화평균. 균형을 고려한다.

 

- F1 Score = 2 x 𝑃𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛∗𝑅𝑒𝑐𝑎𝑙𝑙 / 𝑃𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛+𝑅𝑒𝑐𝑎𝑙𝑙

- 값이 클수록 모델의 성능이 좋음을 의미

 

ROC curve (Receiver Operating Characteristic Curve)

- 분류 모델의 성능을 다양한 임계값에서 시각적으로 평가하는 그래프

- X축 : FPR (False Positive Rate). 거짓 양성 비율.

✓ 실제 음성인데 양성으로 잘못 예측한 비율

✓ 𝐹𝑃𝑅 = 𝐹𝑃 𝐹𝑃+𝑇𝑁

- Y축 : TPR (True Positive Rate). 진짜 양성 비율

✓ 실제 양성인데 모델이 양성으로 잘 예측한 비율

✓ 𝑇𝑃𝑅 = 𝑇𝑃 𝑇𝑃+𝐹N

 

AUC (Area Under the Curve)

- ROC 곡선 아래의 면적으로, 모델의 분류 능력을 나타냄

✓ 1: 완벽한 모델

✓ 0.5 : 랜덤 추측과 동일한 모델

✓ <0.5 : 랜덤 추측보다 못한 경우

 

모델 평가

▪️모델의 과적합 확인

학습데이터의 y값과 모델의 예측값을 이용하여 평가

테스트데이터의 y값과 모델의 예측값을 이용하여 평가

 

 

 

K-Nearest Neighbors, KNN 알고리즘

KNN알고리즘 기본 개념

새로운 데이터 포인트의 클래스나 값을 결정할 때, 가장 가까운 K개의 이웃 데이터 포인트를 참조하는 방식

✓ 학습 과정 없이 훈련 데이터에서 가장 가까운 K개의 이웃을 찾아 그들의 정보를 기반으로 분류나 회귀 수행

 

작동 방식

✓ 분류 : K개 이웃의 다수결로 클래스 결정

✓ 회귀 : K개 이웃의 목표 변수 평균으로 예측

 

 

그림출처 :  https://velog.io/@happyhillll/혼공-6장-회귀-문제-이해-k-최근접-이웃-알고리즘으로-풀어보기

 

[혼공] 6장 회귀 문제 이해, k-최근접 이웃 알고리즘으로 풀어보기

이전과 다르게 stratify는 지정하지 않음 : target은 예측값이기 때문에.stratify는 데이터의 개수가 작을경우 반드시 써야함.prach_length : 1차원 배열이기 때문에 train_input, test_input 모두 1차원 배열로 나

velog.io

 

거리측정

✓ 주로 유클리드 거리 사용

✓ 다른 거리 측정법(맨해튼, 민코프스키 등)도 가능

 

• K값 선택

✓ 홀수 선택 (분류 시 동점 방지)

✓ 작은 K : 과적합 위험. 노이즈에 민감

✓ 큰 K : 과소적합 위험 ▪️KNN알고리즘 개념

 

• 장점

✓ 단순성 : 구현이 간단하고 이해하기 쉬움

✓ 훈련 과정이 빠름

 

• 단점

✓ 이상치에 민감 (피처 스케일링이 중요함)

✓ 피처의 중요도를 반영하지 않음

 

KNN알고리즘 분류

① 데이터 준비: 학습 데이터셋 준비. 각 데이터 포인트는 다차원 공간의 점으로 표현

② 거리 측정: 새로운 데이터 포인트가 주어지면, 학습 데이터셋의 각 데이터 포 인트와의 거리를 계산. 거리 측정을 위해 주로 유클리드 거리(Euclidean Distance)를 사용하지만, 맨해튼 거리(Manhattan Distance)나 다른 거 리 측정 방법을 사용할 수도 있다.

③ K개의 이웃 선택: 계산된 거리 중 가장 짧은 거리의 K개의 이웃을 선택

④ 다수결 투표: 선택된 K개의 이웃 중 가장 빈번하게 등장하는 클래스를 새로 운 데이터 포인트의 클래스로 결정 ※ 회귀의 경우 평균 계산: 선택된 K개의 이웃의 값을 평균 내어 새로운 데 이터 포인트의 값을 결정

 

 

거리 측정 방법

 

# prompt: 과적합 해결

import matplotlib.pyplot as plt
# KNN Classifier - 최적의 k 찾기
k_values = range(1, 21)  # 1부터 20까지 k 값 테스트
train_scores = []
test_scores = []

for k in k_values:
    model_knn = KNeighborsClassifier(n_neighbors=k)
    model_knn.fit(X_train, y_train)
    train_scores.append(model_knn.score(X_train, y_train))
    test_scores.append(model_knn.score(X_test, y_test))

# 결과 시각화
plt.plot(k_values, train_scores, label='Train Accuracy')
plt.plot(k_values, test_scores, label='Test Accuracy')
plt.xlabel('k')
plt.ylabel('Accuracy')
plt.title('KNN Accuracy for Different k Values')
plt.legend()
plt.show()

# 최적의 k 값 선택 (테스트 정확도가 가장 높고 과적합이 적은 k)
optimal_k = test_scores.index(max(test_scores)) + 1  # 인덱스는 0부터 시작하므로 1 더함
print("Optimal k:", optimal_k)

# 최적의 k 값으로 모델 재학습 및 평가
best_model_knn = KNeighborsClassifier(n_neighbors=optimal_k)
best_model_knn.fit(X_train, y_train)
y_pred = best_model_knn.predict(X_test)
print("Test accuracy with optimal k:", accuracy_score(y_test, y_pred))

 

 

# prompt: 모델의 학습 결과 저장

y_pred = model_knn.predict(X_test)

model_result = ['KNN',accuracy_score(y_test,y_pred),
              precision_score(y_test,y_pred), recall_score(y_test,y_pred),
              f1_score(y_test,y_pred),roc_auc_score(y_test,y_pred)]
results.loc[len(results)]=model_result
results

 

 

 

Decision Tree (의사결정 트리)

▪️분류

• 데이터의 특성을 바탕으로 분기를 만들어 트리 구조로 의사결정 과정을 모델링하는 방법

▪️회귀

 

분류트리와 회귀트리

 

▪️의사결정트리의 장단점

장점

- 만들어진 모델을 시각화하여 모델이 어떻게 훈련 되었는지 해석하기 쉽니다.

- 데이터의 스케일에 구애받지 않는다. 

- 학습이 끝난 결정트리의 작업 속도가 빠르다.

 

단점

- 과적합이 되는 경향이 있어 모델의 일반화 성능이 좋지 않은 편이다.

 

 

▪️데이터 분할 기준 : 지니불순도(Gini Impurity)

- 의사결정트리에서 데이터의 불순도, 즉 섞임 정도를 측정하는 지표

- 노드에서 무작위로 선택된 샘플이 잘못 분류될 확률을 나타냄

- 데이터가 얼마나 다양하게 섞여있는지, 또는 특정 클래스가 얼마나 혼합되어 있는지를 평가하는 데 사용

- 지니불순도의 최솟값 : 0

-  지니불순도의 최댓값 ∶ 1 − 1 𝑛 (클래스가 2개일 때 0.5, 3개일 때 0.667, 4개일 때 0.75, …)

 

▪️분류된 값이 순도가 높아지도록(불순도가 낮아지도록) 분기

 

▪️의사결정트리 알고리즘

CART

의사결정트리를 만들기 위한 매우 일반적이고 널리 사용되는 알고리즘 • 이진 분할(binary split)을 사용하여 데이터를 분할한다. • 분류 문제에서는 지니 불순도(Gini Impurity), 회귀 문제에서는 평균 제곱 오차(Mean Squared Error)를 최소화하는 방향으로 분할 기준을 선택한다. • 가지치기를 통해 트리의 복잡성을 조절한다. • 사이킷런의 의사결정트리 구현은 CART 알고리즘을 기반으로 한다.

 

CHAID

Chi-squared Automatic Interaction Detector

• 카이제곱 통계량을 사용하여 데이터를 분할하는 알고리즘

• 주로 범주형 데이터에 사용되며, 연속형 데이터를 처리하기 위해서는 이를 범주형으로 변환해야 한다.

• 데이터를 분할할 때 부모와 자식 노드 간의 통계적 유의성을 평가하여 최적의 분할을 선택한다.

 

▪️가지치기(Pruning)

목적 : 트리의 복잡성 감소, 과적합(Overfitting) 방지, 일반화 성능 향상

 

 

주요 parameter'

max_depth : 트리의 최대 깊이 규정. 깊이가 깊어지면 과적합 문제가 발생할 수 있으므로 제어 필요

min_sample_split : 노드를 분할하기 위한 최소한의 샘플 데이터 수(과적합 제어)

min_sample_leaf : leaf(밑단 노드)가 되기 위한 최소한의 데이터 수

max_features : 최적의 분할을 위해 고려할 최대 피처 개수

max_leaf_nodes :  leaf의 최대 개수

 

• 과도한 가지치기는 underfitting을 발생

 

▪️데이터를 여러 구간으로 나누고, 각 구간에 대해 예측 값을 계산하여 입력 데이터에 대응하는 출력을 제공

 

분할 기준

✓ 주로 MSE(Mean Squared Error)를 최소화하는 방향으로 분할

✓ 분산 감소(Variance Reduction)을 목표로 한다. • 예측 방법

✓ 새로운 데이터 포인트가 속하는 리프 노드의 평균값을 예측값으로 사용

• 장점 ✓ 비선형 관계를 모델링할 수 있다.

✓ 특성의 중요도를 쉽게 해석할 수 있다.

✓ 전처리(예:정규화)가 거의 필요 없다.

• 단점

✓ 과적합의 가능성이 있다.

✓ 연속적인 출력보다는 계단 함수 형태의 예측을 한다.

 

 

# 모델 생성 및 훈련
from sklearn.tree import DecisionTreeClassifier
model_dt = DecisionTreeClassifier()
model_dt.fit(X_train, y_train)

# 모델 평가
print("test accuracy:", model_dt.score(X_test, y_test))
print("train accuracy:", model_dt.score(X_train, y_train))

#test accuracy: 0.7586206896551724
#train accuracy: 1.0


# prompt: decisiontree 과적합 해결

# Decision Tree Classifier with Hyperparameter Tuning
from sklearn.model_selection import GridSearchCV

# 모델 생성
model_dt = DecisionTreeClassifier()

# 하이퍼파라미터 튜닝을 위한 그리드 설정
param_grid = {
    'max_depth': [3, 5, 7, 10],
    'min_samples_split': [2, 5, 10],
    'min_samples_leaf': [1, 2, 4]
}

# GridSearchCV를 사용하여 최적의 하이퍼파라미터 찾기
grid_search = GridSearchCV(model_dt, param_grid, cv=5)
grid_search.fit(X_train, y_train)

# 최적의 하이퍼파라미터 출력
print("Best hyperparameters:", grid_search.best_params_)

# 최적의 모델
best_model_dt = grid_search.best_estimator_

# 모델 평가
print("test accuracy:", best_model_dt.score(X_test, y_test))
print("train accuracy:", best_model_dt.score(X_train, y_train))


#Best hyperparameters: {'max_depth': 7, 'min_samples_leaf': 4, 'min_samples_split': 2}
#test accuracy: 0.8150470219435737
#train accuracy: 0.8413036174263635

 

# 모델의 학습 결과 시각화

import matplotlib.pyplot as plt
from sklearn import tree
plt.figure(figsize=(15, 10))
tree.plot_tree(best_model_dt, max_depth=2, feature_names=X_preprocessed.columns, class_names=['No', 'Yes'], filled=True)
plt.show()

 

# 모델의 학습결과 저장

y_pred = best_model_dt.predict(X_test)
model_result = ['Decision Tree Classifier',accuracy_score(y_test,y_pred),
              precision_score(y_test,y_pred), recall_score(y_test,y_pred),
              f1_score(y_test,y_pred),roc_auc_score(y_test,y_pred)]
results.loc[len(results)]=model_result
results

 

 

앙상블 모델

 

Random Forest

여러 개의 의사결정트리(Dicision Tree)를 앙상블(ensemble) 방식으로 결합하여 예측 성능을 향상시키는 기법

 

배깅(Bootstrap Aggregation)

✓ 원래의 학습 데이터셋에서 여러 개의 중복을 허용하는 부트스트랩 샘플(무작위 샘플)을 생성

✓ 각 부트스트랩 샘플을 사용하여 개별 트리 학습

 

랜덤 피처 선택(Random Feature Selection)

✓ 각 트리의 노드 분할 시 모든 피처를 고려하지 않고, 무작위로 선택된 피처의 서브셋만을 사용

✓ 이를 통해 트리 간의 상관성을 줄이고, 모델의 다양성을 증가

 

앙상블(Ensemble) 방식

✓ 분류 문제에서는 다수결(Majority Voting)을 통해 최종 예측 클래스를 결정

✓ 회귀 문제에서는 개별 트리의 평균 예측값을 사용하여 최종 예측

 

 

장점

✓ 강력한 성능 : 단일 트리보다 더 높은 예측 성능

✓ 과적합 방지 : 배깅과 랜덤 피처 선택으로 인해 모델이 훈련 데이터에 과적합 되지 않고, 일반화 성능이 뛰어남

✓ 변수 중요도 : 각 피처의 중요도를 계산하여, 예측에 가장 큰 영향을 미치는 피처를 선택할 수 있음

✓ 견고성 : 노이즈나 일부 결측치에 강하며, 트리의 개수가 많아질수록 모델의 성능이 안정화 됨

 

단점

✓ 복잡성 : 많은 수의 트리를 사용하기 때문에, 모델이 복잡해지고 해석이 어려울 수 있음

✓ 훈련시간 : 개별트리의 수가 많아질수록 학습 시간이 길어짐

 

하이퍼파라미터

✓ n_estimators : 생성할 트리의 수

✓ 개별 트리에 대해서는 단일트리의 하이퍼라미터와 동일

 

# 모델 생성 및 훈련
from sklearn.ensemble import RandomForestClassifier
model_rf = RandomForestClassifier()
model_rf.fit(X_train, y_train)

# 모델 평가
print("test accuracy:", model_rf.score(X_test, y_test))
print("train accuracy:", model_rf.score(X_train, y_train))

#test accuracy: 0.8343036274070756
#train accuracy: 1.0

#과적합 발생

# prompt: RandomizedSearchCV로 최적화해줘.

from sklearn.model_selection import RandomizedSearchCV

# 모델 생성
model_rf = RandomForestClassifier()

# 하이퍼파라미터 튜닝을 위한 그리드 설정
param_dist = {
    'n_estimators': [50, 100, 200],
    'max_depth': [None, 10, 20, 30],
    'min_samples_split': [2, 5, 10],
    'min_samples_leaf': [1, 2, 4]
}

# RandomizedSearchCV를 사용하여 최적의 하이퍼파라미터 찾기
random_search = RandomizedSearchCV(model_rf, param_distributions=param_dist, n_iter=10, cv=5)
random_search.fit(X_train, y_train)

# 최적의 하이퍼파라미터 출력
print("Best hyperparameters:", random_search.best_params_)

# 최적의 모델
best_model_rf = random_search.best_estimator_

# 모델 평가
print("test accuracy:", best_model_rf.score(X_test, y_test))
print("train accuracy:", best_model_rf.score(X_train, y_train))


#Best hyperparameters: {'n_estimators': 200, 'min_samples_split': 10, 'min_samples_leaf': 1, 'max_depth': None}
#test accuracy: 0.8307210031347962
#train accuracy: 0.9445626609922724
# 모델의 학습결과 저장

y_pred = best_model_rf.predict(X_test)
model_result = ['RandomFroest Classifier',accuracy_score(y_test,y_pred),
              precision_score(y_test,y_pred), recall_score(y_test,y_pred),
              f1_score(y_test,y_pred),roc_auc_score(y_test,y_pred)]
results.loc[len(results)]=model_result
results

 

Gradient Boosting

▪️Gradient Boosting 기본 개념

 

- Boosting 모델 : 일련의 학습기들을 순차적으로 학습시키며, 각 학습기는 이전 학습기들의 오류를 보정하는 방식으로 학습 

- Gradient Boosting은 손실 함수(loss function)의 그래디언트를 따라 각 학습기를 학습시키는 것이 특징

- 회귀와 분류 모델에 모두 사용할 수 있다.

- 성능이 뛰어나다

 

변형 모델

✓ XGBoost (Extreme Gradient Boosting): 정규화, 병렬처리 등 최적화 기능 추가

✓ LightGBM (Light Gradient Boosting Machine): 더 빠른 학습 속도, 큰 데이터셋에 효과적

✓ CatBoost: 범주형 변수 처리 개선, 오버피팅 방지 기법 포함

 

① 초기 모델 생성: 학습을 시작하기 위해 간단한 모델(일반 적으로 평균값)을 생성합니다.

② 잔여 오차(residual error) 계산: 현재 모델의 예측값과 실제 값 사이의 잔여 오차를 계산합니다.잔여 오차에 대 한 새로운

③ 모델 학습: 잔여 오차를 예측하도록 새로운 학습기를 학 습시킵니다.

④ 모델 업데이트: 학습된 모델을 현재 모델에 추가합니다.

⑤ 반복: 지정된 횟수만큼 또는 오차가 충분히 작아질 때까 지 2~4 과정을 반복합니다.

 

# XGBoost
!pip install xgboost
from xgboost import XGBClassifier

# 모델 생성 및 훈련
model_xgb = XGBClassifier()
model_xgb.fit(X_train, y_train)

# 모델 평가
print("test accuracy:", model_xgb.score(X_test, y_test))
print("train accuracy:", model_xgb.score(X_train, y_train))


#test accuracy: 0.8423645320197044
#train accuracy: 0.9618098331280098

# 모델의 학습결과 저장
y_pred = model_xgb.predict(X_test)
model_result = ['XGBoost',accuracy_score(y_test,y_pred),
              precision_score(y_test,y_pred), recall_score(y_test,y_pred),
              f1_score(y_test,y_pred),roc_auc_score(y_test,y_pred)]
results.loc[len(results)]=model_result
results

 

 

Naïve Bayes Classification

▪️Naïve Bayes 분류기의 개념 및 가정

 

개념 : Bayes 정리를 기반으로 한 확률적 분류 알고리즘

✓ 조건부 확률 : 다른 이벤트가 발생했을 때 어떤 이벤트가 발생할 확률.

✓ P(Y|X) = 𝑃(𝑋 𝑎𝑛𝑑 𝑌) / 𝑃(𝑋)

 

Naive한 가정 : 모든 특징(feature)들이 서로 독립적이며, 모든 특징들이 결과에 동등하게 기여한다.

✓ 각 특징에 대해 독립적으로 확률을 계산한 후 이를 결합하여 최종 확률을 산출한다.

✓ 장점 : 특징(feature)이 너무 많은 경우 특징간의 연관관계를 모두 고려하게 되면 너무 복잡해지는 경향이 있다. 특징 (feature)들이 서로 독립이라는 가정으로 분류를 쉽고 빠르게 할 수 있다.

✓ 단점 : 독립성 가정은 현실에서 항상 성립하지는 않으며, 이 가정에 위반되는 경우 에러를 발생시킬 수 있다.

 

 

▪️Bayes 추정

추론 대상의 사전 확률과 추가적인 정보를 기반으로 해당 대상의 사후 확률을 추론하는 통계적 방법

✓ 사전확률 : 사건이 발생하기 전에 이미 알고 있는 사건의 확률

✓ 사후확률 : 어떤 증거가 주어졌을 때, 그 증거를 바탕으로 사건이 발생할 확률

 

 

 

 

추론 대상의 사전 확률과 추가적인 정보를 기반으로 해당 대상의 사후 확률을 추론하는 통계적 방법

✓ 사전확률 : 사건이 발생하기 전에 이미 알고 있는 사건의 확률 (label만으로 구할 수 있는 확률)

✓ 사후확률 : 어떤 증거가 주어졌을 때, 그 증거를 바탕으로 사건이 발생할 확률

 

어떤 사람이 양성 판정을 받았을 때, 이 사람이 암환자일 확률은?

 

✓ 양성 판정을 받을 활률 P (+)

= 암환자가 양성판정을 받을 확률 + 암이 아닌 환자가 양성판정을 받을 확률 = 𝑃 + 𝐶 ∗ 𝑃 𝐶 + 𝑃 + ~𝐶 ∗ 𝑃(~𝐶) = 0.905 ∗ 0.105 + 0.204 ∗ 0.895 = 0.277605

 

응용분야

- 스팸메일 필터링 : 이메일의 단어를 특징으로 하여 스팸인지 아닌지 분류

- 감성분석 : 텍스트데이터의 단어를 특징으로 하여 감정(긍정,부정,중립 등)을 분석

- 문서분류 : 텍스트데이터의 단어를 특징으로 하여 뉴스기사, 논문 등을 주제별로 분류

- 의료진단 : 증상에 다른 질병 예측

- 추천시스템 : 사용자 과거 행동 데이터 및 프로필 기반으로 선호할 만한 제품 추천

 

 

• 가우시안 나이브 베이즈 (Gaussian Naive Bayes)

✓ 연속형 데이터에 사용, 특성이 정규 분포를 따른다고 가정. 각 특징의 평균과 분산을 사용하여 조건부 확률을 계산.

✓ 응용: 실수값 특성을 가진 데이터 분류

• 다항 나이브 베이즈 (Multinomial Naive Bayes)

✓ 이산형 데이터에 사용, 특성이 다항 분포를 따른다고 가정. 특정 클래스 내에서의 단어 빈도나 발생 횟수를 모델링

✓ 응용: 텍스트 분류, 문서 분류

• 베르누이 나이브 베이즈 (Bernoulli Naive Bayes)

✓ 이진 데이터에 사용, 특성이 베르누이 분포를 따른다고 가정. 각 특징이 0 또는 1의 값을 가지며, 특정 클래스 내에서의 단 어 존재 여부를 모델링

✓ 응용: 텍스트 분류 (단어의 존재/부재만 고려)

• 보완 나이브 베이즈 (Complement Naive Bayes)

✓ 다항 나이브 베이즈의 변형, 불균형 데이터셋에 효과적

✓ 응용: 클래스 불균형이 심한 텍스트 분류 문제

• 범주형 나이브 베이즈 (Categorical Naive Bayes)

✓ 범주형 데이터에 사용

✓ 응용: 범주형 특성을 가진 데이터 분류

 

# prompt: Naive Bayes 모델 생성 및 훈련

from sklearn.naive_bayes import GaussianNB

# 모델 생성 및 훈련
model_nb = GaussianNB()
model_nb.fit(X_train, y_train)

# 모델 평가
print("test accuracy:", model_nb.score(X_test, y_test))
print("train accuracy:", model_nb.score(X_train, y_train))

# 모델의 학습결과 저장
y_pred = model_nb.predict(X_test)
model_result = ['Naive Bayes',accuracy_score(y_test,y_pred),
              precision_score(y_test,y_pred), recall_score(y_test,y_pred),
              f1_score(y_test,y_pred),roc_auc_score(y_test,y_pred)]
results.loc[len(results)]=model_result
results

 

 

 

# 예측할 데이터
data = pd.DataFrame(
    [[40,'admin.','married','tertiary','no',3000,'yes','no','cellular',5,'aug',1042,1,-1,0,'unknown'],
        [19,'student','single','secondary','no',100,'no','no','unknown',1,'may',673,4,-1,0,'unknown'],
        [35,'services','married','tertiary','yes',1000,'no','no','telephone',8,'jul',257,1,-1,0,'unknown']],
    columns=X.columns
)
data

 

# 레이블 인코딩
data_preprocessed = data.copy()
for obj in objs:
    le = encoders[obj]
    data_preprocessed[obj] = le.transform(data[obj])
data_preprocessed

 

# 정규화
data_preprocessed[nums] = scaler.transform(data[nums])
data_preprocessed

 

 

# LogisticRegression으로 예측하기
y_pred = model_lr.predict(data_preprocessed)
y_pred_proba = model_lr.predict_proba(data_preprocessed)
print('예측결과(1:가입, 0:미가입):',y_pred)
print('정기예금에 가입할 확률:',y_pred_proba[:,1])


#예측결과(1:가입, 0:미가입): [1 1 0]
#정기예금에 가입할 확률: [0.96451957 0.68598855 0.33924705]

# knn으로 예측하기
y_pred = model_knn.predict(data_preprocessed)
y_pred_proba = model_knn.predict_proba(data_preprocessed)
print('예측결과(1:가입, 0:미가입):',y_pred)
print('정기예금에 가입할 확률:',y_pred_proba[:,1])


#예측결과(1:가입, 0:미가입): [1 0 0]
3정기예금에 가입할 확률: [0.8  0.15 0.15]

# Decision Tree로 예측하기
y_pred = best_model_dt.predict(data_preprocessed)
y_pred_proba = best_model_dt.predict_proba(data_preprocessed)
print('예측결과(1:가입, 0:미가입):',y_pred)
print('정기예금에 가입할 확률:',y_pred_proba[:,1])

#예측결과(1:가입, 0:미가입): [1 1 0]
#정기예금에 가입할 확률: [0.90196078 0.76506024 0.41617357]



# Random Forest로 예측하기
y_pred = best_model_rf.predict(data_preprocessed)
y_pred_proba = best_model_rf.predict_proba(data_preprocessed)
print('예측결과(1:가입, 0:미가입):',y_pred)
print('정기예금에 가입할 확률:',y_pred_proba[:,1])

#예측결과(1:가입, 0:미가입): [1 1 0]
#정기예금에 가입할 확률: [0.88424189 0.62458441 0.49814325]


# XGBoost로 예측하기
y_pred = model_xgb.predict(data_preprocessed)
y_pred_proba = model_xgb.predict_proba(data_preprocessed)
print('예측결과(1:가입, 0:미가입):',y_pred)
print('정기예금에 가입할 확률:',y_pred_proba[:,1])

#예측결과(1:가입, 0:미가입): [1 1 0]
#정기예금에 가입할 확률: [0.95011985 0.6929441  0.43498945]

 

 

03_공공자전거 수요 예측_실습

# 한글폰트 설치(실행 후 세션 다시 시작)
!pip install koreanize-matplotlib


# 라이브러리 임포트
import koreanize_matplotlib
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 그래프 스타일 지정
plt.style.use('ggplot')

# 한글 폰트 테스트
pd.Series([-2,1,2]).plot(figsize=(4,2), title="한글폰트테스트")
plt.show()

 

# datetime 컬럼은 datetime 형식으로 읽어오도록 옵션 설정
df = pd.read_csv('https://raw.githubusercontent.com/JayoungKim-ai/ML_dataset/main/BikeSharingDemand.csv', parse_dates=['datetime'])
display(df.head(3))
display(df.tail(3))
# 연, 월, 일, 시, 요일, 분기
df['year'] = df['datetime'].dt.year
df['month'] = df['datetime'].dt.month
df['day'] = df['datetime'].dt.day
df['hour'] = df['datetime'].dt.hour
df['dayofweek'] = df['datetime'].dt.dayofweek # 월요일:0, 일요일:6
df.head()

 

데이터탐색

 

 

 

 

 

 

 

 

 

다중공산성 방지를 위하여 atemp, temp 중 하나의 변수만 선택

X = df[['holiday','workingday','weather','temp','humidity','windspeed','year','month','day','hour','dayofweek']].copy()
y = df['count'].copy()


#데이터 전처리
# 연속형 변수 스케일링
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X[['temp','humidity','windspeed']] = scaler.fit_transform(df[['temp','humidity','windspeed']])
X.head(3)

# year-2000
X['year'] = df['year']-2010


# 데이터 분할
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train.shape, X_test.shape, y_train.shape, y_test.shape

 

from sklearn.linear_model import LinearRegression

# 모델 생성 및 훈련
model_lr = LinearRegression()
model_lr.fit(X_train, y_train)

# 과적합 확인
print('train:',model_lr.score(X_train, y_train))
print('test:',model_lr.score(X_test, y_test))


#train: 0.3858940229309653
#test: 0.39517692278681493

from sklearn.neighbors import KNeighborsRegressor

# 모델 생성 및 훈련
model_knn = KNeighborsRegressor()
model_knn.fit(X_train, y_train)

# 과적합 확인
print('train:',model_knn.score(X_train, y_train))
print('test:',model_knn.score(X_test, y_test))

#train: 0.8978743323339545
#test: 0.8357469724492553

from sklearn.tree import DecisionTreeRegressor

# 모델 생성 및 훈련
model_dt = DecisionTreeRegressor()
model_dt.fit(X_train, y_train)

# 과적합 확인
print('train:',model_dt.score(X_train, y_train))
print('test:',model_dt.score(X_test, y_test))

#train: 1.0
#test: 0.899884455809497


from sklearn.ensemble import RandomForestRegressor

# 모델 생성 및 훈련
model_rf = RandomForestRegressor()
model_rf.fit(X_train, y_train)

# 과적합 확인
print('train:',model_rf.score(X_train, y_train))
print('test:',model_rf.score(X_test, y_test))

#train: 0.9927365824898922
#test: 0.9532195060040306





# prompt: 최적의 모델 찾아줘.

from sklearn.model_selection import GridSearchCV

# 탐색할 매개변수 그리드 정의
param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [None, 10, 20],
    'min_samples_split': [2, 5, 10]
}

# GridSearchCV 객체 생성
grid_search = GridSearchCV(estimator=RandomForestRegressor(), param_grid=param_grid, cv=5)

# 훈련 데이터에 그리드 검색 적용
grid_search.fit(X_train, y_train)

# 최적의 매개변수 출력
print("Best parameters: ", grid_search.best_params_)

# 최적의 모델 출력
best_model = grid_search.best_estimator_
print("Best model: ", best_model)

# 테스트 데이터에서 최적 모델의 성능 평가
print('test:', best_model.score(X_test, y_test))


#Best parameters:  {'max_depth': None, 'min_samples_split': 2, 'n_estimators': 100}
#Best model:  RandomForestRegressor()
#test: 0.9531235441726251

 

 

df_pred = pd.read_csv('https://raw.githubusercontent.com/JayoungKim-ai/ML_dataset/main/BikeSharingDemand_pred.csv',parse_dates=['datetime'])
df_pred.head()


# 연, 월, 일, 시, 요일 추가
df_pred['year'] = df_pred['datetime'].dt.year
df_pred['month'] = df_pred['datetime'].dt.month
df_pred['day'] = df_pred['datetime'].dt.day
df_pred['hour'] = df_pred['datetime'].dt.hour
df_pred['dayofweek'] = df_pred['datetime'].dt.dayofweek # 월요일:0, 일요일:6

# 컬럼 선택
X_pred = df_pred[['holiday','workingday','weather','temp','humidity','windspeed','year','month','day','hour','dayofweek']].copy()

# 연속형 변수 스케일링
X_pred[['temp','humidity','windspeed']] = scaler.transform(df_pred[['temp','humidity','windspeed']])

# year-2000
X_pred['year'] = df_pred['year']-2010

X_pred.head()


# 예측
y_pred = best_model.predict(X_pred)
df_pred['count'] = y_pred
df_pred.head()



# 예측결과 확인
sns.lineplot(data=df_pred, x='hour', y='count', marker='o', hue='dayofweek', palette='Set1')
plt.title('요일-시간에 따른 총 대여량')
plt.show()

 

# 예측결과 확인
sns.regplot(data=df, x='temp', y='count', color='gray', line_kws={'color':'red'}, marker='.')
plt.title('기온에 따른 대여량')
plt.show()

 

04_와인품종예측_실습

 

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

#그래프 스타일
plt.style.use('ggplot')

from sklearn.datasets import load_wine
import pandas as pd

# 데이터셋 로드
wine = load_wine()

# 특징 데이터와 타겟 데이터를 데이터프레임으로 변환
df = pd.DataFrame(data=wine.data, columns=wine.feature_names)
df['target'] = wine.target

# 데이터셋 정보 출력
df.head()

# prompt: Target의 종류 확인

# Target의 종류 확인
df['target'].unique()


# prompt: 데이터 정보 확인

# 데이터 정보 확인
df.info()


# prompt: 데이터의 크기 확인

# 데이터의 크기 확인
df.shape


# prompt: Target을 제외한 나머지 변수들의 분포를 박스플롯으로 확인

import matplotlib.pyplot as plt
# Target을 제외한 나머지 변수들의 분포를 박스플롯으로 확인
plt.figure(figsize=(12, 10))
sns.boxplot(data=df.drop('target', axis=1))
plt.xticks(rotation=45)
plt.show()

 

스케일링 하지 않고 학습하기

 

# prompt: Target을 종속변수로 하고 나머지를 독립변수로 지정

# Target을 종속변수로 하고 나머지를 독립변수로 지정
X = df.drop('target', axis=1)
y = df['target']

# prompt: X, y 데이터 확인

display(X.head())
display(y.head())
# prompt: 훈련데이터화 테스트데이터 분할

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# prompt: Logistic Regression 모델 생성 및 학습하고, 평가 데이터 확인

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# 모델 생성 및 학습
model = LogisticRegression()
model.fit(X_train, y_train)

# 예측
y_pred = model.predict(X_test)

# 정확도 평가
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

Accuracy: 0.9722222222222222

 

# prompt: DecisionTree 모델 생성 및 학습하고, 평가

from sklearn.tree import DecisionTreeClassifier

# 모델 생성 및 학습
model = DecisionTreeClassifier()
model.fit(X_train, y_train)

# 예측
y_pred = model.predict(X_test)

# 정확도 평가
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)



#Accuracy: 0.9444444444444444

# prompt: KNN 모델 생성하고 평가

from sklearn.neighbors import KNeighborsClassifier

# 모델 생성 및 학습
model = KNeighborsClassifier()
model.fit(X_train, y_train)

# 예측
y_pred = model.predict(X_test)

# 정확도 평가
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

#Accuracy: 0.7222222222222222

스케일링하고 학습하기

# prompt: 독립변수 스케일링

from sklearn.preprocessing import StandardScaler

# 스케일링 객체 생성
scaler = StandardScaler()

# 훈련 데이터에 스케일링 적용
X_train_scaled = scaler.fit_transform(X_train)

# 테스트 데이터에 스케일링 적용 (훈련 데이터의 스케일링 정보를 사용)
X_test_scaled = scaler.transform(X_test)



# prompt: 스케일링 된 독립변수의 분포를 박스플롯으로 확인

import pandas as pd
import matplotlib.pyplot as plt
# 스케일링 된 독립변수를 데이터프레임으로 변환
df_scaled = pd.DataFrame(data=X_train_scaled, columns=wine.feature_names)

# 박스플롯으로 분포 확인
plt.figure(figsize=(12, 10))
sns.boxplot(data=df_scaled)
plt.xticks(rotation=45)
plt.show()

 

# prompt: # Logistic Regression으로 훈련하고 평가

# 모델 생성 및 학습
model = LogisticRegression()
model.fit(X_train_scaled, y_train)

# 예측
y_pred = model.predict(X_test_scaled)

# 정확도 평가
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

#Accuracy: 1.0


# prompt: DecisionTree로 훈련하고 평가

# 모델 생성 및 학습
model = DecisionTreeClassifier()
model.fit(X_train_scaled, y_train)

# 예측
y_pred = model.predict(X_test_scaled)

# 정확도 평가
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

#Accuracy: 0.9444444444444444



# prompt: KNN으로 훈련하고 평가

# 모델 생성 및 학습
model = KNeighborsClassifier()
model.fit(X_train_scaled, y_train)

# 예측
y_pred = model.predict(X_test_scaled)

# 정확도 평가
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

#Accuracy: 0.9444444444444444
# prompt: 예측값 출력하기

# 예측값 출력
print(y_pred)


# prompt: 클래스 별 확률 출력하기

# 모델 예측 확률
y_proba = model.predict_proba(X_test_scaled)

# 클래스별 확률 출력
for i in range(len(y_proba)):
  print(f"{i+1}번째 데이터의 클래스별 확률: {y_proba[i]}")