#coding=utf-8
from math import log
def create_data():
#'''创建样本'''
data=[[1,1,'Y'],
[1,1,'Y'],
[1,0,'N'],
[0,1,'N'],
[0,1,'N'],
]
labels=['no surfacing','flippers']
return data,labels
def shannon_entropy(data):
"""计算香农熵"""
enteries=len(data)
#样本总数
label_count={}
#创建字典用来统计类别出现的频率
for v in data:
#遍历样本
current_label=v[-1]
#获取当前类别
if current_label not in label_count.keys():
label_count[current_label]=0
#判断当前类别是否在字典中,不在的话计数为0
label_count[current_label]+=1
#对类别计数
entropy=0.0
#初始熵为0
for key in label_count:
#遍历字典
prob=float(label_count[key])/enteries
#计算各类类别在样本总数中出现的概率
entropy-=prob*log(prob,2)
#计算香农熵,公式:H(x)=P(x)log2P(x) 以2为底的对数
return entropy
def split_data(data,axis,value):
"""根据某一特征划分数据"""
ret_data=[]
#结果列表
for v in data:
#遍历样本
if v[axis]==value:
#v[axis]样本中第axis的特征,value 预期的特征值
reduced_v=v[:axis]
#样本前axis个值
reduced_v.extend(v[axis+1:])
#样本后axis个值
ret_data.append(reduced_v)
#得到的结果就是除选定的特征外样本中其他的值
#根据需求可返回不同的结果。比如我只想根据axis=1这个条件返回Y or N这个结果
#reduced_v=v[axis+1:] ... ret_data.append(reduced_v) 或者
#单成一个列表 ret_data.extend(v[axis+1:])
return ret_data
def best_split_feature(data):
"""选择最佳特征 即 最小熵 """
feature_number=len(data[0])-1
#获取特征数目。即,这组数据有几个特征
base_entropy=shannon_entropy(data)
#以样本的香农熵为基础熵
best_entropy=0.0;best_feature=-1
#初始化最佳熵和最佳特征。这个best_feature定义的常量应该是随意的。
for i in range(feature_number):
#遍历特征
feature_list=[example[i] for example in data]
#特征列表。i=0时,就是每个样本第一个特征所构成的列表
unique_value=set(feature_list)
#剔除特征列表列表中的重复值
new_entropy=0.0
#设定新熵为0
for value in unique_value:
#遍历具有唯一性的特征列表
sub_data=split_data(data,i,value)
#根据唯一的特征划分数据
prob=len(sub_data)/float(len(data))
#计算按各特征划分后所占数据总量的比例
new_entropy+=prob*shannon_entropy(sub_data)
#计算香农熵
info=base_entropy-new_entropy
#基础熵-新熵
if (info > best_entropy):
best_entropy=info
#对比,传值
best_feature=i
return best_feature
以香农熵为基础选择最佳特征
最新推荐文章于 2024-01-03 22:05:27 发布