Индекс Джини и энтропия являются критериями расчета прироста информации. Алгоритмы дерева решений используют прирост информации для разделения узла.
И Джини, и энтропия являются мерами загрязнения узла. Узел, имеющий несколько классов, является нечистым, тогда как узел, имеющий только один класс, является чистым. Энтропия в статистике аналогична энтропии в термодинамике, где она означает беспорядок. Если в узле есть несколько классов, в этом узле есть беспорядок.
Прирост информации представляет собой энтропию родительского узла за вычетом суммы взвешенных энтропий дочерних узлов.
Вес дочернего узла — это количество выборок в узле/общее количество выборок всех дочерних узлов. Аналогичным образом прирост информации рассчитывается с помощью показателя Джини.
# Let's create functions to calculate gini and entropy scores # Imports from math import log # calcpercent calculates the number of samples and percentages of each class def calcpercent(node): nodesum = sum(node.values()) percents = {c:v/nodesum for c,v in node.items()} return nodesum, percents # giniscore calculates the score for a node using above formula def giniscore(node): nodesum, percents = calcpercent(node) score = round(1 - sum([i**2 for i in percents.values()]), 3) print('Gini Score for node {} : {}'.format(node, score)) return score # entropy score calculates the score for a node using above formula def entropyscore(node): nodesum, percents = calcpercent(node) score = round(sum([-i*log(i,2) for i in percents.values()]), 3) print('Entropy Score for node {} : {}'.format(node, score)) return score # infogain calculates the information gain given parent node, child nodes and criterion def infogain(parent, children, criterion): score = {'gini': giniscore, 'entropy': entropyscore} metric = score[criterion] parentscore = metric(parent) parentsum = sum(parent.values()) weighted_child_score = sum([metric(i)*sum(i.values())/parentsum for i in children]) gain = round((parentscore - weighted_child_score),2) print('Information gain: {}'.format(gain)) return gain # Parent node parent_node = {'Red': 3, 'Blue':4, 'Green':5 } # Let's say after the split nodes are node1 = {'Red':3, 'Blue':4} node2 = {'Green':5} gini_gain = infogain(parent_node, [node1, node2], 'gini') Gini Score for node {'Red': 3, 'Green': 5, 'Blue': 4} : 0.653 Gini Score for node {'Red': 3, 'Blue': 4} : 0.49 Gini Score for node {'Green': 5} : 0.0 Information gain: 0.37 entropy_gain = infogain(parent_node, [node1, node2], 'entropy') Entropy Score for node {'Red': 3, 'Green': 5, 'Blue': 4} : 1.555 Entropy Score for node {'Red': 3, 'Blue': 4} : 0.985 Entropy Score for node {'Green': 5} : 0.0 Information gain: 0.98 # Performance wise there is not much difference between entropy and gini scores. # Imports import numpy as np import pandas as pd import os from sklearn.feature_extraction.text import CountVectorizer from sklearn.model_selection import cross_val_score from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier from sklearn.naive_bayes import MultinomialNB from sklearn.ensemble import RandomForestClassifier # Load Dataset # Dataset can be found at: https://www.kaggle.com/uciml/sms-spam-collection-dataset df = pd.read_csv('spam.csv', encoding = 'latin-1' ) # Keep only necessary columns df = df[['v2', 'v1']] # Rename columns df.columns = ['SMS', 'Type'] df.head() # Let's view top 5 rows of the loaded dataset df.head()
# Let's process the text data # Instantiate count vectorizer countvec = CountVectorizer(ngram_range=(1,4), stop_words='english', strip_accents='unicode', max_features=1000) cdf = countvec.fit_transform(df.SMS) # Instantiate algos dt_gini = DecisionTreeClassifier(criterion='gini') dt_entropy = DecisionTreeClassifier(criterion='entropy') # ests = {'Logistic Regression':lr,'Decision tree': dt,'Random forest': rf, 'Naive Bayes': mnb} ests = {'Decision tree with gini index': dt_gini, 'Decision tree with entropy': dt_unbal} for est in ests: print("{} score: {}%".format(est, round(cross_val_score(ests[est],X=cdf.toarray(), y=df.Type.values, cv=5).mean()*100, 3))) print("\n") Decision tree with gini index score: 96.572% Decision tree with entropy score: 96.464%
Как мы видим, нет большой разницы в производительности при использовании индекса Джини по сравнению с энтропией в качестве критерия разделения. Поэтому в качестве критерия расщепления можно использовать любой из показателей Джини или энтропии.
Ссылка на официальный пост об индексе Джини и энтропии: https://thatascience.com/learn-machine-learning/gini-entropy/
Дополнительные подробные руководства можно найти на https://thatascience.com.
Чтобы получить помощь по Python и машинному обучению, посетите: Справка Python
Скоро будет новый подробный мастер-класс.
Быть в курсе !!!