Scikit-learn (veya başka herhangi bir python çerçevesini) kullanarak farklı tipte regresörlerin topluluğu


27

Regresyon görevini çözmeye çalışıyorum. 3 modelin farklı veri alt kümeleri için iyi çalıştığını öğrendim: LassoLARS, SVR ve Gradient Tree Boostting. Tüm bu 3 modeli kullanarak tahminlerde bulunduğumda ve sonra 'gerçek çıktı' tablosu yaptığımda ve 3 modelimin çıktılarını gördüğümde, modellerin en az birinin gerçekten gerçek çıktıya yakın olduğunu gördüm, ancak diğer iki model nispeten uzak olabilir.

Minimum olası hatayı hesapladığımda (her test örneği için 'en iyi' öngörücüsünden tahmin alırsam), yalnızca herhangi bir modelin hatasından daha küçük bir hata alıyorum. Bu yüzden, bu 3 farklı modelin tahminlerini bir takım topluluğa birleştirmeyi denemeyi düşündüm. Soru şu, bunu doğru şekilde nasıl yapacaksınız? Tüm 3 modellerim, scikit-learn kullanılarak oluşturuldu ve ayarlandı, modelleri bir araya getirmek için kullanılabilecek bir yöntem sunuyor mu? Buradaki sorun, üç modelin hepsinden sadece ortalama tahminleri istememek, bunu belirli bir örneğin özelliklerine göre ağırlıklandırmanın belirleneceği ağırlıklandırma ile yapmak istiyorum.

Scikit-learn böyle bir işlevsellik sağlamazsa bile, birisinin bu görevi nasıl ele alacağını bilmesi - verilerdeki her bir örnek için her bir modelin ağırlığını bulmak güzel olur. Tüm bu 3 modelin üzerine inşa edilen ve her 3 model için en uygun ağırlıkları elde edecek olan ayrı bir regresör tarafından yapılabileceğini düşünüyorum, ancak bunun en iyi yol olup olmadığından emin değilim.

Yanıtlar:


32

Aslında, scikit-learnuygulanması biraz zor olsa da, böyle bir işlevsellik sağlar. İşte üç modelin üzerine inşa edilmiş ortalama bir regresörün eksiksiz bir çalışma örneği. Öncelikle gerekli tüm paketleri alalım:

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

Ardından, üç regresör modelimizi transformatörlere dönüştürmemiz gerekiyor. Bu, tahminlerini aşağıdakileri kullanarak tek bir özellik vektöründe birleştirmemize olanak sağlar 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)

Şimdi frankenstein modelimiz için bir yapıcı işlevi tanımlayalım:

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

Son olarak, modele uyalım:

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)

Çıktı:

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

Neden işleri karmaşık bir şekilde rahatsız ediyorsun? Peki, bu yaklaşım, ya da scikit-learngibi standart modülleri kullanarak model hiperparametreleri optimize etmemize izin verir . Ayrıca, önceden eğitilmiş bir modeli kolayca diskten kaydetmek ve yüklemek mümkündür.GridSearchCVRandomizedSearchCV


Bu yaklaşımı kullanırken, her bir algo kesiminin ne zaman / hangi kesirinde kullanıldığını algılamanın basit bir yolu var mı?
David Hagan

Belki de sonuçta elde edilen doğrusal modelin ( model.named_steps['lin_regr'].coef_) katsayılarına bakmak, bir topluluktaki her bir modelin nihai çözüme ne kadar katkıda bulunduğuna dair bazı bilgiler verecektir.
constt

@ constt Temel modellerde cross_val_predict kullanmanıza gerek yok mu? Üst seviye modeliniz, halihazırda uygulandığı haliyle, temel modelinizden aşırı kapsamlı bir sinyal alacaktır.
Brian Bien,

1
Bu sadece bir çeşit kavram kanıtı örneği, burada bir model seçimine değinmedim. Bu tür modellerin bir bütün olarak optimize edilmesi gerektiğini düşünüyorum, yani tüm yerleşik modellerin hiper parametrelerinin çapraz doğrulama yaklaşımını kullanarak aynı anda optimize edilmesi gerektiğini düşünüyorum.
constt

n_targets = 1 koyarsak X, y = make_regression(n_features=10, n_targets=1)boyut hatası verir. Birisi lütfen ne yapacağımı açıklayabilir mi?
Mohit Yadav

9

Tamam, googling için biraz zaman geçirdikten sonra, pykitte ağırlıklamayı scikit-learn ile bile yapabileceğimi öğrendim. Aşağıdakini düşünün:

