본문 바로가기

파이썬 & 머신러닝과 딥러닝

SVM, K-means 클러스터링, 의사결정나무, 로지스틱회귀

SVM ( Support Vector Machine )

  • 주로 분류(classification) 및 회귀(regression) 분석에 사용되는 강력한 기계 학습 모델.
  • SVM은 데이터를 여러 차원에서 분리하는 가상의 경계선(초평면)을 설정하여 클래스 간의 경계를 최대화하는 방식
  • 새로운 데이터가 입력되면 해당 데이터가 속한 범주를 찾기 위해 대상이 된 집단의 범주를 설정하기 위한 작업 수행
  • 대상 집단을 구분 짓는 기준선을 결정하는 모델이 SVM

 

 

SVM의 핵심 개념

1. 가상의 경계선 (Hyperplane)

  • SVM은 데이터를 두 개의 클래스로 분류하는 가상의 경계선(초평면)을 찾는다.
  • 이 경계선은 데이터 포인트 간의 거리를 최대화하여 분리. 즉, 클래스 간의 여유를 최대화하는 방향으로 설정됨.

2. 마진 (Margin)

  • 마진은 두 클래스 사이의 가장 가까운 데이터 포인트 간의 거리.
  • SVM은 이 마진을 최대화하는 경계선을 찾는 것이 목표임.
  • 경계선에서 가장 가까운 데이터 포인트들은 서포트 벡터(Support Vectors)라고 불리며, 실제 초평면을 정의하는데 중요함.

3. 서포트 벡터 (Support Vectors)

  • 서포트 벡터는 각 클래스의 초평면에 가장 가까운 데이터 포인트.
  • 서포트 벡터는 초평면의 위치를 결정하며, 이 데이터 포인트들이 최적의 경계를 정의.

4. 선형 분리 vs. 비선형 분리

  • 선형 분리(Linear Separation): 데이터가 선형으로 분리 가능한 경우, SVM은 직선(또는 초평면)을 찾아 데이터를 분리.
  • 비선형 분리(Non-linear Separation): 데이터가 선형으로 분리할 수 없는 경우, SVM은 커널 기법(Kernel Trick)을 사용하여 고차원 공간으로 데이터를 변환한 후 선형 분리를 수행.

5. 커널 기법 (Kernel Trick)

  • 커널 기법은 데이터를 고차원 공간으로 매핑하여 비선형 데이터를 선형적으로 분리할 수 있게 해준다.
  • SVM에서 일반적으로 사용되는 커널로는 다항식 커널(Polynomial Kernel), 가우시안 RBF 커널(Radial Basis Function Kernel), 시그모이드 커널(Sigmoid Kernel) 등이 있다.

 

SVM의 작동 원리

1. 초평면 찾기

  • SVM은 각 클래스에 대해 서로 가장 멀리 떨어진 초평면을 찾고, 이 초평면 중간의 최적 경계를 찾는다.
  • 수학적으로 이 초평면은 w \cdot x + b = 0이라는 방정식으로 표현됨.
    • w는 가중치 벡터
    • b는 바이어스(절편)

2. 최대 마진 경계

  • SVM은 두 클래스 사이의 마진을 최대화하는 초평면을 찾는다.
  • 마진이 최대화된다는 것은 서포트 벡터와 초평면 사이의 거리가 최대가 된다는 의미.

3. 서포트 벡터와 초평면의 거리 계산

  • 서포트 벡터는 초평면에서 가장 가까운 데이터 포인트이며, 이 데이터 포인트들은 최적 경계의 결정에 영향을 미침.
  • 최적 경계는 이 서포트 벡터들의 위치에 따라 결정됨.

4. 비선형 분리 및 커널 기법

  • 비선형 데이터를 분리하기 위해 커널 기법을 사용하여 데이터를 고차원으로 변환.
  • 이 변환된 공간에서 선형 초평면을 찾아 비선형 문제를 해결한다.

 

Boston Housing 데이터셋을 이용한 SVM 모델 학습 및 시각화

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sklearn.model_selection as sms
import sklearn.svm as skv
from sklearn.preprocessing import StandardScaler

# 큰 데이터셋을 표시할 때 모든 행과 열을 보이게 설정
pd.set_option('display.max_rows', None)  # 데이터프레임의 최대 행 수를 무제한으로 설정
pd.set_option('display.max_columns', None)  # 데이터프레임의 최대 열 수를 무제한으로 설정

# 데이터셋 로드
file_path = 'boston.csv'
pd_DataSet = pd.read_csv(file_path)  # CSV 파일에서 데이터프레임 생성

# 데이터프레임 생성 및 결측값 제거
DF = pd.DataFrame(pd_DataSet)
New_DF = DF.dropna(how='any')  # 결측값이 포함된 모든 행을 제거

# 독립 변수(특징)와 목표 변수(종속 변수) 선택
threshold = 25  # MEDV의 임계값을 정의하여 이진 분류 문제 생성

# 특징 선택
x = New_DF[['RM', 'LSTAT']]  # 'RM' (방의 수)와 'LSTAT' (저소득층 비율) 선택
y = (New_DF['MEDV'] >= threshold).astype(int)  # MEDV가 임계값 이상이면 1, 그렇지 않으면 0으로 설정

# 데이터셋을 학습 데이터와 테스트 데이터로 분리
x_train, x_test, y_train, y_test = sms.train_test_split(x, y, train_size=0.8, test_size=0.2, random_state=42)
# train_size=0.8: 80%를 학습 데이터로, 20%를 테스트 데이터로 사용

# 스케일 조정: StandardScaler 사용
scaler = StandardScaler()
x_train_scaled = scaler.fit_transform(x_train)  # 학습 데이터에 대해 스케일 조정 및 피팅
x_test_scaled = scaler.transform(x_test)  # 테스트 데이터에 대해 스케일 조정

