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

  [复制链接]
iqiukp 发表于 2020-4-19 13:16:03
qqaaq134679 发表于 2020-4-19 13:06
您好楼主,我是在做一个评价系统,数据是这个[80 100 80 80 80 60 100 80 60 100],想让这十项分数通过rvm ...

你好。RVM的输入x和输出y是一一对应的,即个数一致。不太明白你所说的“十项分数通过 rvm 得出一个综合的分数”是什么意思,感觉不太适合用RVM算法。RVM的应用一般是分类和回归。

qqaaq134679 发表于 2020-4-19 14:32:15
iqiukp 发表于 2020-4-19 13:16
你好。RVM的输入x和输出y是一一对应的,即个数一致。不太明白你所说的“十项分数通过 rvm 得出一个综合的 ...

楼主抱歉,可能是我表达的不太准确。我是参考这篇文章的,第四部分的实例分析里就是得到了一个评价结果,如果按照这篇文章里的数据集的话,x和y应该如何编写?

基于RVM的汽车服务商维修服务质量评价方法.pdf

804.3 KB, 下载次数: 9


iqiukp 发表于 2020-4-19 17:04:11
qqaaq134679 发表于 2020-4-19 14:32
楼主抱歉,可能是我表达的不太准确。我是参考这篇文章的,第四部分的实例分析里就是得到了一个评价结果, ...

你好。看这部分的实验数据: 文献截图.png

只要保证输入X的行方向为样本个数,列方向为特征个数就行。Y就是对应的得分,是一个一维向量。

涉远飞高 发表于 2020-4-19 18:32:03
iqiukp 发表于 2020-4-18 19:27
你好。

1.  在RVM中,对于每个训练样本,都有一个对应的权重w,而这个权重w是假设服从0均值,α ^-1的高 ...

感谢楼主的答疑

涉远飞高 发表于 2020-4-19 18:34:55
iqiukp 发表于 2020-4-18 19:27
你好。

1.  在RVM中,对于每个训练样本,都有一个对应的权重w,而这个权重w是假设服从0均值,α ^-1的高 ...

请问楼主是否有已经发表的研究论文,想进行借鉴和学习。

此外,在撰写文章时进行引用。

iqiukp 发表于 2020-4-19 23:26:12
涉远飞高 发表于 2020-4-19 18:34
请问楼主是否有已经发表的研究论文,想进行借鉴和学习。

此外,在撰写文章时进行引用。 ...

才疏学浅,略懂皮毛:lol

涉远飞高 发表于 2020-4-22 10:50:25
楼主好,在使用RVM的过程中发现了这么一个问题。

以楼主1.3工具包中提供的初始案例为例,使用Gauss核参数,那么需要调整width参数。

当width取得越小,Figure 1中的相关向量就越多,同时训练集的精度也就越高,反之测试集的精度也就越低。比如取width为0.011,训练的精度为:training CD    =  0.9869,测试为predicted CD   =  0.1269。

存在这么一个问题,机器学习中通常是利用训练集训练模型,以训练集的精度为模型优化过程中检验模型的标准。此时,在RVM模型中,当width取得很小时可以获得很好的训练集精度,按照以上理论,这就是最好的预测模型。然后拿预测集一算,结果很差很差,明显不符合要求。

求教楼主,对于这种现象,有什么好对策或者能解释一下这种现象么?

iqiukp 发表于 2020-4-22 11:42:01
涉远飞高 发表于 2020-4-22 10:50
楼主好,在使用RVM的过程中发现了这么一个问题。

以楼主1.3工具包中提供的初始案例为例,使用Gauss核参数 ...

你好。
1. 实验结果的解释

从相关向量的占比来看(demo中width的值取0.011时,占比通常达90%以上),这是一种过拟合现象,泛化性能差,即训练集的预测精度很高,测试集的预测精度很低。事实上这种情况应该尽量避免的,在回归任务中,训练集的精度不是主要核心目标,泛化性能才是需要更多注意的地方。


2. 解决方法
在rvm-1.3里面的模型构建过程中使用了所有训练样本,模型评价时也是使用了所有训练样本。实际上可以把训练集拆分为训练集+验证集,通过评价验证集的预测精度去反映模型精度。通常的模型评估方法有:"留出法"(hold-out)、交叉验证法(k折法、“留一法”)、和自助法等等。



涉远飞高 发表于 2020-4-22 15:26:40
iqiukp 发表于 2020-4-22 11:42
你好。
1. 实验结果的解释

感谢楼主。

