ID3算法中数组越界问题排查及对应Python代码分析
问题排查与代码修正
我来帮你解决这段ID3算法实现里的数组越界问题,同时修正信息熵计算的对数基底问题:
1. 数组越界的根源
在p函数的循环里,你写了Fx[i-1],但循环是for i in range(len(Fx))——当i=0时,i-1=-1,虽然NumPy数组允许负索引(会取最后一个元素),但这完全违背了遍历所有样本标签的逻辑,而且如果是普通Python列表的话,这里直接就会抛出索引越界错误。正确的做法是直接用Fx[i]来遍历每个标签元素。
2. 信息熵的对数基底修正
原代码里用了np.log(自然对数),但ID3算法的信息熵需要以2为底的对数,所以要替换成np.log2。另外还要注意:当某类别的概率为0时,log2(0)会返回-inf,导致熵计算错误,所以需要添加判断处理这种边界情况。
修正后的完整代码
import numpy as np training_set = np.array([[0, 1, 0, 1, 0, 1], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0], [0, 1, 1, 1, 0, 1], [0, 1, 0, 0, 1, 1], [1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 0, 1], [0, 1, 1, 0, 1, 0], [1, 1, 0, 0, 0, 1], [1, 0, 0, 0, 1, 0]]) def p(X): # 提取最后一列作为标签 Fx = X[:, X.shape[1]-1] x0 = 0 # 标签为1的样本数 x1 = 0 # 标签为0的样本数 for i in range(len(Fx)): # 修正索引:直接用i访问当前元素,避免i-1导致的逻辑错误和潜在越界 if Fx[i] == 1: x0 += 1 else: x1 += 1 total = len(Fx) P0 = x0 / total if total != 0 else 0 P1 = x1 / total if total != 0 else 0 return (P0, P1) def H(X): p0, p1 = p(X) # 处理概率为0的情况,避免log2(0)的错误 term0 = -p0 * np.log2(p0) if p0 > 0 else 0 term1 = -p1 * np.log2(p1) if p1 > 0 else 0 return term0 + term1
额外说明
- 修正后的
p函数不仅解决了索引问题,还添加了样本总数为0的边界判断(避免空数据集时的除零错误)。 H函数里的条件判断确保了当某类样本不存在时,对应的熵项为0,符合信息熵的定义(0概率的类别对熵没有贡献)。
内容的提问来源于stack exchange,提问作者Kamil Septio Trojnar
相关产品推荐
相关产品推荐