# SVM 모델 학습
SVM_Model = skv.SVC(kernel='linear', C=1, decision_function_shape='ovr')  # 선형 커널을 사용하는 SVM 모델 생성
SVM_Model.fit(x_train_scaled, y_train)  # 학습 데이터로 모델 학습

# 모델 평가
Train_score = SVM_Model.score(x_train_scaled, y_train)  # 학습 데이터에 대한 정확도 계산
Test_score = SVM_Model.score(x_test_scaled, y_test)  # 테스트 데이터에 대한 정확도 계산

print('SVM - Train_score:', Train_score, ', Test_score:', Test_score)

# 예측할 새로운 데이터 포인트
new_data = [[6.5, 10]]  # 예측할 새로운 데이터 포인트 (방의 수: 6.5, 저소득층 비율: 10)

# 스케일 조정 후 예측
new_data_scaled = scaler.transform(new_data)  # 새로운 데이터 포인트에 대해 스케일 조정
prediction = SVM_Model.predict(new_data_scaled)  # 예측 수행
print('-----------------------------')
print('새로운 데이터 포인트 예측 결과:', prediction)

# 랜덤한 예측용 데이터 생성
n_predict_samples = 5  # 예측할 데이터 샘플 수
np.random.seed(100)  # 랜덤 시드 설정

# 임의의 데이터 생성 (방의 수는 3에서 9 사이, 저소득층 비율은 1에서 30 사이)
X1_predict = np.random.uniform(3, 9, n_predict_samples)
X2_predict = np.random.uniform(1, 30, n_predict_samples)
Pre_S_Parm = pd.DataFrame({'RM': X1_predict, 'LSTAT': X2_predict})

# 스케일 조정
Pre_S_Parm_scaled = scaler.transform(Pre_S_Parm)  # 랜덤 데이터 포인트에 대해 스케일 조정

# 예측 수행
predict_sR = SVM_Model.predict(Pre_S_Parm_scaled)  # 예측 수행

print('-----------------------------')
print('랜덤하게 생성된 데이터 예측 결과:')
print(Pre_S_Parm)
print(predict_sR)

# 시각화 함수 정의
def plot_decision_boundary(X, y, model, ax):
    h = .02  # 메쉬의 단계 크기
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1  # X축의 범위 설정
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1  # Y축의 범위 설정
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))

    Z = model.decision_function(np.c_[xx.ravel(), yy.ravel()])  # 결정 함수 계산
    Z = Z.reshape(xx.shape)  # 결정 함수 값을 메쉬의 모양으로 변환

    # 결정 경계 및 마진 시각화
    ax.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.coolwarm)
    ax.contour(xx, yy, Z, colors='k', levels=[-1, 0, 1], linestyles=['--', '-', '--'])
    ax.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', cmap=plt.cm.coolwarm, s=50)  # 데이터 포인트 시각화
    ax.set_xlim(xx.min(), xx.max())  # X축 범위 설정
    ax.set_ylim(yy.min(), yy.max())  # Y축 범위 설정
    ax.set_xlabel('RM')  # X축 레이블
    ax.set_ylabel('LSTAT')  # Y축 레이블
    ax.set_title('SVM Decision Boundary with Margin')  # 그래프 제목

# 시각화
fig, ax = plt.subplots(figsize=(10, 6))

# 결정 경계와 데이터 포인트 시각화
plot_decision_boundary(x_train_scaled, y_train, SVM_Model, ax)

# 새로운 데이터 포인트 시각화
new_data = [[6.5, 10]]
new_data_scaled = scaler.transform(new_data)
ax.scatter(new_data_scaled[0][0], new_data_scaled[0][1], c='red', edgecolors='k', s=100, marker='x', label='New Data Point')

# 랜덤 데이터 포인트 시각화
n_predict_samples = 5
np.random.seed(100)
X1_predict = np.random.uniform(3, 9, n_predict_samples)
X2_predict = np.random.uniform(1, 30, n_predict_samples)
Pre_S_Parm = pd.DataFrame({'RM': X1_predict, 'LSTAT': X2_predict})
Pre_S_Parm_scaled = scaler.transform(Pre_S_Parm)

# 랜덤 데이터 포인트 시각화
ax.scatter(Pre_S_Parm_scaled[:, 0], Pre_S_Parm_scaled[:, 1], c='green', edgecolors='k', s=100, marker='o', label='Random Data Points')

# 레이블 및 제목 설정
ax.legend()
plt.show()

 

 

  • Train_score: 0.9134: 학습 데이터에 대해 SVM 모델이 91.34%의 정확도를 달성했음을 나타냄. 즉, 학습 데이터에서 91.34%의 샘플을 올바르게 분류했음.
  • Test_score: 0.9020: 테스트 데이터에 대해 SVM 모델이 90.20%의 정확도를 달성했음을 나타냄. 즉, 테스트 데이터에서 90.20%의 샘플을 올바르게 분류함.
  • 이 결과는 모델이 학습 데이터와 테스트 데이터 모두에서 잘 작동하고 있음을 의미.

 

새로운 데이터 포인트 [6.5, 10]에 대한 예측 결과가 [0].

이는 모델이 이 데이터 포인트를 클래스 0으로 분류했음을 의미합니다. 즉, MEDV가 임계값 25보다 작다고 판단

 

 

