пʼятниця, 29 жовтня 2021 р.

Приклад побудови дерева рішень в sklearn

Розглянемо побудову дерева для класифікації набору даних ірисів.
import numpy as np
from sklearn import datasets
iris = datasets.load_iris()
X = iris.data
y = iris.target
print('Атрибути даних:',data.target_names)
print('Форма даних:', X.shape)
Атрибути даних:
['setosa' 'versicolor' 'virginica']
Форма даних:
(150,4)
Розбиваємо данні на навчальну та тестову вибірки
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 67, test_size = 0.25)
Імпортуємо Decision tree класифікатор з бібліотеки sklearn, встановлюємо критерій переходу entropy. За умовчанням використовується критерій Джині.
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(criterion = 'entropy')
Навчаємо дерево на навчальному наборі
clf.fit(X_train, y_train)
DecisionTreeClassifier(ccp_alpha=0.0,class_weight=None,criterion='entropy',
max_depth=None, max_features=None, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, presort='deprecated',
random_state=None, splitter='best')
Виконуємо прогнозування міток на тестових даних
y_pred =  clf.predict(X_test)
Знаходимо оцінки точності класифікації
from sklearn.metrics import accuracy_score
print('Точність на тренувальних даних: ', accuracy_score(y_true=y_train, y_pred=clf.predict(X_train)))
print('Точність на тестових даних: ', accuracy_score(y_true=y_test, y_pred=y_pred))
#Output:
Точність на тренувальних даних:  1.0
Точність на тестових даних:  0.9473684210526315
Будуємо матрицю невідповідностей
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
cm = confusion_matrix(y_test, y_pred, labels=clf.classes_)
disp = ConfusionMatrixDisplay(confusion_matrix=cm,display_labels=clf.classes_)
disp.plot()
plt.show()
Як бачимо, на тестовому наборі допущено лише дві помилки.

Візуалізуємо дерево

from matplotlib.pyplot import figure
figure(figsize=(8,10))
from sklearn import tree
tree.plot_tree(clf)
plt.show()
В вузлах дерева знаходяться предикати, які керують процесом класифікації Визначаємо важливість ознак
print("Важливість ознак:  {}".format(clf.feature_importances_))
Важливість ознак:  [0.03417269 0.02454685 0.90530355 0.0359769 ]
Бачимо, що дві останні ознаки вносять найбільший вклад в класифікацію. Тому навчаємо нову модель відкинувши ознаки з меншим вкладом. РОбота з двома ознаками дозволяє візуалізувати області прийняття рішень
from mlxtend.plotting import plot_decision_regions # Потрібно встановити пакет mlxtend
X = iris.data[:, [2, 3]]
y = iris.target
X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3)
clf = DecisionTreeClassifier(criterion='entropy')
clf.fit(X_train, y_train)
plot_decision_regions(X_train, y_train, clf)
plt.xlabel('petal length [cm]')
plt.ylabel('petal width [cm]')
plt.legend(loc='upper left')
plt.tight_layout()
plt.show()

субота, 16 жовтня 2021 р.

Дерева рішень

Дерево рішень(decision trees) це алгоритм машинного навчання для задач класифікації та регресії, який зображується у вигляді повного дерева, як правило бінарного. Кожен листок (термінальний вузол) дерева помічений міткою класу, в кожному вузлі знаходиться деякий предикат, аргументом якого є об'єкт призначений для класифікації. Процес класифікації відбувається шляхом руху об'єкта деревом від кореневого вузла до листка, мітка якого і присвоюється об'єкту, чим і завершується класифікація. Рух об'єкта регулюється предикатами, які в кожному нелистковому вузлі визначають на основі перевірки ознак об'єкта, в який саме із дочірніх вузлів він переміститься. Саме дерево, та форма предикатів в кожному його вузлі, конструюється у процесі навчання.

понеділок, 11 жовтня 2021 р.

Реалізація алгоритму $k$-найближчих сусідів.

Ілюстрація на прикладі датасет wine який вже є в sklearn.
from sklearn import datasets
#завантажуємо dataset
wine = datasets.load_wine()
 
Дані можна при потребі передати в pandas
wine_pd=pd.DataFrame(data= wine.data, columns=wine.feature_names) 
Ці дані є результатами хімічного аналізу вин, вирощених в одному регіоні в Італії, але отриманих з трьох різних сортів винограду. Аналіз визначив 13 хімічних складових, знайдених у кожному з трьох типів вин і які знаходяться в колонках набору.
 # назви ознак 
