오늘은 과제 제출 일정이 2일 밖에 남아있지않아 

 

과제 발표 대본을 짜고 팀원분들 앞에서 발표를 진행해보며 완성도를 높이는 시간을 가졌다.

 

오늘 목표는 대본을 최대한 빨리 짜서 다른 학습을 진행해 보려했으나 대본짜는게 괴장히 늦어지고 수정을 진행하면서 시간을 너무 많이 사용해서 학습을 많이 진행하지 못했다.

 

오늘 학습내용 소개 순서는

 

1. 과제를 마무리하며 알게 된 내용

 

2. 기초 수학 특강

 

3. 회고 

 

순서로 진행하겟습니다.


☑️과제 발표 준비

지금까지 과제를 준비하며 많은 부분을 학습하게 되었다고 생각했지만

 

좁은 학습분량인 과제 분량에도 아직 모르는 것들이 존재했고 머신러닝 학습에 대한 평가를 하는게 새롭게 느껴졋다.

 

1. 최빈값 mode를 사용할때[0]의 역할

- fillna(df.mode()[0])에서 [0]의 역할은 최빈값의 가장 첫 번째 값을 최빈값으로 설정하겟다고 설정하는 것이다.

 

2. Logistic Regrection의 모델 생성시 설정

model = LogisticRegrection(max_iter=100)

- max_iter=100의 의미는 학습을 최대 100번 반복으로 설정하는 코드입니다.

- 최대반복 수를 설정하는 이유는 데이터셋의 크기가 클수록 크게 설정해야하는 것이 맞지만 학습이 오류가 나서 학습을 멈춰버리는 경우가있어서 적절한 값을 설정해주어야 한다.(기본값은 100)

 

3. RandomForest의 모델 생성시 설정

model = RandomForest(random_state=42)

- random_state를 설정하는 이유는 모델 생성에서 결과를 일관되게 재현 및 비교하기 위해 랜덤 스테이트를 설정하는 것

 

4. XGBoost의 모델 생성시 설정

model = XGBoost( use_label_encoder=False, eval_metric='logloss')

- use_label_encoder=False룰 설정하게 되면 LabelEncoding을 사용했을 때 나올 수 있는 경고 메세지를 무시해준다.

- eval_metric='logloss'는 로그 손실 값을 계산하고 출력하여 학습상태를 확인 할 수 있다.

 

5. Classification_report 해석

우선 Classification의 요소로는

예측하는 값들을 개별 클래스로 나누어 준다

precision (정밀도): 진행한 예측이 얼마나 정밀하게 예측이 되었는지 보여 준다.

recall(재현율): 모델을 학습할 때 실제 계산과 테스트 계산이 얼마나 잘 이루어 졌는지 확인한다.

f1-score: 정밀도와 재현율의 균형 조화 점수를 보여준다.

support: 학습을 진행할 때 몇 개의 값들을 사용했는지 보여준다.

Macro avg: 두 클래스의 평균 성능을 동일한 가중치로 평가한 값 

Weighted avg: 각 클래스의 샘플 수에 따라 가중치를 적용해 계산된 평균 성능 

 

6. confusion_metrix 해석 방법

[[89, 16],

[16, 58]]

89 = 첫 번째 클래스를 정확하게 예측한 수

16 = 첫 번째 클래스를 두 번째 클래스로 잘못 예측한 수

16 = 두번째 클래스를 첫 번째 클래스로 잘못 예측한 수

58 = 두번째 클래스를 정확히 예측한 수

결론: 첫번째 클래스에 대한 예측은 성능이  좋고 두 번째 클래스 예측 또한 좋지만 첫 번째 클래스 예측이 더 성능이 좋다. 

 

 


☑️기초 선형 대수학(행렬과 연산)

스칼라(온도, 길이, 질량)

- 크기만있고 방향은 없다.

- 물리적 단위를 포함 할 수 있음

- 일반적으로 실수로 표현

 

벡터(힘, 속도, 위치)

- 벡터는 크기와 방향으로 데이터를 표현

- 벡터의 표현: 열의 형태로 나타냄

- v1, v2는 벡터의 성분이며 각 차원별 크기

 

벡터의 연산

- 벡터의 덧셈과 뺄셈: 같은 서분끼리 더하거나 뺌 a +b = (a1 + b1, a2 + b2....)

- 스칼라 곱: 벡터와 숫자의 곱으로 벡터 성분에 숫자를 곱함 k*a = (k*a1, k*a2...)

- 벡터의 크기: 벡터의 길이를 나타내는 스칼라 값 a = (a1제곱,a2제곱,...an제곱)

- 벡터의 내적: 주 벡터 사이의 관계를 나타내는 연산으로, 두 벡터를 곱해서 하나의 숫자(스칼라)를 구하는 방법

- 코사인 유사도: 두 벡터가 이루는 각도의 코사인 값을 이용해 벡터 간의 유사성을 특정하는 방법(값이 1에 가까울수록 두 벡터는 동일한 방향, 값이 0이면 두 벡터는 서로 수직, 값이 -1에 가까울수록 두 벡터는 반대 방향)

 

Word Embedding: 충분히 잘 학습되었다면 단어에 대한 연산이 가능

 

코사인 유사도 활용

-문서 유사도 측정: 텍스트 데이터에서 단어의 빈도를 벡터로 표현하고, 문서간의 유사성을 측정

-이미지 검색: 이미지의 특징 벡터를 비교하여 이미지를 찾거나 분류할 때 사용

-추천 시스템: 사용자와 아이템의 특징을 벡터로 나타내어, 유사한 사용자나 아이템을 찾아 비슷한 특징을 가진 사람들 끼리 매칭 혹은 아이템 추천

 

행렬(벡터에서 차원을 늘린 것)

숫자나 변수들을 직사각형 형태로 배열한 것, 행과 열로 구성 됨

 

- 행렬의 덧셈과 뺄셈: 같은 위치의 요소끼리 더하거나 뺌(두 행렬의 크기가 같아야한다.)

- 행렬의 스칼라 곱: 행렬의 모든 요소에 스칼라 값을 곱한 결과 

- 전치 행렬: 행과 열을 바꾼 행렬

- 행렬의 곱셈: 원소 계산(각 행의 원소와 열의 원소를 곱한 후 더함), 행렬 곱의 조건(A가 m*n 행렬이고 B가 n*p행렬일 때, A의 열수와 B의 행수가 같아야하고, 이경우 곱셈AB는 m*p행렬을 만듦)(행렬곱셈도 내적으로 이루어져이싸고 이해하면 편하나)

특수행렬

- 단위행렬: 대각선의 원소가 1이고 나머지가 모두 0인 정방행렬 A*I = A, I*A = A

- 영행렬: 모든 원소가 0인 행렬 A + 0 = A

- 대각행렬: 주대각선에만 원소가 존재하고, 나머지 원소는 모두 0인 행렬(행렬 곱 연산이 비교적 단순하며, 대각선 원소끼리만 연산에 영향을 줌)

 

행렬의 활용

- 데이터 분석: 평균, 표준펴차 등 통계저 수치를 구할 때 각 열의 값을 기반으로 연산을 수행, 행렬의 곱셈을 사용해 데이터를 변환하거나, 피처(변수)들의 상관관계를 계산하여 데이터의 패턴을 분석, 주성분 분석(PCA) 같은 방법을 통해 다차원 데이터를 저차원으로 축소할 때도 행렬 연산이 활용됨

- 이미지 처리: 픽셀 값으로 이루어진 2차원 행렬로 표현됨

- 딥러닝에서 뉴런의 활성화 값을 결정(행렬 연산은 입력 데이터와 가중치를 처리하는 기본적인 방법)

 


☑️ 회고

오늘 발표 준비를 완료하였고 제출 기간 전까지 발표자료의 완성도를 높이는 시간과 도전과제에 대한 내용을 정리해야할 듯하다.

 

학습을 따로 진행하지 못해 조금 아쉬운 날이였지만 밀리진 않았지만 밀린듯한 느낌을 주던 필수과제를 마무리해서 속은 시원하다.

 

선형 대수학은 처음 들어보는 단어들이 매우 많아서 이해는 못하였지만 아 저런 수학 공식들을 사용해서 딥러닝모델이 학습을 진행하는구나 아직은 먼 이야기같아 보이니 딥러닝 코드들이 어떤 기능을 가지는지에 대해서 학습하고 수학에 대한 공부를 진행해야겟다.

 

이제는 이해되는 것보다 저게 뭐지 저런 것이 있구나하는 내용들이 많아서 감이 안잡히기 시작해 현타가 살짝 오지만 전문가는 아니더라도 코드를 보고 이해하고 잘못된 부분을 보면 어떻게 왜 잘못된 것인지 알 수 있을 때까지 노력하고싶다.

오늘은 강의자료에 있는 문제은행 문제를 풀어보며 복습, 학습을 진행하려고 합니다.

 

우선 머신러닝 1 ~ 5 주차 문제들을 푸는 과정을 보여주고

 

마지막 회고에서 오늘 학습하며 새롭게 알게된 내용, 까먹었던 내용을 설명하겟습니다.

 

순서는

 

1주차 개념 OX 퀴즈!

 

2주차 데이터 클리닝(가상 데이터)

 

3주차 타이타닉 데이터셋과 다양한 분류모겔 비교 실습

 

4주차 비지도 학습 기법을 활용한 최적의 2군집 찾기 모델!

 

5주차 최신 모델을 사용해 캐글 도전하기!(실패! => 주말에 해볼예정!!)

 

회고

 

순서로 진행하겟습니다.

 


