罗兰谈MATLAB的艺术

将想法转化为MATLAB

请注意

罗兰谈MATLAB的艺术已存档,不会更新。

子集选择和正则化

本周,来自技术营销部门的Richard Willey将发表关于子集选择和正则化的客座博客。本周的博客文章的动机是在应用曲线拟合中出现的一对常见挑战。

  • 第一个挑战是,当自变量表现出很强的相关性时,如何最好地创建准确的预测模型。在许多情况下,如果减少预测因子的数量,或者将系数值缩小到零,就可以改进普通最小二乘回归的结果。
  • 第二个挑战涉及到当你受到所使用的预测器数量的限制时,生成一个准确的预测模型。例如,假设您需要将模型嵌入到控制器上。你有20个可能的预测因子可供选择,但你的内存只允许8个自变量。

这篇博文将展示两套不同的技术来解决这些相关的挑战。第一组技术是基于特征选择和交叉验证的结合。第二套技术是使用正则化算法,如岭回归,套索和弹性网。所有这些算法都可以在统计工具箱

内容

创建数据集

首先,我要生成一个数据集,这个数据集是故意设计的,很难用传统的线性回归来拟合。数据集有三个特征,这些特征对线性回归提出了挑战

  1. 数据集非常“广泛”。与观测数量相比,(可能的)预测因子数量相对较大。
  2. 这些预测因素彼此之间有很强的相关性
  3. 数据集中有大量的噪声
清晰的所有clc rng (1998);

创建八X变量。每个变量的均值都等于0。

Mu = [0 0 0 0 0 0 0 0 0];

这些变量是相互关联的。协方差矩阵指定为

