이제 모든것을 처음부터 끝까지 한번 달려보자. 그런데, 먼저 통계부터 공부해야 할 것 같다.
머신 러닝
머신 러닝이란 뭘까?
머신 러닝이란, 데이터를 이용해 기계가 스스로 학습하여 특정 작업을 수행하는 기술입니다. 사람이 직접 모든 규칙을 코딩하지 않고, 데이터를 바탕으로 패턴을 찾아내고 이를 통해 결론을 도출하거나 예측을 하는 방법입니다.
머신 러닝은 데이터에서 학습하여 예측이나 결정을 내리는 시스템을 개발하는 분야입니다. 머신 러닝 모델은 주어진 데이터를 바탕으로 패턴을 찾고, 이를 통해 미래의 데이터에 대한 예측을 수행합니다. 그렇기에 3개의 종류로 나뉘어 집니다. 1.지도 학습 (Supervised Learning):입력 데이터와 그에 대한 정답(레이블)이 주어지면, 모델이 이 데이터를 통해 패턴을 학습하는 방식입니다.
2.비지도 학습 (Unsupervised Learning):레이블이 없는 데이터에서 패턴이나 구조를 찾아내는 방법입니다. 예를 들어, 고객 데이터를 클러스터링하여 비슷한 그룹으로 나누는 것이 있습니다.
3.강화 학습 (Reinforcement Learning):에이전트가 환경과 상호작용하며 보상을 최대화하는 방향으로 학습하는 방법입니다. 예를 들어, 게임을 하면서 최적의 전략을 찾아가는 방식입니다.
즉, 새로운 데이터에 대해 예측하거나 분류하는 작업을 할 수 있게 만들어주는 것입니다.
그럼 알고리즘은? 알고리즘은 머신 러닝과 비슷하지만 다른 점이 있습니다. 특정 문제를 해결하기 위한 단계별 절차나 방법을 의미합니다. 알고리즘은 데이터 처리, 정렬, 검색, 계산 등의 다양한 작업을 수행할 수 있습니다. 즉, 알고리즘은 문제를 해결하기 위한 절차 혹은 방법이며, 머신 러닝이란 데이터에서 학습하는 기술입니다. 그래서 머신 러닝 알고리즘이란 개념이 있는데, 머신 러닝 알고리즘은 머신 러닝의 특정 종류이자 방법으로 볼 수 있습니다.
아, 그 전에 머신 러닝에서 쓰이는 단어들은 학습하고 넘어가야 할 것 같습니다.
1. 데이터 관련 용어 데이터셋(Dataset): 머신 러닝 모델을 학습시키기 위해 사용하는 데이터의 모음입니다. 테스트 데이터(Test Data): 최종 모델 성능을 평가하는 데 사용되는 데이터로, 훈련 과정에서 사용되지 않습니다. 훈련 데이터(Training Data): 모델을 학습하는 데 사용되는 데이터입니다. 검증 데이터(Validation Data): 모델을 튜닝하거나 성능을 평가하는 데 사용되는 데이터입니다. 특징(Feature): 데이터의 속성이나 변수로, 모델 학습에 사용됩니다. 레이블(Label): 특정 데이터 포인트의 정답입니다. 지도 학습에서는 주어진 데이터에 대한 정답으로 사용됩니다. 결측값(Missing Values): 데이터셋에서 누락된 값으로, 모델 학습 시 처리해야 합니다. 전처리(Preprocessing): 원시 데이터를 모델이 이해할 수 있는 형태로 변환하는 과정입니다. 데이터 정리, 결측값 처리, 스케일링 등이 포함됩니다. 정규화(Normalization): 데이터의 범위를 0과 1 사이로 조정하는 과정으로, 모델의 성능을 개선할 수 있습니다. 표준화(Standardization): 데이터의 평균을 0, 표준편차를 1로 변환하여 데이터의 분포를 조정합니다.
2. 모델과 알고리즘 모델(Model): 데이터를 학습하여 예측을 수행할 수 있는 수학적 구조입니다. 알고리즘(Algorithm): 모델을 학습시키기 위한 방법론으로, 다양한 머신 러닝 알고리즘이 있습니다(예: 선형 회귀, 의사결정나무, 신경망 등). 하이퍼파라미터(Hyperparameter): 모델 학습 전 설정해야 하는 파라미터로, 모델 성능에 큰 영향을 미칩니다. 선형 회귀(Linear Regression): 입력 변수와 출력 변수 간의 선형 관계를 모델링하는 방법입니다. 로지스틱 회귀(Logistic Regression): 이진 분류 문제를 해결하기 위한 회귀 모델로, 확률을 출력합니다. 의사결정 나무(Decision Tree): 데이터의 특정 특성을 기준으로 분할하여 예측을 수행하는 트리 기반 모델입니다. 랜덤 포레스트(Random Forest): 여러 개의 의사결정 나무를 결합하여 예측을 수행하는 앙상블 방법입니다. 서포트 벡터 머신(Support Vector Machine, SVM): 데이터를 분리하기 위한 최적의 초평면을 찾는 지도 학습 알고리즘입니다. 부스팅(Boosting): 여러 약한 학습기를 결합하여 강력한 모델을 만드는 방법으로, 이전 모델의 오차를 다음 모델이 보완하도록 학습합니다. 배깅(Bagging): 여러 개의 샘플을 랜덤하게 선택해 학습하여 모델의 분산을 줄이는 방법입니다. 신경망(Neural Network): 인공 뉴런을 사용하여 데이터의 패턴을 학습하는 모델로, 복잡한 비선형 관계를 모델링할 수 있습니다. 딥러닝(Deep Learning): 여러 개의 층으로 구성된 신경망을 사용하는 기법으로, 이미지 인식, 자연어 처리 등에 효과적입니다. 3. 성능 평가 정확도(Accuracy): 모델이 올바르게 예측한 비율로, 일반적으로 평가 지표로 사용됩니다. 정밀도(Precision): 모델이 긍정으로 예측한 것 중 실제 긍정인 비율입니다. 재현율(Recall): 실제 긍정 중 모델이 긍정으로 예측한 비율입니다. F1 스코어(F1 Score): 정밀도와 재현율의 조화 평균으로, 두 지표의 균형을 제공합니다. ROC 곡선(ROC Curve): True Positive Rate와 False Positive Rate를 시각적으로 나타낸 곡선으로, AUC(Area Under Curve)를 통해 모델 성능을 평가합니다. 손실 함수(Loss Function): 모델의 예측과 실제 값 간의 차이를 계산하는 함수입니다. 모델 학습 시 최적화하는 대상입니다. 가장 적합한 모델 선택(Best Model Selection): 다양한 모델을 비교하고, 검증 데이터셋의 성능을 바탕으로 최적의 모델을 선택하는 과정입니다. 4. 특성 공학 특성 공학(Feature Engineering): 모델 학습에 사용할 최적의 특징을 선택하거나 생성하는 과정입니다. 차원 축소(Dimensionality Reduction): 고차원 데이터를 낮은 차원으로 변환하여 처리의 용이성을 높이는 기법입니다. 5. 기타 용어 오버피팅(Overfitting): 모델이 훈련 데이터에 지나치게 맞춰져 새로운 데이터에 대해 성능이 떨어지는 현상입니다. 언더피팅(Underfitting): 모델이 훈련 데이터의 패턴을 제대로 학습하지 못하는 현상입니다. 교차 검증(Cross-Validation): 데이터를 여러 번 나누어 모델 성능을 평가하는 기법으로, 과적합을 방지하는 데 유용합니다. 앙상블(Ensemble): 여러 개의 모델을 결합하여 성능을 향상시키는 방법입니다. (예: 배깅, 부스팅)
지도학습 : 회귀모델
선형 회귀란, 연속적인 숫자형 값을 예측하는 지도학습 기법입니다. 즉, 지도학습(정답(레이블)이 주어지면, 모델이 이 데이터를 통해 패턴을 학습하는 방식입니다.)에서, 선형 회귀는 주어진 데이터에서 특정 패턴을 학습해서, 새로운 데이터에 대한 숫자 결과를 예측하는 것을 말합니다.
각각 1. 선형 회귀(Linear Regression) -> 가장 기본적인 회귀모델로, 데이터 사이의 관계가 직선으로 나타날 때 사용합니다. 2. 다항 회귀(Polynomial Regression) -> : 데이터가 직선이 아니라 곡선일 때 사용하는 모델입니다(제곱) 3. 리지 회귀(Ridge Regression), 라쏘 회귀(Lasso Regression -> 복잡한 데이터에서 과적합을 막기 위한 방법이 추가된 모델들입니다.
먼저 선형 회귀에서 쓰일 통계 개념들을 설명하겠습니다. 1. 독립 변수(Independent Variable)와 종속 변수(Dependent Variable): 독립 변수는 입력 데이터로, 선형 회귀에서는 설명 변수라고도 불러. 예를 들어, 집의 크기나 방의 개수가 독립 변수입니다. 종속 변수는 우리가 예측하고자 하는 값으로, 반응 변수라고도 하며, 예를 들어, 집의 가격이 종속 변수가 됩니다.
2. 상관관계(Correlation): 독립 변수와 종속 변수 사이의 연관성을 나타내는 척도입니다. 상관계수는 -1에서 1까지의 값을 가지며, 1에 가까울수록 강한 양의 상관관계를, -1에 가까울수록 강한 음의 상관관계를 의미하며, 상관관계가 0에 가까울수록 두 변수 간에는 아무런 관계가 없고, 상관계수가 높으면 선형 회귀 모델이 잘 맞을 가능성이 큽니다.
3. 잔차(Residuals): 예측된 값과 실제 값의 차이를 잔차라고 합니다. 잔차는 회귀 모델의 오차를 의미하는데, 잔차가 작을수록 모델이 더 정확하다는 뜻이며, 잔차를 분석하면 모델의 성능을 더 잘 평가할 수 있습니다.
4. R제곱값 (R², 결정계수): R²는 모델이 데이터를 얼마나 잘 설명하는지 나타내는 값입니다. 0에서 1 사이의 값을 가지며, 1에 가까울수록 모델이 데이터를 잘 설명한다는 뜻입니다.
5. p-값(p-value): 회귀 분석에서 독립 변수들이 종속 변수에 유의미한 영향을 미치는지를 확인하는 통계적인 값입니다. p-값이 작을수록 (일반적으로 0.05 미만) 해당 독립 변수가 유의미하다고 판단하며, 즉, p-값이 작으면 해당 변수가 예측에 중요한 역할을 한다고 볼 수 있습니다.
6. 표준 오차(Standard Error): 모델에서 예측한 값들이 실제 값과 얼마나 차이가 나는지를 나타내는 값입니다. 표준 오차가 작을수록 모델이 더 정확하다는 뜻이며, 회귀 계수의 표준 오차는 해당 계수의 신뢰성을 평가하는 데 사용됩니다. 표준 오차가 클수록 해당 계수가 신뢰하기 어렵다는 뜻입니다.
7. F-통계량(F-statistic): 회귀 모델의 전체적인 유의미성을 평가하는 지표입니다. F-통계량이 크면 모델이 유의미하다고 판단할 수 있으며. 회귀 모델이 데이터를 설명하는 데 얼마나 효과적인지를 판단하는 데 중요한 역할을 합니다.
8. 다중 공선성(Multicollinearity): 여러 독립 변수들이 서로 상관관계를 가질 때 발생하는 문제입니다. 다중 공선성이 높으면 회귀 계수의 해석이 어려워지고, 모델의 신뢰성이 떨어지며, 이를 해결하기 위해선 변수를 줄이거나 리지 회귀 같은 기법을 사용할 수 있습니다.
9. 자기상관(Autocorrelation): 연속된 데이터에서 오차 항(모델이 설명하지 못한 차이 또는 모델의 예측이 빗나간 정도)들이 상관관계(한 변수가 변할 때 다른 변수가 어떻게 변하는지를 의미)를 가질 때 발생하는 문제입니다. 회귀 모델은 독립적인 오차를 가정하는데, 자기상관이 존재하면 이 가정이 깨지고 모델이 부정확해집니다. 이를 해결하려면 시계열 분석 방법을 사용해야 해야합니다.
10. 회귀 계수(Regression Coefficients): 선형 회귀에서 독립 변수가 종속 변수에 미치는 영향을 숫자로 나타내는 값입니다. 계수의 크기와 방향을 보면 해당 독립 변수가 종속 변수에 얼마나, 그리고 어떤 방향으로 영향을 미치는지 알 수 있습니다. 예를 들어, 회귀 계수가 양수면 독립 변수가 증가할수록 종속 변수도 증가하고, 음수면 반대로 감소합니다.
그러면 이제 한번 보겠습니다.
선형 회귀에는 두가지의 모델이 있습니다. 단순 선형 회귀와 다중 선형 회귀 입니다.
간단히 말하면,
1. 단순 선형 회귀 : 독립 변수가 하나 y : 종속 변수(결과값) x : 독립 변수 β0 : 절편(intercept) β1 : 기울기(slope), 독립 변수 xxx가 yyy에 미치는 영향 ϵ : 오차항(에러)
2. 다중 선형 회귀 : 독립 변수가 여러개
라 할 수 있습니다. 여기서 y : 종속 변수(결과값) x1,x2,…,xn : 여러 개의 독립 변수 β0 : 절편(intercept) β1 : 기울기(slope), 독립 변수 xxx가 yyy에 미치는 영향 ϵ : 오차항(에러)
단순 선형 예를 가져와 봤습니다.
from sklearn.linear_model import LinearRegression
# 독립 변수와 종속 변수 정의
X = [[5], [10], [15]] # 공부 시간 (독립 변수)
y = [50, 70, 80] # 성적 (종속 변수)
# 모델 생성 및 학습
model = LinearRegression()
model.fit(X, y)
# 예측
predicted = model.predict([[12]]) # 공부 시간 12시간일 때 성적 예측
print(predicted)
이 코드는 정말 간단하게 단순 선형 회귀를 나타내는 코드입니다. 먼저 x에 5, 10, 15로 증가하게 된다면, y는 50, 70, 80의 성적이 나옵니다. 지금 보면 약간 안 맞을 수 있지만, 코드를 통해 학습을 시키고, 저희가 원하는 독립 변수를 넣으면 알아서 계산을 해주것이 머닝 러신입니다.
from sklearn.linear_model import LinearRegression은 이제 휘귀모델(LinearRegression())을 쓸 수 있게 해주는 코드 입니다. 그렇게 가져와서 model에 할당하여, model.fit(X, y)를 적으면, .fit()은 ()안에 있는 X,y를 아까의 수식에 맞게 넣으며, fit을 통해 학습을 하게 됩니다.
그렇게 model.predict([[12]])([]가 2개인 이유는 X는 2차원으로 배정되어 있기 때문)를 쓰면, predict가 ()안에 있는 값을 직접 넣어, 계산된 값을 보여주게 됩니다. 답: [72.66666667]
다중 선형 회귀의 예시 입니다.
from sklearn.linear_model import LinearRegression
# 독립 변수와 종속 변수 정의
X = [[5, 8, 80], [10, 6, 70], [15, 7, 90]] # 공부 시간, 수면 시간, 출석률
y = [50, 70, 80] # 성적
# 모델 생성 및 학습
model = LinearRegression()
model.fit(X, y)
# 예측
predicted = model.predict([[12, 7, 85]]) # 공부 시간 12시간, 수면 7시간, 출석률 85%일 때 성적 예측
print(predicted)
자, 여기서는 조금 이해를 하셔야 합니다. 밑의 방식인 fit(X,y)와 predict은 똑같습니다. 하지만 주는 값이 조금 다릅니다. 이것은 단순히, 만약에 공부 시간이 5, 수면 시간이 8, 출석률이 80일때, 성적이 50, 즉 저 세가지가 저 숫자 50 하나에 영향을 미친다고 생각하면 편합니다.
즉, X가 3개 들어가, 복합적으로 계산된 값이 50이라는 것입니다. 그렇기에 predict로 주는 값도 3개 이어야 합니다. 저 3가지의 값을 계산이 되어, 공부 시간, 수면 시간, 출석률이 달라짐에 따라 값도 바뀌게 되는 것입니다.
여기서 힌트를 드리자면, 저 다른 공부 시간, 수면 시간, 출석률의 규칙은 전혀 모르겠지만, 각각 숫자가 올라가고 있고, 그에 따라 성적도 똑같이 올라가고 있다는 뜻입니다. 즉, 어떤면에선 규칙이 있을 수 있다는 것입니다.
그렇게 만약 공부 시간이 12, 수면 7, 출석률이 85일때의 값은 위에 규칙대로 계산된 규칙에 따라 계산이 되며, 값이 출력되게 됩니다. 답: [71.73333333]
그런데 궁금하신 분들이 있을 수 있습니다. 여기서는 왜 X_train, X_test, y_train, y_ test 같은 것이 없는건지 말입니다. 알아두셔야 하는것이, 이것은 모델의 정확도를 파악하기 위해서 쓰이는 것입니다. 저희는 값만 알아내려고 했기 때문에, 쓰지 않았습니다. 강의에서 나온대로 쓸려면, from sklearn.model_selection import train_test_split -> 이 코드는 데이터를 훈련 데이터와 테스트 데이터로 나누는 역할을 합니다. 1. X: 독립 변수(입력 데이터)입니다. 예측에 사용되는 변수들입니다.
2. y: 종속 변수(타겟 데이터)입니다. 예측하려는 값입니다. 3. test_size: 데이터 중 얼마나 많은 부분을 테스트 데이터로 분할할지를 결정합니다. 0.2라면 20%를 테스트 데이터로, 80%를 훈련 데이터로 사용합니다. 4. random_state: 랜덤 시드입니다. 데이터를 무작위로 나눌 때 사용되며, 같은 random_state 값을 주면 항상 동일한 분할을 얻을 수 있습니다. 재현성을 위해 설정하는 것이 좋습니다.
from sklearn.metrics import mean_squared_error, r2_score -> 이 코드는 모델의예측 성능을 평가하는 데 사용됩니다. 주로회귀 모델의 성능을 측정하는 데 쓰입니다.
자, 여기서 MSE(mean squared error)와 R2에 대해 알아보겠습니다. 먼저 MSE는 모델의 예측값과 실제 값 사이의 차이를 제곱해 평균한 값입니다. 오차가 클수록 MSE 값이 커지므로,MSE가 낮을수록모델의 예측 성능이 좋다고 할 수 있습니다. 왜 MSE를 사용하는가? 오차 값을 제곱해서 양수로 만들고, 큰 오차에 더 큰 페널티를 줍니다. 모델 성능을 수치적으로 나타내기 쉽고, 낮을수록 좋은 성능을 의미합니다.
강의에 나온 예시를 들어보겠습니다. # 예측 y_pred = model.predict(X_test) # 모델 평가 mse = mean_squared_error(y_test, y_pred) 바로 이 부분입니다. 자, 이 부분은 train_test_split에 조금 더 들어가서 확인해야 합니다. 첫번째 질문. 왜 X_test가 y_pred에 쓰이는가? 자, train_test_split에서 20%는 테스트에 사용한다고 나와있습니다. 그런데 사실 이 20%의 X_test와 y_test는 실제로, 학습에 사용되지 않고, 숨겨진 상태가 됩니다.즉, 이 모델은 이 X_test와 y_test의 존재 여부를 모릅니다. 그 이유로는 y_pred에는 실제로 쓰이지 않았던, 즉 모델이 쓰지 않았던 값으로 넣어야 y_pred이 될 수 있는겁니다.
그렇다고 아무 숫자를 넣기에는 학습에 20%만큼 빠졌기에, 그만큼 공백이 생길 수 있어, 지금 숨겨진 상태의 X_test를 넣어주는 겁니다. 즉, 그 값은 모델이 훈련 중에 배운 패턴과 상관없이 들어가는 값이 됩니다. 그렇게 되면, 평가의 일관성이 깨지게 되거나, 그 값에 맞는 테스트 결과가 없기 때문에 제대로 평가할 수 없습니다. 예를들어 x가 [2,2]일때, y가 2인것을 테스트로 사용한다고 가정하겠습니다. 그러면 이 두개는 숨겨진 상태가 되면, 모델은 이 두 존재를 모르게 됩니다. 그런 상태에서 나머지를 학습을 하게 되고, predict에 X_test를 넣으면 학습된 규칙을 바탕으로 y를 배출하게 되는데, 이것이 바로 예상된 y의 값 즉, y_pred이 되는 겁니다.
그러면 이제 mean_squared_error를 통해 실제 y_test 값인 2와 계산되어서 나온 y_pred값과 비교하게 되어서, MSE의 수식을 사용해 서로의 차이값이 나오게 되는겁니다. mean_squared_error(테스트 값(y_test), 예상한 값(y_pred))
R²도 비슷한 개념입니다. R² Score (결정 계수)는 모델이 데이터를 얼마나 잘 설명하는지를 나타내는 지표로, 0에서 1 사이의 값을 가집니다. 1에 가까울수록 모델이 데이터를 잘 설명하는 것이고, 0에 가까울수록 설명력이 낮습니다. 왜 R²를 사용하는가? R²는 모델의 설명력을 나타냅니다. R²가 1에 가까우면 모델이 데이터를 매우 잘 설명하고 있다는 의미입니다. R²는 전체 변동 중에서 모델이 설명한 변동의 비율을 나타냅니다. 값이 클수록 모델이 데이터를 더 잘 설명합니다.
R2도 MSE와 비슷한 개념이지만 설명력을 나타내기에 다릅니다. 그렇기에 R2도 수식을 사용해 받은 y_test와 y_pred을 사용해 서로를 비교하여 얼마나 잘 설명되었는지 숫자로 보여주게 됩니다. 즉, 훈련 데이터로 모델을 학습시키고, 훈련 중에 전혀 사용되지 않은 테스트 데이터로 모델이 새로운 데이터를 얼마나 잘 예측하는지 평가하는 것이 핵심입니다.
그렇게 나머지(다항 회귀, 리지 회귀, 라쏘 회귀)도 비슷하게 작동하는 원리입니다
분류모델-로지스틱 회귀
이번에는 회귀모델이 아닌 분류모델입니다. 회귀 모델이 특정한 규칙을 찾아 y를 배출한다면, 분류모델은 종족 변수가 이진형일때(결과가 두 가지 중 하나일 때) 사용되는 통계 기법입니다. 즉, 결과값이 0과 1에 위치하도록 하는 것이기 때문에, 시그모이드 함수를 사용합니다.
로지스틱 회귀는 입력된 데이터를 학습하여 각 데이터 포인트가 특정 클래스에 속할 확률을 예측합니다.
먼저, 로지스틱 회귀에서 알아야할 통계 개념들을 알아보겠습니다.
1. 확률 (Probability): 특정 사건이 발생할 가능성을 수치적으로 나타내는 개념입니다. 로지스틱 회귀에서는 사건이 발생할 확률을 예측합니다. 로지스틱 회귀에서는 특정 클래스에 속할 확률을 모델링하며, 이 확률은 0과 1 사이의 값을 가집니다.
2. 로짓 함수 (Logit Function): 로지스틱 회귀에서 사용하는 함수로, 확률을 로그 오즈로 변환합니다. 그리고 그 확률을 선형 회귀의 형식으로 변환하여 회귀 분석을 가능하게 합니다.
여기서 p는 사건이 발생할 확률입니다.
3. 로지스틱 함수 (Logistic Function): S자 형태의 곡선으로, 입력값에 대한 출력값을 0과 1 사이의 확률로 변환하는 함수입니다.
여기서 z는 독립 변수와 회귀 계수의 선형 결합입니다.
4. 우도 함수 (Likelihood Function): 주어진 데이터에서 모델의 파라미터가 얼마나 잘 맞는지를 나타내는 함수입니다. 로지스틱 회귀에서는 우도 함수를 최대화하여 최적의 파라미터를 찾습니다.
5. 교차 엔트로피 손실 (Cross-Entropy Loss): 로지스틱 회귀에서 모델의 예측과 실제 레이블 간의 차이를 측정하는 손실 함수입니다. 이 손실 함수를 최소화하여 모델의 성능을 향상시킵니다. 6. 정확도 (Accuracy): 모델이 올바르게 예측한 샘플의 비율입니다. 모델의 성능을 평가하는 데 사용됩니다. 7. 민감도와 특이도 (Sensitivity and Specificity): 민감도 (True Positive Rate): 실제 양성 중에서 올바르게 예측한 비율입니다. 특이도 (True Negative Rate): 실제 음성 중에서 올바르게 예측한 비율입니다. 8. AUC-ROC 곡선 (Area Under the Curve - Receiver Operating Characteristic): 류 모델의 성능을 평가하는 지표로, TPR(민감도)와 FPR(거짓 긍정 비율)의 관계를 나타냅니다. AUC 값이 1에 가까울수록 모델의 분류 성능이 우수하다고 평가됩니다.
9. 다중 공선성 (Multicollinearity): 독립 변수 간에 높은 상관관계가 존재하는 경우를 의미합니다. 이는 회귀 계수의 추정치를 불안정하게 만들 수 있습니다. 다중 공선성을 진단하고 조정하는 방법으로는 VIF(Variance Inflation Factor)를 사용할 수 있습니다.
10. 가정 (Assumptions): 로지스틱 회귀는 몇 가지 가정을 필요로 합니다: 1. 독립 변수와 종속 변수는 선형 관계를 가져야 합니다 (로짓 변환 후). 2. 독립 변수는 서로 독립적이어야 합니다. 3. 종속 변수는 이진 형태여야 합니다.
일단 강의에서 나온 예시를 통해 설명하겠습니다.
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)
자, 여기서 load_breast_cancer()에서 data는 세포의 크기, 모양, 텍스처 등이 있습니다. 그리고 target에는 그 세포의 크기, 모양, 텍스쳐에 따른 유방암인지 아닌지에 대한 정보가 있습니다. 즉, data에 따라 유방암인지 아닌지를 구별해주는 것입니다. 그런데 궁금증이 생길 수 있습니다. 왜 이미 유방암인지 아닌지에 대한 답이 있는데 여기서 무엇을 학습을 한다는 것일까? 만약 data에 따라 판단한다면, 이것은 선형 회귀랑 똑같이 규칙을 찾아서 값을 찾는것이 아닐까라는 질문입니다.
자, 여기서 혼동되시면 안됩니다. 둘 다 입력 데이터(X)와 이에 해당하는 정답 데이터(y)가 필요합니다. 여기서 두 모델 모두 입력 데이터와 출력 데이터 간의 관계를 규명하여, 주어진 입력에 대해 적절한 출력을 생성하는 규칙을 학습하는데, 이 개념 자체가(관계를 규명하여, 출력을 한다) 지도 학습입니다. 즉, 둘이 똑같이 지도 학습의 개념을 가지고 있지만, 출력 방식에 따라 서로 다르게 분류가 되는 것입니다.
선형 회귀는 규칙을 이해하고 사용자가 원하는 값을 입력했을때, 규칙에 따라 값을 게산해주는 반면, 로지스틱 회귀는 똑같이 규칙에 따라 계산하지만, 그 결과 자체가 두 가지중 하나일 때는 표현합니다. 이것 자체가 규칙 학습, 즉 지도 학습입니다.
윗 부분은 이미 설명했으니 스킵하겠습니다. 그러면 이제 StandScaler()가 나타납니다. StandScaler()는 얼핏보면 모델중 하나 같지만, 사실 이것은 전처리 단계이며, X에서의 특징들인 세포의 크기, 모양, 텍스쳐들중, 서로의 차이가 너무 심하기 때문에, 전처리를 하는 것입니다. 즉 값을 조정한다(0와 1사이)라고 생각하시면 편합니다.
여기서 .fit_transform이란것도 나옵니다 fit()은 아는데, fit_transform은 뭘까요? 그 전에 표준화와 정규화의 개념에 대해 알아야 합니다. 표준화: 데이터를 평균이 0이고 표준편차가 1이 되도록 변환하는 과정입니다. 일반적으로 각 값에서 평균을 빼고 표준편차로 나누어 수행합니다. 모든 데이터 값들이 일정한 범위 내에서 비교될 수 있도록 만들어서, 값의 범위가 크게 차이가 날 때 효과적이며. 특히, 특성 간의 스케일이 다를 때 정규화를 통해 같은 범위 내로 맞춰주는 게 좋습니다. 주로 K-최근접 이웃(KNN), 신경망(Neural Networks), K-means 클러스터링처럼 거리 기반 알고리즘에서 주로 사용됩니다.
정규화: 데이터를 0과 1 사이의 범위로 변환하는 과정입니다. 일반적으로 데이터의 최소값과 최대값을 이용하여 수행합니다. 데이터가 정규분포를 따를 때 주로 사용되며, 표준화를 통해 데이터의 분포가 평균에서 얼마나 떨어져 있는지 상대적인 값을 구할 수 있습니다. 주로 SVM(Support Vector Machine), 선형 회귀(Linear Regression), 로지스틱 회귀(Logistic Regression) 같은 모델에서는 거리 기반 계산을 할 때 표준화를 많이 사용합니다.
자 여기서 잠깐! 표준편차가 뭔지 짧게 설명드리겠습니다. 표준편차(Standard Deviation)는 데이터의 분산 정도를 나타내는 통계 지표로, 데이터가 평균에서 얼마나 떨어져 있는지를 측정합니다. 쉽게 말해, 데이터가 평균값을 중심으로 얼마나 퍼져 있는지를 보여주는 수치입니다.
1. 표준편차의 개념 평균(Mean): 주어진 데이터의 합을 데이터의 개수로 나눈 값입니다.
분산(Variance): 데이터 각 값과 평균 간의 차이를 제곱하여 평균한 값입니다. 데이터가 평균으로부터 얼마나 퍼져 있는지를 나타내는 지표이며, 표준편차는 분산의 제곱근으로 계산합니다.
표준편차는 데이터의 단위와 동일하게 만들어주기 때문에 해석하기 쉬워.
2. 표준편차 계산 방법 평균 계산: 데이터의 평균을 구합니다.
차이 제곱: 각 데이터 값에서 평균을 뺀 값을 제곱합니다.
분산 계산: 제곱한 값들의 평균을 구합니다.
표준편차 계산: 분산의 제곱근을 구합니다.
예를 들어, 데이터가 [4, 8, 6, 5, 3]라고 할 때, 표준편차를 계산하는 과정은 다음과 같습니다: 1. 평균 계산 2. 차이 제곱 3. 분산 계산 4. 표준편차 계산
이제 다시 fit과 transform에 대해 설명하겠습니다. 자, 참고로 fit()은 모델에 따라 학습 혹은 계산에 쓰입니다.(중요!)
자, StandardScaler()의 fit()은 학습이 아니라, transform()에서 ()안에 받은 값의 평균과 표준 편차를 계산하는데 쓰입니다. 즉, 모델을 학습하는 것이 아니라, 나중에 사용할 통계적 값을 준비하는 단계입니다. 그리고 산된 값은 StandardScaler 객체 내부에 저장됩니다. 따라서, fit() 자체가 StandardScaler 내부의 계산 로직을 실행하는 것이며, 그 결과를 StandardScaler 객체에 저장하게 됩니다. 그리고 다시 계산된 값은 transform()이 받은 값의 평균을 0, 표준 편차를 1로 반환해줍니다(표준화). 그리고 그 값을 반환합니다. 그렇기에 StandardScaler()는 표준화를 진행해주는 것이라 생각하면 편합니다. 따라서 StandardScaler는 그 자체로는 "표준화"를 수행하는 클래스이지만, 실제로 표준화 작업은 transform() 메서드에서 수행됩니다.
그러면 궁금증이 생길 수 있습니다. 그러면 StandardScaler()말고 transform혼자 쓸 수 있는거 아니야? 라고 하실 수 있습니다. 하지만 결국에는 StandardScaler가 있어야 평균과 표준 편차를 구할 수 있고, 그 값들이 있어야 transform이 표준화 작업을 실행할 수 있기 때문에, 둘 다 쓰여야 합니다.
참고로 StandardScaler를 쓰기위해 from sklearn.preprocessing import StandardScaler를 써야합니다.
그런데 약간 다른점이 있습니다. scaler = StandardScaler() X_train = scaler.fit_transform(X_train) X_test = scaler.transform(X_test) 여기서 밑에 X_test에는 fit이 사용되고 있지 않습니다. 아까 말했던 것 처럼, X_test는 숨겨진 상태이며, 이 경우 X_test는 모델이 처음 보는 데이터이므로 fit을 사용하면 평균과 표준 편차가 이전에 학습한 X_train의 통계적 정보와 다를 수 있습니다. 따라서, X_test에 대해 fit을 사용하지 않고 transform만 사용하는 것이 가장 일반적이고 바람직한 방법입니다.
그리고 이제 나머지는 같은 방식이지만, from sklearn.linear_model import LogisticRegression -> 로지스틱 회귀 모델을 구현한 LogisticRegression 클래스를 가져옵니다. from sklearn.metrics import accuracy_score, classification_report, confusion_matrix ->
accuracy_score -> 모델의 정확도를 계산하는 함수입니다. 주어진 예측 결과와 실제 레이블을 비교하여 모델의 성능을 평가합니다. 정확도는 전체 샘플 중 올바르게 분류된 샘플의 비율을 나타냅니다. classification_report -> 분류 모델의 성능에 대한 종합 보고서를 생성하는 함수입니다. 정밀도(precision), 재현율(recall), F1 점수(F1-score) 등 여러 성능 지표를 포함하여 모델의 성능을 자세히 설명합니다. 각 클래스에 대한 성능을 개별적으로 보여줍니다. confusion_matrix -> 혼동 행렬을 생성하는 함수입니다. 모델의 예측 결과를 실제 클래스와 비교하여 얼마나 많은 샘플이 올바르게 분류되었는지를 보여줍니다. 행렬은 각 클래스에 대해 True Positive, False Positive, True Negative, False Negative의 개수를 표시합니다.
즉, test에서 사용되지 않은 실제 y_test의 값과, 사용되지 않은 X_test 값을 규칙에 따라 새롭게 계산된 y레이블을 서로 대치하여 정확성을 알아봅니다.
SVM
여기 들어가기 전에 앞서, 설명할 것이 있습니다. 바로 분류모델에 관환것입니다. 분류 모델(Classification Model)은 데이터 샘플을 주어진 클래스 레이블로 분류하는 머신러닝 알고리즘의 집합입니다. 이 모델들은 주어진 입력 데이터를 기반으로 특정 클래스에 속하는지를 예측합니다.
즉, 로지스틱 회귀에서 배운것과 같이, 두개 중 하나를 답으로 주는것이 로지스틱 회귀의 개념이 아니라, 분류모델의 개념이란 것입니다. 즉, 로지스틱 회귀는 이 개념을 가지고 계산을 하는 것 뿐입니다.
이게 무슨 뜻이냐고 하면, 로지스틱 회귀, SVM, KNN, 나이브베이즈, 의사결정나무는 전부 똑같은 일을 할 뿐 개념과 코드의 차이만 있다는 뜻입니다. 즉, 어떤것을 쓸지에 대한 코드만 바뀔 뿐, 나머지 부분들은 거의 똑같습니다.
SVM 보시는 바와 같이, 서로간의 경계를 만드는데, 그 경계에 맞게 알맞는 데이터들을 집어 넣습니다. (예를 들어 빨간색에는 0에 포함하는 숫자들이, 파란색에는 1에 포함하는 숫자들이, 초록색에는 2에 해당하는 숫자들이). 하지만 이것은 로지스틱도 똑같습니다.
여기서 드는 궁금증이 그러면 왜 SVM이나 다른 모델들을 쓰냐라고 하실 수 있습니다. 그것은 사실 성능에 따라 달라지기 때문입니다. 로지스틱 회귀는 경계를 설정하여 각 데이터 포인트에 대해 해당 클래스의 확률을 제공하는 모델입니다. 경계는 선형적이며, 데이터를 확률적으로 분류하는데 반면, SVM은 데이터 포인트 간의 간격을 최대화하는 초평면을 찾아 경계를 설정합니다.이는 보다 강력한 분류 성능을 제공할 수 있으며, 다양한 데이터 구조를 처리할 수 있는 유연성을 가지고 있습니다. 즉, 데이터 처리와 분별에 있어, 더 명확하게 데이터를 알맞게 포함시킬 수 있으며, 서로간의 간격 덕분에 서로 섞이지 않게 할 수 있습니다. 그 밖에도 여러 이유가 있습니다.
1. 명확한 분리: 최대 마진을 설정함으로써, 두 클래스 간의 경계를 명확하게 정의하고, 각 클래스가 가능한 한 멀리 떨어지게 만듭니다. 이는 새로운 데이터 포인트가 어느 클래스에 속하는지를 판단하는 데 도움이 됩니다.
2. 불확실성 감소: 경계를 최대화함으로써, 두 클래스의 데이터 포인트가 겹치는 것을 최소화하고, 불확실성을 줄입니다. 이는 분류의 정확도를 높이는 데 기여합니다.
3. 일반화 능력 향상: 데이터의 분포가 다소 변하더라도, SVM은 경계를 최대화하여 학습하므로 새로운 데이터에 대한 일반화 능력이 높아집니다. 이는 과적합을 방지하는 데도 도움이 됩니다.
4. 데이터의 통합적 이해: 경계가 넓어짐으로써, 데이터의 각 클래스가 분리되어 있는지, 혹은 어떤 클래스의 데이터가 혼합되어 있는지를 더 명확하게 파악할 수 있습니다.
즉, 로지스틱에 쓰인 코드에서 LogisticRegression()이것을 SVC(kernel='linear')로만 바꾸면 됩니다.
참고로 SVM을 쓰기 위해서는 from sklearn.svm import SVC을 써야합니다.
KNN
KNN도 비슷한 모델입니다. 하지만 다른점이 있습니다.
코드를 예로 들어보겠습니다.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 모델 생성 및 학습
model = KNeighborsClassifier(n_neighbors=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가 되는겁니다. 그리고 코드에서 n_neighbors = 5라고 하는것은, 그 K 즉, 기준에서 5개의 근접한 데이터들을 가져오게 되는겁니다. 그리고 내가 선택한 기준이 주변에 있는 특성과 비슷하다면, 그 기준은 주변 특성에 맞게 배치가 되는것입니다. 예를 들어, 내가 유방암일 가능성이 큰 특성을 넣으면, 그 주변의 특성에 따라 내가 선택한 특성이 유방암인지 아닌지로 구분이 되게 된다는 것입니다. 즉, 내가 선택한 특성이 주변 특성을 참고하여 자기 자신을 분류한다고 생각하시면 편합니다.
여기서 알아햐 하시는 중요한 포인트가 있는데, 그래프 상에서 보면, 만약 사용자가 선택한 특성이 유방암일 가능성이 크다면, 그 데이터 포인트는 유방암일 가능성이 큰 구역에 위치하게 됩니다. 그리고 그 주변 데이터 포인트들(이웃)도 유사한 특성을 가지고 있기 때문에 비슷한 좌표에 위치할 가능성이 큽니다.
저 코드를 다시 한번 설명하자면, predict에 X_test를 넣었습니다. 즉 그 말은 X_test라는 K가 좌표에 알맞게 놓여졌고, 그 X_test 주변에 5개의 특성을 가져오는데, 그 특성들은 이미 유방암일 확률이 큰 데이터 또는 아닐 확률이 큰 데이터로 분류된, 학습된 데이터(X_train) 내에서 선택됩니다. 찾은 5개의 이웃 중에 어떤 클래스(유방암 는 정상)가 더 많은지 확인합니다. 만약 5개의 이웃 중 3개 이상이 유방암일 확률이 높은 데이터라면, KNN은 당 X_test 데이터도 유방암일 가능성이 크다고 판단하게 됩니다. 반대로 5개의 이웃 중 정상 데이터가 더 많다면, 그 X_test는 유방암이 아닐 가능성이 크다고 판단합니다.그 5개의 특성을 참고해서 자신이 유방암인지 아닌지 분류되게 되는 것입니다.
그렇기에 KNN은 SVM이랑 로지스틱 회귀와 다르게 선이 없습니다. 게다가 단점도 명확합니다.
KNN: 결정 경계(선)가 명확하게 설정되지 않고, 새로운 데이터 포인트가 주어지면, 주변의 K개의 데이터를 참고해서 다수결로 분류합니다.
SVM: 결정 경계(선)가 매우 명확하게 설정됩니다. SVM은 두 클래스 간의 가장 큰 간격을 만드는 결정 경계(선)를 찾고, 그 선을 기준으로 각 데이터를 분류합니다. 데이터가 결정 경계의 어느 쪽에 위치하느냐에 따라 분류되며, 고정된 선을 가지고 데이터를 나눕니다.
단점. 1. 경계선 근처에 있는 데이터 두 클래스(예: 유방암일 가능성이 큰 데이터와 아닐 가능성이 큰 데이터)의 경계선에 있는 데이터는 애매한 위치에 놓이게 됩니다. 이런 경우, 그 데이터의 이웃 5개가 유방암일 가능성이 큰 것들과 아닐 가능성이 큰 것들로 섞여 있을 수 있어서, 정확한 분류가 어렵습니다. 결국 근처 이웃에 따라 분류 결과가 달라질 수 있어, 분류의 안정성이 떨어질 가능성이 있습니다.
2. 데이터 밀도가 고르지 않을 때 어떤 구역은 데이터가 많이 모여 있는 반면, 다른 구역은 데이터가 드문드문 있는 경우도 있습니다. 데이터가 적은 구역에서는 이웃을 찾는 것이 어려워져서, 정확한 분류가 어려울 수 있습니다. 특히 드문 데이터가 경계선 근처에 있다면 분류 결과에 대한 신뢰도가 낮아질 수 있습니다.
3. 차원의 저주(Curse of Dimensionality) KNN은 **특성(feature)**이 많아질수록(고차원 데이터) 데이터 포인트들 간의 거리를 측정하는 것이 어려워집니다. 고차원에서는 모든 데이터가 멀리 떨어진 것처럼 보일 수 있어서, 가까운 이웃을 찾기가 어려워지고, 이로 인해 성능이 떨어질 수 있습니다.
4. 데이터가 균형 잡히지 않았을 때 만약 한 클래스의 데이터가 훨씬 많고, 다른 클래스는 매우 적을 때, KNN은 많은 쪽의 클래스로 치우쳐서 예측하게 될 가능성이 큽니다. 예를 들어, 유방암 데이터가 적고, 정상 데이터가 훨씬 많으면, 경계선 근처의 데이터는 정상 데이터 쪽으로 예측될 가능성이 높아지죠.
자, 여기서 헷갈릴 수 있으니 좀더 간략하고 정확하게 분류모델에 대해 설명하겠습니다. 분류 모델은 각 데이터 포인트의 특성(features)을 분석합니다. 예를 들어, 유방암 데이터셋에서는 암의 크기, 모양, 기타 특성들이 있을 수 있습니다. 모델은 이러한 특성들을 기반으로 하여 유방암인지 아닌지를 구분하는 결정 경계 즉, 기준을 만듭니다 (예를들어 1~3이 유방암, 5~10이 유방암이 아닐경우 결정 경계 4(즉, 4를 넘으면 유방암이 아니고, 4를 넘지 않으면 유방암). SVM의 경우, 서포트 벡터를 사용하여 최대 간격을 가진 결정 경계를 설정하고, KNN의 경우, K개의 이웃을 기반으로 주변의 클래스들을 확인하여 결정합니다.
참고로 KNN의 경우, from sklearn.neighbors import KNeighborsClassifier을 써야합니다.
나이브베이즈
나이브베이즈는 약간 다르게 접촉을 합니다. 하지만 두개의 값중 하나를 말하는 것은 똑같습니다.나이브베이즈는 주어진 데이터에서, 각 특성마다 특정 클래스에 속할 확률을 계산하고, 그 확률들을 바탕으로 최종 클래스를 결정합니다. 그리고 각 특성은 서로간의 영향을 주지 않습니다.
예를 들어 보겠습니다. 유방암 특성에서 특성1: 암세포의 크기 특성2: 암세포의 모양 특성3: 환자의 나이 이 특성들은 서로간의 계산에 절대 영향을 주지 않는다는 것이 특징입니다. KNN에서 특성들의 평균을 구할 때, 나이브베이즈는 서로 독립적으로 계산됩니다. 그렇게 될 경우, 암세포의 크기, 암세포의 모양, 환자의 나이의 확률이 계산이 되고, 최종적으로 이 데이터 특성의 확률이 계산이 됩니다(개별적인 확률이 있어야 전체 확률을 구할 수 있음!).
그리고 만약에 사용자가 다른 데이터를 넣었다면, 똑같이 그 특성 하나하나의 확률을 구한 후, 전체 확률를 구합니다. 즉, 해당 데이터가 특정 클래스(유방암 또는 비유방암)에 속할 확률을 계산하고 이미 존재하는 여러 데이터들의 전체 확률들을 비교하여 최종 분류를 수행합니다.
새로운 데이터 전체 확률 >,< 이미 존재하는 유방암,비유방암 데이터들의 전체 확률 이런식으로 분류를 진행합니다.
하지만 반대로 확률이 애매하면 단점이 될 수 있습니다. 그 밖에도,
독립성 가정: 나이브 베이즈는 각 특성이 서로 독립적이라고 가정합니다. 그러나 실제 데이터에서는 특성 간에 상관관계가 있을 수 있습니다. 예를 들어, 암세포의 크기와 모양은 서로 영향을 미칠 수 있는데, 이런 상관관계를 무시하면 잘못된 결과를 초래할 수 있습니다.
애매한 확률: 만약 특정 특성이 유방암과 비유방암의 분류를 명확하게 구분짓지 못하는 경우, 즉 확률이 애매한 경우에는 모델의 예측 성능이 떨어질 수 있습니다. 예를 들어, 암세포의 크기가 유방암일 확률이 높지 않거나 모양이 중간인 경우, 두 클래스 간의 경계가 불분명해져 정확한 분류가 어려워집니다.
학습 데이터에 대한 의존성: 학습 데이터에 특정 패턴이나 편향이 있다면, 이로 인해 예측의 정확성이 떨어질 수 있습니다. 즉, 데이터가 불균형하거나 특정 클래스에 대한 샘플이 적으면 분류 성능이 저하될 수 있습니다.
연속형 변수 처리: 연속형 변수를 처리할 때, 나이브 베이즈는 보통 Gaussian 분포를 가정합니다. 만약 데이터가 Gaussian 분포를 따르지 않는다면 예측이 부정확해질 수 있습니다.
참고로 나이브베이즈를 쓰기 위해서는 from sklearn.naive_bayes import GaussianNB을 써야합니다.
의사결정나무
의사결정나무는 개념만 이해하면 정말 쉽습니다. 나무가 뿌리에서 시작해서 나뭇잎으로 변화하듯, 계속해서 망에 걸러져서 최종 답이 나온다고 생각하시면 됩니다.
사진처럼 맨위에 있는 것을, 루트노드라 합니다. 즉, 나무의 시작점으로, 전체 데이터를 포함합니다. 여기서 제일 중요한 개념이 있는데, 바로 걸러지는 기준이 바로 데이터의 특성들이라는 겁니다. 먼저 기본 개념으로는,
1. 루프 노드: 나무의 시작점으로, 전체 데이터를 포함합니다.
2. 중간 노드: 특정 특성에 따라 데이터를 분할하는 노드입니다.
3. 리프 노드: 더 이상 분할되지 않는 최종 노드로, 특정 클래스(결과)를 나타냅니다.
예를들어 유방암에서, 세포의 크기에 따라, 모양에 따라, 환자의 나이에 따라 계속해서 걸러지면서 결국에는 유방암인지 아닌지를 결정한다고 생각하시면 편합니다. 사용하기 매우 간단하고 개념 또한 간단해서 많이 쓰입니다.
그리고 특성이 데이터를 나누는 기준으로는 불순도와 불확실성이 있으며, 이것은 모델이 알아서 계산해줌으로 써 신경 안 쓰셔도 됩니다.
참고로 의사결정나무를 쓸려면, from sklearn.tree import DecisionTreeClassifier을 써야합니다.
비지도 학습: 군집화모델 - k - means clustering
먼저 비지도 학습에 대해 알아야 합니다. 먼저 비지도 학습은 지도 학습과 다르게 따로 답이 주어지지 않습니다. 그렇기에 규칙을 발견하고 답과 대조하는 그런식이 아닙니다. 레이블이 없는 데이터 사용: 비지도 학습에서는 입력 데이터에 대한 레이블이 제공되지 않습니다. 알고리즘은 데이터를 자체적으로 분석하고, 패턴이나 구조를 발견해야 합니다. 목표: 주어진 데이터의 숨겨진 패턴이나 군집을 식별하는 것이 목표입니다. 데이터 간의 유사성을 기반으로 그룹화하거나 데이터의 분포를 이해하려고 합니다.
그러면 이제 군집화모델에 대해 배워보겠습니다. 군집화모델은 서로 비슷한 특성을 가진 데이터 포인트를 하나의 그룹(군집)으로 묶는 작업입니다. 각 군집 내의 데이터 포인트들은 서로 가까운 거리에 위치하게 됩니다. 즉, 데이터가 추가될 경우, 새로운 데이터 포인트가 기존 클러스터에 어떻게 속하는지를 평가하여 적절한 클래스로 분류하게 됩니다.
즉, 특별히 답과 대조하면서 비슷한 결과끼리 묶는 방법이었던 지도 학습과는 다르게, 답이 아니라 서로 비슷한 특성을 가진 데이터들끼리 묶는 작업입니다. 데이터 포인트 간의 유사성을 측정하기 위해 거리 기반 지표(예: 유클리드 거리, 맨해튼 거리)를 사용합니다. 이 거리 측정 방법은 데이터의 특성과 구조에 따라 달라질 수 있습니다.
군집화 과정에서는 데이터에 포함된 노이즈나 아웃라이어를 처리하는 것이 중요합니다. 일부 알고리즘은 이러한 노이즈를 군집에서 제외하기 위한 방법을 내장하고 있습니다.
주로고객 세분화: 마케팅 분야에서 고객을 세분화하여 맞춤형 서비스를 제공하는 데 사용됩니다. 이미지 분할: 이미지 내의 객체를 식별하고 구분하는 데 사용될 수 있습니다. 문서 군집화: 유사한 주제를 가진 문서들을 그룹화하여 정보 검색 및 추천 시스템에 활용됩니다. 에 쓰입니다.
그럼이제 K-means clustering에 대해 배우겠습니다. K-means clustering은, 사용자가 지정한 K개의 군집 중심을 기반으로 데이터를 클러스터링합니다. 초기 군집 중심을 무작위로 설정한 후, 각 데이터 포인트를 가장 가까운 군집 중심에 할당하고, 군집 중심을 다시 계산하는 과정을 반복하여 최적의 군집을 형성합니다.
그리고, 군집 중심 간의 거리를 계산하는데, 유클리드 거리를 사용하여 계산합니다. 그리고 엘보우 방법을 통해 최적의 k를 선택합니다. 그리고 다시 최적의 k를 사용해 계산합니다.
강의 코드를 가져와서 하나씩 보겠습니다.
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import seaborn as sns
# 데이터 로드
data = pd.read_csv('Mall_Customers.csv')
# 필요한 열 선택 및 결측값 처리
data = data[['Age', 'Annual Income (k$)', 'Spending Score (1-100)']]
# 데이터 스케일링
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)
# 최적의 k 찾기 (엘보우 방법)
inertia = []
K = range(1, 11)
for k in K:
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(data_scaled)
inertia.append(kmeans.inertia_)
# 엘보우 그래프 그리기
plt.figure(figsize=(10, 8))
plt.plot(K, inertia, 'bx-')
plt.xlabel('k')
plt.ylabel('Inertia')
plt.title('Elbow Method For Optimal k')
plt.show()
# k=5로 모델 생성 및 학습
kmeans = KMeans(n_clusters=5, random_state=42)
kmeans.fit(data_scaled)
# 군집 결과 할당
data['Cluster'] = kmeans.labels_
# 2차원으로 군집 시각화 (연령 vs 소득)
plt.figure(figsize=(10, 8))
sns.scatterplot(x=data['Age'], y=data['Annual Income (k$)'],
hue=data['Cluster'], palette='viridis')
plt.title('Clusters of customers (Age vs Annual Income)')
plt.show()
# 2차원으로 군집 시각화 (소득 vs 지출 점수)
plt.figure(figsize=(10, 8))
sns.scatterplot(x=data['Annual Income (k$)'], y=data['Spending Score
(1-100)'], hue=data['Cluster'], palette='viridis')
plt.title('Clusters of customers (Annual Income vs Spending Score)')
plt.show()
일단 여기서
data = data[['Age', 'Annual Income (k$)', 'Spending Score (1-100)']] 에서 따로 컬럼을 지정하는 이유는 바로, K-평균 군집화와 같은 비지도 학습 알고리즘에서는 데이터가 수치형이어야 합니다. 이는 알고리즘이 거리 기반의 방법을 사용하기 때문인데, 수치형 데이터는 거리 계산이 가능하지만, 범주형 데이터는 일반적으로 거리 계산이 어렵기 때문입니다.
데이터 스케일링 부분은 위에서 말했듯이, 데이터간의 갭이 너무 커서 평균을 0, 표준 편차를 1로 만들어서 데이터를 더 보기쉽게 만듭니다.
이제 최적의 k를 만드는 방법에 대해 알아보겠습니다. 그리고 넘어가기전 최적의 k는 1과 10사이에 있을 확률이 매우 큽니다. 이보다 많은 경우 과적합에 해당합니다.
엘보우 방법을 쓰기위해서는 먼저 각 데이터들이 좌표위에 어디에 속하는지 먼저 파악해야 합니다. 그렇게 위에 코드처럼 for문을 사용해 관성(inertia)를 찾는 방법을 쓰고 있습니다. 여기서 주목! 클러스터 수가 증가하면: 클러스터 수가 많아질수록 각 클러스터에 포함되는 데이터 포인트 수가 줄어들고, 데이터 포인트가 클러스터 중심에 더 가까워지기 때문에 관성 값은 낮아집니다. 관성 감소의 패턴: 초기에는 클러스터 수가 증가할 때 관성이 빠르게 줄어들다가, 특정 군집 수 이상부터는 감소 속도가 둔화되는 경향이 있습니다. 이 지점을 엘보우(elbow) 지점이라고 부르며, 이 시점에서 군집 수를 결정하는 것이 일반적입니다.
즉, 어떤 지점에서 감소 속도가 줄어들며, 포인트들 간의 차이가 거의 없어질 때가 있는데, 그 지점을 최적의 k라고 부릅니다.
그렇게
K = range(1, 11)
for k in K:
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(data_scaled)
inertia.append(kmeans.inertia_)
이렇게하면, k에는 1~10의 숫자가 들어가 k개의 군집을 만듭니다. 그리고 그 숫자에 맞게 합습을 시키고, .inertia_코드를 통해 관성을 구합니다. 그런데 여기서 data_scaled를 학습시키는 이유는, kmeans는 그저 군집의 수를 나타낼 뿐, 어디에, 어느 데이터를 가지고 학습을 할 지 모르는 상태입니다. 즉, 모든 데이터 포인트들은 data_scaled 안에 있습니다. 즉, 모든 좌표와 데이터 포인트는 data_scaled에 있고, kmeans는 그저 그 데이터를 학습하고 k개의 군집을 만드는 일을 할 뿐입니다.
즉, 위 코드는 이렇습니다 먼저 1개의 군집을 만들 때, data_scaled의 데이터 정보를 받아서, 빈 리스트 즉, inertia[]에 데이터와 그 안에 군집을 완성시킨(kmeans.fit(data_scaled) kmean를 더한다(.append). 그리고 그것을 k번 한다. 라고 할 수 있습니다. 그러면 좌표에는 k와 관성에 맞게 표시가 될 것이며, plt.figure(figsize=(10, 8)) plt.plot(K, inertia, 'bx-') plt.xlabel('k') plt.ylabel('Inertia') plt.title('Elbow Method For Optimal k') plt.show()를 통해 보여주고, 그 표시에서 엘보 포인트를 찾으면 됩니다. (두 포인트의 길이가 같아지는 지점)
그러고 다시 kmeans = KMeans(n_clusters=5, random_state=42) kmeans.fit(data_scaled)를 다시 한번 최적의 k를 대입하고 다시 학습을 시키면 됩니다. 그러고 'Cluster라는 컬럼을 만들어 대입하면 끝입니다.
군집화모델 - 계층적 군집화
계층적 군집화는 사실 찾는 포인트는 K-means clustering과 비슷하다고 볼 수 있습니다. 하지만 두개의 개념이 있습니다. 1. 병합 군집화 -> 초기 단계에서 각 데이터 포인트가 개별적인 클러스터를 형성합니다. 이후 가장 유사한 두 개의 클러스터를 반복적으로 병합하여 점점 더 큰 클러스터를 형성합니다. 최종적으로 모든 데이터 포인트가 하나의 클러스터로 통합될 때까지 진행됩니다.
2. 분할 군집화 -> 초기 단계에서 모든 데이터 포인트가 하나의 클러스터로 시작합니다. 이후 가장 이질적인 클러스터를 선택하여, 그 클러스터를 분할하는 방식으로 진행됩니다. 이 과정을 반복하여 최종적으로 각 데이터 포인트가 개별적인 클러스터가 될 때까지 진행됩니다.
하지만 여기서 질문이 있을 수 있습니다. 아니 그럼 계층적이랑 무슨 관계인거죠? 좌표에 놓여서 서로 비슷한 데이터끼리 묶으면 계층적이 무슨 소용이 있죠? 라고 하실 수 있습니다. 사실 군집화의 결과를 시각화할 때 주로 덴드로그램을 사용합니다. 이는 클러스터 간의 관계를 나무 형태로 나타내어, 클러스터가 어떻게 형성되었는지를 보여줍니다. 그렇기에, 병합 군집화는 데이터 포인트 간의 유사성을 기준으로 클러스터를 형성하는 방법입니다.
이 방법은 처음에 각 데이터 포인트를 하나의 클러스터로 간주하고, 점차적으로 가장 가까운 두 클러스터를 합쳐가며 클러스터를 형성하는 방식이기에, 그 자체를 계층적으로 보여줄 뿐입니다.
참고로 유사성을 측정하는 방법에는 여러 가지가 있습니다. 대표적으로는 유클리드 거리, 맨하탄 거리, 코사인 유사도 등이 있습니다.
분할 군집화는 그 반대로 큰 군집에서 서로 유사하지 않거나 거리 기반으로 멀리 떨어져 있는 데이터 포인트를 찾아냅니다. 그리고 데이터의 유사성을 기반으로 기준을 설정합니다. 이 기준은 주로 거리 또는 군집의 밀도에 따라 결정되며, 특정한 기준을 만족하지 못하는 데이터 포인트들이 새로운 군집으로 분리됩니다.
하지만, 계층적 군집화는 앨보우 방식처럼 그래프에서 최적의 클러스터 수를 찾아야 합니다.
DBSCAN
DBSCAN은 K-means나 계층적 군집화처럼 그래프를 보고 최적의 값을 찾을 필요가 없습니다. 게다가 개념도 간단합니다. 그냥 데이터 밀도가 높은 영역을 군집으로 간주하고, 낮은 영역은 노이즈로 처리합니다.
개념부터 보겠습니다. eps (입실론 거리): 두 점이 가까운지 여부를 결정하는 최대 거리입니다. 이 거리를 기준으로 군집이 형성됩니다.
min_samples: 하나의 군집으로 정의하기 위해 필요한 최소 데이터 포인트 수입니다. 즉, 최소 몇 개의 데이터가 가까이 모여야 군집으로 인정할 것인지를 결정합니다. DBSCAN은 각 데이터 포인트의 eps 거리 내에 최소 min_samples 이상이 있을 때, 해당 데이터 포인트를 핵심점(core point)로 간주합니다. 원리 핵심점 찾기:데이터 포인트 중에서 eps 반경 내에 min_samples 이상의 이웃을 가진 핵심점을 찾습니다. eps 반경 내의 데이터수 ≥ min_samples : 해당 데이터 포인트를 중심으로 새로운 군집 형성. eps 반경 내의 데이터수 < min_samples : 해당 데이터 포인트를 노이즈로 간주
군집 확장:핵심점에서 시작하여 연결된 이웃점들을 따라가며 군집을 확장합니다. 이 과정에서 경계점은 군집에 포함되지만 노이즈점은 포함되지 않습니다.
반복:모든 데이터 포인트가 처리될 때까지 이 과정을 반복합니다.
노이즈 처리:군집에 속하지 않은 점들은 노이즈(이상치)로 처리됩니다.
주요 개념 핵심점(Core Point): 자신의 eps 거리 내에 min_samples 이상의 다른 점들이 존재하는 데이터 포인트입니다. 군집의 중심을 이루는 점입니다. 경계점(Border Point): 핵심점의 eps 거리 내에 위치하지만, 자신은 min_samples 이상의 이웃을 가지지 않는 데이터 포인트입니다. 군집에 속할 수 있지만, 핵심점은 아닙니다. 노이즈점(Noise Point): eps 거리 내에 충분한 이웃이 없는 데이터 포인트로, 군집에 속하지 않는 이상치로 간주됩니다.
자, 여기서 제일 중요한 포인트가 있습니다. 군집안에 있는 모든 데이터 포인트들이 핵심점이 될 수 있다는 것입니다. 설명하겠습니다. DBSCAN에서는 핵심점이란, 주어진 EPS 반경 내에 min_samples 개수 이상의 데이터 포인트가 있는 포인트를 말합니다. 즉, 특정 포인트가 핵심점이 되려면, 그 주위에 충분히 많은 이웃이 존재해야 합니다.
여기서 상호참조란 개념이 나오는데, 즉 군집을 형성하는 과정에서, 어떤 포인트가 핵심점이 되면, 그 포인트의 EPS 반경 내에 있는 포인트들도 이 핵심점을 참조하여 자신도 핵심점이 될 수 있습니다. 이 과정은 서로의 EPS 반경이 겹치기 때문에 가능합니다.
즉, 모든 포인트가 핵심점이 될 수 있고, 같은 포인트들이 서로의 EPS 반경 내에 있다면, 이들은 모두 핵심점이 될 수 있습니다. 이는 서로를 이웃으로 가지고 있기 때문입니다. 이 핵심점들이 연결되면서, 하나의 밀집된 군집을 형성하게 됩니다. 이렇게 형성된 군집은 밀도가 높은 지역의 데이터를 잘 나타내며, DBSCAN의 핵심적인 목적입니다.