320x100
728x90
해당내용은 정보문화사 파이썬 머신러닝 판다스 데이터 분석 교재를 기준으로 했으며, 책 소개는 아래를 참고하시기 바랍니다.
데이터분석가 관련 도서 https://nesaram-health-1story.tistory.com/136
데이터 분석가 관련 추천도서
데이터 분석가는 보고서작성, 시각화, 통찰력, 비즈니스/도메인 지식의 능력이 필요하다.여기서 비즈니스/도메인 지식은 특정 산업이나 회사의 주요 활동 영역에 대한 이해를 말하며, 쉽게 말해
nesaram-health-1story.tistory.com
# 기본 라이브러리 불러오기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
'''
[Step 1] 데이터 준비 - Seaborn에서 제공하는 titanic 데이터셋 가져오기
'''
# load_dataset 함수를 사용하여 데이터프레임으로 변환
df = sns.load_dataset('data/titanic')
df.head()
'''
[Step 2] 데이터 탐색
'''
# 데이터 자료형 확인
df.info()
<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 object
9 who 891 non-null object
10 adult_male 891 non-null bool
11 deck 203 non-null object
12 embark_town 889 non-null object
13 alive 891 non-null object
14 alone 891 non-null bool
dtypes: bool(2), float64(2), int64(4), object(7)
memory usage: 92.4+ KB
# 데이터 통계 요약정보 확인
df.describe() #fare 값의 최대값이 512로 평균이나 중앙값에 비해 매우 큰값으로 검토필요
# 데이터 통계 요약정보 확인 (범주형)
df.describe(include='object')
# 누락 데이터 확인
df.isnull().sum() # age 177개 누락, deck 688개 누락값 으로 결측치 처리 필요
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
# 중복 데이터 확인
df.duplicated().sum() #107개 행이 중복으로 제거 필요
107
# 목표변수 가 생존여부이므로 목표변수의 분포확인이 중요하다
df['survived'].value_counts()
survived
0 549
1 342
Name: count, dtype: int64
# 목표변수 - 시각화
sns.countplot(data=df, x='survived'); #생존자(1) 비율이 낮다 불균형문제대응:오버샘플링, 언더샘플링
# 시각화
g = sns.FacetGrid(df, col='survived', row='pclass', hue='sex')
g.map(sns.kdeplot, 'age', alpha=0.5, fill=True)
g.add_legend(); #1등석에선 남성이 여성보다 생존률이 낮고 2등석에선 여성이 생존율이 높다
# 시각화 동승한 부모 및 자식의 수가 3명 이하일때가 생존율이 높다
sns.displot(x='sibsp', kind='hist', hue='survived', data=df, multiple='fill');
# 시각화 동승자가 5명이상인 경우 생존자가 없다. 4명이하는 생존자가 있다.
sns.displot(x='parch', kind='hist', hue='survived', data=df, multiple='fill');
# 시각화
sns.boxplot(x='embarked', y='age', hue='survived', data=df);
'''
[Step 3] 데이터 전처리
'''
# 중복 데이터 제거
print('중복 제거 이전: ', df.shape)
df = df.drop_duplicates()
print('중복 제거 이후: ', df.shape)
중복 제거 이전: (891, 15)
중복 제거 이후: (784, 15)
# NaN값이 많은 deck 열을 삭제, embarked와 내용이 겹치는 embark_town 열을 삭제
rdf = df.drop(['deck', 'embark_town'], axis=1)
rdf.columns.values
array(['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare',
'embarked', 'class', 'who', 'adult_male', 'alive', 'alone'],
dtype=object)
# age 열에 나이 데이터가 없는 모든 행을 삭제 - NaN 값 DataFrame에서'age'열에 결측값(NaN)이 있는 행 모두 제거하는 기능
# how='any''age' 열에서 NaN이 하나라도 존재하면 해당 행을 삭제 axis=0 (기본값) 행을 기준으로 제거
rdf = rdf.dropna(subset=['age'], how='any', axis=0)
print(len(rdf))
678
# embarked 열의 NaN값을 승선도시 중에서 가장 많이 출현한 값으로 치환하기
# 'embarked' 열에서 가장 많이 등장한 값(최빈값, Mode)을 찾는 기능
most_freq = rdf['embarked'].value_counts(dropna=True).idxmax() #dropna=True 옵션은 NaN(결측값)을 무시하고 계산
print(most_freq)
S
# mode 메소드 활용 (최빈값) 'embarked' 열에서 가장 많이 등장한 값(최빈값, Mode)을 찾는 기능
most_freq2 = rdf['embarked'].mode()[0] # mode() 최빈값(Mode, 가장 많이 등장한 값)을 리스트 형태로 반환
print(most_freq2)
S
# describe 메소드 활용 (최빈값)
# describe() 함수는 데이터의 기초 통계 요약을 제공하는 함수로, 기본적으로 숫자형(수치형) 데이터에 대한
# 통계를 출력한다.하지만 include='object' 옵션을 추가하면 문자열(범주형) 데이터의 통계를 출력할 수 있다.
rdf.describe(include='object')
# 최빈값으로 누락 데이터 치환하기 'embarked' 열에서 결측값(NaN)을 최빈값(most_freq)으로 채우는 역할
rdf['embarked'] = rdf['embarked'].fillna(most_freq)
# 결측치 확인하기
rdf.isnull().sum()
survived 0
pclass 0
sex 0
age 0
sibsp 0
parch 0
fare 0
embarked 0
class 0
who 0
adult_male 0
alive 0
alone 0
dtype: int64
'''
[Step 4] 변수 선택
'''
# 분석에 활용할 열(특성)을 선택
ndf = rdf[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'embarked']]
ndf.head()
# KNN 모델을 적용하려면 데이터 전처리 → 학습 데이터 준비 → 모델 학습 → 예측 및 평가의 단계를 거쳐야.
# 원핫인코딩 - 범주형 데이터를 모형이 인식할 수 있도록 숫자형으로 변환
onehot_sex = pd.get_dummies(ndf['sex']) #기존 sex열을 female, male 변환된 열을 추가
ndf = pd.concat([ndf, onehot_sex], axis=1)
onehot_embarked = pd.get_dummies(ndf['embarked'], prefix='town') #embarked 열을 town으로 시작하는 값으로 열추가
ndf = pd.concat([ndf, onehot_embarked], axis=1)
ndf = ndf.drop(['sex', 'embarked'], axis=1)
ndf.head()
'''
[Step 5] 데이터셋 구분 - 훈련용(train data)/ 검증용(test data)
'''
#KNN 모델을 학습하기 전에 데이터를 정규화(Normalization)하고, 학습(train)과 테스트(test) 데이터로 분할하는 과정
# 속성(변수) 선택
X = ndf[['pclass', 'age', 'sibsp', 'parch', 'female', 'male',
'town_C', 'town_Q', 'town_S']] #독립 변수 X
y = ndf['survived'] #종속 변수 Y survived 열 → 모델이 예측해야 하는 목표 변수
# 설명 변수 데이터를 정규화(normalization)각 변수의 값이 서로 다른 단위와 범위를 가질 때,
# 이를 동일한 기준으로 맞추는 과정 KNN과 같은 거리 기반 알고리즘은 변수의 크기에 영향을 받으므로 정규화가 필수
from sklearn import preprocessing
# StandardScaler()평균을 0,표준편차를 1로 변환(표준 정규 분포로 변환)데이터의 스케일을 맞춰 특정변수의 영향력을 줄임
# 정규화를 하면 나이(age)와 같은 큰 숫자가 다른 변수(pclass 등)에 비해 모델에 영향을 주지 않도록 조정 가능
X = preprocessing.StandardScaler().fit(X).transform(X)
# train data 와 test data로 구분(7:3 비율)
from sklearn.model_selection import train_test_split
# 데이터를 학습용(Train) 70% / 테스트용(Test) 30% 비율로 분할
# random_state=10 실행할 때마다 같은 결과가 나오도록 랜덤 시드를 고정
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=10)
# 학습 데이터는 모델 훈련에 사용하고, 테스트 데이터는 성능 평가에 사용
print('train data 개수: ', X_train.shape)
print('test data 개수: ', X_test.shape)
train data 개수: (474, 9)
test data 개수: (204, 9)
'''
[Step 6] KNN 분류 모형 - sklearn 사용
'''
# 모델을 학습하고, 테스트 데이터를 예측하는 과정, 생존 여부(survived)를 예측하고 실제값(y_test)과 비교하는 단계
# 거리 기반 알고리즘이므로 데이터 정규화(StandardScaler)를 먼저 진행해야 한다.
# sklearn 라이브러리에서 KNN 분류 모형 가져오기
from sklearn.neighbors import KNeighborsClassifier
# 모형 객체 생성 (k=5로 설정) 보통 k=3~7 사이의 값을 선택하며, 적절한 K 값은 실험적으로 찾아야 함
knn = KNeighborsClassifier(n_neighbors=5)
# train data를 가지고 모형 학습
knn.fit(X_train, y_train)
# test data를 가지고 y_hat을 예측 (분류) 학습한 KNN 모델을 사용하여 테스트 데이터(X_test)를 예측
y_hat = knn.predict(X_test) # y_hat → KNN 모델이 예측한 생존 여부
print(y_hat[0:10])
print(y_test.values[0:10]) #예측값(y_hat)과 실제값(y_test)이 얼마나 일치하는지 확인
# 예측값과 실제값을 비교하여 모델의 성능을 평가할 수 있음
[0 1 0 1 0 0 1 1 1 1]
[1 1 0 1 0 1 1 1 1 0]
# 일치하는 개수: 7개 (위치 1, 3, 5, 6, 7, 8), 틀린 개수: 3개 (위치 0, 4, 9)
accuracy = (7 / 10) * 100
print(f'모델 정확도: {accuracy:.2f}%') # 모델이 70%의 정확도로 생존 여부를 예측함
모델 정확도: 70.00%
'''
[Step 6-1] KNN 분류 모형 - sklearn 사용
'''
# 모델을 학습하고, 테스트 데이터를 예측하는 과정, 생존 여부(survived)를 예측하고 실제값(y_test)과 비교하는 단계
# 거리 기반 알고리즘이므로 데이터 정규화(StandardScaler)를 먼저 진행해야 한다.
# sklearn 라이브러리에서 KNN 분류 모형 가져오기
from sklearn.neighbors import KNeighborsClassifier
# 모형 객체 생성 (k=7로 설정) 보통 k=3~7 사이의 값을 선택하며, 적절한 K 값은 실험적으로 찾아야 함
knn = KNeighborsClassifier(n_neighbors=7) #7값적용
# train data를 가지고 모형 학습
knn.fit(X_train, y_train)
# test data를 가지고 y_hat을 예측 (분류) 학습한 KNN 모델을 사용하여 테스트 데이터(X_test)를 예측
y_hat = knn.predict(X_test) # y_hat → KNN 모델이 예측한 생존 여부
print(y_hat[0:10])
print(y_test.values[0:10]) #예측값(y_hat)과 실제값(y_test)이 얼마나 일치하는지 확인
# 예측값과 실제값을 비교하여 모델의 성능을 평가할 수 있음
[0 1 0 1 0 0 1 1 1 1]
[1 1 0 1 0 1 1 1 1 0]
# 일치하는 개수: 8개, 틀린 개수: 2개 (위치 5, 9)
accuracy = (8 / 10) * 100
print(f'모델 정확도: {accuracy:.2f}%') # 모델이 80%의 정확도로 생존 여부를 예측함
모델 정확도: 80.00%
'''
[Step 6-2] KNN 분류 모형 - sklearn 사용
'''
# 모델을 학습하고, 테스트 데이터를 예측하는 과정, 생존 여부(survived)를 예측하고 실제값(y_test)과 비교하는 단계
# 거리 기반 알고리즘이므로 데이터 정규화(StandardScaler)를 먼저 진행해야 한다.
# sklearn 라이브러리에서 KNN 분류 모형 가져오기
from sklearn.neighbors import KNeighborsClassifier
# 모형 객체 생성 (k=3로 설정) 보통 k=3~7 사이의 값을 선택하며, 적절한 K 값은 실험적으로 찾아야 함
knn = KNeighborsClassifier(n_neighbors=3) #3값적용
# train data를 가지고 모형 학습
knn.fit(X_train, y_train)
# test data를 가지고 y_hat을 예측 (분류) 학습한 KNN 모델을 사용하여 테스트 데이터(X_test)를 예측
y_hat = knn.predict(X_test) # y_hat → KNN 모델이 예측한 생존 여부
print(y_hat[0:10])
print(y_test.values[0:10]) #예측값(y_hat)과 실제값(y_test)이 얼마나 일치하는지 확인
# 예측값과 실제값을 비교하여 모델의 성능을 평가할 수 있음
[0 1 0 1 0 0 1 1 1 1]
[1 1 0 1 0 1 1 1 1 0]
# 일치하는 개수: 7개, 틀린 개수: 3개 (위치 0, 5, 9)
accuracy = (7 / 10) * 100
print(f'모델 정확도: {accuracy:.2f}%') # 모델이 80%의 정확도로 생존 여부를 예측함
모델 정확도: 70.00%
# k 를 7로 했을때 80%
K 값을 5와 7로 설정했을 때, 모델의 정확도를 비교
from sklearn.metrics import accuracy_score
# KNN 모델 학습 및 예측 (k=5)
knn_5 = KNeighborsClassifier(n_neighbors=5)
knn_5.fit(X_train, y_train)
y_hat_5 = knn_5.predict(X_test)
accuracy_5 = accuracy_score(y_test, y_hat_5)
# KNN 모델 학습 및 예측 (k=7)
knn_7 = KNeighborsClassifier(n_neighbors=7)
knn_7.fit(X_train, y_train)
y_hat_7 = knn_7.predict(X_test)
accuracy_7 = accuracy_score(y_test, y_hat_7)
# 결과 출력
print(f'K=5일 때 정확도: {accuracy_5:.4f}')
print(f'K=7일 때 정확도: {accuracy_7:.4f}')
K=5일 때 정확도: 0.7549
K=7일 때 정확도: 0.7696
최적의 K 찾기 - 여러 개의 K를 실험
K=1부터 20까지 여러 개의 값을 실험하여 최적의 K를 찾을 수도 있음.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# 한글 폰트 설정 (Windows 기준 나눔고딕, Mac은 AppleGothic 사용)
plt.rc('font', family='Malgun Gothic') # Windows
# plt.rc('font', family='AppleGothic') # Mac 사용자는 이 줄을 활성화
plt.rcParams['axes.unicode_minus'] = False # 한글 폰트 사용 시 '-' 기호 깨지는 문제 해결
k_values = range(1, 21)
accuracies = []
for k in k_values:
knn = KNeighborsClassifier(n_neighbors=k)
knn.fit(X_train, y_train)
y_hat = knn.predict(X_test)
accuracies.append(accuracy_score(y_test, y_hat))
# 그래프 출력
plt.plot(k_values, accuracies, marker='o')
plt.xlabel('K 값')
plt.ylabel('정확도')
plt.title('K 값에 따른 정확도 변화')
plt.xticks(np.arange(1, 21, 1))
plt.show()
# 모형 성능 평가 - 평가지표 계산
knn_report = metrics.classification_report(y_test, y_hat)
print(knn_report)
precision recall f1-score support
0 0.79 0.86 0.82 123
1 0.76 0.65 0.70 81
accuracy 0.78 204
macro avg 0.77 0.76 0.76 204
weighted avg 0.78 0.78 0.78 204
- 전체적인 정확도는 78%로 준수하지만, 1 클래스(생존자)에 대한 예측 성능이 다소 낮음.
- 1 클래스(생존자)의 Recall이 0.65로 낮기 때문에, 생존자를 놓칠 가능성이 있음.
- 데이터 불균형 문제를 해결하기 위해 샘플링 기법(SMOTE)이나 가중치를 조정하는 방법을 고려할 수 있음.
- K 값을 변경하면서 성능이 더 좋아지는지 실험해볼 필요가 있음.
K=14에서 가장 높은 정확도를 보이지만, 1 클래스(생존자)의 성능을 조금 더 높이려면 다른 방법(K 조정, 데이터 보정 등)을 고려하는 것이 좋음!
K=7로 했을때와 비교하면
- K=7에서는 정확도가 76%로 K=14(78%)보다 낮았음.
- 1 클래스(생존자)의 Recall이 낮아, 생존자를 놓칠 가능성이 큼.
- K=14가 더 높은 정확도를 보였으므로, K=14를 최적의 K로 선택하는 것이 더 적절함.
결론: K=14가 K=7보다 성능이 더 좋으므로, K=14를 선택하는 것이 더 적절함!
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X)
# 데이터 정규화 방법을 StandardScaler() 대신 MinMaxScaler()로 변경하여 KNN 모델의 성능을 테스트하는 방법
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# MinMaxScaler를 사용하여 데이터 정규화 (0~1 범위로 변환)
scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X) # 정규화된 데이터 생성
# train data와 test data로 분할 (7:3 비율)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3, random_state=10)
# MinMaxScaler()는 모든 데이터를 0과 1 사이로 정규화하여 KNN 모델의 거리 계산을 더 효과적으로 수행하도록 함
# KNN 모델 생성 (K=5 설정)
knn = KNeighborsClassifier(n_neighbors=5)
# 학습 데이터로 모델 훈련
knn.fit(X_train, y_train)
# 테스트 데이터를 사용하여 예측 수행
y_hat = knn.predict(X_test)
# 예측값과 실제값 비교 (앞 10개 출력)
print("예측값:", y_hat[:10])
print("실제값:", y_test.values[:10])
# 정확도(Accuracy) 계산
accuracy = accuracy_score(y_test, y_hat)
print(f'KNN 모델 (MinMaxScaler 적용) 정확도: {accuracy:.4f}')
예측값: [0 1 0 1 0 0 1 1 1 1]
실제값: [1 1 0 1 0 1 1 1 1 0]
KNN 모델 (MinMaxScaler 적용) 정확도: 0.7451
# KNN 모델 생성 (K=7 설정)
knn = KNeighborsClassifier(n_neighbors=7)
# 학습 데이터로 모델 훈련
knn.fit(X_train, y_train)
# 테스트 데이터를 사용하여 예측 수행
y_hat = knn.predict(X_test)
print("예측값:", y_hat[:10])
print("실제값:", y_test.values[:10])
# 정확도(Accuracy) 계산
accuracy = accuracy_score(y_test, y_hat)
print(f'KNN 모델 (MinMaxScaler 적용) 정확도: {accuracy:.4f}')
예측값: [0 1 0 1 0 0 1 1 1 1]
실제값: [1 1 0 1 0 1 1 1 1 0]
KNN 모델 (MinMaxScaler 적용) 정확도: 0.7598
# KNN 모델 생성 (K=3 설정)
knn = KNeighborsClassifier(n_neighbors=3)
# 학습 데이터로 모델 훈련
knn.fit(X_train, y_train)
# 테스트 데이터를 사용하여 예측 수행
y_hat = knn.predict(X_test)
print("예측값:", y_hat[:10])
print("실제값:", y_test.values[:10])
# 정확도(Accuracy) 계산
accuracy = accuracy_score(y_test, y_hat)
print(f'KNN 모델 (MinMaxScaler 적용) 정확도: {accuracy:.4f}')
예측값: [1 1 0 1 0 0 1 1 1 1]
실제값: [1 1 0 1 0 1 1 1 1 0]
KNN 모델 (MinMaxScaler 적용) 정확도: 0.7500
# k=7로 설정시 정확도 높음
# 모형 성능 평가 - Confusion Matrix 계산
from sklearn import metrics
knn_matrix = metrics.confusion_matrix(y_test, y_hat)
print(knn_matrix) # k=7로 설정한 값으로 함
[[103 20]
[ 29 52]]
# Confusion Matrix 시각화
plt.figure(figsize=(8, 6))
sns.heatmap(knn_matrix, annot=True, fmt='d', cmap='Blues',
xticklabels=['Negative', 'Positive'],
yticklabels=['Negative', 'Positive'])
plt.title('Confusion Matrix')
plt.ylabel('Actual label')
plt.xlabel('Predicted label')
plt.show()
# 모형 성능 평가 - 평가지표 계산
knn_report = metrics.classification_report(y_test, y_hat)
print(knn_report)
precision recall f1-score support
0 0.78 0.84 0.81 123
1 0.72 0.64 0.68 81
accuracy 0.76 204
macro avg 0.75 0.74 0.74 204
weighted avg 0.76 0.76 0.76 204
# 성능 지표 값
#정확도 (Accuracy) 76%
#평균 정밀도 (macro avg precision) 75%
#평균 재현율 (macro avg recall) 74%
#평균 F1-score (macro avg f1-score) 74%
# 기본 라이브러리 불러오기 SVM분류 (Support Vector Machine, 서포트 벡터 머신)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
'''
[Step 1] 데이터 준비 - Seaborn에서 제공하는 titanic 데이터셋 가져오기
'''
# load_dataset 함수를 사용하여 데이터프레임으로 변환
df = sns.load_dataset('data/titanic')
'''
[Step 2 ~ 3] 데이터 전처리
'''
# 중복 데이터 제거
df = df.drop_duplicates()
# NaN값이 많은 deck 열을 삭제, embarked와 내용이 겹치는 embark_town 열을 삭제
rdf = df.drop(['deck', 'embark_town'], axis=1)
# age 열에 나이 데이터가 없는 모든 행을 삭제 - NaN 값
rdf = rdf.dropna(subset=['age'], how='any', axis=0)
# embarked 열의 NaN값을 승선도시 중에서 가장 많이 출현한 값으로 치환하기
most_freq = rdf['embarked'].mode()[0]
rdf['embarked'] = rdf['embarked'].fillna(most_freq)
'''
[Step 4] 변수 선택
'''
# 분석에 활용할 열(속성)을 선택
ndf = rdf[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'embarked']]
# 원핫인코딩 - 범주형 데이터를 모형이 인식할 수 있도록 숫자형으로 변환
onehot_sex = pd.get_dummies(ndf['sex'])
ndf = pd.concat([ndf, onehot_sex], axis=1)
onehot_embarked = pd.get_dummies(ndf['embarked'], prefix='town')
ndf = pd.concat([ndf, onehot_embarked], axis=1)
ndf = ndf.drop(['sex', 'embarked'], axis=1)
'''
[Step 5] 데이터셋 구분 - 훈련용(train data)/ 검증용(test data)
'''
# 속성(변수) 선택
X = ndf[['pclass', 'age', 'sibsp', 'parch', 'female', 'male',
'town_C', 'town_Q', 'town_S']] #독립 변수 X
y = ndf['survived'] #종속 변수 Y
# 설명 변수 데이터를 정규화(normalization)
from sklearn import preprocessing
X = preprocessing.StandardScaler().fit(X).transform(X)
# train data 와 test data로 구분(7:3 비율)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=10)
print('train data 개수: ', X_train.shape)
print('test data 개수: ', X_test.shape)
train data 개수: (474, 9)
test data 개수: (204, 9)
'''
[Step 6] SVM 분류 모형 - sklearn 사용
'''
# sklearn 라이브러리에서 SVM 분류 모형 가져오기
from sklearn import svm
# 모형 객체 생성 (kernel='rbf' 적용)
svm_model = svm.SVC(kernel='rbf')
# train data를 가지고 모형 학습
svm_model.fit(X_train, y_train)
# test data를 가지고 y_hat을 예측 (분류)
y_hat = svm_model.predict(X_test)
print(y_hat[0:10])
print(y_test.values[0:10])
[1 1 0 1 0 0 0 1 1 1]
[1 1 0 1 0 1 1 1 1 0]
# 모형 성능 평가 - Confusion Matrix 계산
from sklearn import metrics
svm_matrix = metrics.confusion_matrix(y_test, y_hat)
print(svm_matrix)
[[104 19]
[ 24 57]]
# Confusion Matrix 시각화
plt.figure(figsize=(8, 6))
sns.heatmap(svm_matrix, annot=True, fmt='d', cmap='OrRd',
xticklabels=['Negative', 'Positive'],
yticklabels=['Negative', 'Positive'])
plt.title('Confusion Matrix')
plt.ylabel('Actual label')
plt.xlabel('Predicted label')
plt.show()
# 모형 성능 평가 - 평가지표 계산
svm_report = metrics.classification_report(y_test, y_hat)
print(svm_report)
precision recall f1-score support
0 0.81 0.85 0.83 123
1 0.75 0.70 0.73 81
accuracy 0.79 204
macro avg 0.78 0.77 0.78 204
weighted avg 0.79 0.79 0.79 204
# 기본 라이브러리 불러오기 의사결정 나무
from sklearn import metrics
from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
'''
[Step 1] 데이터 준비/ 기본 설정
'''
# Breast Cancer 데이터셋 가져오기 (출처: UCI ML Repository)
breast-cancer-wisconsin/breast-cancer-wisconsin.data'
df = pd.read_csv(uci_path, header=None)
# 열 이름 지정
df.columns = ['id', 'clump', 'cell_size', 'cell_shape', 'adhesion', 'epithlial',
'bare_nuclei', 'chromatin', 'normal_nucleoli', 'mitoses', 'class']
# 데이터셋의 크기
print(df.shape)
(699, 11)
'''
[Step 2] 데이터 탐색
'''
# 데이터 살펴보기
df.sample(5)
# 데이터 자료형 확인
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 699 entries, 0 to 698
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 699 non-null int64
1 clump 699 non-null int64
2 cell_size 699 non-null int64
3 cell_shape 699 non-null int64
4 adhesion 699 non-null int64
5 epithlial 699 non-null int64
6 bare_nuclei 699 non-null object
7 chromatin 699 non-null int64
8 normal_nucleoli 699 non-null int64
9 mitoses 699 non-null int64
10 class 699 non-null int64
dtypes: int64(10), object(1)
memory usage: 60.2+ KB
# 데이터 통계 요약정보 확인
df.describe(include='all') #include='all'사용하면 숫자형뿐만 아니라 object타입 열에 대한 통계 요약정보를 알수 있다
# 누락 데이터 확인
df.isnull().sum() #모든 열에 누락치가 없다.
id 0
clump 0
cell_size 0
cell_shape 0
adhesion 0
epithlial 0
bare_nuclei 0
chromatin 0
normal_nucleoli 0
mitoses 0
class 0
dtype: int64
# 중복 데이터 확인
df.duplicated().sum()
8
# 목표변수
df['class'].value_counts(normalize=True)
class
2 0.655222
4 0.344778
Name: proportion, dtype: float64
# 목표변수를 이진 변수로 변환 - 2: benign(양성), 4: malignant(악성)
df['class'] = df['class'].map({2:0, 4:1})
df['class'].value_counts(normalize=True)
class
0 0.655222
1 0.344778
Name: proportion, dtype: float64
# pandas hist 시각화
df.hist(figsize=(15, 12)); # hist() 데이터프레임에 포함된 모든 숫자형열에 대한 히스트그램을 그린다.
# seaborn pairplot 시각화
vis_cols = ['clump', 'cell_size', 'cell_shape', 'chromatin', 'class']
sns.pairplot(data=df[vis_cols], hue='class');
'''
[Step 3] 데이터 전처리
'''
# 중복 데이터 제거
print('중복 제거 이전: ', df.shape)
df = df.drop_duplicates()
print('중복 제거 이후: ', df.shape)
중복 제거 이전: (699, 11)
중복 제거 이후: (691, 11)
### bare_nuclei 열의 자료형 변경 (문자열 ->숫자)
# bare_nuclei 열의 고유값 확인
print('bare_nuclei 열의 고유값: ', df['bare_nuclei'].unique())
df['bare_nuclei'] = df['bare_nuclei'].replace('?', np.nan) # '?'을 np.nan으로 변경
df = df.dropna(subset=['bare_nuclei'], axis=0) # 누락데이터 행을 삭제
df['bare_nuclei'] = df['bare_nuclei'].astype('int') # 문자열을 숫자형으로 변환
# 데이터 통계 요약정보 확인
df.describe()
'''
[Step 4] 데이터셋 구분 - 훈련용(train data)/ 검증용(test data)
'''
# 속성(변수) 선택
train_features = ['clump', 'cell_size', 'cell_shape', 'adhesion', 'epithlial',
'bare_nuclei', 'chromatin', 'normal_nucleoli', 'mitoses']
X = df[train_features] # 설명 변수 X
y = df['class'] # 예측 변수 Y
# 설명 변수 데이터를 정규화
X = preprocessing.StandardScaler().fit(X).transform(X)
# train data 와 test data로 구분(7:3 비율)
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.3,
random_state=10)
print('train data 개수: ', X_train.shape)
print('test data 개수: ', X_test.shape)
train data 개수: (472, 9)
test data 개수: (203, 9)
'''
[Step 5] Decision Tree 분류 모형 - sklearn 사용
'''
# sklearn 라이브러리에서 Decision Tree 분류 모형 가져오기
# 모형 객체 생성 (criterion='entropy' 적용)
tree_model = tree.DecisionTreeClassifier(criterion='entropy', max_depth=5)
# train data를 가지고 모형 학습
tree_model.fit(X_train, y_train)
# test data를 가지고 y_hat을 예측 (분류)
y_hat = tree_model.predict(X_test)
print(y_hat[0:10])
print(y_test.values[0:10])
[0 1 1 0 0 1 1 0 0 1]
[0 1 1 0 0 1 1 0 0 1]
# 모형 성능 평가 - Confusion Matrix 계산
tree_matrix = metrics.confusion_matrix(y_test, y_hat)
print(tree_matrix) # TN 123개 FP는 7개, 악성을 양성으로 잘못분류한 FN은 2개, 악성을 정확 예측한 TP는 71개
[[123 7]
[ 2 71]]
# Confusion Matrix 시각화
plt.figure(figsize=(8, 6))
sns.heatmap(tree_matrix, annot=True, fmt='d', cmap='Greens',
xticklabels=['Negative', 'Positive'],
yticklabels=['Negative', 'Positive'])
plt.title('Confusion Matrix')
plt.ylabel('Actual label')
plt.xlabel('Predicted label')
plt.show()
# 모형 성능 평가 - 평가지표 계산
tree_report = metrics.classification_report(y_test, y_hat)
print(tree_report)
precision recall f1-score support
0 0.98 0.95 0.96 130
1 0.91 0.97 0.94 73
accuracy 0.96 203
macro avg 0.95 0.96 0.95 203
weighted avg 0.96 0.96 0.96 203
# 특성 중요도 출력
features = pd.DataFrame(tree_model.feature_importances_,
index=train_features,
columns=['Importance'])
features = features.sort_values(by='Importance', ascending=False)
features
# 특성 중요도 시각화
plt.figure(figsize=(10, 6))
sns.barplot(x=features.Importance, y=features.index,
hue=features.index, legend=False,
palette='viridis')
plt.title('Feature Importances')
plt.xlabel('Importance')
plt.ylabel('Features')
plt.show()
'데이터 분석가:Applied Data Analytics > 판다스 데이터분석' 카테고리의 다른 글
Feature Engineering (1) | 2025.02.18 |
---|---|
데이터분석머신러닝-실습(k-Means, DBSCAN) (0) | 2025.02.17 |
머신러닝(Machine Learning, ML)-실습 (1) | 2025.02.14 |
머신러닝(Machine Learning, ML)-용어편 (0) | 2025.02.14 |
4. Data transformation - 영국시장의 중고 자동차 가격 데이터 다루기[프로젝트] (0) | 2025.02.13 |