scikit-learn (또는 다른 파이썬 프레임 워크)을 사용하여 다른 종류의 회귀 변수 앙상블


27

회귀 작업을 해결하려고합니다. LassoLARS, SVR 및 Gradient Tree Boosting의 3 가지 모델이 서로 다른 데이터 하위 집합에 잘 작동한다는 것을 알았습니다. 나는이 3 가지 모델을 모두 사용하여 예측을 한 다음 '실제 출력'과 내 3 가지 모델의 출력 테이블을 만들 때마다 적어도 하나의 모델이 실제로 실제 출력에 가깝다는 것을 알았습니다. 비교적 멀리있을 수 있습니다.

가능한 최소 오차를 계산할 때 (각 테스트 예에 대해 '최상의'예측 변수로부터 예측을 얻는 경우) 모든 모델의 오차보다 훨씬 작은 오차가 발생합니다. 그래서 저는이 3 가지 다른 모델의 예측을 어떤 종류의 앙상블에 결합시키는 것에 대해 생각했습니다. 질문은, 이것을 올바르게하는 방법입니다. 내 3 가지 모델은 모두 scikit-learn을 사용하여 빌드 및 조정됩니다. 모델을 앙상블에 포장하는 데 사용할 수있는 방법이 있습니까? 여기서 문제는 세 가지 모델 모두의 평균 예측을 원하지 않고 가중치를 사용 하여이 작업을 수행하려는 것입니다. 여기서 가중치는 특정 예제의 속성을 기반으로 결정해야합니다.

scikit-learn이 그러한 기능을 제공하지 않더라도 누군가 가이 작업을 처리하는 방법을 알고 있다면 데이터의 각 예에 대한 각 모델의 가중치를 파악하는 것이 좋습니다. 나는이 3 가지 모델 위에 구축 된 별도의 회귀 분석을 통해 수행 될 수 있다고 생각합니다.이 모델은 3 가지 모델 각각에 대해 최적의 가중치를 출력하려고 시도하지만 이것이 최선의 방법인지 확실하지 않습니다.

답변:


32

실제로 scikit-learn는 구현하기가 약간 까다로울 수 있지만 이러한 기능을 제공합니다. 다음은 세 가지 모델 위에 구축 된 평균 회귀 분석기의 완전한 작동 예입니다. 먼저 필요한 모든 패키지를 가져 오십시오.

from sklearn.base import TransformerMixin
from sklearn.datasets import make_regression
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.neighbors import KNeighborsRegressor
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.linear_model import LinearRegression, Ridge

그런 다음 세 가지 회귀 모델을 변압기로 변환해야합니다. 그러면 다음을 사용하여 예측을 단일 피쳐 벡터로 병합 할 수 있습니다 FeatureUnion.

class RidgeTransformer(Ridge, TransformerMixin):

    def transform(self, X, *_):
        return self.predict(X)


class RandomForestTransformer(RandomForestRegressor, TransformerMixin):

    def transform(self, X, *_):
        return self.predict(X)


class KNeighborsTransformer(KNeighborsRegressor, TransformerMixin):

    def transform(self, X, *_):
        return self.predict(X)

이제 프랑켄슈타인 모델을위한 빌더 함수를 정의 해 봅시다 :

def build_model():
    ridge_transformer = Pipeline(steps=[
        ('scaler', StandardScaler()),
        ('poly_feats', PolynomialFeatures()),
        ('ridge', RidgeTransformer())
    ])

    pred_union = FeatureUnion(
        transformer_list=[
            ('ridge', ridge_transformer),
            ('rand_forest', RandomForestTransformer()),
            ('knn', KNeighborsTransformer())
        ],
        n_jobs=2
    )

    model = Pipeline(steps=[
        ('pred_union', pred_union),
        ('lin_regr', LinearRegression())
    ])

    return model

마지막으로 모델을 맞추겠습니다.

print('Build and fit a model...')

model = build_model()

X, y = make_regression(n_features=10, n_targets=2)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

model.fit(X_train, y_train)
score = model.score(X_test, y_test)

print('Done. Score:', score)

산출:

Build and fit a model...
Done. Score: 0.9600413867438636

그런 식으로 문제를 복잡하게하는 이유는 무엇입니까? 이 접근법을 사용하면 또는 scikit-learn과 같은 표준 모듈을 사용하여 모델 하이퍼 파라미터를 최적화 할 수 있습니다 . 또한 사전 훈련 된 모델을 디스크에서 쉽게 저장하고로드 할 수 있습니다.GridSearchCVRandomizedSearchCV


이 방법을 사용할 때 각 Algo가 언제 / 몇 분의 어떤 Algo가 사용되고 있는지 추출하는 간단한 방법이 있습니까?
David Hagan

결과 선형 모델 ( model.named_steps['lin_regr'].coef_) 의 계수를 보면 앙상블의 각 모델이 최종 솔루션에 얼마나 기여하는지에 대한 통찰력을 얻을 수 있습니다.
constt

@constt 기본 모델에서 cross_val_predict를 사용할 필요가 없습니까? 최상위 모델이 현재 구현되어 있으므로 기본 모델에서 지나치게 낙관적 인 신호를 얻는 것처럼 보입니다.
Brian Bien

