Today I learned
1. [라이브세션] 머신러닝 특강 - 머신러닝 주요 기법 3일차
1) 랜덤 포레스트
집단 지성의 원리를 학습한 앙상블 알고리즘
- 랜덤포레스트 분석의 원리
1단계: 부트스트랩 샘플링
부트스트랩 샘플링은 원본 데이터에서 복원 추출로 새로운 데이터셋을 만드는 방법입니다.
- 원본 데이터 N개(1000)에서 N개(1000)를 복원 추출
- 각 트리마다 서로 다른 부트스트랩 샘플 사용
효과:
- 각 트리가 약간씩 다른 패턴을 학습
- 과적합 방지 및 일반화 성능 향상

2단계: 특성 무작위성
특성 무작위성은 각 노드 분할 시 전체 특성 중 일부만 랜덤하게 선택하여 고려하는 방법입니다.
방법:
- 전체 특성 수를 p(8개)라고 할 때, 보통 √p 루트8 개의 특성만 고려
- 각 분할마다 다른 특성 조합 사용
- 트리 간 상관관계 감소로 앙상블 효과 극대화
예를들어
- 전체 특성: 9개
- 각 분할에서 고려할 특성: √9 ≈ 3개
- 가능한 조합: C(9,3) = 84가지
3단계: 투표 방식
앙상블의 최종 예측은 개별 트리드르이 예측을 종합하여 결정

