
오늘 한 일은,
- SQL 공부
- [코드카타] SQL 7문제 풀기(138~144번)
- 통계학 공부
- [통계 라이브세션] 6회차 수강하기
- 머신러닝 공부
- [python standard] 9회차 수강하기
- [실무에 쓰는 머신러닝 기초] 1-6 실습하기
- [실무에 쓰는 머신러닝 기초] 1-7, 1-8, 1-9 수강하기
- 제45회 데이터 분석 준전문가(ADsP) 접수하기 미래의 나, 믿고 있을게^^ 합격 맡겨놨어~~
SQL 공부: [코드카타] SQL 문제 풀기(138~144번)
140. Weather Observation Station 8
Query the list of CITY names from STATION which have vowels (i.e., a, e, i, o, and u) as both their first and last characters. Your result cannot contain duplicates.
SELECT DISTINCT city
FROM station
WHERE (SUBSTR(city, 1, 1) IN ('A', 'E', 'I', 'O', 'U')) AND
(SUBSTR(city, -1, 1) IN ('a', 'e', 'i', 'o', 'u'))
마지막 글자를 가지고 오고 싶을 때는 SUBSTR()의 두 번째 값을 음수로 입력한다. (-1은 끝에서 첫 번째부터, -2는 끝에서 두 번째부터)
머신러닝 공부: [실무에서 쓰는 머신러닝 기초]
앙상블 기법: [실습] XGBoost 모델로 유방암 여부 분류하기

새로이 진도를 나가기 전에 이전 학습 범위의 실습 문제부터!
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
# 1. 유방암 데이터셋 로드 및 X와 y 정의하기
data = load_breast_cancer()
X = data.data
y = data.target
feature_names = data.feature_names

언제나처럼, 우선 데이터를 불러오고 독립 변수와 종속 변수를 정의했다. 독립 변수가 무려 30개...
그리고 사용할 XGBoost 모델은 숫자형 데이터 입력만 허용하기에 바꿔줘야 할 범주형 변수는 없는지 확인해보기로 했다.
# 2. 데이터 전처리 - 범주형 변수가 있는지 확인하기
# 확인해보니 데이터 타입이 전부 숫자형이라 처리할 컬럼이 없었음
df = pd.DataFrame(
X, columns=feature_names
)
df['target'] = y
df
df.info()

익숙한 .info()로 확인하고 싶어서 데이터 프레임으로 담아서 확인했더니 모두 숫자형임을 확인하여 딱히 전처리는 안 해도 될 것 같았다. (사실 컬럼 수가 너무 많아서 어떤 식으로 줄여야 하나 고민했지만 문제 자체가 '어떤 변수가 가장 중요한지' 찾는 것이기에 그냥 이대로 하기로 했다. 그리고 뭘 알아야 삭제하고 그럴 텐데 뭔 소리인지 모르겠기도 하고..)
그리고 이제 학습용 데이터와 검증용 데이터를 분리하기 전에 이번에 하이퍼파라미터를 배울 때 새로이 알게 된 validation 데이터셋에 대해서 좀 더 찾아봤다.
[참고1] Train / Test / Validation set의 차이
[참고2] validation set이란? test set과의 차이점과 사용 방법
- 데이터셋을 train / test 2개로만 분리하는 것이 아니라, 현업에서는 모델을 만들 때 train / validation / test 3개로 분리함
- train : 학습에만 사용
- validation : 최적의 모델을 탐색할 때 시험 검증용으로 사용 학습을 시킬 때 사용하지 않지만, 학습에 관여하는 데이터
- test : 오직 최종 성능의 평가에만 사용 학습에 전혀 관여하지 않음
- 보통은 train : validation : test의 비율은 8:1:1
- validation 데이터셋을 굳이 할애하는 것은,
- ①train 데이터의 과적합을 피하고
- ②새로운 데이터에서도 여전히 괜찮은 성능을 보장하는 모델을 만들기 위해서
# 3. 학습용 데이터와 검증용 데이터 분리하기 (train:validation:test=6:2:2)
# train:test = 6:4로 나누기
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.4,
random_state=42,
stratify=y
)
# validation:test = 5:5로 나누기
X_test, X_val, y_test, y_val = train_test_split(
X_test, y_test,
test_size=0.5,
random_state=42,
stratify=y_test
)

