🌀Jarson Cai's Blog
头脑是日用品,不是装饰品
《模式识别&机器学习》课后作业(2)
研究生课程课后小作业

《模式识别&机器学习》课后作业

作业二

根据最小均方误差算法(hk算法)对0~9的中任意两个数进行分类。

代码实现

  • h_k.m:(主函数)
 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
%h_k.m
clear variables
clc

%读取数据
load('test_images.mat');
load('test_labels.mat');

%设定数据集
train_num = 1000;
test_num = 200;

%临时变量
j = 1;
epoch = 100;%设定的最大训练轮数
nums = [4, 6];
lr = 0.2; %学习率
flag = 1;%默认代表线性可分

%提取样本并做好标签转换
for i = 1:10000
    if test_labels1(i) == nums(1)
        data(:, :, j) = test_images(:, :, i);
        label(j) = 1;%代表第一个数的标签
        j = j + 1;
    end
    if test_labels1(i) == nums(2)
        data(:, :, j) = test_images(:, :, i);
        label(j) = -1;%代表第二个数的标签
        j = j + 1;
    end
    if j > train_num + test_num
        break;
    end
end


%将标签提前准备好,增广到训练数据中
temp = ones(train_num, 1);
for i = 1 : 1000
   temp(i, 1) = label(i); 
end
%矩阵转向量
data_ = mat2vector(data, train_num + test_num);

%测试数据归一化
test_data = [data_(train_num + 1:train_num + test_num, :), ones(test_num, 1)];

%权向量迭代
[w, flag, e] = lmse(data_(1:train_num, :),label(1,1:train_num), lr, flag, epoch, temp);


% 测试(预测) 
s = [];
for k = 1:test_num
        s(k) = test_data(k,:)*w;
        if s(k) > 0
            result(k) = 1;%预测为第一个数
        else
            result(k) = -1;%预测为第二个数
        end
    end

% 输出预测的准确率
acc = 0;%正确分类个数
err = 0;%错误分类的个数
for sample = 1:test_num
	if result(sample)==label(train_num+sample)
acc = acc+1;
else
fprintf('分类错误的序号为:%d\n',sample);
        err = err + 1;
end    
end

fprintf('分类错误的个数为:%d,分类正确的个数为:%d\n',err, acc);
fprintf('精确度为:%5.2f%%\n',(acc / test_num)*100);
  • mat2vector.m:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
%mat2vector.m
function[w] = mat2vector(mat, maxCnt)
    w = [];
    for i = 1 : maxCnt
        mat1 = mat(:, :, i);
        [x, y] = size(mat1);
        mat2 = mat1';
        mat3 = reshape(mat2, 1, x * y);
        w = [w; mat3];
    end
end 
  • lmse.m:
 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
%lmse.m
%lmse算法
%参数1:训练数据 参数2:标签 参数3:学习率 参数4:标志位(是否线性可分)参数5:增广需要的数据
%返回值:权向量 flag标志位 误差向量
function[res,flag,e] = lmse(data, label,lr, flag, maxEpoch, temp)
    res = [];
    [rows,cols]=size(data);
    for m = 1 : rows
        if label(m) == -1
            data(m,:) = -data(m,:);
        end
    end
    b=[ones(1000,1)];%初始松弛向量
    data = [data,temp];%训练数据增广
 
    data1 = pinv(data); %pinv为求伪逆,因为部分矩阵不可逆
    w = (data1)*b;%初始权向量 
    e = data * w - b;%误差向量
    
    delta = lr * (e + abs(e));% (e(k) + |e(k)|)*n(k + 1)
    N = length(b);
    k = 0;
    isEnd = 0; %循环结束的标志
    
    while(~isEnd)
        if(k >= maxEpoch)%最大训练轮数
            flag = 0;
            break;
        end
        
        %误差大于0的数目
        x = 0;
        x_tozero = 0;
        %误差小于0的数目
        y = 0;
        y_tozero = 0;
        for i = 1 : N
            if(e(i) < 1e-4 && e(i) > 0)
                x_tozero = x_tozero + 1;
            elseif (e(i) > -(1e-4) && e(i) < 0)
                y_tozero = y_tozero + 1;
            elseif (e(i) > 0)
                x = x + 1;
            else 
                y = y + 1;
            end
        end
        
        %fprintf('x,x_tozero,y,y_tozero:%d,%d,%d,%d', x,x_tozero,y,y_tozero);
        
        if((x_tozero + y_tozero) == N) %%所有样本误差趋向于0
            isEnd = 1;
        elseif ((x_tozero + x) == N) %%误差趋向于0或者大于0
            isEnd = 1;
        elseif ((y_tozero + y) == N) %%误差趋向于0或者小于0
            flag = 0;%线性不可分
            isEnd = 1;
            break;
        else
           k = k + 1;
           w = w + data1*delta;%权向量更新
           b = b + delta; %松弛向量更新
           e = data * w - b;%误差向量更新
           delta = lr * (e + abs(e));
        end
    end
    res = [res;w];
    fprintf('迭代的轮数:%d\n', k);
end

结果

  • 对4和8进行分类:
迭代的轮数:100
分类错误的序号为:6
分类错误的序号为:19
分类错误的序号为:25
分类错误的序号为:27
分类错误的序号为:29
分类错误的序号为:39
分类错误的序号为:41
分类错误的序号为:42
分类错误的序号为:50
分类错误的序号为:51
分类错误的序号为:55
分类错误的序号为:57
分类错误的序号为:105
分类错误的序号为:112
分类错误的序号为:146
分类错误的序号为:150
分类错误的序号为:151
分类错误的序号为:157
分类错误的序号为:158
分类错误的序号为:166
分类错误的序号为:184
分类错误的序号为:188
分类错误的个数为:22,分类正确的个数为:178
精确度为:89.00%
  • 对1和9进行分类:
迭代的轮数:100
分类错误的序号为:11
分类错误的序号为:17
分类错误的序号为:36
分类错误的序号为:40
分类错误的序号为:81
分类错误的序号为:85
分类错误的序号为:92
分类错误的序号为:99
分类错误的序号为:115
分类错误的序号为:116
分类错误的序号为:126
分类错误的序号为:130
分类错误的序号为:166
分类错误的序号为:191
分类错误的个数为:14,分类正确的个数为:186
精确度为:93.00%
  • 对2和6进行分类:
迭代的轮数:100
分类错误的序号为:8
分类错误的序号为:11
分类错误的序号为:49
分类错误的序号为:73
分类错误的序号为:107
分类错误的序号为:149
分类错误的序号为:189
分类错误的序号为:190
分类错误的序号为:196
分类错误的个数为:9,分类正确的个数为:191
精确度为:95.50%

最后修改于 2022-04-05

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。