0 Daumen
513 Aufrufe

Ich versuche eine Methode der Einlage von Sätzen anzuwenden, [InferSent] [1], die semantische Darstellungen von Sätzen liefert. Es wird in den Inferenzdaten natürlicher Sprache trainiert und verallgemeinert sich in vielen verschiedenen Aufgaben.

Der Prozess ist wie folgt:

Erstellen Sie ein Vokabular aus den Trainingsdaten und verwenden Sie dieses Vokabular, um das betreffende Modell zu trainieren. Sobald das Modell trainiert ist, geben Sie einen Satz als Eingabe für die Encoderfunktion an, die unabhängig von der Anzahl der Wörter im Satz einen Vektor mit 4096 Dimensionen zurückgibt.



In meinem Fall gibt es jedoch 130319 Fragen zu kodieren, und daher nimmt die Funktion des Kodierers viel Zeit in Anspruch. Ich frage mich, ob es irgendeinen Weg gibt, es zu beschleunigen.

 

    # Load model
    from models import InferSent
    MODEL_PATH =  '../new_models/infersent1.pkl'
    params_model = {'bsize': 64, 'word_emb_dim': 300, 'enc_lstm_dim': 2048,
                    'pool_type': 'max', 'dpout_model': 0.0, 'version': 1}
    model = InferSent(params_model)
   
    model.load_state_dict(torch.load('InferSent/encoder/infersent1.pkl'))
   
    W2V_PATH = 'InferSent/dataset/GloVe/glove.840B.300d.txt'
    model.set_w2v_path(W2V_PATH)

    model.build_vocab_k_words(K=100000)

    # encode questions
    questions = list(df["question"])



Das ist, wenn ich code. Ich habe einen Timer für die Prognosen hinzugefügt:

    import time
   
    t0 = time.time()
    for i in range(len(questions)):
        if i%1000 == 0:
            t1 = time.time()
            total = t1-t0
            print("encoding number ",i," time since beginning:", total)
        dict_embeddings[questions[i]] = model.encode([questions[i]], tokenize=True)


Dann gibt es mir in den ersten 1000 Iterationen:

 

    encoding number  0  time since beginning: 0.00016880035400390625
    encoding number  1000  time since beginning: 228.6366264820099


Wenn wir gut von Sekunde sprechen, mit 130000 Iterationen, schätze ich die Zeit für 8 Stunden 14 Minuten. Was wirklich zu lang ist. Deshalb versucht man diesen Zyklus zu optimieren.

Reproduzierbares Beispiel

Um ein reproduzierbares Beispiel zu geben, hier ist, wie ich zu den "Sätzen" komme, die ich verwende:

    # load json file
    train = pd.read_json("data/train-v2.0.json")
    # add data to a dataframe
    contexts = []
    questions = []
    answers_text = []
    answers_start = []
    for i in range(train.shape[0]):
        topic = train.iloc[i,0]['paragraphs']
        for sub_para in topic:
            for q_a in sub_para['qas']:
                questions.append(q_a['question'])
                if q_a['answers']:
                    answers_start.append(q_a['answers'][0]['answer_start'])
                    answers_text.append(q_a['answers'][0]['text'])
                elif q_a['plausible_answers']:
                    answers_start.append(q_a['plausible_answers'][0]['answer_start'])
                    answers_text.append(q_a['plausible_answers'][0]['text'])
                contexts.append(sub_para['context'])
    df = pd.DataFrame({"context":contexts, "question": questions, "answer_start": answers_start, "text": answers_text})
    # load data in csv file
    df.to_csv("data/train.csv", index = None)
    # Create dictionary of sentence embeddings for faster computation
    paras = list(df["context"].drop_duplicates().reset_index(drop= True))
    blob = TextBlob(" ".join(paras))
    sentences = [item.raw for item in blob.sentences]



Sie finden die Daten auf [der Stanford-Frage-Antwort-Datensatz github] [2].


  [1]: https://github.com/facebookresearch/InferSent/blob/master/encoder/demo.ipynb
  [2]: https://rajpurkar.github.io/SQuAD-explorer/

Avatar von

1 Antwort

0 Daumen

Antwort mit KI erzeugt:

Wie beschleunigt man eine Encoder-Funktion?