我将尝试把k折法运用到程序里。:handshake:handshake:handshake

阿濠 发表于 2020-4-25 16:32:14
楼主您好,刚学习相关向量机,有问题想请教一下,看楼上您说的多核相关向量机的修改方法,按要求修改成高斯与多项式混合的核函数。最后提供的demo里为何相关向量只有一个,预测值是一条平滑曲线呢?这是什么问题呀
rvm_train中:
  1. % compute the kernel matrix
  2.     kernel_poly=Kernel('type','poly','degree',2,'offset',0);
  3.     K_poly=kernel_poly.getKernelMatrix(x,x);
  4.    
  5.     kernel_gaussian=Kernel('type','gauss','width',0.5);
  6.     K_gaussian=kernel_gaussian.getKernelMatrix(x,x);
  7.    
  8.     K=K_poly+K_gaussian;
复制代码
rvm_test中:
  1. % compute the kernel matrix
  2.     kernel_poly = Kernel('type', 'poly', 'degree', 2, 'offset', 0);
  3.     K_poly = kernel_poly.getKernelMatrix(xt, model.rv);

  4.     kernel_gaussian = Kernel('type', 'sigm', 'width', 0.5);
  5.     K_gaussian = kernel_gaussian.getKernelMatrix(xt, model.rv);

  6.     K = K_poly+K_gaussian;
复制代码
1.png

iqiukp 发表于 2020-4-25 18:08:41
阿濠 发表于 2020-4-25 16:32
楼主您好,刚学习相关向量机,有问题想请教一下,看楼上您说的多核相关向量机的修改方法,按要求修改成高斯 ...

你好。可以换其他数据集试试,这个sinc函数的数据集对核函数比较敏感,之前也出现过类似情况。近期我会发布2.0版本的代码,集成混合核函数功能,到时候可以关注一下。

阿濠 发表于 2020-4-25 19:48:16
iqiukp 发表于 2020-4-25 18:08
你好。可以换其他数据集试试,这个sinc函数的数据集对核函数比较敏感,之前也出现过类似情况。近期我会发 ...

哦哦哦好的,我试一下。期待新版本:D

iqiukp 发表于 2020-4-28 03:12:27
本帖最后由 iqiukp 于 2020-5-27 12:35 编辑

untitled.png



2020.4.28更新(V2.0)

源代码
RVM-MATLAB-V2.0.zip (176.72 KB, 下载次数: 306)

涉远飞高 发表于 2020-4-28 08:39:48
本帖最后由 涉远飞高 于 2020-4-28 08:51 编辑

楼主好,感谢您提供的程序代码。

基于一些自身的需要,我将您V1.3的代码进行了修改,主要是将一个矩阵P加入到了rvm_test和rvm_train中进行混合核函数计算,修改后程序变成了model = rvm_train(P, x, y, varargin) 及 result = rvm_test(P,model, xt, yt),但修改程序报错: Parameters of rvm_train should be pairs。

后来我认识到是由于程序输入变量数量变化了产生了影响, 因此我将如下代码注释掉了。
    % nargin: number of function input arguments.
     if nargin < 3
         warning('Please input the real value of the test data')
     end

但后面的代码看不太懂:
    numParameters = nargin/2-1;

    for n =1:numParameters
        parameters = varargin{(n-1)*2+1};
        value        = varargin{(n-1)*2+2};
        switch parameters
                %
            case 'kernel'
                kernel = value;
                %
            case 'option'
                option = value;
        end
    end

    %
    numSamples = size(x, 1);

想请教楼主,如果只想加这个P加进去,然后再函数中能够正常使用,而不影响rvm_train和rvm_test的正常功能,请问还有什么地方需要修改的么?
PS:我也看到了您刚提供的2.0版本代码,但因为我这个程序已经基本改完了,所以还是希望能够用我修改的这个程序。后期我也会对您的2.0版本代码进行学习。感谢


