서론
이미 검색창에 AutoML이라고 검색하면, 잘 만들어진 AutoML들이 많다.
많은 좋은 프로그래밍들을 보고 코드 의도와 구현 방식을 배우는 것이 목표이다.
AutoSklearnClassifier Source 확인
원본은 아래 공식홈페이지에서 확인 할 수 있습니다.
https://automl.github.io/auto-sklearn/master/api.html#classification
분석대상은 AutoSklearnClassifier 알고리즘입니다.
[AutoML] 구현을 향해, sklearn-BaseEstimator? 2편
1. BaseEstimator 확인
대표적으로 2개 클래스가 있습니다
class AutoSklearnEstimator(BaseEstimator):
class AutoSklearnClassifier(AutoSklearnEstimator, ClassifierMixin):
AutoSklearnClassifier는 AutoSklearnEstimator를 상속받고 있으며, AutoSkearnEstimator는 BaseEstimator를 상속받고 있습니다. 그렇다면 sklearn의 BaseEstimator를 확인해보겠습니다.
BaseEstimator
- BaseEstimator는 이름에서도 알 수 있는 것처럼 사이킷런의 모든 분류기의 기본 클래스입니다.
- BaseEstimator에서 사용 할 수 있는 메서드는 'get_params'와 'set_params' 입니다.
get_params : 분류기에 대해 설정된 파라미터를 가져오는 메서드
set_params : 분류기의 파라미터를 설정하는 메서드
set_params
def set_params(self, **params):
"""
Set the parameters of this estimator.
The method works on simple estimators as well as on nested objects
(such as :class:`~sklearn.pipeline.Pipeline`). The latter have
parameters of the form ``<component>__<parameter>`` so that it's
possible to update each component of a nested object.
Parameters
----------
**params : dict
Estimator parameters.
Returns
-------
self : estimator instance
Estimator instance.
"""
if not params:
# Simple optimization to gain speed (inspect is slow)
return self
valid_params = self.get_params(deep=True)
nested_params = defaultdict(dict) # grouped by prefix
for key, value in params.items():
key, delim, sub_key = key.partition("__")
if key not in valid_params:
raise ValueError(
"Invalid parameter %s for estimator %s. "
"Check the list of available parameters "
"with `estimator.get_params().keys()`." % (key, self)
)
if delim:
nested_params[key][sub_key] = value
else:
setattr(self, key, value)
valid_params[key] = value
for key, sub_params in nested_params.items():
valid_params[key].set_params(**sub_params)
return self
분석에 사용되는 객체는 RandomForsetClassifier로 정했습니다.
# get_params를 사용해 현재 RandomForestClassifier에서 사용된 파라미터를 valid_params에 저장한다.
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier()
valid_params = rf.get_params()
valid_params
[out]
'''
{'bootstrap': True,
'ccp_alpha': 0.0,
'class_weight': None,
'criterion': 'gini',
'max_depth': None,
'max_features': 'auto',
'max_leaf_nodes': None,
'max_samples': None,
'min_impurity_decrease': 0.0,
'min_samples_leaf': 1,
'min_samples_split': 2,
'min_weight_fraction_leaf': 0.0,
'n_estimators': 100,
'n_jobs': None,
'oob_score': False,
'random_state': None,
'verbose': 0,
'warm_start': False}
'''
set_params를 하기위해서 적용할 새로운 파라미터를 만들어야하는데 만들기 귀찮으니까,
랜덤포레스트의 기존 파라미터를 카피하고 'ccp_alpha'부분만 1로 수정해주겠습니다.
params = valid_params.copy()
params['ccp_alpha'] = 1
params
[out]
'''
{'bootstrap': True,
'ccp_alpha': 1,
'class_weight': None,
'criterion': 'gini',
'max_depth': None,
'max_features': 'auto',
'max_leaf_nodes': None,
'max_samples': None,
'min_impurity_decrease': 0.0,
'min_samples_leaf': 1,
'min_samples_split': 2,
'min_weight_fraction_leaf': 0.0,
'n_estimators': 100,
'n_jobs': None,
'oob_score': False,
'random_state': None,
'verbose': 0,
'warm_start': False}
'''
- 그렇다면 이제 set_params를 사용하면 'ccp_alpha'의 값이 0에서 1로 바뀌어야 한다.
- 사이킷런은 파라미터의 값에서 '__'가 있는 경우를 위해 nested_params를 사용하는데, 아직까지 피쳐 값에 언더바 두개('__')가 있는 경우를 본적이 없습니다.
- partition() 함수를 사용하면 __기준으로 split됩니다.
dict_['abc__efg'] = 1
for i,k in dict_.items():
print(i.partition("__"))
[out]
'''
('abc', '__', 'efg')
'''
그리고 파라미터를 업데이트 하는 과정은 아래 코드 주석으로 설명하겠습니다.
# '__'가 있는 경우를 위해 빈 딕셔너리를 만듭니다
nested_params = defaultdict(dict)
# params는 적용하고 싶은 새 파라미터입니다.
# 값을 하나씩 for문 돌리면서 확인합니다.
for key, value in params.items():
print('key = ',key)
print('value = ', value)
# key를 __기준으로 분리합니다. key에 '__'가 없는 경우는 공백이 생깁니다
# ex) key = n_features
# key.partition('__') -> (n_features, "", "")
key, delim, sub_key = key.partition("__")
print('after partition_key ',key)
# 업데이트 하고 싶은 파라미터 key가 해당 분류가에서 지원하지 않으면 에러를 발생시킴
if key not in valid_params:
raise ValueError(
"Invalid parameter %s for estimator %s. "
"Check the list of available parameters "
"with `estimator.get_params().keys()`." % (key, rf)
)
# 업데이트 하고싶은 파라미터 key에 '__'가 포함되어서 delim값이 있는 경우
# nested_params를 업데이트함
if delim:
nested_params[key][sub_key] = value
print(nested_params)
# 아닌경우 rf.key를 value값으로 업데이트 합니다
# valid_params값과 rf의 get_params의 주소값이 같아서 아래와같은 방식으로 업데이트됩니다.
else:
setattr(rf, key, value)
valid_params[key] = value
print("=======================")
print('nested_params', nested_params)
# 현재는 nested_params에 아무값도 없기떄문에 아무일도 일어나지않습니다.
for key, sub_params in nested_params.items():
valid_params[key].set_params(**sub_params)
[out]
'''
key = bootstrap
value = True
after partition_key bootstrap
=======================
key = ccp_alpha
value = 1
after partition_key ccp_alpha
=======================
key = class_weight
value = None
after partition_key class_weight
=======================
key = criterion
value = gini
after partition_key criterion
=======================
key = max_depth
value = None
after partition_key max_depth
=======================
key = max_features
value = auto
after partition_key max_features
=======================
key = max_leaf_nodes
value = None
after partition_key max_leaf_nodes
=======================
key = max_samples
value = None
after partition_key max_samples
=======================
key = min_impurity_decrease
value = 0.0
after partition_key min_impurity_decrease
=======================
key = min_samples_leaf
value = 1
after partition_key min_samples_leaf
=======================
key = min_samples_split
value = 2
after partition_key min_samples_split
=======================
key = min_weight_fraction_leaf
value = 0.0
after partition_key min_weight_fraction_leaf
=======================
key = n_estimators
value = 100
after partition_key n_estimators
=======================
key = n_jobs
value = None
after partition_key n_jobs
=======================
key = oob_score
value = False
========================
nested_params defaultdict(<class 'dict'>, {})
'''
'''
이번 포스팅에서는 AutoSklearnClassifier에서 상속하는 BaseEstimator에 대해 분석했습니다.
다음 포스팅에서는 AutoSklearnClassifier를 세분화하여 알아보겠습니다.
'코드읽기 > auto-sklearn' 카테고리의 다른 글
[AutoML] 구현을 향해, AutoSklearnClassifeir.fit(2) - 5편 (0) | 2022.05.14 |
---|---|
[AutoML] 구현을 향해, AutoSklearnClassifier-fit - 4편 (0) | 2022.05.08 |
[AutoML] 구현을 향해, AutoSklearn-parameters - 3편 (0) | 2022.05.05 |
[AutoML]구현을 향해, AutoML? 그거 별거 없는거 아닌가? 1편 (0) | 2022.04.16 |