랜덤하게 생성된 데이터 예측 결과:

  • 다음은 랜덤하게 생성된 5개의 데이터 포인트와 이들의 예측 결과. 
  • 데이터 포인트:
    • 첫 번째 포인트: RM = 6.2604, LSTAT = 4.5255
    • 두 번째 포인트: RM = 4.6702, LSTAT = 20.4517
    • 세 번째 포인트: RM = 5.5471, LSTAT = 24.9497
    • 네 번째 포인트: RM = 8.0687, LSTAT = 4.9645
    • 다섯 번째 포인트: RM = 3.0283, LSTAT = 17.6777

 

  • 예측 결과: [0 0 0 1 0]: 각 데이터 포인트에 대한 예측 결과.
    • 첫 번째 포인트는 클래스 0
    • 두 번째 포인트는 클래스 0
    • 세 번째 포인트는 클래스 0
    • 네 번째 포인트는 클래스 1
    • 다섯 번째 포인트는 클래스 0
  • 이는 모델이 각각의 랜덤 데이터 포인트를 MEDV가 임계값 25 이상인지 이하인지에 따라 분류한 결과임

SVM (Support Vector Machine) 모델의 결정 경계, 마진, 그리고 데이터 포인트를 시각화

 

 

 

 

  • 결정 경계 시각화 (plot_decision_boundary):
    • 결정 경계를 시각화하기 위해 np.meshgrid를 사용하여 2차원 공간을 그리드로 나누고, 각 그리드 포인트에 대해 모델의 예측을 수행.
    • plt.contourf를 사용하여 결정 경계를 색으로 구분하고, 데이터 포인트를 plt.scatter로 시각화.
  • 새로운 데이터 포인트와 랜덤 데이터 포인트 시각화:
    • plt.scatter를 사용하여 학습 데이터, 새로운 데이터 포인트, 그리고 랜덤 데이터 포인트를 플로팅함.
    • 학습 데이터는 기본적으로 Training Data로, 새로운 데이터 포인트는 빨간색(red), 랜덤 데이터 포인트는 초록색(green)으로 구분.

 


 

 

다중선형회귀와 SVM 회귀 모델 성능 비교 및 시각화

import pandas as pd
import numpy as np
import sklearn.model_selection as sms
import sklearn.svm as skv
import sklearn.linear_model as sklm
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt

# 코드 제목: 다중선형회귀와 SVM 회귀 모델 비교

# 데이터셋 로드
file_path = 'boston.csv'
pd_DataSet = pd.read_csv(file_path)  # CSV 파일에서 데이터프레임 생성

# 데이터프레임 생성 및 결측값 제거
DF = pd.DataFrame(pd_DataSet)
New_DF = DF.dropna(how='any')  # 결측값이 포함된 모든 행을 제거

# 특징(독립 변수)과 목표 변수(종속 변수) 선택
x = New_DF[['RM', 'LSTAT']]  # 독립 변수: 방의 수(RM)와 저소득층 비율(LSTAT)
y = New_DF['MEDV']  # 종속 변수: 주택 가격(MEDV)

# 데이터셋을 학습 데이터와 테스트 데이터로 분리
x_train, x_test, y_train, y_test = sms.train_test_split(x, y, train_size=0.8, test_size=0.2, random_state=42)

# 스케일 조정
scaler = StandardScaler()
x_train_scaled = scaler.fit_transform(x_train)  # 학습 데이터 스케일 조정
x_test_scaled = scaler.transform(x_test)  # 테스트 데이터 스케일 조정

# 다중선형회귀 모델 학습
linear_model = sklm.LinearRegression()
linear_model.fit(x_train_scaled, y_train)  # 모델 학습

# SVM 회귀 모델 학습
svr_model = skv.SVR(kernel='linear', C=1)
svr_model.fit(x_train_scaled, y_train)  # 모델 학습

# 모델 예측
y_pred_linear = linear_model.predict(x_test_scaled)  # 다중선형회귀 모델 예측
y_pred_svr = svr_model.predict(x_test_scaled)  # SVM 회귀 모델 예측

# 모델 평가
mse_linear = mean_squared_error(y_test, y_pred_linear)  # 다중선형회귀 모델의 MSE
r2_linear = r2_score(y_test, y_pred_linear)  # 다중선형회귀 모델의 R^2

mse_svr = mean_squared_error(y_test, y_pred_svr)  # SVM 회귀 모델의 MSE
r2_svr = r2_score(y_test, y_pred_svr)  # SVM 회귀 모델의 R^2

# 결과 출력
print('다중선형회귀 모델:')
print('MSE:', mse_linear)  # 평균 제곱 오차
print('R^2:', r2_linear)  # 결정 계수

print('SVM 회귀 모델:')
print('MSE:', mse_svr)  # 평균 제곱 오차
print('R^2:', r2_svr)  # 결정 계수

# 시각화 코드
plt.figure(figsize=(14, 6))

# 다중선형회귀 모델 예측 결과 시각화
plt.subplot(1, 2, 1)
plt.scatter(y_test, y_pred_linear, color='blue', edgecolor='k', alpha=0.7)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color='red', linestyle='--')  # 기준선
plt.title('다중선형회귀 모델 예측')
plt.xlabel('실제 값')
plt.ylabel('예측 값')

# SVM 회귀 모델 예측 결과 시각화
plt.subplot(1, 2, 2)
plt.scatter(y_test, y_pred_svr, color='green', edgecolor='k', alpha=0.7)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color='red', linestyle='--')  # 기준선
plt.title('SVM 회귀 모델 예측')
plt.xlabel('실제 값')
plt.ylabel('예측 값')

plt.tight_layout()
plt.show()

 

 

  • MSE 비교: 다중선형회귀 모델의 MSE가 SVM 회귀 모델보다 낮으므로, 다중선형회귀 모델이 평균적으로 더 정확한 예측을 제공한다고 할 수 있다.
  • R² 비교: 다중선형회귀 모델의 R²가 SVM 회귀 모델보다 높으므로, 다중선형회귀 모델이 데이터의 변동성을 더 잘 설명하고 있다.

