1. 程式人生 > >基於PCA+SVM的MINIST資料集分類

基於PCA+SVM的MINIST資料集分類

1. MINIST資料集下載地址:http://yann.lecun.com/exdb/mnist/.

2. MINIST資料影象讀取MATLAB程式碼(參考斯坦福大學Andrew Ng教授的課件):

function images = loadMNISTImages(filename)
%loadMNISTImages returns a 28x28x[number of MNIST images] matrix containing
%the raw MNIST images

fp = fopen(filename, 'rb');
assert(fp ~= -1, ['Could not open ', filename, '']);

magic = fread(fp, 1, 'int32', 0, 'ieee-be');
assert(magic == 2051, ['Bad magic number in ', filename, '']);

numImages = fread(fp, 1, 'int32', 0, 'ieee-be');
numRows = fread(fp, 1, 'int32', 0, 'ieee-be');
numCols = fread(fp, 1, 'int32', 0, 'ieee-be');

images = fread(fp, inf, 'unsigned char');
images = reshape(images, numCols, numRows, numImages);
images = permute(images,[2 1 3]);

fclose(fp);

% Reshape to #pixels x #examples
images = reshape(images, size(images, 1) * size(images, 2), size(images, 3));
% Convert to double and rescale to [0,1]
images = double(images) / 255;
end

3. MINIST資料label讀取MATLAB程式碼(參考斯坦福大學AndrewNg教授的課件):

function labels = loadMNISTLabels(filename)
%loadMNISTLabels returns a [number of MNIST images]x1 matrix containing
%the labels for the MNIST images

fp = fopen(filename, 'rb');
assert(fp ~= -1, ['Could not open ', filename, '']);

magic = fread(fp, 1, 'int32', 0, 'ieee-be');
assert(magic == 2049, ['Bad magic number in ', filename, '']);
numLabels = fread(fp, 1, 'int32', 0, 'ieee-be');
labels = fread(fp, inf, 'unsigned char');
assert(size(labels,1) == numLabels, 'Mismatch in label count');

fclose(fp);
end

4. PCA介紹:PCA主要通過對高維資料進行投影得到子空間向量來進行降維。具體地,就是求樣本的協方差矩陣及其特徵值、特徵值向量,通過選取一定閾值內的特徵值及其對應的特徵向量,構成投影矩陣,這個投影矩陣中的向量之間都相互正交,在儘量降低特徵維數的同時也儘量減少資訊損失。降維後的特徵向量具有低相關性,具有樣本的本質屬性,也使得後續分類不易陷入過擬合。

5. PCA具體步驟:

6. 常用降維方法:PCA(無監督),LDA(有監督),LLE(非線性),ISOMAP(非線性);

7. 常用分類方法:PCA+SVM,SRC(稀疏表徵+字典),LRC;

8. 注意1:對於非線性降維方法,在求取投影矩陣P時,只需利用訓練資料即可,不需要用到測試資料,P一旦求取後可認為是固定的,直接對測試資料進行降維即可;而非線性降維方法是需要保持區域性結構不變,沒有顯式的對映,所以需要測試資料的參與;目前將非線性方法線性化是一個趨勢。

9. 注意2: MATLAB中的eig函式求取的特徵值一般是按照從小到達的順序給出的,但是某些情況下相反,因此需要採用sort函式進行固定方向排序;

10. 注意3:實驗發現在minist資料集上採用Chi-square距離沒有歐氏距離的分類效果好;

11. PCA降維後再恢復的公式:;

12. SVM方法的兩種實現:

     a. 採用MATLAB自帶的svmtrain和svmclassify函式;

     b. 採用libSVM工具箱;

13. MATLAB自帶SVM函式和libSVM工具箱中函式的區別:

     a. libSVM工具箱使用方便,引數調節也方便;

     b. MATLAB自帶的SVM只能用於二分類,且不能用於迴歸(regression);

     c. libSVM中有多種如c-SVM,nu-SVM模型可選,而MATLAB自帶SVM只有c-SVM;

     d. libSVM可實現多分類,有1對多的方法,也有1對1的方法,還有層次法,MATLAB中採用的是1對1的方法,1對多的方法是訓練樣本不平衡,如果對負樣本進行去掉,則沒有充分利用全部資料;1對1的方法是設計(k-1)*k/2個二分類器,對每個測試樣本進行輸出,輸出最多的那個類別就是最終的判別類。

14. 注意:SVM實現的核心是採用SMO演算法,SMO:Sequentialminimal optimization, 微軟研究員提出,是一種快速的二次規劃演算法,針對線性和資料稀疏時效能更優;

15. 注意: libSVM中的資料有時可能需要用libsvmread函式進行格式轉換;

16. libSVM基本用法:

     model = svmtrain(label, data, ‘option’);

     引數option選項:

            -s:表示SVM的型別,0:c-SVC, 1:nu- SVC, 2: one-class SVR; 3:epsilon-SVR, 4: nu-SVR;

            -t: 表示核函式型別,0: 線性,1:多項式,2:徑向基函式,3:sigmoid, 4: precomputed的核;

           -d: 多項書的階數;

           -c: 損失函式係數;

           -g: 核函式gamma引數,針對rbf,多項式核,sigmoid核。

     例子: model = sumtrain(label, data,’-s 0 -t 2-c 0.5 -g 0.1’);

18. 有關SVM核函式的選取:

    a.當特徵數和樣本數差不多時,可以採用線性或多項式核;

    b. 當特徵數小於樣本數時,一般採用高斯核;

    c.當特徵數遠小於樣本數時,需要手動新增特徵滿足上面兩個的要求;

17. PCA+SVM用於MINIST資料集分類程式碼:

function minist_svmcls()

clc;
% 讀取minist資料集
train_data_name = 'F:\train-images.idx3-ubyte';
train_label_name = 'F:\train-labels.idx1-ubyte';
test_data_name = 'F:\t10k-images.idx3-ubyte';
test_label_name = 'F:\t10k-labels.idx1-ubyte';

train_data = loadMNISTImages(train_data_name);
train_label = loadMNISTLabels(train_label_name);
test_data = loadMNISTImages(test_data_name);
test_label = loadMNISTLabels(test_label_name);

% 下面採用SVM進行分類,特徵向量都一樣,只是分類器在變化
%訓練模型,x_train每一行代表一個樣本,列數等於樣本特徵維度,y_train為一列向量,每一個元素代表一個標籤
test_N = 500;
trains = train_reduced_feat';
tests = test_reduced_feat(:,1:test_N)';
trainClassIDs = train_label;
testClassIDs = test_label(1:test_N);
model = svmtrain(trainClassIDs, trains,'-s 0 -t 2');
%測試模型,x_test每一行代表一個樣本,列數等於樣本特徵維度,y_test為一列向量,每一個元素代表一個標籤
[pred, acc, ~] = svmpredict(testClassIDs, tests, model);