黄山网站网站建设,wordpress 用户注册插件,保安公司的网站设计比较好的,互联网营销公司经营范围实验1.使用sklearn的GaussianNB、BernoulliNB、MultinomialNB完成肿瘤预测任务
实验内容#xff1a;
使用GaussianNB、BernoulliNB、MultinomialNB完成肿瘤预测计算各自十折交叉验证的精度、查准率、查全率、F1值根据精度、查准率、查全率、F1值的实际意义以及四个值的对比阐…实验1.使用sklearn的GaussianNB、BernoulliNB、MultinomialNB完成肿瘤预测任务
实验内容
使用GaussianNB、BernoulliNB、MultinomialNB完成肿瘤预测计算各自十折交叉验证的精度、查准率、查全率、F1值根据精度、查准率、查全率、F1值的实际意义以及四个值的对比阐述三个算法在肿瘤预测中的表现对比
1. 读取数据集
import pandas as pd
import numpy as np
data pd.read_csv(./breast-cancer.csv)
data data.replace({B: 1, M: -1})
data data.values
data_x data[:,2:]
data_y data[:,1:2].ravel()
2. 导入模型
from sklearn.naive_bayes import GaussianNB
from sklearn.naive_bayes import MultinomialNB
from sklearn.naive_bayes import BernoulliNB
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score3. 计算十折交叉验证下GaussianNB、BernoulliNB、MultinomialNB的精度、查准率、查全率、F1值
model GaussianNB()
prediction cross_val_predict(model, data_x, data_y, cv10)acc accuracy_score(data_y, prediction)
precision precision_score(data_y, prediction)
recall recall_score(data_y, prediction)
f f1_score(data_y, prediction)print(GaussianNB在测试集上的四项指标)
print(精度:,acc)
print(查准率:,precision)
print(查全率:,recall)
print(f1值:,f)model12 BernoulliNB()
prediction12 cross_val_predict(model12, data_x, data_y, cv10)acc12 accuracy_score(data_y, prediction12)precision12 precision_score(data_y, prediction12)recall12 recall_score(data_y, prediction12)f12 f1_score(data_y, prediction12)
print(BernoulliNB在测试集上的四项指标)
print(精度:,acc12)
print(查准率:,precision12)
print(查全率:,recall12)
print(f1值:,f12)model13 MultinomialNB()
prediction13 cross_val_predict(model13, data_x, data_y, cv10)acc13 accuracy_score(data_y, prediction13)precision13 precision_score(data_y, prediction13)recall13 recall_score(data_y, prediction13)f13 f1_score(data_y, prediction13)
print(MultinomialNB在测试集上的四项指标)
print(精度:,acc13)
print(查准率:,precision13)
print(查全率:,recall13)
print(f1值:,f13)
实验2.实现一个高斯朴素贝叶斯分类器
实验内容
实现高斯朴素贝叶斯分类器计算模型的查准率查全率F1值
我们要实现一个可以处理连续特征的服从高斯分布的朴素贝叶斯分类器
符号
给定训练集 T T T T { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋅ ⋅ ⋅ , ( x N , y N ) } T \{(x_1, y_1), (x_2, y_2), ···, (x_N, y_N)\} T{(x1,y1),(x2,y2),⋅⋅⋅,(xN,yN)}
其中 x x x 为样本的特征 y y y 是该样本对应的标记下标表示对应的是第几个样本上标表示第几个特征。训练集 T T T 内一共 ∣ T ∣ N \vert T \vert N ∣T∣N 个样本。
假设我们的任务是处理 K K K 类分类任务记类标记分别为 c 1 , c 2 , . . . , c k c_1, c_2, ..., c_k c1,c2,...,ck 。
目标
我们的目标是对样本进行分类这里我们用概率的方法求 P ( Y c k ∣ X x ) , k 1 , 2 , . . . , K P(Y c_k \mid X x), \ k 1, 2, ..., K P(Yck∣Xx), k1,2,...,K 中最大的那个概率对应的 k k k 是哪个也就是给定样本 x x x 模型认为它是哪个类别的概率最大。
原理
由贝叶斯公式 P ( Y c k ∣ X x ) P ( Y c k , X x ) P ( X x ) P ( X x ∣ Y c k ) P ( Y c k ) ∑ k P ( X x ∣ Y c k ) P ( Y c k ) \begin{aligned} P(Y c_k \mid X x) \frac{P(Y c_k, X x)}{P(X x)} \\ \frac{P(X x \mid Y c_k)P(Y c_k)}{\sum_kP(X x \mid Y c_k)P(Y c_k)} \\ \end{aligned} P(Yck∣Xx)P(Xx)P(Yck,Xx)∑kP(Xx∣Yck)P(Yck)P(Xx∣Yck)P(Yck)
这里我们要求 K K K 个概率中最大的那个而这 K K K 个概率的分母都相同我们可以忽略分母部分比较分子部分的大小也就是比较 先验概率 P ( Y c k ) P(Y c_k) P(Yck) 和 似然 P ( X x ∣ Y c k ) P(X x \mid Y c_k) P(Xx∣Yck) 的乘积。 通过先验概率分布 P ( Y c k ) , k 1 , 2 , . . . , K P(Y c_k), \ k 1, 2, ..., K P(Yck), k1,2,...,K
和条件概率分布 P ( X x ∣ Y c k ) P ( X ( 1 ) x ( 1 ) , ⋅ ⋅ ⋅ , X ( n ) x ( n ) ∣ Y c k ) , k 1 , 2 , . . . , K P(X x \mid Y c_k) P(X^{(1)} x^{(1)}, ···, X^{(n)} x^{(n)} \mid Y c_k), \ k 1, 2, ..., K P(Xx∣Yck)P(X(1)x(1),⋅⋅⋅,X(n)x(n)∣Yck), k1,2,...,K
我们就可以得到联合概率分布 P ( X x , Y c k ) P(X x, Y c_k) P(Xx,Yck) 。
1. 先验概率 P ( Y c k ) P(Y c_k) P(Yck)
先验概率的求解很简单只要统计训练集中类别 k k k 出现的概率即可。 P ( Y c k ) n u m b e r o f c k N P(Y c_k) \frac{\mathrm{number} \ \mathrm{of}\ c_k}{N} P(Yck)Nnumber of ck
2. 似然 P ( X x ∣ Y c k ) P(X x \mid Y c_k) P(Xx∣Yck)
求解这个条件概率比较复杂这里我们要假设特征之间相互独立可得 P ( X x ∣ Y c k ) ∏ j 1 n P ( X ( j ) x ( j ) ∣ Y c k ) P(X x \mid Y c_k) \prod^n_{j1}P(X^{(j)}x^{(j)} \mid Y c_k) P(Xx∣Yck)j1∏nP(X(j)x(j)∣Yck)
其中 x ( j ) x^{(j)} x(j) 表示样本 x x x 的第 j j j 个特征。
这样复杂的条件概率就转换为了多个特征条件概率的乘积。
3. 特征 j j j 的条件概率 P ( X ( j ) x ( j ) ∣ Y c k ) P(X^{(j)}x^{(j)} \mid Y c_k) P(X(j)x(j)∣Yck)
因为我们处理的特征都是连续型特征一般我们假设这些特征服从正态分布。
当 Y c k Y c_k Yck 时 X ( j ) a j l X^{(j)} a_{jl} X(j)ajl 的概率可由下面的公式计算得到 P ( X ( j ) a j l ∣ Y c k ) 1 2 π σ c k , j 2 exp ( − ( a j l − μ c k , j ) 2 2 σ c k , j 2 ) P(X^{(j)} a_{jl} \mid Y c_k) \frac{1}{\sqrt{2 \pi \sigma^2_{c_k,j}}} \exp{\bigg( - \frac{(a_{jl} - \mu_{c_k,j})^2}{2 \sigma^2_{c_k,j}} \bigg)} P(X(j)ajl∣Yck)2πσck,j2 1exp(−2σck,j2(ajl−μck,j)2)
这里 μ c k , j \mu_{c_k,j} μck,j 和 σ c k , j 2 \sigma^2_{c_k,j} σck,j2 分别表示当 Y c k Y c_k Yck 时第 j j j 个特征的均值和方差这个均值和方差都是通过训练集的样本计算出来的。
因为正态分布只需要两个参数均值和方差就可以确定对于特征 j j j 我们要估计 K K K 个类别的均值和方差所以特征 j j j 的参数共有 2 K 2K 2K个。
综上
朴素贝叶斯分类器可以表示为 y arg max c k P ( Y c k ) ∏ j P ( X ( j ) x ( j ) ∣ Y c k ) y \mathop{\arg\max}_{c_k} P(Y c_k) \prod_j P(X^{(j)} x^{(j)} \mid Y c_k) yargmaxckP(Yck)j∏P(X(j)x(j)∣Yck)
实现
实现的时候会遇到数值问题在上面的条件概率连乘中如果有几个概率值很小它们的连乘就会导致下溢解决方案就是将其改写为连加的形式。
首先我们的目标是 y arg max c k P ( Y c k ) ∏ j P ( X ( j ) x ( j ) ∣ Y c k ) y \mathop{\arg\max}_{c_k} P(Y c_k) \prod_j P(X^{(j)} x^{(j)} \mid Y c_k) yargmaxckP(Yck)j∏P(X(j)x(j)∣Yck)
比较这 K K K 个数值的大小然后取最大的那个数对应的 k k k。
为了解决可能出现的下溢问题我们对上面的式子取对数因为是对 K K K 项都取对数不会改变单调性所以取对数是不影响它们之间的大小关系的。
那目标就变成了 y arg max c k [ log P ( Y c k ) ∏ j P ( X ( j ) x ( j ) ∣ Y c k ) ] arg max c k [ log P ( y c k ) ∑ j log P ( X ( j ) x ( j ) ∣ Y c k ) ] \begin{aligned} y \mathop{\arg\max}_{c_k} \big[ \log^{ \ P(Y c_k) \prod_j P(X^{(j)} x^{(j)} \mid Y c_k)} \big] \\ \mathop{\arg\max}_{c_k} \big[ \log^{ \ P(y c_k)} \sum_j \log^{ \ P(X^{(j)} x^{(j)} \mid Y c_k)} \big] \end{aligned} yargmaxck[log P(Yck)∏jP(X(j)x(j)∣Yck)]argmaxck[log P(yck)j∑log P(X(j)x(j)∣Yck)]
在求条件概率的时候也进行变换 log P ( X ( j ) x ( j ) ∣ Y c k ) log [ 1 2 π σ c k , j 2 exp ( − ( a j l − μ c k , j ) 2 2 σ c k , j 2 ) ] log 1 2 π σ c k , j 2 log exp ( − ( a j l − μ c k , j ) 2 2 σ c k , j 2 ) − 1 2 log 2 π σ c k , j 2 − 1 2 ( a j l − μ c k , j ) 2 σ c k , j 2 \begin{aligned} \log^{ \ P(X^{(j)} x^{(j)} \mid Y c_k)} \log^{ \ \bigg[\frac{1}{\sqrt{2 \pi \sigma^2_{c_k,j}}} \exp{\bigg(- \frac{(a_{jl} - \mu_{c_k,j})^2}{2 \sigma^2_{c_k,j}}\bigg)}\bigg]}\\ \log^{ \frac{1}{\sqrt{2 \pi \sigma^2_{c_k,j}}} } \log^{ \exp{\bigg(- \frac{(a_{jl} - \mu_{c_k,j})^2}{2 \sigma^2_{c_k,j}}\bigg)} }\\ - \frac{1}{2} \log^{2 \pi \sigma^2_{c_k,j}} - \frac{1}{2} \frac{(a_{jl} - \mu_{c_k,j})^2}{\sigma^2_{c_k,j}} \end{aligned} log P(X(j)x(j)∣Yck)log [2πσck,j2 1exp(−2σck,j2(ajl−μck,j)2)]log2πσck,j2 1logexp(−2σck,j2(ajl−μck,j)2)−21log2πσck,j2−21σck,j2(ajl−μck,j)2
所以高斯朴素贝叶斯就可以变形为 y arg max c k [ log P ( y c k ) ∑ j ( − 1 2 log 2 π σ c k , j 2 − 1 2 ( a j l − μ c k , j ) 2 σ c k , j 2 ) ] y \mathop{\arg\max}_{c_k} \bigg[ \log^{ \ P(y c_k)} \sum_j \big( - \frac{1}{2} \log^{2 \pi \sigma^2_{c_k,j}} - \frac{1}{2} \frac{(a_{jl} - \mu_{c_k,j})^2}{\sigma^2_{c_k,j}} \big) \bigg] yargmaxck[log P(yck)j∑(−21log2πσck,j2−21σck,j2(ajl−μck,j)2)]
上式就是我们需要求的我们要求出 K K K 个值然后求最大的那个对应的 k k k。
1. 导入数据集
import pandas as pd
import numpy as np
data pd.read_csv(./breast-cancer.csv)
data data.replace({B: 1, M: -1})
data data.values
data_x data[:,2:]
data_y data[:,1:2].ravel()
2. 划分数据集
from sklearn.model_selection import train_test_split
trainX, testX, trainY, testY train_test_split(data_x, data_y, test_size 0.4, random_state 32)3. 实现高斯朴素贝叶斯
接下来我们开始实现高斯朴素贝叶斯我们以类的形式实现这个高斯朴素贝叶斯。因为朴素贝叶斯是懒惰学习所以这个模型只有在预测的时候会进行大量的运算。
class myGaussianNB:处理连续特征的高斯朴素贝叶斯def __init__(self):初始化四个字典self.label_mapping 类标记 与 下标(int)self.probability_of_y 类标记 与 先验概率(float)self.mean 类标记 与 均值(np.ndarray)self.var 类标记 与 方差(np.ndarray)self.label_mapping dict()self.probability_of_y dict()self.mean dict()self.var dict()def _clear(self):为了防止一个实例反复的调用fit方法我们需要每次调用fit前将之前学习到的参数删除掉self.label_mapping.clear()self.probability_of_y.clear()self.mean.clear()self.var.clear()def fit(self, trainX, trainY):这里我们要根据trainY内的类标记针对每类计算这类的先验概率以及这类训练样本每个特征的均值和方差Parameters----------trainX: np.ndarray, 训练样本的特征, 维度(样本数, 特征数)trainY: np.ndarray, 训练样本的标记, 维度(样本数, )# 先调用_clearself._clear()# 获取类标记labels np.unique(trainY)# 添加类标记与下标的映射关系self.label_mapping {label: index for index, label in enumerate(labels)}# 遍历每个类for label in labels:# 取出为label这类的所有训练样本存为 xx trainX[trainY label, :]# 计算先验概率用 x 的样本个数除以训练样本总个数存储到 self.probability_of_y 中键为 label值为先验概率self.probability_of_y[label] len(x) / len(trainY)# 对 x 的每列求均值使用 keepdims True 保持维度存储到 self.mean 中键为 label值为每列的均值组成的一个二维 np.ndarrayself.mean[label] np.mean(x, axis0, keepdimsTrue)# 这句话是debug用的如果不满足下面的条件会直接跳出assert self.mean[label].shape (1, trainX.shape[1])# 对 x 的每列求方差使用 keepdims True 保持维度存储到 self.var 中键为 label值为每列的方差组成的一个二维 np.ndarrayself.var[label] np.var(x, axis0, keepdimsTrue)# debugassert self.var[label].shape (1, trainX.shape[1])# 平滑因为方差在公式的分母部分我们要加一个很小的数防止除以0self.var[label] 1e-9 * np.var(trainX, axis 0).max()def predict(self, testX):给定测试样本预测测试样本的类标记这里我们要实现化简后的公式Parameters----------testX: np.ndarray, 测试的特征, 维度(测试样本数, 特征数)Returns----------prediction: np.ndarray, 预测结果, 维度(测试样本数, )# 初始化一个空矩阵 results存储每个样本属于每个类的概率维度是 (测试样本数类别数)每行表示一个样本每列表示一个特征results np.empty((testX.shape[0], len(self.probability_of_y)))# 初始化一个列表 labels按 self.label_mapping 的映射关系存储所有的标记一会儿会在下面的循环内部完成存储labels [0] * len(self.probability_of_y)# 遍历当前的类label为类标记index为下标我们将每个样本预测出来的这个 label 的概率存到 results 中的第 index 列for label, index in self.label_mapping.items():# 先验概率存为 pypy self.probability_of_y[label]# 使用变换后的公式计算所有特征的条件概率之和存为sum_of_conditional_probabilitysum_of_conditional_probability -0.5 * np.sum(np.log(2 * np.pi * self.var[label])) \- 0.5 * np.sum(((testX - self.mean[label]) ** 2) / self.var[label], axis1)# debugassert sum_of_conditional_probability.shape (len(testX), )# 使用变换后的公式将 条件概率 与 log先验概率 相加存为result维度应该是 (测试样本数, )result sum_of_conditional_probability np.log(py)# debugassert result.shape (len(testX), )# 将所有测试样本属于当前这类的概率存入到results中results[:, index] result# 将当前的label按index顺序放入到labels中labels[index] label# 将labels转换为np.ndarraynp_labels np.array(labels)# 循环结束后就计算出了给定测试样本当前样本属于这类的概率的近似值存放在了results中每行对应一个样本每列对应一个特征# 我们要求每行的最大值对应的下标也就是求每个样本概率值最大的那个下标是什么结果存入max_prob_index中max_prob_index np.argmax(results, axis1)# debugassert max_prob_index.shape (len(testX), )# 现在得到了每个样本最大概率对应的下标我们需要把这个下标变成 np_labels 中的标记# 使用上面小技巧中的第五点求解prediction np_labels[max_prob_index]# debugassert prediction.shape (len(testX), )# 返回预测结果return prediction# 测试样例
from sklearn.metrics import accuracy_score
model2 myGaussianNB()
model2.fit(trainX, trainY)
accuracy_score(testY, model2.predict(testX)) # 0.92543859649122814. 计算其他的指标
# YOUR CODE HERE
prediction2 model2.predict(testX)precision2 precision_score(testY, prediction2)recall2 recall_score(testY, prediction2)
f2 f1_score(testY, prediction2)
print(查准率:,precision2)
print(查全率:,recall2)
print(f1值:,f2)实验3.实现带有拉普拉斯修正的朴素贝叶斯
实验内容
叙述拉普拉斯修正的作用使用给定的数据集给出实现的代码要有详细的注释给出模型评价指标的结果
1. 叙述拉普拉斯修正的作用
回答
在朴素贝叶斯分类器中拉普拉斯修正主要用于解决概率估计中的零概率问题。当在训练数据中出现一个特征值而在测试数据中没有相应特征值时朴素贝叶斯分类器的条件概率计算中可能会出现零概率这会导致整个后验概率为零影响分类器的性能。拉普拉斯修正通过在概率估计的分子和分母中添加一个小的常数解决了零概率的问题确保每个特征值都有一个非零的概率。2. 拉普拉斯修正的具体介绍
在训练集中总共的分类数用 N 表示di 属性可能的取值数用 Ni 表示因此原来的先验概率 P© 的计算公式由
P© Dc / D
被拉普拉斯修正为
P© (Dc 1) / (D N)
类的条件概率由P(xi|c) Dc,xi / Dc
被拉普拉斯修正为
P(xi|c) (Dc,xi 1) / (Dc Ni)
3. 数据集的介绍
Balance Scale Data Set
离散特征的三分类数据集
Attribute Information:
1. Class Name: 3 (L左边重, B天平平衡, R右边重)
2. Left-Weight: 5 (1, 2, 3, 4, 5)
3. Left-Distance: 5 (1, 2, 3, 4, 5)
4. Right-Weight: 5 (1, 2, 3, 4, 5)
5. Right-Distance: 5 (1, 2, 3, 4, 5)4. 导入数据集及处理
import numpy as np
data np.loadtxt(./balance-scale.data, str, unpack True)
print(data)
#数据处理分类结果数值化B-0, L--1, R-1
dicts {R: 1, L: -1, B: 0}
# print(dicts[R])
results []
for i in data:tmp []for j in i:if j ,:continueif j B or j R or j L:tmp.append(dicts[j])else:tmp.append(int(j))results.append(tmp)
data np.array(results) # 处理后的数据集
datax data[ : , 1 : ]
datay data[ : , 0]
print(datax.shape)
print(datay.shape)5. 划分数据集
测试集30%训练集70%
from sklearn.model_selection import train_test_split
trainX, testX, trainY, testY train_test_split(datax, datay, test_size 0.3, random_state 32)6. 实现带拉普拉斯修正的朴素贝叶斯
class myGaussianNB:def __init__(self):初始化四个字典self.label_mapping 类标记 与 下标(int)self.probability_of_y 类标记 与 先验概率(float)self.probability_of_attributes 类标记 与 每个属性的类条件概率# your codeself.label_mapping dict()self.probability_of_y dict()self.probability_of_attributes dict()self.mean_of_attributes dict()def _clear(self):为了防止一个实例反复的调用fit方法我们需要每次调用fit前将之前学习到的参数删除掉# your code self.label_mapping.clear()self.probability_of_y.clear()self.probability_of_attributes.clear()def fit(self, trainX, trainY):self._clear()# 获取类标unique_labels, counts np.unique(trainY, return_countsTrue)total_samples len(trainY)# 遍历每个类for label, count in zip(unique_labels, counts):# 类标映射下标self.label_mapping[label] len(self.label_mapping)# 先验概率self.probability_of_y[label] count / total_sampleslabel_indices np.where(trainY label)[0]label_data trainX[label_indices, :]# 计算每个特征的频率feature_frequencies []for feature_values in label_data.T:unique_values, value_counts np.unique(feature_values, return_countsTrue)feature_frequency dict(zip(unique_values, value_counts / count))feature_frequencies.append(feature_frequency)self.mean_of_attributes[label] feature_frequenciesdef predict(self, testX):predictions []for sample in testX:max_probability float(-inf)predicted_label None# 遍历当前类, 预测概率for label, index in self.label_mapping.items():prior_prob np.log(self.probability_of_y[label])likelihood 0# 计算类条件概率for feature, value in enumerate(sample):if value in self.mean_of_attributes[label][feature]:likelihood np.log(self.mean_of_attributes[label][feature][value])else:likelihood float(-inf)# 条件概率加 log(先验概率)posterior_prob prior_prob likelihoodif posterior_prob max_probability:max_probability posterior_probpredicted_label labelpredictions.append(predicted_label)# lebels转换为np.ndarrayreturn np.array(predictions)7. 模型评价指标的计算
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_scoremodel myGaussianNB()
model.fit(trainX, trainY)
prediction model.predict(testX)# 多分类任务 your code
acc3 accuracy_score(testY, prediction)
precision3 precision_score(testY, prediction, averageweighted)
recall3 recall_score(testY, prediction, averageweighted)
f3 f1_score(testY, prediction, average weighted)
print(精度:, acc3)
print(查准率:,precision2)
print(查全率:,recall2)
print(f1值:,f2)