解题思路
- 计算整个数据集的信息熵
- 对每个特征:
- 计算条件熵(按特征取值划分子集)
- 计算特征固有值(属性熵)
- 计算信息增益比
- 选择信息增益比最大的特征
代码解析
import sys
from math import log
def calcInfoEnt(data):
"""计算数据集的信息熵"""
numEntres = len(data)
labelcnt = {} # 统计各类标签数量
for item in data:
label = item[-1] # 最后一列为标签
labelcnt[label] = labelcnt.get(label, 0) + 1
infoEnt = 0.0
for count in labelcnt.values():
prob = count / numEntres # 计算概率
infoEnt -= prob * log(prob, 2) # 累加熵值
return infoEnt
def create_sub_dataset(dataSet, i, value):
"""根据特征值划分子集(移除当前特征列)"""
res = []
for item in dataSet:
if item[i] == value:
# 拼接特征i前后的列
curr_data = item[:i] + item[i+1:]
res.append(curr_data)
return res
def calc_max_info_gain_ratio(dataSet):
"""计算信息增益比最大的特征"""
n = len(dataSet[0]) - 1 # 特征数(最后一列为标签)
total_entropy = calcInfoEnt(dataSet) # 总信息熵
best_feature = 0 # 最佳特征索引
best_gain_ratio = 0.0 # 最佳信息增益比
for i in range(n): # 遍历每个特征
# 获取特征i的所有取值
unique_val = set(item[i] for item in dataSet)
cur_info_ent = 0.0 # 条件熵
info_V = 0.0 # 属性熵(特征固有值)
for val in unique_val:
# 划分子集(特征i取值为val的样本)
sub_dataset = create_sub_dataset(dataSet, i, val)
prob = len(sub_dataset) / len(dataSet) # 当前取值概率
# 累加条件熵
cur_info_ent += prob * calcInfoEnt(sub_dataset)
# 累加属性熵(跳过概率为0的情况)
if prob > 0:
info_V -= prob * log(prob, 2)
# 计算信息增益
info_gain = total_entropy - cur_info_ent
# 计算信息增益比(避免除零错误)
if info_V == 0:
gain_ratio = 0.0
else:
gain_ratio = info_gain / info_V
# 更新最佳特征
if gain_ratio > best_gain_ratio:
best_gain_ratio = gain_ratio
best_feature = i
return best_feature
if __name__ == "__main__":
data = eval(sys.stdin.readline().strip())
result = calc_max_info_gain_ratio(data)
print(result)
关键函数说明
-
calcInfoEnt(data)
:- 计算数据集的信息熵
- 遍历数据统计标签分布
- 根据熵公式计算结果
-
create_sub_dataset(dataSet, i, value)
:- 根据特征值划分子集
- 移除当前特征列
- 返回新子集
-
calc_max_info_gain_ratio(dataSet)
:- 计算总信息熵
- 遍历每个特征:
- 计算条件熵(各子集熵的加权和)
- 计算属性熵(特征取值分布的熵)
- 计算信息增益比
- 返回信息增益比最大的特征索引
总结
信息增益比通过引入特征固有值,解决了信息增益对多值特征的偏好问题。本题实现的关键步骤:
- 正确计算数据集的信息熵
- 按特征取值划分子集
- 分别计算条件熵和属性熵
- 综合得出信息增益比
- 选择增益比最大的特征
该算法能有效识别最具判别力的特征,优化电商平台的推荐系统。