机器学习之朴素贝叶斯三、拉普拉斯平滑技术、优化改进情感分析

文章目录

  • 一、前文问题
    • 1. 先看下改进前我们的代码计算部分
    • 2. `问题分析`:
  • 二、针对问题进行解决
    • 1. 什么是`拉普拉斯平滑`技术
    • 2. 拉普拉斯优化-下溢上溢问题
    • 3. 改进地方分析:
    • 4.改进优化
      • 1.优化一,对条件概率计算进行优化
      • 2.优化二,对后延概率计算进行优化
      • 3. 优化结果分析
  • 三、源码
  • 四、下一篇 学习如何做舆情分析

一、前文问题

改进前情感分析实践

1. 先看下改进前我们的代码计算部分

条件概率计算部分

机器学习之朴素贝叶斯三、拉普拉斯平滑技术、优化改进情感分析_第1张图片看下训练后的结果展示

机器学习之朴素贝叶斯三、拉普拉斯平滑技术、优化改进情感分析_第2张图片

2. 问题分析

可以看到此时的训练后的结果是,在开心和伤心的条件概率中存在0,的结果。那么在计算后验概率P(C|X)其中X是特征C是label。发现:计算的结果为0
原因是什么?
来看下我们的条件概率计算过程是什么:

'''
	在计算样本 x 属于某个类别 C 的后验概率时,朴素贝叶斯假设各个特征之间相互独立,即 
	p(x|C) = p(x1|C)p(x2|C)...p(xn|C),其中 x1, x2, ..., xn 分别是特征向量的不同维
	度。这个假设简化了计算过程,但是忽略了特征之间的相关性。	
	根据贝叶斯公式,朴素贝叶斯可表示为: p(C|x) = p(x|C)p(C)/p(x) 其中,p(x|C) 表示在类
	别 C 下特征向量 x 出现的概率,p(C) 表示类别 C 的先验概率,p(x) 表示特征向量出现的概
	率。由于对于所有类别都是相同的,所以可以省略分母 p(x)

	可以看到vec_0 =  array_0/_0计算的就是p(x|C) = p(x1|C)p(x2|C)...p(xn|C)
	也就是当是开心样本的时候,是特征 X 的概率。
	array_0,中的每一个维度就是一个特征,那么array_0将所有开行样本中的数据相加,也就计算出
	了,每个特征发生次数。那么就可以计算,当开心label时候,特征X发生的概率。即 每个特征发生
	次数/总的样本发生次数
	_0 计算的就是,开心样本数据中,总的样本发生次数。
'''

可以看到,array_0计算的是 每个特征发生次数/总的样本发生次数,那么如果我们的样本中某个特征发生次数为0,这个时候这进行p(x|C) = p(x1|C)p(x2|C)...p(xn|C)计算的时候,就会出现为0的情况。

二、针对问题进行解决

我们经过分析知道问题所在那么可以针对问题进行解决了。

1. 什么是拉普拉斯平滑技术

拉普拉斯平滑是一种用于解决朴素贝叶斯算法中零概率问题的技术。在计算条件概率时,有些情况下会出现某个特征在某个类别下没有出现过的情况导致概率为零,这就无法使用贝叶斯公式进行计算。为了避免这种情况,可以对概率进行平滑处理,使得每个特征在每个类别下至少出现一次,从而避免概率为零的情况。而拉普拉斯平滑就是一种常用的平滑方法,它在计算概率时将每个特征的计数都加上一个常数k,从而保证每个特征至少出现k次

2. 拉普拉斯优化-下溢上溢问题

在进行拉普拉斯平滑时,条件概率的计算会涉及多个特征的连乘积,这容易导致数值过小而出现下溢(underflow)或者上溢(overflow)的问题。因此,为了避免这种问题,在实际应用中通常会使用对数操作将连乘积转换成加和运算,从而方便计算。同时,取对数还有一个好处是可以简化计算,因为对数具有以下常用的运算规则:

