pycaret 2.3.1) tune_model hyperopt example

2021. 6. 20. 13:31분석 Python/구현 및 자료

pycaret에서 search_library 중에서 tune-sklearn을 사용할 때 방법을 공유한다. 

특히 custom_grid를 통해서 구현된 것이 없어서 시행착오의 결과를 공유하고, 결론적으로 모든 기능을 완벽히 제공하는 것 같지는 않다 ( 21/06/20 기준) 

pycaret version : 2.3.1

 

일단 custom_grid를 보면 format은 search_library를 기준으로 한다고 한다.

 

그래서 search_library를 가보니 각 방법에 따라서 링크가 걸려있다.

그래서 들어가 보니 다음과 같이 tune을 통해서 choice 하거나 loguniform을 하는 것을 알 수 있었다.

# Define the `param_dists using the SearchSpace API
# This allows the specification of sampling from discrete and 
# categorical distributions (below for the `learning_rate` scheduler parameter)
from ray import tune
param_dists = {
    'loss': tune.choice(['squared_hinge', 'hinge']),
    'alpha': tune.loguniform(1e-4, 1e-1),
    'epsilon': tune.uniform(1e-2, 1e-1),
}


hyperopt_tune_search = TuneSearchCV(SGDClassifier(),
    param_distributions=param_dists,
    n_trials=2,
    early_stopping=True, # uses Async HyperBand if set to True
    max_iters=10,
    search_optimization="hyperopt"
)

hyperopt_tune_search.fit(X_train, y_train)

그래서 조금 더 자세히 알고 싶어서 ray에 들아가 보니 다음과 같은 예제가 있었다.

config = {
    # Sample a float uniformly between -5.0 and -1.0
    "uniform": tune.uniform(-5, -1),

    # Sample a float uniformly between 3.2 and 5.4,
    # rounding to increments of 0.2
    "quniform": tune.quniform(3.2, 5.4, 0.2),

    # Sample a float uniformly between 0.0001 and 0.01, while
    # sampling in log space
    "loguniform": tune.loguniform(1e-4, 1e-2),

    # Sample a float uniformly between 0.0001 and 0.1, while
    # sampling in log space and rounding to increments of 0.0005
    "qloguniform": tune.qloguniform(1e-4, 1e-1, 5e-4),

    # Sample a random float from a normal distribution with
    # mean=10 and sd=2
    "randn": tune.randn(10, 2),

    # Sample a random float from a normal distribution with
    # mean=10 and sd=2, rounding to increments of 0.2
    "qrandn": tune.qrandn(10, 2, 0.2),

    # Sample a integer uniformly between -9 (inclusive) and 15 (exclusive)
    "randint": tune.randint(-9, 15),

    # Sample a random uniformly between -21 (inclusive) and 12 (inclusive (!))
    # rounding to increments of 3 (includes 12)
    "qrandint": tune.qrandint(-21, 12, 3),

    # Sample a integer uniformly between 1 (inclusive) and 10 (exclusive),
    # while sampling in log space
    "lograndint": tune.lograndint(1, 10),

    # Sample a integer uniformly between 1 (inclusive) and 10 (inclusive (!)),
    # while sampling in log space and rounding to increments of 2
    "qlograndint": tune.qlograndint(1, 10, 2),

    # Sample an option uniformly from the specified choices
    "choice": tune.choice(["a", "b", "c"]),

    # Sample from a random function, in this case one that
    # depends on another value from the search space
    "func": tune.sample_from(lambda spec: spec.config.uniform * 0.01),

    # Do a grid search over these values. Every value will be sampled
    # `num_samples` times (`num_samples` is the parameter you pass to `tune.run()`)
    "grid": tune.grid_search([32, 64, 128])
}

그래서 실제로 테스트한 코드는 다음과 같고 아쉬운 점이 있었다.

일단 아쉬운 점 중에서 하나는 ray의 cpu 제한을 pycaret에서는 할 수가 없었다.

 그래서 ray의 초기화 함수를 이용하여서 진행하였다.

