본문으로 바로가기

최근 저는 케라스를 이용해서 선형 회귀도 살짝 공부할 겸, 다변수 입력에 대한 선형회귀 문제로 혈중 지방함량이라는 데이터를 어디서 구해서 케라스를 이용한 다변수 함수에 대한 선형회귀를 학습하고, 그리고 머신러닝을 학습하는 과정에서 필수라고 하는 MNIST 데이터 셋을 케라스를 이용해서 CNN으로 구분하는 학습을 해 보았습니다. 그리고 그렇게 CNN을 이용해서 학습한 모델을 저장한 후에, 그 모델만 다시 읽어와서 내가 손으로 쓴 글씨에 테스트도 해 보았네요^^ 그러다가, 이진 분류도 학습할 겸, 케라스를 이용해서 타이타닉 생존자도 예측을 해보았습니다.

오늘은 그 흐름에서 살짝 뒤로 가는 거긴 합니다만, 또 하나의 유명한 예제인 붓꽃 Iris 분류를 이야기하려고 합니다. 너무나 유명한 통계적 예제라서 통계와 관련된 모듈, 프로그램에서는 아예 이 데이터가 포함되어 있더라구요. 현재 쉽게 구할 수 있는 붓꽃 데이터는 150개 양입니다. 현대 통계학에서 위대한 업적을 많이 남기셨다고 하는 Roland Fisher라는 분이 수집한 데이터인데요.

출처 : 위키백과 아이리스 항목

뭐 일단, Iris가 어떤 아이인지는 알아야죠. 이쁘네요^^. 프랑스의 국화라고 하던데... 전 왜 이 꽃을 평상시 본적이 없다고 기억하는지 모르지만 말이죠^^. 여하튼 이 꽃은 꽃받침(Sepal)과 꽃잎(Petal)의 길이와 폭을 가지고 세 개의 종을 분류하는 예제로 사용됩니다.^^

출처 : http://mirlab.org/의 아이리스 항목

꽃받침과 꽃잎의 길이로와 폭으로 구분할 수 있는 종인 모양입니다. 뭐 꽃을 잘 모르니ㅠㅠ.

출처 : http://mirlab.org/의 아이리스 항목

구분하는 세 개의 종은 위 그림처럼 Setosa, Vericolor, Virginica입니다. 꽃에 정통하지 않은 경우라도 쉽게 저 세개의 종을 분류하기 위해서는 앞서 이야기한 네 종류의 데이터(꽃받침과 꽃잎의 가로 세로 길이)를 이용해서 분류할 수 있어야겠죠.

출처 : http://articles.concreteinteractive.com/

꽃잎의 가로 세로 길이만 가지고도 Setosa는 확실히 잘 구분이 가는 모양입니다. 그러나 Versicolor와 Virginica는 혼돈되는 데이터가 있는 것 같습니다. 좀 더 많은 자료를 찾아보면 머신러닝에서 아주 심플하게 kNN을 이용해서 분류하는 예제가 많이 보입니다. 그러나 저는 Keras도 함께 학습하는 것이 목적이니.. 오늘은 Keras를 이용해서 딥러닝으로 분류를 해볼려고 합니다.

%matplotlib inline
import seaborn as sns
import pandas as pd
import numpy as np

sns.set(style="ticks", color_codes=True)
iris = sns.load_dataset("iris")
g = sns.pairplot(iris, hue="species", palette="husl")

먼저 필요한 모듈을 먼저 읽고... Seaborn이 제공하는 Iris 데이터를 가져옵니다.

Pairplot으로 그려보면 저렇게 나오네요. Petal의 길이와 폭(제일 아랫줄 세번째)이 아까 나온 그림이구요. 확실히 녹색과 청색 , 즉, Versicolor, Virginica를 딱 구분할 방법은 없어 보입니다. 뭐 그러니까 이렇게 붓꽃의 분류가 중요한 예제로 자리 잡았겠죠...

iris.info()

