2016-07-29 5 views
2

나는 사용자 정의 견적 객체를 Python (mkl_regressor)으로 가지고 있습니다. 이러한 객체의 학습 매개 변수 중 하나는 numpy.array 수레입니다. 일반적으로 sklearn 견적 객체는 SVM의 C과 같은 단일 매개 변수로 조정됩니다. 따라서 randomizedSearchCV 검색 개체는 원하는 매개 변수에 대해 주어진 분포 (예 : scipy.stats.expon)에서 일부 값을 선택하기위한 분포 또는 값 목록을 사용합니다. randomizedSearchCV은 배포판 배열의 요소를 실행하지 않기 때문에 배포본 목록을 전달하려고했지만 성공하지 못했습니다.여러 배포판 목록을 sklearn randomizedSearchCV에 전달하는 방법

from modshogun import * 
import Gnuplot, Gnuplot.funcutils 
from numpy import * 
from sklearn.metrics import r2_score 

class mkl_regressor(): 

    def __init__(self, widths = [0.01, 0.1, 1.0, 10.0, 50.0, 100.0], kernel_weights = [0.01, 0.1, 1.0,], svm_c = 0.01, mkl_c = 1.0, svm_norm = 1, mkl_norm = 1, degree = 2): 
     self.svm_c = svm_c 
     self.mkl_c = mkl_c 
     self.svm_norm = svm_norm 
     self.mkl_norm = mkl_norm 
     self.degree = degree 
     self.widths = widths 
     self.kernel_weights = kernel_weights 


    def fit(self, X, y, **params): 
     for parameter, value in params.items(): 
      setattr(self, parameter, value)   

     self.feats_train = RealFeatures(X.T) 
     labels_train = RegressionLabels(y.reshape((len(y),))) 
     self._kernels_ = CombinedKernel() 
     for width in self.widths: 
      kernel = GaussianKernel() 
      kernel.set_width(width) 
      kernel.init(self.feats_train,self.feats_train) 
      self._kernels_.append_kernel(kernel) 
      del kernel 

     kernel = PolyKernel(10, self.degree)    
     self._kernels_.append_kernel(kernel) 
     del kernel 

     self._kernels_.init(self.feats_train, self.feats_train) 

     binary_svm_solver = SVRLight() 
     self.mkl = MKLRegression(binary_svm_solver) 

     self.mkl.set_C(self.svm_c, self.svm_c) 
     self.mkl.set_C_mkl(self.mkl_c) 
     self.mkl.set_mkl_norm(self.mkl_norm) 
     self.mkl.set_mkl_block_norm(self.svm_norm) 

     self.mkl.set_kernel(self._kernels_) 
     self.mkl.set_labels(labels_train) 
     self.mkl.train() 
     self.kernel_weights = self._kernels_.get_subkernel_weights() 

    def predict(self, X): 
     self.feats_test = RealFeatures(X.T) 
     self._kernels_.init(self.feats_train, self.feats_test) 
     self.mkl.set_kernel(self._kernels_) 
     return self.mkl.apply_regression().get_labels() 

    def set_params(self, **params): 
     for parameter, value in params.items(): 
      setattr(self, parameter, value) 

     return self 

    def get_params(self, deep=False): 

     return {param: getattr(self, param) for param in dir(self) if not param.startswith('__') and not callable(getattr(self,param))}  

    def score(self, X_t, y_t): 

     predicted = self.predict(X_t) 
     return r2_score(predicted, y_t)  

if __name__ == "__main__": 

    from sklearn.grid_search import RandomizedSearchCV as RS 
    from scipy.stats import randint as sp_randint 
    from scipy.stats import expon 

    labels = array([2.0,0.0,2.0,1.0,3.0,2.0]) 
    labels = labels.reshape((len(labels), 1)) 
    data = array([[1.0,2.0,3.0],[1.0,2.0,9.0],[1.0,2.0,3.0],[1.0,2.0,0.0],[0.0,2.0,3.0],[1.0,2.0,3.0]]) 
    labels_t = array([1.,3.,4]) 
    labels_t = labels_t.reshape((len(labels_t), 1)) 
    data_t = array([[20.0,30.0,40.0],[10.0,20.0,30.0],[10.0,20.0,40.0]]) 
    k = 3 

    param_grid = [ {'svm_c': expon(scale=100, loc=5), 
       'mkl_c': expon(scale=100, loc=5), 
       'degree': sp_randint(0, 32), 
       #'widths': [array([4.0,6.0,8.9,3.0]), array([4.0,6.0,8.9,3.0,2.0, 3.0, 4.0]), array([100.0, 200.0, 300.0, 400.0]) 
       'widths': [[expon, expon]] 
       }] 

    mkl = mkl_regressor() 
    rs = RS(mkl, param_distributions = param_grid[0], n_iter = 10, n_jobs = 24, cv = k)#, scoring="r2", verbose=True) 
    rs.fit(data, labels) 
    preds = rs.predict(data_t) 

    print "R^2: ", rs.score(data_t, labels_t) 
    print "Parameters: ", rs.best_params_ 

