Eine speichereffizientere Methode für eine Hot-Coding-Spalte - Python 3.6.x.

Oct 28 2020

Ich habe eine Methode, mit der man eine Liste von Spalten aus einem pandasDatenrahmen heiß codiert und die ursprüngliche Spalte löscht. Während dies für einige Bereiche sehr schnell funktioniert, dauert dieser für andere unglaublich lange. Zum Beispiel arbeite ich derzeit an hochkategorialen Datensätzen (dh mehr als 80 kategorialen Features), bei denen mich ein einzelnes Feature in überdimensionale 100,000Dimensionen treibt .

Ich bin auf der Suche nach einer optimierten und speichereffizienten Routine für eine Hot-Codierung hochdimensionaler Daten.

Unten ist mein aktueller Ansatz:

# For each column to encode
for col in encode_cols:
    col_name = str(col)
    if col not in ('PRICE_AMOUNT', 'CHECKSUM_VALUE'):
        old_cols = df.shape[1]
        print("Now testing: {}".format(col_name))
        # Use pandas get_dummies function
        temp = pd.get_dummies(df[col], prefix=col_name, prefix_sep='_')
        df.drop(col, axis=1, inplace=True)
        df = pd.concat([df, temp], axis=1, join='inner')
        print("New Size: {}".format(df.shape))
        sizes[col] = df.shape[1] - old_cols
    else:
        continue
    
    del(temp)
    gc.collect()

In meinem Fall sind encode_colses nur etwa 75 Elemente, aber der Vektor geht von den 100Dimensionen bis zur 107,000Fertigstellung. Wie kann ich diese Routine optimieren?

Antworten

1 Marcus Oct 28 2020 at 19:56

Ohne Zugriff auf Ihre Daten kann ich Ihnen keinen voll funktionsfähigen Code zur Verfügung stellen, obwohl hier meine Gedanken sind. Bei sehr spärlichen, binären Features können spärliche Matrizen verwendet werden. Dies ist eine clevere (und sehr speichereffiziente) Methode zum Speichern von Daten.

Sie können dann OneHotEncodervon sklearn, wie hier erläutert , verwenden, um One-Hot-codierte spärliche , kategoriale Features zu generieren . In Ihrem Fall müssten Sie also für jedes kategoriale Merkmal alle seine Ebenen berechnen und diese verwenden, um die spärlichen Vektoren zu codieren.

vec = OneHotEncoder(n_values=n_of_levels_among_all_features)
X = vec.fit_transform(level_ids_data)
 
X.toarray() # To get it back to an "normal" nd-array.

Dann können Sie hstackwie hier beschrieben verwenden, um Ihre dichten Features ( PRICE_AMOUNT, CHECKSUM_VALUE) mit Ihren spärlichen Features zusammenzuführen.

from scipy.sparse import hstack

X = hstack((sparse_ohe_categorical_features, dense_features), format='csr')

Xist jetzt eine spärliche Matrix mit all Ihren Daten. Ändern Sie das Format csrje nach Anwendungsfall. Wenn Sie beispielsweise die logistische Regression von verwenden sklearn, müssen spärliche Matrizen im csrFormat vorliegen, damit die Anpassungsmethode funktioniert.

HotMailRob Oct 28 2020 at 19:53

Ich würde vorschlagen, das OneHotEncoder-Tool von scikit-learn zu verwenden.

from sklearn.preprocessing import OneHotEncoder

features_to_one_hot = ['feature1','feature2']
to_one_hot_df = df.loc[:,features_to_one_hot]

categorical_encoder = OneHotEncoder()
new_one_hot = cat_encoder.fit_transform(to_one_hot_df)

Wenn der Encoder spezifischere Aktionen ausführen soll, verwendet Scikit-learn die Ententypisierung. Das heißt, Sie können Ihre eigene Klasse implementieren. Hier zeige ich, wie Sie eine für den Encoder erstellen können, um die alten Spalten zu löschen:

from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.preprocessing import OneHotEncoder


class OneHotAndDrop(BaseEstimator, TransformerMixin):
    def __init__(self, operate=True):
        self.operate = operate

    def fit(self, X, y=None):
        return self

    def transform(self, X):

        if self.operate:
            old_columns = list(X.columns)
            new_one_hot = OneHotEncoder().fit_transform(X)
            X = new_one_hot.drop(old_columns, axis=1)
            
        return X

one_hot_costum = OneHotAndDrop()
new_one_hot = one_hot_costum.fit_transform(to_one_hot_df)

Sie können diese Klasse dann wie im ersten Beispiel verwenden. Diese Methode verwendet eine spärliche Matrix. Sie ist höchstwahrscheinlich weitaus effizienter als Ihre ursprüngliche Funktion und benennt die neuen Funktionen automatisch.

Außerdem ist eine Hot-Codierung möglicherweise nicht die beste Idee, je nachdem, warum Sie sie codieren müssen. Wenn es sich um maschinelles Lernen handelt, werden dadurch viel zu viele Funktionen erstellt und wahrscheinlich überpasst. Ich würde empfehlen, sie zuerst zu gruppieren und dann zu kategorisieren, um die Anzahl der neuen Funktionen zu verringern.