English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Apprendimento dell'algoritmo di classificazione delle decisioni delle decision tree in Python

Dalla parte corrente inizia lo studio ufficiale degli algoritmi.

Prima impariamo l'algoritmo di classificazione classico ed efficace: l'algoritmo di classificazione degli alberi decisionali.

1、Algoritmo di decision tree

L'albero decisionale utilizza una struttura ad albero per classificare le proprietà dei campioni, è l'algoritmo di classificazione più intuitivo e può anche essere utilizzato per la regressione. Tuttavia, ha difficoltà con alcune classificazioni logiche speciali. Tipicamente, come la logica XOR, l'albero decisionale non è particolarmente abile nel risolvere tali problemi.
La costruzione dell'albero decisionale non è unica, purtroppo la costruzione dell'albero decisionale ottimale appartiene al problema NP. Pertanto, come costruire un albero decisionale buono è uno dei punti di ricerca chiave.
J. Ross Quinlan propose nel 1975 di introdurre il concetto di entropia informativa nella costruzione degli alberi decisionali, questo è il famoso algoritmo ID3. Successivi miglioramenti come C4.5, C5.0, CART sono basati su questo metodo.

L'entropia è la misura di 'disordine' e 'confusione'. La prima volta che si incontra questo concetto potrebbe essere confuso. Per comprendere rapidamente come dividere l'attributo utilizzando il guadagno di entropia informativa, si può fare riferimento all'articolo di questo collega: Python Machine Learning Decision Tree Algorithm

Se non si capisce ancora, guardate questo esempio sottostante.

Supponiamo di voler costruire un albero decisionale automatico per selezionare mele buone, per semplificare, lo lascio apprendere solo questi 4 campioni:
Campione Rosso Grande Buona mela 
0  1  1  1 
1  1  0  1 
2  0  1  0 
3  0  0  0 

Il campione ha 2 attributi, A0 rappresenta se è una mela rossa. A1 rappresenta se è una mela grande.

Quindi l'entropia informativa di questo campione prima della classificazione è S = -(1/2 * log(1/2) + 1/2 * log(1/2)) = 1.

L'entropia informativa di 1 indica che ci si trova nello stato più caotico e disordinato.

Questo esempio ha solo 2 attributi. Pertanto, naturalmente, ci possono essere solo 2 alberi decisionali, come illustrato di seguito:

Evidentemente, il decision tree di sinistra che utilizza A0 (rosso) come base di divisione è migliore rispetto a quello di destra che utilizza A1 (dimensione) come base di divisione.
Certo, questo è un'interpretazione intuitiva. Per un esame quantitativo, è necessario calcolare il guadagno di entropia informativa di ogni situazione di divisione.
Prima si seleziona A0 come divisione, il calcolo dell'entropia informativa di ciascun sotto-nodo è il seguente:
I nodi fogli 0 e 1 hanno 2 esempi positivi e 0 esempi negativi. L'entropia è: e1 = -(2/2 * log(2/2) + 0/2 * log(0/2)) = 0.
I nodi fogli 2 e 3 hanno 0 esempi positivi e 2 esempi negativi. L'entropia è: e2 = -(0/2 * log(0/2) + 2/2 * log(2/2)) = 0.

Quindi la scelta di A0 divide l'entropia informativa in un peso ponderato per ogni sotto-nodo dell'entropia informativa: E = e1*2/4 + e2*2/4 = 0.
选择A0做划分的信息熵增益G(S, A0)=S - E = 1 - 0 = 1.

事实上,决策树叶子节点表示已经都属于相同类别,因此信息熵一定为0。

同样的,如果先选A1作划分,各子节点信息熵计算如下:
0,2子节点有1个正例,1个负例。信息熵为:e1 = -(1/2 * log(1/2) + 1/2 * log(1/2)) = 1。
1,3子节点有1个正例,1个负例。信息熵为:e2 = -(1/2 * log(1/2) + 1/2 * log(1/2)) = 1。
因此选择A1划分后的信息熵为每个子节点的信息熵所占比重的加权和:E = e1*2/4 + e2*2/4 = 1。也就是说分了跟没分一样!
选择A1做划分的信息熵增益G(S, A1)=S - E = 1 - 1 = 0.
因此,每次划分之前,我们只需要计算出信息熵增益最大的那种划分即可。

2、数据集

