图像识别4:决策树+神经网络GUI+支持向量机实验
写在最前面
图像识别1:基于相似性度量的二分类实验
图像识别2:图像多分类实验
图像识别3:梯度下降和LDA线性模型实验
图像识别4:决策树+神经网络GUI+支持向量机实验
图像识别5:LDA 与 SVM+神经网络+支持向量机实验
图像识别6:综合
一、实验目的
熟练matlab中决策树的使用,初步掌握神经网络的搭建和使用,以及神经网络 GUI 的使用方法,了解支持向量机的使用方法;
二、实验内容及结果
1.使用决策数实现西瓜数据集2.0的分类(随机十次的结果取平均);
2.使用决策数实现鸢尾花的分类(随机十次的结果取平均) ;
3.画出十次实验的精度变化曲线图。
1.使用鸢尾花数据分为2组,每组各75个样本,每组中每种花各有25个样本。当中一组作为训练样本,另外一组作为测试样本,将3类花分别编号为1,2,3 ,实现神经网络实验;
2.分析网络层数及节点数对分类精度的影响;
3.掌握神经网络工具箱GUI操作(nntool)。
1.掌握 lib-svm 的安装,了解 libsvm 的使用和参数设置;
2.根据两类人脸图,实现二分类实验;
3.获得不同参数下的分类精度。
(1)决策树
划分方法和前几个实验一样,预测这里调的是C4_5的函数包。
决策树预测的10次精度分别为0.9600 0.9600 0.9000 0.9000 0.9400 0.9600 0.9600 0.8400 0.9600 0.9600,均值为0.9340,可以看到决策树预测的精度相比之前的欧式距离等提高了很多。
(2)神经网络
数据归一化,为了消除数量级的影响,同时收敛更快。最大最小标准化(Min-Max Normalization)使结果值映射到[0,1]之间,适用在数值比较集中的情况,其缺点为如果max和min不稳定,很容易使得归一化结果不稳定,使得后续使用效果也不稳定。
每类花依次分别取二分之一作训练、测试。这里采用eval函数,可以自动给变量赋名赋值。
注意调包时,需要测试集标签长这样:
使用newff函数进行神经网络的搭建。设置三层网络层中的节点数依次为[10,5,3],激活函数均为双曲正切 S 形函数(tansig)函数,训练算法采用常见的梯度下降 BP 训练函数,对应参数为’traingd’,神经网络训练的目标误差、周期、最大迭代次数、学习率分别为 50、500、0.01、0.01。
得到分类正确率为:97.333333%
改成两层神经网络后,分类正确率为:86.666667%
学习率改为0.1后,分类正确率为:64.000000%(十之八九),分类正确率为:94.666667%
改为1后,分类正确率为:93.333333%(十之八九),分类正确率为:48.000000%
(多次实验均为这个结果,不确定分类正确率上升的原因)
参考:https://www.cnblogs.com/yumoye/p/11055813.html
猜测:克服了因为学习率不够,而无法跳出鞍点的情况;
之前由于学习率过低,而处于过拟合状态。
绘制学习率变化的精度曲线图。01变化明显,1100几乎没有变化。
使用 matlab 的 nntool 工具箱做神经网络预测。
先进行数据预处理。
Performance 查看训练和测试的 mse(均方误差)的变化情况。
(3)支持向量机二分类实验
图片读取并保存(步骤和之前实验一样),并计算hog特征。
预测结果精度为40%
改变参数。
三、实验心得
通过本次实验,熟练matlab中决策树的使用,初步掌握神经网络的搭建和使用,以及神经网络 GUI 的使用方法,了解支持向量机的使用方法。通过实验发现了学习率的知识盲点,通过查阅文献及课本及时进行了查缺补漏。对数学与编程的应用中有了更深的理解,在老师和同学的帮助下,代码的时空复杂度降低,并且复用性得到了较大的提升。
四、实验源码
实验八 决策树预测
clc;clear;close all;
%% 数据预处理
% delimiterIn = ','; % 字符分隔符
% data=importdata('iris.txt', delimiterIn);
% data=load('iris.data'); %ASCII 文件 iris.data 的行号 1 中的文本未知
data=load('data.mat');
data.iris(1:50,5)=ones(50,1);
data.iris(51:100,5)=2*ones(50,1);
data.iris(101:150,5)=3*ones(50,1);
for a=1:10
disp(a);
%% 划分训练集和测试集比例(2:1划分)
e=round(length(data.iris(:,1))*2/3);
num=randperm(length(data.iris)); %打乱列序列
train_num=num(1:e); %取打乱序列的前60%
test_num=num(e+1:end); %取打乱序列的后40% %end直到数组结尾
% 划分数据
traindata=data.iris(train_num,:); % 留出法的训练集
testdata=data.iris(test_num,:); % 留出法的测试集
% 划分data和label
train_patterns=traindata(:,1:(size(traindata,2)-1));
train_targets=traindata(:,size(traindata,2))';
test_patterns=testdata(:,1:(size(testdata,2)-1));
test_targets=testdata(:,size(testdata,2))';
% 决策树预测
[test_targets_predict]=C4_5(train_patterns',train_targets,test_patterns',5,10);
temp_count=0;
for i=1:size(test_targets_predict,2)
if test_targets(:,i)==test_targets_predict(:,i)
temp_count=temp_count+1;
end
end
accuracy(a)=temp_count/size(test_targets,2);
disp(accuracy);
end
%% 画出精度曲线图,通过曲线图分析噪声对两种方法的影响
x=[1:10];
plot(x,accuracy,'-*b')
axis([0 10 0 1])
% 设置坐标格
grid on;
% 设置字体格式
set(gca,'FontSize',15); xlabel('实验次数','fontsize',17);
ylabel('分类精度','fontsize',17);
title('精度曲线图');
实验九 神经网络
% 使用鸢尾花数据,将3类花分别编号为1,2,3。
% 每组中每种花各有25个样本,每组各75个样本,共2组。
% 当中一组作为训练样本,另外一组作为测试样本,实现神经网络实验;
clc;clear;close all;
% iris1(1:50,5)=ones(50,1);
% iris1(51:100,5)=2*ones(50,1);
% iris1(101:150,5)=3*ones(50,1);
%% 数据预处理
load('iris.mat');
data1=iris;
% 一行归一化
data2 = data1';
[data, PS] = mapminmax(data2(1:4,:));
data = data';
% 3类花分别编号为1,2,3
data(1:50,5)=ones(50,1);
data(51:100,5)=2*ones(50,1);
data(101:150,5)=3*ones(50,1);
%% 划分数据
for i=1:3
eval(['temp',num2str(i),'=','find(data(:,5)==i)']); %自动给变量赋名和赋值
% eval(['e',num2str(i),'=',round(length(eval(['temp',num2str(i)]))/2)]);
e = round(length(eval(['temp',num2str(i)]))/2);
num=randperm(length(eval(['temp',num2str(i)]))); %打乱列序列
train_num=num(1:e); %取打乱序列的前50%
test_num=num(e+1:end); %取打乱序列的后50% %end直到数组结尾
% 划分数据
if i==1
traindata1=data(temp1(train_num),:); % 留出法的训练集
testdata1=data(temp1(test_num),:); % 留出法的测试集
end
if i==2
traindata2=data(temp2(train_num),:); % 留出法的训练集
testdata2=data(temp2(test_num),:); % 留出法的测试集
end
if i==3
traindata3=data(temp3(train_num),:); % 留出法的训练集
testdata3=data(temp3(test_num),:); % 留出法的测试集
end
end
traindata=[traindata1;traindata2;traindata3];
testdata=[testdata1;testdata2;testdata3];
X_train = traindata(:,1:4);
% x_label = traindata(:,5);
Y_test = testdata(:,1:4);
Y_label = testdata(:,5);
x_label = zeros(length(X_train),3);
x_label(:,1)=ones(length(X_train),1);
x_label(:,2)=2*ones(length(X_train),1);
x_label(:,3)=3*ones(length(X_train),1);
% 神经网络的搭建
A = minmax(X_train');
% 创建神经网络
net = newff(A, [10,5,3], {'tansig','tansig','tansig'}, 'traingd');
%设置训练参数
net.trainparam.show = 50;
net.trainparam.epochs = 500;
net.trainparam.goal = 0.01;
net.trainParam.lr = 0.01;
%开始训练
[net, tr, Y1, E] = train(net, X_train', x_label');
% 开始测试
Y = sim(net, Y_test');
% 统计识别正确率
[s1, s2] = size(Y);
true_num = 0;
for j = 1:s2
[m ,index] = max(Y(:,j));
if(index == Y_label(j))
true_num = true_num + 1;
end
end
fprintf("分类正确率为:%f%%\n",100*true_num/s2);
实验十 支持向量机
% 根据两类人脸图,实现二分类实验
clc;clear;close all;
warning('off') %关掉警告
base_path = 'D:\Desktop\大三上\神经网络\10\人脸图';
path = string();
subpath = dir( base_path );
%% 训练阶段
%读取样本并计算hog特征
all_imgnum=0;
for i = 1:length(subpath)-2 % 读取单文件夹下,all文件夹% 1,2分别是.和..% 先获取第一个子文件路径,然后获取第二个子文件路径
sub_path = fullfile(base_path, subpath(i+2).name);% disp(sub_path); % D:\Desktop\大三上\神经网络\数据\MIT室内场景\airport_inside
image_name = dir(sub_path); % 获取文件夹里的所有图像信息% disp(image_name(3).name); % airport_inside_0001.jpg
img_num=length(image_name)-2; % 文件夹里图像个数% disp(img_num); % 608 405 197 662
all_imgnum=all_imgnum+img_num;% disp(all_imgnum); % 608 1013 1210 1872
%% 获取图片数据
for j = 1:img_num % 获取子文件夹下图片的路径
% fullfile函数利用文件各部分信息创建并合成完整文件名
img_path = fullfile(sub_path, image_name(j+2).name); % 子文件夹+图片名称
img_path
read_img = imread(img_path); % 读图
image = imresize(read_img, [64,64]); % 图片统一大小,指定长宽[64,64]
if(ndims(read_img)==3)
read_img = rgb2gray(read_img); % RGB图像转灰度图像
end
hog =hogcalculator(image);
data(all_imgnum-img_num+j,1:1764)=hog;
end
% 存放图片label % 定义标签,0:负样本 1:正样本
label(all_imgnum-img_num+1:all_imgnum,1)=(i-1)*ones(img_num,1);
end
for i = 1:5
[m,n]=size(data);
%[Train, Test] = crossvalind('LeaveMOut',N, M);
% 该命令返回一个逻辑值的标记向量,从N个观察样本中随机选取M个样本作为测试集。M的缺省值为1。值得注意的是,LeaveMOut在循环中使用不能保证产生的是互补集合,即每次循环的随机选取是独立的。如果要用互补的话还是使用Kfold命令。
[train,test]=crossvalind('LeaveMOut',m,10);
svmStruct = svmtrain(label(train),data(train,:),['-s '+ 4,'-v'+10,'-t'+i-1]);
[prelabel,accuracy,decision_values]=svmpredict(label(test),data(test,:),svmStruct); %预测
accuracy1(i)=accuracy(1)/100;
end
x=[1:5];
plot(x,accuracy1,'-*b')
axis([0 5 0 1])
% 设置坐标格
grid on;
% 设置字体格式
set(gca,'FontSize',15); xlabel('t','fontsize',17);
ylabel('分类精度','fontsize',17);
title('精度曲线图');