분류 알고리즘은 예측하려는 대상의 속성(설명 변수)을 입력 받고, 목표 변수가 갖고 있는 카테고리(범주형)
값 중에서 어느 한 값으로 분류하여 예측한다.
훈련 데이터에 목표 변수 값(0 또는 1)을 함께 입력하므로 지도 학습 유형에 속한다.
KNN
K-Nearest-Neighbors로 k개의 가까운 이웃이라는 뜻이다. 새로운 관측값이 주어지면 기존 데이터에서 가장 속성이
비슷한 k개의 이웃을 먼저 찾고, 가까운 이웃들이 갖고 있는 목표 값과 같은 값으로 분류하여 예측하는 것이다.
import pandas as pd
import seaborn as sns
df = sns.load_dataset('titanic')
print(df.head())
print('\n')
pd.set_option('display.max_columns', 15)
print(df.head())
survived pclass sex age sibsp parch fare embarked class \
0 0 3 male 22.0 1 0 7.2500 S Third
1 1 1 female 38.0 1 0 71.2833 C First
2 1 3 female 26.0 0 0 7.9250 S Third
3 1 1 female 35.0 1 0 53.1000 S First
4 0 3 male 35.0 0 0 8.0500 S Third
who adult_male deck embark_town alive alone
0 man True NaN Southampton no False
1 woman False C Cherbourg yes False
2 woman False NaN Southampton yes True
3 woman False C Southampton yes False
4 man True NaN Southampton no True
info() 메소드로 일부 열에 누락 데이터가 있는지 확인해본다.
print(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 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
None
deck열에 유효한 값이 203개에 불과하고, 688개의 누락 데이터가 있는데 전체 891명의 승객 중 688명의 데이터가
존재하지 않는다는 뜻이다. 따라서 deck 열ㅇ르 제거하도록 하고, embark_town 열은 embarked 열과 동일한 의미가
갖기 때문에 중복을 없애기 위해 열 자체를 제거한다..
rdf = df.drop(['deck', 'embark_town'], axis=1)
age열에 누락 데이터가 177개 포함되어있다. 분석에 포함시켜야하는 중요한 속성으로 판단될 경우에 예측 결과에
영향을 최소화하는 방법을 선택해야 한다. 평균 나이로 치환하는 방법도 가능하지만 누락 데이터가 있는 행을 모두
제거하도록 하자.
rdf = rdf.dropna(subset=['age'], how='any', axis=0)
print(len(rdf))
714
embarked 열에는 승객들이 탑승한 도시명의 첫 글자가 들어있다. 누락 데이터가 2개이므로 가장 많이 탑승한
도시명으로 치환한다.
most_freq = rdf['embarked'].value_counts(dropna=True).idxmax()
print(most_freq)
print('\n')
print(rdf.describe(include='all'))
print('\n')
rdf['embarked'].fillna(most_freq, inplace=True)
survived pclass sex age sibsp parch \
count 714.000000 714.000000 714 714.000000 714.000000 714.000000
unique NaN NaN 2 NaN NaN NaN
top NaN NaN male NaN NaN NaN
freq NaN NaN 453 NaN NaN NaN
mean 0.406162 2.236695 NaN 29.699118 0.512605 0.431373
std 0.491460 0.838250 NaN 14.526497 0.929783 0.853289
min 0.000000 1.000000 NaN 0.420000 0.000000 0.000000
25% 0.000000 1.000000 NaN 20.125000 0.000000 0.000000
50% 0.000000 2.000000 NaN 28.000000 0.000000 0.000000
75% 1.000000 3.000000 NaN 38.000000 1.000000 1.000000
max 1.000000 3.000000 NaN 80.000000 5.000000 6.000000
fare embarked class who adult_male alive alone
count 714.000000 712 714 714 714 714 714
unique NaN 3 3 3 2 2 2
top NaN S Third man True no True
freq NaN 554 355 413 413 424 404
mean 34.694514 NaN NaN NaN NaN NaN NaN
std 52.918930 NaN NaN NaN NaN NaN NaN
min 0.000000 NaN NaN NaN NaN NaN NaN
25% 8.050000 NaN NaN NaN NaN NaN NaN
50% 15.741700 NaN NaN NaN NaN NaN NaN
75% 33.375000 NaN NaN NaN NaN NaN NaN
max 512.329200 NaN NaN NaN NaN NaN NaN
다음은 속성을 선택한다. 예측 변수로는 생존 여부를 나타내는 survived 열을 추가하고, 나머지 6개의 열을 포함하자.
ndf = rdf[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'embarked']]
print(ndf.head())
survived pclass sex age sibsp parch embarked
0 0 3 male 22.0 1 0 S
1 1 1 female 38.0 1 0 C
2 1 3 female 26.0 0 0 S
3 1 1 female 35.0 1 0 S
4 0 3 male 35.0 0 0 S
sex와 embarked 열의 범주형 데이터를 숫자형 데이터로 변환하는데, 이를 0과 1로 변환할 것이다.
이 과정을 더미 변수를 만든다고 하고 원핫인코딩이라고도 부른다.
onehot_sex = pd.get_dummies(ndf['sex'])
ndf = pd.concat([ndf, onehot_sex], axis=1)
onehot_embarkde = pd.get_dummies(ndf['embarked'], prefix='town')
ndf = pd.concat([ndf, onehot_embarked], axis=1)
ndf.drop(['sex', 'embarked'], axis=1, inplace=True)
print(ndf.head())
survived pclass age sibsp parch female male town_C town_Q town_S
0 0 3 22.0 1 0 0 1 0 0 1
1 1 1 38.0 1 0 1 0 1 0 0
2 1 3 26.0 0 0 1 0 0 0 1
3 1 1 35.0 1 0 1 0 0 0 1
4 0 3 35.0 0 0 0 1 0 0 1
훈련/검증 데이터 분할을 해보자. 예측 변수인 'survived' 열을 변수 y에 저장하고
나머지 열을 설명 변수 x에 할당한다. 그리고 데이터의 상대적 크기 차이를 없애기 위해 정규화 과정을 거친다.
x = ndf[['pclass', 'age', 'sibsp', 'parch', 'female', 'male', 'town_C', 'town_Q', 'town_S']]
y = ndf['survived']
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
x = ss.fit(x).transform(x)
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(x_train.shape)
print(x_test.shape)
(499, 9)
(215, 9)
분류 모형의 예측력을 평가하는 지표가 있는데
Confusion Matrix (오차행렬)가 있다.
정확도는 True 예측 대상 중에 실제값이 True인 비율이다 ( Precision = TP / (TP + FP) )
재현율은 실제 값이 True인 분석대상 중에서 True로 예측하여 모형이 적중한 비율이다 ( Recall = TP / (TP + FN) )
F1-score은 정확도와 재현율이 균등하게 반영될 수 있도록 정확도와 재현율의 조화평균을 계산한 값으로, 모형의 예측력을 종합적으로 평가하는 지표이다. ( F1 Score = 2*(Precision*Recall) / (Precision + Recall) )
모형을 학습하고 검증해보자. 사이킷런의 neighbors 모듈을 사용한다.
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
kn.fit(x_train, y_train)
kn.score(x_train, y_train)
0.8537074148296593
모형을 가지고 y_hat을 예측해보자.
y_hat = knn.predict(x_test)
print(y_hat[0:10])
print(y_test.values[0:10])
[0 0 1 0 0 1 1 1 0 0]
[0 0 1 0 0 1 1 1 0 0]
모형의 예측 능력을 평가해보자. metrics 모듈의 confusion_matrix() 함수를 사용하여 오차 행렬을 계산해보자.
from sklearn import metrics
knn_matrix = metrics.confusion_matrix(y_test, y_hat)
print(knn_matirx)
[[111 14]
[ 24 66]]
왼쪽 위에부터 TP, FP, FN, TN 이다.
이번에는 모형의 예측 능력을 평가하는 지표를 계산해보자. metrics 모듈의 classification_report() 함수를 사용하면
precision, recall, f1-score 지표를 출력할 수 있다.
knn_report = metrics.classification_report(y_test, y_hat)
print(knn_report)
precision recall f1-score support
0 0.82 0.89 0.85 125
1 0.82 0.73 0.78 90
accuracy 0.82 215
macro avg 0.82 0.81 0.82 215
weighted avg 0.82 0.82 0.82 215
SVM
Support Vector Machine의 약자로 벡터 개념을 가져와서 사용하는 알고리즘이다.
각 열은 열 벡터 형태로 구현이 되고, 열 벡터들이 각각 고유의 축을 갖는 벡터 공간을 만들게 된다.
분석 대상이 되는 개별 관측값은 모든 속성(열 벡터)에 관한 값을 해당 축의 좌표로 표시하여 벡터 공간에서의 위치를
나타낸다. 속성이 2개 존재하면 2차원 평면 공간에 표시, 3개면 3차원 공간에 표시하고 고차원 벡터 공간의 좌표도 사용이 가능하다
SVM 모형은 벡터 공간에 위치한 훈련 데이터의 좌표와 각 데이터가 어떤 분류 값을 가져야 하는지 정답을 입력 받아서
학습하는 것으로, 같은 분류 값을 갖는 데이터끼리 같은 공간에 위치하도록 벡터 공간을 여러조각을 나눌 수 있다면,
새로운 데이터에 대해서도 어느 공간에 위치하는지 분류할 수 있다.
df = sns.load_dataset('titanic')
pd.set_option('display.max_columns', 15)
rdf = df.drop(['deck', 'embark_town'], axis=1)
rdf = rdf.dropna(subset=['age'], how='any', axis=0)
most_freq = rdf['embarked'].value_counts(dropna=True).idxmax()
rdf['embarked'].fillna(most_freq, inplace=True)
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.drop(['sex', 'embarked'], axis=1, inplace=True)
x = ndf[['pclass', 'age', 'sibsp', 'parch', 'female', 'male', 'town_C', 'town_Q', 'town_S']]
y = ndf['survived']
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(x)
x = ss.transform(x)
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(x_train.shape)
print(x_test.shape)
(499, 9)
(215, 9)
데이터를 준비했고, 모형 학습 및 검증을 진행해보자.
sklearn의 svm 모듈의 SVC() 함수를 사용하여 모형 객체를 생성한다.
이때 데이터를 벡터 공간으로 매핑하는 함수를 커널이라고 하는데, kernel='rbf' 옵션으로 RBF 함수를 적용한다.
이 외에도 Linear, Polynomial, Sigmoid 등의 커널이 있다.
from sklearn import svm
svm_model = svm.SVC(kernel='rbf')
svm_model.fit(x_train, y_train)
y_hat = svm_model.predict(x_test)
print(y_hat[0:10])
print(y_test.values[0:10])
[0 0 1 0 0 0 1 0 0 0]
[0 0 1 0 0 1 1 1 0 0]
예측값인 y_hat 과 실제 데이터인 y_test를 비교하면 10개 중 8개가 일치한다.
이 모형의 오차 행렬을 출력해보자.
from sklearn import metrics
svm_matrix = metrics.confusion_matrix(y_test, y_hat)
print(svm_matrix)
print('\n')
svm_report = metrics.classification_report(y_test, y_hat)
print(svm_report)
[[120 5]
[ 35 55]]
precision recall f1-score support
0 0.77 0.96 0.86 125
1 0.92 0.61 0.73 90
accuracy 0.81 215
macro avg 0.85 0.79 0.80 215
weighted avg 0.83 0.81 0.81 215
표 좌측 상단부터 TP, FP, FN, TN 이다.
'Study > 혼자 공부하는 판다스' 카테고리의 다른 글
혼자 공부하는 판다스 - 의사결정 나무 (1) | 2022.04.30 |
---|---|
혼자 공부하는 판다스 - 머신러닝 데이터 분석 (머신러닝 개요, 회귀분석) (0) | 2022.04.29 |
혼자 공부하는 판다스 - 데이터프레임의 다양한 응용(함수 매핑, 열 재구성) (0) | 2022.04.26 |
혼자 공부하는 판다스 - 데이터 사전처리(정규화, 시계열 데이터) (0) | 2022.04.22 |
혼자 공부하는 판다스 - 데이터 사전 처리(데이터 표준화, 범주형 데이터 처리) (0) | 2022.04.22 |