1. 半监督与无监督极限学习机(SS-US-ELM)概述
极限学习机(Extreme Learning Machine, ELM)作为一种新兴的单隐层前馈神经网络算法,近年来在机器学习领域获得了广泛关注。与传统神经网络相比,ELM最大的特点在于其隐层节点的参数可以随机生成且无需调整,只需通过解析计算确定输出权重,这使得ELM具有极快的训练速度。而半监督和无监督极限学习机(SS-US-ELM)则进一步扩展了ELM的应用场景,使其能够处理标记数据稀缺或完全缺失的情况。
在实际工程应用中,我们经常会遇到这样的困境:获取大量标记数据成本高昂,而未标记数据却相对容易获得。例如在医学图像分析领域,专业医生标注一张CT扫描图像可能需要数小时,而医院每天产生的未标注扫描图像却数以千计。SS-US-ELM正是为解决这类问题而生,它能够充分利用少量标记数据和大量未标记数据(半监督场景),甚至完全不依赖任何标记数据(无监督场景)来构建有效的学习模型。
提示:ELM与传统神经网络的关键区别在于其随机隐层节点和解析解特性,这使得它特别适合需要快速建模的场景,如实时系统和嵌入式应用。
2. SS-US-ELM的核心算法原理
2.1 极限学习机基础架构
标准ELM的网络结构包含三层:输入层、隐层和输出层。给定N个训练样本{(x_i, t_i)} (i=1,...,N),其中x_i∈R^n是输入向量,t_i∈R^m是目标输出。具有L个隐层节点的ELM模型可以表示为:
f_L(x) = Σ_{i=1}^L β_i h_i(x) = h(x)β
其中h(x)=[h_1(x),...,h_L(x)]是隐层输出向量,β=[β_1,...,β_L]^T是输出权重。h_i(x)通常采用激活函数g(a_i,b_i,x)=g(a_i·x+b_i),其中a_i和b_i是随机生成的输入权重和偏置。
2.2 半监督ELM(SS-ELM)实现机制
半监督ELM通过将流形正则化引入目标函数,充分利用未标记数据的内在几何结构。其优化目标可表示为:
min ||Hβ-T||^2 + λ_1||β||^2 + λ_2 tr(β^T H^T LHβ)
其中H是隐层输出矩阵,T是标记数据的目标矩阵,L是图拉普拉斯矩阵,λ_1和λ_2是正则化参数。第三项即为流形正则化项,它强制相似样本(基于未标记数据构建的邻域图)在隐层空间具有相似表示。
在实际实现中,构建邻域图是关键步骤。常见方法包括:
- k近邻图:每个样本与最近的k个样本相连
- ε-邻域图:距离小于ε的样本相连
- 全连接图:所有样本互连,边权重随距离衰减
2.3 无监督ELM(US-ELM)实现机制
无监督ELM将ELM与谱聚类思想结合,其目标函数为:
min tr(β^T H^T LHβ) s.t. β^T H^T Hβ = I_m
该优化问题可通过求解广义特征值问题H^T LHv = λH^T Hv得到解。US-ELM的输出权重β由对应于最小m个特征值的特征向量组成。
注意:US-ELM的性能高度依赖于图拉普拉斯矩阵L的构建质量。实践中建议尝试多种相似度度量(如高斯核、余弦相似度等)并选择最优方案。
3. Matlab实现详解
3.1 基础ELM实现代码
matlab复制function [beta, trainTime] = elm_train(X, T, L)
% X: 输入数据 (N×n)
% T: 目标输出 (N×m)
% L: 隐层节点数
[N, n] = size(X);
m = size(T, 2);
% 随机生成输入权重和偏置
a = randn(n, L);
b = rand(1, L);
% 计算隐层输出矩阵H
H = 1 ./ (1 + exp(-X * a + repmat(b, N, 1)));
% 计算输出权重beta
tic;
beta = pinv(H) * T;
trainTime = toc;
end
3.2 SS-ELM的Matlab实现关键步骤
matlab复制function [beta, trainTime] = sselm_train(X_l, T_l, X_u, L, k, lambda1, lambda2)
% X_l: 标记数据 (N_l×n)
% T_l: 标记目标 (N_l×m)
% X_u: 未标记数据 (N_u×n)
% k: 近邻数
X = [X_l; X_u];
N = size(X, 1);
N_l = size(X_l, 1);
% 构建图拉普拉斯矩阵L
D = pdist2(X, X);
W = zeros(N, N);
for i = 1:N
[~, idx] = sort(D(i,:));
W(i, idx(2:k+1)) = 1;
W(idx(2:k+1), i) = 1;
end
D_mat = diag(sum(W, 2));
L = D_mat - W;
% 随机生成隐层参数
a = randn(size(X,2), L);
b = rand(1, L);
% 计算隐层输出H
H = 1 ./ (1 + exp(-X * a + repmat(b, N, 1)));
% 构建目标矩阵T
T = zeros(N, size(T_l, 2));
T(1:N_l, :) = T_l;
% 计算输出权重beta
tic;
I = eye(L);
H_l = H(1:N_l, :);
beta = (H_l' * H_l + lambda1 * I + lambda2 * H' * L * H) \ (H_l' * T_l);
trainTime = toc;
end
3.3 US-ELM的Matlab实现关键步骤
matlab复制function [beta, trainTime] = uselm_train(X, L, k, m)
% m: 降维维度
N = size(X, 1);
% 构建图拉普拉斯矩阵
D = pdist2(X, X);
W = zeros(N, N);
for i = 1:N
[~, idx] = sort(D(i,:));
W(i, idx(2:k+1)) = exp(-D(i,idx(2:k+1)).^2 / (2 * mean(D(i,idx(2:k+1)))^2));
end
W = max(W, W'); % 确保对称
D_mat = diag(sum(W, 2));
L = D_mat - W;
% 随机生成隐层参数
a = randn(size(X,2), L);
b = rand(1, L);
% 计算隐层输出H
H = 1 ./ (1 + exp(-X * a + repmat(b, N, 1)));
% 求解广义特征值问题
tic;
A = H' * L * H;
B = H' * H;
[V, ~] = eigs(A, B, m, 'sm');
beta = V;
trainTime = toc;
end
4. 实战应用与调优技巧
4.1 参数选择经验
-
隐层节点数L:通常选择在100-1000之间。可以通过交叉验证确定最优值,但实践中发现L=500在大多数情况下表现良好。
-
近邻数k:对于SS-ELM和US-ELM中的图构建,k值过小会导致图不连通,过大则会模糊局部结构。建议从k=5开始尝试,逐步增加至k=15。
-
正则化参数:
- λ1(L2正则化):常用范围1e-6到1e-3
- λ2(流形正则化):常用范围1到100
-
激活函数选择:除了示例中的sigmoid函数,还可以尝试:
matlab复制% ReLU H = max(0, X * a + repmat(b, N, 1)); % 径向基函数 H = exp(-gamma * pdist2(X, a').^2);
4.2 性能优化技巧
-
大规模数据处理:
- 对于样本数超过10,000的数据集,直接计算图拉普拉斯矩阵可能内存不足。可以采用以下策略:
matlab复制% 分块计算距离矩阵 blockSize = 2000; W = sparse(N, N); for i = 1:blockSize:N blockEnd = min(i+blockSize-1, N); D_block = pdist2(X(i:blockEnd,:), X); [~, idx] = sort(D_block, 2); for j = 1:size(D_block,1) W(i+j-1, idx(j,2:k+1)) = 1; end end -
并行计算加速:
matlab复制parfor i = 1:N [~, idx] = sort(D(i,:)); W(i, idx(2:k+1)) = 1; end -
提前终止策略:当隐层节点数很大时(如L>2000),可以监控验证集性能,在性能不再提升时提前终止训练。
4.3 常见问题排查
-
矩阵奇异问题:
- 症状:计算伪逆(pinv)或求解线性方程组时出现警告或错误
- 解决方案:
- 增加λ1正则化参数
- 检查输入数据是否有常数特征(方差为零)
- 尝试使用更稳定的求解器:
beta = linsolve(H'*H + lambda*eye(L), H'*T)
-
性能不稳定:
- 由于ELM的隐层参数随机生成,不同运行结果可能有差异
- 解决方案:
- 固定随机种子:
rng(42) - 多次运行取平均
- 增加隐层节点数L
- 固定随机种子:
-
内存不足:
- 主要发生在构建大图拉普拉斯矩阵时
- 解决方案:
- 使用稀疏矩阵:
W = sparse(N, N) - 采用Nystrom近似等降维技术
- 使用稀疏矩阵:
5. 应用案例:手写数字识别
5.1 数据集准备
使用MNIST手写数字数据集,模拟半监督场景:
matlab复制load('mnist.mat'); % 假设已加载数据
% 随机选择少量标记样本
labeledIdx = randperm(60000, 1000);
X_l = train_X(labeledIdx, :);
T_l = train_labels(labeledIdx, :);
X_u = train_X(setdiff(1:60000, labeledIdx), :);
testX = test_X;
testT = test_labels;
5.2 SS-ELM模型训练与评估
matlab复制L = 800; % 隐层节点数
k = 10; % 近邻数
lambda1 = 1e-4; % L2正则化参数
lambda2 = 10; % 流形正则化参数
[beta, time] = sselm_train(X_l, T_l, X_u, L, k, lambda1, lambda2);
% 计算隐层输出
a = randn(size(X_l,2), L);
b = rand(1, L);
H_test = 1 ./ (1 + exp(-testX * a + repmat(b, size(testX,1), 1)));
% 预测
pred = H_test * beta;
[~, predLabels] = max(pred, [], 2);
accuracy = sum(predLabels == testT) / length(testT);
fprintf('SS-ELM准确率: %.2f%%, 训练时间: %.2fs\n', accuracy*100, time);
5.3 US-ELM特征提取与可视化
matlab复制m = 2; % 降维到2维用于可视化
[beta, time] = uselm_train(train_X, 1000, 15, m);
% 提取特征
a = randn(size(train_X,2), 1000);
b = rand(1, 1000);
H = 1 ./ (1 + exp(-train_X * a + repmat(b, size(train_X,1), 1)));
features = H * beta;
% 可视化
scatter(features(:,1), features(:,2), 10, train_labels, 'filled');
colorbar;
title('US-ELM特征可视化');
6. 扩展与进阶方向
6.1 深度ELM架构
将多个ELM堆叠形成深度网络:
matlab复制function [betas, Hs] = deep_elm_train(X, T, Ls)
% Ls: 各层隐层节点数,如[500,300,100]
betas = cell(1, length(Ls));
Hs = cell(1, length(Ls)+1);
Hs{1} = X;
for l = 1:length(Ls)
[N, ~] = size(Hs{l});
a = randn(size(Hs{l},2), Ls(l));
b = rand(1, Ls(l));
Hs{l+1} = 1 ./ (1 + exp(-Hs{l} * a + repmat(b, N, 1)));
if l < length(Ls)
% 中间层使用无监督ELM
[beta, ~] = uselm_train(Hs{l+1}, 500, 10, Ls(l+1));
else
% 最后一层使用监督ELM
beta = pinv(Hs{l+1}) * T;
end
betas{l} = beta;
end
end
6.2 在线学习ELM
适用于数据流场景的增量式ELM:
matlab复制function [beta, H] = online_elm_update(beta_old, H_old, X_new, T_new, L)
% 增量更新输出权重
% 计算新样本的隐层输出
a = randn(size(X_new,2), L);
b = rand(1, L);
H_new = 1 ./ (1 + exp(-X_new * a + repmat(b, size(X_new,1), 1)));
% 合并隐层输出
H = [H_old; H_new];
% 递归更新输出权重
if isempty(beta_old)
beta = pinv(H) * T_new;
else
K = H_old' * H_old;
M = K + H_new' * H_new;
beta = beta_old + pinv(M) * H_new' * (T_new - H_new * beta_old);
end
end
6.3 多核ELM
结合多种核函数提升性能:
matlab复制function [beta, trainTime] = multi_kernel_elm(X, T, L, kernels)
% kernels: 核函数元胞数组,如{'gaussian','poly','wavelet'}
N = size(X, 1);
H = zeros(N, L*length(kernels));
% 为每种核函数生成隐层节点
for k = 1:length(kernels)
a = randn(size(X,2), L);
b = rand(1, L);
switch kernels{k}
case 'gaussian'
H_block = exp(-pdist2(X, a').^2 ./ (2 * mean(b)^2));
case 'poly'
H_block = (X * a' + repmat(b, N, 1)).^2;
case 'wavelet'
H_block = cos(1.75 * (X * a' + repmat(b, N, 1))) ...
.* exp(-(X * a').^2 / 2);
end
H(:, (k-1)*L+1:k*L) = H_block;
end
% 计算输出权重
tic;
beta = pinv(H) * T;
trainTime = toc;
end
我在实际项目中应用SS-US-ELM时发现,对于高维稀疏数据(如文本),先进行随机投影降维再应用ELM通常能获得更好的效果。此外,当标记数据极少时(如少于10个/类),适当减小流形正则化权重λ2可以防止模型过度依赖未标记数据的结构信息。