데이터의 개요를 한 번 보면...

150개 데이터와 4개의 특성, 그리고 종의 이름이 있습니다.

iris['species'].unique()

종의 특성만 보면...

방금 이야기한 세 개의 종이 나타납니다.

from sklearn.preprocessing import LabelEncoder

X = iris.iloc[:,0:4].values
y = iris.iloc[:,4].values

encoder =  LabelEncoder()
y1 = encoder.fit_transform(y)
Y = pd.get_dummies(y1).values
Y

위 코드는 꽤 유용한 역할을 하는데요. 문자열로된 이름에 번호를 붙이고(LabelEncoder) 그 번호를 원핫인코딩 방식으로 펼쳐줍니다.

그럼 저렇게 결과가 나오는거죠.

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, Y, 
                                                    test_size=0.2, 
                                                    random_state=1) 
X_train.shape, X_test.shape, y_train.shape, y_test.shape

이제 위 코드로 데이터를 학습용과 훈련용으로 나누고...

음.. 120개의 학습데이터와 30개의 테스트 데이터로 나누어졌네요. 이제 모델을 만들어야죠^^ 이 예제에서 사용된 Keras의 버전은 2.1.6입니다.^^

from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam

model = Sequential()

model.add(Dense(64,input_shape=(4,),activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(3,activation='softmax'))

model.compile(loss='categorical_crossentropy', 
              optimizer='Adam', 
              metrics=['accuracy'])

model.summary()

심플하게~ 잡았습니다.

구조는 저렇구요^^ 대망의~

hist = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=100)

훈련... 뭐 너무나도 스몰~ 데이터라 금방 끝납니다.^^

뭐.. 한 epoch가 micro second 단위죠^^

import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(12,8))
plt.plot(hist.history['loss'])
plt.plot(hist.history['val_loss'])
plt.plot(hist.history['acc'])
plt.plot(hist.history['val_acc'])
plt.legend(['loss','val_loss', 'acc','val_acc'])
plt.grid()
plt.show()

이제... Accuracy와 loss를 확인해보죠.

넵.. 잘 들어간듯 합니다. 100번의 epoch를 늘린다고 뭐 뽀족하게 좋을것 같진 않습니다. 테스트 데이터에 대한 결과가 있지만,

loss, accuracy = model.evaluate(X_test, y_test)
print("Accuracy = {:.2f}".format(accuracy))

를 통해 확인해보면...

이라고 나타나네요. 97%입니다. 더 좋아지기도 하고, 뭐.. 그렇더라구요.. 그냥 여기서 멈추겠습니다. 

한가지 더 재미난 결과를 확인해보기 위해 살짝 더 알아두면 좋은 것이 있는데요.

출처 : http://scikit-learn.org/

바로, Precision과 Recall, 그리고 F1-Score입니다.

출처 : http://scikit-learn.org/

이건 꽤 직관적인 예제를 scikit-learn 공식 홈페이지에서 얻을 수 있는데요.

출처 : http://scikit-learn.org/

위 예제입니다. y_true와 y_pred를 가지고 확인한 예제인데요. precision입장에서 이야기하면, 0이라고 두 번 예측했는데, 하나가 참이었던거구요. 1이라고 한 번 예측했는데 한번도 못 맞춘거죠. 그래서 precision은 예측한 결과 중에서 참인 결과를 의미하구요. recall은 0이 하나 있는데, 한 번 이상 맞췄으니 100%이구요. 2가 세 개 있는데 두 개를 맞춰서 67%인거죠. recall은 실제 데이터 중 몇 개를 예측에 성공했는지를 보는 겁니다. 그 둘을 복합적으로 점수(?)로 환산하는 장치가 F-score인거죠. 이걸 scikit-learn에서 잘 함수로 제공해 주네요^^

import numpy as np
from sklearn.metrics import classification_report,confusion_matrix

y_pred = model.predict(X_test)
y_test_class = np.argmax(y_test,axis=1)
y_pred_class = np.argmax(y_pred,axis=1)