Bir dizi regresyon modelini eğitiyorum (SVR, LassoLars ve GradientBoostingRegressor'da belirtildiği gibi). Sonra hepsini eğitim verileri üzerinde çalıştırıyorum (bu 3 regresörün her birinin eğitimi için kullanılan verilerle aynı). Her algoritmamla ilgili örnekler için tahminler alıyorum ve bu 3 sonucu 'öngörülenSVR', 'predictedLASSO' ve 'öngörülen GBR' sütunlarıyla pandaların veri çerçevesine kaydediyorum. Ve son sütunu, gerçek bir tahmin değeri olan 'tahmini' olarak adlandırdığım bu veri alanına ekledim.

Sonra sadece bu yeni veri karesine doğrusal bir regresyon öğretirim:

 #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'])

Bu nedenle, yeni bir örnek için bir tahmin yapmak istediğimde, sadece 3 regresörümün her birini ayrı ayrı çalıştırıyorum ve sonra:

 stacker.predict() 

3 regülatörümün çıkışlarında. Ve bir sonuç alın.

Buradaki sorun, ortalama olarak regresörlerin ortalama ağırlıklarını bulmak olduğumda, ağırlık tahmininde bulunacağım her örnek için aynı olacaktır.

Birisi, mevcut örneğin özelliklerini kullanarak istifleme (ağırlıklandırma) konusunda herhangi bir fikri varsa, bunları duymak güzel olurdu.


Vay, bu yaklaşımı çok seviyorum! Peki model LinearRegression()yerine neden kullandın LogisticRegression()?
harrison4

1
@ harrison4 çünkü sınıflandırma görevi değil, regresyon yapıyordum? Bu yüzden her modelden çıktı 'ağırlık' istedim. Her neyse, bu kötü bir yaklaşım, burada iyi anlatılıyor: stackoverflow.com/a/35170149/3633250
Maksim Khaitovich

Evet, üzgünüm haklısın! bağlantıyı paylaştığınız için teşekkür ederiz!
harrison4

5

Verileriniz belirgin alt kümelere sahipse, k-means gibi bir kümeleme algoritması çalıştırabilir ve ardından her sınıflandırıcıyı iyi çalıştığı kümelerle ilişkilendirebilirsiniz. Yeni bir veri noktası geldiğinde, hangi kümede olduğunu belirleyin ve ilişkili sınıflandırıcıyı çalıştırın.

Her sınıflandırıcı için bir ağırlık seti almak ve aynı zamanda tüm sınıflandırıcıların doğrusal bir kombinasyonunu kullanmayı tahmin etmek için merkezlerin ters uzaklıklarını da kullanabilirsiniz.


Bu durumu test eden bir makale buldum (benzer fikirlerin karşılaştırılmasıyla birlikte): paper
anthonybell

İlginç bir fikir olsa da, itiraz etmek için çok çalışma gerektirir. Kağıt için teşekkürler!
Maksim Khaitovich

1

Tüm modelleriniz tamamen eğitilip iyi performans gösterdikten sonra, aşağıdakileri yaparak bir ağırlıklandırma yaparım:

  1. Tüm modellerinizi büyük bir görünmeyen test verisi setinde çalıştırın
  2. Her bir model için, her sınıf için belirlenen testte f1 puanlarını saklayın.
  3. Toplulukla ilgili öngörüde bulunduğunuzda, her model size en olası sınıfı verecektir, bu nedenle o sınıftaki o model için f1 puanının güven veya olasılığını değerlendirin. Mesafeyle uğraşıyorsanız (örneğin SVM'deki gibi), genel bir güven almak için mesafeleri normalleştirin ve ardından f1 ağırlık sınıfına göre devam edin.

Bir süre içinde doğru yüzde oranını ölçerek grubunuzu daha fazla ayarlayabilirsiniz. Önemli miktarda büyük, yeni bir veri kümesine sahip olduğunuzda, eşiği 0,1'lik adımlarla çizebilirsiniz; örneğin, eşik değerinin% 95 doğru olduğunu size söyleyeceği hakkında bir fikir edinmek için, eğer eşiği puanlamak için kullanıyorsanız, yüzde doğru sınıf 1 ve benzerleri için. Test setini ve f1 puanlarını güncellemeye devam ederek yeni veriler gelir ve sürüklenmeyi takip eder, eşikler veya doğruluk düştüğünde modelleri yeniden kurar.


1
Bu ilginç, ancak regresyon görevini çözmeye çalışırken yalnızca gördüğüm kadarıyla sınıflandırma işleri için çalışıyor. Böylece F1 skorunu hesaplayamıyorum.
Maksim Khaitovich
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.