fmax优化 逻辑_实例:利用随机优化算法求解逻辑回归问题

本文通过实例展示了如何利用随机优化算法(如SGD, Momentum, Adagrad, RMSProp, AdaDelta 和 Adam)解决逻辑回归问题。在CINA和a9a数据集上,对比不同批量大小的实验结果,揭示了自适应步长对算法性能的提升,特别是Adam和Adagrad算法表现出快速的下降速度。" 50063379,1339966,ArrayList深度解析:从源码到原理,"['数据结构', 'java-基础', 'ArrayList']
摘要由CSDN通过智能技术生成

实例:利用随机优化算法求解逻辑回归问题

考虑逻辑回归问题

其中 为已知的待分类的数据集。

我们测试不同的随机算法(包括SGD, Momentum, Adagrad, RMSProp, AdaDelta 和 Adam),在 LIBSVM 网站上的 CINA 和 a9a 数据集对应的逻辑回归问题的表现。 取批量大小 (batchsize) 为 1 和 10 分别进行实验。

目录

测试主体

我们将固定数据集和批量大小的一个测试封装为一个函数 test, 并且在两个数据集和两个不同的批量大小下分别调用该函数,完成测试。clear;

alphalist 用于随机算法的步长格点搜索,当 gs>0 时进行格点搜索。 由于格点搜索的耗时较长,在这里我们省略了搜索的过程,直接以预先搜索得到的结果进行展示。alphalist = [1e-4:3e-4:1e-3, 1e-3:3e-3:1e-2, 1e-2:3e-2:0.1, 0.1:0.1:0.9, 1:1:10,20,40];

gs = 0;

test('CINA.test', 1, alphalist, gs);

test('CINA.test', 10, alphalist, gs);

test('a9a.test', 1, alphalist, gs);

test('a9a.test', 10, alphalist, gs);

格点搜索函数

该函数利用给定的 alphalist ,对给定的数据集、批量和随机算法进行步长的格点搜索。function [out] = grid_research(alphalist, batchsize, dataset, stoalg, lr_loss, pgfun)

设定随机种子。seed = 97006855;

ss = RandStream('mt19937ar','Seed',seed);

RandStream.setGlobalStream(ss);

利用预先编译的 libsvmread 函数读取数据集。[b,A] = libsvmread(dataset);

[N,m] = size(A);

令正则化系数为 。lambda = 1e-2/N;

随机选取迭代初始点,每个实验重复 5 遍,取其平均值。记录最优步长和相应的函数值。x0 = randn(m,1);

repnum = 5;

alpha_best = 0.1;

fvec_best = inf;

参数的设定。opts = struct();

opts.batchsize = batchsize;

opts.maxit = 15*N/opts.batchsize;

opts.alpha = 1e1;

opts.step_type = 'fixed';

fun = @(x)lr_loss(x,A,b,lambda);

设定不同的随机算法,通过将 stofun 赋为对应的算法的函数句柄调用对应的算法。if strcmp(stoalg,'sgd')

stofun = @sgd;

opts.momentum = 0;

elseif strcmp(stoalg, 'sgd_m')

stofun = @sgd;

opts.momentum = 1;

elseif strcmp(stoalg, 'AdaDelta')

stofun = @AdaDelta;

elseif strcmp(stoalg, 'Adagrad')

stofun = @Adagrad;

elseif strcmp(stoalg, 'Adam')

stofun = @Adam;

elseif strcmp(stoalg, 'RMSProp')

stofun = @RMSProp;

end

对 alphalist 中的步长进行格点搜索,找到最优步长。在每一个选定的步长下,重复若干次实验,取其平均值。for alpha = alphalist

opts.alpha = alpha;

for i = 1:repnum

调用相应的随机算法进行求解。 out.fvec 记录随机算法的目标函数值变化,这里对重复实验的目标函数值进行累加,并求其平均值。[~,out] = stofun(x0,N,@(x, ind)pgfun(x, ind, A, b, lambda),fun,opts);

if i == 1

fvec = out.fvec;

else

fvec = fvec + out.fvec;

end

end

fvec = fvec / repnum;

如果当前步长下,最后一步的目标函数值比历史最优值更小,则记录当前步长为最优步长, 并且记录此步长下的目标函数变化。格点搜索结束后,返回最优步长和此步长下的目标函数变化。if fvec(end) < fvec_best(end)

fvec_best = fvec;

alpha_best = alpha;

end

end

out.fvec = fvec_best;

out.alpha_best = alpha_best;

end

测试函数

测试函数完成对于六种随机算法在给定数据集和批量大小下的测试,按照给定的 alphalist 搜索最佳步长,并且对最佳步长下的优化过程予以可视化。

分别对六种随机算法,在给定的数据集和批量大小下测试,寻找最佳步长,并返回在最佳步长下的收敛结果。function test(dataset, batchsize, alphalist, gs)

if gs

out1 = grid_research(alphalist, batchsize, dataset, 'sgd', @lr_loss, @pgfun);

out2 = grid_research(alphalist, batchsize, dataset, 'sgd_m', @lr_loss, @pgfun);