为方便讲解与理解,我们使用如下一个极其简单的测试数据集:
1.5 50 thin 
1.5 60 fat 
1.6 40 thin 
1.6 60 fat 
1.7 60 thin 
1.7 80 fat 
1.8 60 thin 
1.8 90 fat 
1.9 70 thin 
1.9 80 fat 

这个数据一共有10个样本,每个样本有2个属性,分别为身高和体重,第三列为类别标签,表示“胖”或“瘦”。该数据保存在1.txt中。

我们的任务就是训练一个决策树分类器,输入身高和体重,分类器能给出这个人是胖子还是瘦子。
(数据是作者主观臆断,具有一定逻辑性,但请无视其合理性)

决策树对于“是非”的二值逻辑的分枝相当自然。而在本数据集中,身高与体重是连续值怎么办呢?

虽然麻烦一点,不过这也不是问题,只需要找到将这些连续值划分为不同区间的中间点,就转换成了二值逻辑问题。
本例决策树的任务是找到身高、体重中的一些临界值,按照大于或者小于这些临界值的逻辑将其样本两两分类,自顶向下构建决策树。

使用python的机器学习库,实现起来相当简单和优雅。

3、Python实现

Python代码实现如下:

# -*- coding: utf-8 -*- 
import numpy as np 
import scipy as sp 
from sklearn import tree 
from sklearn.metrics import precision_recall_curve 
from sklearn.metrics import classification_report 
from sklearn.cross_validation import train_test_split 
'''Lettura dei dati''' 
data  = [] 
labels = [] 
with open("data\\1.txt") as ifile: 
    for line in ifile: 
      tokens = line.strip().split(' ') 
      data.append([float(tk) for tk in tokens[:-1]]) 
      labels.append(tokens[-1]) 
x = np.array(data) 
labels = np.array(labels) 
y = np.zeros(labels.shape) 
'''Converti i tag in 0/1''' 
y[labels=='fat']=1 
'''Dividi i dati di addestramento e di test''' 
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2) 
'''Utilizza l'entropia come criterio di divisione per addestrare l'albero decisionale''' 
clf = tree.DecisionTreeClassifier(criterion='entropy') 
print(clf) 
clf.fit(x_train, y_train) 
'''Scrivi la struttura dell'albero decisionale nel file''' 
with open("tree.dot", 'w') as f: 
  f = tree.export_graphviz(clf, out_file=f) 
'''I coefficienti riflettono l'influenza di ciascuna caratteristica. Più grandi sono, maggiore è l'effetto della caratteristica nella classificazione''' 
print(clf.feature_importances_) 
'''Stampa dei risultati del test''' 
answer = clf.predict(x_train) 
print(x_train) 
print(answer) 
print(y_train) 
print(np.mean( answer == y_train)) 
'''''Precisione e recall''' 
precision, recall, thresholds = precision_recall_curve(y_train, clf.predict(x_train)) 
answer = clf.predict_proba(x)[:,1] 
print(classification_report(y, answer, target_names = ['thin', 'fat'])) 

Il risultato dell'output è simile al seguente:
[ 0.2488562  0.7511438]
array([[  1.6,  60. ]
       [  1.7,  60. ]
       [  1.9,  80. ]
       [  1.5,  50. ]
       [  1.6,  40. ]
       [  1.7,  80. ]
       [  1.8,  90. ]
       [  1.5,  60. ]
array([ 1.,  0.,  1.,  0.,  0.,  1.,  1.,  1.])
array([ 1.,  0.,  1.,  0.,  0.,  1.,  1.,  1.])
1.0
             precisione  recall  f1-score  supporto
       thin       0.83      1.00      0.91         5
        fat        1.00      0.80      0.89         5
avg / total       1.00      1.00      1.00         8
array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  0.])
array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.])

Si può vedere che, testando i dati addestrati, l'accuratezza è del 100%. Tuttavia, testando tutti i dati, ci sarà un campione di test classificato in modo errato.
L'albero decisionale dell'esempio assorbe bene le regole del set di addestramento, ma la predizione è leggermente inferiore.
Ci sono tre punti da spiegare, che saranno utilizzati in futuro nell'apprendimento automatico.

1. Dividere i dati di addestramento e i dati di test.

Questo viene fatto per facilitare la cross-validation. La cross-validation serve a testare a fondo la stabilità del classificatore.
Il valore 0.2 nel codice rappresenta il 20% dei dati randomici utilizzati per il test. Gli altri 80% vengono utilizzati per addestrare l'albero decisionale.
Questo significa che 8 campioni sono stati selezionati casualmente per l'addestramento tra 10 campioni. Il set di dati di questo articolo è piccolo, e lo scopo di questo è vedere che a causa della selezione casuale dei dati di addestramento, l'albero decisionale costruito ogni volta è diverso.

