机器学习实战之bayes

本文介绍了朴素贝叶斯分类器的基础知识,包括其作为概率模型的特点、假设和优缺点。通过一个文本分类的例子,展示了如何利用Python进行数据预处理、向量化以及训练算法,最终计算后验概率并输出分类结果。朴素贝叶斯模型假设特征之间相互独立,适用于处理标称型数据,即使在数据量较小的情况下也能取得不错的效果。

朴素贝叶斯—概率模型

写在前面 : 我本科是学医的(0数学基础),刚开始搞这些东西的是和都是硬背,磨蹭了半年只学会各种框架搭积木,后来意识到这样不行遂从头开始翻机器学习的书和深度学习的经典论文,开始一点点理解算法本质,这时候才感觉到搭建模型的过程其实还是很有趣的,找到方法就容易多了。和广大转行者共勉同行吧

朴素贝叶斯分类器

Naive Bayes模型为基础的概率模型,最最最明显的特点就是进行分类时会输出样本属于每个类别的概率,而不是像KNN或者Decision Tree那样非黑即白的硬分类。
搞机器学习算法不学概率论无异于谈恋爱不结婚——都是耍流氓。所以推荐同步看一下概率论与数理统计。

贝叶斯条件概率分布:p(a∣b)=p(b∣a)p(a)p(b)p(a|b) =\frac{p(b|a)p(a)}{p(b)}p(ab)=p(b)p(ba)p(a)
朴素贝叶斯的两个假设:

  1. 所有特征之间相互独立(这也是naive的含义)
  2. 所有特征同等重要
  • 优点:在数据比较少得情况下仍有效果,可以处理多分类问题。
  • 缺点:对于输入得数据准备的方式比较敏感。
  • 适用数据类型:标称型数据

Naive Bayes的一般过程

  • 收集数据:本文用RSS源
  • 准备数据:需要数值型或布尔型数据
  • 分析数据:有大量特征时,绘制特征作用不大,用直方图效果更好
  • 训练算法:计算不同的独立特征的条件概率
  • 测试算法:计算错误率
  • 使用算法:是用朴素贝叶斯分类器,一个常见应用场景是文档分类器
下面思考一个文本分类的例子

所有代码模块都是Python代码

1.首先,创造一个文档集来代替真实文本数据,对于其中每个文档都进行标注(0代表正常文本,1代表侮辱性文本)代码如下:

def loadDataSet():
    postingList = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
                   ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
                   ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
                   ['stop','posting', 'stupid', 'worthless', 'garbage'],
                   ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
                   ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
    classVec = [0, 1, 0, 1, 0, 1]   # 1代表侮辱性词汇, 0代表正常词汇
    return postingList, classVec

2.第一步已经获得了初始标注好的数据,接下来要做的事情就是对数据进行分析,预处理。这一步要做的几件是

  • 2-1.将所有词汇整理,提取出一个vocabulary,包含所有不重复的词汇
def createVocabList(dataSet):
    vocabSet = set([])  # 创造一个空集
    for document in dataSet:
        vocabSet = vocabSet | set(document)  # 求并集,换句话说就是将文本去重
    return list(vocabSet)

  • 2-2.以2-1创造的vocabulary为模板,创建文本向量,元素下标(或者index)对应vocabulary
  • 可以用词集模型,每个元素都为0-1,0表示没出现,1表示出现过。
def setOfWords2Vec(vocabList, inputSet):
    """词集模型
    input:vocabList 词汇表
           inputSet 输入文档
    output: 与词汇表对应的词汇向量,一个0-1矩阵"""
    returnVec = [0] * len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
        else:
            print('this word: %s is not in my Vocabulary!' % word)
    return returnVec
  • 也可有用词袋模型,每个元素为0-n,表示该下标对应的单词出现的频率
def bagOfwords2VecMN(vocabList, inputSet):
    """词袋模型
    input:vocabList 词汇表
           inputSet 输入文档
    output: 与词汇表对应的词汇向量,一个单词频数矩阵"""
    returnVec = [0] * len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec

第二步的目的主要是对文本进行向量化,因为分类的是和数值方便计算。类似于one-hot编码

3.训练算法:从词向量计算概率(重头戏)

  • 先来理解一下模型。
    首先,我们的算法模型是离散概率分布,**其中XXX表示特征随机变量,CCC表示类别随机变量,要计算分类概率,公式为:
    p(类别i∣特征)=p(特征∣类别i)p(类别i)p(特征)p(类别_i|特征) =\frac{p(特征|类别_i)p(类别_i)}{p(特征)}p(i)=p()p(i)p(i),用数学符号表示就是p(Ci∣X)=p(X∣Ci)p(Ci)p(X)p(C_i|X) =\frac{p(X|C_i)p(C_i)}{p(X)}p(CiX)=p(X)p(XCi)p(Ci) —(1)

    根据全概率公式可以得到:P(X)=P(x1)P(x2)P(x3)...P(xn)P(X) = P(x_1)P(x_2)P(x_3)...P(x_n)P(X)=P(x1)P(x2)P(x3)...P(xn) —(2)

    通过(1)(2)我们可以通过先验概率P(Ci)P(C_i)P(Ci),特征概率P(X)P(X)P(X),和条件概率p(X∣Ci)p(X|C_i)p(XCi)计算得到后验概率P(Ci∣X)P(C_i|X)P(CiX),这样正式我们想要输出的结果

  • 算法流程:

    • (1) 先将先验概率p(C)p(C)p(C)和不同类别C_i的条件下所有P(xi∣Ci)P(x_i|C_i)P(xiCi)计算出来
    • (2) 用朴素贝叶斯公式来计算后验概率输出结果
# 2.训练算法:从词向量计算概率
def trainNB0(trainMatrix, trainCategory):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory) / float(numTrainDocs)
    p0Num = ones(numWords); p1Num = ones(numWords)  # 初始化p(0)和p(1)的词频数
    p0Denom = 2.; p1Denom = 2.    # 初始化文档的总词数
    for i in range(numTrainDocs):   # 遍历所有文档,记录累加随机变量x=1,x=0的词频数和文档总词数
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = log(p1Num / p1Denom)
    p0Vect = log(p0Num / p0Denom)
    return p0Vect, p1Vect, pAbusive


# 朴素贝叶斯分类函数
def classifyNB(vec2Classify, p0Vect, p1Vect, pClass1):
    p1 = sum(vec2Classify * p1Vect) + log(pClass1)
    p0 = sum(vec2Classify * p0Vect) + log(1. - pClass1)
    return 1 if p1 > p0 else 0

这里需要强调一下:
第一,朴素贝叶斯之所以naive,是因为我们假设所有的词汇都是独立的特征,也就是说每个词出现的频率不会受其他词的影响,这一点肯定不成立,这样假设的好处是可以减少样本量(因为独立特征可以共用同一套样本),而且在实际应用过程中效果还是不错的。
第二,因为概率很小,所以计算全概率时,所有特征概率相乘会出现数值下溢问题(得到的结果为0),解决这个问题的方法就是对概率进行对数化

到这里算法构建已经完成了,下一步我们算法进行测试,跑下面的代码:

def testingNB():
    listOposts, listClasses = loadDataSet()
    myVocabList = createVocabList(listOposts)
    trainMat = []
    for postinDoc in listOposts:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    p0v, p1v, pAb = trainNB0(array(trainMat), array(listClasses))
    testEntry = ['love', 'my', 'dalmation']
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print(testEntry, 'classified as:', classifyNB(thisDoc, p0v, p1v, pAb))
    testEntry = ['stupid', 'garbage']
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print(testEntry, 'classified as: ', classifyNB(thisDoc, p0v, p1v, pAb))

得到结果

跑测试模型的结果

### 光流法C++源代码解析与应用 #### 光流法原理 光流法是一种在计算机视觉领域中用于追踪视频序列中运动物体的方法。它基于亮度不变性假设,即场景中的点在时间上保持相同的灰度值,从而通过分析连续帧之间的像素变化来估计运动方向和速度。在数学上,光流场可以表示为像素位置和时间的一阶导数,即Ex、Ey(空间梯度)和Et(时间梯度),它们共同构成光流方程的基础。 #### C++实现细节 在给定的C++源代码片段中,`calculate`函数负责计算光流场。该函数接收一个图像缓冲区`buf`作为输入,并初始化了几个关键变量:`Ex`、`Ey`和`Et`分别代表沿x轴、y轴和时间轴的像素强度变化;`gray1`和`gray2`用于存储当前帧和前一帧的平均灰度值;`u`则表示计算出的光流矢量大小。 #### 图像处理流程 1. **初始化和预处理**:`memset`函数被用来清零`opticalflow`数组,它将保存计算出的光流数据。同时,`output`数组被填充为白色,这通常用于可视化结果。 2. **灰度计算**:对每一像素点进行处理,计算其灰度值。这里采用的是RGB通道平均值的计算方法,将每个像素的R、G、B值相加后除以3,得到一个近似灰度值。此步骤确保了计算过程的鲁棒性和效率。 3. **光流向量计算**:通过比较当前帧和前一帧的灰度值,计算出每个像素点的Ex、Ey和Et值。这里值得注意的是,光流向量的大小`u`是通过`Et`除以`sqrt(Ex^2 + Ey^2)`得到的,再乘以10进行量化处理,以减少计算复杂度。 4. **结果存储与阈值处理**:计算出的光流值被存储在`opticalflow`数组中。如果`u`的绝对值超过10,则认为该点存在显著运动,因此在`output`数组中将对应位置标记为黑色,形成运动区域的可视化效果。 5. **状态更新**:通过`memcpy`函数将当前帧复制到`prevframe`中,为下一次迭代做准备。 #### 扩展应用:Lukas-Kanade算法 除了上述基础的光流计算外,代码还提到了Lukas-Kanade算法的应用。这是一种更高级的光流计算方法,能够提供更精确的运动估计。在`ImgOpticalFlow`函数中,通过调用`cvCalcOpticalFlowLK`函数实现了这一算法,该函数接受前一帧和当前帧的灰度图,以及窗口大小等参数,返回像素级别的光流场信息。 在实际应用中,光流法常用于目标跟踪、运动检测、视频压缩等领域。通过深入理解和优化光流算法,可以进一步提升视频分析的准确性和实时性能。 光流法及其C++实现是计算机视觉领域的一个重要组成部分,通过对连续帧间像素变化的精细分析,能够有效捕捉和理解动态场景中的运动信息
微信小程序作为腾讯推出的一种轻型应用形式,因其便捷性与高效性,已广泛应用于日常生活中。以下为该平台的主要特性及配套资源说明: 特性方面: 操作便捷,即开即用:用户通过微信内搜索或扫描二维码即可直接使用,无需额外下载安装,减少了对手机存储空间的占用,也简化了使用流程。 多端兼容,统一开发:该平台支持在多种操作系统与设备上运行,开发者无需针对不同平台进行重复适配,可在一个统一的环境中完成开发工作。 功能丰富,接口完善:平台提供了多样化的API接口,便于开发者实现如支付功能、用户身份验证及消息通知等多样化需求。 社交整合,传播高效:小程序深度嵌入微信生态,能有效利用社交关系链,促进用户之间的互动与传播。 开发成本低,周期短:相比传统应用程序,小程序的开发投入更少,开发周期更短,有助于企业快速实现产品上线。 资源内容: “微信小程序-项目源码-原生开发框架-含效果截图示例”这一资料包,提供了完整的项目源码,并基于原生开发方式构建,确保了代码的稳定性与可维护性。内容涵盖项目结构、页面设计、功能模块等关键部分,配有详细说明与注释,便于使用者迅速理解并掌握开发方法。此外,还附有多个实际运行效果的截图,帮助用户直观了解功能实现情况,评估其在实际应用中的表现与价值。该资源适用于前端开发人员、技术爱好者及希望拓展业务的机构,具有较高的参考与使用价值。欢迎查阅,助力小程序开发实践。资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值