[PYTHON] Ich habe "K-Fold Target Encoding" ausprobiert.

Einführung

Von Ende 2019 bis Anfang 2020? Ich erinnere mich, dass die Zielcodierung ein heißes Thema wurde.

Die Zielcodierung ersetzt die kategoriale Variable durch den Durchschnittswert der Zielvariablen. Wenn Sie sie jedoch einfach verarbeiten, tritt ein Leck auf, sodass Sie sie erstellen müssen. Um Undichtigkeiten zu vermeiden, können Sie Maßnahmen ergreifen, z. B. die Methode "Auslassen", bei der der Durchschnittswert außer der zu konvertierenden Zeile verwendet wird, oder die K-fache Unterteilung und Ersetzung durch den anderen Durchschnittswert als die Falte, die die Zielbranche umfasst.

Es gibt weltweit viele Erklärungen zur Zielcodierung, daher werde ich sie in diesem Artikel nicht erläutern (z. B. diese Site. out-TS-% E4% BD% BF% E3% 81% A3% E3% 81% A1% E3% 82% 83% E3% 83% 80% E3% 83% A1) ist sehr hilfreich). In diesem Artikel versuche ich zu sehen, wie es funktioniert, indem ich den erstaunlichen Zielcodierungscode von [dieser Site] verwende (https://medium.com/@pouryaayria/k-fold-target-encoding-dfe9a594874b). Ich werde es versuchen.

Referenz

--Python: Verwendung der Zielcodierung (https://blog.amedama.jp/entry/target-mean-encoding-types#Leave-one-out-TS-%E4%BD%BF%E3%81%A3% E3% 81% A1% E3% 82% 83% E3% 83% 80% E3% 83% A1)

Verfahren

Beispieldatenrahmen

Eine Funktion, die einen Beispieldatenrahmen erstellt.

import numpy as np
import pandas as pd

def getRandomDataFrame(data, numCol):
    
    if data== 'train':
    
        key = ["A" if x ==0  else 'B' for x in np.random.randint(2, size=(numCol,))]
        value = np.random.randint(2, size=(numCol,))
        df = pd.DataFrame({'Feature':key, 'Target':value})
        return df
    
    elif data=='test':
        
        key = ["A" if x ==0  else 'B' for x in np.random.randint(2, size=(numCol,))]
        df = pd.DataFrame({'Feature':key})
        return df
    else:
        print(';)')

Sie können einen Datenrahmen mit dem folgenden Code generieren. Wenn als erstes Argument test angegeben wird, wird die Zielvariablenzeichenfolge nicht ausgegeben. Geben Sie die Anzahl der Zeilen im zweiten Argument an.

train = getRandomDataFrame('train', 10)
test = getRandomDataFrame('test', 10)

Der Inhalt ist in der folgenden Abbildung dargestellt. スクリーンショット 2020-01-22 23.37.22.png スクリーンショット 2020-01-22 23.37.32.png

K-fold Target Encoding K-fache Zielcodierungsklasse. Es hat "fit" und "transform", so dass es auf die gleiche Weise wie die Vorverarbeitung von sklern verwendet werden kann. Der Testcodierer verwendet das Zugdatenergebnis als Eingabe und fügt die Zielcodierungsfunktion hinzu. Zusätzlich wird der im Kommentar geschriebene Teil (1) verarbeitet, um die Linie zu füllen, die beim K-Falten mit dem Durchschnittswert nan wird. Wir werden das später sehen.

from sklearn import base
from sklearn.model_selection import KFold

class KFoldTargetEncoderTrain(base.BaseEstimator,
                               base.TransformerMixin):
    """How to use.
    targetc = KFoldTargetEncoderTrain('Feature','Target',n_fold=5)
    new_train = targetc.fit_transform(train)
    """
    def __init__(self,colnames,targetName,
                  n_fold=5, verbosity=True,
                  discardOriginal_col=False):
        self.colnames = colnames
        self.targetName = targetName
        self.n_fold = n_fold
        self.verbosity = verbosity
        self.discardOriginal_col = discardOriginal_col
        
    def fit(self, X, y=None):
        return self
    
    def transform(self,X):        
        assert(type(self.targetName) == str)
        assert(type(self.colnames) == str)
        assert(self.colnames in X.columns)
        assert(self.targetName in X.columns)       
        
        mean_of_target = X[self.targetName].mean()
        kf = KFold(n_splits = self.n_fold,
                   shuffle = False, random_state=2019)        
        col_mean_name = self.colnames + '_' + 'Kfold_Target_Enc'
        X[col_mean_name] = np.nan       
        
        for tr_ind, val_ind in kf.split(X):
            X_tr, X_val = X.iloc[tr_ind], X.iloc[val_ind]
            X.loc[X.index[val_ind], col_mean_name] = X_val[self.colnames].map(X_tr.groupby(self.colnames)[self.targetName].mean())
            X[col_mean_name].fillna(mean_of_target, inplace = True)  #Füllen Sie den Teil, der nan geworden ist, mit dem Durchschnittswert aus--(1)
            
        if self.verbosity:            
            encoded_feature = X[col_mean_name].values
            print('Correlation between the new feature, {} and, {} is {}.'.format(col_mean_name,self.targetName, 
                                                                                  np.corrcoef(X[self.targetName].values,encoded_feature)[0][1]))
        if self.discardOriginal_col:
            X = X.drop(self.targetName, axis=1)
        return X
    
    
class TargetEncoderTest(base.BaseEstimator, base.TransformerMixin):
    """How to use.
    test_targetc = TargetEncoderTest(new_train,
                                      'Feature',
                                      'Feature_Kfold_Target_Enc')
    new_test = test_targetc.fit_transform(test)
    """
    
    def __init__(self,train,colNames,encodedName):
        
        self.train = train
        self.colNames = colNames
        self.encodedName = encodedName
        
    def fit(self, X, y=None):
        return self
    
    def transform(self,X):       
        mean =  self.train[[self.colNames, self.encodedName]].groupby(self.colNames).mean().reset_index() 
        
        dd = {}
        for index, row in mean.iterrows():
            dd[row[self.colNames]] = row[self.encodedName]
            X[self.encodedName] = X[self.colNames]
        X = X.replace({self.encodedName: dd})
        return X

Verwenden Sie es wie folgt. Geben Sie im Konstruktor von "KFoldTargetEncoderTrain" den zu codierenden Spaltennamen der Kategorievariablen, den Spaltennamen der Zielvariablen und die Anzahl der Falten an. Geben Sie im Konstruktor von "TargetEncoderTest" den codierten Datenrahmen, den Spaltennamen der codierten kategorialen Variablenspalte und den Spaltennamen des Zielcodierten Funktionsbetrags an ([Name der codierten Spaltenspalte der kategorialen Variablen] _Kfold_Target_Enc).

targetc = KFoldTargetEncoderTrain('Feature','Target',n_fold=5)
new_train = targetc.fit_transform(train)

test_targetc = TargetEncoderTest(new_train, 'Feature', 'Feature_Kfold_Target_Enc')
new_test = test_targetc.fit_transform(test)

Jeder hat den folgenden Inhalt. スクリーンショット 2020-01-22 23.54.52.png スクリーンショット 2020-01-22 23.55.05.png

Lassen Sie uns new_train überprüfen. Da es sich um eine 5-fache handelt, werden die Daten in 5-fache, jeweils 2 Zeilen, unterteilt. Die erste Falte ist die erste und zweite Zeile von oben. Um die erste und zweite Zeile zu codieren, sehen Sie sich die kombinierten Daten der anderen vier Falten an, die Datensätze in den Zeilen 3-10. Der Durchschnittswert von "Ziel" in jeder Gruppe von A und B beträgt 3/4 = 0,75 für A und 1/4 = 0,25 für B. Verwenden Sie diesen Wert, um den Wert der ersten Falte zu codieren. Die erste und die zweite Zeile der ersten Falte sind beide A, codieren Sie also mit 0,75. Führen Sie das obige Verfahren für alle Falten durch.

Lassen Sie uns new_test überprüfen. Testdaten werden unter Verwendung des Durchschnittswerts der kategorialen Variablen codiert, die für die Zielcodierungsfunktion von Zugdaten codiert werden sollen. A ist (0,75 + 0,75 + 0,6 + 0,8 + 0,5 + 0,5) / 6 = 0,65 und B ist (0,3333333333333333 + 0,3333333333333333 + 0,0 + 0,0) / 4 = 0,166666666666666666.

Betrachten Sie als nächstes den Fall, Nan zu werden.

train = getRandomDataFrame('train', 10)
train['Feature'].iloc[0] = "C"
スクリーンショット 2020-01-23 0.12.34.png

Mit diesen Daten muss ich den Durchschnittswert der C-Gruppe in den verbleibenden Falten berechnen, um die erste Zeile zu codieren, aber in den verbleibenden Falten befindet sich kein C. Daher wird die Menge des Zielcodierungsmerkmals zu nan. Füllen Sie es daher mit dem Durchschnittswert der Zielvariablen aller Zeilen. Daher ist C (1 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 1 + 1) / 10 = 0,5.

スクリーンショット 2020-01-23 0.16.57.png

Übrigens, wenn Sie den Teil (1) auskommentieren, können Sie ihn als "np.nan" belassen. Mit LightGBM können Sie auch mit nan lernen und vorhersagen. Daher ist es möglicherweise besser, den Durchschnittswert nicht anzugeben.

Leave-one-out Target Encoding Es wird gesagt, dass diese Methode nicht verwendet werden sollte, da sie mehr als die K-fache Zielcodierung verliert. Ich werde den Code jedoch veröffentlichen, da es eine große Sache ist.

class LOOTargetEncoderTrain(base.BaseEstimator,
                               base.TransformerMixin):
    """How to use.
    targetc = LOOTargetEncoderTrain('Feature','Target')
    new_train = targetc.fit_transform(train)
    """
    def __init__(self,colnames,targetName,
                  verbosity=True, discardOriginal_col=False):
        self.colnames = colnames
        self.targetName = targetName
        self.verbosity = verbosity
        self.discardOriginal_col = discardOriginal_col
        
    def fit(self, X, y=None):
        return self
    
    def transform(self,X):        
        assert(type(self.targetName) == str)
        assert(type(self.colnames) == str)
        assert(self.colnames in X.columns)
        assert(self.targetName in X.columns)
        
        col_mean_name = self.colnames + '_' + 'Kfold_Target_Enc'
        X[col_mean_name] = np.nan
        self.agg_X = X.groupby(self.colnames).agg({self.targetName: ['sum', 'count']})
        X[col_mean_name] = X.apply(self._loo_ts, axis=1)
        
        return X
        
    def _loo_ts(self, row):
        group_ts = self.agg_X.loc[row[self.colnames]]
        loo_sum = group_ts.loc[(self.targetName, 'sum')] - row[self.targetName]
        loo_count = group_ts.loc[(self.targetName, 'count')] - 1
        return loo_sum / loo_count

abschließend

Diesmal habe ich K-Fold Target Encoding ausprobiert.

Wenn die Zielvariable binär ist, scheint es eine Möglichkeit zu geben, Überlernen zu verhindern, z. B. Glätten.

Recommended Posts

Ich habe "K-Fold Target Encoding" ausprobiert.
Ich habe versucht zu kratzen
Ich habe PyQ ausprobiert
Ich habe AutoKeras ausprobiert
Ich habe es mit Papiermühle versucht
Ich habe versucht, Django-Slack
Ich habe es mit Django versucht
Ich habe es mit Spleeter versucht
Ich habe es mit cgo versucht
Ich habe versucht, parametrisiert zu verwenden
Ich habe versucht, Argparse zu verwenden
Ich habe versucht, Mimesis zu verwenden
Ich habe versucht, anytree zu verwenden
Ich habe versucht, Pymc auszuführen
Ich habe ARP-Spoofing ausprobiert
Ich habe versucht, aiomysql zu verwenden
Ich habe versucht, Summpy zu verwenden
Ich habe Python> autopep8 ausprobiert
Ich habe versucht, Coturn zu verwenden
Ich habe versucht, Pipenv zu verwenden
Ich habe versucht, Matplotlib zu verwenden
Ich habe versucht, "Anvil" zu verwenden.
Ich habe versucht, Hubot zu verwenden
Ich habe versucht, ESPCN zu verwenden
Ich habe PyCaret2.0 (pycaret-nightly) ausprobiert.
Ich habe versucht, openpyxl zu verwenden
Ich habe versucht, tief zu lernen
Ich habe AWS CDK ausprobiert!
Ich habe versucht, Ipython zu verwenden
Ich habe versucht zu debuggen.
Ich habe versucht, PyCaret zu verwenden
Ich habe versucht, Cron zu verwenden
Ich habe Kivys Kartenansicht ausprobiert
Ich habe versucht, ngrok zu verwenden
Ich habe versucht, face_recognition zu verwenden
Ich habe versucht, Jupyter zu verwenden
Ich habe versucht, EfficientDet zu verschieben
Ich habe versucht, Shell zu programmieren
Ich habe versucht, doctest zu verwenden
Ich habe Python> Decorator ausprobiert
Ich habe versucht, TensorFlow auszuführen
Ich habe Auto Gluon ausprobiert
Ich habe versucht, Folium zu verwenden
Ich habe versucht, jinja2 zu verwenden
Ich habe AWS Iot ausprobiert
Ich habe die Bayes'sche Optimierung ausprobiert!
Ich habe versucht, Folium zu verwenden
Ich habe versucht, das Zeitfenster zu verwenden
Ich habe Value Iteration Networks ausprobiert
Ich habe fp-Wachstum mit Python versucht
Ich habe versucht, mit Python zu kratzen
Ich habe versucht, PredNet zu lernen
Ich habe versucht, mit Elasticsearch Ranking zu lernen!
[Ich habe versucht, Pythonista 3 zu verwenden] Einführung
Ich habe versucht, easydict (Memo) zu verwenden.
Ich habe versucht, SVM zu organisieren.
Ich habe versucht, das Gesicht mit Face ++ zu erkennen
Ich habe versucht, RandomForest zu verwenden