1、信息增益(Information Gain)
信息增益(Information Gain,IG)是指由于分割而导致数据集不确定性(熵)的减少。信息增益是选择数据分割点(即决策树节点)的一种方法。信息增益基于熵的概念,旨在选择能够最有效减少数据集不确定性的特征。公式代码如下,
import numpy as np
def entropy(y):
"""计算给定数据集的熵"""
class_counts = np.bincount(y)
probabilities = class_counts / len(y)
return -np.sum([p * np.log2(p) for p in probabilities if p > 0])
def information_gain(y, y_left, y_right):
"""计算分割后的信息增益"""
parent_entropy = entropy(y)
left_entropy = entropy(y_left)
right_entropy = entropy(y_right)
n = len(y)
n_left = len(y_left)
n_right = len(y_right)
ig = parent_entropy - (n_left / n) * left_entropy - (n_right / n) * right_entropy
return ig
# 示例数据
y = np.array([0, 0, 1, 1, 1, 1, 0]) # 原始数据集标签
y_left = np.array([0, 0, 1]) # 分割后的左子集标签
y_right = np.array([1, 1, 0, 0]) # 分割后的右子集标签
# 计算信息增益
ig = information_gain(y, y_left, y_right)
print("信息增益:", ig)
2、分裂信息量(Split Information)
在决策树算法中,除了使用熵(Entropy)来衡量数据的混乱程度外,还可以使用分裂信息量(Split Information)来衡量特征的分裂能力。分裂信息量越小,表示特征的分裂能力越好。分裂信息量的计算通常是使用特征的信息增益(Information Gain)来衡量的。信息增益是熵与分裂后的子节点的熵之差。在计算信息增益时,也需要考虑分裂后每个子节点的样本比例。分裂信息是用来衡量按某特征分裂数据时产生的子集分布的“广度”和“均匀度”。特征的每个值都会创建一个子集,分裂信息量化了这些子集大小的不均衡程度。公式代码如下,
import math
def entropy(p):
if p == 0 or p == 1:
return 0
return -p * math.log2(p) - (1 - p) * math.log2(1 - p)
def information_gain(p_parent, p_children, ent_children):
ent_parent = entropy(p_parent)
ent_children_combined = sum((p * ent for p, ent in zip(p_children, ent_children)))
return ent_parent - ent_children_combined
def split_information(p_children):
return sum((-p * math.log2(p) if p != 0 else 0) for p in p_children)
# 示例:假设分裂后两个子节点的样本比例分别为0.6和0.4
p_children = [0.6, 0.4]
# 计算分裂信息量
split_info = split_information(p_children)
print("分裂信息量为:", split_info)
2、信息增益率(Gain Ratio)
信息增益率是信息增益和分裂信息量的比值,通过使用信息增益率,决策树算法能够更平衡地选择分裂属性,有助于构建更准确和有效的预测模型。信息增益率是对信息增益的一个改进,旨在减少对具有大量值的特征的偏好。
import math
def entropy(data):
"""计算数据集的熵"""
total = len(data)
label_counts = {}
for feat_vec in data:
current_label = feat_vec[-1]
if current_label not in label_counts:
label_counts[current_label] = 0
label_counts[current_label] += 1
ent = 0.0
for key in label_counts:
prob = float(label_counts[key]) / total
ent -= prob * math.log2(prob)
return ent
def split_dataset(data, axis, value):
"""根据特定特征分割数据集"""
ret_data_set = []
for feat_vec in data:
if feat_vec[axis] == value:
reduced_feat_vec = feat_vec[:axis]
reduced_feat_vec.extend(feat_vec[axis+1:])
ret_data_set.append(reduced_feat_vec)
return ret_data_set
def gain_ratio(data, feature_i):
"""计算给定特征的信息增益率"""
total = len(data)
feat_values = {example[feature_i] for example in data}
info_gain = entropy(data)
split_info = 0.0
for value in feat_values:
sub_data_set = split_dataset(data, feature_i, value)
prob = len(sub_data_set) / float(total)
info_gain -= prob * entropy(sub_data_set)
split_info -= prob * math.log2(prob)
if split_info == 0: # 避免除以0
return 0
return info_gain / split_info
# 示例数据集
data = [[1, 'yes'],
[1, 'yes'],
[1, 'no'],
[0, 'no'],
[0, 'no']]
# 如我们想要按照第一个特征(索引为0)计算信息增益率
feature_index = 0
print("信息增益率:", gain_ratio(data, feature_index))