log(a*b) = log(a) + log(b)
log(a/b) = log(a) - log(b)
通过这些运算规则,可以大大简化计算,并且防止由于浮点数的精度限制而导致的计算误差。因此,在进行拉普拉斯优化时,经常会使用对数操作来计算条件概率

3. 改进地方分析:

机器学习之朴素贝叶斯三、拉普拉斯平滑技术、优化改进情感分析_第3张图片
看到我们在进行初始化的时候,使用的是np.zeros()函数,也就造成前面说的问题。

4.改进优化

1.优化一,对条件概率计算进行优化

def train(data,label):
    '''
    :param data: 这里的数据是样本经过向量化后的向量信息
    :param label:  样本所对应的标签信息
    :return:
    1. vec_0 --- 开心的条件概率组
    2. vec_1 --- 伤心的条件概率组
    3. simple_1 --- 样本数据属于伤心的概率
    '''
    num_simple = len(data) #样本的数量
    num_words = len(data[0]) #统计每个样本的词的数据量

    simple_1 = sum(label)/float(num_simple)  #计算的是伤心的
    '''
    这里说明一下,为什么使用的是sum(label) 来进行计算:
    正常这里应该是,属于伤心的样本数据/总的样本数
    那么我们这里用sum的效果就是,伤心样本的数量,因为伤心
    的label为1,开心为0,所有label的和就是,伤心的数量
    这里取巧了。
    '''
    #todo 改进一
    # 进行条件概率数组初始化
    # array_0,array_1 = np.zeros(num_words),np.zeros(num_words)
    array_0,array_1 = np.ones(num_words),np.ones(num_words) #todo 改进一
    _0 = 2.0 #todo 改进
    _1 = 2.0 #这里是多求条件概率的分母进行初始化,至于怎么用后面说
	'''
	这里为甚使用np.ones,和2来进行优化,这个没有定数,你可以自己指定,
	用这个主要还是好计算
	'''


    #todo 对所有伤心的样本进行计算条件概率
    for i in range(num_simple):
        if label[i] == 1: #伤心
            array_1 += data[i]
            _1 += sum(data[i])
        else: #开心
            array_0 += data[i]
            _0 += sum(data[i])

    #todo 改进优化二
    # vec_0 =  array_0/_0
    vec_0 =  np.log(array_0/_0)
    vec_1 =  np.log(array_1/_1)
    return vec_0,vec_1,simple_1

改进后的结果

机器学习之朴素贝叶斯三、拉普拉斯平滑技术、优化改进情感分析_第4张图片

2.优化二,对后延概率计算进行优化

机器学习之朴素贝叶斯三、拉普拉斯平滑技术、优化改进情感分析_第5张图片
这里分析一下为什么使用对数优化

pro_0 = sum(vec_test*vec_0) * np.log(1 - simple_1)
print('pro_0:',pro_0)
#pro_1 = reduce(lambda x,y:x*y,vec_test*vec_1) * simple_1
pro_1 = sum(vec_test*vec_1) * np.log(simple_1)
'''
这里pro_0 计算的是后验概率P(C|X),我们的vec_0计算的是条件概率,
我们知道朴素贝叶斯:后验概率=先验概率*条件概率
根据 log(后验概率)=log(先验概率) + log(条件概率)
vec_0在训练的时候已经进行log()过了。
'''


print('pro_1:',pro_1)
if pro_0 > pro_1:
    return 0
else:
    return 1

改进后结果展示

机器学习之朴素贝叶斯三、拉普拉斯平滑技术、优化改进情感分析_第6张图片

3. 优化结果分析

可以看到优化后的结果,效果直线上升。
后续问题::::
但是我在进行优化后的代码执行的的时候,依然会遇到,不能识别的类别的情况,甚至,分类的记过都是一种情况,经过试验我发现是因为,样本数据不均衡导致的,我适当优化下数据集,就好了。
由此可以看到,机器学习,对数据特征工程依赖还是很大的,到没有深度端到端来的爽,但是机器学习有着深度不可替代的能力。

三、源码

改进后的源码

致谢

四、下一篇 学习如何做舆情分析

你可能感兴趣的:(机器学习,机器学习,人工智能,算法)