☑️ 1주차 개념 OX퀴즈!

  1. 머신러닝은 사람처럼 생각하고 행동하는 기술을 의미한다. (O/X) X
  2. 딥러닝은 머신러닝의 한 분야로, 이미지 인식이나 자연어 처리에 뛰어나다. (O/X) O
  3. 머신러닝에서는 수학 공식에 대한 깊은 이해가 필수적이다. (O/X) X
  4. 머신러닝의 구성요소에는 데이터셋, 특징(Feature), 레이블이 포함된다. (O/X) O
  5. 전통적인 프로그래밍은 데이터를 통해 스스로 학습하고 예측하는 능력을 갖춘다. (O/X) X
  6. 지도 학습은 레이블이 없는 데이터셋을 이용하여 모델을 학습시키는 방법이다. (O/X) X
  7. 배깅(Bagging)은 여러 모델을 독립적으로 학습시키고 예측을 평균내거나 다수결 투표로 최종 예측을 수행한다. (O/X) 
  8. 과적합(Overfitting)은 모델이 훈련 데이터에 지나치게 적응하여 새로운 데이터에 대한 일반화 성능이 떨어지는 현상이다. (O/X) O
  9. 모든 데이터셋에 대해 완벽한 성능을 보이는 모델이 존재한다. (O/X) X

배깅이 기억 나지 않아 답을 기입하지 않았습니다.

배깅이란?

배깅(Bagging)은 여러 모델을 독립적으로 학습시키고 예측을 평균내거나 다수결 투표로 최종 예측을 수행한다.

 


☑️ 2주차 데이터 클리닝(가상 데이터)

import pandas as pd
import numpy as np

# 가상 데이터 생성
data = {
    'TransactionID': range(1, 21),
    'CustomerID': [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110],
    'PurchaseAmount': [250, -50, 3000000, 450, 0, 300, 200, 150, -10, 800, 50, 75, 400, np.nan, 600, 1000, 20, 5000, 150, 80],
    'PurchaseDate': pd.date_range(start='2024-01-01', periods=20, freq='ME').tolist(),
    'ProductCategory': ['Electronics', 'Clothing', 'Electronics', 'Home', 'Electronics', 'Home', 'Clothing', 'Home', 'Clothing', 'Electronics', 'Electronics', 'Home', 'Clothing', 'Electronics', 'Home', 'Home', 'Clothing', 'Electronics', 'Home', 'Electronics'],
    'CustomerAge': [25, 35, 45, np.nan, 22, 29, 33, 41, 27, 36, 28, 34, 42, 39, 24, 30, 32, 40, 38, 26],
    'CustomerGender': ['Male', 'Female', 'Female', 'Male', 'Female', 'Male', 'Female', np.nan, 'Male', 'Female', 'Male', 'Female', 'Male', 'Female', 'Male', 'Female', 'Male', 'Female', 'Male', 'Female'],
    'ReviewScore': [5, np.nan, 4, 3, 2, 5, 3, 4, 1, 2, np.nan, 4, 5, 3, 4, np.nan, 1, 5, 2, 4]
}

df = pd.DataFrame(data)

 

1. 결측값 처리:

PurchaseAmount, CustomerAge, CustomerGender, ReviewScore 열의 결측값을 적절히 처리하세요.

df['PurchaseAmount'].fillna(df['PurchaseAmount'].mean(), inplace=True)
df['CustomerAge'].fillna(df['CustomerAge'].mean(), inplace=True)
df.dropna(subset=['CustomerGender'], inplace=True)
df['ReviewScore'].fillna(df['ReviewScore'].mean(), inplace=True)

2. 이상치 처리:

PurchaseAmount 열에서 비정상적으로 큰 값과 음수 값을 처리하세요.

1) 이상치 확인 (IQR)

for column in df.columns:
    Q1 = df[column].quantile(0.25)
    Q3 = df[column].quantile(0.75)
    IQR = Q3 - Q1
    
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    
    outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
    
    if not outliers.empty:
        print(f"Column: {column}")
        print(outliers[[column]])
        print()

 

2) 간단한 이상치 처리

# 음수 값 제거
df = df[df['PurchaseAmount'] >= 0]

# 비정상적인 큰 값 제거
df = df[df['PurchaseAmount'] < 1000000]

 

3) IQR방법사용

# 이상치 처리 

df_no_outliers = df[(df['PurchaseAmount'] >= lower_bound) & (df['PurchaseAmount'] <= upper_bound)]

# 이상치 대체

mean_value = df['PurchaseAmount'].mean()
df['PurchaseAmount']= df['PurchaseAmount'].apply(lambda x: mean_value if x < lower_bound or x > upper_bound else x)

 

3. 중복 데이터 제거:

중복된 TransactionID가 있는 경우 제거하세요.

df = df.drop_duplicates(subset='TransactionID')

 

4. 데이터 타입 변환:

PurchaseDate 열의 데이터 타입을 날짜 형식으로 변환하세요.

df['ProductCategory'] = df['ProductCategory'].astype(str)
df['CustomerGender'] = df['CustomerGender'].astype(str)
df['PurchaseDate'] = pd.to_datetime(df['PurchaseDate'])

 

5. 정규화:

PurchaseAmount 열을 정규화하세요.

# MinMaxScaler

scaler = MinMaxScaler()

df['PurchaseAmount'] = scaler.fit_transform(df[['PurchaseAmount']])

 

# StandardScaler

from sklearn.preprocessing import StandardScaler

numeric_cols = ['TransactionID', 'CustomerID', 'PurchaseAmount', 'CustomerAge', 'ReviewScore', 'CustomerGender', 'ProductCategory']


scaler = StandardScaler()
standard_data = scaler.fit_transform(df_numeric)
print(pd.DataFrame(standard_data, columns=numeric_cols))

 

언제 정규화를 진행할까?

 

  • 스케일이 다른 피처가 있는 경우: 예를 들어, 한 피처는 수백 단위의 값을, 다른 피처는 소수점을 가진 값을 가질 때 정규화가 필요합니다.
  • 거리 기반 알고리즘: k-NN, SVM, 그리고 신경망은 피처들의 상대적인 크기에 매우 민감합니다.
  • 경사 하강법을 사용하는 경우: 피처들의 값이 크게 차이가 나면 학습 과정이 느려질 수 있습니다.

 

6. 범주형 데이터 선별 및 인코딩:

ProductCategory와 CustomerGender 열을 인코딩하세요.

df['ProductCategory'] = df['ProductCategory'].map(lambda x: 0 if x == 'Electronics' else 1 if x == 'Clothing' else 2)
df['CustomerGender'] = df['CustomerGender'].map(lambda x: 0 if x == 'Female' else 1)

 

7. 샘플링:

데이터를 무작위로 5개 샘플링하세요.

# 데이터셋에서 50% 샘플 추출

df_sampled = df.sample(frac=0.5)

# 데이터셋에서 100개의 샘플 추출

df_sampled_n = df.sample(n=100)

 


☑️ 3주차 타이타닉 데이터셋과 다양한 분류모델 비교 실습

 

1. 캐글에서 타이타닉 데이터셋을 다양한 방법으로 다운로드 후 로드해주세요 

# URL 데이터 로드
train_data = pd.read_csv('https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv')

 

2. 이전과제의 코드를 사용해 전처리를 진행하고 타겟 즉 레이블 분리 작업을 해봅시다.

# 필요한 열 선택 및 전처리
df['Age'].fillna(df['Age'].mean(), inplace=True)

df['Sex'] = df['Sex'].apply(lambda x: 0 if x == 'maie' else 1)

 

df = df[['Age', 'Pclass', 'Sex', 'Survived', 'SibSp', 'Parch', 'Fare']]

X = df.drop('Survived', axis=1)
y = df['Survived']


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

 

3. 3개 이상의 분류모델을 만들어주세요

from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# 모델 정의
models = {
    'Logistic Regression': LogisticRegression(max_iter=200),
    'Decision Tree': DecisionTreeClassifier(),
    'Random Forest': RandomForestClassifier(),
    'Support Vector Machine': SVC(),
    'K-Nearest Neighbors': KNeighborsClassifier()
}

# 모델 학습 및 평가
results = {}
for model_name, model in models.items():
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    
    results[model_name] = {
        'Accuracy': accuracy_score(y_test, y_pred),
        'Precision': precision_score(y_test, y_pred),
        'Recall': recall_score(y_test, y_pred),
        'F1 Score': f1_score(y_test, y_pred)
    }

results_df = pd.DataFrame(results).T


results_df

4. 성능을 비교해볼까요?

 

 


☑️4주차 비지도 학습 기법을 활용한 최적의 2군집 찾기 모델!

import pandas as pd
from sklearn.impute import SimpleImputer
from sklearn.cluster import KMeans
from sklearn.metrics import adjusted_rand_score, homogeneity_score, completeness_score


# 데이터 로드
train_data = pd.read_csv('https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv')

data = train_data[['Survived', 'Pclass', 'Age', 'SibSp', 'Parch', 'Fare']]
data = data.dropna()


# 레이블 분리
labels = data['Survived']
data = data.drop('Survived', axis=1)


# KMeans 모델 초기화 (군집 수 2로 설정)
kmeans = KMeans(n_clusters=2, random_state=42)

# 모델 적합
kmeans.fit(data)

# 군집 예측
clusters = kmeans.predict(data)

# 평가 지표 계산
ari = adjusted_rand_score(labels, clusters)
homogeneity = homogeneity_score(labels, clusters)
completeness = completeness_score(labels, clusters)

print(f"Adjusted Rand Index: {ari}")
print(f"Homogeneity: {homogeneity}")
print(f"Completeness: {completeness}")

 


☑️ 기초 수학 특강

기초 통계

1. 질적 데이터와 양적 데이터

 

1)질적: 혈액혈, 시험등급과 같이 종류 구별

 

명목척도: 순서나 크기의 개념없이 단순한 구분만 가능(혈액형, 학생번호, 전화번호 등)

서열 척도: 순서나 대소 관계가 의미가 있지만 비례관계를 나타내지 않음(설문지 만족도 평가, 성적 등급, 순위)

 

2) 양적: 거리, 몸무게등 수치로 표현, 연산가능

 

 구간 척도: 대소 관계와 함께 값들간의 차이에 의미가 있는 데이터, 0의 값은 절대적이지 않고 임의로 정한 기준(온도, IQ, 날짜와 시간)

 비율 척도: 절대적 0을 포함하며 비율 비교가 가능한 데이터(키, 몸무게, 시험 점수, 거리) (절대온도는 0의값이 정해져있어서 비율척도)

2. 데이터의 연속성

1) 이산형 데이터: 연속적인 값이 아닌 정해진 범위 내의 특정 값으로만 표현