out3 = grid_research(alphalist, batchsize, dataset, 'Adagrad', @lr_loss, @pgfun);

out4 = grid_research(alphalist, batchsize, dataset, 'RMSProp', @lr_loss, @pgfun);

out5 = grid_research(alphalist, batchsize, dataset, 'AdaDelta', @lr_loss, @pgfun); % AdaDelta不需要步长参数。

out6 = grid_research(alphalist, batchsize, dataset, 'Adam', @lr_loss, @pgfun);

% 依次输出六种随机算法的最佳步长。

fprintf('best alpha %.2e, %.2e, %.2e, %.2e, %.2e\n',out1.alpha_best,...

out2.alpha_best,out3.alpha_best,out4.alpha_best, out6.alpha_best);

这里我们直接给出经过线搜索得到的最佳步长,以节省时间,特别的由于 sgd 对于步长选取不稳定,这里选择惯用的 作为默认值。else

out1 = grid_research(1e-3, batchsize, dataset, 'sgd', @lr_loss, @pgfun);

out2 = grid_research(1e-3, batchsize, dataset, 'sgd_m', @lr_loss, @pgfun);

out3 = grid_research(0.4, batchsize, dataset, 'Adagrad', @lr_loss, @pgfun);

out4 = grid_research(1e-3, batchsize, dataset, 'RMSProp', @lr_loss, @pgfun);

out5 = grid_research(1e-3, batchsize, dataset, 'AdaDelta', @lr_loss, @pgfun); % AdaDelta不需要步长参数。

out6 = grid_research(5e-3, batchsize, dataset, 'Adam', @lr_loss, @pgfun);

end

结果可视化。fig = figure;

semilogy(out1.epoch, out1.fvec, '-*', 'Color',[0.99 0.1 0.99], 'LineWidth',1.2);

hold on

semilogy(out2.epoch, out2.fvec, '-.d', 'Color',[0.99 0.1 0.1], 'LineWidth',1.5);

hold on

semilogy(out3.epoch, out3.fvec, '--

hold on

semilogy(out4.epoch, out4.fvec, ':x', 'Color',[0.5 0.2 0.99], 'LineWidth',1.5);

hold on

semilogy(out5.epoch, out5.fvec, '-o', 'Color',[0.99 0.2 0.5], 'LineWidth',2);

hold on

semilogy(out6.epoch, out6.fvec, '-.s', 'Color',[0.1 0.99 0.1], 'LineWidth',1.8);

hold on

legend('SGD', 'Momentum','Adagrad', 'RMSProp', 'AdaDelta','Adam','fontsize', 14,'Location','northeast');

ylabel('函数值', 'fontsize', 14);

xlabel('时期');

name = sprintf('dataset: %s, batchsize: %d',dataset(1:end-5),batchsize);

title(name);

dir = sprintf('sg-lr-%s-batch-%d.eps', dataset(1:end-5), batchsize);

print(fig, '-depsc',dir);

end

辅助函数

逻辑回归问题的分量梯度,该函数利用 ind 表示一个批量选取的下标,并返回该批量对应的梯度。

function g = pgfun(x,ind, A, b, lambda)

bind = b(ind);

Aind = A(ind,:);

Ax = Aind*x;

expba = exp(- bind.*Ax);

g = Aind'*(bind./(1+expba) - bind)/length(ind) + 2*lambda*x;

end

优化问题的目标函数,在数据 , , 和当前点 处返回逻辑回归的目标函数值

和全部数据对应的梯度

function [f,g] = lr_loss(x,A,b,lambda)

[N,~] = size(A);

Ax = A*x;

Atran = A';

expba = exp(- b.*Ax);

f = sum(log(1 + expba))/N + lambda*norm(x,2)^2;

if nargout > 1

g = Atran*(b./(1+expba) - b)/N + 2*lambda*x;

end

end

结果分析

在上面的四个折线图中,我们展示了在两个数据集和两种不同的批量大小下,各种随机算法的收敛性。 注意到对于随机梯度法(SGD),由于当步长过大时算法表现不够稳定,因此我们直接采用了惯用的 的学习率,而其他算法我们则利用格点搜索搜索到了较为合适的步长。

在选取的特定步长下,这些基于一般的 SGD 而改进的算法得到了更快的下降速度。其中,Adam 和 Adagrad 算法的下降速度最快,并在迭代初期就有非常快的下降速度,这说明自适应步长对于 SGD 性能有着较为明显的提升。同时带动量的 SGD、 RMSProp、 AdaDelta 也都有不错的表现。

同时,也注意到这些随机算法均不是单调算法。

参考页面

在本页面中使用的六个随机算法,参考: 随机梯度下降法 (包括带动量的sgd)、 AdaGrad、 RMSProp、 AdaDelta、 Adam。

我们在此页面中使用了 LIBSVM 数据集,关于数据集,请参考 LIBSVM 数据集。

版权声明

此页面为《最优化:建模、算法与理论》、《最优化计算方法》配套代码。 代码作者:文再文、刘浩洋、户将,代码整理与页面制作:杨昊桐。

著作权所有 (C) 2020 文再文、刘浩洋、户将

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值