[PYTHON] [Sprachverarbeitung 100 Schläge 2020] Kapitel 8: Neuronales Netz

Einführung

Die Version 2020 von 100 Klopfen der Sprachverarbeitung, die als Sammlung von Problemen der Verarbeitung natürlicher Sprache bekannt ist, wurde veröffentlicht. Dieser Artikel fasst die Ergebnisse der Lösung von "Kapitel 8: Neuronales Netz" aus den folgenden Kapiteln 1 bis 10 zusammen.

Vorbereitungen

Wir verwenden Google Colaboratory für Antworten. Ausführliche Informationen zum Einrichten und Verwenden von Google Colaboratory finden Sie in diesem Artikel. ** Da in diesem Kapitel die GPU verwendet wird, ändern Sie den Hardwarebeschleuniger von "Laufzeit" -> "Laufzeittyp ändern" in "GPU" und speichern Sie ihn im Voraus. ** ** ** Das Notizbuch mit den Ausführungsergebnissen der folgenden Antworten ist unter [github] verfügbar (https://github.com/hana-mame/nlp100/blob/master/chapter08.ipynb).

Kapitel 8: Neuronales Netz

Implementieren Sie ein Kategorisierungsmodell mit einem neuronalen Netzwerk basierend auf der Kategorisierung der in Kapitel 6 beschriebenen Nachrichtenartikel. Verwenden Sie in diesem Kapitel maschinelle Lernplattformen wie PyTorch, TensorFlow und Chainer.

70. Merkmale nach Summe der Wortvektoren

Ich möchte die in Aufgabe 50 erstellten Trainingsdaten, Verifizierungsdaten und Bewertungsdaten in Matrizen und Vektoren konvertieren. Zum Beispiel möchte ich für Trainingsdaten eine Matrix $ X $ erstellen, in der die Merkmalsvektoren $ \ boldsymbol {x} _i $ aller Fälle $ x_i $ angeordnet sind, und eine Matrix (Vektor) $ Y $, in der die richtigen Antwortbezeichnungen angeordnet sind.

X = \begin{pmatrix} \boldsymbol{x}_1 \ \boldsymbol{x}_2 \ \dots \ \boldsymbol{x}_n \ \end{pmatrix} \in \mathbb{R}^{n \times d}, Y = \begin{pmatrix} y_1 \ y_2 \ \dots \ y_n \ \end{pmatrix} \in \mathbb{N}^{n}

>
 > Hier ist $ n $ die Anzahl der Fälle von Trainingsdaten, und $ \ boldsymbol x_i \ in \ mathbb {R} ^ d $ und $ y_i \ in \ mathbb N $ sind $ i \ in \ {1. \ dots, n \} Repräsentiert den Merkmalsvektor und die korrekte Bezeichnung des $ -ten Falls.
 > Dieses Mal gibt es vier Kategorien: "Business", "Wissenschaft und Technologie", "Unterhaltung" und "Gesundheit". Wenn $ \ mathbb N_ {<4} $ eine natürliche Zahl (einschließlich $ 0 $) darstellt, die kleiner als $ 4 $ ist, lautet die korrekte Bezeichnung $ y_i $ in jedem Fall $ y_i \ in \ mathbb N_ {<4} $ Kann ausgedrückt werden durch.
 > Im Folgenden wird die Anzahl der Etikettentypen durch $ L $ dargestellt ($ L = 4 $ in dieser Klassifizierungsaufgabe).
>
 > Der Merkmalsvektor $ \ boldsymbol x_i $ des $ i $ -ten Falls wird durch die folgende Gleichung berechnet.
>
> $$\boldsymbol x_i = \frac{1}{T_i} \sum_{t=1}^{T_i} \mathrm{emb}(w_{i,t})$$
>
 > Hier ist der $ i $ -te Fall $ T_i $ (Artikelüberschrift) Wortketten $ (w_ {i, 1}, w_ {i, 2}, \ dots, w_ {i, T_i}) $ , Und $ \ mathrm {emb} (w) \ in \ mathbb {R} ^ d $ ist ein Wortvektor (die Anzahl der Dimensionen ist $ d $), der dem Wort $ w $ entspricht. Das heißt, $ \ boldsymbol x_i $ ist die Artikelüberschrift des $ i $ -ten Falls, ausgedrückt durch den Durchschnitt der Vektoren der in der Überschrift enthaltenen Wörter. Dieses Mal sollte der in Frage 60 heruntergeladene Wortvektor verwendet werden. Da wir einen Wortvektor mit der Dimension $ 300 $ verwendet haben, ist $ d = 300 $.
 > Die Bezeichnung $ y_i $ des $ i $ -ten Falls ist wie folgt definiert.
>
>```math
y_i = \begin{cases}
0 & (\mbox{Artikel}\boldsymbol x_i\mbox{If ist in der Kategorie "Business"}) \\
1 & (\mbox{Artikel}\boldsymbol x_i\mbox{Ist in der Kategorie "Wissenschaft und Technologie"}) \\
2 & (\mbox{Artikel}\boldsymbol x_i\mbox{If ist in der Kategorie "Unterhaltung"}) \\
3 & (\mbox{Artikel}\boldsymbol x_i\mbox{If ist in der Kategorie "Gesundheit"}) \\
\end{cases}

Wenn zwischen dem Kategorienamen und der Etikettennummer eine Eins-zu-Eins-Entsprechung besteht, muss die Entsprechung nicht der in der obigen Formel angegebenen entsprechen.

Erstellen Sie anhand der obigen Spezifikationen die folgende Matrix / den folgenden Vektor und speichern Sie sie in einer Datei.

  • Trainingsdaten-Feature-Matrix: $ X_ {\ rm train} \ in \ mathbb {R} ^ {N_t \ times d} $
  • Trainingsdaten-Beschriftungsvektor: $ Y_ {\ rm train} \ in \ mathbb {N} ^ {N_t} $
  • Funktionsmatrix für Validierungsdaten: $ X_ {\ rm valid} \ in \ mathbb {R} ^ {N_v \ times d} $
  • Validierungsdaten-Beschriftungsvektor: $ Y_ {\ rm valid} \ in \ mathbb {N} ^ {N_v} $
  • Funktionsmatrix für Auswertungsdaten: $ X_ {\ rm test} \ in \ mathbb {R} ^ {N_e \ times d} $
  • Bewertungsdaten-Beschriftungsvektor: $ Y_ {\ rm test} \ in \ mathbb {N} ^ {N_e} $

Beachten Sie, dass $ N_t, N_v und N_e $ die Anzahl der Fälle von Trainingsdaten, die Anzahl der Fälle von Verifizierungsdaten bzw. die Anzahl der Fälle von Bewertungsdaten sind.

Lesen Sie die angegebenen Daten nach dem Herunterladen zunächst als Datenrahmen. Anschließend wird es in Trainingsdaten, Verifizierungsdaten und Bewertungsdaten unterteilt und gespeichert. Bis zu diesem Punkt ist die Verarbeitung genau die gleiche wie bei Problem 50, so dass es kein Problem gibt, die dort erstellten Daten zu lesen.

#Daten herunterladen
!wget https://archive.ics.uci.edu/ml/machine-learning-databases/00359/NewsAggregatorDataset.zip
!unzip NewsAggregatorDataset.zip
#Doppelte Anführungszeichen durch einfache Anführungszeichen ersetzt, um Fehler beim Lesen zu vermeiden
!sed -e 's/"/'\''/g' ./newsCorpora.csv > ./newsCorpora_re.csv
import pandas as pd
from sklearn.model_selection import train_test_split

#Daten lesen
df = pd.read_csv('./newsCorpora_re.csv', header=None, sep='\t', names=['ID', 'TITLE', 'URL', 'PUBLISHER', 'CATEGORY', 'STORY', 'HOSTNAME', 'TIMESTAMP'])

#Datenextraktion
df = df.loc[df['PUBLISHER'].isin(['Reuters', 'Huffington Post', 'Businessweek', 'Contactmusic.com', 'Daily Mail']), ['TITLE', 'CATEGORY']]

#Datenaufteilung
train, valid_test = train_test_split(df, test_size=0.2, shuffle=True, random_state=123, stratify=df['CATEGORY'])
valid, test = train_test_split(valid_test, test_size=0.5, shuffle=True, random_state=123, stratify=valid_test['CATEGORY'])

#Datenspeicher
train.to_csv('./train.txt', sep='\t', index=False)
valid.to_csv('./valid.txt', sep='\t', index=False)
test.to_csv('./test.txt', sep='\t', index=False)

#Bestätigung der Anzahl der Fälle
print('[Lerndaten]')
print(train['CATEGORY'].value_counts())
print('[Verifizierungsdaten]')
print(valid['CATEGORY'].value_counts())
print('[Bewertungsdaten]')
print(test['CATEGORY'].value_counts())

Ausgabe


[Lerndaten]
b    4501
e    4235
t    1220
m     728
Name: CATEGORY, dtype: int64
[Verifizierungsdaten]
b    563
e    529
t    153
m     91
Name: CATEGORY, dtype: int64
[Bewertungsdaten]
b    563
e    530
t    152
m     91
Name: CATEGORY, dtype: int64

Laden Sie als Nächstes den in Frage 60 verwendeten gelernten Wortvektor herunter und laden Sie ihn.

#Laden Sie den gelernten Wortvektor herunter
FILE_ID = "0B7XkCwpI5KDYNlNUTTlSS21pQmM"
FILE_NAME = "GoogleNews-vectors-negative300.bin.gz"
!wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=$FILE_ID' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=$FILE_ID" -O $FILE_NAME && rm -rf /tmp/cookies.txt
from gensim.models import KeyedVectors

#Gelernten Wortvektor laden
model = KeyedVectors.load_word2vec_format('./GoogleNews-vectors-negative300.bin.gz', binary=True)

Erstellen Sie abschließend einen Feature-Vektor und einen Beschriftungsvektor und speichern Sie diese. Danach wird es in den Tensor-Typ konvertiert, damit es von PyTorch als Eingabe für das neuronale Netz verwendet werden kann.

import string
import torch

def transform_w2v(text):
  table = str.maketrans(string.punctuation, ' '*len(string.punctuation))
  words = text.translate(table).split()  #Nachdem Sie das Symbol durch ein Leerzeichen ersetzt haben, teilen Sie es durch ein Leerzeichen und listen Sie es auf.
  vec = [model[word] for word in words if word in model]  #Wort für Wort vektorisiert

  return torch.tensor(sum(vec) / len(vec))  #Konvertieren Sie den Durchschnittsvektor in Tensortyp und Ausgabe
#Erstellen eines Feature-Vektors
X_train = torch.stack([transform_w2v(text) for text in train['TITLE']])
X_valid = torch.stack([transform_w2v(text) for text in valid['TITLE']])
X_test = torch.stack([transform_w2v(text) for text in test['TITLE']])

print(X_train.size())
print(X_train)

Ausgabe


torch.Size([10684, 300])
tensor([[ 0.0837,  0.0056,  0.0068,  ...,  0.0751,  0.0433, -0.0868],
        [ 0.0272,  0.0266, -0.0947,  ..., -0.1046, -0.0489, -0.0092],
        [ 0.0577, -0.0159, -0.0780,  ..., -0.0421,  0.1229,  0.0876],
        ...,
        [ 0.0392, -0.0052,  0.0686,  ..., -0.0175,  0.0061, -0.0224],
        [ 0.0798,  0.1017,  0.1066,  ..., -0.0752,  0.0623,  0.1138],
        [ 0.1664,  0.0451,  0.0508,  ..., -0.0531, -0.0183, -0.0039]])
#Erstellen eines Beschriftungsvektors
category_dict = {'b': 0, 't': 1, 'e':2, 'm':3}
y_train = torch.tensor(train['CATEGORY'].map(lambda x: category_dict[x]).values)
y_valid = torch.tensor(valid['CATEGORY'].map(lambda x: category_dict[x]).values)
y_test = torch.tensor(test['CATEGORY'].map(lambda x: category_dict[x]).values)

print(y_train.size())
print(y_train)

Ausgabe


torch.Size([10684])
tensor([0, 1, 3,  ..., 0, 3, 2])
#sparen
torch.save(X_train, 'X_train.pt')
torch.save(X_valid, 'X_valid.pt')
torch.save(X_test, 'X_test.pt')
torch.save(y_train, 'y_train.pt')
torch.save(y_valid, 'y_valid.pt')
torch.save(y_test, 'y_test.pt')

71. Vorhersage durch einschichtiges neuronales Netzwerk

Lesen Sie die in Frage 70 gespeicherte Matrix und führen Sie die folgenden Berechnungen für die Trainingsdaten durch.

\hat{y}1=softmax(x_1W),\\hat{Y}=softmax(X{[1:4]}W)

 $ Softmax $ ist jedoch die Softmax-Funktion, $ X_ {[1: 4]} ∈ \ mathbb {R} ^ {4 × d} $ ist der Merkmalsvektor $ x_1 $, $ x_2 $, $ x_3 $, $ x_4 $ Ist eine vertikal angeordnete Matrix.

>```math
X_{[1:4]}=\begin{pmatrix}x_1\\x_2\\x_3\\x_4\end{pmatrix}

Die Matrix $ W \ in \ mathbb {R} ^ {d \ times L} $ ist die Gewichtsmatrix des einschichtigen neuronalen Netzwerks, die mit einem Zufallswert initialisiert werden kann (gelernt in Aufgabe 73 und höher). .. Beachten Sie, dass $ \ hat {\ boldsymbol y_1} \ in \ mathbb {R} ^ L $ ein Vektor ist, der die Wahrscheinlichkeit der Zugehörigkeit zu jeder Kategorie darstellt, wenn der Fall $ x_1 $ durch die verlernte Matrix $ W $ klassifiziert wird. In ähnlicher Weise drückt $ \ hat {Y} \ in \ mathbb {R} ^ {n \ times L} $ die Wahrscheinlichkeit der Zugehörigkeit zu jeder Kategorie als Matrix für die Trainingsdatenbeispiele $ x_1, x_2, x_3, x_4 $ aus. tun.

Definieren Sie zunächst ein einschichtiges neuronales Netzwerk mit dem Namen "SLPNet". Definieren Sie die Ebenen, aus denen das Netzwerk besteht, mit `__init__``` und ordnen Sie die Ebenen, durch die die Eingabedaten weitergeleitet werden, mit der Methode` forward``` an.

from torch import nn

class SLPNet(nn.Module):
  def __init__(self, input_size, output_size):
    super().__init__()
    self.fc = nn.Linear(input_size, output_size, bias=False)
    nn.init.normal_(self.fc.weight, 0.0, 1.0)  #Initialisieren Sie Gewichte mit normalen Zufallszahlen

  def forward(self, x):
    x = self.fc(x)
    return x

Anschließend wird das definierte Modell initialisiert und die angegebenen Berechnungen durchgeführt.

model = SLPNet(300, 4)  #Initialisierung eines einschichtigen neuronalen Netzwerks
y_hat_1 = torch.softmax(model.forward(X_train[:1]), dim=-1)
print(y_hat_1)

Ausgabe


tensor([[0.4273, 0.0958, 0.2492, 0.2277]], grad_fn=<SoftmaxBackward>)
Y_hat = torch.softmax(model.forward(X_train[:4]), dim=-1)
print(Y_hat)

Ausgabe


tensor([[0.4273, 0.0958, 0.2492, 0.2277],
        [0.2445, 0.2431, 0.0197, 0.4927],
        [0.7853, 0.1132, 0.0291, 0.0724],
        [0.5279, 0.2319, 0.0873, 0.1529]], grad_fn=<SoftmaxBackward>)

72. Verlust- und Steigungsberechnung

Berechnen Sie den Kreuzentropieverlust und den Gradienten für die Matrix $ W $ für den Fall $ x_1 $ und die Fallmenge $ x_1 $, $ x_2 $, $ x_3 $, $ x_4 $ der Trainingsdaten. Für einen bestimmten Fall $ x_i $ wird der Verlust durch die folgende Gleichung berechnet.

l_i = −log [Wahrscheinlichkeit, dass der Fall x_i als y_i klassifiziert wird]

Der Kreuzentropieverlust für die Fallmenge ist jedoch der Durchschnitt der Verluste für jeden in der Menge enthaltenen Fall.

Hier verwenden wir den `CrossEntropyLoss``` des` nn``` Moduls. Durch Eingabe des Ausgabevektors und des Beschriftungsvektors des Modells kann der durchschnittliche Verlust der obigen Gleichung berechnet werden.

criterion = nn.CrossEntropyLoss()
l_1 = criterion(model.forward(X_train[:1]), y_train[:1])  #Der Eingabevektor ist der Wert vor Softmax
model.zero_grad()  #Gradient auf Null initialisieren
l_1.backward()  #Berechnen Sie den Gradienten
print(f'Verlust: {l_1:.4f}')
print(f'Steigung:\n{model.fc.weight.grad}')

Ausgabe


Verlust: 2.9706
Steigung:
tensor([[-0.0794, -0.0053, -0.0065,  ..., -0.0713, -0.0411,  0.0823],
        [ 0.0022,  0.0001,  0.0002,  ...,  0.0020,  0.0011, -0.0023],
        [ 0.0611,  0.0041,  0.0050,  ...,  0.0549,  0.0316, -0.0634],
        [ 0.0161,  0.0011,  0.0013,  ...,  0.0144,  0.0083, -0.0167]])
l = criterion(model.forward(X_train[:4]), y_train[:4])
model.zero_grad()
l.backward()
print(f'Verlust: {l:.4f}')
print(f'Steigung:\n{model.fc.weight.grad}')

Ausgabe


Verlust: 3.0799
Steigung:
tensor([[-0.0207,  0.0079, -0.0090,  ..., -0.0350, -0.0003,  0.0232],
        [-0.0055, -0.0063,  0.0225,  ...,  0.0252,  0.0166,  0.0039],
        [ 0.0325, -0.0089, -0.0215,  ...,  0.0084,  0.0122, -0.0030],
        [-0.0063,  0.0072,  0.0081,  ...,  0.0014, -0.0285, -0.0241]])

73. Lernen durch probabilistische Gradientenabstiegsmethode

Lernen Sie die Matrix $ W $ mit der SGD-Methode (Stochastic Gradient Descent). Das Lernen kann nach einem geeigneten Standard abgeschlossen werden (z. B. "Ende in 100 Epochen").

Bereiten Sie zum Lernen `Dataset``` und` Dataloadervor.dataset```Ist ein Typ, der den Merkmalsvektor und den Beschriftungsvektor zusammenhalten kann und den ursprünglichen Tensor mithilfe der folgenden Klasse transformiert.

from torch.utils.data import Dataset

class CreateDataset(Dataset):
    def __init__(self, X, y):  #Geben Sie die Komponenten des Datasets an
        self.X = X
        self.y = y

    def __len__(self):  # len(dataset)Geben Sie den Wert an, mit dem zurückgegeben werden soll
        return len(self.y)

    def __getitem__(self, idx):  # dataset[idx]Geben Sie den Wert an, mit dem zurückgegeben werden soll
        if isinstance(idx, torch.Tensor):
            idx = idx.tolist()
        return [self.X[idx], self.y[idx]]

Erstellen Sie nach der Konvertierung "DataLoader". `Dataloader``` kann in` Dataset eingegeben werden, und die in der angegebenen Größe (`` `batch_size) gesammelten Daten können der Reihe nach abgerufen werden. Hier wird `batch_size = 1``` gesetzt, was bedeutet, dass` Dataloader erstellt wird, um Daten einzeln abzurufen. Beachten Sie, dass `` `Dataloader in der Reihenfolge mit der for``` -Anweisung abgerufen werden kann oder der nächste Block mit`` next (iter (Dataloader)) `aufgerufen werden kann.

