Список работ

Классификаторы библиотеки scikit-learn на Python

Содержание

Введение

Классификаторы библиотеки scikit-learn рассматриваются на задаче классификации ирисов Фишера-Андерсона, описание которых дано в виде набора из данных о 150 экземплярах ириса, по 50 экземпляров из трех следующих видов (рис. 1):

Ирисы Фишера-Андерсона

Рис. 1. Ирисы

Для каждого экземпляра приведены 4 следующие характеристики (в см.):

Данные находятся в файле iris.csv. (рис. 2):

Ирисы Фишера-Андерсона

Рис. 2. Примеры записей файла iris.csv

На основании этого набора данных требуется построить правило классификации, определяющее класс растения.

Замечание. Один из классов (Iris setosa) линейно-разделим от двух остальных (рис. 3).

Ирисы Фишера-Андерсона

Рис. 3. Представление классов ирисов по трем характеристикам

Рис. 3 будет выведен, если в приводимой далее программе задать groundTruth = True.

Первая строка файла iris.csv содержит заголовки столбцов, далее следуют строки данных:
sepalLength,sepalWidth,petalLength,petalWidth,variety
5.1,3.5,1.4,.2,Setosa
4.9,3,1.4,.2,Setosa

Гистограммы характеристик ирисов, описанных в вышерассмотренном наборе, показаны на рис. .

Гистограммы характеристик ирисов

Рис. 4. Гистограммы характеристик ирисов (получены по файлу iris.csv)

Для построения гистограмм можно применить следующий код:

import pandas
import matplotlib.pyplot as plt
iris = pandas.read_csv('iris.csv')
iris.hist()
plt.show()

Используемые классификаторы