이번에는 이렇게 validation 데이터셋까지 추가하여 데이터를 분리했다. 일반적으로 6:2:2의 비율로 나눈대서 그렇게 나눴는데 뭔가 학습용 데이터가 너무 적지 않나 싶긴 하다.
# 4. XGBoost 모델 학습시키기
from xgboost import XGBClassifier
xgb_model = XGBClassifier(random_state=42)
xgb_model.fit(X_train, y_train)
y_pred_xgb = xgb_model.predict(X_val) # 결과를 봐서 파라미터를 손봐야 할 수도 있으니 validation 데이터로
# 기본 상태에서 예측 성능 확인하기
print("=== XGBoost ===")
print("Accuracy:", accuracy_score(y_val, y_pred_xgb))
print("Confusion Matrix:\n", confusion_matrix(y_val, y_pred_xgb))
print("Classification Report:\n", classification_report(y_val, y_pred_xgb, target_names=['0(악성)', '1(양성)']))

그냥 기본으로만 해도 예측 성능이 괜찮다. 클래스가 2개인데 악성(0)은 43개 중에 40개를 제대로 분류하며 재현율(recall)이 93%, 양성(1)은 71개 중에서 70개를 제대로 분류하며 재현율을 99% 달성했다.
그런데 암을 진단하는 데서 중요한 것은 악성 종양을 발견해내는 것이기 때문에 악성(0)의 재현율을 더 높일 수 있는 모델이 있을지 매개변수를 조정하여 다른 모델들도 찾아보기로 했다.
[참고1] XGBoost 파라미터들
[참고2] xgboost
- XGBClassifier() 주요 매개변수
- n_estimators : 결정 트리 수 (기본=100)
- learning_rate : 학습 단계별로 이전 결과를 얼마나 반영할지, 일반적으로 0.01~0.2 (기본=0.1)
- max_depth : 트리의 깊이, 일반적으로 3~10 (기본=6)
# 5. XGBoost 모델 결정하기: Grid Search 이용하여
# n_estimators, max_depth만 해보기
from sklearn.model_selection import GridSearchCV
param_grid = {
'n_estimators' : [100, 200, 300],
'max_depth' : [4, 5, 6, 7]
}
grid = GridSearchCV(
XGBClassifier(random_state=42),
param_grid,
cv=5,
scoring='accuracy',
n_jobs=-1
)
grid.fit(X_train, y_train)
# 사용한 매개변수 중 최적의 조합 알아보기
print(f'best parameter: {grid.best_params_}')
print(f'best Cross-Validation Score: {grid.best_score_}')

# 5. XGBoost 모델 결정하기(2): max_depth=4, n_estimators=100로 모델 생성하기
xgb_model_2 = XGBClassifier(n_estimators=100, max_depth=4, random_state=42)
xgb_model_2.fit(X_train, y_train)
y_pred_xgb_2 = xgb_model_2.predict(X_val)
# max_depth를 4로 조정한 상태에서 예측 성능 확인하기
print("=== XGBoost(2)(max_depth=4) ===")
print("Accuracy:", accuracy_score(y_val, y_pred_xgb_2))
print("Confusion Matrix:\n", confusion_matrix(y_val, y_pred_xgb_2))
print("Classification Report:\n", classification_report(y_val, y_pred_xgb_2, target_names=['0(악성)', '1(양성)']))