以下为我修改后的rvm_train 和 rvm_test 代码。
  1. function model = rvm_train(P, x, y, varargin)
  2.     %{

  3.         DESCRIPTION

  4.         Prediction based on Relevance Vector Machine (RVM)
  5.         Using SB2_Release_200 toolbox
  6.         -------------------------------------------------------------

  7.               model = rvm_train(X,Y,varargin)

  8.         INPUT
  9.           x            training samples (n*d)
  10.                        n: number of samples
  11.                        d: number of features
  12.           y            target samples (n*1)

  13.         OUTPUT
  14.           model        RVM model

  15.         Created on 18th March 2020, by Kepeng Qiu.
  16.         -------------------------------------------------------------%

  17.     %}

  18.     tic
  19.     % 默认设置
  20.     % default parameter setting
  21.     kernel = Kernel('type', 'gauss', 'width', sqrt(size(x, 2)));
  22.     option = struct('freeBasis', 'off',...
  23.                     'display', 'on');
  24.     %
  25. %     if rem(nargin, 2)
  26. %         error('Parameters of rvm_train should be pairs')
  27. %     end
  28.     numParameters = nargin/2-1;

  29.     for n =1:numParameters
  30.         parameters = varargin{(n-1)*2+1};
  31.         value        = varargin{(n-1)*2+2};
  32.         switch parameters
  33.                 %
  34.             case 'kernel'
  35.                 kernel = value;
  36.                 %
  37.             case 'option'
  38.                 option = value;
  39.         end
  40.     end

  41.     %
  42.     numSamples = size(x, 1);

  43.     % compute the kernel matrix
  44.     %K = kernel.getKernelMatrix(x, x);
  45.         
  46.         %混合核函数
  47.         % 创建一个多项式核函数对象
  48.         kernel_poly = Kernel('type', 'poly', 'degree', P(1), 'offset', 0);
  49.         % 计算多项式核函数矩阵
  50.         K_poly = kernel_poly.getKernelMatrix(x, x);
  51.         % 创建一个双曲正切核函数对象
  52.         kernel_gauss = Kernel('type', 'gauss', 'width', P(2));
  53.         % 计算双曲正切核函数矩阵
  54.         K_gauss = kernel_gauss.getKernelMatrix(x, x);
  55.         % 混合的核函数矩阵(也可以单独设置每个核函数的权重)
  56.         K = P(3)*K_poly+(1-P(3))*K_gauss;

  57.     % construct the basis vectors
  58.     if ~strcmp(option.freeBasis, 'on')
  59.         % no bias
  60.         BASIS = K;
  61.         [PARAMETER, HYPERPARAMETER, DIAGNOSTIC] = ...
  62.         SparseBayes('Gaussian', BASIS, y);
  63.     else
  64.         % add bias
  65.         indexBias = numSamples+1;  % index of bias
  66.         BASIS = [K, ones(numSamples, 1)];
  67.         [PARAMETER, HYPERPARAMETER, DIAGNOSTIC] = ...
  68.         SparseBayes('Gaussian', BASIS, y, SB2_UserOptions('freeBasis', indexBias));
  69.     end
  70.     timeCost = toc;
  71.    
  72.     % RVM model
  73.     model = struct();
  74.     model.index = PARAMETER.Relevant;  % index of BASIS
  75.     model.relevant = model.index; % index of relevance vectors
  76.     if strcmp(option.freeBasis, 'on')
  77.         model.bias = PARAMETER.Value(end); % value of bias
  78.         model.relevant(model.relevant == numSamples+1) = [];
  79.         if isempty(model.relevant)
  80.             warning('No relevant vetors were found! Please change the values of kernel parameters.')
  81.         end
  82.     else
  83.         model.bias = 0; % value of bias
  84.     end

  85.     model.mu = PARAMETER.Value;          % vector of weight values
  86.     model.beta = HYPERPARAMETER.beta;    % noise precision
  87.     model.alpha = HYPERPARAMETER.Alpha;  % vector of weight precision values
  88.     model.kernel = kernel; % kernel function
  89.     model.PHI = BASIS(:, PARAMETER.Relevant); % Used BASIS
  90.     model.iter = DIAGNOSTIC.iterations; % iteration
  91.     model.nRVs = size(model.relevant, 1);  % number of relevance vectors
  92.     model.option = option; % RVM model option
  93.     model.sigma = inv(diag(HYPERPARAMETER.Alpha)+...
  94.         HYPERPARAMETER.beta*(model.PHI'*model.PHI));% posterior covariance
  95.     model.rv = x(model.relevant, :); % relevance vectors
  96.    
  97.     % model evaluation
  98.     ypre = model.PHI*model.mu;
  99.     [model.RMSE, model.CD, model.MAE] = computePretIndex(y, ypre);

  100.     % display
  101.     if strcmp(model.option.display, 'on')
  102.         fprintf('\n')
  103.         fprintf('*** RVM model training finished ***\n')
  104.         fprintf('iter           =  %d \n', model.iter);
  105.         fprintf('nRVs           =  %d \n', model.nRVs)
  106.         fprintf('radio of nRVs  =  %.2f%% \n', 100*model.nRVs/numSamples)
  107.         fprintf('time cost      =  %.4f s\n', timeCost)
  108.         fprintf('training RMSE  =  %.4f\n', model.RMSE)
  109.         fprintf('training CD    =  %.4f\n', model.CD)
  110.         fprintf('training MAE   =  %.4f\n', model.MAE)
  111.         fprintf('\n')
  112.     end
  113. end





  114. function result = rvm_test(P,model, xt, yt)
  115.     %{

  116.         DESCRIPTION

  117.               result = rvm_test(model, xt, yt)

  118.         INPUT
  119.           model        RVM model
  120.           xt           testing samples (n*d)
  121.                        n: number of samples
  122.                        d: number of features
  123.           yt           target samples (n*1)


  124.         OUTPUT
  125.           result       predicted results

  126.         Created on 18th March 2020, by Kepeng Qiu.
  127.         -------------------------------------------------------------

  128.     %}
  129.     % nargin: number of function input arguments.
  130. %     if nargin < 3
  131. %         warning('Please input the real value of the test data')
  132. %     end
  133.    
  134.    
  135.     tic
  136.     nt = size(xt, 1);
  137.     % Compute the kernel matrix
  138.    
  139.     %K = model.kernel.getKernelMatrix(xt, model.rv);
  140.    
  141.         %混合核函数
  142.         % 创建一个多项式核函数对象
  143.         kernel_poly = Kernel('type', 'poly', 'degree', 2, 'offset', 0);
  144.         % 计算多项式核函数矩阵
  145.         K_poly = kernel_poly.getKernelMatrix(xt, model.rv);
  146.         % 创建一个双曲正切核函数对象
  147.         kernel_gauss = Kernel('type', 'gauss', 'width', P(2));
  148.         % 计算双曲正切核函数矩阵
  149.         K_gauss = kernel_gauss.getKernelMatrix(xt, model.rv);
  150.         % 混合的核函数矩阵(也可以单独设置每个核函数的权重)
  151.         K = P(3)*K_poly+(1-P(3))*K_gauss;

  152.     % Construct the basis vectors
  153.     if ~strcmp(model.option.freeBasis, 'on')
  154.         % No bias
  155.         BASIS = K;
  156.     else
  157.         % Add bias
  158.         BASIS = [K, ones(nt, 1)];
  159.     end
  160.    
  161.     result = struct();
  162.     % prediction
  163.     result.ypre = BASIS*model.mu;

  164.     % variance of prediction 预测方差
  165.     result.yvar = model.beta^-1+diag(BASIS*model.sigma*BASIS');
  166.     timeCost = toc;
  167.    
  168.     % model evaluation  % 预测结果分析
  169.     [result.RMSE, result.CD, result.MAE] = computePretIndex(yt, result.ypre);
  170.    
  171.     if strcmp(model.option.display, 'on')
  172.         fprintf('\n')
  173.         fprintf('*** RVM model test finished ***\n')
  174.         fprintf('time cost      =  %.4f s\n', timeCost)
  175.         fprintf('predicted RMSE =  %.4f\n', result.RMSE)
  176.         fprintf('predicted CD   =  %.4f\n', result.CD)
  177.         fprintf('predicted MAE  =  %.4f\n', result.MAE)
  178.         fprintf('\n')
  179.     end
  180. end
复制代码



王镇_zVnvQ 发表于 2020-4-28 12:28:23
iqiukp 发表于 2020-4-28 03:12
2020.4.28更新(V2.0)

源代码

看楼主之前也做过鲸鱼算法,是否也做了与相关向量机的结合?二者需要哪些地方进行修改,方便将代码分享一下吗

iqiukp 发表于 2020-4-28 12:35:38
本帖最后由 iqiukp 于 2020-4-28 12:39 编辑
涉远飞高 发表于 2020-4-28 08:39
楼主好,感谢您提供的程序代码。

基于一些自身的需要,我将您V1.3的代码进行了修改,主要是将一个矩阵P加 ...

你好。

1. 代码解释
  1. numParameters = nargin/2-1;
  2.     for n =1:numParameters
  3.      parameters = varargin{(n-1)*2+1};
  4.      value        = varargin{(n-1)*2+2};
  5.      switch parameters
  6.          %
  7.          case 'kernel'
  8.              kernel = value;
  9.          %
  10.         case 'option'
  11.             option = value;
  12.      end
  13.     end
复制代码

首先看V1.3中,rvm_train的传参形式:
  1. model = rvm_train (x, y, varargin)
复制代码
有两个固定参数x和y,同时支持不定传参个数(varargin),在这里要求是键值对的形式,譬如‘width’ - 4。在这种情况下,函数中识别的传参个数(nargin)是4个,x, y, ‘width’, 4, 但实际上参数应该为3个:x, y 和width。所以不定传参个数的计算为numParameters = nargin/2-1或者是numParameters = (nargin-2)/2

因此,上述代码块实现的功能是:判断不定传参是哪个变量的键值对('kernel'或者'option'),然后把键值对的值赋给该参数。

可以结合matlab的文档了解一下vararginnargin的用法,一般是为了实现函数传参的灵活性。

2. 代码修改

如果把rvm_train的传参形式改为:
  1. model = rvm_train (P, x, y, varargin)
复制代码
相当于固定参数变为3个,那么判断不定传参的个数就要修改为:
  1. numParameters = (nargin-3)/2;
复制代码
其他地方不用修改了。另外,如果这个矩阵P也应用到rvm_test,建议直接在把该值存储到结构体model里面:model.P = P;
然后在rvm_test以model.P的形式调用。





iqiukp 发表于 2020-4-28 12:50:03
王镇_zVnvQ 发表于 2020-4-28 12:28
看楼主之前也做过鲸鱼算法,是否也做了与相关向量机的结合?二者需要哪些地方进行修改,方便将代码分享一 ...

你好。抱歉没有做WOA与RVM的结合。关于两者结合的代码修改,主要在RvmOptimization.m修改,部分说明如图所示:


Snipaste_2020-04-28_12-43-36.png




在RVM2.0中,优化算法的实现封装到RvmOptimization类中,建议先阅读这个代码,然后再考虑添加WOA算法。

涉远飞高 发表于 2020-4-28 14:39:15
iqiukp 发表于 2020-4-28 12:35
你好。

1. 代码解释

感谢楼主的答疑。

楼主的MATLAB功底不一般,向楼主学习:handshake:handshake

1246078874 发表于 2020-4-28 17:20:46
楼主你好,我是刚接触这一块,用了你分享的程序代码已经跑通了,十分感谢,但是在最后结果处理上不太会画像你分析的那种图,求教楼主。

iqiukp 发表于 2020-4-28 17:35:09
1246078874 发表于 2020-4-28 17:20
楼主你好,我是刚接触这一块,用了你分享的程序代码已经跑通了,十分感谢,但是在最后结果处理上不太会画像 ...

你好。帖子中的图是用另外的数据集跑出来的,sinc函数,为了方便可视化。
demo中用的数据是UCI里面的一个数据集。

王镇_zVnvQ 发表于 2020-4-28 22:28:12
iqiukp 发表于 2020-4-28 12:50
你好。抱歉没有做WOA与RVM的结合。关于两者结合的代码修改,主要在RvmOptimization.m修改,部分说明如图所 ...

好的,谢谢楼主

1246078874 发表于 2020-5-5 09:21:26
楼主你好,谢谢你的分享,我最近在用你发布的v1.3做寿命预测方面的内容,数据是随周期下降,呈退化趋势,对数据进行标准化后输入到训练和测试中后在测试中得到的预测结果是一条上升曲线且正好与真实值轴对称,请教一下楼主哪出问题了,该怎么弄啊,万分感谢

阿濠 发表于 2020-5-5 09:36:56
楼主,有个问题想问一下,换上自己编的数据(输入80*15,输出80*1)后。建立模型时显示相关向量是79个。。。再做预测出来的值就是一条直线了。是因为数据是编的所以不能用么:(

iqiukp 发表于 2020-5-5 21:36:53
阿濠 发表于 2020-5-5 09:36
楼主,有个问题想问一下,换上自己编的数据(输入80*15,输出80*1)后。建立模型时显示相关向量是79个。。 ...

嗯有可能。这种情况是过拟合了。去找些标准数据集来测试测试吧。

iqiukp 发表于 2020-5-5 21:43:51
1246078874 发表于 2020-5-5 09:21
楼主你好,谢谢你的分享,我最近在用你发布的v1.3做寿命预测方面的内容,数据是随周期下降,呈退化趋势,对 ...

你好。寿命预测问题涉及的数据集是时间序列的吗?如果是的话,直接使用RVM获取的结果可能不理想。69#的帖子和你的类似,我在70#给出了这种问题的可能性分析以及一些解决方案,可以参考一下。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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