→ 결론적으로, 이 데이터셋에 대해서는 다중선형회귀 모델이 SVM 회귀 모델보다 더 나은 성능을 보이는 것으로 나타남.

 


K-means 클러스터링

1. 특징

K-means는 데이터 포인트를 K개의 클러스터로 그룹화하는 알고리즘

각 클러스터는 해당 클러스터에 속하는 데이터 포인트들의 평균을 중심으로 정의됨.

목표는 각 데이터 포인트가 가장 가까운 클러스터 중심에 배치되도록 하는 것.

 

2. 작동 원리

K-means 알고리즘은 다음과 같은 단계로 작동:

  1. 초기화: K개의 클러스터 중심(centroids)을 무작위로 선택.
  2. 클러스터 할당: 각 데이터 포인트를 가장 가까운 클러스터 중심에 할당.
  3. 중심 재계산: 각 클러스터에 할당된 데이터 포인트들의 평균을 계산하여 클러스터 중심을 업데이트.
  4. 반복: 2단계와 3단계를 반복하여 클러스터 중심이 더 이상 변화하지 않거나 변화가 미미할 때까지 반복.

 

3. 거리 측정 방법

K-means에서 데이터 포인트와 클러스터 중심 간의 거리는 일반적으로 유클리드 거리(Euclidean distance)로 측정

유클리드 거리는 두 점 사이의 직선 거리를 측정한다.

4. 유사도

K-means에서는 클러스터 중심과 데이터 포인트 간의 유사도를 거리를 기반으로 측정.

즉, 클러스터 중심과의 거리(작은 거리)가 가까울수록 데이터 포인트와 클러스터 중심의 유사도가 높다고 간주됨.

 

5. 알고리즘의 장단점

장점:

  • 간단하고 이해하기 쉬운 알고리즘
  • 많은 데이터셋에서 잘 작동하며, 계산이 빠름.
  • 클러스터 중심이 명확하게 정의되어 클러스터링의 결과를 해석하기 쉬움.

단점:

  • K값(클러스터 수)을 미리 지정해야 한다.
  • 초기 클러스터 중심에 따라 결과가 달라질 수 있다 (초기화의 민감성).
  • 비구조적 형태의 클러스터링에 적합하지 않을 수 있다.
  • 군집의 개수가 K로 고정되어 있어 군집의 개수를 사전에 설정해야 함.

 

6. 실루엣 스코어

실루엣 스코어는 클러스터링 결과의 품질을 평가하는 지표

각 데이터 포인트에 대해 실루엣 스코어를 계산하고, 전체 클러스터링 결과의 평균을 구함

스코어는 -1에서 1 사이의 값을 가지며, 클러스터링의 적절성을 나타낸다.

 

  • 실루엣 스코어 수식:

여기서:

  • a(i)는 데이터 포인트 ii와 같은 클러스터 내 다른 데이터 포인트들과의 평균 거리
  • b(i)는 데이터 포인트 ii가 가장 가까운 다른 클러스터의 평균 거리
  • 스코어 해석:
    • s(i)가 1에 가까우면 데이터 포인트가 잘 클러스터링되었음을 의미.
    • s(i)가 0에 가까우면 데이터 포인트가 클러스터 경계에 위치하고 있음을 의미.
    • s(i)가 -1에 가까우면 데이터 포인트가 잘못된 클러스터에 속해 있을 수 있음을 의미.

K-Means 클러스터링을 이용한 Boston Housing 데이터셋 분석 및 시각화

import pandas as pd
import sklearn.cluster as skc
import matplotlib.pyplot as plt
import sklearn.metrics as skm
import matplotlib.font_manager as fm


# 한글 폰트 설정 (Windows의 경우)
path = 'C:/Windows/Fonts/malgun.ttf'
fontprop = fm.FontProperties(fname=path, size=14)
plt.rcParams['font.family'] = fontprop.get_name()

# 큰 데이터셋을 표시할 때 모든 행과 열을 보이게 설정
pd.set_option('display.max_rows', None)  # 데이터프레임의 최대 행 수를 무제한으로 설정
pd.set_option('display.max_columns', None)  # 데이터프레임의 최대 열 수를 무제한으로 설정

# 데이터셋 로드
file_path = 'KMeans_Sample.csv'  # 데이터셋 파일 경로
pd_DataSet = pd.read_csv(file_path)  # CSV 파일에서 데이터프레임 생성

# 데이터프레임 생성 및 결측값 제거
DF = pd.DataFrame(pd_DataSet)  # 데이터프레임 생성
New_DF = DF.dropna(how='any')  # 결측값이 포함된 모든 행을 제거

# K-Means 클러스터링 모델 학습
k_means_Model = skc.KMeans(n_clusters=4)  # 클러스터 수를 4로 설정
k_means_Model.fit(New_DF)  # K-Means 모델 학습
Re = k_means_Model.predict(New_DF)  # 데이터 포인트의 클러스터 레이블 예측

# 실루엣 스코어 계산
S_score = skm.silhouette_score(New_DF, Re)  # 클러스터링 품질을 평가하는 실루엣 스코어 계산
print('실루엣 스코어 : ', S_score)  # 실루엣 스코어 출력

# 데이터 시각화
x = New_DF['X1']  # X1 열을 x축 데이터로 사용
y = New_DF['Y1']  # Y1 열을 y축 데이터로 사용