print(wine.feature_names)
['alcohol', 'malic_acid', 'ash', 'alcalinity_of_ash', 'magnesium', 'total_phenols', 'flavanoids', 'nonflavanoid_phenols', 'proanthocyanins', 'color_intensity', 'hue', 'od280/od315_of_diluted_wines', 'proline']
 
В колонці target знаходиться номер типу - 0, 1, або 2 , до якого відноситься вино з даним хімічним аналізом. Данні записані в масивах 'data', 'target'.
wine.target
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2]) 
Розіб'ємо дані на навчальні і тестові.
#в scikit-learn
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(wine.data, wine.target, test_size=0.3) # 70\% тренувальна вибірка і  30\% тестова
# В  pandas вручну
f_target=df['y']
df_data=df.iloc[:,1:]
X_train, X_test, y_train, y_test = train_test_split(df_data, df_target, test_size=0.3) 
Навчаємо модель для кількості сусідів рівній 5 і виконуємо прогнозування на тестовому наборі. Щоб отримати прогнози для тестових даних, ми викликаємо метод predict. Для кожної точки тестового набору він знаходить її найближчих 5 сусідів в навчальному наборі і знаходить серед них клас який зустрічається найчастіше.
from sklearn.neighbors import KNeighborsClassifier
#Створюємо  KNN класифікатор
knn = KNeighborsClassifier(n_neighbors=5)
#Тренуєил модель на тренувальному  наборі
knn.fit(X_train, y_train)
#Виконуємо прогнозування на тестовому наборі
y_pred = knn.predict(X_test)
y_pred
[1 2 2 2 1 2 2 2 2 0 0 0 2 0 1 2 2 2 0 0 1 0 2 0 2 1 2 2 1 0 2 1 2 1 0 1 2
 1 2 1 0 0 2 1 0 1 2 0 1 2 1 2 1 0]
Для оцінки точності використаємо метрику metrics.accuracy_score, яка обчислює частку правильно класифікованих об'єктів з тестового набору $$ \frac{1}{n}\sum_{i=1}^n [y\_pred[i]=y\_test[i]]. $$ Якщо встановити параметр normalize=False, то метрика повертає загальну кількість елементів двох списків, які співпадають, наприклад
A = [0, 2, 1, 3]
B = [0, 1, 2, 3]
accuracy_score(A, B)
0.5
accuracy_score(A, B, normalize=False)
2
Оцінюємо точність моделі порівнюючи отримані результати з тестовим набором
from sklearn import metrics
print("Accuracy:",metrics.accuracy_score(y_test, y_pred))
Accuracy: 0.6666666666666666
Точність може сильно відрізнятися оскільки залежить від конкретного розбиття даних. Знаходимо при якій кількості сусідів точність найкраща
 X_train , X_test , y_train , y_test = train_test_split(wine.data, wine.target,test_size=0.25)
training_accuracy = []
test_accuracy=[]
# задаємо діапазон n_neighbors від 1 до 30
neighbors_settings = range(1, 30)
for n_neighbors in neighbors_settings:
# будуємо модель
    knn = KNeighborsClassifier(n_neighbors=n_neighbors)
    knn.fit(X_train, y_train)
    y_pred = knn.predict(X_test)
# записуємо точність на навчальному наборі
    training_accuracy.append(metrics.accuracy_score(y_test, y_pred))
# записуємо точність на тестовому  наборі
    test_accuracy.append(metrics.accuracy_score(y_train, y_train_pr))
#Знаходимо найкращу точність
print('Найкраща точність при k=',np.argmax(training_accuracy))
Будуємо графік точності
from matplotlib.pyplot import figure
figure(figsize=(10,8))
plt.plot(neighbors_settings, training_accuracy, label="точність на тестовому наборі")
#plt.plot(neighbors_settings, test_accuracy, label="точність на тестовому наборі")
plt.ylabel("Точність")
plt.xlabel("кількість сусідів")
plt.legend()
Форма графіків, їхнє взаємне розташування та оптимальне значення $k$ залежать від конкрентного розбиття на навчальну та тестову вибірки і можуть сильно відрізнятися від наведеного тут.