Was macht Python -Slots?Was macht Python -Slots?
Bild von Autor | Leinwand

Was ist, wenn es eine Möglichkeit gibt, Ihren Python -Code schneller zu gestalten? __slots__ In Python ist es einfach zu implementieren und kann die Leistung Ihres Codes verbessern und gleichzeitig die Speicherverwendung reduzieren.

In diesem Artikel werden wir mithilfe eines Datenwissenschaftsprojekts aus der realen Welt, in dem Allegro dies als Herausforderung für den Rekrutierungsprozess für Datenwissenschaften nutzt, durchlaufen. Bevor wir uns jedoch mit diesem Projekt befassen, lassen Sie uns ein solides Verständnis dafür aufbauen, was __slots__ tut.

Was ist __slots__ in Python?

In Python hält jedes Objekt ein Wörterbuch seiner Attribute. Auf diese Weise können Sie sie hinzufügen, ändern oder löschen, aber es ist auch mit Kosten erhältlich: zusätzlicher Speicher und langsamerer Attributzugriff.
Der __slots__ Die Erklärung sagt Python, dass dies die einzigen Attribute sind, die dieses Objekt jemals benötigen wird. Es ist eine Artwork Einschränkung, aber es wird uns Zeit retten. Lassen Sie uns mit einem Beispiel sehen.

class WithoutSlots:
    def __init__(self, title, age):
        self.title = title
        self.age = age

class WithSlots:
    __slots__ = ('title', 'age')

    def __init__(self, title, age):
        self.title = title
        self.age = age

In der zweiten Klasse, __slots__ fordert Python an, für jedes Objekt kein Wörterbuch zu erstellen. Stattdessen reserviert es einen festen Punkt im Speicher für den Namen und die Alterswerte, wodurch er schneller und die Speicherverwendung verringert wird.

Warum benutzen __slots__?

Lassen Sie uns nun den Grund nennen, warum Sie verwenden sollten __slots__.

  • Speicher: Objekte nehmen weniger Platz ein, wenn Python ein Wörterbuch erstellt.
  • Geschwindigkeit: Der Zugriff auf Werte ist schneller, da Python weiß, wo jeder Wert gespeichert ist.
  • Bugs: Diese Struktur vermeidet stille Fehler, da nur die definierten erlaubt sind.

Verwenden Sie die Information Science Problem von Allegro als Beispiel

In diesem Datenprojekt forderte Allegro Information Science -Kandidaten auf, Laptoppreise durch Erstellen von Modellen für maschinelles Lernen vorherzusagen.

Ein echtes Datenprojekt zum Verständnis von Python -SlotsEin echtes Datenprojekt zum Verständnis von Python -Slots

Hyperlink zu diesem Datenprojekt: https://platform.stratascratch.com/data-projects/laptop-price-prediction

Es gibt drei verschiedene Datensätze:

  • Train_dataset.json
  • val_dataset.json
  • test_dataset.json

Intestine. Fahren wir mit dem Datenexplorationsprozess fort.

Datenexploration

Laden wir nun einen von ihnen, um die Struktur des Datensatzes zu sehen.

with open('train_dataset.json', 'r') as f:
    train_data = json.load(f)
df = pd.DataFrame(train_data).dropna().reset_index(drop=True)
df.head()

Hier ist die Ausgabe.

Python Slots BeispielPython Slots Beispiel

Intestine, lass uns die Spalten sehen.

Hier ist die Ausgabe.

Python Slots BeispielPython Slots Beispiel

Lassen Sie uns nun die numerischen Spalten überprüfen.

Hier ist die Ausgabe.

Python Slots BeispielPython Slots Beispiel

Datenexploration mit __slots__ gegen reguläre Klassen

Lassen Sie uns eine Klasse namens SlottedDataExploration erstellen, die das verwenden wird __slots__ Attribut. Es ermöglicht nur ein Attribut namens DF. Lassen Sie uns den Code sehen.