plt.scatter(x, y, c=Re)  # x와 y 데이터 포인트를 클러스터 레이블에 따라 색상으로 시각화
plt.xlabel('X1')  # x축 레이블 설정
plt.ylabel('Y1')  # y축 레이블 설정
plt.title('K-Means 클러스터링 결과')  # 그래프 제목 설정
plt.colorbar(label='Cluster Label')  # 클러스터 레이블 색상 바 추가
plt.show()  # 그래프 출력

 

  • 결과 해석 
    • 실루엣 스코어는 -1에서 1 사이의 값을 가진다.
    • 스코어가 1에 가까울수록 데이터 포인트가 자신의 클러스터에 잘 맞고, 다른 클러스터와 잘 구분된다는 의미
    • 스코어가 0에 가까우면 데이터 포인트가 클러스터 경계에 위치하거나 클러스터가 겹쳐 있다는 의미
    • 스코어가 -1에 가까우면 데이터 포인트가 잘못된 클러스터에 속하고 있다는 의미
  • 스코어 해석:
    • 실루엣 스코어: 0.7489는 클러스터링 결과가 전반적으로 좋은 품질을 나타냄

 

 


K-Means 클러스터링을 통한 보스턴 주택 가격 데이터셋 분석 및 시각화

import pandas as pd
import sklearn.cluster as skc
import matplotlib.pyplot as plt
import sklearn.metrics as skm
import matplotlib.font_manager as fm

# 한글 폰트 설정 (Windows의 경우)
path = 'C:/Windows/Fonts/malgun.ttf'
fontprop = fm.FontProperties(fname=path, size=14)
plt.rcParams['font.family'] = fontprop.get_name()

# 데이터셋 로드
file_path = 'boston.csv'  # 데이터셋 파일 경로
pd_DataSet = pd.read_csv(file_path)  # CSV 파일에서 데이터프레임 생성

# 데이터프레임 생성 및 결측값 제거
DF = pd.DataFrame(pd_DataSet)  # 데이터프레임 생성
New_DF = DF.dropna(how='any')  # 결측값이 포함된 모든 행을 제거

# 군집화에 사용할 특징 선택
# 예를 들어 'RM' (방의 수)와 'LSTAT' (저소득층 비율)를 사용할 수 있습니다.
features = ['RM', 'LSTAT']
X = New_DF[features]

# K-Means 클러스터링 모델 학습
k_means_Model = skc.KMeans(n_clusters=4, random_state=42)  # 클러스터 수를 4로 설정
k_means_Model.fit(X)  # K-Means 모델 학습
Re = k_means_Model.predict(X)  # 데이터 포인트의 클러스터 레이블 예측

# 실루엣 스코어 계산
S_score = skm.silhouette_score(X, Re)  # 클러스터링 품질을 평가하는 실루엣 스코어 계산
print('실루엣 스코어 : ', S_score)  # 실루엣 스코어 출력

# 데이터 시각화
plt.figure(figsize=(10, 6))  # 그래프 크기 설정

# 클러스터링 결과 시각화
scatter = plt.scatter(X['RM'], X['LSTAT'], c=Re, cmap='viridis')  # x와 y 데이터 포인트를 클러스터 레이블에 따라 색상으로 시각화

# 축 레이블과 제목 설정
plt.xlabel('RM', fontsize=14)  # x축 레이블 설정
plt.ylabel('LSTAT', fontsize=14)  # y축 레이블 설정
plt.title('K-Means 클러스터링 결과 (RM vs LSTAT)', fontsize=16)  # 그래프 제목 설정

# 색상 바 추가
cbar = plt.colorbar(scatter, label='Cluster Label')  # 클러스터 레이블 색상 바 추가
cbar.ax.tick_params(labelsize=12)  # 색상 바의 레이블 크기 조정

plt.show()  # 그래프 출력

 

실루엣 스코어 (Silhouette Score)는 군집화의 품질을 평가하는 지표로,

각 데이터 포인트가 자신의 군집에 얼마나 잘 속하는지와 다른 군집과 얼마나 잘 구분되는지를 측정.

이 스코어는 -1에서 1 사이의 값을 가지며, 다음과 같은 의미:

  • 1에 가까운 값: 데이터 포인트가 자신의 군집에 잘 속하고, 다른 군집과 잘 구분됨. 
  • 0에 가까운 값: 데이터 포인트가 자신의 군집에 경계에 있으며, 군집의 구분이 명확하지 않음을 의미.
  • -1에 가까운 값:  군집이 잘못 형성되었음을 의미.

→ 양호한 군집화: 0.535는 실루엣 스코어가 양수로 군집화가 비교적 잘 되어 있음을 나타냅니다. 군집의 구분이 어느 정도 잘 이루어졌다는 것을 의미.

방의 수와 저소득층 비율에 대한 클러스터링 분석을 통해 주택의 특징에 따라 군집을 나누었고,

이 군집들은 특정 패턴을 가진 주택들을 묶어준다.

 

 


 

 

의사결정나무(Decision Tree)

  • 데이터 분석과 머신러닝에서 사용되는 분류 및 회귀 모델
  • 주어진 데이터를 기반으로 결정을 내리거나 예측을 수행하기 위해 트리 구조를 사용
  • 의사결정나무는 인간의 의사 결정 과정을 모델링한 것으로 이해할 수 있다.

 

기본 개념

  1. 트리 구조:
    • 노드: 트리의 각 지점을 나타냅니다. 노드는 크게 두 종류로 나뉨:
      • 루트 노드 (Root Node): 트리의 최상위 노드로, 모든 데이터가 이 노드에서 시작됨.
      • 내부 노드 (Internal Node): 루트 노드에서 분기되는 노드들로, 데이터의 특정 특징에 따라 데이터를 분할
      • 리프 노드 (Leaf Node): 트리의 가장 끝 부분에 위치하는 노드로, 최종적인 예측 결과를 나타낸다.
    • 가지 (Branch): 노드 간의 연결을 나타내며, 특정 특징에 따라 데이터가 분리되는 것을 의미
  2. 분할 기준:
    • 의사결정나무는 데이터를 여러 가지 기준으로 분할하여 각 노드에서 최적의 분할을 찾아간다. 이 기준은 특정 특징을 기반으로 데이터를 분할하여 각 분할 후의 노드에서 데이터의 동질성이 높아지도록 함.
  3. 결정 규칙:
    • 각 노드에서 사용된 분할 기준에 따라 데이터가 나뉘며, 최종 리프 노드는 데이터를 특정 클래스 또는 값으로 예측

 

