实现初衷:学业要求,本想从网上copy,但为了那点可怜的自尊心,花费一个周末写了ID3算法,用了一个周末确实有点菜。
声明:实现该算法时,使用的都是些基本函数,并未设计高深的函数。实现的过程冗余度也很高,没有进行优化也并未达到可以对很多数据进行处理。当然如果想要进行多数据处理,可以再次算法基础上改进一下。全部代码在底部。
需要解决的问题
如图所示
思路
先对数据进行处理,使用pandas包将数据转化为易处理的数据
对数据的每一列进行计数,统计每一列的元素出现的个数
计算信息熵,这也是非常重要的一步,信息熵决定了每个属性判断的先后
排序选优
建模型
全部代码如下所示
import math
import pandas as pd
import numpy as np
data = [[0, 2, 0, 0, 0], # 数据集
[0, 2, 0, 1, 0],
[1, 2, 0, 0, 1],
[2, 1, 0, 0, 1],
[2, 0, 1, 0, 1],
[2, 0, 1, 1, 0],
[1, 0, 1, 1, 1],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 1],
[2, 1, 1, 0, 1],
[0, 1, 1, 1, 1],
[1, 1, 0, 1, 1],
[1, 2, 1, 0, 1],
[2, 1, 0, 1, 0]]
data = np.array(data)
df = pd.DataFrame(data) # 转为df
# 计数
def count(data, a):
df = pd.DataFrame(data)
sum = {}
for i in range(len(df[a].value_counts())): # 遍历目标列的数据个数
m1 = df[a].value_counts().values[i]
sum[i] = m1 # 存储到sum中
return sum
# 信息熵
def allInformationEntropy(data, a):
m2 = count(data, a) #计数
m3 = len(data)
ie = 0
for i in range(len(m2)): # for循环计算每个项
ie1 = (m2[i] / m3 * math.log2(m2[i] / m3)) * (-1)
i += 1
ie += ie1
return ie
# 分叉信息熵
# 先将每一列的元素提取出来,在分别提取(去掉其余列,如何进行上述迭代)
def InformationEntropy(data, a):
df = pd.DataFrame(data)
ie = 0
m5 = 0
for i in range(len(df[a].value_counts())):
data1 = df[df[a] == i] # 删除不想要的行
m2 = count(data1, 4) #对新的数据最后结果计数
m3 = len(data1) #选出来的label的行数
for j in range(len(m2)): # for循环计算每个项
# print(m2[j])
ie1 = ((m2[j] / m3) * (math.log2(m2[j] / m3))) * (-1)
j += 1
ie += ie1
# print(ie)
m4 = (m3 / len(data)) * ie
# print(m4)
i += 1
m5 += m4 # 该列总的E
ie=0
# print(m5)
return m5
def Gain(m,n): #m为总的 n 为每个决策
return m - n
#选优
def best(data):
a4 = allInformationEntropy(data, 4)
a3 = InformationEntropy(data, 3)
a2 = InformationEntropy(data, 2)
a1 = InformationEntropy(data, 1)
a0 = InformationEntropy(data, 0)
g0 = Gain(a4, a0)
g1 = Gain(a4, a1)
g2 = Gain(a4, a2)
g3 = Gain(a4, a3)
list= [g0,g1,g2,g3] #0 2 3 1
return list
def makingDecision(data,test):
#判断test的列的优先级
list =best(data)
list1 = best(data)
first = max(list)
firstDecision1 = list1.index(first)
list.remove(first)
second = max(list)
secondDecision1 = list1.index(second)
list.remove(second)
three = max(list)
threeDecision1 = list1.index(three)
list.remove(three)
four = max(list)
fourDecision1 = list1.index(four)
# list = best(data)
firstDecision = test[firstDecision1]
secondDecision = test[secondDecision1]
threeDecision = test[threeDecision1]
fourDecision = test[fourDecision1]
data1 = df[df[firstDecision1] == firstDecision] #选取第一列 0
df1 = pd.DataFrame(data1)
if(df1[4].nunique()!=1): #用if语句决策 根据信息增益得到各个决策的高低 读取test数据的最优那一列的数据,筛选数据,这样重复得出结果
data2 = df1[df1[secondDecision1] == secondDecision] #选取第二列 2
df2 = pd.DataFrame(data2)
if(df2[4].nunique()!=1):
data3 = df2[df2[threeDecision1] == threeDecision] #选第三列 3
df3 = pd.DataFrame(data3)
if (df3[4].nunique() != 1):
data4 = df3[df3[fourDecision1] == fourDecision] #选第四列 1
df4 = pd.DataFrame(data4)
# print(df4[4].values)
return df4[4].values.max()
else:
# print(df3[4].values)
return df3[4].values.max()
else:
# print(df2[4].values)
return df2[4].values.max()
else:
# print(df1[4].values)
return df1[4].values.max()
#执行
if __name__ == '__main__':
test = [0,0,0,1]
result = makingDecision(data,test)
# print(result)
if result == 0:
print("不买")
if result == 1:
print("买")
结果
所有步骤的说明均写在代码中。
本模型并未建树,但是思路和建树大体一样,我也不太清楚算不算建树,每一次test,都是根据已有的分层模型进行处理得出结果。