class SlottedDataExploration:
    __slots__ = ('df')

    def __init__(self, df):
        self.df = df

    def data(self):
        return self.df.data()

    def head(self, n=5):
        return self.df.head(n)

    def tail(self, n=5):
        return self.df.tail(n)

    def describe(self):
        return self.df.describe(embrace="all")

Lassen Sie uns nun die Implementierung sehen und anstatt zu verwenden __slots__ Verwenden wir reguläre Klassen.

class DataExploration:
    def __init__(self, df):
        self.df = df

    def data(self):
        return self.df.data()

    def head(self, n=5):
        return self.df.head(n)

    def tail(self, n=5):
        return self.df.tail(n)

    def describe(self):
        return self.df.describe(embrace="all")

Sie können mehr darüber erfahren, wie Klassenmethoden dabei funktionieren Python -Klassenmethoden Führung.

Leistungsvergleich: Zeitbenchmark

Messen wir nun die Leistung, indem wir Zeit und Speicher messen.

import time
from pympler import asizeof  # reminiscence measurement

start_normal = time.time()
de = DataExploration(df)
_ = de.head()
_ = de.tail()
_ = de.describe()
_ = de.data()
end_normal = time.time()
normal_duration = end_normal - start_normal
normal_memory = asizeof.asizeof(de)

start_slotted = time.time()
sde = SlottedDataExploration(df)
_ = sde.head()
_ = sde.tail()
_ = sde.describe()
_ = sde.data()
end_slotted = time.time()
slotted_duration = end_slotted - start_slotted
slotted_memory = asizeof.asizeof(sde)

print(f"⏱️ Regular class length: {normal_duration:.4f} seconds")
print(f"⏱️ Slotted class length: {slotted_duration:.4f} seconds")

print(f"📦 Regular class reminiscence utilization: {normal_memory:.2f} bytes")
print(f"📦 Slotted class reminiscence utilization: {slotted_memory:.2f} bytes")

Jetzt sehen wir das Ergebnis.

Python Slots BeispielPython Slots Beispiel

Die Dauer der Schlitzklassen beträgt 46,45% schneller, aber die Speicherverwendung ist für dieses Beispiel dieselbe.

Maschinelles Lernen in Aktion

Lassen Sie uns nun in diesem Abschnitt mit dem maschinellen Lernen fortfahren. Aber bevor wir dies tun, machen wir einen Zug und testen wir.

Trainieren und testen aufgeteilt

Jetzt haben wir drei verschiedene Datensätze, Zug, Val und Take a look at, additionally finden wir zuerst ihre Indizes.

train_indeces = train_df.dropna().index
val_indeces = val_df.dropna().index
test_indeces = test_df.dropna().index

Jetzt ist es Zeit, diese Indizes zuzuweisen, um diese Datensätze im nächsten Schritt problemlos auszuwählen.

train_df = new_df.loc(train_indeces)
val_df = new_df.loc(val_indeces)
test_df = new_df.loc(test_indeces)

Großartig, jetzt formatieren wir diese Datenrahmen, weil Numpy das flache (n,) Format anstelle von
die (n, 1). Dazu müssen wir .Ravel () nach to_numpy () verwenden.

X_train, X_val, X_test = train_df(selected_features).to_numpy(), val_df(selected_features).to_numpy(), test_df(selected_features).to_numpy()
y_train, y_val, y_test = df.loc(train_indeces)(label_col).to_numpy().ravel(), df.loc(val_indeces)(label_col).to_numpy().ravel(), df.loc(test_indeces)(label_col).to_numpy().ravel()

Anwendung maschineller Lernmodelle

import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error 
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.ensemble import ExtraTreesRegressor
from sklearn.ensemble import VotingRegressor
from sklearn import linear_model
from sklearn.neural_network import MLPRegressor
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler, MaxAbsScaler
import matplotlib.pyplot as plt
from sklearn import tree
import seaborn as sns
def rmse(y_true, y_pred): 
    return mean_squared_error(y_true, y_pred, squared=False)