| scikit-learn을 활용한 랜덤포레스트 분석 예시(머신러닝 특강 2일차 데이터에서 이어짐) | |
| 1단계: 랜덤포레스트 모델 생성 | |
|
# RandomForestClassifier import
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# 랜덤 포레스트 모델 생성
rf_model = RandomForestClassifier(
n_estimators=100, # 트리 개수
max_depth=10, # 최대 깊이
min_samples_split=20, # 분할 최소 샘플
min_samples_leaf=10, # 리프 최소 샘플
max_features='sqrt', # 특성 무작위성 루트, decision tree에서 추가된거, 개인이 임의로 세팅할 수 있음
#max_feature = 1 이면 전체를 사용하겠다, 0.5 면 절반 사용하겠다 이런 애기임
bootstrap=True, # 부트스트랩 사용, decision tree에서 추가된거
random_state=42,
)
print("=== 랜덤 포레스트 모델 설정 ===")
print(f"트리 개수: {rf_model.n_estimators}")
print(f"최대 깊이: {rf_model.max_depth}")
print(f"특성 선택: {rf_model.max_features}")
print(f"부트스트랩: {rf_model.bootstrap}")
|
=== 랜덤 포레스트 모델 설정 === 트리 개수: 100 최대 깊이: 10 특성 선택: sqrt 부트스트랩: True |
| 2단계: 모델 학습 과정 | |
|
# 모델 학습 시작
print("=== 랜덤 포레스트 학습 시작 ===")
print("100개의 트리를 병렬로 학습 중...")
# 학습 시간 측정
import time
start_time = time.time()
rf_model.fit(X_train, y_train)
end_time = time.time()
training_time = end_time - start_time
print(f"학습 완료! 소요 시간: {training_time:.2f}초")
print(f"학습된 트리 개수: {len(rf_model.estimators_)}")
|
=== 랜덤 포레스트 학습 시작 === 100개의 트리를 병렬로 학습 중... 학습 완료! 소요 시간: 0.15초 학습된 트리 개수: 100 |
| 3단계: 기본 성능 평가 | |
|
rf_train_pred = rf_model.predict(X_train)
rf_test_pred = rf_model.predict(X_test)
# 정확도 계산
rf_train_acc = accuracy_score(y_train, rf_train_pred)
rf_test_acc = accuracy_score(y_test, rf_test_pred)
rf_overfit = rf_train_acc - rf_test_acc
print(f"훈련 데이터 정확도: {rf_train_acc:.3f}")
print(f"테스트 데이터 정확도: {rf_test_acc:.3f}")
|
훈련 데이터 정확도: 0.850 테스트 데이터 정확도: 0.782 |
| - 특성 중요도 확인 | |
|
# 특성 중요도 추출
feature_importance = pd.DataFrame({
'feature': X.columns,
'importance': rf_model.feature_importances_
}).sort_values('importance', ascending=False)
print("랜덤 포레스트 특성 중요도 순위:")
print("-" * 30)
for idx, row in feature_importance.iterrows():
print(f"{row['feature']:15}: {row['importance']:.3f}")
# 상위 5개 특성 강조
print(f"\n🏆 TOP 5 중요 특성:")
top5_features = feature_importance.head(5)
for i, (_, row) in enumerate(top5_features.iterrows(), 1):
print(f"{i}위. {row['feature']} ({row['importance']:.3f})")
|
![]() |
| - 트리 시각화 | |
|
first_tree = rf_model.estimators_[0] # 첫 번째 트리를 가져옴
for i in range(0, 100):
first_tree = rf_model.estimators_[i]
# 첫 번째 트리 시각화
plt.figure(figsize=(20, 12))
plot_tree(first_tree,
feature_names=X.columns,
class_names=['사망', '생존'],
filled=True,
rounded=True,
fontsize=10)
plt.title('랜덤 포레스트 내 첫 번째 디시전 트리', fontsize=16)
plt.show()
# 첫 번째 트리 구조를 텍스트로 출력
print("\n=== 랜덤 포레스트 내 첫 번째 디시전 트리 구조 (텍스트) ===")
tree_rules = export_text(first_tree, feature_names=list(X.columns))
print(tree_rules[:1000]) # 처음 1000자만 출력
|
![]() |
2) XGBoost
XGBoost (eXtreme Gradient Boosting)**는 그래디언트 부스팅을 극한으로 최적화한 알고리즘입니다. 캐글 대회 우승작의 80% 이상에서 사용될 정도로 실무에서 가장 인기 있는 머신러닝 알고리즘입니다.
XGBoost의 핵심 특징:
- 순차적 학습: 이전 모델의 오류를 다음 모델이 보완
- 정규화: L1, L2 정규화로 과적합 방지
- 병렬 처리: GPU 지원으로 빠른 학습
- 결측치 처리: 자동으로 최적의 결측치 처리 방향 학습 </aside>
랜덤포레스트 vs xgboost
랜포: 독립적인 트리들의 병렬 학습
엑지: 오류를 보완하는 트리들의 순차 학습
![]() |
![]() |
- 1단계: 첫 번째 기본 트리 만들기(약한 분류기)첫 번째 모델의 시도
- 매우 간단한 트리 1개로 시작 (깊이 1-2 정도)
- 예: "성별이 여성이면 생존, 남성이면 사망"
- 정확히 예측된 승객: 700명 ✅
- 틀리게 예측된 승객: 191명 ❌
- 실제로는 생존했는데 사망으로 예측: 80명
- 실제로는 사망했는데 생존으로 예측: 111명
- 상황: 타이타닉 승객 891명의 생존 여부를 예측해야 합니다.
- 2단계: 첫 번째 모델의 오차 분석하기
- 남성인데 생존한 사람들: 어린 남자아이들, 1등급 남성들
- 여성인데 사망한 사람들: 3등급의 나이 많은 여성들
- 틀리게 예측된 191명에게 **"더 중요하다"**는 표시
- 올바르게 예측된 700명은 **"덜 중요하다"**는 표시
- 3단계: 두 번째 약한 분류기 만들기 (실수 보완에 집중)
- 첫 번째 모델이 틀린 191명에 집중적으로 학습
- 새로운 규칙 발견: "남성이면서 나이가 10세 이하면 생존"
- 이전에 틀렸던 191명 중 120명을 올바르게 수정 ✅
- 하지만 새롭게 71명을 틀리게 예측 ❌
- 두 번째 모델은 혼자서는 성능이 나쁠 수 있음
- 하지만 첫 번째 모델의 특정 약점을 보완하는 데 특화됨
- 두 번째 모델의 학습
- 4단계: 세 번째 약한 분류기 만들기 (남은 실수 더 보완)
- 첫 번째 + 두 번째 모델이 여전히 틀리는 승객들에 집중
- 이 과정을 통해 점진적 성능 향상
- 전체 891명 중: 1단계 후: 191명 틀림 (정확도 78.5%) 2단계 후: 71명 틀림 (정확도 92.0%) 3단계 후: 25명 틀림 (정확도 97.2%)
- 5단계: 최종 예측 - 모든 모델의 지혜 결합
- 가중 투표 방식! → 각 모델의 성능에 따라 다른 영향력 부여:
새로운 승객의 생존 예측:
- 1번 모델: "사망" (영향력 40%)
- 2번 모델: "생존" (영향력 35%)
- 3번 모델: "생존" (영향력 25%)
최종 계산:
사망: 40%
생존: 35% + 25% = 60%
→ 결론: 생존 예측! 🎯
최종 예측 = 기본값 + α₁×모델₁ + α₂×모델₂ + α₃×모델₃ + ...
여기서:
- 기본값: 전체 데이터의 평균 (타이타닉의 경우 생존률 38%)
- α₁, α₂, α₃: 각 모델의 학습률 (보통 0.1~0.3)
- 모델₁, 모델₂, 모델₃: 각 단계에서 학습된 약한 분류기
XGBoost로 이걸 구현하기
3) 클러스터링
지금까지 우리가 배운건 지도학습
비지도학습 (Unsupervised Learning)
- 정답에 해당하는 값이 주어지지 않은 상태에서
- 입력 데이터(X)의 특성을 분석하는 모델을 학습하는 과정
- 특징: 분석가의 주관이 많이 개입, 사람마다 해석이 다를 수 있음
- 목적: 데이터 사이의 연관 규칙이나 군집을 구하는 과정
- 예시: 고객 세분화, 패턴 발견, 이상 탐지