위의 코드 목록 매개 변수의 사전 'widths'의 요소로 NumPy와 배열을 전달하여 잘 작동합니다 : 이것은 내가 뭘하려합니다. I는 분배리스트를 통과 할 때 그러나 randomizedSearchCV 개체에서 원하는 반응하지 :

/home/ignacio/distributionalSemanticStabilityThesis/mkl_test.py in fit(self=<__main__.mkl_regressor instance>, X=array([[ 1., 2., 3.], 
     [ 1., 2., 0.], 
     [ 0., 2., 3.], 
     [ 1., 2., 3.]]), y=array([[ 2.], 
     [ 1.], 
     [ 3.], 
     [ 2.]]), **params={}) 
    24   self.feats_train = RealFeatures(X.T) 
    25   labels_train = RegressionLabels(y.reshape((len(y),))) 
    26   self._kernels_ = CombinedKernel() 
    27   for width in self.widths: 
    28    kernel = GaussianKernel() 
---> 29    kernel.set_width(width) 
     kernel.set_width = <built-in method set_width of GaussianKernel object> 
     width = <scipy.stats._continuous_distns.expon_gen object> 
    30    kernel.init(self.feats_train,self.feats_train) 
    31    self._kernels_.append_kernel(kernel) 
    32    del kernel 
    33 

TypeError: in method 'GaussianKernel_set_width', argument 2 of type 'float64_t' 

I에서, randomizedSearchCV 때문에 이러한 경우에 각각의 분포 생성을 실행하기위한 추정기 강제 싶지 않은 사용 된 값을 제어 할 수 없습니다.

몇 가지 제안 사항이 있습니까? 고맙습니다.

답변

1

RandomizedSearchCV는를 샘플링하는 방법으로 RVS분포 객체 또는 시도 파라미터 값들의 목록 중 하나를 취할 수있다. 목록을 전달하면 매개 변수 값의 개별 세트를 샘플로 전달했다고 가정합니다. 단일 매개 변수에 대한 분배 목록을 지원하지 않습니다. 기존 배포판이 사용자 요구에 맞지 않는 경우 사용자 지정 배포판을 만드십시오.

배열을 반환하는 배포판이 필요한 경우 rvs() 메서드가있는 클래스를 만들어 무작위 샘플을 반환하고 단일 변형 배포 목록 대신 인스턴스를 전달하면됩니다.

+0

안녕 @bpachev는 답변을 주셔서 감사합니다. 이는 내가 산정 한 추정기 객체 (MKL)가 별도의 매개 변수를 필요로하기 때문에 필요합니다. 이들 파라미터는 상이한 커널 대역폭, 즉 고정 된 길이가 아닌 대역폭의 벡터 (예를 들어, SVR의 경우와 같이 하나 일뿐만 아니라)이다. 'RandomizedSearchCV'에 대역폭 벡터의 각 구성 요소에 대해 샘플링되는 것을 제어하기위한 몇 가지 제안이 있습니까? 나는 현재'RandomizedSearchCV'에 전달하기 전에 무작위 벡터를 생성하고 있습니다. 그러나 이것은 매우 비효율적 인 해결책입니다. – Nacho

+0

적절한 분포를 갖는 배열을 반환하는 분포 함수를 만들어야합니다. 그에 따라 응답으로 편집 할 것입니다. – bpachev

+0

@bpachev가 작동했습니다. 고맙습니다. – Nacho

0

해결책 @bpachev가 제안되었습니다. 분포 클래스 :

class expon_vector(stats.rv_continuous): 

    def __init__(self, loc = 1.0, scale = 50.0, min_size=2, max_size = 10): 
     self.loc = loc 
     self.scale = scale 
     self.min_size = min_size 
     self.max_size = max_size 
     self.size = max_size - min_size # Only for initialization 

    def rvs(self): 

     self.size = randint.rvs(low = self.min_size, 
           high = self.max_size, size = 1) 
     return expon.rvs(loc = self.loc, scale = self.scale, size = self.size) 

내가 사용하고 사용자 정의 추정에 대한 매개 변수의 사전에 포함되어

param_grid = [ {'svm_c': expon(scale=100, loc=5), 
        'mkl_c': expon(scale=100, loc=5), 
        'degree': sp_randint(0, 24), 
        'widths': expon_vector(loc = 0.1, scale = 100.0, 
           min_size = 2, max_size = 10) } ]