머신러닝

Scikit-learn 라이브러리 지원 Iris flowers 예제

coding art 2019. 7. 22. 15:02
728x90

 

Iris flowers Classification 문제는 2019년 텐서플로우 홈페이지 리모델링 전에 있었던 머신러닝 예제로서 붓꽃의 꽃잎(Petal) 사이즈와 꽃받침(Sepal) 사이즈 데이터를 사용하여 세부적으로 종 분류를 지원하는 sklearn(Scikit-learn) 라이브러리 사용법의 좋은 예이다.

 

 

공식 사이트에서 주어졌던 결과와 비교해 보면 Virginica에서 오차가 상당히 큼을 알 수 있다. 매번 실행할 때 마다 Shuffling 및 랜덤 넘버 사용에 따라 3가지 결과에 꽤 변동이 있을 수 있으나 틀린 것이 아님에 유의하자.

 

아나콘다 스파이더3 편집기에서 붓꽃 예제를 다루기 위해서는 Scikit-learn 라이브러리 모듈이 사전에 설치되어 있어야 한다. 설치 방법은 가상환경 설치 방법을 참고하도록 한다.

 

 

Anaconda navigator 의 Environments 에서 미리 가상환경을 지정한 후 Open Terminal 을 열어서 pip install sklearn  명령을 실행시켜 설치하도록 하자.

 

이와 같이 특정 가상환경에 sklearn 라이브러리 모듈이 설치되면 가상환경 내에 설치된 라이브러리 모듈들 간에 상호종속성(depencendy)이 확인되므로 함께 불러내어 사용이 가능하다. NumPy, Matplotlib, Pandas, SciPy 들이 이미 설치되어 있을 것이다. 하지만 이 가상환경을 벗어나게 되면 라이브러리 모듈을 불러 올 수 없음에 유의하자.

 

Sklearn 라이브러리 모듈을 사용하는 iris flowers(붓꽃) 식별 코드를 다루어 보자. 이 문제를 풀기 위해서 Pandas를 비롯 여러 개의 sklearn 라이브러리 모듈들을 아래와 같이 불러들인다. 이 부분은 수정없이 그대로 사용하기로 한다.

특히 후반부를 보면 Logistic Regression 을 비롯하여 LDA SVM(Support Vector Machine), Gaussian Naive Bayes 모델까지 다루고 있음을 알 수 있다. LDA SVM 기법 은 별도로 상세히 다루어 보기로 하며 여기서는 개괄적인 비교 작업에 국한하기로 한다.

 

sklearn 라이브러리 업데이트에 따라 발생되는 경고 메세지 출력 억제

 

 

아래의 코드에서처럼 인터넷 url 주소에서 Iris.data를 다운 받아 읽어서 변수명 dataset 으로 선언한다, 데이터 파일의 확장자는 .csv 로서 pandas 라이브러리 모듈은 csv 데이터를 읽도록 특화되어 있다. 반대로 읽어 들인 csv 파일을 현재의 실행 코드가 위치한 폴더에 csv 파일 로 저장하고 코드 실행 완료 후 열어서 체크해 보자. index= False 는 pandas  처리 과정에서 row  단위별로 부과되었던 인덱스 0, 1, 2, 3, ...  을 의미하며 False 로 두면 데이터 알맹이만 저장한다는 의미이다.

 

dataset.head(10) 의 출력은 첫 번째 즉 0 번에서 열 번째 즉 9번까지의 데이터를 출력한다. 아울러 dataset.tail(10) 명령을 사용하면 끝부분의 10개 데이터를 출력하며 전체를 출력하고 싶으면 셸(Shell)에서 dataset을 실행시키면 된다.

dataset.describe()는 데이터 전체의 평균, 표준편차, 최대, 최소값을 포함하는 통계치를 계산하는 명령이며 dataset.groupby(‘class’).size() csv 데이타 파일의 ‘class’ 행 데이터를 대상으로 내용을 구분하여 총 샘플 수를

