赞
踩
本文主要是学习记录贴,参考《统计学习方法》和部分博客完成。如有错误,欢迎积极评论指出。
首先,简单讲一下机器学习中的两大学派——频率学派和贝叶斯派。
频率派认为世界是确定的,即θ(表示需要求的事件)存在唯一的真值,并且这个真值是不变的,我们的目标就是找到这个真值或者说这个真值存在的范围。用个例子来说明,我们在学概统时,常说投硬币,如果我们现在投硬币100次,出现正面朝上的概率是40,那么我们用θ表示硬币正面朝上,则p(θ) = 40 / 100 = 0.4。当数据量趋于无穷大的时候,这种方法能给出准确的估计。但是在缺乏数据的时候,就可能存在很大的误差。比如现在我们投10次硬币,全部都是正面朝上的,这是我们认为正面朝上的概率就是1,这在我们的认知中,是肯定错误的。
贝叶斯派认为世界是不确定的,人们应该提前有个先验,然后通过观测数据,对这个先验进行调整,然后找到最优的用于描述这个世界的概率分布。在贝叶斯派中,有两大输入和一大输出。两大输入是先验和似然,输出的是后验。先验,p(θ)指的是在没有观察到数据时对θ的预先判断,可以通过给定的训练样本进行统计得到的。似然,p(x|θ)是假设θ已知后我们观察到的数据应该是什么样,也是可以根据训练样本进行统计得到的。后验,p(θ|x)也就是我们最后需要求的值。
朴素贝叶斯法的核心是贝叶斯公式,其工作原理是根据通过某种方法求该事件所有可能性的发生概率,然后哪个高就是哪个。那么,这种方法是什么?
首先是贝叶斯公式,如下:
P
(
θ
∣
X
)
=
P
(
X
∣
θ
)
×
P
(
θ
)
P
(
X
)
P(\theta|X)=\frac{P(X|\theta) \times P(\theta)}{P(X)}
P(θ∣X)=P(X)P(X∣θ)×P(θ)
公式中,
P
(
θ
)
\ P(\theta)
P(θ)表示先验概率,
P
(
X
∣
θ
)
\ P(X|\theta)
P(X∣θ)表示似然。
接下来,我们针对实际应用中,定义几个变量。首先Ck 表示不同的类,X表示给定的样本,Y表示Ck的概率。公式变换如下:
对于上面公式变换,可能会存在一个疑问,那就是为什么可以将里面的拆开成连乘?我们在概率论中,这个公式的使用是有前提条件的,也就是相互独立。那么这里面,是条件独立吗?事实上,特征向量之间大概率不是独立的,但是我们默认特征之间是独立的,最主要的原因就是简便计算。如果我们考虑其特征向量之间的联系,会使模型变得非常复杂,容易造成过拟合。所以我们就假设所有的特征向量都是相互独立的。
最后我们得到了如下公式:
针对上面上面的公式,我们会发现,对同一组训练数据,其分母部分是相同的。我们最后的目的,是要找出最大的那个类,因此,这一部分不影响大小比较,接着简化公式。
在朴素贝叶斯法中,学习意味着对于参数P(Y=Ck) 和 P(X=x|Y=Ck)进行估计。常用的方法是利用极大似然估计,估计如下:
构建学习与分类算法如下:
对于上面的算法,因为其中出现了连乘,那么就需要考虑,零的问题了。
在利用极大似然进行估计的时候,可能会出现某个值为0,那么在进行后续连乘计算的时候,就会出现问题,导致分类产生偏差。解决这个问题的一个方法就是采用贝叶斯估计。条件概率的贝叶斯估计如下:
其中,λ=0时,就是极大似然估计。常取λ=1,称为拉普拉斯平滑,其中S表示该项特征的可能取值。
import numpy as np # 读取数据,将图片读取为785维的向量,其中前784维是28*28,最后是标签 def LoadData(filename): data = [] i = 0 file = open(filename) for line in file.readlines(): curline = line.strip().split(',') data.append([int(int(dt) > 128) for dt in curline[1:]]) #二值化 data[i].append(int(curline[0])) i += 1 return data # 计算似然和先验 def calProbability(trainData): featurenum = len(trainData[0]) - 1 P_y = [0] * 10 # 计算先验P(θ),并存储 for i in trainData: P_y[i[-1]] += 1 for j in range(len(P_y)): P_y[j] = (P_y[j] + 1) / (len(trainData) + len(P_y)) P_x_y = np.zeros((10, featurenum, 2)) # 计算似然P(x|θ) for i in trainData: for j in range(featurenum): P_x_y[i[-1]][j][i[j]] += 1 for m in range(10): for n in range(featurenum): value0 = P_x_y[m][n][0] value1 = P_x_y[m][n][1] P_x_y[m][n][0] = (value0 + 1) / (value0 + value1 + 2) P_x_y[m][n][1] = (value1 + 1) / (value0 + value1 + 2) return P_y, P_x_y # 通过朴素贝叶斯进行概率估计 # Data:测试数据 # P_y:先验 # P_x_y:似然 def Bayes(Data, P_y, P_x_y): predict = [0] * 10 for i in range(10): p = P_y[i] for j in range(len(Data)): p = p * P_x_y[i][j][Data[j]] predict[i] = p return predict.index(max(predict)) # 测试函数 def test(testData, P_y, P_x_y): err = 0 m = 0 for i in testData: print('测试编号:', m) m += 1 predict = Bayes(i[:-1], P_y, P_x_y) if predict != i[-1]: err += 1 return 1 - (err / (len(testData))) if __name__ == "__main__": print('read train data') trainData = LoadData('Mnist/mnist_train/mnist_train.csv') print('read test data') testData = LoadData('Mnist/mnist_test/mnist_test.csv') print('start train model') P_y, P_x_y = calProbability(trainData) print('start test model') acc = test(testData, P_y, P_x_y) print('the acc is: ', acc)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。