1
이것은 단지 개념 증명의 예일뿐입니다. 여기서는 모델 선택을 다루지 않았습니다. 이러한 모델은 전체적으로 최적화되어야한다고 생각합니다. 즉, 교차 검증 방식을 사용하여 모든 내장 모델의 하이퍼 파라미터를 동시에 최적화해야합니다.
constt

n_targets = 1 X, y = make_regression(n_features=10, n_targets=1)을 입력하면 치수 오류가 발생합니다. 누구든지 무엇을해야하는지 설명해 주시겠습니까?
Mohit Yadav

9

좋아, 인터넷 검색에 시간을 보낸 후 scikit-learn을 사용하여 파이썬에서 가중치를 수행하는 방법을 알았습니다. 아래를 고려하십시오.

SVR, LassoLars 및 GradientBoostingRegressor와 같이 일련의 회귀 모델을 학습합니다. 그런 다음 훈련 데이터 (이 세 회귀 자 각각의 훈련에 사용 된 것과 동일한 데이터)에서 모두 실행합니다. 각 알고리즘으로 예를 예측하고 'predictedSVR', 'predictedLASSO'및 'predictedGBR'열이있는 팬더 데이터 프레임 에이 3 가지 결과를 저장합니다. 그리고 마지막 예측 열을이 예측에 추가하여 실제 예측 값인 'predicted'라고합니다.

그런 다음이 새로운 데이터 프레임에서 선형 회귀를 훈련시킵니다.

 #df - dataframe with results of 3 regressors and true output

 from sklearn linear_model
 stacker= linear_model.LinearRegression()
 stacker.fit(df[['predictedSVR', 'predictedLASSO', 'predictedGBR']], df['predicted'])

그래서 새로운 예를 예측하고 싶을 때 3 개의 회귀자를 각각 개별적으로 실행하면됩니다.

 stacker.predict() 

내 3 회귀 자의 출력에. 그리고 결과를 얻으십시오.

여기서 문제는 평균적으로 회귀 자에 대한 최적의 가중치를 찾는 것입니다. 가중치는 예측하려는 각 예제마다 동일합니다.

현재 예제의 기능을 사용하여 스태킹 (가중치)을 수행하는 방법에 대한 아이디어가 있다면 들으면 좋을 것입니다.


와우, 나는이 접근법을 매우 좋아합니다! 그러나 왜 모델 LinearRegression()대신에 사용 했 LogisticRegression()습니까?
harrison4

1
분류 작업이 아닌 회귀를 수행했기 때문에 @ harrison4? 그래서 각 모델의 출력을 '가중치'하고 싶었습니다. 어쨌든,이 나쁜 방법은 좋은 사람은 여기에 설명되어 있습니다 : stackoverflow.com/a/35170149/3633250
막심 Khaitovich을

네, 죄송합니다. 링크를 공유해 주셔서 감사합니다!
harrison4

5

데이터에 분명한 부분 집합이있는 경우 k- 평균과 같은 클러스터링 알고리즘을 실행 한 다음 각 분류기를 성능이 우수한 클러스터와 연관시킬 수 있습니다. 새 데이터 포인트가 도착하면 해당 클러스터가있는 클러스터를 판별하고 연관된 분류기를 실행하십시오.

또한 중심으로부터의 거리를 반대로하여 각 분류기에 대한 가중치 세트를 얻고 모든 분류기의 선형 조합을 사용하여 예측할 수 있습니다.


나는이 비슷한 상태를 테스트 한 종이를 발견했습니다 (유사한 아이디어와 비교) : paper
anthonybell 14

흥미로운 아이디어는 적용하기 위해 많은 작업이 필요합니다. 종이 주셔서 감사합니다!
Maksim Khaitovich

1

모든 모델이 완전히 훈련되고 잘 수행되면 다음을 수행하여 가중치 유형을 달성합니다.

  1. 보이지 않는 많은 테스트 데이터에서 모든 모델을 실행하십시오.
  2. 각 모델의 각 클래스에 대한 테스트 세트에 f1 점수를 저장하십시오.
  3. 앙상블로 예측할 때 각 모델은 가장 가능성있는 클래스를 제공하므로 해당 클래스의 해당 모델에 대한 f1 점수로 신뢰도 또는 확률을 가중합니다. 거리를 처리하는 경우 (예 : SVM에서와 같이) 거리를 정규화하여 일반적인 신뢰를 얻은 다음 클래스 별 f1 가중치를 진행하십시오.

일정 시간 동안 정확한 퍼센트를 측정하여 앙상블을 더 조정할 수 있습니다. 상당히 큰 새 데이터 세트에 점수가 매겨지면, 예를 들어, 해당 임계 값을 사용하여 점수를 매길 경우 정확한 백분율에 대해 임계 값을 0.1 단계로 플롯 할 수 있습니다. 클래스 1 등. 새 데이터가 들어 오면 테스트 세트 및 f1 점수를 계속 업데이트하고 드리프트를 추적하여 임계 값 또는 정확도가 떨어질 때 모델을 다시 빌드 할 수 있습니다.


1
흥미롭지 만 회귀 작업을 해결하려고하는 동안 분류 작업에 대해서만 작동합니다. 따라서 F1 점수를 계산할 수 없습니다.
Maksim Khaitovich
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.