I = 1:8;矩阵= abs(bsxfun(@minus,i',i));协方差= repmat(.5,8,8).^矩阵;

使用这些参数生成一组多元正态随机数。

X = mvnrnd(mu,协方差,20);

创建用于描述Y = f(X)再加上一个噪声向量。请注意,八个预测因子中只有三个具有系数值> 0。这意味着八个预测因子中有五个对实际模型的影响为零。

Beta = [3;1.5;0;0;2;0;0;0);ds =数据集(测试版);Y = X * Beta + 3 * randn(20,1);

对于那些感兴趣的人,这个例子是由罗伯特引起的Tibshirani 1996年关于套索的经典论文

Tibshirani, R.(1996)。通过套索回归收缩和选择。j .皇家。中央集权。Soc B., Vol. 58, No. 1, page 267-288)。

我们的模型Y = f(X)使用普通最小二乘回归。我们将首先使用传统的线性回归来建模Y = f(X)并将回归模型估计的系数与已知向量进行比较β

b =回归(Y,X);ds。Linear = b;disp (ds)
Beta线性3 3.5819 1.5 0.44611 0 0.92272 0 -0.84134 2 4.7091 0 -2.5195 0 0.17123 0 -0.42067

正如预期的那样,回归模型的表现非常糟糕。

  • 回归是对所有八个预测因子的系数值的估计。客观地说,我们“知道”这些系数中有五个应该是零。
  • 此外,所估计的系数与真实值相差甚远。

让我们看看是否可以使用一种叫做“所有可能子集回归”的技术来改善这些结果。首先,我将生成255个不同的回归模型,其中包含八个预测因子的每个可能组合。接下来,我将使用交叉验证的均方误差来测量结果回归的准确性。最后,我将选择产生最准确结果的回归模型,并将其与我们原始的回归模型进行比较。

为回归子集创建索引。

索引= dec2bin(1:255);索引=索引=' 1 ';结果= double(index);结果(:,9)= 0(长度(结果),1);

生成回归模型。

I = 1:length(index) foo = index(I,:);rng (1981);regf = @(XTRAIN, YTRAIN, XTEST)(XTEST* return (YTRAIN,XTRAIN));结果(i,9) = crossval(mse的, X(:,foo), Y,“kfold”5,“predfun”, regf);结束

按MSE对输出进行排序。我先给你们看几个。

索引= sortrows(结果,9);指数(1:10,:)
ans = 1到5列1 1 0 0 1 1 1 0 1 1 1 0 1 0 1 1 1 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 0 1 1 1 0 0 0 1 1 0 1 0 1 1 0 0 1 1列6至9年1 0 0 10.239 10.533 1 0 0 1 0 0 0 0 0 10.615 10.976 1 0 0 0 0 0 11.062 11.257 11.938 11.641 1 0 0 0 0 0 0 0 0 0 0 0 12.068 12.249

比较结果

beta =回归(Y, X(:,逻辑(索引(1,1:8))));子集= 0 (8,1);ds。子集=子集;d . sub (logical(index(1,1:8))) = beta;disp (ds)
Beta线性子集3 3.5819 3.4274 1.5 0.44611 1.1328 0 0.92272 00 -0.84134 0 2 4.7091 4.1048 0 -2.5195 -2.0063 0 0.17123 00 -0.42067 0

结果相当惊人。

  • 我们的新模型只包含4个预测因子。变量3,4,7,8已从回归模型中剔除。此外,被排除在外的变量是我们“知道”应该归零的变量。
  • 同样重要的是,从结果回归模型估计出来的系数更接近“真实”值。

所有可能的子集回归似乎生成了一个明显更好的模型。这R ^ 2这个回归模型的值不如原来的线性回归;然而,如果我们试图从一个新的数据集中产生预测,我们希望这个模型表现得更好。

进行模拟

依赖单一的观察结果总是很危险的。如果我们改变我们用来生成原始数据集的噪声向量中的任何一个,我们可能会得到完全不同的结果。下一段代码将重复我们最初的实验100次,每次添加不同的噪声向量。我们的输出将是一个柱状图,显示每个不同变量在结果模型中被包含的频率。我使用并行计算来加快速度,尽管你可以在串行中执行这个(更慢)。

matlabpool开放Sumin = 0 (1,8);parforJ =1:100亩= [0 00 00 00 0];Beta = [3;1.5;0;0;2;0;0;0);I = 1:8; matrix = abs(bsxfun(@minus,i',i)); covariance = repmat(.5,8,8).^matrix; X = mvnrnd(mu, covariance, 20); Y = X * Beta + 3 * randn(size(X,1),1); index = dec2bin(1:255); index = index ==' 1 ';结果= double(index);结果(:,9)= 0(长度(结果),1);K = 1:length(index) foo = index(K,:);regf = @(XTRAIN, YTRAIN, XTEST)(XTEST* return (YTRAIN,XTRAIN));结果(k,9) = crossval(mse的, X(:,foo), Y,“kfold”5,“predfun”, regf);结束%按MSE对输出进行排序索引= sortrows(结果,9);Sumin = Sumin +指数(1,1:8);结束% parformatlabpool关闭
使用local4配置启动matlabpool…连接3个实验室。向所有实验室发出停止信号…停止了。
%的阴谋的结果。栏(sumin)

结果清楚地表明,“所有可能的子集选择”在识别驱动我们模型的关键变量方面做得非常好。变量1、2和5出现在大多数模型中。个别干扰因素也会影响模型,然而,它们的频率远不如真正的预测因素高。

介绍顺序特征选择

所有可能的子集选择都有一个巨大的局限性。将这种技术应用于包含大量(潜在)预测因子的数据集在计算上是不可行的。第一个例子有八个可能的预测因子。测试所有可能的子集需要生成(2^8)-1 = 255个不同的模型。假设我们正在评估一个有20个可能预测因素的模型。所有可能的子集都需要用于测试1,048,575个不同的模型。有了40个预测因子,我们就能看到10亿种不同的组合。

序列特征选择是一种更现代的方法,它试图在搜索空间中定义一条智能路径。反过来,这应该允许我们确定一组良好的系数,但确保问题在计算上仍然可行。

序列特征选择工作如下:

  • 从每次测试一个可能的预测器开始。确定产生最准确模型的单个预测器。这个预测器会自动添加到模型中。
  • 接下来,一次一个,将每个剩余的预测因子添加到一个包含单个最佳变量的模型中。确定最能提高模型准确性的变量。
  • 检验两个模型的统计显著性。如果新模型没有明显比原始模型更准确,则停止该过程。然而,如果新模型在统计上更显著,那么就去寻找第三个最佳变量。
  • 重复这个过程,直到您无法确定一个对模型有统计上显著影响的新变量。
下一段代码将向您展示如何使用顺序特性%的选择来解决一个明显更大的问题。

生成数据集

清晰的所有clc rng (1981);Z12 = randn(100,40);Z1 = randn(100,1);X = Z12 + repmat(Z1, 1,40);B0 = 0 (10,1);B1 = ones(10,1);Beta = 2 * vertcat(B0,B1,B0,B1);ds =数据集(测试版);Y = X * Beta + 15*randn(100,1);

用线性回归来拟合模型。

b =回归(Y,X);ds。Linear = b;

使用序列特征选择来拟合模型。

Opts = statset(“显示”“通路”);Fun = @(x0,y0,x1,y1)范数(y1-x1*(x0\y0))^2;%残差平方和[in,history] = sequentialfs(fun,X,Y,“简历”5,“选项”选择)
开始前向顺序特性选择:包含的初始列:无不能包含的列:步骤1,增加列26,判据值868.909步骤2,增加列31,判据值566.166步骤3,增加列9,判据值425.096步骤4,增加列35,判据值369.597步骤5,增加列16,判据值314.445步骤6,增加列5,判据值283.324步骤7,增加列18,判据值269.421步骤8,增加列15,判据值253.78步骤9,增加列40,判据值242.04步骤10,增加列27,步骤11,增加列12,准则值223.271步骤12,增加列17,准则值216.464步骤13,增加列14,准则值212.635步骤14,增加列22,准则值207.885步骤15,增加列7,准则值205.253步骤16,增加列33,准则值204.179最终列包括:5 7 9 12 14 15 16 17 18 22日26日27日31日33 35 40 =列1到12 0 0 0 0 1 0 1 0 1 0 0 1列13到24 0 1 1 1 1 1 0 0 0 1 0 0列25到36 0 1 1 0 0 0 1 0 1 0 1 0列通过40 0 0 0 1历史= 37:[16 x40逻辑]暴击:[1乘16双]

我已经配置了sequentialfs以显示每次迭代的特征选择过程。您可以看到添加到模型中的每个变量,以及交叉验证的均方误差的变化。

使用最优特征集生成线性回归

beta =回归(Y,X(:,in));ds。顺序= 0(长度(ds),1);ds.Sequential(in) = beta
ds =β线性顺序0 -0.74167 -0.66373 0 0 0 0 0 0 0 0 0 1.6493 -1.7087 2.5441 1.3721 1.2025 -3.5482 0 0 -1.6411 -1.1617 0 0 0 4.1643 1.7454 - 2.9983 2.9544 0.28763 -1.9067 0 2 0 2 2 0 2 2.2226 - 3.5806 4.4912 - 4.0527 0.1005 4.7129 - 5.3879 3.9699 0.9606 5.9834 - 5.1789 1.9982 - 2 2 0 2 0 0 2.861 0 0 0.94454 -0.51398 1.8677 -1.6324 -2.1236 - -2.4748 0 0 0 0 0 0 0 1.4756 -0.98227 3.6856 - 4.0398 -3.3103 - -4.1396 0 0 0 0 0 0.026193 0 2 0.8035 2.3509 - 1.9472 2.9373 0.63056 3.8792 - 2 0 2 2 0 22.9242 4.35 2 0.4794 0 2 -0.6632 0 2 0.6066 0 2 -0.70758 0 2 4.4814 3.8164

如你所见,sequentialfs生成了一个比普通最小二乘回归更简洁的模型。我们还有一个模型,可以产生更准确的预测。此外,如果我们需要(假设地)提取五个最重要的变量,我们可以简单地从步骤1:5中获取输出。

运行模拟

作为最后一步,我们将再次运行模拟来对该技术进行基准测试。这里,再一次,我们可以看到特征选择技术在识别真正的预测因素时做得很好,同时筛选出干扰因素。

matlabpool开放Sumin = 0;parforj=1:100 Z12 = randn(100,40);Z1 = randn(100,1);X = Z12 + repmat(Z1, 1,40);B0 = 0 (10,1);B1 = ones(10,1);Beta = 2 * vertcat(B0,B1,B0,B1);Y = X * Beta + 15*randn(100,1);Fun = @(x0,y0,x1,y1)范数(y1-x1*(x0\y0))^2;%残差平方和[in,history] = sequentialfs(fun,X,Y,“简历”5);Sumin = in + Sumin;结束栏(sumin) matlabpool关闭
使用local4配置启动matlabpool…连接3个实验室。向所有实验室发出停止信号…停止了。

最后一个评论:正如你所看到的,两者都不是sequentialfs并不是所有可能的子集选择都是完美的。这两种技术都不能在排除干扰因素的同时捕捉到所有的真实变量。重要的是要认识到这些数据集是故意设计成难以拟合的。[我们不想使用任何旧技术都可能成功的“简单”问题来衡量性能。]

下周的博客文章将关注一种完全不同的方法来解决这些相同类型的问题。请继续关注正则化技术,如脊回归,套索和弹性网。

这里有几个你可能需要考虑的问题:#所有可能的子集方法都是O(2^n)。序列特征选择的复杂度顺序是什么?#除了缩放问题,你还能想到序列特征选择的其他可能问题吗?是否存在算法可能遗漏重要变量的情况?




使用MATLAB®7.13发布


评论

如欲留言,请点击在这里登录您的MathWorks帐户或创建一个新帐户。

Baidu
map