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.
--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)
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.
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.
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"
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.
Ü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
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