基于SVM的图像分类

今天在星巴克呆了一天,复习了一下学习的内容,翻到了研一期间旁听人工智能的课程设计,第一个完全写的一个基于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位系统提供了 预编译好的二进制可执行文件。

On Windows systems, pre-built binary files are already in the 
directory '..\windows', so no need to conduct installation. Now we 
provide binary files only for 64bit MATLAB on Windows. If you would 
like to re-build the package, please rely on the following steps.

至于为什么编译不好,先不浪费时间在这上面了,应该是编译器版本的原因,现在Win10要比Win8.1稳定了,应该就没有这个问题了。

将根目录中的windows目录拷贝到MATLAB的安装目录中的toolboxs中,里面全是各种包,不用自己在维护一个文件夹了,然后在MATLAB中Set Path,把这Windows目录添加进去,在MATLAB中就可以使用了。

输入 svmtrain 测试一下,会输出基本的用法:

>> svmtrain
Usage: model = svmtrain(training_label_vector, training_instance_matrix, 'libsvm_options');
libsvm_options:
-s svm_type : set type of SVM (default 0)
    0 -- C-SVC      (multi-class classification)
    1 -- nu-SVC     (multi-class classification)
    2 -- one-class SVM
    3 -- epsilon-SVR    (regression)
    4 -- nu-SVR     (regression)
-t kernel_type : set type of kernel function (default 2)

基于SVM的图像分类

这是一个课程设计,给定数据,设计分类器,建议使用SVM和kmeans。

问题描述

两类图像(一种是动物,也就是恐龙,另外一种是公共汽车)每种图像95张,总共190张图片,为了方便操作,已经使用sift工具包提取了sift特征描述子,设计了个分类器,可采用直接分割的方法用来训练和测试,也可用交叉验证法训练和测试。

扫描二维码关注公众号,回复: 2231925 查看本文章

基本思路

每个图像都被提取了SIFT特征,每个SIFT特征向量的维度是固定的,128维,但是每个图片会有多个sift描述子,数量不固定。

参考Bag of Visual Word模型,先用KMeans将将所有的SIFT描述子分类,比如分为10类,那么统计每个图像sift描述子的直方图分布描述子,这个直方图分布描述子就是10维的,这个类似于词袋模型,计算出每个图像的描述特征,然后用SVM训练一个监督学习分类器。

问题的关键点是用词袋模型来描述每张图片。

代码实现

用matlab 实现,下面是两个代码文件。
Main文件

%%#########################################################################
%       名称:作业一
%       时间:2013.12.01
%       学院:计算机学院
%##########################################################################
%%

%利用Bag of visual Word模型,使用Kmeans聚类,形成字典
%分类,采用监督学习方法,SVM,每种特征训练集于测试集的比例大约为21
%%

%清空工作空间,清屏
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
%分别提取出训练数据和测试数据,比例是21
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是参考了网络资源:

function 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

猜你喜欢

转载自blog.csdn.net/qust_waiwai/article/details/54935702