-
一、实验目的
该实验的Wine数据集来自于UCI机器学习数据库中,数据集中的数据则是产自意大利同一地区但来自三个不同品种的葡萄酒进行化学分析的结果,分析确定了三种酒中每种所含13种不同成分的数量。
实验的目的就是利用分类算法实现Wine数据集中三种不同品种的葡萄酒分类。通过学习贝叶斯分类相关的知识,我们决定使用贝叶斯分类算法对Wine数据集进行分类。Wine数据集含有178个样本,我们将采用不同比例的训练集和测试集,并采用朴素贝叶斯分类算法实现Wine数据集的分类。实验过程所使用的编程软件为MATLAB仿真软件,利用MATLAB实现算法及分类。
-
二、实验内容
对葡萄酒数据集运用朴素贝叶斯算法实现分类任务,并计算测试集准确率。
-
三、实验数据
这些数据包括了三种酒中13中不同成分的数量。13种成分分别是:Alcohol、Malic acid、Ash、 Alkalinity of ash、Magnesium、Total phenols、Flavanoids 、Nonflavanoid phenols、Proanthocyanins、Color intensity、Hue、OD280/OD315 of diluted wines、Proline。在‘Wine.data’文件中,每一行代表一种酒的样本,共有178个样本;一共14列,其中第一列为类别标志属性,共有3类,分别标记为‘1’、‘2’、‘3’,对于三种不同的葡萄酒;后面13列为每一个样本对应属性的属性值;类别‘1’共有59个样本,类别‘2’共有71个样本,类别‘3’共有48个样本。
由于数据集中每个样本的数据都是完整的,没有空缺值,所以没有对该数据集进行必要的数据清洗工作。
-
四、实验要求
- 对程序作注。
- 对训练样本和测试样本分别选取不同的比例进行实验,具体如下表所示:
组别 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
训练样本数 | 1/2 | 1/3 | 1/4 | 1/5 | 1/6 | 1/7 | 1/8 | 1/9 |
测试样本数 | 1/2 | 2/3 | 3/4 | 4/5 | 5/6 | 6/7 | 7/8 | 8/9 |
识别率 |
- 根据实验结果,作出二维曲线图(横坐标为训练样本数,纵坐标为识别率)。
- 根据实验结果作分析,在可能情况下,对所给的程序作修改和补充。
- 实验报告求:
- 项目报告(必须用给定的报告封面)(电子版和打印板)
- 内容:
第一部分:基于最小错误率贝叶斯分类器的介绍;
第二部分:分类算法的流程图;
第三部分:代码+注示;
第四部分:结果和分析
-
五、实验步骤
- 基于最小错误率贝叶斯分类器的介绍:
贝叶斯分类算法是一种基于统计分类的方法。在贝叶斯学习算法中有一种实用性很强的算法被称为朴素贝叶斯分类算法。即使错误率为最小的分类规则称之为基于最小错误率的贝叶斯决策。若已知总共有M类样品,以及各类在n维特征空间的统计分布,根据概率知识可以通过样品库得知各类别wi(i=1,2,…,M)的先验概率p(wi)以及类条件概率p(X/wi)。对于待测样品,贝叶斯公式可以计算出该样品分属各类别的概率,叫做后验概率p(wi/X)。比较各个后验概率,把X归于后验概率最大的那一个类。
2.分类算法的流程图:
3.代码+注释
clear
clc
load wine.data.txt
wine=wine_data
% load wine.data
wine_class = wine; % 变量wine_class接收训练样本数据
% mapminmax为MATLAB自带的归一化函数
[wine_class,ps] = mapminmax(wine_class(:,2:size(wine_class,2))',0,1); % 归一化要先转置
wine_class = [wine(:,1),wine_class'];
% 训练集和测试集的划分
% K-折交叉验证(k-fold crossValidation)
[wine_class_r, wine_class_c] = size(wine_class); % wine_class_r接收返回的矩阵的行数,wine_class_c接收返回的矩阵的列数
K=10;
sum_accuracy = 0; % 初始化数据
%将数据样本随机分割为10部分
indices = crossvalind('Kfold', wine_class_r,K); % 做十次交叉验证,按照矩阵的行数均分成十份,每一份打上不同的记号,记号为一个正整数
for i = 1 :K % 做K次循环,每一次取其中一份作为训练集,其余的做测试集。
% 获取第i份测试数据的索引逻辑值
train = (indices == i);
% 取反,获取其余i-1份的测试数据的索引逻辑值
test = ~train; % 将矩阵中所有值为0的元素重新赋值为1,
%1份测试,9份训练
% 将test和wineclass比较,test中元素值为1的那一行,对应wineclass的那一行元素的第2列到第wineclass_c列里的数据就会被选中出来。
test_data = wine_class(test, 2 : wine_class_c); %获取其余i-1份中每一行的第二列到第wineclass_c列的数据
test_label = wine_class(test, 1); % 获取第i份中每一行数据所对应的类别
train_data = wine_class(train, 2 : wine_class_c ); %获取第i份中每一行的第二列到第wineclass_c列的数据
train_label = wine_class(train, 1); % 获取第i份中每一行数据所对应的类别
%模型的训练以及预测结果
train_model = Naive_Bayesian( train_data,train_label); % 通过训练样本和训练类别得到分类训练模型
result = predict_BN(train_model,test_data,test_label); % 通过分类训练模型,测试样本和测试类别得到预测结果的类别
accuracy_test = sum(result == test_label) / length(test_label)*100; % 测试的准确率
sum_accuracy = sum_accuracy + accuracy_test; % 对每一次的测试的准确率进行求和
end
%求平均准确率
mean_accuracy = sum_accuracy / K;
disp('平均准确率:');
fprintf('%15.2f%%\n',mean_accuracy) % 输出平均准确率
%%
function [model]= Naive_Bayesian(X, Y)
% 朴素贝叶斯分类器的实现
m=size(X,1);%记录训练集样本总数
n=size(X,2);%记录训练集特征属性数目
%记录类别数及每个类别编号
yy=Y(:); % 得到所有类别数
yy=sort(yy); % 对yy进行排序
d=diff([yy;max(yy)+1]);%差分计算
count = diff(find([1;d]));%记录每个类别出现次数//find返回非零元素的索引位置
class_num=yy(find(d));%记录类别编号[1;2;3]
%计算每个类别的先验概率 p(W)
for i=1:length(class_num) % 依次计算3个类别的先验概率
pW(i) = count(i)/m; % 计算第i个类别的先验概率
end
x1 = X(1:count(1),:); %第一类样本
x2 = X(count(1)+1:count(1)+count(2),:); %第二类样本
x3 = X(count(1)+count(2)+1:count(1)+count(2)+count(3),:); %第三类样本
x = {x1;x2;x3};
for i = 1:length(class_num)
smean{i} = mean(cell2mat(x(i))); %求各类别的均值
scov{i} = cov(cell2mat(x(i))); %求各类别的协方差矩阵
end
for i = 1:length(class_num)
sinv{i} = pinv(cell2mat(scov(i))); %求各类别协方差矩阵的逆矩阵
sdet{i} = det(cell2mat(scov(i))); %求各类别协方差矩阵的行列式
end
model.ssmean = smean;
model.sscov = scov;
model.ssinv = sinv;
model.ssdet = sdet;
model.pW = pW;
end
function result = predict_BN(model,X,Y)
%朴素贝叶斯分类器的预测
ssmean = model.ssmean ; % 得到判别函数公式所需要的各个元素的值
sscov = model.sscov ;
ssinv = model.ssinv ;
ssdet = model.ssdet ;
pW = model.pW;
m = size(X,1);%记录测试样本总数
n = size(X,2);%记录测试样本特征数13
%记录每个类别编号
yy=Y(:);
yy=sort(yy);
d=diff([yy;max(yy)+1]);%差分计算
class_num=yy(find(d));%记录类别编号
%求判别函数gi(x)
for i = 1:length(class_num)
for j = 1:length(X)
gi(j,i) =log(pW(i))-(1/2)*(X(j,:)'-cell2mat(ssmean(i))')'*(cell2mat(ssinv(i)))*(X(j,:)'-cell2mat(ssmean(i))')-(1/2)*log(cell2mat(ssdet(i)));
end
end
for i=1:m
[max_Pro(i,1), index] = max(gi(i,:));%输出处于最大概率的概率值以及其对应的索引位置
result(i,1)=class_num(index);%待测样本的预测类别
end
end
4.结果和分析:训练样本数越多则识别率越高
组别 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
训练样本数 | 1/2 | 1/3 | 1/4 | 1/5 | 1/6 | 1/7 | 1/8 | 1/9 |
测试样本数 | 1/2 | 2/3 | 3/4 | 4/5 | 5/6 | 6/7 | 7/8 | 8/9 |
识别率 | 92.13% | 81.67% | 17.36% | 23.34% | 29.13% | 26.11% | 40.53% | 27.60% |