今天在星巴克呆了一天,复习了一下学习的内容,翻到了研一期间旁听人工智能的课程设计,第一个完全写的一个基于SVM的图像分类任务,记得当时我是实验室第一个独立完成课程设计的,其他小伙伴还是参考我的代码,现在工业界,已经被漫天的深度学习覆盖,难道忘记了曾经万能的SVM了吗?
还是写一遍小文,整理一下笔记,万一有初学者想要参考一下呢,也督促自己熟悉曾经做过的工作。
当时还在CSDN上写过一篇文章,原因是用matlab配置libsvm总是配置不好(当时Win8.1是最新版的系统,libsvm还是最流行的svm工具包,当时是2013年),博客地址在http://blog.csdn.net/qust_waiwai/article/details/17189787 ,只是写了个草稿,没想到,却成了评论最多的文章。
那就先把这个草稿整理完。
Windows64位 MATLAB使用LibSVM
在LibSVM的网站上下载压缩包,然后解压。会发现有一些文件夹还有一些代码文件,其中一个MATLAB
的的文件夹,里面就是提供的matlab接口(这些都在根目录的README文件里面介绍了,还有其他接口的安装与使用说明)。
在MATLAB这个目录下也有一个README文件,这个文件详细的描述了如何使用LibSVM的MATLAB接口,其中介绍了64位系统提供了 预编译好的二进制可执行文件。
1 | On Windows systems, pre-built binary files are already in the |
至于为什么编译不好,先不浪费时间在这上面了,应该是编译器版本的原因,现在Win10要比Win8.1稳定了,应该就没有这个问题了。
将根目录中的windows目录拷贝到MATLAB的安装目录中的toolboxs中,里面全是各种包,不用自己在维护一个文件夹了,然后在MATLAB中Set Path
,把这Windows目录添加进去,在MATLAB中就可以使用了。
输入 svmtrain 测试一下,会输出基本的用法:
1 | >> svmtrain |
基于SVM的图像分类
这是一个课程设计,给定数据,设计分类器,建议使用SVM和kmeans。
问题描述
两类图像(一种是动物,也就是恐龙,另外一种是公共汽车)每种图像95张,总共190张图片,为了方便操作,已经使用sift工具包提取了sift特征描述子,设计了个分类器,可采用直接分割的方法用来训练和测试,也可用交叉验证法训练和测试。
基本思路
每个图像都被提取了SIFT特征,每个SIFT特征向量的维度是固定的,128维,但是每个图片会有多个sift描述子,数量不固定。
参考Bag of Visual Word模型,先用KMeans将将所有的SIFT描述子分类,比如分为10类,那么统计每个图像sift描述子的直方图分布描述子,这个直方图分布描述子就是10维的,这个类似于词袋模型,计算出每个图像的描述特征,然后用SVM训练一个监督学习分类器。
问题的关键点是用词袋模型来描述每张图片。
代码实现
用matlab 实现,下面是两个代码文件。
Main文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120%%#########################################################################
% 名称:作业一
% 时间:2013.12.01
% 姓名:张亚南
% 专业:生物医学工程
% 学院:计算机学院
%##########################################################################
%%
%利用Bag of visual Word模型,使用Kmeans聚类,形成字典
%分类,采用监督学习方法,SVM,每种特征训练集于测试集的比例大约为2:1
%%
%清空工作空间,清屏
clear all;
clc;
%%
%文件夹'k_f'中存放恐龙图片的特征向量
%存放每个恐龙图片特征的文件名
file_name_k = dir('k_f');
%获取特征文件的个数
n_k = length(file_name_k);
%初始化一个矩阵,存放恐龙图片的所有的特征
d_k =zeros(1,128);
%初始化一个矩阵,存放每个恐龙图片的特征的个数
num = zeros(1,2);
%按照文件名读这些特征及其个数,分别存放在矩阵d_k和矩阵中num
for i=3:n_k
%组合文件名
name = strcat('./k_f/',file_name_k(i).name);
%没个特征文件第一行为特征的维数个个数,跳过第一行,读取特征矩阵,并用d临时存储
d = textread(name,'','headerlines',1);
%采用textread读取数据时,默认是以空格为间隔标志,没恶感特征向量都在结尾多了一个0 ,去除最后一维数据
d =d(:,1:128);
%将所有恐龙图片的特征向量存储在一个矩阵d_k中
d_k = [d_k ; d];
%eval(['data_k_' num2str(i-2) '=d']);
%从每个文件中读出每个图片特征的个数个维数
t = textread(['./k_f/' file_name_k(i).name],'',1);
%将每个图片的特征和维数都存放在矩阵num中
num = [num;t];
end
%end of loop
%获取此时矩阵num的维数,去除初始化时的第一行的无用数据
[m,n] =size(num);
num = num(2:m,:);
%获取恐龙图片的特征的矩阵的维数,去除初始化时第一行的无用数据
[m,n] = size(d_k);
d_k = d_k(2:m,:);
%%
%文件夹'_f'中存放汽车图片的特征向量
%存放每个汽车图片特征的文件名
file_name_q = dir('q_f');
%获取特征文件的个数
n_q = length(file_name_q);
%初始化一个矩阵,存放汽车图片的所有的特征
d_q = zeros(1,128);
%按照文件名读这些特征及其个数,分别存放在矩阵d_q和矩阵中num
for i=3:n_q
%组合文件名
name = strcat('./q_f/',file_name_q(i).name);
%没个特征文件第一行为特征的维数个个数,跳过第一行,读取特征矩阵,并用d临时存储
d = textread(name,'','headerlines',1);
%采用textread读取数据时,默认是以空格为间隔标志,没恶感特征向量都在结尾多了一个0 ,去除最后一维数据
d =d(:,1:128);
%将所有汽车图片的特征向量存储在一个矩阵d_q中
d_q = [d_q ; d];
%eval(['data_q_' num2str(i-2) '=d']);
%从每个文件中读出每个图片特征的个数个维数
t = textread(['./q_f/' file_name_q(i).name],'',1);
%将每个图片的特征和维数都存放在矩阵num中
num= [num;t];
end
%end of loop
%获取汽车图片的特征的矩阵的维数,去除初始化时第一行的无用数据
[m,n] = size(d_q);
d_q = d_q(2:m,:);
%将恐龙和汽车的特征向量放在一个矩阵d中
d = [d_k;d_q];
%%
%使用matlab内置的K-均值函数将所有的特征聚类
%idx = kmeans(d,10);
%使用K-中心点将所有的特征的聚类
idx = KMeans(d,10,2);
%%
%初始化一个矩阵,用来记录每个图片特征给文件的由字典中的词的个数组成的向量
dema = zeros(190,10);
%设定每个图片特征在总的特征矩阵中的标志
last = 0;
%两重循环,构建每个特征文件的向量,组成一个新的矩阵
for i = 1:190
for j =1:num(i,1)
dema(i,idx(j+last)) = dema(i,idx(j+last)) +1;
end
last = num(i,1);
end
%分别提取出训练数据和测试数据,比例是2:1
train_data = dema(1:60,:);
train_data = [train_data;dema(96:155,:)];
test_data = dema(61:95,:);
test_data= [test_data;dema(156:190,:)];
%存储类别标志,对应训练数据和测试数据
label_train = zeros(1,60);
label_train = [label_train,ones(1,60)];
label_train = label_train';
label_test = zeros(1,35);
label_test = [label_test,ones(1,35)];
label_test = label_test';
%%
%使用svmtrain函数训练
model = svmtrain(label_train,train_data);
%用训练的数据预测待测试的数据
[predice_label,accuracy,dec_values] = svmpredict(label_test,test_data,model);
%end
KMeans是参考了网络资源:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60function label = KMeans( data,K,mode)
% -data
% -K: number of clusters
% -mode:
% 1: use kmeans cluster algorithm in matlab
% 2: k_medroid algorithm: use data points as k centers
N_samples = 91024;
N_features = 128;
switch (mode)
%call system function KMeans
case 1
label = kmeans(data,K);
%use kmedroid method
case 2
for testcase = 1:10% do 10 times to get rid of the influence from Initial_center
K_center = Initial_center(data,K); %select initial points randomly
changed_label = N_samples;
label = zeros(1,N_samples);
iteration_times = 0;
while changed_label~=0
cls_label = cell(1,K);
for i = 1: N_samples
for j = 1 : K
D(j) = dis(data(i,:),K_center(j,:));
end
[~,label(i)] = min(D);
cls_label{label(i)} = [cls_label{label(i)} i];
end
changed_label = 0;
cls_center = zeros(K,N_features);
for i = 1 : K
cls_center(i,:) = mean(data(cls_label{i},:));
D1 = [];
for j = 1:size(cls_label{i},2)%number of samples clsutered in i-th class
D1(j) = dis(cls_center(i,:),data(cls_label{i}(j),:));
end
[~,min_ind] = min(D1);
if ~isequal(K_center(i,:),data(cls_label{i}(min_ind),:))
K_center(i,:) = data(cls_label{i}(min_ind),:);
changed_label = changed_label+1;
end
end
iteration_times = iteration_times+1;
end
end
end
function center = Initial_center(X,K)
rnd_Idx = randperm(N_samples,K);
center = X(rnd_Idx,:);
end
function res = dis(X1,X2)
res = norm(X1-X2);
end
end