값이 하나하나 개별적으로 구분 되는 변수로 주로 정수 값을 가지며 불연속적임(주사위눈, 시험점수, 학생 수)

 

2) 연속형 데이터: 연속적인 값을 가지며, 범위 내에서 무한히 많은 값으로 표현

값이 연속적임, 값 사이에 무한히 많은 세부적인 값이 존재(사람의 키, 온도, 시간)

 

3. 데이터 전처리

1) 질적 데이터(명목척도, 서열척도)는 숫자로 변환하여, 모델에 입력해야함

명목척도: 원 핫 인코딩(숫자에 구분만 짓게하고 숫자 크기 차이에 의미를 두지 않기 위해 한다.)

서열척도: 라벨 인코딩(숫자에 의미를 넣어 대소 관계를 구분 지어야할 때)

 

2) 양적 데이터(등간, 비율 척도)는 숫자 그대로 사용가능

등간 척도 데이터는 비율 척도처럼 절대적 의미가 없기 때문에 주의

-비율연산을 피해야함(값을 두 배로 하거나, 나누기 연산은 의미가 없음 EX. 섭씨 온도20도의 두 배는 40도라고 인식하지 않도록 해야 함)

-정규화: 0~1사이의 정규화보다 표준화(Standard)가 적절

-피처 엔지니어링: 차이를 강조한 특징을 생성하는 것이 좋음(날짜 데이터를 사용할 때 특정 날짜에서 얼마나 시간이 흘렀는지로 표현)

-분류 모델에 클래스로 사용: 순서나 차이만을 반영하도록 데이터 변환(구간별로 범주화 - 온도를 여러 구간(저,중,고온)으로 나눔

 

4. 데이터 시각화(이상치를 처리하는 가능성이 큰 데이터를 보여주기도 한다.)

질적 데이터: 카테고리나 범주의 빈도와 비율 시각화(막대 그래프, 파이 차트, 히트맵)

양적 데이터: 데이터의 분포, 관게, 변화 추이를 시각화(히스토그램, 산점도, 선 그래프, 상자그림)

 

5. 데이터의 중심지표란?

데이터의 중심 경향을 나타내는 값으로 주어진 데이터의 대표적인 값

-평균mean(이상치에 민감)

-중앙값median(이상치에 영향을 덜 받음)

-최빈값mode(이상치에 영향을 덜 받음)

 

-데이터 분포 형태에 따른 중심 지표 비교

대칭: 데이터가 정규 분포처럼 돠우 대칭으로 나타나는 분포(사람의 키, 시험점수, 제품 품질)

왼쪽꼬리: 데이터가 왼쪽으로 치우쳐있을 때 나타나는 분포(기계고장률, 퇴직 연령)

오른쪽 꼬리: 데이터가 오른쪽으로 치우쳐져 있을 때 나타나는 분포(소득 분포, 주택 가격)

 

6. 데이터의 중심 지표의 중요성

데이터의 대표성 활용

1) 결측치, 이상치 대체

2) 데이터 표준화:

-데이터의 분포를 평균이 0, 표준편차가 1(standardscaler)

-표준화된 값은 원래 값이 평균으로부터 얼마나 떨어져있는지 나타내는 상대적인 거리

-표준화의 중요성: 데이터가 서로 다른 단위나 범위를 가질 경우, 학습이 왜곡될 수 있음

3) 모델 선택

-평균 중심의 데이터

데이터가 대칭적: 선형 모델(선형 회귀, SVM)

-중앙값 중심의 데이터

데이터가 치우쳐져 있거나 이상치가 많을 때: 비선형 모델(로버스트 회귀, 랜덤 포레스트)

-최빈값 중심의 데이터:데이터가 명목형(카테고리형)인 경우나 이산형 데이터

주어진 데이터의 주변 이웃 중 가장 많이 나타나는 값 예측(K-이웃)

이산형 결과 예측 시(로지스틱 회귀)

범주형 데이터 기반 분류( 나이브 베이즈)

 

7. 데이터 산포도

데이터가 평균이나 중앙값을 중심으로 얼마나 퍼져 있는지 나타내는 지표

편차variance:각 데이터 값과 데이터의 평균 사이의 차이

분산variance: 편차 제곱의 평균

표준 편차Standard Deviation: 분산의 제곱근으로 단위가 원래 데이터와 같음