def regression(regressor_name, regressor):
    pipe = make_pipeline(MaxAbsScaler(), regressor)
    pipe.match(X_train, y_train) 
    predicted = pipe.predict(X_test)
    rmse_val = rmse(y_test, predicted)
    print(regressor_name, ':', rmse_val)
    pred_df(regressor_name+'_Pred') = predicted
    plt.determine(regressor_name)
    plt.title(regressor_name)
    plt.xlabel('predicted')
    plt.ylabel('precise')
    sns.regplot(y=y_test,x=predicted)

Als nächstes werden wir ein Wörterbuch der Regressoren definieren und jedes Modell ausführen.

regressors = {
    'Linear' : LinearRegression(),
    'MLP': MLPRegressor(random_state=42, max_iter=500, learning_rate="fixed", learning_rate_init=0.6),
    'DecisionTree': DecisionTreeRegressor(max_depth=15, random_state=42),
    'RandomForest': RandomForestRegressor(random_state=42),
    'GradientBoosting': GradientBoostingRegressor(random_state=42, criterion='squared_error',
                                                  loss="squared_error",learning_rate=0.6, warm_start=True),
    'ExtraTrees': ExtraTreesRegressor(n_estimators=100, random_state=42),
}
pred_df = pd.DataFrame(columns =("Precise"))
pred_df("Precise") = y_test
for key in regressors.keys():
    regression(key, regressors(key))

Hier sind die Ergebnisse.

Python Slots BeispielPython Slots Beispiel

Implementieren Sie dies nun sowohl mit Slots als auch mit regulären Klassen.

Maschinelles Lernen mit __slots__ gegen reguläre Klassen

Überprüfen Sie nun den Code mit Slots.

class SlottedMachineLearning:
    __slots__ = ('X_train', 'y_train', 'X_test', 'y_test', 'pred_df')

    def __init__(self, X_train, y_train, X_test, y_test):
        self.X_train = X_train
        self.y_train = y_train
        self.X_test = X_test
        self.y_test = y_test
        self.pred_df = pd.DataFrame({'Precise': y_test})

    def rmse(self, y_true, y_pred):
        return mean_squared_error(y_true, y_pred, squared=False)

    def regression(self, title, mannequin):
        pipe = make_pipeline(MaxAbsScaler(), mannequin)
        pipe.match(self.X_train, self.y_train)
        predicted = pipe.predict(self.X_test)
        self.pred_df(title + '_Pred') = predicted

        rating = self.rmse(self.y_test, predicted)
        print(f"{title} RMSE:", rating)

        plt.determine(figsize=(6, 4))
        sns.regplot(x=predicted, y=self.y_test, scatter_kws={"s": 10})
        plt.xlabel('Predicted')
        plt.ylabel('Precise')
        plt.title(f'{title} Predictions')
        plt.grid(True)
        plt.present()

    def run_all(self):
        fashions = {
            'Linear': LinearRegression(),
            'MLP': MLPRegressor(random_state=42, max_iter=500, learning_rate="fixed", learning_rate_init=0.6),
            'DecisionTree': DecisionTreeRegressor(max_depth=15, random_state=42),
            'RandomForest': RandomForestRegressor(random_state=42),
            'GradientBoosting': GradientBoostingRegressor(random_state=42, learning_rate=0.6, warm_start=True),
            'ExtraTrees': ExtraTreesRegressor(n_estimators=100, random_state=42)
        }

        for title, mannequin in fashions.gadgets():
            self.regression(title, mannequin)

Hier ist die reguläre Klassenanwendung.