분류와 회귀

  • 분류 (Classification):
    • 의사결정나무를 사용하여 데이터를 분류하는 작업으로 각 리프 노드는 데이터가 특정 클래스에 속하는 확률을 나타냄.
    • 예를 들어, 이메일이 스팸인지 아닌지 분류하는 경우가 해당됨.
  • 회귀 (Regression):
    • 의사결정나무를 사용하여 연속적인 값을 예측하는 작업으로 각 리프 노드는 특정 값의 평균 또는 중앙값을 나타냄.
    • 예를 들어, 집의 가격을 예측하는 경우가 해당됨.

장점

  1. 해석 용이성:
    • 트리 구조가 직관적이고 쉽게 이해할 수 있어 모델의 결정 과정을 시각적으로 해석하기 용이하다.
  2. 비선형 관계 처리:
    • 데이터의 비선형 관계를 잘 처리할 수 있으며, 특징 간의 상호작용을 잘 포착한다..
  3. 데이터 전처리 최소화:
    • 의사결정나무는 데이터의 스케일 조정이나 정규화 없이 사용할 수 있다.

단점

  1. 과적합 (Overfitting):
    • 트리가 너무 깊어질 경우 학습 데이터에 과적합될 수 있다. 즉, 학습 데이터에 너무 맞춰져 일반화 성능이 떨어질 수 있다.
  2. 불안정성 (Instability):
    • 작은 데이터 변화에 민감하게 반응하여 트리 구조가 크게 달라질 수 있다.
  3. 편향 (Bias):
    • 특정 특징이 자주 사용되면, 그 특징이 모델의 예측에 과도하게 영향을 줄 수 있다.

주요 알고리즘

  • CART (Classification and Regression Trees): 분류와 회귀에 모두 사용되는 알고리즘으로, 주로 의사결정나무를 구현할 때 사용된다.
  • ID3 (Iterative Dichotomiser 3): 정보를 이득(Information Gain) 기반으로 분할하는 알고리즘.
  • C4.5: ID3의 확장으로, 분할 기준을 정보 이득 비율로 조정한다.

 

import pandas as pd  # 데이터 조작 및 분석을 위한 라이브러리
import sklearn.model_selection as sms  # 모델 선택 및 데이터 분할을 위한 모듈
import sklearn.tree as str  # 결정 트리 모델을 위한 모듈

# 판다스의 데이터프레임을 출력할 때 모든 행과 열을 보이도록 설정
pd.set_option('display.max_rows', None)  # 행의 출력 최대값을 무제한으로 설정
pd.set_option('display.max_columns', None)  # 열의 출력 최대값을 무제한으로 설정

# CSV 파일을 읽어와 데이터프레임 생성
pd_DataSet = pd.read_csv('SVM_Sample.csv')  # 'SVM_Sample.csv' 파일을 읽어와 데이터프레임 생성

# 데이터프레임을 다시 생성하여 처리
DF = pd.DataFrame(pd_DataSet)  # 기존 데이터프레임을 기반으로 새로운 데이터프레임 생성

# 결측값이 있는 행 제거
New_DF = DF.dropna(how='any')  # 결측값이 포함된 모든 행을 제거

# 독립 변수(특징)와 종속 변수(라벨) 선택
x = New_DF[['X1', 'X2']]  # 특징: X1과 X2 열 선택
y = New_DF['Y1']  # 종속 변수: Y1 열 선택

# 학습 데이터와 테스트 데이터로 분리
x_train, x_test, y_train, y_test = sms.train_test_split(x, y, train_size=0.8, test_size=0.2)
# train_size=0.8: 80%를 학습 데이터로, 20%를 테스트 데이터로 사용

# 결정 트리 모델 생성 및 학습
#DT_Model = str.DecisionTreeClassifier()  # 결정 트리 분류기 모델 생성
#DT_Model.fit(x_train, y_train)  # 학습 데이터로 모델 학습

DT_Model = str.DecisionTreeRegressor()
DT_Model.fit(x_train, y_train)

# 모델 성능 평가
Train_score = DT_Model.score(x_train, y_train)  # 학습 데이터에 대한 모델의 정확도
Test_score = DT_Model.score(x_test, y_test)  # 테스트 데이터에 대한 모델의 정확도

# 결과 출력
print('Decision Tree - Train_score : ', Train_score, ', Test_score : ', Test_score)

# 특정 데이터 포인트에 대한 예측 수행
Pre_Parm = [[250, 260]]  # 예측할 데이터 포인트
predict_R = DT_Model.predict(Pre_Parm)  # 예측 수행
print('-------------------------------------')
print(predict_R)  # 예측 결과 출력

# 다른 CSV 파일을 읽어와 예측 수행
Pre_DataSet = pd.read_csv('Prediction_Scenario.csv')  # 'Prediction_Scenario.csv' 파일을 읽어와 데이터프레임 생성
Pre_DF = pd.DataFrame(Pre_DataSet)  # 기존 데이터프레임을 기반으로 새로운 데이터프레임 생성

Pre_S_Parm = Pre_DF[['X1', 'X2']]  # 예측할 데이터 포인트 선택
predict_sR = DT_Model.predict(Pre_S_Parm)  # 예측 수행