사분위수 범위IQR: 중간 50% 데이터의 범위를 나타내는 지표(데이터의 1사분위수(Q1) 3사분위수(Q3)의 차이

 

8. 데이터 상관 관계(수치로 검색해서 보고 선택하는게 좋다)

-양의 상관관계: 한 변수가 증가할 때 다른 변수도 증가하는 관계

-음의 상관 관계: 한 번수가 증가할 때 다른 변수는 감소하는 관계

-무 상관관계:두변수 간에 일정한 관계가 없음(0에 가까울수록 무상관관계다) 

-상관계수: 상관관계의 정도를 수치화한 값이 상관계수(피어슨 상관계수 공식/한계: 주로 선형 관계를 측정하기 때문에 두 변수 간의 관계가 비선형일 경우 이를 제대로 반영하지 못 할 수 있음)

산점도: 상관계수에 따른 데이터 분포 시각화

 

특징(feature)선택

중복정보제거(상관관계가 높은 변수는 유사한 정보를 담고 있을 가능성이 큼,중복되는 변수들 제거하여 모델의 복잡성을 줄이고 성능을 향상 시킬 수 있다.)

중요한 특징 식별: 종속 변수(출력)과 상관관계가 높은 독립변수(입력)을 선택함으로써 모델의 성능을 향상 시킬 수 있음

 

 

9. 확률과 확률 분포

확률: 어떤일이 일어날 가능성을 나타내는 수치

확률 분포: 가능한 경우에 대한 각각의 확률을 나타낸 것

확률의 정의: 특정 사건이 발생하는 경우의 수를 전체 가능 경우의 수로 나눈 값(동전 던지기, 카드 뽑기)

확률의 법칙

어떤 사건 A의 확률은 0에서 1 사이의 값(전체 확률의 합은 1)

확률의 덧셈 법칙: 두 사건 A,B가 있을 때, 둘중 하나가 발생할 확률(두 사건의 확률을 더하고 동시에 일어날 확률을 뺌)

확률의 곱셈 법칙: 두 사건 A,B갈 동시에 일어날 확률(A가 발생활 확률과 A가 발생한 후에 B가 발생할 확률의 곱(서로 독립적일 땐 발생 여부에 영향없음)

여사건 확률: 어떤 사건 A가 일어나지 않을 확률은 1에서 A가 발생할 확률을 뺀 값

조건부 확률: 어떤 사건 a가 발생했을 때, 다른 사건b가 발생할 확률

머신러닝에서의 확률

-다중 클래스 분류:소프트맥스 함수를 통해 각 클래스별 확률을 구함(숫자 이미지 분류)

 

확률분포: 가능한 모든 사건과 각 사건에 대한 확률을 나타낸것

종류

-이산 확률 분포: 이산형 데이터가 가질 수 있는 각각의 값과 그에 대한 확률(주사위 눈금, 로또 번호 추첨, 머신러닝 분류 모델)

-연속 확률 분포:연속형 데이터가 특정 구간에 속할 확률(하루 온도 20~30도일 확률, 금융시장의 주가 확률)

 

 


☑️회고

1주차

배깅이란?

배깅(Bagging)은 여러 모델을 독립적으로 학습시키고 예측을 평균내거나 다수결 투표로 최종 예측을 수행한다.

 

2주차

언제 정규화를 진행할까?

  • 스케일이 다른 피처가 있는 경우: 예를 들어, 한 피처는 수백 단위의 값을, 다른 피처는 소수점을 가진 값을 가질 때 정규화가 필요합니다.
  • 거리 기반 알고리즘: k-NN, SVM, 그리고 신경망은 피처들의 상대적인 크기에 매우 민감합니다.
  • 경사 하강법을 사용하는 경우: 피처들의 값이 크게 차이가 나면 학습 과정이 느려질 수 있습니다.

StandardScaler 사용할 상황은?

데이터의 분포가 정규분포(가우시안 분포)일 때 많이 사용 수치형 데이터에만 사용 가능

 

MinMaxScaler란?

값의 범위를 0과 1사이로 조정하여 정규화를 진행해 모델학습에 도움을 준다.

 

중복값 제거

df = df.drop_duplicates(subset='TransactionID')
TransactionID 열에서 같은 값이 여러 번 나타나는 행 중에서 첫 번째 행을 남기고, 그 외의 중복된 행들을 제거하는 역할

 

IQR을 사용해 제거 및 대체했을 때

제거

df_no_outliers = df[(df['PurchaseAmount'] >= lower_bound) & (df['PurchaseAmount'] <= upper_bound)]
모든 값이 사라짐

 

대체

mean_value = df['PurchaseAmount'].mean()
df['PurchaseAmount'] =df['PurchaseAmount'].apply(lambda x: mean_value if x < lower_bound or x > upper_bound else x)
 PurchaseAmount 모든값이 같은 값으로 바뀜

 

3추차

여러가지 모델 한번에 학습 및 결과 출력 방법

# 모델 정의
models = {
    'Logistic Regression': LogisticRegression(max_iter=200),
    'Decision Tree': DecisionTreeClassifier(),
    'Random Forest': RandomForestClassifier(),
    'Support Vector Machine': SVC(),
    'K-Nearest Neighbors': KNeighborsClassifier()
}

# 모델 학습 및 평가
results = {}
for model_name, model in models.items():
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    
    results[model_name] = {
        'Accuracy': accuracy_score(y_test, y_pred),
        'Precision': precision_score(y_test, y_pred),
        'Recall': recall_score(y_test, y_pred),
        'F1 Score': f1_score(y_test, y_pred)
    }

results_df = pd.DataFrame(results).T


results_df

 

 

results_df = pd.DataFrame(results).T에서 T의 역할은?

데이터프레임의 행을 열로, 열을 행으로 바꿔서 results_df에 저장

 

 

4주차

클러스트링이란?(고객 세분화, 이미지 처리, 문서 군집화 / K-means, Hierarchical Clustering, DBSCAN)

데이터를 비슷한 특성을 가진 그룹(클러스터)으로 나누는 비지도 학습(unsupervised learning) 기법

데이터의 구조를 이해하고, 패턴을 발견하며, 데이터 포인트 간의 유사성을 기반으로 분류하기 위해 사용

목적: 데이터 탐색, 군집화, 분류 전처리, 이상 탐지

 

 

metrics 중

1. adjusted_rand_score

정의: 두 클러스터링 결과 간의 유사성을 측정하는 지표로, 클러스터링의 결과가 얼마나 비슷한지를 평가

범위: -1부터 1까지의 값을 가지며, 1은 완벽하게 일치함, -1은 완전히 불일치함, 0은 임의의 클러스터링을 의미

용도: 클러스터링의 품질을 평가할 때 사용하며, 클러스터링 결과와 실제 레이블 간의 일치를 평가

 

2. homogeneity_score

정의: 클러스터 내의 샘플들이 얼마나 동일한 클래스를 가지는지를 측정( 얼마나 "균일"한지를 평가)

범위: 0에서 1 사이의 값을 가지며, 1은 모든 클러스터가 동일한 클래스를 포함

용도: 클러스터가 얼마나 잘 구성되어 있는지를 평가하며,  ("순수성")

 

3. completeness_score

정의: 실제 레이블의 모든 샘플들이 해당 클러스터에 얼마나 포함되어 있는지를 측정( 샘플들이 얼마나 잘 클러스터링되어 있는지를 평가)

범위: 0에서 1 사이의 값을 가지며, 1은 모든 샘플이 동일한 클러스터에 포함되어 있음을 의미

용도: 얼마나 잘 모든 샘플을 포함하는지를 평가(완전성)

 

train_test_split는 언제 사용?

머신러닝 모델을 훈련하고 평가하기 위해 데이터셋을 훈련 세트와 테스트 세트로 나눌 때 사용

모델을 학습한 후, 테스트 데이터로 학습하지 않은 데이터에서의 성능을 평가

과적합(overfitting)되는 것을 방지하며 일반화 성능을 확인

 

SimpleImputer는 언제 사용?

데이터셋에서 누락된 값을 채우기 위해 사용

누락된 데이터가 있으면 오류가 발생하거나 모델 성능에 영향을 줄 수 있기 때문

 

사용방법

from sklearn.impute import SimpleImputer

imputer = SimpleImputer(strategy='mean')

 

오늘을 도전 과제인 Netfilx리뷰 파일 모델학습 까지 도전해 보았다.

 

나는 발표와 발표자료 만들기 담당이지만

 

내가 한번 해보아야 팀원들이 어떤 말을 하는지 알 수 있을거같다는 생각에 진행해 보았다.

 

순서는 

 

1. 데이터 셋 불러오기

 

2. 데이터 전처리

 

3. feature 분석

 

4. 리뷰 예측 모델 학습시키기(LSTM)

 

5. 회고(모델학습 / git사용)

 

으로 소개를 진행하겟습니다.

 


☑️ 데이터 셋 불러오기

링크에서 데이터셋을 다운로드한 후에 데이터셋을 불러오고, 불러온 데이터프레임의 상단 5개의 데이터와 하단 5개의 데이터, 컬럼과 shape를 불러오는 코드를 작성해주세요.

 

import pandas as pd
import numpy as np


df = pd.read_csv("netflix_reviews.csv")
df_sh = data.shape
df_index = data.columns

print(f"Shape of the dataset {df_sh}")
print(f"Columns in the dataset: {df_index}")

df.head()

df.head(-1)

 

이제 f-string을 사용하는 방법은 버벅이지도 않고 바로 생각할 수 있게 되었다.


☑️ 데이터 전처리

텍스트 데이터에는 불용어(쓸모없는 단어, 구두점 등)가 많습니다. 해당 부분을 없애주는 처리가 필요합니다. 텍스트 데이터에 대한 전처리를 해주세요.

 

import re

def preprocess_text(text):
    if isinstance(text, float):
        return ""
    text = text.lower()
    text = re.sub(r'[^\w\s]', '', text)
    text = re.sub(r'\d+', '', text)
    text = text.strip()
    return text

df['content'] = df['content'].apply(lambda x: preprocess_text(x))

 

위 코드를 이용하여 content열의 문자를 소문자로,  구두점 제거, 띄어쓰기 제외 빈칸 제거를 시키는 함수를 정의 하였고

 

content열에만 적용 시켰다.


☑️ feature 분석

데이터를 잘 불러오셨다면 해당 데이터의 feature를 찾아야 합니다. 해당 넷플릭스의 데이터에는 리뷰가 1점부터 5점까지 있습니다. 해당 데이터의 분포를 그래프로 그려주세요.

 

import seaborn as sns  # 시각화 라이브러리
import matplotlib.pyplot as plt  # 그래프 표시 라이브러리

# 리뷰 점수 빈도 계산
score_counts = df['score'].value_counts()

# 그래프 만들기
plt.figure(figsize=(10, 7))
# 색상 넣기는 강의 자료에서 찾았습니다. palette = 'viridis'
# X축에 점수, Y축에 해당 점수의 개수
sns.barplot(x=score_counts.index, y=score_counts.values, palette='viridis')  
plt.xlabel('Score')  # X축 레이블
plt.ylabel('Count')  # Y축 레이블
plt.title('Distribution of Review Scores')  # 그래프 제목
plt.show()

 

 

위 코드를 작성하여 점수별 분포를 막대 그래프로 표현 하였다.


☑️ 리뷰 예측 모델 학습시키기(LSTM)

이제 어떤 리뷰를 쓰면 점수가 어떻게 나올지에 대해서 예측을 해보고 싶습니다. 로지스틱 회귀 등을 사용하여, 리뷰에 대한 점수 예측을 진행해보세요

 

import torch
import torch.nn as nn
import torch.optim as optim
from torchtext.data.utils import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator
from torch.utils.data import DataLoader, Dataset
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder

reviews = df['content'].fillna('')  # 리뷰가 없는 경우 공백으로 대체
ratings = df['score']

# 토크나이저 및 어휘 집합 생성
tokenizer = get_tokenizer("basic_english")

def yield_tokens(df_iter):
    for text in df_iter:
        yield tokenizer(text)

vocab = build_vocab_from_iterator(yield_tokens(train_reviews), specials=["<unk>"])
vocab.set_default_index(vocab["<unk>"])

 

# 텍스트 파이프라인: 텍스트 -> 토큰 -> 인덱스
def text_pipeline(x):
    return [vocab[token] for token in tokenizer(x)]

# 레이블 파이프라인: 점수(1-5)를 0부터 시작하는 인덱스로 변환
label_encoder = LabelEncoder()
train_ratings_encoded = label_encoder.fit_transform(train_ratings)
test_ratings_encoded = label_encoder.transform(test_ratings)
    
class ReviewDataset(df):
    # 초기화 메서드
    def __init__(self, reviews, ratings, text_pipeline, lable_pipeline):
        # 각 데이터를 변수로 저장
        self.reviews = reviews
        self.ratings = ratings
        self.text_pipeline = text_pipeline
        self.label_pipeline = label_pipeline
        
    # 데이터 셋의 크기 반환
    def __len__(self):
        return len(self.reviews)
    
    # 인덱스를 사용해 특정 데이터 항목 가져오기
    def __getitem__(self, idx):
        review = self.text_pipeline(self.reviews[idx])
        rating = self.label_pipeline(self.ratings[idx])
        # 리뷰와 점수 텐서로 변환
        return torch.tensor(review), torch.tensor(rating)
    
# 데이터 셋 정의
train_dataset = ReviewDataset(train_reviews, train_ratings, text_pipeline, label_pipeline)
test_dataset = ReviewDataset(test_reviews, test_ratings, text_pipeline, label_pipeline)

# 데이터 로더 정의
BATCH_SIZE = 64

# LSTM모델 정의
class LSTMModel(nn.Module):
    def __init__(self, vocab_size, embed_dim, hidden_dim, output_dim):
        # super()은 부모 클래스의 메서드나 속성을 호출
        # nn.Module의 초기화 메서드를 호출해 초기화 수행
        super(LSTMModel, self).__init__()
        # 임베딩을 진행하는 이유: 단어를 고차원 공간에서의 실수 벡터로 변환
        # 모델이 텍스트의 의미를 이해하게 만든다.
        # sparse=True는 희소 인베딩을 활성화 한다.
        # 임베딩 레이어가 메모리 효율적으로 작동하게 만들며, 단어 인덱스 만을 사용하게 만든다.
        self.embedding = nn.EmbeddingBag(vocab_size, embed_dim, sparse=True)
        # LSTM 정의
        # 시퀀스 데이터를 처리 역할
        # LSTM은 장기 의존성 학습으로 문맥의 정보를 잘 기억
        # 텍스트 시퀀스는 시간적으로 의존성을 가지므로 LSTM을 통해 정보를 효과적으로 학습
        # batch_first=True는 입력텐서의 첫 번째 차원이 배치 크기로 만든다.
        self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True)
        self.fc = nn.Linear(hidden_dim, output_dim)
        
    # 모델의 순전파 정의
    # text는 모델에 입력 되는 텍스트 데이터
    # 순전파란? 입력 데이터가 모델을 통해 전달되어 최종 출력이 생성 되는 과정 의미
    # 출력 레이어에서 예측값이 생성된다.
    def forward(self, text):
        embedded = self.embedding(text)
        # unsqueeze(0)는 입력 텐서에 배치차원을 추가하는 방법
        # 왜 추가하는지? LSTM은 일반적으로 (배치 크기, 시퀀스 길이, 특성 수)의 형태를 가진 텐서를 입력받는데
        # embedded 텐서가 (시퀀스 길이, 특성 수)의 형태일 경우, unsqueeze(0)을 사용하여 (1, 시퀀스 길이, 특성 수)의 형태로 변환해 LSTM에 맞춘다.  
        output, (hidden, cell) = self.lstm(embedded.unsqueeze(0))
        # hidden[-1]은 모든 숨겨진 상태의 텐서에서 마지막에 숨겨진 상태를 의미
        return self.fc(hidden[-1])

 

 

위 코드는 완성이 된것이 아니다.

 

작성해나가며 새롭게 알게 된 정보들을 정리하고 적용해나가다가

 

너무 어렵고 감이 잡히지않아 멈추게 되었다 (공부를 마치는 시간은 이미 지나 버림)

 

위 코드 설명은 생략하겟다.(지금 머리가 너무 볶잡해서..)

 


☑️ 회고

오늘 공부하면 만난 정보와 오류나 궁금증들을 공유해보고자 한다.

 

데이터 셋 불러오기

1. 처음부분 마지막부분 5개씩 가져오기

 

2가지 방벙이 있다는 것을 확인했다

 

df.head

------------------------

df.head()

df.head(-1)

 

이 두가지 방법 중에서 가독성이 두번 째 방법이 더 좋은 것으로 보인다.

 

데이터 전처리

 

1. 사용자 지정 함수 (def)를 데이터 프레임에 적용 시키는 방법을 모르겟음 
apply와 lambda함수를 사용하여 적용(lambda 함수의 활용법을 더 알아봐야할듯)
lambda는 임의의 함수, 맵핑 등에 사용 가능함(지금 알고있는 방식이 2가지) 

 

2. 텍스트의 불필요한 부분만 제거하는 re의 표현식

. : 임의의 한 문자 (줄바꿈 문자는 제외)
 \w : 알파벳 문자, 숫자, 언더스코어 ([a-zA-Z0-9_])
 \W : 문자, 숫자, 언더스코어가 아닌 모든 것
 \d : 숫자 ([0-9])
 \D : 숫자가 아닌 것
 \s : 공백 문자 (스페이스, 탭, 줄바꿈)
 \S : 공백이 아닌 문자

 w랑 s는 묶어서 사용했는데 왜 d+는 따로 사용했는지

 * : 0번 이상 반복
 + : 1번 이상 반복
 ? : 0번 또는 1번
 {n} : 정확히 n번 반복
 {n,} : n번 이상 반복
 {n,m} : 최소 n번, 최대 m번 반복
    
 ^ : 문자열의 시작
 $ : 문자열의 끝
 \b : 단어의 경계
 \B : 단어 경계가 아님

 

feature 분석

1. 수치형 데이터의 값마다 수를 세는 방법 

Score_count = df['score'].value_counts()

사용할수있는 모든 count방법을 다 사용해보았음

 

2. 그래프의 x,y열에 값을 넣고 인덱스를 넣는 방법

sns.barplot(x=score_counts.index, y=score_counts.values, palette='viridis')  

저기 위치에 아무것도 안 넣기, keys/values넣기, keys/value하나씩 넣어보기 하다가 튜터님에게 질문하여 알게 되었다.


☑️ GIT

git
git rm --cached "레포 파일 삭제" => commit => push해야지 레포에 적용 됨
git rm 삭제할 파일 "파일 자체 삭제"
git config --global core.autocrlf true"윈도우 줄바꿈 자동변환"
git config --global core.autocrlf false"자동변환 비활성화"

vim에서 탈출 방법
esc누르고 :wq

git 공동 작업 환경
git branch -a 브랜치 이름 학인
git checkout branch-name 특정 브랜치로 이동
git pull origin branch-name 최신파일 가져오기

충돌이 발생했을 때
vim example_file.txt
nano example_file.txt
code example_file.txt
3개중에 1개로 파일을 열어서 내리다보면 <<<<<<<======>>>>>>으로
표시된 구간에서 이전/지금/ 합쳐서 저장할지 마우스로 클릭하고 저장한 뒤
다시 git add부터 시작하면 된다.

 

 

 

오늘은 강의나 복습보다 다음주에 있을 과제 준비를 하며 공부를 하였습니다.

 

발표자료 만들기와 발표가 저의 파트이지만 발표를 제대로 준비하기 위해서 코드들이 어떻게 흘러가는지 흐름을 파악 하자는 생각으로 진행하였습니다.

 

  1. DATA LOAD
  2. DATA FEATURE 분석
  3. DATA 전처리
  4. 모델학습 (로지스틱, 랜덤 포레스트, XGBoost)
  5. 회고(진행하며 오류, 해결, 지식 등)

이 순서대로 학습을 진행하였고 소개해 볼까 합니다.

 

☑️ DATA  LOAD

DATA LOAD에는 2가지 방법이 있습니다.

  • import pandas as pd df = pd.read_csv(”titanic.csv”)
  • import seaborn as sns titanic = sns.load_dataset('titanic')

위 두가지의 차이점을 설명하겟습니다.

 

READ: Kaggle 또는 다른 곳에서 제공하는 타이타닉 데이터는 원본에 가까운 형태이다.

SEABORN: Seaborn에서 제공하는 타이타닉 데이터셋은 시각화에 적합한 형식으로 다듬어진다.

  • 정보 추가: Seaborn의 타이타닉 데이터셋은 시각화와 분석을 위해 추가된 정보(column) class, who, alive, deck
  • 컬럼 이름의 차이: 일부 컬럼은 시각화에 더 직관적이게 사용되도록 이름이 변경 pclass는 class라는 범주형 변수로 다시 변환
  • 범주형 데이터 변환: sex, alive와 같은 열들은 범주형(categorical) 데이터로 변경되었고, who, adult_male 등의 새로운 파생 변수가 추가되었습니다.

결론:

Seaborn에서 제공하는 타이타닉 데이터셋은 시각화와 머신러닝 분석을 위해 좀 더 가공된 버전입니다. 데이터 전처리가 일부 포함되어 있고, 추가적인 열이 생겼기 때문에 원본 타이타닉 데이터셋과 차이가 생깁니다.

 


☑️ DATA  FEATURE 분석

  • titanic.columns()

위 함수를 이용해서 타이타닉 데이터 셋의 columns를 가져와서 해석을 진행하였다.

 

 

위 함수를 사용해서 결측치, 데이터타입, 행/열의 수를 확인

 

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 15 columns):
 #   Column       Non-Null Count  Dtype