2. Fattori di influenza diversi delle caratteristiche.

Le differenze nel peso delle diverse caratteristiche dei campioni avranno un grande impatto sulla classificazione. Vedere l'impatto di ciascun campione sulla classificazione alla fine è anche molto importante.
In questo esempio, il peso dell'altezza è 0.25, il peso del peso è 0.75, è possibile vedere che l'importanza del peso è molto superiore a quella dell'altezza. Per il giudizio di grasso e magro, questo è anche abbastanza logico.

3. Accuratezza e ricall.

Questi due valori sono un importante standard di valutazione dell'accuratezza di classificazione. Ad esempio, nel codice finale, tutti i 10 campioni sono stati immessi nel classificatore per il test:
Risultato di test: array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  0.])
Risultato reale: array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.])
L'accuratezza della classificazione come magro è 0.83. Questo è perché il classificatore ha classificato 6 magri, dei quali 5 sono corretti, quindi l'accuratezza della classificazione come magro è 5/6 = 0.83.
Il ricall della classificazione come magro è 1.00. Questo è perché ci sono 5 magri nel set di dati, e il classificatore li ha tutti classificati correttamente (anche se ha classificato un grasso come magro!), il ricall è 5/5 = 1.
L'accuratezza della classificazione come grasso è 1.00. Senza ulteriori considerazioni.
Il ricall della classificazione come grasso è 0.80. Questo è perché ci sono 5 grassi nel set di dati, e il classificatore ha classificato solo 4 (ha classificato un grasso come magro!), il ricall è 4/5 = 0.80.
Spesso, specialmente in casi di classificazione di dati complessi, l'accuratezza e il ricall sono spesso in conflitto. Potrebbe essere necessario trovare il miglior punto di equilibrio in base alle tue esigenze.
Ad esempio, nel presente esempio, il tuo obiettivo è garantire il più possibile che i grassi trovati siano veramente grassi (accuratezza), o garantire che si trovino il maggior numero possibile di grassi (ricall).

Il codice ha anche scritto la struttura dell'albero decisionale nel file tree.dot. Aprire questo file, è facile disegnare l'albero decisionale, e vedere anche ulteriori informazioni di classificazione dell'albero decisionale.
Il seguente è il file tree.dot di questo articolo:

digraph Tree { 
0 [label="X[1] <= 55.0000\nentropia = 0.954434002925\nsamples = 8", shape="box"] ; 
1 [label="entropia = 0.0000\nsamples = 2\nvalue = [ 2. 0.]", shape="box"] ; 
0 -> 1 ; 
2 [label="X[1] <= 70.0000\nentropy = 0.650022421648\nsamples = 6", shape="box"] ; 
0 -> 2 ; 
3 [label="X[0] <= 1.6500\nentropy = 0.918295834054\nsamples = 3", shape="box"] ; 
2 -> 3 ; 
4 [label="entropy = 0.0000\nsamples = 2\nvalue = [ 0. 2.]", shape="box"] ; 
3 -> 4 ; 
5 [label="entropy = 0.0000\nsamples = 1\nvalue = [ 1. 0.]", shape="box"] ; 
3 -> 5 ; 
6 [label="entropy = 0.0000\nsamples = 3\nvalue = [ 0. 3.]", shape="box"] ; 
2 -> 6 ; 
} 

Secondo questa informazione, l'albero di decisione dovrebbe essere così:

Questo è tutto il contenuto dell'articolo, spero che sia utile per la tua apprendimento, e ti prego di supportare fortemente il tutorial di urla.

Dichiarazione: il contenuto di questo articolo è stato tratto da Internet, il diritto d'autore è dell'autore originale, il contenuto è stato contribuito autonomamente dagli utenti di Internet e caricato autonomamente, il sito web non possiede il diritto di proprietà, non è stato elaborato manualmente e non assume responsabilità legali correlate. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una e-mail a: notice#oldtoolbag.com (al momento dell'invio dell'e-mail, sostituisci # con @) per segnalare e fornire prove pertinenti. Una volta verificata, il sito eliminerà immediatamente il contenuto sospetto di violazione del copyright.

Ti potrebbe interessare