출력해준다.

 

5행으로 구성되는 붓꽃 데이터는 각각 꽃받침의 길이와 폭, 꽃잎의 길이와 폭, 아울러 해당 꽃의 세부 종의 명칭으로 구성된다.

 

 

이 데이터를 Classification 목적으로 사용하기 위해서 다음과 같이 통계학 처리과정을 거치도록 한다.

꽃받침과 꽃잎 사이즈 데이터는 X 어레이, 꽃의 종명 즉 라벨명은 Y 어레이로 둔다.

validation_size 는 머신 러닝 단계에서 학습용 데이터와 테스트용 데이터로 나누는 비율을 뜻한다.

Iris_data 3개 종별로 각 50개씩 총 150 개로 이루어지므로 0.2 는 총30개로서 각 종별 10개의 임의로 선택된 검증용 테스트 데이터를 뜻한다.

seed =7 은 난수 생성을 위한 초기 값으로서 항상 동일한 연산결과를 생성하도록 한다.

                                      

 

sklearn 라이브러리를 사용하여 비교 모델별로 머신 러닝 학습을 준비하자.

Iris flowers의 세부적인 종들을 분류하기 위한  선형 및 비선형을 포함하는  머신 러닝 모델들이다

Scikit-learn 라이브러리 모듈은 TensorFlow 와는 별도로 발전해 온 오픈소스로서 이 문제에 대한 97% 수준의 validation 결과를 준다. 

 

K fold cross validation  통계 기법을 사용하자.  n_splits=10 이므로 꽃 종류별 학습 데이터 50개를 셔플링 후 validation 데이터를 10개씩 순차적으로 바꾸어 가면서 5회 실행하여 평균을 내도록 한다. 

 

실행결과에 의하면 SVM(Support Vector Machine)기법이 가장 정확한 결과를 주고 있다. 하지만 숫자 상으로 약간 차이가 있으나 이는 한번 잘못 평가한 경우에 해당하므로 거의 동일한 결ㄹ과로 평가할 수 있다.

 

첨부된 파이선 코드를 다운 받아 실행해 보자.

#Iris_practice.py

import pandas
from pandas.plotting import scatter_matrix
import matplotlib.pyplot as plt
from sklearn import model_selection
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC

# 아래는 불필요한 경고 메세지를 억제함
from warnings import simplefilter
from sklearn.exceptions import ConvergenceWarning
simplefilter(action='ignore', category=FutureWarning)
simplefilter(action='ignore', category=ConvergenceWarning)


#Load dataset
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class']
dataset = pandas.read_csv(url, names=names)
print (dataset.head(10))
print (dataset.describe())
print(dataset.groupby('class').size())

 

# 읽었던 csv 파일을 이 실행 파일이 위치한 폴더에 iris_dataset.csv 파일로 저장하여라.

# 실행 후 iris_dataset.csv 파일을 열어서 체크하여라.
dataset.to_csv('iris_dataset.csv', index=False)


#validation dataset
array = dataset.values
X = array[:,0:4]
Y = array[:,4]
validation_size = 0.2
seed = 7
X_train, X_validation, Y_train, Y_validation = model_selection.train_test_split(X, Y, test_size=validation_size, random_state=seed)
print(X_validation)
print(Y_validation)

scoring = 'accuracy'
models = []
models.append(('LR', LogisticRegression()))
models.append(('LDA', LinearDiscriminantAnalysis()))
models.append(('KNN', KNeighborsClassifier()))
models.append(('CART', DecisionTreeClassifier()))
models.append(('NB', GaussianNB()))
models.append(('SVM', SVC()))
# evaluate each model in turn

results = []
names = []
for name, model in models:
 kfold = model_selection.KFold(n_splits=10, random_state=None)  # CV means Cross Validation
 cv_results = model_selection.cross_val_score(model, X_train, Y_train, cv=kfold, scoring=scoring)
 results.append(cv_results)
 names.append(name)
 msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
 print(msg)