class MachineLearning:
    def __init__(self, X_train, y_train, X_test, y_test):
        self.X_train = X_train
        self.y_train = y_train
        self.X_test = X_test
        self.y_test = y_test
        self.pred_df = pd.DataFrame({'Precise': y_test})

    def rmse(self, y_true, y_pred):
        return mean_squared_error(y_true, y_pred, squared=False)

    def regression(self, title, mannequin):
        pipe = make_pipeline(MaxAbsScaler(), mannequin)
        pipe.match(self.X_train, self.y_train)
        predicted = pipe.predict(self.X_test)
        self.pred_df(title + '_Pred') = predicted

        rating = self.rmse(self.y_test, predicted)
        print(f"{title} RMSE:", rating)

        plt.determine(figsize=(6, 4))
        sns.regplot(x=predicted, y=self.y_test, scatter_kws={"s": 10})
        plt.xlabel('Predicted')
        plt.ylabel('Precise')
        plt.title(f'{title} Predictions')
        plt.grid(True)
        plt.present()

    def run_all(self):
        fashions = {
            'Linear': LinearRegression(),
            'MLP': MLPRegressor(random_state=42, max_iter=500, learning_rate="fixed", learning_rate_init=0.6),
            'DecisionTree': DecisionTreeRegressor(max_depth=15, random_state=42),
            'RandomForest': RandomForestRegressor(random_state=42),
            'GradientBoosting': GradientBoostingRegressor(random_state=42, learning_rate=0.6, warm_start=True),
            'ExtraTrees': ExtraTreesRegressor(n_estimators=100, random_state=42)
        }

        for title, mannequin in fashions.gadgets():
            self.regression(title, mannequin)

Leistungsvergleich: Zeitbenchmark

Vergleichen wir jetzt jeden Code mit dem, den wir im vorherigen Abschnitt gemacht haben.

import time

start_normal = time.time()
ml = MachineLearning(X_train, y_train, X_test, y_test)
ml.run_all()
end_normal = time.time()
normal_duration = end_normal - start_normal
normal_memory = (
    ml.X_train.nbytes +
    ml.X_test.nbytes +
    ml.y_train.nbytes +
    ml.y_test.nbytes
)

start_slotted = time.time()
sml = SlottedMachineLearning(X_train, y_train, X_test, y_test)
sml.run_all()
end_slotted = time.time()
slotted_duration = end_slotted - start_slotted
slotted_memory = (
    sml.X_train.nbytes +
    sml.X_test.nbytes +
    sml.y_train.nbytes +
    sml.y_test.nbytes
)

print(f"⏱️ Regular ML class length: {normal_duration:.4f} seconds")
print(f"⏱️ Slotted ML class length: {slotted_duration:.4f} seconds")

print(f"📦 Regular ML class reminiscence utilization: {normal_memory:.2f} bytes")
print(f"📦 Slotted ML class reminiscence utilization: {slotted_memory:.2f} bytes")

time_diff = normal_duration - slotted_duration
percent_faster = (time_diff / normal_duration) * 100
if percent_faster > 0:
    print(f"✅ Slotted ML class is {percent_faster:.2f}% quicker than the common ML class.")
else:
    print(f"ℹ️ No velocity enchancment with slots on this run.")

memory_diff = normal_memory - slotted_memory
percent_smaller = (memory_diff / normal_memory) * 100
if percent_smaller > 0:
    print(f"✅ Slotted ML class makes use of {percent_smaller:.2f}% much less reminiscence than the common ML class.")
else:
    print(f"ℹ️ No reminiscence financial savings with slots on this run.")

Hier ist die Ausgabe.

Python Slots BeispielPython Slots Beispiel

Abschluss

Durch Verhinderung der Schaffung von Dynamik __dict__ Für jeden Fall Python __slots__ sind sehr intestine darin, die Speicherverwendung zu reduzieren und das Attributzugriff zu beschleunigen. Sie haben gesehen, wie es in der Praxis sowohl durch Datenerforschung als auch durch maschinelle Lernaufgaben mit dem Actual Recruitment -Projekt von Allegro funktioniert.

In kleinen Datensätzen können die Verbesserungen gering sein. Da Daten jedoch skaliert werden, werden die Vorteile jedoch auffälliger, insbesondere in Speicher- oder leistungskritischen Anwendungen.

Nate Rosidi ist Datenwissenschaftler und in Produktstrategie. Er ist außerdem eine zusätzliche Professorin für Lehranalysen und Gründer von Stratascratch, einer Plattform, die Datenwissenschaftlern hilft, sich auf ihre Interviews mit echten Interviewfragen von High -Unternehmen vorzubereiten. Nate schreibt über die neuesten Traits auf dem Karrieremarkt, gibt Interviewberatung, teilt Datenwissenschaftsprojekte und deckt alles SQL ab.



Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert