机器学习入门之草履虫都能看懂的朴素贝叶斯模型

        朴素贝叶斯是非常经典的一个生成模型,所谓生成模型就是指通过联合概率 P(X,Y) 建模,先学习输入 X 和标签 Y 的分布关系,再通过贝叶斯定理推导 P(Y∣X)。

特征​​生成模型​​判别模型​
​建模对象​联合概率 P(X,Y)条件概率 P(Y∣X)
​目标​学习数据如何生成(数据分布)直接学习类别边界(决策函数)
​是否生成样本​可以生成新样本(如图像、文本)仅用于分类/回归,无法生成数据
​典型算法​朴素贝叶斯、GMM、VAE、GAN、扩散模型逻辑回归、SVM、决策树、神经网络

 贝叶斯公式与全概率公式

全概率公式

          设\omega为实验E的空间,A为E的事件,B_{1},B_{2},....B_{n}\omega的一个划分,且P(B_{i})>0 (i=1,2,....n) 则P(A)=\sum_{i=1}^{n}P(A|B_{i})*P(B_{i})

贝叶斯公式

         设\omega为实验E的空间,A为E的事件,B_{1},B_{2},....B_{n}\omega的一个划分,且P(B_{i})>0 (i=1,2,....n) ,则P(B_{i}|A)=\frac{P(B_{i}A)}{P(A)}=\frac{P(B_{i})P(A|B_{i})}{\sum_{k=1}^{n}P(B_{k})P(A|B_{k})},第三个恒等式是将分母P(A)使用全概率公式展开的结果。

朴素贝叶斯模型要解决的问题

        存在K类C_{1},C_{2},......C_{K},给定一个新实例(x^1,x^2,....x^n),该实例归属于哪一类,若属于这一类,其可能性有多大?

        对于上述问题,一个不违背直觉的想法便是分别计算这个实例属于每一类的概率,然后选出概率最大的那一类作为该实例的所述分类。好的,那么到这儿你便掌握了整个朴素贝叶斯模型的精髓,接下来我们要做的不过就是进行公式上的推敲验证了……

        将我们上述的描述转换为公式即:

 P(Y=C_{k}|X=x)=\frac{P(Y=C_{k}X=x)}{P(X=x)}=\frac{P(X=x|Y=C_{k})P(Y=C_{k})}{P(X=x)}

         其中P(Y=C_{i}|X=x)为我们描述的给定新的实例属于某一类C_{i}的概率,我们只需要找到哪一个C_{i}能使这个概率最大便解决了整个问题,对于这个概率而言,根据贝叶斯公式我们对其变一下型会出现这样一个等式P(Y=C_{i}|X=x)=\frac{P(X=x|Y=C_{i})P(Y=C_{i})}{P(X=x)},我们仔细观察一下右边式子分子上的P(X=x|Y=C_{i}),你会发现这玩意儿不就是我们需要极大化的条件概率式子里的Y与X换了一下前后顺序吗?

        是的,没错,就是这样。为了区分二者,我们给他俩起一个好听的名字,P(Y=C_{i}|X=x)是我们最终要求解的概率,我们称他为后验概率。P(X=x|Y=C_{i})是我们根据数据分布可以计算出的概率,我们称他为先验概率。

        那么整个朴素贝叶斯分类模型的核心思路便出来了,即通过后验概率最大化的原则, 来确定某个实例的类别。

“朴素“一词的由来

         朴素贝叶斯的英文缩写为NB,不是牛逼是Naive Bayes,Naive这个单词我们都知道其可以用来表示孩童的'思想'天真''。这里的Naive也差不多是这个意思。

        这里Naive一词的由来是因为其假设:朴素贝叶斯模型中样本的各个特征之间都是条件独立的。也就是P(AB)!=P(B)P(A|B)=P(A)P(B) 。再直白点就是各个特征之间的相关系数为0,二者之间压根没有任何关系。

        这个听起来感觉有点扯淡,在现实生活中,比如身高和体重,我们很难说明这二者之间互不影响没有任何关系,甚至二者之间还可能存在很强的相关性。当然,既然存在那必然合理,这一假设最大的好处就是我们在推导后验概率最大化时能够减少运算,因为求解P(A,B,C,D)时不需要用到P(A|B,C,D)这样的条件概率。但这也会牺牲一部分分类的准确性。

模型推导

        我们前边说到过,朴素贝叶斯分类器模型就是通过后验概率最大化的原则来确定数据的类别。这里我们来推导一下。

        P(Y=C_{k}|X=x)=\frac{P(X=x|Y=C_{k})P(Y=C_{k})}{P(X=x)} (1)

        对于(1)式,我们将X后的x换成我们的数据\begin{Bmatrix} x^1,x^2....&x^n \end{Bmatrix},那么对于先验概率P(X=x|Y=C_{k})便有P(X^1=x^1,X^2=x^2,...X^n=x^n|Y=C_{k}),根据假设以及乘法法则,P(X^1=x^1,X^2=x^2,...X^n=x^n|Y=C_{k})又可以写作\prod_{j=1}^{n}P(X^{j}=x^{j}|Y=C_{k})(因为X^1=X^1,X^2=x^2,...X^n=x^n要同时成立,且因为各个特征之间相互独立),同理,分母上我们也带入后便得到了这样的一个式子:

 P(Y=C_{k}|X=x)=\frac{\prod_{j=1}^{n}P(X^{j}=x^{j}|Y=C_{k})P(Y=C_{k})}{\prod_{j=1}^{n}P(X^{j}=x^{j})}(2)

        由于我们需要做的是令右边这个分式最大化并求解此时的Y值C_{k},那么分母上那一坨东西便是常数,对于我们求解Y没有任何帮助,因此令整个分式最大化也就是令分子最大化即可。

那么到这儿,朴素贝叶斯分类器模型便呼之欲出了:(注意,这里我们使用的是极大似然估计推导 )

Y=argmax_{C_{k}}P(Y=C_{k})\prod_{j=1}^{N}P(X^{j}=x^{j}|Y=C_{k})(3),其中,N为样本数量

        对于(3)式中的P(Y=C_{k})来说,其表示的含义为任一样本是C_{k}类的概率,这个概率我们在计算时只需要统计出样本中类别为C_{K}的个数后与总数相除即可,即P(Y=C_{k})=\frac{\sum_{i=1}^{N}I(y_i=C_k)}{N},其中I为计数函数。

       我们再将(3)式一般化到表格型数据(一个样本i(行)有多个特征x(列)),设第i个样本的第j个特征x^{j}的可能取值集合为\begin{Bmatrix} a_{j1},a_{j2},... a_{jSj} \end{Bmatrix},那么对于(3)式中的P(X^{j}=x^{j}|Y=C_{k})这个先验概率,便可以替换为P(X^j=a_{jl}|Y=C_k)\frac{\sum{i=1}^{N}I(x_{i}^{j}=a_{jl},y_i=c_k)}{\sum_{i=1}^{N}I(y_i=c_k)},其中a_{jl}是第j个特征可能取的第l个值,x_{i}^{j}是第i个样本的第j个特征,I表示计数函数。

模型学习方法

  • 1.计算各个类别的概率,对第k个种类C_{k}来说P(Y=C_{k})=\frac{\sum_{i=1}^{N}I(y_i=C_k)}{N}
  • 2.计算在各个类别的条件下,对应特征下每个取值的概率即P(X^j=a_{jl}|Y=C_k)\frac{\sum{i=1}^{N}I(x_{i}^{j}=a_{jl},y_i=c_k)}{\sum_{i=1}^{N}I(y_i=c_k)}
  • 3.将(2)中共计算的概率代入(3)式,找到新的数据在每个类别下的最大概率,这个概率下的类别便是新的数据的类别(后验概率最大化)

例题 

        这里我们来看一个例子来进一步带大家理解上述过程。

        试由下表的训练数据学习一个朴素贝叶斯分类器来确定x=(2,5)^T的类标,记为y。表中X^{(1)},X^{(2)}为特征,Y为类标记,Y \in \begin{Bmatrix} -1,1 \end{Bmatrix}

X^{(1)}X^{(2)}Y
1S-1
1M-1
1M1
1S1
1S-1
2S-1
2M-1
2M1
2L1
2L1
3L1
3M1
3M1
3L1
3L-1

计算结果: 

<think>我们被要求详细解释PHP封装协议,从基础到精通,使用简单易懂的语言。根据引用[1]和[3],我们知道PHP在Web开发中用于处理动态内容,并且经常需要与文件系统或网络资源交互。封装协议(Wrapper)是PHP中一个重要的特性,它允许我们像操作普通文件一样操作各种资源(如HTTP、FTP、压缩文件等)。计划回答结构:1.什么是封装协议?(基础)2.内置的封装协议有哪些?(列举并简要说明)3.如何使用封装协议?(包括示例)4.自定义封装协议(进阶)5.封装协议的应用场景注意:引用中并没有直接提到封装协议,但提到了PHP处理数据、存储和读取,封装协议正是处理这些资源访问的一种机制。我们将按照上述结构进行解释,并尽量使用简单易懂的语言和示例。</think>### PHP封装协议详解:从入门到精通 #### 一、基础概念(什么是封装协议?) 封装协议(Wrapper)是PHP中用于**统一访问不同资源**的抽象层。它允许开发者使用标准文件函数(如`fopen()`, `file_get_contents()`)处理各种资源类型,包括: - 本地文件系统(`file://`) - HTTP/HTTPS网页(`http://`) - FTP服务器(`ftp://`) - 压缩文件(`zip://`) - 数据流(`php://`)等 核心原理:通过**协议前缀**(如`http://`)告诉PHP使用对应的协议处理器解析资源路径,实现**统一操作接口**[^1]。 --- #### 二、常用内置封装协议详解 1. **`file://` (默认协议)** 访问本地文件系统: ```php $content = file_get_contents('file:///var/www/data.txt'); // 等效于(默认省略协议): $content = file_get_contents('/var/www/data.txt'); ``` 2. **`http://` & `https://`** 获取网络资源: ```php $html = file_get_contents('https://www.example.com/api'); // 发送带参数的GET请求: $data = file_get_contents('http://api.com?user=john&page=2'); ``` 3. **`php://` (PHP流协议)** - `php://input`:读取原始POST数据 ```php $rawData = file_get_contents('php://input'); ``` - `php://output`:直接写入输出缓冲 ```php fwrite(fopen('php://output', 'w'), 'Hello World'); ``` - `php://temp`:临时数据存储(内存不足时转存磁盘) ```php $temp = fopen('php://temp', 'r+'); fwrite($temp, 'Temporary data'); ``` 4. **`zip://`** 直接读取压缩包内文件: ```php // 读取 archive.zip 中 config.ini 的内容 $content = file_get_contents('zip://archive.zip#config.ini'); ``` 5. **`data://`** 嵌入Base64或URL编码数据: ```php $img = file_get_contents('data:image/png;base64,iVBORw0KGgo...'); ``` --- #### 三、高级应用:自定义封装协议 通过`stream_wrapper_register()`创建自定义协议处理器: ```php class MyWrapper { public function stream_open($path, $mode, $options, &$opened_path) { // 解析路径并建立连接 $this->position = 0; return true; } public function stream_read($count) { // 返回自定义数据 $data = "Custom data chunk"; $this->position += strlen($data); return $data; } } // 注册 myproto:// 协议 stream_wrapper_register('myproto', 'MyWrapper'); // 使用自定义协议 $data = file_get_contents('myproto://example-data'); ``` **关键方法**: - `stream_open()`:打开资源 - `stream_read()`/`stream_write()`:读写数据 - `stream_close()`:关闭资源 - `stream_seek()`:随机访问 --- #### 四、封装协议的应用场景 1. **统一资源访问** 用相同代码处理本地文件和网络资源: ```php function getContent($path) { return file_get_contents($path); // 自动识别协议 } ``` 2. **安全控制** 通过`allow_url_fopen`和`allow_url_include`配置限制危险协议访问。 3. **数据处理管道** 结合`stream_filter_append()`实现实时数据转换: ```php $stream = fopen('http://example.com/data.csv', 'r'); stream_filter_append($stream, 'convert.iconv.UTF-8/ASCII'); // 字符编码转换 ``` --- #### 五、安全注意事项 1. **禁用危险协议** 在`php.ini`中设置: ```ini allow_url_include = Off // 禁止直接包含远程代码 allow_url_fopen = On // 按需开启网络访问 ``` 2. **验证用户输入路径** 防止路径注入攻击: ```php $userPath = $_GET['path']; if (!preg_match('/^[a-z0-9:\/\.\-]+$/i', $userPath)) { die('Invalid path!'); } ``` > **最佳实践**:优先使用PHP内置协议(如`php://input`),避免直接操作`$_POST`处理二进制数据[^3]。 --- ### 相关问题 1. PHP封装协议与cURL在处理HTTP请求时有何性能差异? 2. 如何通过`php://filter`实现文件内容实时加密? 3. 自定义封装协议时如何实现目录遍历功能? 4. 为什么`allow_url_include`默认关闭?它可能引发哪些安全问题? [^1]: PHP封装协议允许统一访问不同资源类型,简化开发流程。 [^3]: PHP内置协议如`php://input`能安全处理原始数据流。
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值