첫 번째 모델(xgb_model)과 비교해서 두 번째 모델(xgb_model_2)는 매개변수 max_depth를 4(기본(6) →4)로 조정함으로써 양성의 재현율은 그대로인 반면 목표로 삼았던 악성의 재현율이 43개 중에 41개를 맞춤으로써 95%로 소폭 올랐다.
그래서 두 번째 모델로 정하고 test 데이터셋으로도 예측 성능을 최종 확인해봤다.
# 6. 최종적으로 test 데이터셋으로 한 번 더 예측 성능 확인하기
y_final_pred_xgb = xgb_model_2.predict(X_test)
# xgb_model_2에서 예측 성능 확인하기
print("=== XGBoost(final)(max_depth=4) ===")
print("Accuracy:", accuracy_score(y_test, y_final_pred_xgb))
print("Confusion Matrix:\n", confusion_matrix(y_test, y_final_pred_xgb))
print("Classification Report:\n", classification_report(y_test, y_final_pred_xgb, target_names=['0(악성)', '1(양성)']))

뭐야, 새로운 데이터셋으로 보니까 다시 재현율 93%로 나왔네..? 하긴 생각해보면 95%나 93%나 둘이 유의미하게 차이가 있는 건 아닌 것 같기도 하다.
# 7. 피처 중요도 시각화하기
from sklearn.ensemble import RandomForestClassifier
# 랜덤 포레스트 모델 학습시키기
rf = RandomForestClassifier(random_state=42)
rf.fit(X_train, y_train)
# 피처 중요도 추출하기
importances = rf.feature_importances_
# 시각화하기
plt.bar(range(len(importances)), importances)
plt.xticks(range(len(importances)), feature_names, rotation=90)
plt.xlabel("Feature")
plt.ylabel("Importance")
plt.title("Feature Importances in RandomForest")
plt.tight_layout()
plt.show()
# 가장 중요한 변수
most_important_idx = importances.argmax()
most_important_feature = feature_names[most_important_idx]
print("가장 중요한 변수:", most_important_feature)