Die Beschleunigung einer Encoder-Funktion, insbesondere in einem NLP-Kontext wie dem von InferSent zur semantischen Darstellung von Sätzen, kann auf verschiedene Arten erreicht werden. Die Schlüsselaspekte zur Optimierung der Performance umfassen Hardwarebeschleunigung, Stapelverarbeitung, effiziente Datenverarbeitung und parallele Verarbeitung. Nachfolgend finden Sie einige Ansätze zur Beschleunigung der Encoder-Funktion:

1. Stapelverarbeitung (Batch Processing): Das sequenzielle Verarbeiten einzelner Sätze kann sehr ineffizient sein, vor allem wegen dem Overhead, der durch die Modellinitialisierung für jede Vorhersage entsteht. Stattdessen sollten die Sätze in Batches gruppiert und gemeinsam verarbeitet werden. InferSent unterstützt die Verarbeitung von Batch-Daten, was die Laufzeit erheblich reduzieren kann.

2. GPU-Beschleunigung: Die Verwendung einer GPU (Graphics Processing Unit) kann die Berechnungszeit dramatisch verkürzen. Die meisten modernen Deep-Learning-Frameworks, einschließlich PyTorch (das von InferSent verwendet wird), unterstützen GPU-Beschleunigung. Stellen Sie sicher, dass Ihr Modell und Ihre Daten auf der GPU sind.

3. Asynchrone Verarbeitung: Die asynchrone Verarbeitung kann genutzt werden, um die CPU- und GPU-Auslastung zu optimieren. Während ein Satz (oder ein Batch von Sätzen) auf der GPU kodiert wird, kann die CPU für Datenvorbereitungsaufgaben eingesetzt werden.

4. Optimierung der Datenpipeline: Die Effizienz des Datenladens und der Vorverarbeitung ist ebenfalls kritisch für die Gesamtperformance. Verwenden Sie effiziente Datenstrukturen und vermeiden Sie unnötige Datenmanipulationen.

5. Verwendung einer effizienteren Vektorisierungsmethode: Überprüfen Sie, ob die Wortvektoren und Satzdarstellungen so effizient wie möglich gehandhabt werden. Die model.encode Methode wird möglicherweise effizienter, wenn sie weniger Zugriffe auf den Datenträger erfordert und Datenstrukturen verwendet, die für den schnellen Zugriff optimiert sind.

6. Parallelisierung: Wenn Sie über eine Maschine mit mehreren CPUs oder mehreren GPU-Kernen verfügen, könnten Sie den Kodierungsprozess parallelisieren. Python bietet mehrere Möglichkeiten zur Parallelisierung von Aufgaben, darunter die multiprocessing und concurrent.futures Module. Jedoch ist darauf zu achten, dass bei der Parallelisierung auf GPUs der Speicher nicht überlastet wird.

7. Code-Optimierung: Überprüfen Sie den Code auf ineffiziente Schleifen oder unnötige Berechnungen und ersetzen Sie diese durch effizientere Konstrukte. Profile-Tools können helfen, Engpässe im Code zu identifizieren.

Für ein konkretes Beispiel, wie man die Stapelverarbeitung in PyTorch implementiert, siehe den folgenden Code-Snippet:

python
import torchimport numpy as npfrom models import InferSent

# Vorausgesetzt, Ihr Modell ist bereits initialisiert und geladen
# sowie die Fragen vorhanden als Liste von Strings: questions

# Konvertieren Sie Ihre Fragen-Liste in einen DataLoader
from torch.utils.data import DataLoader, TensorDataset

# Beispiel für die Umwandlung der Fragen in Tensoren (hängt von Ihrer Vorverarbeitung ab)
questions_tensors = [...] # Umwandlung der Fragen in Tensoren

# Erstellen Sie einen DataLoader zum Batching
questions_dataset = TensorDataset(torch.tensor(questions_tensors, dtype=torch.long))
questions_dataloader = DataLoader(questions_dataset, batch_size=64, shuffle=False)

for i, batch in enumerate(questions_dataloader):
batch = batch.to(device) # Verschieben Sie den Batch auf das gewünschte Gerät (CPU oder GPU)
embeddings = model.encode(batch, tokenize=True)
# Verarbeiten Sie hier Ihre Embeddings weiter


Beachten Sie, dass der Code an Ihr spezifisches Setup und die Struktur Ihrer Daten angepasst werden muss. Die Verwendung eines DataLoader ermöglicht es Ihnen, von der effizienten Batch-Verarbeitung und, wenn eingerichtet, von der GPU-Beschleunigung zu profitieren.