Используются следующие классификаторы:

  1. SGD Classifier (SGD) - Линейный классификатор с SGD-обучением (stochastic gradient descent - стохастический градиентный спуск)
  2. Support Vector Machines (SVM) - Метод опорных векторов (kernel = 'linear').
  3. Random Forest Classifier (RF) - Случайный лес (используются деревья решений).
  4. Gaussian process classification (GP) - Гауссовская классификация (основана на аппроксимации Лапласа).
  5. AdaBoost (Adaptive Boosting) Classifier (AB) - Адаптивное усиление.
  6. Decision tree classifier (DT) - Дерево решений (http://scikit-learn.org/stable/modules/tree.html).
  7. Logistic Regression (LR) - Логистическая регрессия.
  8. Gaussian Naive Bayes (NB) - Гауссовский наивный байесовский классификатор.
  9. Support Vector (SV) Classification - Метод опорных векторов http://scikit-learn.org/stable/modules/svm.html#svm-classification.
  10. MLP (Multi-layer Perceptron) Classifier (MLP) - Многослойный перцептрон.
  11. K-Nearest Neighbors (KNN) - Метод K-ближайших соседей.
  12. Quadratic Discriminant Analysis (QDA) - Квадратичный дискриминантный анализ.
  13. Linear Discriminant Analysis (LDA) - Линейный дискриминантный анализ.

Классификация средствами scikit-learn

import numpy as np
import pandas
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # Для управления 3D-изображением (посредством мышки)
from sklearn.metrics import accuracy_score
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression, SGDClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.neural_network import MLPClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.svm import SVC
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis
import sys # Для sys.exit()
np.random.seed(348)
# Загрузка данных
iris = pandas.read_csv('iris.csv')
print(iris.shape) # (150, 5)
print(iris.head(10)) ## Печать первых 10 строк данных, загруженных из файла iris.csv
print(iris.describe()) # count, mean, std и др.
print(iris.groupby('variety').size()) # Setosa 50, Versicolor 50, Virginica 50
#
# Ветви программы
hist = False # True - вывод гистограмм
groundTruth = False # True - вывод классов по трем характеристикам: ширина лепестка, длина чашелистика, длина лепестка
cross_val = True # True, False - вывод карт вероятности по двум характеристикам: длина и ширина чашелистика
#
if hist:
    ## Гистограммы характеристик ирисов
    iris.hist()
    plt.show()
    sys.exit()
if groundTruth:
    # Заменяем имена классов на номера
    iris["variety"] = iris["variety"].map({"Setosa":0, "Versicolor":1, "Virginica":2})
    # Выводим результаты наблюдений (по 3-м характеристикам)
    X = iris.values[:, 0:4]
    y = iris.values[:, 4]
    fig = plt.figure(1, figsize = (5, 4))
    ax = Axes3D(fig, rect = [0, 0, .95, 1], elev = 48, azim = 134)
    for name, label in [('Setosa', 0), ('Versicolor', 1), ('Virginica', 2)]:
        ax.text3D(X[y == label, 3].mean(),
                 X[y == label, 0].mean(),
                 X[y == label, 2].mean() + 2, name,
                 horizontalalignment = 'center',
                 bbox = dict(alpha = 0.2, edgecolor = 'w', facecolor = 'w'))
    ax.scatter(X[:, 3], X[:, 0], X[:, 2], c = y, edgecolor = 'k')
    ax.w_xaxis.set_ticklabels([])
    ax.w_yaxis.set_ticklabels([])
    ax.w_zaxis.set_ticklabels([])
    ax.set_xlabel('Ширина лепестка')
    ax.set_ylabel('Длина чашелистика')
    ax.set_zlabel('Длина лепестка')
    ax.set_title('Ирисы Фишера')
    ax.dist = 12
    fig.show()
    sys.exit()
iris_array = iris.values
x = iris_array[:, 0:4]
y = iris_array[:, 4]
#
# Используемые методы:
# 1. SGD Classifier (SGD) - Линейный классификатор с SGD-обучением (stochastic gradient descent - стохастический градиентный спуск)
# 2. Support Vector Machines (SVM) - Метод опорных векторов (kernel = 'linear')
# 3. Random Forest Classifier (RF) - Случайный лес (используются деревья решений)
# 4. Gaussian process classification (GP) - Гауссовская классификация (основана на аппроксимации Лапласа)
# 5. AdaBoost (Adaptive Boosting) Classifier (AB) - Адаптивное усиление
# 6. Decision tree classifier (DT) - Дерево решений (http://scikit-learn.org/stable/modules/tree.html)
# 7. Logistic Regression (LR) - Логистическая регрессия
# 8. Gaussian Naive Bayes (NB) - Гауссовский наивный байесовский классификатор
# 9. Support Vector (SV) Classification - Метод опорных векторов http://scikit-learn.org/stable/modules/svm.html#svm-classification
# 10. MLP (Multi-layer Perceptron) Classifier (MLP) - Многослойный перцептрон
# 11. K-Nearest Neighbors (KNN) - Метод K-ближайших соседей
# 12. Quadratic Discriminant Analysis (QDA) - Квадратичный дискриминантный анализ
# 13. Linear Discriminant Analysis (LDA) - Линейный дискриминантный анализ
classifiers = []
if cross_val:
    classifiers.append(('SGD', SGDClassifier(max_iter = 1500, tol = 1e-4)))
classifiers.append(('SVL', SVC(kernel = 'linear', C = 0.025, probability = True))) # C - штраф в случае ошибки
classifiers.append(('RF', RandomForestClassifier(max_depth = 5, n_estimators = 10, max_features = 1)))
if cross_val:
    classifiers.append(('GP', GaussianProcessClassifier()))
classifiers.append(('AB', AdaBoostClassifier()))
classifiers.append(('DT', DecisionTreeClassifier()))
classifiers.append(('LR', LogisticRegression(solver = 'lbfgs', max_iter = 500, multi_class = 'auto')))
classifiers.append(('NB', GaussianNB()))
classifiers.append(('SVR', SVC(gamma = 2, C = 1.0))) # gamma - коэффициент ядра для 'rbf' - radial basis function, 'poly' and 'sigmoid'
classifiers.append(('MLP', MLPClassifier(alpha = 0.01, max_iter = 200, solver = 'lbfgs', tol = 0.001)))
classifiers.append(('KNN', KNeighborsClassifier(3)))
classifiers.append(('QDA', QuadraticDiscriminantAnalysis()))
classifiers.append(('LDA', LinearDiscriminantAnalysis()))
# Оценка методов
if cross_val:
    results = []
    names = []
    k = 10
    for name, classifier in classifiers:
        # Генерируем индексы для выделения обучающих и тестовых данных
        # k - 1 подвыборок будут использованы для обучения, а одна - для проверки (валидации)
        kfold = model_selection.KFold(n_splits = k, random_state = 348)
        ## cv - стратегия кросс-валидации
        cv_results = model_selection.cross_val_score(classifier, x, y, cv = kfold, scoring = 'accuracy')
        results.append(cv_results)
        names.append(name)
        #print("%s: %f (%f)" % (name, cv_results.mean(), cv_results.std()))
        print(name, np.round(cv_results, 3), 'Средняя точность: ', round(cv_results.mean(), 3))
    # Графическое представление результатов
    fig = plt.figure()
    fig.suptitle('Точность, показанная классификаторами')
    ax = fig.add_subplot(1, 1, 1)
    plt.boxplot(results)
    ax.set_xticklabels(names)
    plt.show()
else:
    x = x[:, 0:2] # Берем для отображения только две характеристики: длина и ширина чашелистика
    n_classifiers = 4 # Число обучаемых классификаторов
    plt.figure(figsize = (3 * 2, n_classifiers * 2))
    plt.subplots_adjust(bottom = 0.2, top = 0.95)
    xx = np.linspace(3, 9, 100)
    yy = np.linspace(1, 5, 100).T
    xx, yy = np.meshgrid(xx, yy)
    Xfull = np.c_[xx.ravel(), yy.ravel()]
    index = -1
    for name, classifier in classifiers:
        index += 1
        if index < n_classifiers:
            classifier.fit(x, y) # Обучение
            y_pred = classifier.predict(x) # Оцениваем результат
            accuracy = accuracy_score(y, y_pred)
            print("Точность обучения %s: %0.1f%% " % (name, accuracy * 100))
            # Показываем вероятности
            probas = classifier.predict_proba(Xfull)
            n_classes = np.unique(y_pred).size
            for k in range(n_classes):
                plt.subplot(n_classifiers, n_classes, index * n_classes + k + 1)
                class_name = {
                    k == 0 : 'Setosa',
                    k == 1 : 'Versicolor',
                    k == 2 : 'Virginica'
                }[True]
                plt.title(class_name)
                if k == 0:
                    plt.ylabel(name)
                imshow_handle = plt.imshow(probas[:, k].reshape((100, 100)), extent = (3, 9, 1, 5), origin = 'lower')
                plt.xticks(())
                plt.yticks(())
                idx = (y_pred == k)
                if idx.any():
                    plt.scatter(X[idx, 0], X[idx, 1], marker = 'o', c = 'w', edgecolor = 'k')
    ax = plt.axes([0.15, 0.04, 0.7, 0.05])
    plt.title("Вероятность")
    plt.colorbar(imshow_handle, cax = ax, orientation = 'horizontal')
    plt.show()

Все классификаторы будут задействованы, если cross_val = True.
После выполнения классификации выводятся результаты (рис. 5):
SGD [1. 0.933 1. 0.8 0.267 0. 1. 0.933 1. 1. ] Средняя точность: 0.793
SVL [1. 1. 1. 0.867 0.867 0.733 1. 0.8 0.667 0.733] Средняя точность: 0.867
RF [1. 1. 1. 1. 0.867 0.867 1. 0.8 0.6 0.933] Средняя точность: 0.907
GP [1. 1. 1. 1. 0.867 0.867 1. 0.867 0.733 0.933] Средняя точность: 0.927
AB [1. 1. 1. 1. 0.933 0.867 1. 0.867 0.8 0.933] Средняя точность: 0.94
DT [1. 1. 1. 1. 0.933 0.867 1. 0.867 0.8 1. ] Средняя точность: 0.947
LR [1. 1. 1. 1. 0.933 0.867 1. 0.867 0.867 0.933] Средняя точность: 0.947
NB [1. 1. 1. 0.933 0.933 0.867 1. 0.867 0.867 1. ] Средняя точность: 0.947
SVR [1. 1. 1. 1. 0.867 0.867 1. 0.867 0.867 1. ] Средняя точность: 0.947
MLP [1. 1. 1. 1. 0.867 0.933 1. 0.867 0.667 1. ] Средняя точность: 0.933
KNN [1. 1. 1. 1. 0.867 0.867 1. 0.867 0.867 1. ] Средняя точность: 0.947
QDA [1. 1. 1. 1. 0.8 0.933 1. 1. 0.933 1. ] Средняя точность: 0.967
LDA [1. 1. 1. 1. 0.933 0.933 1. 1. 0.8 1. ] Средняя точность: 0.967

Результаты

Рис. 5. Точность классификации

Если указать cross_val = False, тогда для 4-х классификаторов будут выведены карты вероятностей (рис. 6):

Карты вероятностей

Рис. 6. Карты вероятностей для SVL, RF, AB и DT

Достигнутая точность классификации ниже, поскольку для обучения были использованы только две характеристики: длина и ширина чашелистика:
Точность классификации:
SVL: 79.3%
RF: 83.3%
AB: 72.0%
DT: 92.7%

Решение задачи классификации с помощью нейронной сети

Выполняется следующим кодом:

import numpy as np # for random
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # Для управления 3D-изображением (посредством мышки)
from sklearn import datasets
from sklearn import model_selection # for split
import keras # keras.utils.to_categorical
from keras.models import Sequential
from keras.layers import Dense
from keras import backend as K
#
def myLoss(y_true, y_pred):
    return K.mean(K.square(y_pred - y_true))
#
seed = 348
np.random.seed(seed)
# Загружаем набор из библиотеки scikit-learn
iris = datasets.load_iris() # iris - dictionary-like object
X = iris.data
y = iris.target
# Выделяем обучающую и тестовую выборки
x_train, x_test, y_train, y_test = model_selection.train_test_split(X, y, test_size = 0.20) #, random_state = seed)
y_train = keras.utils.to_categorical(y_train, 3) # 3 - число классов; необязательный параметр
y_test_cat = keras.utils.to_categorical(y_test, 3)
# Создаем НС
model = Sequential()
model.add(Dense(units = 16, input_dim = 4, activation = 'relu'))
##model.add(Dense(48, activation = 'relu'))
##model.add(Dense(16, activation = 'relu'))
# softmax или sigmoid - функция активация нейрона последнего слоя
model.add(Dense(3, activation = 'softmax')) # softmax, sigmoid
##model.compile(loss = 'mse', optimizer = 'adam', metrics = ['accuracy']) # mean_squared_error, Adam
model.compile(loss = myLoss, optimizer = 'adam', metrics = ['accuracy']) # mean_squared_error, Adam
model.summary()
#
# Обучение нейронной сети
print('\nОбучение')
model.fit(x_train, y_train, epochs = 60, batch_size = 10, verbose = 0)
#
# Оценка результата
print('\nТестирование')
scores = model.evaluate(x_test, y_test_cat, verbose = 2)
#
print("%s: %.2f%%" % (model.metrics_names[0], scores[0]*100)) # loss (потери)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100)) # acc (точность)
#
# Прогноз
classes = model.predict_classes(x_test) # , batch_size = 10
# np.sum(classes == y_test) вернет сумму случаев, когда classes[i] = y_test[i]
# Поскольку в тестовой выборке 30 элементов (150 * 0.2), то для получения % пишем '/ 30.0 * 100'
accuration = np.sum(classes == y_test) / 30.0 * 100
print("Точность прогнозирования: " + str(accuration) + '%')
print("Прогноз:")
print(classes)
print("На самом деле:")
print(y_test)
if True:
    # Выводим результаты наблюдений (по 3-м характеристикам)
    fig = plt.figure(1, figsize = (5, 4))
    ax = Axes3D(fig, rect = [0, 0, .95, 1], elev = 48, azim = 134)
    for name, label in [('Setosa', 0), ('Versicolor', 1), ('Virginica', 2)]:
        ax.text3D(X[y == label, 3].mean(),
                 X[y == label, 0].mean(),
                 X[y == label, 2].mean() + 2, name,
                 horizontalalignment = 'center',
                 bbox = dict(alpha = 0.2, edgecolor = 'w', facecolor = 'w'))
    ax.scatter(X[:, 3], X[:, 0], X[:, 2], c = y, edgecolor = 'k')
    ax.w_xaxis.set_ticklabels([])
    ax.w_yaxis.set_ticklabels([])
    ax.w_zaxis.set_ticklabels([])
    ax.set_xlabel('Ширина лепестка')
    ax.set_ylabel('Длина чашелистика')
    ax.set_zlabel('Длина лепестка')
    ax.set_title('Ирисы Фишера')
    ax.dist = 12
    fig.show()

Получены следующие результаты:

Тестирование:
loss: 3.55%
acc: 100.00%
Точность прогнозирования: 100.0%
Прогноз:
[0 1 0 1 2 0 1 2 2 0 0 2 0 2 1 0 0 1 1 1 1 2 0 1 2 0 0 2 2 1]
На самом деле:
[0 1 0 1 2 0 1 2 2 0 0 2 0 2 1 0 0 1 1 1 1 2 0 1 2 0 0 2 2 1]

Литература

  1. Ирисы Фишера. [Электронный ресурс] URL: https://ru.wikipedia.org/w/index.php?title=%D0%98%D1%80%D0%B8%D1%81%D1%8B_%D0%A4%D0%B8%D1%88%D0%B5%D1%80%D0%B0&stable=0&redirect=no (Дата обращения: 27.05.2018).
  2. Scikit-learn. [Электронный ресурс] URL: http://scikit-learn.org/stable/auto_examples/classification/plot_classifier_comparison.html\ (Дата обращения: 27.05.2018).
  3. K-means Clustering. [Электронный ресурс] URL: http://scikit-learn.org/stable/auto_examples/cluster/plot_cluster_iris.html#sphx-glr-auto-examples-cluster-plot-cluster-iris-py (Дата обращения: 27.05.2018).

Список работ

Рейтинг@Mail.ru