您的位置:首页 > 其它

机器学习之朴素贝叶斯法(基于西瓜数据3.0的算法实现)

2017-10-15 17:19 621 查看
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。简单的说就是,假设特征条件之间独立,无相互之间的影响(这也是"朴素"的含义),在此情况下运行贝叶斯定理进行分类。

朴素贝叶斯方法是一种生成模型,对于输入

和类别

,生成式模型估计联合概率分布

,而判别式模型估计条件概率分布



朴素贝叶斯的思想是:对于给定的输入(也就是待判别的条件),通过学习到的模型计算后验概率分布

,将后验概率最大的类

作为x的类输出。也就是说计算输入条件为每个类的可能性,可能性最大的作为输入的类输出。

朴素贝叶斯将实例分到后验概率最大的类中,这等价于期望风险最小化。根据期望风险最小化准则,得到后验概率最大化准则(推导见统计学习方法第4章):



也就是上面说的朴素贝叶斯的思想。
朴素贝叶斯法公式为:



其中,



的计算运用了极大似然法估计相应的概率。

朴素贝叶斯的优点:

方法简单,学习和预测的效率高,易于实现,对小规模数据表现较好;

可以增量式训练;

对数据缺失不敏感

缺点:

条件独立性牺牲一定的分类准确率;

计算先验概率的准确性依赖于概率模型的选择,先验概率模型不准回导致结果不准;

对输入数据的表达形式很敏感。

应用场景:

数据样本较少,标称型数据(0/1)

朴素贝叶斯算法实现:

利用Pandas库导入数据,较以前使用的方法更便于后面处理和使用。

def loadDatapd(filename):
data = pd.read_csv(filename,encoding='gb2312')
del data[u'编号'] #删除编号列,用index做编号
return data


将导入的数据中的中文用数字编码来代替,方便使用。

def toNum(data_input): #pd格式的中文
data = data_input.copy()
map_dictionary = {
u'浅白': 0,
u'青绿': 1,
u'乌黑': 2,
u'蜷缩': 0,
u'稍蜷': 1,
u'硬挺': 2,
u'沉闷': 0,
u'浊响': 1,
u'清脆': 2,
u'模糊': 0,
u'稍糊': 1,
u'清晰': 2,
u'凹陷': 0,
u'稍凹': 1,
u'平坦': 2,
u'硬滑': 0,
u'软粘': 1,
u'是': 1,
u'否': 0
}
for feat in data.columns[:-4]:
data[feat] = data_input[feat].map(map_dictionary)
data[u'好瓜'] = data_input[u'好瓜'].map(map_dictionary)
return data


这里假设密度和含糖量服从正态分布,定义正态分布函数计算:

def st_norm(x,uci,eci):
return 1.0/(math.sqrt(2*math.pi)*eci)*math.e**(-(x - uci)**2/(2*eci**2))


朴素贝叶斯模型训练,将所有的先验概率计算出来,在预测函数中按需要取概率就可以了。

Pc用于存储类别先验概率,Pcx存储所有特征的每个特征值的先验概率,Uc,Ue存储正态分布的两个参数。

#P(c|x) = P(c)*P(x|c)/P(x)
def bayes(data_input):
dataset = data_input.copy()
Pc = {}   #用于存储P(c)
Pcx = {}  #用于存储P(x|c)
Uc = {}
Ue = {}
c_valuecount = dataset[u'好瓜'].value_counts() #样本的总数
for c in c_valuecount.index:
c_count = c_valuecount[c]
N_count = dataset[u'好瓜'].count()#sum(axis=0)
Pc[c] = c_count*1.0/N_count
data_c = dataset[dataset[u'好瓜']==c]

#区分连续属性和离散属性
#离散属性
Pcx[c] = {}
for x in dataset.columns[:-4]:
Pcx[c][x] = {}
c_x_xi_count = data_c[x].value_counts()
for xi in c_x_xi_count.index:
c_xi_count = c_x_xi_count[xi]  #[c].value_counts()[xi]
Pcx[c][x][xi] = c_xi_count*1.0/c_count

#连续属性
#假设密度和含糖度服从正态分布
#计算uci,eci
Uc[c] = {}
Ue[c] = {}
for x in dataset.columns[-4:-2]:
c_x_sum = data_c[x].sum()
uci = c_x_sum*1.0/c_count
xsubuci2 = ((data_c[x] - uci)**2).cumsum().iloc[c_count-1]
eci = math.sqrt(xsubuci2*1.0/c_count)
Uc[c][x] = uci
Ue[c][x] = eci
#for xi in dataset[x].values():
#    Pcx[c][x][xi] = st_norm(xi,uci,eci)
return Pc,Pcx,(Uc,Ue)


预测函数
def predict(data_input,Pc,Pcx,(Uc,Ue)): #为含表头的DataFrame格式待预测数据
data = data_input.copy()
max_probil = 0
c = -1
for key in Pc.keys():
probtmp = Pc[key]
for x in data.columns[:-2]:
print Pcx[key][x][data[x].values[0]]
probtmp = probtmp * Pcx[key][x][data[x].values[0]]  #data[x].values[0]从array中取出数值
for x in data.columns[-2:]:
uci = Uc[key][x]
eci = Ue[key][x]
#Pcx[key][x][data[x].values] = st_norm(data[x].values,uci,eci)
probtmp = probtmp * st_norm(data[x].values[0],uci,eci)    #Pcx[key][x][data[x].values]
prob = probtmp
print 'the probablity of label %d is %8.7f' %(key,prob)
if prob > max_probil:
max_probil = prob
c = key
return c


根据周志华《机器学习》P153的测试数据,得到的结果是:好瓜概率0,坏瓜概率0.0446,与书上结果有出入。分析发现计算正态分布参数时均数uci与书上相同,但是标准差eci与书上有一定偏差,没分析出具体的原因。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