마지막으로 피처 중요도를 시각화하고 가장 중요한 변수를 찾기 위해 랜덤 포레스트 모델을 생성해서도 봤다. worst concave points가 가장 중요하다고 나왔다.
1-7. 군집 분석
군집 분석(Clustering)
- 비지도 학습!
- 비슷한 특성을 가진 데이터들을 묶는 기법(cluster)
: 각 그룹 내 데이터들끼리는 유사도를 최대화하고, 다른 그룹과의 차이는 최대화하는 기법 - 목적
- 데이터의 구조 파악: 정답 없이 데이터의 자연스러운 분포를 확인할 수 있음
- 세분화 마케팅에선 고객 세분화를, 제조업에선 센서 데이터로 기계 작동 패턴 분류 등
- 절차
- 데이터 수집 및 전처리 (이상치 제거, 결측치 처리, 스케일링 등)
- 군집 수 및 매개변수 설정 K-Means→k / DBSCAN→거리(ε), 최소 데이터 수(minPts)
- 군집화 알고리즘 적용
- 결과 해석 및 평가 실루엣 계수 등 활용
- 사후 활용 마케팅 전략, 제품 개선, 이상치 탐지 등
대표적인 군집 분석: ① K-평균 군집화(K-Means Clustering)
- K개의 clustering point(cluster center)를 잡고 데이터 집합에서 가장 가까운 값들을 같은 class로 묶는 방식
- 몇 개의 군집으로 묶을지 설정해야 함
- 무작위로 K개의 중심을 선택한 후에 각 데이터 포인트를 가장 가까운 중심에 할당
- 각 군집의 중심ㅁ을 다시 계산하고 재할당하는 과정을 반복
- 군집 내 데이터와 중심 간 거리의 제곱합을 최소화함
- 장단점
- [장] 계산 속도가 빠르고 구현이 간단함
- [장] 대용량 데이터에도 비교적 잘 작동함
- [단] 군집 수(K)를 미리 알아야 함
- [단] 이상치에 취약함 전처리 시 꼭 이상치 처리를 해주고서 분석에 들어가야 함
- [단] 구형이 아닌 복잡한 형태의 분포는 파악하기 어려움
- 예시
- 고객 데이터(나이, 월평균 지출액, 자주 구매하는 카테고리 등)로 분석하여 K=3으로 설정하여 '저가 위주의 고객', '중간 가격대 선호 고객', '고가 제품 위주의 고객'으로 군집을 나눠볼 수 있음
대표적인 군집 분석: ② DBSCAN(Density-Based Spatial Clustering of Applications with Noise)
- 일정 거리(ε) 내에 데이터가 많으면(=최소 포인트 수(minPts) 이상) 그 영역을 '밀도가 높다'고 판단해 하나의 군집으로 결정
밀도 기반 군집화 기법 - 장단점
- [장] 군집 수를 사전에 알 필요 없음
- [장] 노이즈와 이상치를 자연스럽게 처리함 노이즈 포인트(어느 군집에도 속하지 않는 점)을 구분할 수 있음
- [장] 복잡한 형태의 군집도 잘 찾아냄
- [단] 매개변수 ε, minPts에 민감함
- [단] 데이터 밀도가 균일하지 않으면 성능이 떨어짐
- 예시
- 지리 정보(GIS)를 기반으로 지역별로 가게가 얼마나 밀집되어 있는지 분석하여 특정 지점에 가게가 몰려 있으면 하나의 군집으로, 뜨문뜨문 있으면 노이즈(cluster 속하지 않음)로 분류
대표적인 군집 분석: ③ 계층적 군집화(Hierarchical Clustering)
- 데이터 포인트 하나하나는 하나의 군집으로 시작
→ 유사도가 가장 높은 군집끼리 병합함
→ 최종적으로 하나의 군집(트리)을 형성함 이와 반대로 하나의 군집에서 시작해 분할해 나가는 방식도 있음(분할적 접근) - 장단점
- [장] 군집의 계층적 구조 파악이 쉬움(덴드로그램)
- [장] 덴드로그램의 특정 높이에 따라 유연하게 군집 개수를 결정할 수 있음
- [단] 계산 복잡도가 높아 대규모 데이터엔 적용이 어려움
- 예시
- 다양한 문서(텍스트) 클러스터링에서의 단어 사용 빈도 등을 기반으로 문서 구조를 시각화할 수 있음
군집 분석의 평가 지표
- 실루엣 계수(Silhouette Score)
- 값의 범위: -1 ~ +1
- +1에 가까울수록 → 해당 데이터가 잘 군집됨
- 0에 가까울수록 → 군집의 경계에 위치함
- 0보다 작음 → 군집화가 잘못됨
- 값의 범위: -1 ~ +1
- Davies-Bouldin Index
- 값의 범위: 0 이상
- 0에 가까울수록 → 군집 간 구분이 잘 됨
- 값이 커질수록 → 군집화 품질이 좋지 않음 군집 간 겹치는 곳이 많음
- 값의 범위: 0 이상
- 내부 평가와 외부 평가
- 내부 평가: 데이터 내부의 정보를 활용해 평가함 실루엣 계수, Davies-Bouldin Index 등을 활용하는 것
- 외부 평가: 이미 잘 알려진 레이블(정답)과 군집 결과를 비교한다거나 해당 분석을 바탕으로 마케팅 전략을 수립했을 때 결과가 어땠는지 등
1-8. 차원 축소
차원 축소(Dimensionality Reduction)
- 고차원 데이터에서 중요한 정보는 유지하면서 데이터의 차원을 줄이는 과정
- 고차원의 데이터 = 데이터의 피처(변수)가 매우 많은 상태
- 고차원 데이터의 문제
- 모델 학습 시 연산 복잡도가 급증하여 시간이 오래 걸림
- 많은 피처들 중 일부는 실제로 중요한 정보를 주지 못하는 노이즈(잡음)일 수 있음
- 데이터를 시각화하기가 어려워 패턴 파악이 힘듦
- 차원 축소의 장점
- 노이즈 제거로 모델 성능 및 일반화 능력을 개선
= 차원 축소 시, 중요한 변동을 잘 설명하지 못하는 데이터는 줄여버림으로써 불필요한 정보를 걸러냄 - 2차원/3차원으로 축소하면 시각적으로 직관적인 분석이 가능
- 데이터의 핵심 구조나 패턴을 더 쉽게 발견할 수 있음
- 노이즈 제거로 모델 성능 및 일반화 능력을 개선
- 선형 차원 축소 vs 비선형 차원 축소
- 선형 차원 축소
- 데이터를 특정 선형 변환(ex : 행렬 곱)으로 투영하여 차원을 줄이는 기법
- 주요 분석 기법: PCA
- 비선형 차원 축소
- 데이터가 복잡한 기하학적 구조를 가질 때, 선형 변환만으로는 충분치 않을 수 있으므로 비선형 맵핑을 이용
- 주요 분석 기법: t-SNE, UMAP 등
- 선형 차원 축소
차원 축소 기법: ①주성분 분석(PCA, Principal Component Analysis)
- 데이터에서 가장 ‘분산이 큰 방향(주성분)’을 찾아 그 방향으로 데이터를 투영하면, 그 축이 데이터의 중요한 변동(variance)을 많이 설명할 수 있음
- 주성분(Principal Component)
- 1주성분: 가장 큰 분산을 갖는 방향
- 2주성분: 그 다음으로 큰 분산을 갖는 서로 직교하는 방향
- 설명 분산(Explained Variance) 비율
- 몇 개의 주성분만으로 전체 분산의 몇 퍼센트를 설명할 수 있는지
- 주성분(Principal Component)
- 장단점
- [장] 계산이 비교적 간단함(선형 연산), 결과 해석이 용이함
- [단] 데이터가 선형을 띄지 않으면 매우 복잡한 구조를 충분히 반영하기 어려움
차원 축소 기법: ②t-SNE(t-Distributed Stochastic Neighbor Embedding)
- 고차원 공간에서 ‘서로 가까운 데이터 포인트는 가까이, 먼 데이터 포인트는 멀리’ 배치하려고 하는 비선형 차원 축소 기법
고차원에서 A가 B와 가까울 확률을 구하고, 2D에서는 그 확률을 최대한 비슷하게 만들도록 위치를 조정
- 고차원에서 데이터 간 ‘지역적 확률 분포’를 추정(주변 데이터와의 거리를 기반으로)
- 2차원 혹은 3차원에서 비슷한 확률 분포가 되도록 데이터들을 배치
- 장단점
- [장] 군집별 패턴을 인지하기 쉬움
- [단] 계산 비용이 큰 편 대규모 데이터에는 시간이 오래 걸림
- [단] 시각화 결과 해석이 직관적이지만, 실제 거리 척도가 왜곡될 수 있으니 주의
차원 축소 기법: ③UMAP(Uniform Manifold Approximation and Projection)
- 고차원 데이터의 구조를 2D/3D로 매핑하는 비선형 차원 축소 기법 t-SNE와 유사
‘근접 그래프(nearest neighbor graph)’와 ‘Riemannian manifold’ 이론에 기반 - 장단점
- [장] t-SNE보다 빠르고, 대규모 데이터에도 비교적 효율적
- [단] 알고리즘의 개념이 비교적 복잡하고, 하이퍼파라미터 튜닝을 요함
- [단] t-SNE만큼은 아니지만, 여전히 축소 과정에서 정보 왜곡이 발생
차원 축소를 실무에 적용할 시 고려할 사항
- 데이터 전처리는 먼저!!
- PCA는 주성분 개수만 설정해줘도 충분한 편인데, t-SNE와 UMAP은 하이터파라미터 튜닝을 잘해줘야 함
- 결과 해석에 있어서,
- PCA : 주성분 방향이 어떤 피처 조합과 관련 있는지 알 수 있음
각 주성분이 원본 데이터에서 어떠한 변수(=피처)와 유독 관련이 있는지 확인 가능 - t-SNE/UMAP : 시각화를 통해 군집 형태 및 분포를 확인하기엔 좋지만 지나치게 해석하기보다 그냥 느낌만 보는 정도로 참고하길 왜냐하면 거리 자체의 절대적 의미는 왜곡될 수 있기 때문에
- PCA : 주성분 방향이 어떤 피처 조합과 관련 있는지 알 수 있음
- 성능 측정 및 검증에서,
- 차원 축소만을 확인하기 위한 지표는 없음
- 그런데 대체로 차원 축소는 다른 기법과 함께 쓰게 됨
- (목적1) 노이즈 제거하려고 → 그 다음에 회귀/분류를 한다면 그 회귀/분류에 해당하는 평가 지표로
- (목적2) 군집 분석을 위해 → 실루엣 계수로
- (목적3) 시각화하려고 → 시각화가 잘 나왔는지 그냥 확인해
1-9. 이상 탐지
이상 탐지(Anomaly Detection)
- 데이터에서 ‘정상(normal) 패턴’과 크게 다른 행위를 보이는 특이한 패턴(이상, anomaly)을 찾는 기법
- 현업에서의 사례
- 금융: 금융 사기
- 제조: 고장을 사전에 예측하기,
- 보안: 네트워크 침입 시도 탐지, 데이터 탈취 감지
- 이상 탐지(anomaly detection)이 이상치 탐지(outlier detection)를 포함하는 더 넓은 개념!
- 이상치 탐지: 단순히 통계적으로 극단값을 찾아내는 것
- 이상 탐지: 극단값뿐만 아니라, 맥락 및 시계열 상의 패턴을 함께 고려했을 때 비정상적임을 판단하는 것
이상 탐지 기법: ①One-Class SVM
- ‘단 하나의 클래스(정상 클래스)’만을 학습해 해당 클래스 영역을 정의
: 정상 데이터가 분포하는 공간 주위에 경계를 형성(“decision boundary”)하고, 경계 밖에 있는 데이터는 ‘비정상’으로 분류함 - 고차원 공간에서도 비교적 잘 동작 가능(커널 함수를 사용하면) 근데 기본적으로는 그냥 기본값으로 두면 된다고 함
- 데이터 스케일링과 커널 파라미터 선택이 중요 (ex. rbf 커널 → γ값, nu(ν) 값 등)
*nu(ν): 이 데이터에 이상치가 몇 퍼센트 있을 것이라 생각하는지 예상해서 설정해야 함
이상 탐지 기법: ②Isolation Forest
- 무작위로 특성과 분할값을 골라 데이터를 계속 나누어가는 과정에서 ‘쉽게 분리(또는 격리)되는’ 데이터는 이상일 가능성이 높다고 간주
- 랜덤 포레스트 방식으로 여러 개의 무작위 트리를 구성하고, 각 트리에서 한 데이터가 분리되는 “깊이(depth)”를 측정하여 이상 점수를 부여함
- 대규모 데이터셋에서도 빠르게 동작하는 편이며, 구현이 간단하고 직관적임
- 매개변수 contamination : 실제 데이터셋에서 예상되는 이상치 비율을 추정해 설정하거나 도메인 지식이나 사전 샘플링을 통해 결정하는 경우도 많음

실습 문제들은 내일 복습하는 느낌으로다가 풀기로~~
'[내배캠] 데이터분석 6기 > 본캠프 기록' 카테고리의 다른 글
[본캠프 42일차] SQL 공부, 머신러닝 공부 (0) | 2025.04.16 |
---|---|
[본캠프 41일차] SQL 공부, 머신러닝 공부 (1) | 2025.04.15 |
[본캠프 39일차] SQL 공부, QCC ④, 머신러닝 공부 (0) | 2025.04.11 |
[본캠프 38일차] SQL 공부, 머신러닝 공부 (0) | 2025.04.10 |
[본캠프 37일차] SQL 공부, 머신러닝 공부 (0) | 2025.04.09 |