---  ------       --------------  -----
 0   survived     891 non-null    int64
 1   pclass       891 non-null    int64
 2   sex          891 non-null    object
 3   age          714 non-null    float64
 4   sibsp        891 non-null    int64
 5   parch        891 non-null    int64
 6   fare         891 non-null    float64
 7   embarked     889 non-null    object
 8   class        891 non-null    category
 9   who          891 non-null    object
 10  adult_male   891 non-null    bool
 11  deck         203 non-null    category
 12  embark_town  889 non-null    object
 13  alive        891 non-null    object
 14  alone        891 non-null    bool
dtypes: bool(2), category(2), float64(2), int64(4), object(5)
memory usage: 80.7+ KB

 

  • titanic.head()

위 함수를 사용하여 각 column의 1~5번 까지의 행을 가져와서 어떤 값들이 들어있는지 확인

  • titanic.describe()

위 함수를 사용하여 수치형으로 이루어진 데이터들의 count(행의 수), mean(평균), std(표준편차), min/25%/50%/75%/max(크기에 맞는 값)을 확인

  • print(titanic.isnull().sum())

위 함수를 사용하여 각 column의 결측치를 확인

survived         0
pclass           0
sex              0
age            177
sibsp            0
parch            0
fare             0
embarked         2
class            0
who              0
adult_male       0
deck           688
embark_town      2
alive            0
alone            0
dtype: int64

 


☑️ DATA  전처리

1. 결측값 대체

# 나이(age) 열의 결측값을 중앙값으로 채움
titanic['age'].fillna(titanic['age'].median(), inplace=True)

# 승선한 항구(embarked) 열의 결측값을 최빈값으로 채움
titanic['embarked'].fillna(titanic['embarked'].mode()[0], inplace=True)

# 승선 도시(embark_town) 열의 결측값을 'Unknown'으로 채움 
titanic['embark_town'].fillna('Unknown', inplace=True)

# 'deck' 열을 object 타입으로 변환
titanic['deck'] = titanic['deck'].astype(str)

# 결측값을 'Unknown'으로 채움
titanic['deck'].fillna('Unknown', inplace=True)

#결측치 제거 데이터 프레임
titanic_no_nan = titanic

#deck과 embark_town을 fillna(0)로 진행했을 때 TypeError
#해결하기 위해 dtype으로 각 데이터 타입을 확인
#숫자형 데이터'0'에서 문자형 데이터'Unknown'으로 대체
#각 타입을 astype(category)과 (object)로 타입 변화 추가해도 안됨
#이유를 찾아보니 원래 카테고리 타입인 데이터에는 새로운 카테고리 값을 추가할 때 에러가 발생
#category 타입 경우 새로운 카테고리를 추가하기 위해선 기존 카테고리 목록에 추가 되어있어야 가능 
#또는 타입을 변환을 진행할 때 astype(object)로 작성해서 오류
#astype(str)로 수정 하니 object타입으로 변환 가능

 

2. 인코딩