# 예측 결과 출력
print('-------------------------------------')
print(predict_sR)  # 예측 결과 출력

 

 

  • DecisionTreeClassifier:
    • 사용 목적: 데이터를 특정 클래스 또는 카테고리로 분류할 때 사용.
    • 예: y가 클래스 레이블 (e.g., 스팸/비스팸).
  • DecisionTreeRegressor:
    • 사용 목적: 데이터를 기반으로 연속적인 숫자 값을 예측할 때 사용.
    • 예: y가 연속적인 값 (e.g., 집의 가격, 온도).

 

→ y가 연속형인데 분류 모델 넣으니까 test_score가 박살 나서 y가 연속형이면 회귀 모델 넣음

 

Pre_Parm = [[250, 260]]이라는 입력 값에 대해 예측된 결과는 6230

→  이는 주어진 독립 변수 X1=250과 X2=260에 대해 모델이 예측한 종속 변수 값

 

Pre_S_Parm에 대해 모델이 예측한 결과

→  이 값들은 Pre_DF 데이터의 각 입력 샘플에 대해 예측된 연속적인 값들.

→  많은 예측 값이 15124로 나타나고 있는데, 이는 모델이 특정 입력 값에 대해 동일한 예측 결과를 반환하거나, 데이터의 분포가 모델에 의해 특정 값으로 압축된 것으로 보임

 

 


로지스틱 회귀 분석(Logistic Regression)

주로 이진 분류 문제를 해결하는 데 사용

즉, 결과가 두 가지 카테고리 중 하나로 분류되는 문제를 다룬다.

예를 들어, 이메일이 스팸인지 아닌지, 환자가 병에 걸렸는지 여부를 예측하는 데 사용할 수 있다.

 

1. 기본 개념

로지스틱 회귀는 선형 회귀의 확장으로, 선형 모델을 통해 이진 분류 문제를 해결한다.

일반적으로 로지스틱 함수 또는 시그모이드 함수를 사용하여 예측 확률을 계산.

로지스틱 함수 (Sigmoid Function)

로지스틱 회귀의 핵심은 시그모이드 함수입니다. 이 함수는 다음과 같은 형태를 가지고 있다:

 

 

시그모이드 함수의 출력

시그모이드 함수는 0과 1 사이의 값을 반환.

이 값은 주어진 입력에 대해 클래스 1의 확률로 해석된다.

예를 들어, 출력이 0.7이라면 입력이 클래스 1에 속할 확률이 70%라는 뜻.

 

2. 모델 수식

로지스틱 회귀 모델의 예측 확률:

 

3. 로지스틱 회귀의 손실 함수

로지스틱 회귀에서 모델의 성능을 평가하기 위해

로그 손실 함수(Log Loss) 또는 이진 교차 엔트로피 손실 함수를 사용.

이 손실 함수는 다음과 같이 정의:

 

4. 모델 학습

로지스틱 회귀 모델은 경사 하강법(Gradient Descent) 등의 최적화 알고리즘을 사용하여

모델의 가중치 w와 절편 b를 학습. 목표는 손실 함수를 최소화하는 것.

 

5. 모델 평가

로지스틱 회귀 모델의 성능을 평가하는 주요 지표는 다음과 같다:

  • 정확도 (Accuracy): 전체 샘플 중 올바르게 분류된 샘플의 비율.
  • 정밀도 (Precision): 양성으로 예측된 샘플 중 실제 양성 샘플의 비율.
  • 재현율 (Recall): 실제 양성 샘플 중 양성으로 예측된 샘플의 비율.
  • F1 Score: 정밀도와 재현율의 조화 평균.

 

타이타닉 데이터셋에서 승객의 생존 여부를 예측

 

1. Age (나이):

승객의 나이를 나타내며, 연속적인 숫자형 변수

결측값을 평균값으로 대체하고, 스케일링하여 모델에 포함시킴.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer

# 데이터 로드
df = pd.read_csv("titanic.csv")  # 타이타닉 데이터셋을 CSV 파일에서 로드합니다.

# 필요한 열 선택 (Pclass, Age, Survived)
df = df[['Pclass', 'Age', 'Survived']]  # 분석에 필요한 열만 선택합니다: Pclass(객실 등급), Age(나이), Survived(생존 여부)

# 결측값 처리 (Age의 결측값을 평균으로 대체)
imputer = SimpleImputer(strategy='mean')  # 결측값을 평균으로 대체하기 위한 SimpleImputer 객체를 생성합니다.
df['Age'] = imputer.fit_transform(df[['Age']])  # 'Age' 열의 결측값을 평균값으로 대체합니다.

# 독립 변수와 종속 변수 설정
X = df[['Pclass', 'Age']]  # 독립 변수로 사용할 열을 선택합니다: Pclass와 Age
y = df['Survived']  # 종속 변수로 사용할 열을 선택합니다: Survived

# 데이터 분리 (학습용 데이터와 테스트용 데이터로)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)  # 데이터를 학습용과 테스트용으로 80:20 비율로 분리합니다.

# 특성 스케일링 (로지스틱 회귀는 스케일에 민감함)
scaler = StandardScaler()  # 데이터를 표준화하기 위한 StandardScaler 객체를 생성합니다.
X_train = scaler.fit_transform(X_train)  # 학습 데이터에 대해 표준화를 수행합니다.
X_test = scaler.transform(X_test)  # 테스트 데이터에 대해 표준화를 수행합니다. 학습 데이터의 스케일을 기준으로 변환합니다.

# 로지스틱 회귀 모델 생성 및 학습
lr = LogisticRegression()  # 로지스틱 회귀 모델 객체를 생성합니다.
lr.fit(X_train, y_train)  # 학습 데이터를 사용하여 모델을 학습합니다.

# 모델 평가
train_score = lr.score(X_train, y_train)  # 학습 데이터에 대한 모델의 정확도를 계산합니다.
test_score = lr.score(X_test, y_test)  # 테스트 데이터에 대한 모델의 정확도를 계산합니다.
coefficient = lr.coef_  # 모델의 회귀 계수를 가져옵니다.
intercept = lr.intercept_  # 모델의 절편을 가져옵니다.