Avatar von

Antwort mit KI erzeugt:

Wie beschleunigt man eine Encoder-Funktion?

Um eine Encoder-Funktion zu beschleunigen, besonders in Fällen, wo man mit großen Datensätzen arbeitet, wie deinem Beispiel mit 130319 zu kodierenden Fragen, gibt es mehrere Ansätze, die man verfolgen kann. Wir konzentrieren uns hier auf die Optimierung im Kontext von Python und PyTorch, da das von dir verwendete Modell (InferSent) mit PyTorch implementiert ist.

1. Batchverarbeitung: Anstatt Sätze einzeln zu kodieren, nutze die Batch-Fähigkeiten des Modells, um mehrere Sätze gleichzeitig zu kodieren. Dies kann die Laufzeit signifikant verringern, da moderne Deep Learning Bibliotheken wie PyTorch speziell für die effiziente Verarbeitung von Batches optimiert sind.

2. Mehrere Worker bei der Datenvorbereitung verwenden: Beim Laden und Vorbereiten deiner Daten kannst du PyTorch's DataLoader verwenden, um mehrere Prozesse zum Laden deiner Daten zu nutzen (num_workers Parameter). Dadurch kann die Zeit zum Laden und Vorverarbeiten der Daten verringert werden, während dein Modell die Daten verarbeitet.

3. GPU-Nutzung: Stelle sicher, dass du eine GPU verwendest, wenn verfügbar. Modelle laufen deutlich schneller auf GPUs als auf CPUs. Du kannst dein Modell und deine Daten auf die GPU verschieben, indem du .to('cuda') anwenden, vorausgesetzt, dein System unterstützt CUDA.

4. Modell- und Code-Optimierung: Überprüfe, ob das Modell oder der Vorverarbeitungscode optimiert werden kann. Manchmal gibt es ineffiziente Operationen, die durch effizientere ersetzt werden können, ohne die Ergebnisse zu beeinflussen.

5. Parallelisierung/Distributed Computing: Für sehr große Datenmengen könntest du überlegen, den Vorgang über mehrere Maschinen oder Prozesse hinweg zu parallelisieren. PyTorch unterstützt verteiltes Rechnen, was bedeutet, dass du Trainieren und Inference-Aufgaben über mehrere GPUs oder sogar mehrere Maschinen verteilen kannst.

Beispiel für Batchverarbeitung mit dem InferSent-Modell:

Um den Ansatz der Batchverarbeitung zu veranschaulichen, hier ein Beispiel-Code, der zeigt, wie man ein Listen von Sätzen in Batches verarbeitet:

python
import torch
from models import InferSent

# Modellparameter
MODEL_PATH = '../new_models/infersent1.pkl'
params_model = {'bsize': 64, 'word_emb_dim': 300, 'enc_lstm_dim': 2048, 'pool_type': 'max', 'dpout_model': 0.0, 'version': 1}
model = InferSent(params_model)
model.load_state_dict(torch.load(MODEL_PATH, map_location='cpu'))  # 'cpu' oder 'cuda'
W2V_PATH = 'InferSent/dataset/GloVe/glove.840B.300d.txt'
model.set_w2v_path(W2V_PATH)
model.build_vocab_k_words(K=100000)

# Angenommen, `questions` ist deine Liste von Sätzen
batch_size = 64  # Oder ein anderer Wert, der zur GPU/CPU passt
encoded_questions = []

for start_idx in range(0, len(questions), batch_size):
  end_idx = min(start_idx + batch_size, len(questions))
  batch = questions[start_idx:end_idx]
  encoded_batch = model.encode(batch, tokenize=True)
  encoded_questions.extend(encoded_batch)

# `encoded_questions` enthält jetzt die kodierten Sätze


Dieses Beispiel nutzt Batch-Verarbeitung, was die Kodierungsgeschwindigkeit im Vergleich zur Verarbeitung jedes Satzes einzeln erhöhen sollte. Für noch bessere Ergebnisse stellt sicher, dass du nach der Möglichkeit, das Modell und die Daten auf eine GPU zu übertragen, Ausschau hältst, falls eine verfügbar ist.

Ein anderes Problem?

Stell deine Frage

Willkommen bei der Stacklounge! Stell deine Frage einfach und kostenlos

x
Made by a lovely community