- 클러스터링이란 분석 대상이 되는 데이터의 그룹을 만드는 방법론.
- 그룹을 만들 때는 마구잡이로 만드는 것이 아니라 특정 기준을 가지고 제작.
- intra-cluster(군집 내 거리): 군집 사이의 데이터들의 거리는 가까울수록 좋음
- inter-cluster(군집 간 거리): 각각의 군집 사이의 거리는 멀수록 좋음
- 클러스터링 활용 예시
- 목적: 수많은 양의 데이터를 몇 개의 그룹으로 묶어서 전체 특성 파악
- 장점: 모든 데이터를 확인하지 않아도 전체 데이터 특성을 이해 가능
- 예시:
- 1년간의 뉴스 데이터를 클러스터링하여 그 해의 주요 뉴스 토픽 찾기
- 1. 요약 및 시각화 (Summarization)
2. 개인과제 해설
- 라이브러리 실행 및 데이터 불러오기
|
# 라이브러리 실행
import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report
|
![]() |
|
# 데이터 불러오기
df = pd.read_csv("data.csv")
df.info()
|
- 필수1. 기초통계
| 필수1 문제 | 필수 1 답안 |
|
- Breast Cancer 데이터셋의 종양 특성들을 카테고리별로 **진단 결과(diagnosis)**에 따라 분석해보세요.
각 카테고리에 속한 특성들의 **평균과 중앙값**을 구하고 해석해주세요.
1. **크기/형태 관련 특성의 기초통계**
- radius_mean, perimeter_mean, area_mean에 대한 진단별 평균과 중앙값을 구하세요.
2. **표면 특성의 기초통계**
- texture_mean, smoothness_mean에 대한 진단별 평균과 중앙값을 구하세요.
3. **형태 복잡도 특성의 기초통계**
- compactness_mean, concavity_mean, concave points_mean에 대한 진단별 평균과 중앙값을 구하세요.
4. **구조적 특성의 기초통계**
- symmetry_mean, fractal_dimension_mean에 대한 진단별 평균과 중앙값을 구하세요.
- **유의 사항**
- 결과는 **소수점 둘째자리**까지 표현해주세요.
- 각 카테고리별로 **간단한 해석**을 덧붙여주세요.
|
|
|
# 필수 1. 기초 통계
def get_category_stats(df, features):
results = []
for feature in features:
# 진단별 평균 계산
means = df.groupby('diagnosis')[feature].mean().round(2)
# 진단별 중앙값 계산
medians = df.groupby('diagnosis')[feature].median().round(2)
results.append({
'feature': feature,
'B_mean': means['B'],
'B_median': medians['B'],
'M_mean': means['M'],
'M_median': medians['M'],
'diff_mean': (means['M'] - means['B']).round(2)
})
return pd.DataFrame(results)
# 카테고리별 특성 정의
size_shape = ['radius_mean', 'perimeter_mean', 'area_mean']
surface = ['texture_mean', 'smoothness_mean']
morphological = ['compactness_mean', 'concavity_mean', 'concave points_mean']
structural = ['symmetry_mean', 'fractal_dimension_mean']
# 각 카테고리별 분석 수행 및 결과 출력
print("1. 크기/형태 관련 특성 통계량")
print("-" * 50)
size_results = get_category_stats(df, size_shape)
print("\n양성(B) 종양:")
for _, row in size_results.iterrows():
print(f"* {row['feature']}:")
print(f" 평균: {row['B_mean']}, 중앙값: {row['B_median']}")
print("\n악성(M) 종양:")
for _, row in size_results.iterrows():
print(f"* {row['feature']}:")
print(f" 평균: {row['M_mean']}, 중앙값: {row['M_median']}")
print("\n2. 표면 특성 통계량")
print("-" * 50)
surface_results = get_category_stats(df, surface)
print("\n양성(B) 종양:")
for _, row in surface_results.iterrows():
print(f"* {row['feature']}:")
print(f" 평균: {row['B_mean']}, 중앙값: {row['B_median']}")
print("\n악성(M) 종양:")
for _, row in surface_results.iterrows():
print(f"* {row['feature']}:")
print(f" 평균: {row['M_mean']}, 중앙값: {row['M_median']}")
print("\n3. 형태 복잡도 특성 통계량")
print("-" * 50)
morphological_results = get_category_stats(df, morphological)
print("\n양성(B) 종양:")
for _, row in morphological_results.iterrows():
print(f"* {row['feature']}:")
print(f" 평균: {row['B_mean']}, 중앙값: {row['B_median']}")
print("\n악성(M) 종양:")
for _, row in morphological_results.iterrows():
print(f"* {row['feature']}:")
print(f" 평균: {row['M_mean']}, 중앙값: {row['M_median']}")
print("\n4. 구조적 특성 통계량")
print("-" * 50)
structural_results = get_category_stats(df, structural)
print("\n양성(B) 종양:")
for _, row in structural_results.iterrows():
print(f"* {row['feature']}:")
print(f" 평균: {row['B_mean']}, 중앙값: {row['B_median']}")
print("\n악성(M) 종양:")
for _, row in structural_results.iterrows():
print(f"* {row['feature']}:")
print(f" 평균: {row['M_mean']}, 중앙값: {row['M_median']}")
|
1. 크기/형태 관련 특성 통계량 -------------------------------------------------- 양성(B) 종양: * radius_mean: 평균: 12.15, 중앙값: 12.2 * perimeter_mean: 평균: 78.08, 중앙값: 78.18 * area_mean: 평균: 462.79, 중앙값: 458.4 악성(M) 종양: * radius_mean: 평균: 17.46, 중앙값: 17.33 * perimeter_mean: 평균: 115.37, 중앙값: 114.2 * area_mean: 평균: 978.38, 중앙값: 932.0 2. 표면 특성 통계량 -------------------------------------------------- 양성(B) 종양: * texture_mean: 평균: 17.91, 중앙값: 17.39 * smoothness_mean: 평균: 0.09, 중앙값: 0.09 악성(M) 종양: * texture_mean: 평균: 21.6, 중앙값: 21.46 * smoothness_mean: 평균: 0.1, 중앙값: 0.1 3. 형태 복잡도 특성 통계량 -------------------------------------------------- 양성(B) 종양: * compactness_mean: 평균: 0.08, 중앙값: 0.08 * concavity_mean: 평균: 0.05, 중앙값: 0.04 * concave points_mean: 평균: 0.03, 중앙값: 0.02 악성(M) 종양: * compactness_mean: 평균: 0.15, 중앙값: 0.13 * concavity_mean: 평균: 0.16, 중앙값: 0.15 * concave points_mean: 평균: 0.09, 중앙값: 0.09 4. 구조적 특성 통계량 -------------------------------------------------- 양성(B) 종양: * symmetry_mean: 평균: 0.17, 중앙값: 0.17 * fractal_dimension_mean: 평균: 0.06, 중앙값: 0.06 악성(M) 종양: * symmetry_mean: 평균: 0.19, 중앙값: 0.19 * fractal_dimension_mean: 평균: 0.06, 중앙값: 0.06 |
- 필수 2. 통계적 가설검정 1(t-test)
| 필수2 문제 | 필수2 답안 |
|
|
|
# 필수 2. 통계적 가설검정 1
def perform_ttest_by_category(df, features):
results = []
for feature in features:
# 양성과 악성 그룹 나누기
benign = df[df['diagnosis'] == 'B'][feature]
malignant = df[df['diagnosis'] == 'M'][feature]
# T-test 수행
t_stat, p_value = stats.ttest_ind(benign, malignant)
# 평균값 계산
mean_diff = malignant.mean() - benign.mean()
results.append({
'feature': feature,
't_score': t_stat,
'p_value': p_value,
'mean_benign': benign.mean(),
'mean_malignant': malignant.mean(),
'mean_difference': mean_diff
})
return pd.DataFrame(results)
# 카테고리별 특성 정의
size_shape = ['radius_mean', 'perimeter_mean', 'area_mean']
surface = ['texture_mean', 'smoothness_mean']
morphological = ['compactness_mean', 'concavity_mean', 'concave points_mean']
structural = ['symmetry_mean', 'fractal_dimension_mean']
# 각 카테고리별 분석 수행 및 결과 출력
print("1. 크기/형태 관련 특성 분석")
print("-" * 50)
size_results = perform_ttest_by_category(df, size_shape)
print("\n크기/형태 특성 T-test 결과:")
print(size_results.round(4))
print("\n2. 표면 특성 분석")
print("-" * 50)
surface_results = perform_ttest_by_category(df, surface)
print("\n표면 특성 T-test 결과:")
print(surface_results.round(4))
print("\n3. 형태 복잡도 특성 분석")
print("-" * 50)
morphological_results = perform_ttest_by_category(df, morphological)
print("\n형태 복잡도 특성 T-test 결과:")
print(morphological_results.round(4))
print("\n4. 구조적 특성 분석")
print("-" * 50)
structural_results = perform_ttest_by_category(df, structural)
print("\n구조적 특성 T-test 결과:")
print(structural_results.round(4))
# 종합 분석: 각 카테고리에서 가장 영향력 있는 특성 찾기
def get_most_significant_feature(results):
return results.loc[results['t_score'].abs().idxmax()]
print("\n\n종합 분석")
print("=" * 50)
print("\n각 카테고리별 가장 영향력 있는 특성:")
categories = {
'크기/형태': size_results,
'표면': surface_results,
'형태 복잡도': morphological_results,
'구조적': structural_results
}
for category_name, results in categories.items():
most_sig = get_most_significant_feature(results)
print(f"\n{category_name} 카테고리:")
print(f"- 가장 영향력 있는 특성: {most_sig['feature']}")
print(f"- t-score: {most_sig['t_score']:.4f}")
print(f"- p-value: {most_sig['p_value']:.4f}")
print(f"- 평균 차이: {most_sig['mean_difference']:.4f}")
|
1. 크기/형태 관련 특성 분석 -------------------------------------------------- 크기/형태 특성 T-test 결과: feature t_score p_value mean_benign mean_malignant \ 0 radius_mean -25.4358 0.0 12.1465 17.4628 1 perimeter_mean -26.4052 0.0 78.0754 115.3654 2 area_mean -23.9387 0.0 462.7902 978.3764 mean_difference 0 5.3163 1 37.2900 2 515.5862 2. 표면 특성 분석 -------------------------------------------------- 표면 특성 T-test 결과: feature t_score p_value mean_benign mean_malignant \ 0 texture_mean -10.8672 0.0 17.9148 21.6049 1 smoothness_mean -9.1461 0.0 0.0925 0.1029 mean_difference 0 3.6901 1 0.0104 3. 형태 복잡도 특성 분석 -------------------------------------------------- 형태 복잡도 특성 T-test 결과: feature t_score p_value mean_benign mean_malignant \ 0 compactness_mean -17.6984 0.0 0.0801 0.1452 1 concavity_mean -23.1040 0.0 0.0461 0.1608 2 concave points_mean -29.3543 0.0 0.0257 0.0880 mean_difference 0 0.0651 1 0.1147 2 0.0623 4. 구조적 특성 분석 -------------------------------------------------- 구조적 특성 T-test 결과: feature t_score p_value mean_benign mean_malignant \ 0 symmetry_mean -8.3383 0.0000 0.1742 0.1929 1 fractal_dimension_mean 0.3057 0.7599 0.0629 0.0627 mean_difference 0 0.0187 1 -0.0002 종합 분석 ================================================== 각 카테고리별 가장 영향력 있는 특성: 크기/형태 카테고리: - 가장 영향력 있는 특성: perimeter_mean - t-score: -26.4052 - p-value: 0.0000 - 평균 차이: 37.2900 표면 카테고리: - 가장 영향력 있는 특성: texture_mean - t-score: -10.8672 - p-value: 0.0000 - 평균 차이: 3.6901 형태 복잡도 카테고리: - 가장 영향력 있는 특성: concave points_mean - t-score: -29.3543 - p-value: 0.0000 - 평균 차이: 0.0623 구조적 카테고리: - 가장 영향력 있는 특성: symmetry_mean - t-score: -8.3383 - p-value: 0.0000 - 평균 차이: 0.0187 |
- 필수3. 통계적 가설검정2(ANOVA)
필수 3. 통계적 가설검정 2
|
필수 3 답안
|
|
from scipy import stats
import pandas as pd
def perform_anova_by_category(df, base_features):
results = []
for feature in base_features:
# 세 측정치 추출
mean_vals = df[f'{feature}_mean']
se_vals = df[f'{feature}_se']
worst_vals = df[f'{feature}_worst']
# ANOVA 수행
f_stat, p_value = stats.f_oneway(mean_vals, se_vals, worst_vals)
# 평균값 계산
results.append({
'feature': feature,
'f_statistic': f_stat,
'p_value': p_value,
'mean_mean': mean_vals.mean(),
'mean_se': se_vals.mean(),
'mean_worst': worst_vals.mean(),
'max_diff': max(abs(mean_vals.mean() - se_vals.mean()),
abs(mean_vals.mean() - worst_vals.mean()),
abs(se_vals.mean() - worst_vals.mean()))
})
return pd.DataFrame(results)
# 데이터프레임에서 양성 / 음성 분리 (열 이름 맞게 수정)
benign_df = df[df['diagnosis'] == 'B'] # 0: Benign
malignant_df = df[df['diagnosis'] == 'M'] # 1: Malignant
# 카테고리 정의 (기존 동일)
size_shape = ['radius', 'perimeter', 'area']
surface = ['texture', 'smoothness']
morphological = ['compactness', 'concavity', 'concave points']
structural = ['symmetry', 'fractal_dimension']
# 양성 / 음성 각각에 대해 수행
groups = {
"Benign(음성)": benign_df,
"Malignant(양성)": malignant_df
}
for group_name, group_df in groups.items():
print(f"\n\n===== {group_name} 그룹 ANOVA 분석 =====")
print("\n1. 크기/형태 관련 특성 분석")
size_results = perform_anova_by_category(group_df, size_shape)
print(size_results.round(4))
print("\n2. 표면 특성 분석")
surface_results = perform_anova_by_category(group_df, surface)
print(surface_results.round(4))
print("\n3. 형태 복잡도 특성 분석")
morphological_results = perform_anova_by_category(group_df, morphological)
print(morphological_results.round(4))
print("\n4. 구조적 특성 분석")
structural_results = perform_anova_by_category(group_df, structural)
print(structural_results.round(4))
# 해당 그룹에서 카테고리별 가장 큰 차이를 보이는 feature 출력
def get_most_different_feature(results):
return results.loc[results['f_statistic'].abs().idxmax()]
print("\n▶ 카테고리별 가장 큰 측정치 차이를 보이는 특성")
categories = {
'크기/형태': size_results,
'표면': surface_results,
'형태 복잡도': morphological_results,
'구조적': structural_results
}
for category_name, results in categories.items():
most_diff = get_most_different_feature(results)
print(f"\n[{category_name}]")
print(f"- 특성: {most_diff['feature']}")
print(f"- F-statistic: {most_diff['f_statistic']:.4f}")
print(f"- p-value: {most_diff['p_value']:.4f}")
print(f"- mean 값: {most_diff['mean_mean']:.4f}")
print(f"- se 값: {most_diff['mean_se']:.4f}")
print(f"- worst 값: {most_diff['mean_worst']:.4f}")
|
===== Benign(음성) 그룹 ANOVA 분석 ===== 1. 크기/형태 관련 특성 분석 feature f_statistic p_value mean_mean mean_se mean_worst max_diff 0 radius 7877.9312 0.0 12.1465 0.2841 13.3798 13.0957 1 perimeter 7235.8446 0.0 78.0754 2.0003 87.0059 85.0056 2 area 1962.8767 0.0 462.7902 21.1351 558.8994 537.7643 2. 표면 특성 분석 feature f_statistic p_value mean_mean mean_se mean_worst max_diff 0 texture 3098.8495 0.0 17.9148 1.2204 23.5151 22.2947 1 smoothness 6707.3312 0.0 0.0925 0.0072 0.1250 0.1178 3. 형태 복잡도 특성 분석 feature f_statistic p_value mean_mean mean_se mean_worst \ 0 compactness 720.2337 0.0 0.0801 0.0214 0.1827 1 concavity 271.7046 0.0 0.0461 0.0260 0.1662 2 concave points 774.2281 0.0 0.0257 0.0099 0.0744 max_diff 0 0.1612 1 0.1402 2 0.0646 4. 구조적 특성 분석 feature f_statistic p_value mean_mean mean_se mean_worst \ 0 symmetry 7056.4308 0.0 0.1742 0.0206 0.2702 1 fractal_dimension 6951.1999 0.0 0.0629 0.0036 0.0794 max_diff 0 0.2497 1 0.0758 ▶ 카테고리별 가장 큰 측정치 차이를 보이는 특성 [크기/형태] - 특성: radius - F-statistic: 7877.9312 - p-value: 0.0000 - mean 값: 12.1465 - se 값: 0.2841 - worst 값: 13.3798 [표면] - 특성: smoothness - F-statistic: 6707.3312 - p-value: 0.0000 - mean 값: 0.0925 - se 값: 0.0072 - worst 값: 0.1250 [형태 복잡도] - 특성: concave points - F-statistic: 774.2281 - p-value: 0.0000 - mean 값: 0.0257 - se 값: 0.0099 - worst 값: 0.0744 [구조적] - 특성: symmetry - F-statistic: 7056.4308 - p-value: 0.0000 - mean 값: 0.1742 - se 값: 0.0206 - worst 값: 0.2702 ===== Malignant(양성) 그룹 ANOVA 분석 ===== 1. 크기/형태 관련 특성 분석 feature f_statistic p_value mean_mean mean_se mean_worst max_diff 0 radius 2651.8503 0.0 17.4628 0.6091 21.1348 20.5257 1 perimeter 2492.3763 0.0 115.3654 4.3239 141.3703 137.0464 2 area 605.8169 0.0 978.3764 72.6724 1422.2863 1349.6139 2. 표면 특성 분석 feature f_statistic p_value mean_mean mean_se mean_worst max_diff 0 texture 3044.7330 0.0 21.6049 1.2109 29.3182 28.1073 1 smoothness 4935.4538 0.0 0.1029 0.0068 0.1448 0.1381 3. 형태 복잡도 특성 분석 feature f_statistic p_value mean_mean mean_se mean_worst \ 0 compactness 600.3386 0.0 0.1452 0.0323 0.3748 1 concavity 720.2198 0.0 0.1608 0.0418 0.4506 2 concave points 1331.1311 0.0 0.0880 0.0151 0.1822 max_diff 0 0.3425 1 0.4088 2 0.1672 4. 구조적 특성 분석 feature f_statistic p_value mean_mean mean_se mean_worst \ 0 symmetry 2280.0136 0.0 0.1929 0.0205 0.3235 1 fractal_dimension 2401.6841 0.0 0.0627 0.0041 0.0915 max_diff 0 0.3030 1 0.0875 ▶ 카테고리별 가장 큰 측정치 차이를 보이는 특성 [크기/형태] - 특성: radius - F-statistic: 2651.8503 - p-value: 0.0000 - mean 값: 17.4628 - se 값: 0.6091 - worst 값: 21.1348 [표면] - 특성: smoothness - F-statistic: 4935.4538 - p-value: 0.0000 - mean 값: 0.1029 - se 값: 0.0068 - worst 값: 0.1448 [형태 복잡도] - 특성: concave points - F-statistic: 1331.1311 - p-value: 0.0000 - mean 값: 0.0880 - se 값: 0.0151 - worst 값: 0.1822 [구조적] - 특성: fractal_dimension - F-statistic: 2401.6841 - p-value: 0.0000 - mean 값: 0.0627 - se 값: 0.0041 - worst 값: 0.0915 |
- 필수4. 머신러닝
필수 4. 머신러닝 1
|
|
# 필수 4. 머신러닝 1
# 독립변수(X)와 종속변수(Y) 준비
X = df['radius_mean'].values.reshape(-1, 1) # 2D array 형태로 변환
Y = df['area_mean'].values
# 선형 회귀 모델 학습
model = LinearRegression()
model.fit(X, Y)
# 결정계수(R²) 계산
r_squared = model.score(X, Y)
# 회귀식 계수
slope = model.coef_[0] #기울기 가중치
intercept = model.intercept_
# radius_mean이 25일 때의 예측
new_radius = np.array([[25]]) #판다스로 만들어도 무관하다.
predicted_area = model.predict(new_radius)[0]
# 시각화
plt.figure(figsize=(10, 6))
plt.scatter(X, Y, color='blue', alpha=0.5, label='실제 데이터')
plt.plot(X, model.predict(X), color='red', label='회귀선')
plt.scatter(new_radius, predicted_area, color='green', s=100, label='예측값')
plt.xlabel('radius_mean')
plt.ylabel('area_mean')
plt.title('Radius와 Area의 선형 회귀 관계')
plt.legend()
plt.grid(True)
plt.show()
# 결과 출력
print("1. 결정계수(R²):", round(r_squared, 4))
print("\n2. 회귀식:")
print(f"area_mean = {round(slope, 2)} × radius_mean + {round(intercept, 2)}")
print("\n3. 예측 결과:")
print(f"radius_mean이 25일 때의 예측 area_mean: {round(predicted_area, 2)}")
|
![]() |
| 1. 결정계수(R²): 0.9749 2. 회귀식: area_mean = 98.6 × radius_mean + -738.04 3. 예측 결과: radius_mean이 25일 때의 예측 area_mean: 1726.92 |
도전1. 머신러닝 2
|
도전 1 답안 3. Feature Importance 해석 - perimeter_mean가 0.3541로 가장 중요한 특성으로 나타났습니다. - 이는 종양의 크기/형태 특성 중에서 perimeter_mean가 악성 여부를 판단하는데 가장 큰 영향을 미친다는 것을 의미합니다. |
|
#도전 1. 머신러닝 2
# 크기/형태 관련 특성 선택
X = df[['radius_mean', 'perimeter_mean', 'area_mean']]
y = df['diagnosis']
# 레이블 인코딩
le = LabelEncoder()
y = le.fit_transform(y)
# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# RandomForest 모델 학습
rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(X_train, y_train)
# 모델 평가
y_pred = rf_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
# Feature Importance 시각화
importances = rf_model.feature_importances_
feature_names = X.columns
plt.figure(figsize=(10, 6))
bars = plt.bar(feature_names, importances)
plt.title('Feature Importance in Random Forest Model')
plt.xlabel('Features')
plt.ylabel('Importance')
plt.xticks(rotation=45)
# 중요도 값 표시
for bar in bars:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width()/2., height,
f'{height:.4f}',
ha='center', va='bottom')
plt.tight_layout()
plt.show()
# 결과 출력
print("1. 모델 정확도:", round(accuracy * 100, 2), "%")
print("\n3. Feature Importance 수치:")
importance_df = pd.DataFrame({
'Feature': feature_names,
'Importance': importances
}).sort_values('Importance', ascending=False)
print(importance_df)
print("\nFeature Importance 해석:")
most_important = importance_df.iloc[0]
print(f"- {most_important['Feature']}가 {most_important['Importance']:.4f}로 가장 중요한 특성으로 나타났습니다.")
print(f"- 이는 종양의 크기/형태 특성 중에서 {most_important['Feature']}가")
print(" 악성 여부를 판단하는데 가장 큰 영향을 미친다는 것을 의미합니다.")
|
![]() |
| 1. 모델 정확도: 91.81 % 3. Feature Importance 수치: Feature Importance 1 perimeter_mean 0.354107 0 radius_mean 0.338884 2 area_mean 0.307009 Feature Importance 해석: - perimeter_mean가 0.3541로 가장 중요한 특성으로 나타났습니다. - 이는 종양의 크기/형태 특성 중에서 perimeter_mean가 악성 여부를 판단하는데 가장 큰 영향을 미친다는 것을 의미합니다. |
도전 2. 머신러닝 3
|
|
# 도전 2. 머신러닝 3
# 형태 복잡도 특성 선택
X = df[['compactness_mean', 'concavity_mean', 'concave points_mean']]
y = df['diagnosis']
# 레이블 인코딩
le = LabelEncoder()
y = le.fit_transform(y)
# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 로지스틱 회귀 모델 학습
log_model = LogisticRegression(random_state=42)
log_model.fit(X_train, y_train)
# 모델 평가
y_pred = log_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
# 계수 시각화
coefficients = log_model.coef_[0]
feature_names = X.columns
plt.figure(figsize=(10, 6))
colors = ['red' if c < 0 else 'blue' for c in coefficients]
bars = plt.bar(feature_names, coefficients, color=colors)
plt.title('Logistic Regression Coefficients')
plt.xlabel('Features')
plt.ylabel('Coefficient Value')
plt.xticks(rotation=45)
# 계수 값 표시
for bar in bars:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width()/2., height,
f'{height:.2f}',
ha='center', va='bottom' if height > 0 else 'top')
plt.show()
# 새로운 종양 데이터에 대한 예측
new_tumor = np.array([[0.1, 0.1, 0.05]])
probabilities = log_model.predict_proba(new_tumor)
# 결과 출력
print("1. 모델 정확도:", round(accuracy * 100, 2), "%")
# [양성= 86.5, 악성 .13.5]
print("\n3. 새로운 종양의 예측 확률:")
print("양성(B) 확률:", round(probabilities[0][0] * 100, 2), "%")
print("악성(M) 확률:", round(probabilities[0][1] * 100, 2), "%")
|
![]() |
| 1. 모델 정확도: 82.46 % 3. 새로운 종양의 예측 확률: 양성(B) 확률: 61.81 % 악성(M) 확률: 38.19 % |
'빅데이터 QAQC_3기 > 빅데이터 QAQC_3기 TIL' 카테고리의 다른 글
| TIL_251110 (1) | 2025.11.10 |
|---|---|
| TIL_251107 (0) | 2025.11.07 |
| TIL_251103 (0) | 2025.11.03 |
| TIL_251030 (0) | 2025.10.30 |
| TIL_251029 (1) | 2025.10.29 |