# 예측 결과
y_pred = lr.predict(X_test)  # 테스트 데이터에 대한 예측 결과를 생성합니다.
print("Train Score: ", train_score)  # 학습 데이터에 대한 정확도를 출력합니다.
print("Test Score: ", test_score)  # 테스트 데이터에 대한 정확도를 출력합니다.
print("Coefficient: ", coefficient)  # 모델의 회귀 계수를 출력합니다.
print("Intercept: ", intercept)  # 모델의 절편을 출력합니다.
print("Predictions: ", y_pred)  # 테스트 데이터에 대한 예측 결과를 출력합니다.

→ 모델의 학습 데이터에서의 성능이 테스트 데이터에서의 성능보다 높다.

이는 모델이 학습 데이터에 비해 테스트 데이터에서 약간의 과적합이 있을 수 있음

  이 회귀 계수는 각 독립 변수 (여기서는 Pclass와 Age)가 종속 변수 (Survived, 생존 여부)에 미치는 영향을 나타냄

  • -0.5233은 Pclass(객실 등급) 변수의 계수로, Pclass의 값이 증가할 때 생존 확률이 감소함을 의미.
  • -0.2653은 Age(나이) 변수의 계수로, 나이가 증가할 때 생존 확률이 감소함을 의미

  Intercept (절편) : [-0.5951] 절편은 독립 변수들이 모두 0일 때 로지스틱 회귀 모델의 예측 값.

이 값이 음수이므로, 모든 독립 변수가 0일 때의 생존 확률이 낮다는 것을 의미

 

  Predictions (예측 결과):
예측 결과는 0과 1로 이루어져 있으며,

각 값은 테스트 데이터 샘플이 생존하지 않았음을 나타내는 0 또는 생존했음을 나타내는 1.

예를 들어, 첫 번째 예측은 0, 즉 해당 샘플이 생존하지 않았다고 모델이 예측한 것

 


 

2. Sex (성별):

승객의 성별을 나타내며, 원-핫 인코딩을 통해 이진 변수로 변환하여 모델에 포함시킴

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer

# 데이터 로드
df = pd.read_csv("titanic.csv")  # Titanic 데이터셋을 읽어옵니다.

# 필요한 열 선택 (Sex, Age, Survived)
df = df[['Sex', 'Age', 'Survived']]  # 분석에 필요한 열만 선택합니다.

# 결측값 처리 (Age의 결측값을 평균으로 대체)
imputer = SimpleImputer(strategy='mean')  # 결측값을 평균으로 대체하기 위한 SimpleImputer 객체 생성
df['Age'] = imputer.fit_transform(df[['Age']])  # Age 열의 결측값을 평균값으로 대체합니다.

# 'Sex' 컬럼을 원-핫 인코딩하여 숫자형으로 변환
df = pd.get_dummies(df, columns=['Sex'], drop_first=True)  # Sex 열을 원-핫 인코딩하고 첫 번째 카테고리를 제거합니다.

# 독립 변수와 종속 변수 설정
X = df[['Age', 'Sex_male']]  # Age와 Sex_male(남성) 컬럼을 독립 변수로 설정합니다.
y = df['Survived']  # Survived 열을 종속 변수로 설정합니다.

# 데이터 분리 (학습용 데이터와 테스트용 데이터로)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)  
# 데이터를 학습용 데이터와 테스트용 데이터로 분리합니다. 테스트 데이터 비율은 20%입니다.

# 특성 스케일링 (로지스틱 회귀는 스케일에 민감함)
scaler = StandardScaler()  # 특성 스케일링을 위한 StandardScaler 객체 생성
X_train = scaler.fit_transform(X_train)  # 학습 데이터에 스케일링 적용
X_test = scaler.transform(X_test)  # 테스트 데이터에 동일한 스케일링 적용

# 로지스틱 회귀 모델 생성 및 학습
lr = LogisticRegression()  # 로지스틱 회귀 모델 생성
lr.fit(X_train, y_train)  # 학습 데이터로 모델을 학습시킵니다.

# 모델 평가
train_score = lr.score(X_train, y_train)  # 학습 데이터에서의 모델 정확도 평가
test_score = lr.score(X_test, y_test)  # 테스트 데이터에서의 모델 정확도 평가
coefficient = lr.coef_  # 모델의 회귀 계수
intercept = lr.intercept_  # 모델의 절편

# 예측 결과
y_pred = lr.predict(X_test)  # 테스트 데이터에 대한 예측 수행
print("Train Score: ", train_score)  # 학습 데이터에서의 정확도 출력
print("Test Score: ", test_score)  # 테스트 데이터에서의 정확도 출력
print("Coefficient: ", coefficient)  # 회귀 계수 출력
print("Intercept: ", intercept)  # 절편 출력
print("Predictions: ", y_pred)  # 테스트 데이터에 대한 예측 결과 출력

 

  모델은 약 68%~70%의 정확도로 생존 여부를 예측하고 있다.

이는 모델이 상당히 유용하지만, 개선의 여지가 있는 수준

 

  • 나이가 증가할수록 생존 확률에 미치는 영향이 크지 않다는 것을 의미.
  • Sex_male의 계수는 -0.6970으로, 남성일 경우 생존 확률이 감소하는 경향이 있음을 나타냄. 즉, 모델이 남성에 대해 생존 확률을 낮게 예측한다는 것을 의미.

 

  Intercept: [-0.6183] 인 모델의 절편은 독립 변수들이 0일 때 모델의 기본 예측값을 나타낸다.

절편이 음수이므로, 독립 변수들이 0일 때 생존 확률의 기본값이 낮다는 것을 의미.