[我分享] 相关向量机 (Relevance Vector Machine, RVM)

  [复制链接]
阿濠 发表于 2020-5-7 16:33:34
本帖最后由 阿濠 于 2020-5-7 16:36 编辑

楼主您好,我又遇到了几个问题问您一下:lol
1、我使用的数据在粒子群优化的单核模型中能够达到预测效果,但使用优化的多核模型报错了,这是什么原因造成的呢?
错误如下:
  1. 错误使用 chol
  2. 矩阵必须为具有实数对角线的正定矩阵。

  3. 出错 SB2_FullStatistics (line 81)
  4.   U                = chol(PHI'*PHI*beta + diag(Alpha));

  5. 出错 SparseBayes (line 665)
  6.                   SB2_FullStatistics(LIKELIHOOD,BASIS,PHI,Targets,Used,Alpha,beta,...
复制代码
代码如下:
  1. A=xlsread('CS.xlsx','Sheet5');
  2. x=A(3:343,1:10);
  3. y=A(3:343,11);
  4. xt=A(344:492,1:10);
  5. yt=A(344:492,11);
复制代码
2、组合的核函数想使用这种形式K=aK(1)+(1-a)K(2)。怎么对核函数的权重进行约束呀?
3、代码中采用的内置的粒子群优化方法,我只看到了对lb,ub,numVariable,maxIter这些参数初始化,像种群规模,学习因子这些是默认数值了么?particleswarm太复杂了看不懂呀:(

阿濠 发表于 2020-5-7 16:38:21
本帖最后由 阿濠 于 2020-5-7 16:40 编辑

上面代码少了一段kernel_1 = Kernel('type', 'gauss', 'width', 2);
kernel_2 = Kernel('type','poly', 'degree', 2, 'offset', 0);
optimization = struct('method', 'pso',...
                      'target', {{kernel_1, kernel_2,'weight'}},...
                      'lb', [2^-5,  10^-2, 10^-3, 10^-3],...
                      'ub', [2^5, 10^0, 10^3, 10^3],...
                      'numVariable', 4,...
                      'maxIter', 100,...
                      'Kfolds', 5);


% parameter setting
parameter = struct( 'freeBasis', 'on',...
                    'display', 'on',...
                    'maxIter', 1000,...
                    'kernel', [kernel_1, kernel_2],...
                    'weight',[0.5,0.5],...
                    'optimization', optimization);
               
% RVM model training, testing, and visualization
rvm = RVM(parameter);
rvm.train(x, y);
rvm.test(xt, yt);
rvm.draw






iqiukp 发表于 2020-5-7 19:46:43
本帖最后由 iqiukp 于 2020-5-27 12:50 编辑
阿濠 发表于 2020-5-7 16:38
上面代码少了一段kernel_1 = Kernel('type', 'gauss', 'width', 2);
kernel_2 = Kernel('type','poly', 'de ...

你好。

1.  可能是因为某些数据的开方出现了虚数导致报错。
2. 如果要 K=aK (1)+(1-a) K (2) 这种形式,需要修改RVM.getModel 中核函数的计算方法。如:

  1. switch obj.model.kernelType
  2.     case 'single'
  3.         K = obj.parameter.weight*obj.parameter.kernel.getKernelMatrix(obj.model.x, obj.model.x);
  4.     case 'hybrid'
  5.         for i = 1:obj.model.numKernel
  6.             K = K+obj.parameter.weight(i)*obj.parameter.kernel(i).getKernelMatrix(obj.model.x, obj.model.x);
  7.         end
  8.             end
复制代码



如果你打算用两种核函数,那就简单地把case为'hybrid'的情况改为:
  1. K1 = obj.parameter.weight(1)*obj.parameter.kernel(1).getKernelMatrix(obj.model.x, obj.model.x);
  2. K2 = (1-obj.parameter.weight(1))*obj.parameter.kernel(2).getKernelMatrix(obj.model.x, obj.model.x);
  3. K = K1+K2;
复制代码
同样地把RVM.test中对应位置改为:
  1. K1 = obj.parameter.weight(1)*obj.parameter.kernel(1).getKernelMatrix(obj.prediction.xt, obj.model.relevanceVector);
  2. K2 = (1-obj.parameter.weight(1))*obj.parameter.kernel(2).getKernelMatrix(obj.prediction.xt, obj.model.relevanceVector);
  3. K = K1+K2;
复制代码


然后把RvmOptimization.setParameterValue中的权重传参改为:
  1. if strcmp(parameterType{1, i}, 'char')
  2.           rvm.parameter.weight = parameter(1, i);
  3. end
复制代码


最后在主函数中的参数设置为:
  1. optimization = struct('method', 'pso',...
  2.                       'target', {{kernel_1, kernel_2, 'weight'}},...
  3.                       'lb', [2^-5,  2^-5, 0],...
  4.                       'ub', [2^5, 2^5, 1],...
  5.                       'numVariable', 3,...
  6.                       'maxIter', 10,...
  7.                       'Kfolds', 5);
复制代码
第三个参数就是权重的范围0~1。需要优化的参数个数为3个。

总的来说需要改动的地方挺多的。

3.  MATLAB 内置的pso函数其他参数都是默认的,如果要修改,看帮助文档就行了,在变量options中添加对应的键值对。


阿濠 发表于 2020-5-7 19:52:09
iqiukp 发表于 2020-5-7 19:46
你好。

1.  可能是因为某些数据的开方出现了虚数导致报错。

哦哦哦,十分感谢楼主解答,我去改一改试试:lol

阿濠 发表于 2020-5-8 10:33:28
楼主。这个K折线交叉验证用在粒子群优化时的适应度函数值的计算这里,是有什么作用呀?采用的混合核函数竟然比单一核函数得到的预测效果还差

iqiukp 发表于 2020-5-8 11:15:52
阿濠 发表于 2020-5-8 10:33
楼主。这个K折线交叉验证用在粒子群优化时的适应度函数值的计算这里,是有什么作用呀?采用的混合核函数竟 ...

你好。K折交叉验证是防止过拟合。混合核函数目前应该没有理论证明一定比单核的好吧?所以出现“混合核函数比单一核函数得到的预测效果还差”这种情况挺正常的。

阿濠 发表于 2020-5-8 11:27:09
iqiukp 发表于 2020-5-8 11:15
你好。K折交叉验证是防止过拟合。混合核函数目前应该没有理论证明一定比单核的好吧?所以出现“混合核函 ...

原来是这样呀,看了一些论文里都是说单核存在缺陷,他们就都根据全局和局部核组合改进了一下,我就那么以为了。。。

王镇_zVnvQ 发表于 2020-5-26 18:30:57

RE: 相关向量机 (Relevance Vector Machine, RVM) 训练和预测的实现

红色预测结果,黑色为原始数据。
其中,预测与原始吻合较好的部分为训练阶段。红色预测结果突然上升且数值保持一致的部分为验证集。发现验证集无论怎么修改模型参数(核函数),他的值一致都是固定不变的,请问是什么原因?

红色预测结果,黑色为原始值

红色预测结果,黑色为原始值

iqiukp 发表于 2020-5-26 19:00:08
王镇_zVnvQ 发表于 2020-5-26 18:30
红色预测结果,黑色为原始数据。
其中,预测与原始吻合较好的部分为训练阶段。红色预测结果突然上升且数值 ...

你好。
(1)数据集
这个数据集是一个时间序列吗?如果是的话,直接使用 RVM 获取的结果可能不理想。69#的帖子和你的类似,我在 70#给出了这种问题的可能性分析以及一些解决方案,可以参考一下。如果不是的话,这个数据集的输入部分,特征维度是多少?
(2)训练集的预测效果
从训练集的情况来看,预测结果也不理想,而且验证值后面的值出现恒定不变的情况,建议检查一下验证集的数据是否正确。

王镇_zVnvQ 发表于 2020-5-26 19:06:33
iqiukp 发表于 2020-5-26 19:00
你好。
(1)数据集
这个数据集是一个时间序列吗?如果是的话,直接使用 RVM 获取的结果可能不理想。69# ...

数据集不是一个时间序列,训练集:输入为3500*3,输出为3500*1;验证集:输入为500*3,输出为500*1

王镇_zVnvQ 发表于 2020-5-26 19:15:13
王镇_zVnvQ 发表于 2020-5-26 19:06
数据集不是一个时间序列,训练集:输入为3500*3,输出为3500*1;验证集:输入为500*3,输出为500*1 ...

嗯呢,按照楼主的提示,解决了(预测阶段不是恒定值了),谢谢楼主

iqiukp 发表于 2020-5-26 19:26:14
王镇_zVnvQ 发表于 2020-5-26 19:06
数据集不是一个时间序列,训练集:输入为3500*3,输出为3500*1;验证集:输入为500*3,输出为500*1 ...

这个问题还是先从数据集本身去排除吧,从训练集的预测结果来看,模型本身应该没有过拟合(看看相关向量个数的占比),暂时没想到其他的原因了。

辣鸡小斐 发表于 2020-5-26 21:36:42
本帖最后由 辣鸡小斐 于 2020-5-26 21:54 编辑

楼主大大。你好,我想问下为什么我的混合函数权重一直是[1 1],以及weightkernel的代表含义

iqiukp 发表于 2020-5-26 22:17:41
辣鸡小斐 发表于 2020-5-26 21:36
楼主大大。你好,我想问下为什么我的混合函数权重一直是[1 1],以及weightkernel的代表含义 ...

你好。以下面这个代码为例:
  1. % kernel function (default: kernel = kernel_1+kernel_2)
  2. kernel_1 = Kernel('type', 'gauss', 'width', 2);
  3. kernel_2 = Kernel('type', 'sigm', 'gamma', 0.6, 'offset', 0);
  4. optimization = struct('method', 'pso',...
  5.                               'target', {{kernel_1, kernel_2, 'weight'}},...
  6.                               'lb', [2^-8, 10^-2, 10^-3, 10^-3],...
  7.                               'ub', [2^2, 10^0, 10^3, 10^3],...
  8.                               'numVariable', 4,...
  9.                               'maxIter', 10,...
  10.                               'Kfolds', 5);
  11. % parameter setting
  12. parameter = struct( 'freeBasis', 'off',...
  13.                              'display', 'on',...
  14.                              'maxIter', 1000,...
  15.                              'kernel', [kernel_1, kernel_2],...
  16.                              'optimization', optimization);
复制代码

1. 核函数定义


首先,定义了两个核函数对象:
  • kernel_1: 高斯核函数
  • kernel_2: 双曲正切核函数
然后,这两个核函数的混合形式为:

  • K = w1*K1+w2*K2
K1是高斯核矩阵,K2是双曲正切核矩阵,w1和w2分别是权重,默认是1,即:

  • K = K1+K2


2.  优化步骤

定义optimization结构体,其中键值对 'target' -  {{kernel_1, kernel_2, 'weight'}} 的含义是,优化的目标分别是第一个核函数的参数、第二个核函数的参数以及对应的权重,则优化的参数共有4个。如果仅仅优化混合核函数的参数,就把键值对设置为: 'target' -  {{kernel_1, kernel_2}},则优化的参数共有2个。


如果不需要优化,就简单用以下代码:
  1. % kernel function (default: kernel = kernel_1+kernel_2)
  2. kernel_1 = Kernel('type', 'gauss', 'width', 2);
  3. kernel_2 = Kernel('type', 'sigm', 'gamma', 0.6, 'offset', 0);

  4. % parameter setting
  5. parameter = struct( 'freeBasis', 'on',...
  6.                              'display', 'on',...
  7.                              'maxIter', 1000,...
  8.                              'kernel', [kernel_1, kernel_2],...
  9.                              'weight', [1, 1]);
复制代码


把键值对 'weight', [1, 1] 修改为想要的取值,比如: 'weight', [0.2, 0.8]


Gz琪 发表于 2020-5-27 17:59:35
楼主,我想问一下您的程序可以对未知数据进行预测吗,例如我有80个数据,之后的数据未知,可以用该程序预测80之后的数据变化趋势吗

Gz琪 发表于 2020-5-27 18:03:17
Gz琪 发表于 2020-5-27 17:59
楼主,我想问一下您的程序可以对未知数据进行预测吗,例如我有80个数据,之后的数据未知,可以用该程序预测 ...

例如图中这样的,由前80次数据预测后面的数据
捕获.PNG

iqiukp 发表于 2020-5-27 18:33:51
Gz琪 发表于 2020-5-27 18:03
例如图中这样的,由前80次数据预测后面的数据

你好。RVM的原理是建立自变量X和因变量Y的关系f, 即:Y = f(X)。像你图中展示的曲线,实际上可以看作时间序列数据,利用前面时刻的数据去估计未来时刻的数据。RVM不考虑时序,只考虑自变量和因变量数据的一一对应关系。时间序列的问题在于没有自变量,时间虽然是一个变量,但这个变量单调上升的一条固定斜率的直线,作为自变量的话没有意义。所以直接应用RVM来处理这类问题,效果可能不好,可能还得结合其他的数据处理方法。

Gz琪 发表于 2020-5-27 21:06:11
iqiukp 发表于 2020-5-27 18:33
你好。RVM的原理是建立自变量X和因变量Y的关系f, 即:Y = f(X)。像你图中展示的曲线,实际上可以看作时 ...

感谢楼主的回复   我还想问一下3σ区域在这里主要体现了什么作用

iqiukp 发表于 2020-5-27 22:12:59
Gz琪 发表于 2020-5-27 21:06
感谢楼主的回复   我还想问一下3σ区域在这里主要体现了什么作用

RVM的预测结果假设是一个高斯分布,即给出预测的均值与方差。3σ代表3σ准则,即预测值落在 ±3σ 以外的概率为 0.27%。

hemao2222 发表于 2020-6-16 16:46:10
iqiukp 发表于 2019-2-28 17:57
报错的原因:
1. 训练集中的相关向量数据点标记范围超过了样本个数,导致第一幅图的第三条曲线报错(即相 ...

楼主你好,辛苦了。我在用你的代码:demo_optimization_kernel时,代码报错如下:
错误使用 optimoptions (line 105)
'MaxIterations' is not an option for PARTICLESWARM.
A list of options can be found on the PARTICLESWARM documentation page.
当我点击documentation page时,代码显示如下信息:
MATLAB cannot link to this file or URL:

file:///D:/matlab2014b/help/optim/ug/particleswarm.html
。请问楼主这是什么原因造成的,我该怎么解决。再次谢谢你分享的代码

王镇_zVnvQ 发表于 2020-6-19 14:26:15
楼主,你好!
(1)你给的源程序里面用的是高斯核函数,但当我换成多项式核函时,我只在主函数里面将
% parameter setting 参数设置
kernel = Kernel('type', 'gauss', 'width', parameter);
option = struct('freeBasis', 'on','display', 'on');
替换为
% parameter setting 参数设置
kernel = Kernel('type', 'poly', 'degree', 2, 'offset', 1);%多项式核函数对象
option = struct('freeBasis','on','display','on');
结果一直出现这个警告
警告: 矩阵接近奇异值,或者缩放错误。结果可能不准确。RCOND =  2.208054e-20。
> In rvm_train at 93
(2)当我使用混合核函数(高斯+多项式)发现无论对两个核函数怎么赋予权重,结果都和多项式预测得到的结果一致?不知道是哪出问题啦,请楼主帮忙指导指导

iqiukp 发表于 2020-6-19 16:09:48
王镇_zVnvQ 发表于 2020-6-19 14:26
楼主,你好!
(1)你给的源程序里面用的是高斯核函数,但当我换成多项式核函时,我只在主函数里面将
% par ...

你好。
1. 矩阵接近奇异值这个问题,一方面是数据问题,导致矩阵求逆的时候出现问题;另一方面是MATLAB 内置算法的鲁棒性问题。可以参考一下下面的链接(去掉中文):ht去掉tp去掉s://blo去掉g.csd去掉n.net/lyx去掉left/article/det去掉ails/83去掉998去掉246

另外,这个只是warning,没有报错,可以执行完程序,看看模型训练的结果以及测试结果。如果出现预测值是一条直线,很可能是矩阵求逆结果出现了NaN。建议把建模数据预处理,包括异常值剔除、标准化/归一化。

2.  如果还是用的1里面的建模数据,那么还是得先解决1的问题。

王镇_zVnvQ 发表于 2020-6-19 18:09:21
iqiukp 发表于 2020-6-19 16:09
你好。
1. 矩阵接近奇异值这个问题,一方面是数据问题,导致矩阵求逆的时候出现问题;另一方面是MATLAB  ...

好的,我先对数据进行预处理,谢谢楼主

王镇_zVnvQ 发表于 2020-6-20 00:42:45
iqiukp 发表于 2020-4-28 03:12
2020.4.28更新(V2.0)

源代码

楼主,V2.0版本中,在参数优化(混合核函数的参数与权重)时,程序如下:
% kernel function (default: kernel = kernel_1+kernel_2)
kernel_1 = Kernel('type', 'gauss', 'width', 2);
kernel_2 = Kernel('type', 'sigm', 'gamma', 0.6, 'offset', 0);
optimization = struct('method', 'pso',...
                              'target', {{kernel_1, kernel_2, 'weight'}},...
                              'lb', [2^-8, 10^-2, 10^-3, 10^-3],...
                              'ub', [2^2, 10^0, 10^3, 10^3],...
                              'numVariable', 4,...
                              'maxIter', 10,...
                              'Kfolds', 5);
% parameter setting
parameter = struct( 'freeBasis', 'off',...
                             'display', 'on',...
                             'maxIter', 1000,...
                             'kernel', [kernel_1, kernel_2],...
                             'optimization', optimization);
程序对核函数和权重同时寻优,我想了解:
(1)对两个核函数的权重优化时,是分别进行赋值的,但这样的话没有保证两个权重相加等于1吧?如果只对其中一个权重a优化,另一个赋值为(1-a),主函数和子函数都需要怎么修改?
(2)优化算法寻优时,我想了解它的目标函数是什么?是训练误差均方根吗?

iqiukp 发表于 2020-6-20 01:04:52
王镇_zVnvQ 发表于 2020-6-20 00:42
楼主,V2.0版本中,在参数优化(混合核函数的参数与权重)时,程序如下:
% kernel function (default: k ...

你好。若要实现权重的和为1,参考一下127#的回帖。优化算法的目标函数是RMSE,即均方根误差:

Snipaste_2020-06-20_01-00-03.png



Snipaste_2020-06-20_01-01-29.png

您需要登录后才可以回帖 登录 | 注册

本版积分规则

热门教程
站长推荐
快速回复 返回顶部 返回列表