# 성별 인코딩: 'male'은 0, 'female'은 1로 매핑
titanic_no_nan['sex'] = titanic_no_nan['sex'].map(lambda x: 0 if x == 'male' else 1 )
# 생존 여부 인코딩: 'yes'는 0, 'no'는 1로 매핑
titanic_no_nan['alive'] = titanic_no_nan['alive'].map(lambda x: 0 if x == 'yes' else 1)
# 승선한 항구 인코딩: 'C'는 0, 'Q'는 1, 'S'(Southampton)은 2로 매핑
titanic_no_nan['embarked'] = titanic_no_nan['embarked'].map(lambda x: 0 if x == 'C' else 1 if x == 'Q' else 2)
# 승객 등급 인코딩: 'First'는 0, 'Second'는 1, 'Third'는 2로 매핑
titanic_no_nan['class'] = titanic_no_nan['class'].map(lambda x: 0 if x =='First' else 1 if x =='Second' else 2) 
# 성별에 따른 그룹화 인코딩: 'man'은 0, 나머지(여성)는 1로 매핑
titanic_no_nan['who'] = titanic_no_nan['who'].map(lambda x: 0 if x == 'man' else 1)
# 성인 남성 여부 인코딩: 'False'는 0, 'True'는 1로 매핑
titanic_no_nan['adult_male'] = titanic_no_nan['adult_male'].map(lambda x: 0 if x == 'False' else 1)
# 갑판 인코딩: 'A'는 0, 'B'는 1, 'C'는 2, 'D'는 3, 'E'는 4, 'F'는 5, 'G'는 6으로 매핑
titanic_no_nan['deck'] = titanic_no_nan['deck'].map(lambda x:  0 if x == 'A' else 1 if x == 'B' else 2 if x == 'C' else 3 if x == 'D' else 4 if x == 'E' else 5 if x == 'F' else 6)
# 승선 도시 인코딩: 'Cherbourg'는 1, 'Queenstown'은 2, 'Southampton'은 3, 결측값은 0으로 매핑
titanic_no_nan['embark_town'] = titanic_no_nan['embark_town'].map(lambda x: 1 if x == 'Cherbourg' else 2 if x == 'Queenstown' else 3 if x == 'Southampton' else 0)
# 혼자 탑승 여부 인코딩: 'False'는 0, 'True'는 1로 매핑
titanic_no_nan['alone'] = titanic_no_nan['alone'].map(lambda x: 0 if x == 'False' else 1)

#head함수에서 class의 데이터 타입이 category인것으로 확인
#타입 통일을 위해서 astype으로 int 적용해도 category로 나옴
#str을 적용해서 int64로 바뀐것 확인
titanic_no_nan['class'].astype(str)

# 인코딩된 데이터프레임을 titanic_enco 변수에 저장
titanic_enco = titanic_no_nan 

 

 

3. HEAD()로 인코딩 작동여부 확인

print(titanic_enco['sex'].head())
print(titanic_enco['alive'].head())
print(titanic_enco['embarked'].head())
print(titanic_enco['class'].head())
print(titanic_enco['who'].head())
print(titanic_enco['adult_male'].head())
print(titanic_enco['deck'].head())
print(titanic_enco['embark_town'].head())
print(titanic_enco['alone'].head())

 

4. 새로운 열 작성

#형제,자매, 부부, 부모, 자식의 수는 가족family_size로 묶을 수 있어 데이터 관리에 용이함
#본인을 포함 시켜야 하니 +1
titanic_enco['family_size'] = titanic_enco['sibsp'] + titanic_enco['parch'] + 1

 

5. 이상치 확인

#이상치를 확인 했지만 특별히 높은 값이 없어 그대로 진행
#모든 열의 이상치 확인

#25%보다 작거나 75%보다 크면 이상치로 처리
#quantile로 이상치의 기준점 설정
for column in titanic_enco.columns:
    Q1 = titanic_enco[column].quantile(0.25)
    Q3 = titanic_enco[column].quantile(0.75)
    IQR = Q3 - Q1

    # 이상치 범위 설정
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR

    #여기서 |는 OR의 논리연산자
    #C열의 값중 lower_bound보다 작거나 upper_bound보다 큰 수를 이상치로 간주해 outliers에 저장해서 확인
    outliers = titanic_enco[(titanic_enco[column] < lower_bound) | (titanic_enco[column] > upper_bound)]

    # 이상치가 있을 경우 출력
    # outliers 데이터프레임이 비어 있지 않은지 확인하는 조건문
    # empty 속성은 데이터프레임이 비어있으면 True, 데이터가 하나라도 있으면 False를 반환
    if not outliers.empty:
        print(f"Column: {column}")
        print(outliers[[column]])  # 해당 열의 이상치만 출력
        print()  # 줄바꿈
        
# 값이 출력 되었지만 양이 너무 적어보여 GPT에 제대로 작동 한지 검증해서 마지막 열에만 적용 된것을 확인
# 조건문을 활용한 출력 값 코드 이해 X

 

6. 중복값 확인

#모델 성능 개선을 위해 중복값 존재하는지 확인 후 제거
print(titanic_enco.duplicated().sum())

#데이터 중복값 제거 후 titanic_no_duplicates 변수에 저장
titanic_no_duplicates = titanic_enco.drop_duplicates()

#출력 140

 


 

☑️ 모델학습

📚  로지스틱 회귀 모델

 

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

data = titanic_no_duplicates

data = data[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare', 'embarked', 'family_size']].dropna()

X = data.drop('survived', axis=1)
y = data['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)

# 예측
# model.predict(X_test) 학습된 모델을 사용하여 테스트데이터 X_test에 대한 예측값을 계산.예측 결과는 y_pred에 저장
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)}")

# accuracy_score(y_test, y_pred) 실제값 y_test와 예측 값 y_pred를 비교하여 정확도 계산
# classification_report(y_test, y_pred) 모델의 성능을 요약하여 출력(정밀도, 재현율,F1점수, 지원)
# confusion_matrix(y_test, y_pred) 혼동 행렬을 생성하여 모델의 성능을 시각적으로 나타낸다.
#Precision (정밀도): 모델이 양성으로 예측한 것 중 실제 양성의 비율입니다.
#Recall (재현율): 실제 양성 샘플 중에서 모델이 올바르게 예측한 비율입니다.
#F1-Score: 정밀도와 재현율의 조화 평균으로, 두 지표의 균형을 잡아줍니다.(높을 수 록 성능이 균형있게 수행 된 것이다.)
#평균 Avg 나온 숫자들이 비슷할 수록 좋다.
# 혼동행렬: TP, FN, FP, TN
#TP (True Positives): 올바르게 긍정으로 예측된 샘플 수
#FP (False Positives): 잘못 긍정으로 예측된 샘플 수
#TN (True Negatives): 올바르게 부정으로 예측된 샘플 수
#FN (False Negatives): 잘못 부정으로 예측된 샘플 수


📚  랜덤포레스트 모델

from sklearn.ensemble import BaggingRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error

data = titanic_no_duplicates