from pycaret.datasets import get_data
boston = get_data('boston')
from pycaret.regression import *
exp_name = setup(data = boston,  target = 'medv',silent=True,n_jobs =20)
catboost_model = create_model('catboost')

 

 

from ray import tune
import ray
catboost_param_dists = {
    'iterations': tune.choice([500,100,300]),
    # 'reg_lambda': tune.uniform(1, 100),
    # 'bagging_temperature': tune.uniform(0, 100),
    # 'colsample_bylevel': tune.uniform(0.5, 1.0),
    'random_strength': tune.choice([0,0.1,0.2,1,10]), # tune.uniform(0, 100),
    # 'learning_rate': tune.uniform(1e-3, 1e-1),
    'max_depth' : tune.choice([5,6,7,8,9])
}

 

아쉬운 점 중에 하나는 모든 함수를 못쓰고, 오로지 choice만 사용 가능해 보인다. 

다른 것을 하게 되면, 내부적으로 에러가 나는 것을 발생했다. 

 

ray.init(num_cpus=20, num_gpus=2)
tuned_top1 = tune_model(catboost_model,
                        optimize="R2",
                        search_library="tune-sklearn",
                        search_algorithm="hyperopt",
                        choose_better = True ,
                        custom_grid = catboost_param_dists ,
                        early_stopping = "asha",
                        early_stopping_max_iters = 10,
                        return_tuner = False , 
                        n_iter=100)
ray.shutdown()

 

그래서 이런 식으로 진행해야지 tune-sklearn을 사용할 수 있었다. 

다만 이걸 사용하고자 한 이유는 특정 범위만 주면 알아서 찾는 방법론으로써 사용하고 싶었으나, 실제로 그렇게 되지 않아서 아쉽다...

그래서 코드를 좀 뜯어보니 현재는 choice만 가능할 것 같고, 이것은 나머지 경우에도 동일한 상황일 것 같다.

 


수정!!! (21/06/21)

github에 issue를 제기하니, 내가 잘 못 했다는 것을 알았다. 

다음과 같이 진행하면 내가 원하는 기능이 잘 작동한다는 것을 공유한다

from pycaret.distributions import (
    UniformDistribution, # uniform log uniform
    IntUniformDistribution, # intuniform intloguniform
    DiscreteUniformDistribution, # quniform
    CategoricalDistribution,
)
catboost_param_dists = {
    'iterations': CategoricalDistribution([500,100,300]),
    # 'reg_lambda': UniformDistribution(1, 100),
    # 'bagging_temperature': UniformDistribution(0, 100),
    'colsample_bylevel': UniformDistribution(0.5, 1.0),
    'random_strength': CategoricalDistribution([0,0.1,0.2,1,10]), # tune.uniform(0, 100),
    # 'learning_rate': UniformDistribution(1e-3, 1e-1),
    'max_depth' : CategoricalDistribution([5,6,7,8,9])
}
tuned_top1 = tune_model(catboost_model,
                        optimize="R2",
                        search_library="tune-sklearn",
                        search_algorithm="hyperopt",
                        choose_better = True ,
                        custom_grid = catboost_param_dists ,
                        early_stopping = "asha",
                        early_stopping_max_iters = 10,
                        return_tuner = False , 
                        n_iter=100)

문서에 없고 예제에도 없으니 ㅠㅠ 알 길이 없어서 안되는 줄 알았다.

된다고 하니 다행인 것 같다 ㅠㅠ 

 

 

https://github.com/ray-project/tune-sklearn/issues/213#event-4913870765

 

The hyperopt search algorithm fails with a custom_grid. · Issue #213 · ray-project/tune-sklearn

pycaret version : 2.3.1 I want to use a variety of tune methods when using hyperopt in pycaret, but only tune.choice is possible, not others. I hope you check and improve! from pycaret.datasets imp...

github.com

 

 

https://docs.ray.io/en/master/tune/api_docs/search_space.html

 

Search Space API — Ray v2.0.0.dev0

.rst .pdf to have style consistency -->

docs.ray.io

https://docs.ray.io/en/master/tune/api_docs/search_space.html

 

Search Space API — Ray v2.0.0.dev0

.rst .pdf to have style consistency -->

docs.ray.io

 

728x90