2013-12-10 695 views
5

我想比较不同的机器学习算法。作为其中的一部分,我需要能够执行grid search for optimal hyperparameters。然而,我并不是真的想为每个固定算法和超参数的固定子集写一个单独的网格搜索实现。相反,我希望它看起来更像scikit-learn,但可能没有太多功能(例如,我不需要多个网格)并使用MATLAB编写。算法不可知的超参数在MATLAB中的网格搜索

到目前为止,我想了解的还没有被写入grid_search.m

function model = grid_search(algo, data, labels, varargin) 
    p = inputParser; 
    % here comes the list of all possible hyperparameters for all algorithms 
    % I will just leave three for brevity 
    addOptional(p, 'kernel_function', {'linear'}); 
    addOptional(p, 'rbf_sigma', {1}); 
    addOptional(p, 'C', {1}); 

    parse(p, algo, data, labels, varargin{:}); 

    names = fieldnames(p.Results); 
    values = struct2cell(p.Results); % a cell array of cell arrays 

    argsize = 2 * length(names); 
    args = cell(1, argsize); 
    args(1 : 2 : argsize) = names; 
    % Now this is the stumbling point. 
end 

grid_search函数的调用逻辑应该是这个样子:

m = grid_search('svm', data, labels, 'kernel_function', {'rbf'}, 'C', {[0.1], [1], [10]}, 'rbf_sigma', {[1], [2], [3]}) 
m = grid_search('knn', data, labels, 'NumNeighbors', {[1], [10]}, 'Distance', {'euclidean', 'cosine'}) 

的第一个电话,然后会尝试rbf内核与约束条件和sigma的所有组合:

{'rbf', 0.1, 1} 
{'rbf', 0.1, 2} 
{'rbf', 0.1, 3} 
{'rbf', 1, 1} 
{'rbf', 1, 2} 
{'rbf', 1, 3} 
{'rbf', 10, 1} 
{'rbf', 10, 2} 
{'rbf', 10, 3} 

args变量背后的想法是它是一个格式为{'name1', 'value1', 'name2', 'value2', ..., 'nameN', 'valueN'}的单元格数组,它将在稍后传递给相应的算法:algo(data, labels, args{:}){'name1', 'name2', ..., 'nameN'}的一部分很简单。问题是我不能在每个步骤中指定如何创建{'value1', 'value2', ..., 'valueN'}零件。

据我所知,机器学习术语并不无人不晓这就是为什么下面自带一个独立的例子:

假设TARDIS的船员可以由人类的下列类:

tardis_crew = {{'doctor'}, {'amy', 'clara'}, {'dalek', 'cyberman', 'master'}} 

因为总是有一个Timelord,同伴和对手只是一个地方,请告诉我如何生成以下电池阵列:

{'Timelord', 'doctor', 'Companion', 'amy', 'Villain', 'dalek'} 
{'Timelord', 'doctor', 'Companion', 'amy', 'Villain', 'cyberman'} 
{'Timelord', 'doctor', 'Companion', 'amy', 'Villain', 'master'} 
{'Timelord', 'doctor', 'Companion', 'clara', 'Villain', 'dalek'} 
{'Timelord', 'doctor', 'Companion', 'clara', 'Villain', 'cyberman'} 
{'Timelord', 'doctor', 'Companion', 'clara', 'Villain', 'master'} 

该解决方案应该是一般性的,即如果一个类中生命的数量发生了变化,或者增加了更多类别的生命,它仍然应该起作用。我会非常感谢一步一步的解释,而不是代码。

PS:non-stripped github版本的原始grid_search.m可能会让您更好地了解我的意思。

回答

2

看来你想要的是生成任意数量的集合的笛卡尔乘积。我认为这个ALLCOMB函数会为你做,但如果你想要一个(迭代)算法的细节,以便你自己实现它,请检查this answer

编辑:非常感谢您为没有ML知识的人提供一般性措辞。

+0

我最终从ALLCOMB脚本中得到了一个不错的技巧'[A {:}] = ndgrid(varargin {:})',并从原始的'ndgrid中实际上重写(删除所有'full()'调用)。 m' matlab函数。它现在可行,但我对此有一个非常模糊的理解。如果我得到一个更好的,我肯定会更新。现在,这里是[hackish版本](https://gist.github.com/all3fox/615542bdaea8f41e7de1) – alisianoi