from torch.utils.data import DataLoader

dataset_train = CreateDataset(X_train, y_train)
dataset_valid = CreateDataset(X_valid, y_valid)
dataset_test = CreateDataset(X_test, y_test)
dataloader_train = DataLoader(dataset_train, batch_size=1, shuffle=True)
dataloader_valid = DataLoader(dataset_valid, batch_size=len(dataset_valid), shuffle=False)
dataloader_test = DataLoader(dataset_test, batch_size=len(dataset_test), shuffle=False)

Nachdem die Daten fertig sind, trainieren wir die Matrix $ W $. Die Definition des Modells und die Definition der Verlustfunktion sind dieselben wie in der vorherigen Frage. Dieses Mal werden wir auch die Gewichte aus dem berechneten Gradienten aktualisieren, sodass wir auch einen Optimierer definieren. Hier wird SGD gemäß den Anweisungen eingestellt. Wenn die Teile fertig sind, wird das Lernen mit der Anzahl der auf 10 eingestellten Epochen ausgeführt.

#Modelldefinition
model = SLPNet(300, 4)

#Definition der Verlustfunktion
criterion = nn.CrossEntropyLoss()

#Optimierungsdefinition
optimizer = torch.optim.SGD(model.parameters(), lr=1e-1)

#Lernen
num_epochs = 10
for epoch in range(num_epochs):
  #Auf Trainingsmodus einstellen
  model.train()
  loss_train = 0.0
  for i, (inputs, labels) in enumerate(dataloader_train):
    #Gradient auf Null initialisieren
    optimizer.zero_grad()

    #Vorwärtsausbreitung+Fehler bei der Weitergabe+Gewichtsaktualisierung
    outputs = model.forward(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()

    #Rekordverlust
    loss_train += loss.item()
 
  #Berechnung des Batch-Durchschnittsverlusts
  loss_train = loss_train / i

  #Berechnung des Validierungsdatenverlusts
  model.eval() 
  with torch.no_grad():
    inputs, labels = next(iter(dataloader_valid))
    outputs = model.forward(inputs)
    loss_valid = criterion(outputs, labels)

  #Ausgabeprotokoll
  print(f'epoch: {epoch + 1}, loss_train: {loss_train:.4f}, loss_valid: {loss_valid:.4f}')  

Ausgabe


epoch: 1, loss_train: 0.4745, loss_valid: 0.3637
epoch: 2, loss_train: 0.3173, loss_valid: 0.3306
epoch: 3, loss_train: 0.2884, loss_valid: 0.3208
epoch: 4, loss_train: 0.2716, loss_valid: 0.3150
epoch: 5, loss_train: 0.2615, loss_valid: 0.3141
epoch: 6, loss_train: 0.2519, loss_valid: 0.3092
epoch: 7, loss_train: 0.2474, loss_valid: 0.3114
epoch: 8, loss_train: 0.2431, loss_valid: 0.3072
epoch: 9, loss_train: 0.2393, loss_valid: 0.3096
epoch: 10, loss_train: 0.2359, loss_valid: 0.3219

Im Verlauf der Epoche können wir feststellen, dass der Verlust von Trainingsdaten allmählich abnimmt.

74. Messung der richtigen Antwortrate

Wenn Sie die Fälle von Trainingsdaten und Bewertungsdaten anhand der in Frage 73 erhaltenen Matrix klassifizieren, ermitteln Sie für jede die richtige Antwortrate.

Definieren Sie mit dem trainierten Modell und `` `Dataloader``` als Eingabe eine Funktion zur Berechnung der Genauigkeitsrate.

def calculate_accuracy(model, loader):
  model.eval()
  total = 0
  correct = 0
  with torch.no_grad():
    for inputs, labels in loader:
      outputs = model(inputs)
      pred = torch.argmax(outputs, dim=-1)
      total += len(inputs)
      correct += (pred == labels).sum().item()
      
  return correct / total
acc_train = calculate_accuracy(model, dataloader_train)
acc_test = calculate_accuracy(model, dataloader_test)
print(f'Richtige Antwortrate (Lerndaten):{acc_train:.3f}')
print(f'Richtige Antwortrate (Bewertungsdaten):{acc_test:.3f}')

Ausgabe


Richtige Antwortrate (Lerndaten): 0.920
Richtige Antwortrate (Bewertungsdaten): 0.891

75. Verlust- und Genauigkeitsdiagramm

Durch Ändern des Codes von Frage 73 können jedes Mal, wenn die Parameteraktualisierung jeder Epoche abgeschlossen ist, der Verlust der Trainingsdaten, die korrekte Antwortrate, der Verlust der Verifizierungsdaten und die korrekte Antwortrate in einem Diagramm aufgezeichnet werden, um den Lernfortschritt zu überprüfen. Tu es.

Der Verlust und die korrekte Antwortrate werden aufgezeichnet, indem die Funktion in der vorherigen Frage so geändert wird, dass der Verlust auch berechnet und für jede Epoche angewendet werden kann.

def calculate_loss_and_accuracy(model, criterion, loader):
  model.eval()
  loss = 0.0
  total = 0
  correct = 0
  with torch.no_grad():
    for inputs, labels in loader:
      outputs = model(inputs)
      loss += criterion(outputs, labels).item()
      pred = torch.argmax(outputs, dim=-1)
      total += len(inputs)
      correct += (pred == labels).sum().item()
      
  return loss / len(loader), correct / total
#Modelldefinition
model = SLPNet(300, 4)

#Definition der Verlustfunktion
criterion = nn.CrossEntropyLoss()

#Optimierungsdefinition
optimizer = torch.optim.SGD(model.parameters(), lr=1e-1)

#Lernen
num_epochs = 30
log_train = []
log_valid = []
for epoch in range(num_epochs):
  #Auf Trainingsmodus einstellen
  model.train()
  for inputs, labels in dataloader_train:
    #Gradient auf Null initialisieren
    optimizer.zero_grad()

    #Vorwärtsausbreitung+Fehler bei der Weitergabe+Gewichtsaktualisierung
    outputs = model.forward(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()
 
  #Verlustberechnung und korrekte Rücklaufquote
  loss_train, acc_train = calculate_loss_and_accuracy(model, criterion, dataloader_train)
  loss_valid, acc_valid = calculate_loss_and_accuracy(model, criterion, dataloader_valid)
  log_train.append([loss_train, acc_train])
  log_valid.append([loss_valid, acc_valid])

  #Ausgabeprotokoll
  print(f'epoch: {epoch + 1}, loss_train: {loss_train:.4f}, accuracy_train: {acc_train:.4f}, loss_valid: {loss_valid:.4f}, accuracy_valid: {acc_valid:.4f}')  

Ausgabe


epoch: 1, loss_train: 0.3476, accuracy_train: 0.8796, loss_valid: 0.3656, accuracy_valid: 0.8840
epoch: 2, loss_train: 0.2912, accuracy_train: 0.8988, loss_valid: 0.3219, accuracy_valid: 0.8967
・ ・ ・
epoch: 29, loss_train: 0.2102, accuracy_train: 0.9287, loss_valid: 0.3259, accuracy_valid: 0.8930
epoch: 30, loss_train: 0.2119, accuracy_train: 0.9289, loss_valid: 0.3262, accuracy_valid: 0.8945
from matplotlib import pyplot as plt

#Visualisierung
fig, ax = plt.subplots(1, 2, figsize=(15, 5))
ax[0].plot(np.array(log_train).T[0], label='train')
ax[0].plot(np.array(log_valid).T[0], label='valid')
ax[0].set_xlabel('epoch')
ax[0].set_ylabel('loss')
ax[0].legend()
ax[1].plot(np.array(log_train).T[1], label='train')
ax[1].plot(np.array(log_valid).T[1], label='valid')
ax[1].set_xlabel('epoch')
ax[1].set_ylabel('accuracy')
ax[1].legend()
plt.show()

75.png

76. Kontrollpunkt

Ändern Sie den Code in Frage 75 und schreiben Sie die Prüfpunkte (Werte der Parameter im Lernprozess (Gewichtsmatrix usw.) und den internen Status des Optimierungsalgorithmus) jedes Mal in eine Datei, wenn die Parameteraktualisierung jeder Epoche abgeschlossen ist.

Auf die Parameter in der Mitte des Lernens kann mit `` model.state_dict () zugegriffen werden, und auf den internen Status des Optimierungsalgorithmus kann mit optimizer.state_dict () `zugegriffen werden. Speichern Sie ihn also zusammen mit der Anzahl der Epochen in jeder Epoche. Verarbeitung hinzufügen. Die Ausgabe ist die gleiche wie bei der vorherigen Frage, daher wird sie weggelassen.

#Modelldefinition
model = SLPNet(300, 4)

#Definition der Verlustfunktion
criterion = nn.CrossEntropyLoss()

#Optimierungsdefinition
optimizer = torch.optim.SGD(model.parameters(), lr=1e-1)

#Lernen
num_epochs = 10
log_train = []
log_valid = []
for epoch in range(num_epochs):
  #Auf Trainingsmodus einstellen
  model.train()
  for inputs, labels in dataloader_train:
    #Gradient auf Null initialisieren
    optimizer.zero_grad()

    #Vorwärtsausbreitung+Fehler bei der Weitergabe+Gewichtsaktualisierung
    outputs = model.forward(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()
 
  #Verlustberechnung und korrekte Rücklaufquote
  loss_train, acc_train = calculate_loss_and_accuracy(model, criterion, dataloader_train)
  loss_valid, acc_valid = calculate_loss_and_accuracy(model, criterion, dataloader_valid)
  log_train.append([loss_train, acc_train])
  log_valid.append([loss_valid, acc_valid])

  #Checkpoint speichern
  torch.save({'epoch': epoch, 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict()}, f'checkpoint{epoch + 1}.pt')

  #Ausgabeprotokoll
  print(f'epoch: {epoch + 1}, loss_train: {loss_train:.4f}, accuracy_train: {acc_train:.4f}, loss_valid: {loss_valid:.4f}, accuracy_valid: {acc_valid:.4f}')  

77. Mini-Charge

Ändern Sie den Code von Problem 76, berechnen Sie den Verlust / Gradienten für jeden $ B $ -Fall und aktualisieren Sie den Wert der Matrix $ W $ (Mini-Batch). Vergleichen Sie die Zeit, die erforderlich ist, um eine Epoche zu lernen, während Sie den Wert von $ B $ in $ 1,2,4,8,… $ ändern.

Da es schwierig ist, alle Prozesse jedes Mal zu schreiben, wenn die Stapelgröße geändert wird, funktionieren die Prozesse nach der Erstellung von `Dataloader``` als` train_model``` und nehmen einige Parameter einschließlich der Stapelgröße als Argumente. Festlegen als.

import time

def train_model(dataset_train, dataset_valid, batch_size, model, criterion, optimizer, num_epochs):
  #Erstellen eines Datenladers
  dataloader_train = DataLoader(dataset_train, batch_size=batch_size, shuffle=True)
  dataloader_valid = DataLoader(dataset_valid, batch_size=len(dataset_valid), shuffle=False)

  #Lernen
  log_train = []
  log_valid = []
  for epoch in range(num_epochs):
    #Startzeit aufzeichnen
    s_time = time.time()

    #Auf Trainingsmodus einstellen
    model.train()
    for inputs, labels in dataloader_train:
      #Gradient auf Null initialisieren
      optimizer.zero_grad()

      #Vorwärtsausbreitung+Fehler bei der Weitergabe+Gewichtsaktualisierung
      outputs = model.forward(inputs)
      loss = criterion(outputs, labels)
      loss.backward()
      optimizer.step()
  
    #Verlustberechnung und korrekte Rücklaufquote
    loss_train, acc_train = calculate_loss_and_accuracy(model, criterion, dataloader_train)
    loss_valid, acc_valid = calculate_loss_and_accuracy(model, criterion, dataloader_valid)
    log_train.append([loss_train, acc_train])
    log_valid.append([loss_valid, acc_valid])

    #Checkpoint speichern
    torch.save({'epoch': epoch, 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict()}, f'checkpoint{epoch + 1}.pt')

    #Endzeit aufzeichnen
    e_time = time.time()

    #Ausgabeprotokoll
    print(f'epoch: {epoch + 1}, loss_train: {loss_train:.4f}, accuracy_train: {acc_train:.4f}, loss_valid: {loss_valid:.4f}, accuracy_valid: {acc_valid:.4f}, {(e_time - s_time):.4f}sec') 

  return {'train': log_train, 'valid': log_valid}

Messen Sie die Verarbeitungszeit, während Sie die Chargengröße ändern.

#Datensatz erstellen
dataset_train = CreateDataset(X_train, y_train)
dataset_valid = CreateDataset(X_valid, y_valid)

#Modelldefinition
model = SLPNet(300, 4)

#Definition der Verlustfunktion
criterion = nn.CrossEntropyLoss()

#Optimierungsdefinition
optimizer = torch.optim.SGD(model.parameters(), lr=1e-1)

#Modelllernen
for batch_size in [2 ** i for i in range(11)]:
  print(f'Chargengröße: {batch_size}')
  log = train_model(dataset_train, dataset_valid, batch_size, model, criterion, optimizer, 1)

Ausgabe


Chargengröße: 1
epoch: 1, loss_train: 0.3237, accuracy_train: 0.8888, loss_valid: 0.3476, accuracy_valid: 0.8817, 5.4416sec
Chargengröße: 2
epoch: 1, loss_train: 0.2966, accuracy_train: 0.8999, loss_valid: 0.3258, accuracy_valid: 0.8847, 3.0029sec
Chargengröße: 4
epoch: 1, loss_train: 0.2883, accuracy_train: 0.8999, loss_valid: 0.3222, accuracy_valid: 0.8862, 1.5988sec
Chargengröße: 8
epoch: 1, loss_train: 0.2835, accuracy_train: 0.9023, loss_valid: 0.3179, accuracy_valid: 0.8907, 0.8732sec
Chargengröße: 16
epoch: 1, loss_train: 0.2817, accuracy_train: 0.9038, loss_valid: 0.3164, accuracy_valid: 0.8907, 0.5445sec
Chargengröße: 32
epoch: 1, loss_train: 0.2810, accuracy_train: 0.9038, loss_valid: 0.3159, accuracy_valid: 0.8900, 0.3482sec
Chargengröße: 64
epoch: 1, loss_train: 0.2806, accuracy_train: 0.9040, loss_valid: 0.3157, accuracy_valid: 0.8900, 0.2580sec
Chargengröße: 128
epoch: 1, loss_train: 0.2806, accuracy_train: 0.9041, loss_valid: 0.3156, accuracy_valid: 0.8900, 0.1984sec
Chargengröße: 256
epoch: 1, loss_train: 0.2801, accuracy_train: 0.9039, loss_valid: 0.3155, accuracy_valid: 0.8900, 0.1715sec
Chargengröße: 512
epoch: 1, loss_train: 0.2802, accuracy_train: 0.9038, loss_valid: 0.3155, accuracy_valid: 0.8900, 0.2177sec
Chargengröße: 1024
epoch: 1, loss_train: 0.2792, accuracy_train: 0.9038, loss_valid: 0.3155, accuracy_valid: 0.8900, 0.1603sec

Im Allgemeinen können Sie sehen, dass die Berechnungszeit umso kürzer ist, je größer die Chargengröße ist.

78. Lernen auf GPU

Ändern Sie den Code in Frage 77 und führen Sie das Training auf der GPU aus.

Fügen Sie das Argument `device``` hinzu, um die GPU für` berechne_verlust_und_genauigkeit und `` `train_model anzugeben. In jeder Funktion können Sie die GPU verwenden, indem Sie den Prozess zum Senden des Modells und des Eingabetensors an die GPU hinzufügen und `cuda``` für` device``` angeben.

def calculate_loss_and_accuracy(model, criterion, loader, device):
  model.eval()
  loss = 0.0
  total = 0
  correct = 0
  with torch.no_grad():
    for inputs, labels in loader:
      inputs = inputs.to(device)
      labels = labels.to(device)
      outputs = model(inputs)
      loss += criterion(outputs, labels).item()
      pred = torch.argmax(outputs, dim=-1)
      total += len(inputs)
      correct += (pred == labels).sum().item()
      
  return loss / len(loader), correct / total
  

def train_model(dataset_train, dataset_valid, batch_size, model, criterion, optimizer, num_epochs, device=None):
  #An GPU senden
  model.to(device)

  #Erstellen eines Datenladers
  dataloader_train = DataLoader(dataset_train, batch_size=batch_size, shuffle=True)
  dataloader_valid = DataLoader(dataset_valid, batch_size=len(dataset_valid), shuffle=False)

  #Lernen
  log_train = []
  log_valid = []
  for epoch in range(num_epochs):
    #Startzeit aufzeichnen
    s_time = time.time()

    #Auf Trainingsmodus einstellen
    model.train()
    for inputs, labels in dataloader_train:
      #Gradient auf Null initialisieren
      optimizer.zero_grad()

      #Vorwärtsausbreitung+Fehler bei der Weitergabe+Gewichtsaktualisierung
      inputs = inputs.to(device)
      labels = labels.to(device)
      outputs = model.forward(inputs)
      loss = criterion(outputs, labels)
      loss.backward()
      optimizer.step()
    
    #Verlustberechnung und korrekte Rücklaufquote
    loss_train, acc_train = calculate_loss_and_accuracy(model, criterion, dataloader_train, device)
    loss_valid, acc_valid = calculate_loss_and_accuracy(model, criterion, dataloader_valid, device)
    log_train.append([loss_train, acc_train])
    log_valid.append([loss_valid, acc_valid])

    #Checkpoint speichern
    torch.save({'epoch': epoch, 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict()}, f'checkpoint{epoch + 1}.pt')

    #Endzeit aufzeichnen
    e_time = time.time()

    #Ausgabeprotokoll
    print(f'epoch: {epoch + 1}, loss_train: {loss_train:.4f}, accuracy_train: {acc_train:.4f}, loss_valid: {loss_valid:.4f}, accuracy_valid: {acc_valid:.4f}, {(e_time - s_time):.4f}sec') 

  return {'train': log_train, 'valid': log_valid}
#Datensatz erstellen
dataset_train = CreateDataset(X_train, y_train)
dataset_valid = CreateDataset(X_valid, y_valid)

#Modelldefinition
model = SLPNet(300, 4)

#Definition der Verlustfunktion
criterion = nn.CrossEntropyLoss()

#Optimierungsdefinition
optimizer = torch.optim.SGD(model.parameters(), lr=1e-1)

#Gerätespezifikation
device = torch.device('cuda')

#Modelllernen
for batch_size in [2 ** i for i in range(11)]:
  print(f'Chargengröße: {batch_size}')
  log = train_model(dataset_train, dataset_valid, batch_size, model, criterion, optimizer, 1, device=device)

Ausgabe


Chargengröße: 1
epoch: 1, loss_train: 0.3300, accuracy_train: 0.8874, loss_valid: 0.3584, accuracy_valid: 0.8772, 9.0342sec
Chargengröße: 2
epoch: 1, loss_train: 0.3025, accuracy_train: 0.8994, loss_valid: 0.3374, accuracy_valid: 0.8870, 4.6391sec
Chargengröße: 4
epoch: 1, loss_train: 0.2938, accuracy_train: 0.9005, loss_valid: 0.3321, accuracy_valid: 0.8855, 2.4228sec
Chargengröße: 8
epoch: 1, loss_train: 0.2894, accuracy_train: 0.9039, loss_valid: 0.3299, accuracy_valid: 0.8855, 1.2517sec
Chargengröße: 16
epoch: 1, loss_train: 0.2876, accuracy_train: 0.9038, loss_valid: 0.3285, accuracy_valid: 0.8855, 0.7149sec
Chargengröße: 32
epoch: 1, loss_train: 0.2867, accuracy_train: 0.9050, loss_valid: 0.3280, accuracy_valid: 0.8862, 0.4323sec
Chargengröße: 64
epoch: 1, loss_train: 0.2863, accuracy_train: 0.9050, loss_valid: 0.3277, accuracy_valid: 0.8862, 0.2834sec
Chargengröße: 128
epoch: 1, loss_train: 0.2869, accuracy_train: 0.9051, loss_valid: 0.3276, accuracy_valid: 0.8862, 0.2070sec
Chargengröße: 256
epoch: 1, loss_train: 0.2864, accuracy_train: 0.9054, loss_valid: 0.3275, accuracy_valid: 0.8862, 0.1587sec
Chargengröße: 512
epoch: 1, loss_train: 0.2859, accuracy_train: 0.9056, loss_valid: 0.3275, accuracy_valid: 0.8862, 0.2016sec
Chargengröße: 1024
epoch: 1, loss_train: 0.2858, accuracy_train: 0.9056, loss_valid: 0.3275, accuracy_valid: 0.8862, 0.1303sec

Obwohl die Stapelgröße klein ist, scheint die Zeit zum Senden an die GPU für jeden Stapel länger und die Verarbeitungszeit bei Verwendung der CPU kürzer zu sein. Auf der anderen Seite können wir mit zunehmender Stapelgröße feststellen, dass die Verwendung der GPU schneller ist.

79. Mehrschichtiges neuronales Netzwerk

Ändern Sie den Code in Problem 78, um einen Hochleistungs-Kategorisierer zu erstellen und gleichzeitig die Form des neuronalen Netzwerks zu ändern, z. B. das Einführen von Bias-Begriffen und das Überlagern.

Definieren Sie ein neues mehrschichtiges neuronales Netzwerk "MLPNet". Dieses Netzwerk besteht aus Eingabeschicht-> Mittelschicht-> Ausgabeschicht, und die Chargennormalisierung wird nach der Mittelschicht durchgeführt. Darüber hinaus führt `` `train_model``` einen neuen Standard für die Beendigung des Lernens ein. Dieses Mal besteht die Regel einfach darin, anzuhalten, wenn der Verlust von Verifizierungsdaten in drei aufeinander folgenden Epochen nicht abnimmt. Darüber hinaus werden wir einen Scheduler hinzufügen, der die Lernrate schrittweise senkt, um die Generalisierungsleistung zu verbessern.

from torch.nn import functional as F

class MLPNet(nn.Module):
  def __init__(self, input_size, mid_size, output_size, mid_layers):
    super().__init__()
    self.mid_layers = mid_layers
    self.fc = nn.Linear(input_size, mid_size)
    self.fc_mid = nn.Linear(mid_size, mid_size)
    self.fc_out = nn.Linear(mid_size, output_size) 
    self.bn = nn.BatchNorm1d(mid_size)

  def forward(self, x):
    x = F.relu(self.fc(x))
    for _ in range(self.mid_layers):
      x = F.relu(self.bn(self.fc_mid(x)))
    x = F.relu(self.fc_out(x))
 
    return x
from torch import optim

def calculate_loss_and_accuracy(model, criterion, loader, device):
  model.eval()
  loss = 0.0
  total = 0
  correct = 0
  with torch.no_grad():
    for inputs, labels in loader:
      inputs = inputs.to(device)
      labels = labels.to(device)
      outputs = model(inputs)
      loss += criterion(outputs, labels).item()
      pred = torch.argmax(outputs, dim=-1)
      total += len(inputs)
      correct += (pred == labels).sum().item()
      
  return loss / len(loader), correct / total
  

def train_model(dataset_train, dataset_valid, batch_size, model, criterion, optimizer, num_epochs, device=None):
  #An GPU senden
  model.to(device)

  #Erstellen eines Datenladers
  dataloader_train = DataLoader(dataset_train, batch_size=batch_size, shuffle=True)
  dataloader_valid = DataLoader(dataset_valid, batch_size=len(dataset_valid), shuffle=False)

  #Scheduler-Einstellungen
  scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, num_epochs, eta_min=1e-5, last_epoch=-1)

  #Lernen
  log_train = []
  log_valid = []
  for epoch in range(num_epochs):
    #Startzeit aufzeichnen
    s_time = time.time()

    #Auf Trainingsmodus einstellen
    model.train()
    for inputs, labels in dataloader_train:
      #Gradient auf Null initialisieren
      optimizer.zero_grad()

      #Vorwärtsausbreitung+Fehler bei der Weitergabe+Gewichtsaktualisierung
      inputs = inputs.to(device)
      labels = labels.to(device)
      outputs = model.forward(inputs)
      loss = criterion(outputs, labels)
      loss.backward()
      optimizer.step()
    
    #Verlustberechnung und korrekte Rücklaufquote
    loss_train, acc_train = calculate_loss_and_accuracy(model, criterion, dataloader_train, device)
    loss_valid, acc_valid = calculate_loss_and_accuracy(model, criterion, dataloader_valid, device)
    log_train.append([loss_train, acc_train])
    log_valid.append([loss_valid, acc_valid])

    #Checkpoint speichern
    torch.save({'epoch': epoch, 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict()}, f'checkpoint{epoch + 1}.pt')

    #Endzeit aufzeichnen
    e_time = time.time()

    #Ausgabeprotokoll
    print(f'epoch: {epoch + 1}, loss_train: {loss_train:.4f}, accuracy_train: {acc_train:.4f}, loss_valid: {loss_valid:.4f}, accuracy_valid: {acc_valid:.4f}, {(e_time - s_time):.4f}sec') 

    #Das Lernen endet, wenn der Verlust von Verifizierungsdaten in drei aufeinander folgenden Epochen nicht abnimmt
    if epoch > 2 and log_valid[epoch - 3][0] <= log_valid[epoch - 2][0] <= log_valid[epoch - 1][0] <= log_valid[epoch][0]:
      break

    #Machen Sie mit dem Scheduler einen Schritt
    scheduler.step()

  return {'train': log_train, 'valid': log_valid}
#Datensatz erstellen
dataset_train = CreateDataset(X_train, y_train)
dataset_valid = CreateDataset(X_valid, y_valid)

#Modelldefinition
model = MLPNet(300, 200, 4, 1)

#Definition der Verlustfunktion
criterion = nn.CrossEntropyLoss()

#Optimierungsdefinition
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)

#Gerätespezifikation
device = torch.device('cuda')

#Modelllernen
log = train_model(dataset_train, dataset_valid, 64, model, criterion, optimizer, 1000, device)

Ausgabe


epoch: 1, loss_train: 1.1176, accuracy_train: 0.6679, loss_valid: 1.1150, accuracy_valid: 0.6572, 0.4695sec
epoch: 2, loss_train: 0.8050, accuracy_train: 0.7620, loss_valid: 0.8005, accuracy_valid: 0.7687, 0.4521sec
・ ・ ・
epoch: 96, loss_train: 0.1708, accuracy_train: 0.9460, loss_valid: 0.2858, accuracy_valid: 0.9034, 0.4632sec
epoch: 97, loss_train: 0.1702, accuracy_train: 0.9466, loss_valid: 0.2861, accuracy_valid: 0.9034, 0.5373sec

Es wurde in 97 Epochen eingestellt. Visualisieren Sie den Verlust und die Genauigkeitsrate für jede Epoche.

fig, ax = plt.subplots(1, 2, figsize=(15, 5))
ax[0].plot(np.array(log['train']).T[0], label='train')
ax[0].plot(np.array(log['valid']).T[0], label='valid')
ax[0].set_xlabel('epoch')
ax[0].set_ylabel('loss')
ax[0].legend()
ax[1].plot(np.array(log['train']).T[1], label='train')
ax[1].plot(np.array(log['valid']).T[1], label='valid')
ax[1].set_xlabel('epoch')
ax[1].set_ylabel('accuracy')
ax[1].legend()
plt.show()

79.png

Überprüfen Sie die Genauigkeitsrate der Bewertungsdaten.

def calculate_accuracy(model, loader, device):
  model.eval()
  total = 0
  correct = 0
  with torch.no_grad():
    for inputs, labels in loader:
      inputs = inputs.to(device)
      labels = labels.to(device)
      outputs = model(inputs)
      pred = torch.argmax(outputs, dim=-1)
      total += len(inputs)
      correct += (pred == labels).sum().item()
      
  return correct / total
#Bestätigung der korrekten Antwortrate
acc_train = calculate_accuracy(model, dataloader_train, device)
acc_test = calculate_accuracy(model, dataloader_test, device)
print(f'Richtige Antwortrate (Lerndaten):{acc_train:.3f}')
print(f'Richtige Antwortrate (Bewertungsdaten):{acc_test:.3f}')

Ausgabe


Richtige Antwortrate (Lerndaten): 0.947
Richtige Antwortrate (Bewertungsdaten): 0.921

In dem einschichtigen neuronalen Netzwerk betrug die Genauigkeitsrate der Bewertungsdaten 0,891, sie wird jedoch durch Verwendung mehrerer Schichten um 3 Punkte verbessert.

abschließend

Sprachverarbeitung 100 Klopfen sind so konzipiert, dass Sie nicht nur die Verarbeitung natürlicher Sprache selbst lernen können, sondern auch die grundlegende Datenverarbeitung und das allgemeine maschinelle Lernen. Sogar diejenigen, die maschinelles Lernen in Online-Kursen studieren, können sehr gute Ergebnisse erzielen. Probieren Sie es also bitte aus.

Zu allen 100 Fragen

Recommended Posts

[Sprachverarbeitung 100 Schläge 2020] Kapitel 8: Neuronales Netz
100 Sprachverarbeitungsklopfen ~ Kapitel 1
100 Sprachverarbeitung klopft Kapitel 2 (10 ~ 19)
100 Sprachverarbeitungsklopfen 03 ~ 05
100 Sprachverarbeitungsklopfen (2020): 40
100 Sprachverarbeitungsklopfen (2020): 32
100 Sprachverarbeitungsklopfen (2020): 35
[Sprachverarbeitung 100 Schläge 2020] Kapitel 3: Reguläre Ausdrücke
100 Sprachverarbeitungsklopfen (2020): 47
100 Sprachverarbeitungsklopfen (2020): 39
100 Klicks in der Verarbeitung natürlicher Sprache Kapitel 4 Kommentar
[Sprachverarbeitung 100 Schläge 2020] Kapitel 6: Maschinelles Lernen
100 Sprachverarbeitungsklopfen (2020): 22
100 Sprachverarbeitungsklopfen 2020: Kapitel 4 (morphologische Analyse)
[Sprachverarbeitung 100 Schläge 2020] Kapitel 5: Abhängigkeitsanalyse
100 Sprachverarbeitungsklopfen (2020): 42
100 Sprachverarbeitungsklopfen (2020): 29
100 Sprachverarbeitungsklopfen (2020): 49
[Sprachverarbeitung 100 Schläge 2020] Kapitel 1: Vorbereitende Bewegung
100 Sprachverarbeitungsklopfen (2020): 45
100 Sprachverarbeitungsklopfen (2020): 10-19
[Sprachverarbeitung 100 Schläge 2020] Kapitel 7: Wortvektor
100 Sprachverarbeitungsklopfen (2020): 30
100 Sprachverarbeitungsklopfen (2020): 00-09
100 Sprachverarbeitung klopfen 2020: Kapitel 3 (regulärer Ausdruck)
100 Sprachverarbeitung Knock 2020 Kapitel 8: Neuronales Netz
100 Sprachverarbeitungsklopfen (2020): 48
[Sprachverarbeitung 100 Schläge 2020] Kapitel 2: UNIX-Befehle
100 Sprachverarbeitungsklopfen (2020): 44
100 Sprachverarbeitungsklopfen (2020): 41
100 Sprachverarbeitungsklopfen (2020): 37
[Sprachverarbeitung 100 Schläge 2020] Kapitel 9: RNN, CNN
100 Sprachverarbeitungsklopfen (2020): 25
100 Sprachverarbeitungsklopfen (2020): 23
100 Sprachverarbeitungsklopfen (2020): 33
100 Sprachverarbeitungsklopfen (2020): 20
100 Sprachverarbeitungsklopfen (2020): 27
[Sprachverarbeitung 100 Schläge 2020] Kapitel 4: Morphologische Analyse
100 Sprachverarbeitungsklopfen (2020): 46
100 Sprachverarbeitungsklopfen (2020): 21
100 Sprachverarbeitungsklopfen (2020): 36
Sprachverarbeitung 100 Schläge Kapitel 4: Morphologische Analyse 31. Verben
100 Amateur-Sprachverarbeitungsklopfen: 41
100 Amateur-Sprachverarbeitungsklopfen: 71
100 Amateur-Sprachverarbeitungsklopfen: 56
100 Amateur-Sprachverarbeitungsklopfen: 24
100 Amateur-Sprachverarbeitungsklopfen: 59
100 Amateur-Sprachverarbeitungsklopfen: 70
100 Amateur-Sprachverarbeitungsklopfen: 60
100 Sprachverarbeitung Knock 2020 Kapitel 1
100 Amateur-Sprachverarbeitungsklopfen: 92
100 Amateur-Sprachverarbeitungsklopfen: 30
100 Amateur-Sprachverarbeitungsklopfen: 06
100 Amateur-Sprachverarbeitungsklopfen: 84
100 Amateur-Sprachverarbeitungsklopfen: 81
100 Amateur-Sprachverarbeitungsklopfen: 33
100 Amateur-Sprachverarbeitungsklopfen: 40
100 Amateur-Sprachverarbeitungsklopfen: 45
100 Amateur-Sprachverarbeitungsklopfen: 43
100 Amateur-Sprachverarbeitungsklopfen: 55
100 Amateur-Sprachverarbeitungsklopfen: 22