高斯朴素贝叶斯分类器是针对特征值连续的情况下给出的一种分类方法。
贝叶斯公式 所有的贝叶斯分类器的基石都是概率论中的贝叶斯公式,给定训练数据集
D
=
{
x
i
,
C
i
}
,
i
=
1
,
.
.
.
,
N
,
x
i
∈
R
D
,
C
i
∈
1
,
.
.
.
,
K
D=\{x_i,C_i\},i=1,...,N,x_i\in R^D,C_i\in {1,...,K}
D={xi?,Ci?},i=1,...,N,xi?∈RD,Ci?∈1,...,K有贝叶斯公式如下:
p
(
C
∣
x
)
=
p
(
C
)
p
(
x
∣
C
)
p
(
x
)
,
C
∈
{
C
1
,
C
2
,
.
.
.
,
C
k
}
p(C|x)=\frac {p(C)p(x|C)}{p(x)},C\in \{C_1,C_2,...,C_k\}
p(C∣x)=p(x)p(C)p(x∣C)?,C∈{C1?,C2?,...,Ck?} 其中
p
(
C
)
p(C)
p(C)为分类先验概率,
p
(
x
∣
C
)
p(x|C)
p(x∣C)为分类条件分布概率。我们的主要任务就是求得
p
(
x
∣
C
)
和
p
(
C
)
p(x|C)和p(C)
p(x∣C)和p(C)。
高斯分布式 在此时我们假设
p
(
x
∣
C
)
p(x|C)
p(x∣C)是服从高斯分布的,对任意
x
i
∈
(
x
1
,
x
2
,
.
.
.
,
x
D
)
T
x_i\in(x_1,x_2,...,x_D)^T
xi?∈(x1?,x2?,...,xD?)T是相互独立的并且均服从高斯分布:
p
(
x
∣
C
)
=
1
2
π
σ
c
e
x
p
[
?
(
x
?
μ
c
)
2
2
σ
c
2
]
p(x|C)=\frac {1}{\sqrt {2\pi}\sigma_c}exp[- \frac{(x-\mu_c)^2}{2\sigma_c^2} ]
p(x∣C)=2π
?σc?1?exp[?2σc2?(x?μc?)2?] 其中
μ
c
和
σ
c
\mu_c和\sigma_c
μc?和σc?分别为各特征的平均值和标准差。
最终分类条件概率可写成:
p
(
x
∣
C
)
=
∏
d
=
1
D
p
(
x
i
∣
C
)
=
∏
d
=
1
D
1
2
π
σ
c
d
e
x
p
[
?
(
x
?
μ
c
d
)
2
2
(
σ
c
d
)
2
]
p(x|C)=\prod_{d=1}^Dp(x_i|C)=\prod_{d=1}^D\frac {1}{\sqrt{2\pi}\sigma_c^d}exp[- \frac{(x-\mu_c^d)^2}{2(\sigma_c^{d})^2}]
p(x∣C)=d=1∏D?p(xi?∣C)=d=1∏D?2π
?σcd?1?exp[?2(σcd?)2(x?μcd?)2?]
那么最终得到的预测分类结果就是:
C
=
arg?max
?
c
p
(
C
∣
x
)
C=\argmax_c{p(C|x)}
C=cargmax?p(C∣x)
算法流程 明确了高斯朴素贝叶斯分类器的原理以及计算过程,那么我们很容易得到其算法流程如下:
- 准备数据集,分离出feature集以及label集,并根据label集计算先验概率p(C)
- 训练模型,根据training dataset计算各特征向量的平均值及标准差
- 预测分类,根据输入特征向量计算出所有特征对应的p(x|C)p(C)即k*p(x|C),这里由于分母均相同,所以直接忽略计算分母
- 求argmax(k*p(x|C))=argmax(p(x|C))
python实现: 花的分类问题: 数据集:数据集链接
import numpy as np
import collections
class GuassianNB:
def __init__(self):
self.prior = None
self.avgs = None
self.vars = None
self.nums = None
def _get_prior(self, label: np.array)->dict:
cnt = collections.Counter(label)
a = {}
for k,v in cnt.items():
a[k]=v/len(label)
return a
def _get_avgs(self,data:np.array,label:np.array)->np.array:
return np.array([data[label == i].mean(axis=0) for i in self.nums])
def _get_vars(self,data:np.array,label:np.array)->np.array:
return np.array([data[label == i].var(axis=0) for i in self.nums])
def _get_likelihood(self,row:np.array)->np.array:
return (1 / np.sqrt(2 * np.pi * self.vars) * np.exp(
-(row - self.avgs) ** 2 / (2 * self.vars))).prod(axis=1)
def fit(self, data: np.array, label: np.array):
self.prior = self._get_prior(label)
print(self.prior)
a=[]
for key in self.prior.keys():
a.append(key)
self.nums = a
self.avgs = self._get_avgs(data, label)
self.vars = self._get_vars(data, label)
def predict_prob(self, data: np.array) -> np.array:
likelihood = np.apply_along_axis(self._get_likelihood, axis=1, arr=data)
print(likelihood)
a = []
for key in self.prior.keys():
a.append(self.prior[key])
probs = np.array(a) * likelihood
print(probs)
probs_sum = probs.sum(axis=1)
return probs / probs_sum[:, None]
def predict(self, data: np.array) -> np.array:
return self.predict_prob(data).argmax(axis=1)
def main():
origin_dataset = np.loadtxt('iris.txt',dtype=str,delimiter=',')
np.random.shuffle(origin_dataset)
feature_dataset = []
label_dataset = []
feature_dataset_test = []
label_dataset_test = []
for i in range(int(len(origin_dataset)*0.8)):
feature_dataset.append(origin_dataset[i][0:4])
label_dataset.append(origin_dataset[i][4])
for i in range(int(len(origin_dataset)*0.8),len(origin_dataset)):
feature_dataset_test.append(origin_dataset[i][0:4])
label_dataset_test.append(origin_dataset[i][4])
feature_dataset = np.array(feature_dataset,dtype=float)
label_dataset = np.array(label_dataset,dtype=str)
feature_dataset_test = np.array(feature_dataset_test,dtype=float)
label_dataset_test = np.array(label_dataset_test,dtype=str)
nb = GuassianNB()
nb.fit(feature_dataset,label_dataset)
test_result = nb.predict(feature_dataset_test)
print(test_result)
acc = 0
for i in range(len(test_result)):
if nb.nums[test_result[i]] == label_dataset_test[i]:
acc+=1
print("精确度:"+str(acc/len(test_result)))
if __name__ == '__main__':
main()
预测结果: 精确度基本可达90%以上。
|