data = data[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare', 'embarked', 'family_size']].dropna()

X = data.drop('survived', axis=1)
y = data['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_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

rf_model = RandomForestRegressor(n_estimators=100, random_state=42)
# 모델 학습
rf_model.fit(X_train_scaled, y_train)

# 예측
y_pred_rf = rf_model.predict(X_test_scaled)

# 평가
mse_rf = mean_squared_error(y_test, y_pred_rf)
print(f'랜덤 포레스트 모델의 MSE: {mse_rf}')

# 훈련 데이터에서 예측
y_train_pred = xgb_model.predict(X_train_scaled)

# 훈련 데이터의 MSE 계산
mse_train = mean_squared_error(y_train, y_train_pred)
print(f'훈련 데이터에 대한 MSE: {mse_train}')


#MSE는 회귀모델에 적합한 평가모델이기 때문에 좋지 못한 성능으로 나온다.
# 0 또는 1로 나뉘는 이진 분류는, MSE가 0.25는 예측이 실제 값에서 평균적으로 0.5 (반쯤 맞고 반쯤 틀림) 정도
#과적합: 훈련 데이터에서 너무 성능이 좋고 테스트 데이터에서 성능이 떨어진다면 과적합의 징후
#0.06 정도 차이로 과적합은 없는듯

 


📚  XGBoost모델

import pandas as pd
import numpy as np
import seaborn as sns
from sklearn.ensemble import BaggingRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import xgboost as xgb
from sklearn.metrics import mean_squared_error

data = titanic_no_duplicates

data = data[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare', 'embarked', 'family_size']].dropna()

X = data.drop('survived', axis=1)
y = data['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_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

xgb_model = xgb.XGBRegressor(n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42)

# 모델 학습
xgb_model.fit(X_train_scaled, y_train)

# 예측
y_pred_xgb = xgb_model.predict(X_test_scaled)

# 평가
mse_xgb = mean_squared_error(y_test, y_pred_xgb)
print(f'XGBoost 모델의 MSE: {mse_xgb}')

# 훈련 데이터에서 예측
y_train_pred = xgb_model.predict(X_train_scaled)

# 훈련 데이터의 MSE 계산
mse_train = mean_squared_error(y_train, y_train_pred)
print(f'훈련 데이터에 대한 MSE: {mse_train}')

#과적합: 훈련 데이터에서 너무 성능이 좋고 테스트 데이터에서 성능이 떨어진다면 과적합의 징후
#0.06 정도 차이로 과적합은 없는듯
# 0 또는 1로 나뉘는 이진 분류는, MSE가 0.25는 예측이 실제 값에서 평균적으로 0.5 (반쯤 맞고 반쯤 틀림) 정도

 


☑️ 회고

결측치 대체 및 제거

titanic['age'].fillna(titanic['age'].median(), inplace=True)

titanic['embarked'].fillna(titanic['embarked'].mode()[0], inplace=True)

titanic['embark_town'].fillna('Unknown', inplace=True)

titanic['deck'].fillna('Unknown', inplace=True)


#deck과 embark_town을 fillna(0)로 진행했을 때 TypeError
#해결하기 위해 dtype으로 각 데이터 타입을 확인
#숫자형 데이터'0'에서 문자형 데이터'Unknown'으로 대체
#각 타입을 astype(category)과 (object)로 타입 변화 추가해도 안됨
#이유를 찾아보니 원래 카테고리 타입인 데이터에는 새로운 카테고리 값을 추가할 때 에러가 발생
#category 타입 경우 새로운 카테고리를 추가하기 위해선 기존 카테고리 목록에 추가 되어있어야 가능 
#또는 타입을 변환을 진행할 때 astype(object)로 작성해서 오류
#astype(str)로 수정 하니 object타입으로 변환 가능

 

결론 =>

1. 카테고리 데이터 타입일 경우 결측치가 바뀌지 않아 데이터타입 변환을 해야한다.

2. 문자열 데이터에 대체값으로 숫자형 데이터를 넣으면 오류가 난다.

3. 카테고리 타입 변환시 str로 변환하면 object로 표시 된다.

 

인코딩

titanic_no_nan['sex'] = titanic_no_nan['sex'].map({'male': 0, 'female': 1})
titanic_no_nan['alive'] = titanic_no_nan['alive'].map({'no': 1, 'yes': 0})
titanic_no_nan['embarked'] = titanic_no_nan['embarked'].map({'C': 0, 'Q': 1, 'S': 2})
titanic_no_nan['class'] = titanic_no_nan['class'].map({'First': 0, 'Second': 1, 'Third': 2})
titanic_no_nan['who'] = titanic_no_nan['who'].map({'man': 0, 'woman': 1})
titanic_no_nan['adult_male'] = titanic_no_nan['adult_male'].map({'True': 1, 'False': 0})
titanic_no_nan['deck'] = titanic_no_nan['deck'].map({'A': 1, 'B': 2, 'C': 3, 'D': 4, 'E': 5, 'F': 6, 'G': 7, 'nan': 0})
titanic_no_nan['embark_town'] = titanic_no_nan['embark_town'].map({'Cherbourg': 1, 'Queenstown': 2, 'Southampton': 3, 'Unknown': 0})
titanic_no_nan['alone'] = titanic_no_nan['alone'].map({'False': 0, 'True': 1})

#map만 사용하였을때 nan값으로 처리 되어서 lambda함수를 같이 사용해야지 된다는 피드백 받음
#그래서 lambda함수를 사용하면 왜 되는건지 찾아봄
#map만 사용했을 땐 사전의 키와 값을 직접적으로 연결하여 변환하기에 간단한 매핑 가능
#lambda함수를 사용하게 되면 복잡한 변환 로직 사용 가능하며 어떤 형식이든 유연히 처리

 

결론 =>

1. map함수는 간단한 맴핑에만 사용해야한다.

2. map(lambda())함수를 이용하면 복잡한 로직에도 유연하게 작동한다.

3. apply(lambda())도 맴핑에 사용 가능하다.

4. lambda함수 사용 방법을 익혔다.

 

 

이상치 확인

Q1 = titanic_enco.quantile(0.25)
Q3 = titanic_enco.quantile(0.75)
IQR = Q3 - Q1 

lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

outliers = titanic_enco[(titanic_enco < lower_bound) | (titanic_enco > upper_bound)]
print(outliers)

#데이터프레임 전체를 한번에 확인해서 출력값에 nan값이 많이나오는 것을 확인
#컬럼별로 하나씩 확인하던 중 간단하게 작성하는 방법 검색해서 해결

 

결론 =>

이상치 확인 할 column이 많은 경우 for 함수식을 활용해 간단하게 적용 시킬 수 있다.

 

이상치확인 출력

    if not outliers.empty:
        print(f"Column: {column}")
        print(outliers[[column]])  # 해당 열의 이상치만 출력
        print()  # 줄바꿈

아직 이해하지는 못했지만 코드를 배워서 만족(내일 튜터님에게 물어볼 예정)

☑️ 노션

노션을 이용해서 과제발표를 준비하기로 마음을 먹었습니다.

 

하지만 노션을 사용해 본적이 없어 

 

노션에 대해 알아보며 작성했고 어떤 부분을 알게 되었는지 말하려 합니다.

 

머신 / 딥 러닝

 

머신 / 딥 러닝 | Notion

타이타닉 생존자 예측(필수)

teamsparta.notion.site

 

타이타닉 데이터 셋의 특징 분석 까지 끝났다.

 

노션을 활용해서 알게 된 내용

  1. 노션을 메모장 등 본인이 확인하기 편하게 꾸밀 수 있다.
  2. 이미지, 토글, 파일 첨부 등 많은 노션의 기본 옵션이 존재한다.
  3. 커버, 이모지 등을 활용해서 꾸밀 수 있다.
  4. 레고형식으로 작성해서 가족성을 높일 수 있다.(일렬로 작성하거나 상하좌우로 토글들을 배치하며 작성 가능)

☑️ GITHUB

GITHUB의 공동 작업 환경에서 과제를 진행 하며 알게되고 궁금한 점을 정리하겟습니다.

 

1. github 공동 작업자 환경에서 잘못된 파일을업로드 한 경우 


git rm --cached "레포 파일 삭제"
git rm 삭제할 파일 "파일 자체 삭제"

 

2. github의 파일을 가져올 때 자동으로 줄바꿈이 되지만 오류가 나기도 한다.

 

이를 방지하기 위한 명령어

 

git config --global core.autocrlf true"윈도우 줄바꿈 자동변환"
git config --global core.autocrlf false"자동변환 비활성화"

3. git 공동 작업 환경에서 파일을 자신의 로컬 환경에 가져오는 명령어


git branch -a 브랜치 이름 학인
git checkout branch-name 특정 브랜치로 이동
git pull origin branch-name 최신파일 가져오기

 

이떄 pull로 가져온 업데이트한 파일은 기존 로컬 환경에 있는 파일에 덮어씌어져 자동 업데이트가 된다.

 

 


☑️ 머신러닝 코드 분석

📚  분류모델-SVM

 

  • 분류와 회귀분석
  • 결정경계를 를 찾아 분류
  • 목표는 마진을 최대화하면서 결정 초평면을 찾아 데이터 포인트를 정확하게 분류

마진: 두 클래스 간의 가장 가까운 데이터 포인트 사이의 거리

 

📚 데이터 로드 및 전처리 

import numpy as np

import pandas as pd

# sklearn.datasets의 load_breast_canser데이터 import

from sklearn.datasets import load_breast_canser

from sklearn.model_selection import train_test_split

#평균을 0, 분산을 1로

from sklearn.preprocessiong import StandardScaler

 

# X에는 특징(feature) 데이터, y에는 타겟(target) 레이블이 저장됩니다.

data = load_breast_canser()

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)

 

scaler = StandradScaler()

# 학습 데이터를 기준으로 스케일을 맞추고(fit_transform), 학습 데이터에 변환 적용

X_train = scaler.fit_transform(X_train)

# 테스트 데이터는 이미 학습 데이터로 스케일이 맞춰졌으므로 transform만 적용

X_test = scaler.transform(X_test)

 

📚모델 학습

#SVC는 SVM알고리즘을 구현한 클래스

from sklearn.svm import SVC

from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

 

#학습

#데이터가 선형으로 분리가능한 경우 사용

# kelnel='linear'선형 커널을 사용해서 학습

model = SVC(kelnel='linear')

model.fit(X_train, y_train)

 

#예측

y_pred = model.predict(X_test)

 

#평가

#\n은 **줄바꿈(new line)**을 의미합니다. 즉, 출력할 때 다음 줄로 넘어가게 합니다.

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)}")

 


📚  분류모델-KNN

  • 분류와 회귀 분석
  • 가장 가까운 이웃을 찾아 분류
  • 새로운 데이터 포인트의 클래스 예측

📚 데이터 로드 및 전처리 

import numpy as np

import pandas as pd

from sklearn.datas import load_breast_cancer

from sklearn.model_selection import train_test_split

from sklearn.preprocessing impor 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)

 

scaler = StandardScaler()

X_train = scaler.fit_transform(X_train)

X_test = scaler.transform(X_test)

 

📚모델 학습

#  sklearn.neighbors의  KNeighborsClassifier를 import

from sklearn.neighbors import KNeighborsClassifier

from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

 

#모델 생성 및 학습

# n_neighbors=5는 K값, 즉 한 데이터의 분류를 결정할 때 참고할 이웃 데이터의 개수

model = KNeighborsClassifier(n_neighors=5)

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)}")

 

k인자에 얼마를 설정할지 결정하는 방법

1. k값은 홀수로 설정(클래스 간의 동점(tie)을 방지)

2. k값이 너무 작으면 과적합, 너무 크면 과소적합

3. 교차 검증 (Cross-Validation) 사용

4. 엘보우 방법 (Elbow Method)

여러 k값에 대해 정확도를 평가하고, 정확도가 급격하게 변화하는 구간을 찾아 k를 선택하는 방법

5. 데이터 크기에 따른 고려(데이터가 클수록 큰 k값, 작을수록 작은 k값)

 

=> 다양한 k값을 시도하면서, 교차 검증을 통해 각 k값에 대한 모델 성능을 평가하고, 그 중 가장 높은 성능을 보이는 k값을 선택

 


📚  분류모델-나이브베이즈

📚나이브베이즈

  • 주어진 데이터 포인트가 특정 클래스에 속할 확률을 계산하여 분류
  • 3가지 베이즈 정리를 기반으로 통계적 분류
  • 가우시안 나이브베이즈: 특징들이 연속적이고 정규 분포를 따른다고 가정합니다.                                                           from sklearn.naive_bayes import GaussianNB
  • 베르누이 나이브베이즈: 특징들이 이진수(0 또는 1)로 표현되는 경우 사용합니다.                                                      from sklearn.naive_bayes import BernoulliNB
  • 멀티노미얼 나이브베이즈: 특징들이 다항 분포를 따르는 경우 사용합니다. from sklearn.naive_bayes import MultinomialNB

📚 데이터 로드 및 전처리

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)

 

scaler = StandardScaler()

X_train = scaler.fit_transform(X_train)

X_test = scaler.transform(X_test)

 

📚모델 학습

#GaussianNB 연속형 피처들이 많은 경우에 사용 된다.

from sklearn.naive_bayes import GaussianNB

from sklearn.metrics import accuracy_score, classification_report, confusion_metrix

 

model = GaussinaNB()

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 Metrix:\n{confusion_metrix(y_test, y_pre)}")

 


 

📚 분류모델 - 의사결정 나무

📚의사결정 나무

데이터 특징을 기준으로 의사결정 규칙을 만들고 분류나 회귀에 사용한다.

트리구조를 가지며 내부 노드는 데이터의 특징의 테스트, 가지(brach)는 결과, 리프노드(leaf)는 클래스 레이블을 나타낸다.

 

📚 데이터 로드 및 전처리

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)

# 데이터 스케일링
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

 

📚모델학습

# DecisionTreeClassifier의사결정 나무 분류 모델 import

from sklearn.tree import DecisionTreeClassifier

from sklearn.metrics import accuracy_score, classification_report, confusion_metrix

 

#모델 생성 시 random_state를 설정한다.

model = DecisionTreeClassifier(random_state=42)

model.fit(X_train, y_train)

 

y_pred = model.predict(X_test)

 