print(classification_report(y_test_class,y_pred_class))
print(confusion_matrix(y_test_class,y_pred_class))

이렇게 사용해 주면 됩니다.

이렇네요. 특히 confusion_matrix 결과에서 보면 두 번째 종 이름을 12개는 맞고, 하나는 세번째 종으로 틀렸네요. 애초 데이터를 관찰할때도, 그걸 어느정도는 예상했죠^^

test_set = np.array([[5, 2.9, 1, 0.2]])
print("Predicted target name: {}".format(
    iris['species'].unique()[model.predict_classes(test_set)]))

이번에는 임의의 데이터를 한 번 넣어서 어떻게 판단하는지 볼까요

짠~ Setosa스러운 데이터였으니 말이죠. 또, versicolor의 특성을 보면

iris.query("species == 'versicolor'")

이 종은

각 특성별로 위와 같은 특성을 가지고 있네요. 그것과 유사하게.. 

test_set = np.array([[7, 3.0, 5, 1.4]])
print("Predicted target name: {}".format(
    iris['species'].unique()[model.predict_classes(test_set)]))

로 테스트해보니...

이런 결과가 나오네요. 뭐 150개 데이터를 사용한 것 뿐이라, 또 다른 심플하고 효율적인 방법도 많지만, 처음에 이야기했듯이, Keras를 이용해서 딥러닝(을 꼭 쓸 필요는 없지만)을 공부하는 하나의 예제로 Iris 품종 구분이라는 예제를 수행해 보았습니다.^^


댓글을 달아 주세요

  1. BlogIcon 공수래공수거 2018.05.18 08:20 신고

    이런걸 이용헤서 이미지를 확인 꽃 이름을 알려 주는건가요

  2. BlogIcon 북두협객 2018.05.18 09:52 신고

    프로그래밍 언어에 관해서는 이제 도통을 하신 듯 합니다!

  3. BlogIcon 휴식같은 친구 2018.05.18 15:57 신고

    아이리스 품종을 구분하는 예제, 뭔지 잘 모르겠네여.ㅎㅎ
    즐거운 하루 보내세요~^^

  4. BlogIcon 드래곤포토 2018.05.18 22:30 신고

    재미있는 데이타 분류네요
    즐거운 주말되세요

  5. BlogIcon 스티마 2018.05.19 01:24 신고

    솔직히 이번건 어렵다고 생각 됩니다.
    몇번 더 읽어 봐야겠네요. ㅎㅎ

  6. BlogIcon Bliss :) 2018.05.19 02:40 신고

    아....아이리스의 품종을 데이터 분류 작업을 하시다니....대단하십니다!! 이렇게 보면 정말 활용도가 어마어마한 거겠네요. 행복한 주말 보내시길요~

  7. BlogIcon 핑구야 날자 2018.05.19 06:55 신고

    꽃이 참 예쁘네요 오늘은 꽃만 보고 갑니다

  8. BlogIcon 귀요미디지 2018.05.19 10:05 신고

    뭔가 다양한 방법으로 예제를 하시는 중인가 봐요
    본인이 하고자 하는 건 타인에게 꼭 필요한 자료가 되진 않아됴
    해봐야죠 ㅎㅎ
    즐거운 토요일 되세요 ^^

  9. BlogIcon 잉여토기 2018.05.19 17:03 신고

    꽃검색 어플이 이러한 프로그램 과정으로 꽃을 검색할 수 있게 해줄 수 있는 거 같네요~^^

    • BlogIcon PinkWink 2018.05.21 01:01 신고

      음.. 이건 대상이 아이리스라서 그렇지.. 저에겐 기계학습의 분류를 한 번 수행해 보았다는 의의를 가지지요^^

  10. BlogIcon Deborah 2018.05.22 01:16 신고

    예 오늘도 확실하게 공부를 시켜 주시네요. 열공하겠습니다.