print(f"Accuracy: {accuracy_score(y_test, y_pred)}")

print(f"Classifier Report:\n{classifier_report(y_test, y_pred)}")

print(f"Confusion Metrix:\n{confusion_metrix(y_test, y_pred)}")

 

모델생성에서 random_state를 설정하는가?

1. 결과의 재현성

random_state를 설정하면 무작위성에 대해 고정된 시드(seed)를 지정하는 것으로 모델을 동일한 조건에서 다시 실행할 때 항상 같은 결과를 얻게 된다.

2. 무작위성이 적용되는 상황

정보이득이나 지니계수를 가진 특성들이 여러개 있을 수 있다. 이때 어떤 특성으로 분할할지 무작위로 선택

최적화: 의사결정나무는 앙상블 기법, 특히 **랜덤 포레스트(Random Forest)**나 **엑스트라 트리(Extra Trees)**에서 무작위로 여러 나무를 구성할 때 사용됩니다. 이러한 무작위성을 제어하기 위해 random_state를 설정하는 것

3. 모델 비교

동일한 데이터셋에서 서로 다른 알고리즘 또는 설정을 비교할 때, 같은 무작위성 조건에서 실행하는 것이 중요합니다. 이를 통해 공정한 비교가 가능합니다.

 


📚 비지도 학습 - K-means clustering

📚K-means clustering

  • 데이터를 k개의 군집(클러스터)으로 나누는 비지도 학습(레이블이 필요없으며, 유사성을 기반으로 군집 형성)
  • 유사한 특성을 가진 데이터를 하나의 클러스터로 묶고, 서로 다른 특성을 가진 데이터를 다른 클러스터로 구분
  • 클러스터 내의 데이터가 최대한 유사하고, 클러스터 간의 데이터는 서로 다르게 만드는 것이 목표
  • 유클리드 거리를 사용해 유사성 측정
  • 중심점: 데이터의 평균 위치

📚데이터 로드 및 전처리

import numpy as np

import pandas as pd

from sklearn.preprocessing import StandardScaler

# sklearn라이브러리의 cluster모듈에서 KMeans클래스 임포트

from sklearn.cluster import kMeans

# 데이터를 시각화 하기 위한 라이브러리 matplotlib의 pyplot 모듈을 plt로 임포트한다.

import matplotlib.pyplot as plt

# 시각화를 위한 고급 API제공, matplotlob과 호환(산점도, 히트맵 등의 시각화)

import seaborn as sns

 

data = pd.read_csv("Mall_Customer.csv")

 

# data에서 필요한 열만 선택하여 새로운 데이터프레임 생성

# Age: 고객의 나이

# Annual Income (k$): 고객의 연간 소득(천 달러 단위)

#Spending Score (1-100): 고객의 소비 점수 (1에서 100 사이)

data = data[['Age', 'Annual Income (k$)', Spending Score (1-100)']]

 

scaler = StandardScaler()

data_scaler.fit_transform(data)

 

📚모델 학습 및 군집화

#각 k값에 대해 K-Means 클러스터링 모델이 계산한 응집도를 저장하기 위한 리스트

inertia = []

#1개부터 10개의 군집으로 실행해 각 군집에 대해 inertia 값을 구할 예정

k = range(1, 11)

for k in K:

#KMeans 클래스의 인스턴스를 생성

# n_clusters=k는 군집 수를 현재 k값으로 설정

# random_state=42는 결과의 재현성을 위해 무작위 초기값을 고정

     kmeans = KMeans(n_clusters=k, random_state=42)

#모델 학습(k개의 군집으로 나누며, inertia 값이 계산)

#data_scaled는 입력 데이터를 전처리하여 스케일링한 데이터셋

     kmeans.fit(data_scaled)

# kmeans.inertia_은 현재 k값에서 K-Means 모델의 inertia값을 반환, 이 값을 리스트 inertia에 추가

     inertia.append(kmeans.inertia_)

 

# 엘보우 그래프를 그릴 때 사용할 도화지(그래프의 크기를 너비 10, 높이 8로 지정)

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

#x축에는 k값, y축에는 inertia값을 설정해 선 그래프를 그린다.

# bx-는 파란색(x축) 선을 의미하여 각 k에 대한 데이터를 시각화한다.

plt.plot(k, inertia, 'bx-')

#x축 레이블을 k, y축 레이블을 inertia로 설정

plt.xlable('k')

plt.ylabel('Inertia')

#그래프의 제목을 'Elbow Method For Optimal k'로 설정

plt.title('Elbow Method For Optimal k')

#그래프 화면 출력

plt.show()

 

# 앞서 엘보우 그래프를 통해 최적의 k 값이 5로 선택되었다고 가정하고, 군집 수가 5인 K-Means 모델을 다시 생성

kmeans = KMeans(n_cluster=5, random_state=42)

# k=5인 K-Means 모델을 data_scaled 데이터에 대해 학습(데이터가 5개의 군집으로 나누어진다.)

kmeans.fit(data_scaled)

 

# 각 데이터 포인트에 할당된 군집 번호를 data 데이터프레임에 새로운 열 'Cluster'로 추가

# kmeans.labels_는 학습된 K-Means 모델에서 각 데이터 포인트가 속하는 군집 번호를 반환

data['Cluster'] = kmeans.labels_

 


📚 비지도 학습 - 계층적 군집화

📚계층적 군집화

  • 데이터포인트를 계층 구조로 그룹화
  • 점진적 병합, 분할 군집 형성
  • 병합 군집화: 각 데이터포인트를 개별 군집으로 시작하여, 가장 가까운 군집을 반복적으로 병합
  • 분할 군집화: 모든 데이터포인트를 하나의 군집으로 시작하여, 반복적으로 가장 멀리 떨어진 군집을 분할

📚 데이터 로드 및 전처리

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

from sklearn.preprocessing import StandardScaler

#병합 계층적 군집화를 구현하는 클래스

from sklearn.cluster import AgglomerativeClustering

#계층적군집화를 수행하고  그 결과를 덴드로그램으로 시각화 기능 제공

import scipy.cluster.hierarchy as sch

 

df = pd.read_csv('Mall_Customers.csv')

 

X = df[['Age', 'Annual Income (k$)', 'Spending Score (1-100)"]]

 

scaled = StandardScaler()

X_scaled = scaler.fit_transfrom(X)

 

📚덴드로그램 생성

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

dendrogram = sch.dendrogram(sch.linkage(X_scaled, method='ward'))

plt.title('Dendrogram')

plt.xlabel('Customers')

plt.ylabel('Euclidean distances')

plt.show()

 

📚계층적 군집화 모델 구현

# AgglomerativeClistering클래스의 인스턴스 생성

# n_clusters=5 데이터를 5개의 군집으로 나누겟다는 뜻

# metric='euclidean' 유클리드 거리를 사용하여 데이터 간의 거리를 계산

# linkage='ward' 워드 연결 방법을 사용한다.(군집 간의 분산을 최소화하는 방식으로 군집을 결합)

hc = AgglomerativeClistering(n_clusters=5, metric='euclidean', linkage='ward')

 

#X_scaled 데이터에 맞추어 학습하고, 각 데이터포인트에 대한 군집 번호를 예측

# fit_predict는 데이터를 학습

# X_scaled는 스케일링(표준화)된 데이터로, 계층적 군집화 모델의 입력 데이터

# y_hc에는 각 데이터가 할당된 군집 번호(라벨)이 저장

y_hc = hc.fit_predict(X_scaled)

 

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

# 군집 1에 속하는 데이터 포인트들을 빨간색으로 산점도 그래프로 시각화

# X_scaled[y_hc == 0, 0]: y_hc == 0은 군집 1(라벨 0)에 속하는 데이터 포인트를 선택하는 조건입니다. X_scaled의 첫 번째 축(열 0, 즉 Age)을 선택하여 x축에 표시

# X_scaled[y_hc == 0, 1]: X_scaled의 두 번째 축(열 1, 즉 Annual Income)을 선택하여 y축에 표시

# s=100: 각 데이터 포인트의 크기를 100으로 설정합니다.

# c ='red': 빨간색으로 데이터를 표시합니다.

# label='Cluster 1': 군집 1의 라벨을 'Cluster 1'로 지정하여 범례에 표시할 때 사용됩니다.

plt.scatter(X_scaled[y_hc == 0, 0], X_scaled[y_hc == 0, 1], s=100, c='red', label='Cluster 1')

plt.scatter(X_scaled[y_hc == 1, 0], X_scaled[y_hc == 1, 1], s=100, c='blue', label='Cluster 2')

plt.scatter(X_scaled[y_hc == 2, 0], X_scaled[y_hc == 2, 1], s=100, c='green', label='Cluster 3')

plt.scatter(X_scaled[y_hc == 3, 0], X_scaled[y_hc == 3, 1], s=100, c='cyan', label='Cluster 4')

plt.scatter(X_scaled[y_hc == 4, 0], X_scaled[y_hc == 4, 1], s=100, c='magenta', label='Cluster 5')

plt.title('Clusters of customers')

plt.xlabel('Age')

plt.ylabel('Annual Income (k$)')

# 각 군집의 레이블을 그래프의 범례로 표시( 'Cluster 1', 'Cluster 2', 'Cluster 3', 'Cluster 4', 'Cluster 5'가 각각 해당 군집의 색상과 함께 표시)

plt.legend()

plt.show()

 

📚모델 평가

# silhouette_score는 군집화 모델의 성능을 평가하기 위해 사용

# 실루엣 점수는 -1에서 1 사이의 값을 가지며, 1에 가까울수록 군집화가 잘 된 것

from sklearn.metrics import silhouette_score

 

# 실루엣 점수 계산

# X_scaled 표준화된 입력 데이터

# y_hc: 군집화 결과로 각 데이터 포인트에 할당된 군집 레이블

silhouette_avg = silhouette_score(X_scaled, y_hc)

# 계산된 실루엣 점수를 출력

# f-string을 사용하여 Silhouette Score: {silhouette_avg} 형식으로 실루엣 점수를 화면에 출력

print(f'Silhouette Score: {silhouette_avg}')

 

 

+ Recent posts