One place for hosting & domains

      So erstellen Sie ein neuronales Netz zum Übersetzen der Gebärdensprache ins Englische


      Der Autor hat Code.org ausgewählt, um im Rahmen des Programms Write for DOnations eine Spende zu erhalten.

      Einführung

      Computer Vision (deutsch: computerbasiertes Sehen) ist ein Teilbereich der Informatik, mit dem ein höherrangiges Verstehen von Bildern und Videos ermöglicht werden soll. Damit werden Technologien wie lustige Video-Chat-Filter, die Gesichtserkennung Ihres Mobilgeräts und selbstfahrende Autos unterstützt.

      In diesem Tutorial nutzen Sie Computer Vision, um einen Übersetzer für die amerikanische Gebärdensprache zu entwickeln, der mithilfe Ihrer Webcam arbeitet. Während des Tutorial werden Sie OpenCV, eine Computer-Vision-Bibliothek, PyTorch zum Einrichten eines tiefen neuronalen Netzes und onnx zum Exportieren Ihres neuronalen Netzes verwenden. Zudem werden Sie eine Computer-Vision-Anwendung erstellen und dabei folgende Konzepte anwenden:

      • Sie verwenden dieselbe dreistufige Methode, die auch im Tutorial How To Apply Computer Vision to Build an Emotion-Based Dog Filter (So wenden Sie Computer Vision beim Erstellen eines emotionsbasierten Hundefilters an) genutzt wird: Vorverarbeitung eines Datensatzes, Trainieren eines Modells und Bewertung des Modells.
      • Außerdem werden Sie jeden dieser einzelnen Schritte erweitern: Sie nutzen Data Augmentation (Datenanreicherung) für den Umgang mit gedrehten oder nicht zentrierten Händen, Sie ändern die Learning Rate Schedules (Zeitpläne für die Lernrate), um die Modellgenauigkeit zu verbessern, und Sie exportieren Modelle für eine höhere Inferenzgeschwindigkeit.
      • Überdies werden Sie auch verwandte Konzepte im maschinellen Lernen erkunden.

      Am Ende dieses Tutorials verfügen Sie über einen Übersetzer für die amerikanische Gebärdensprache sowie über ein umfassendes Know-how über das Deep Learning. Sie können auch auf den kompletten Quellcode für dieses Projekt zugreifen.

      Voraussetzungen

      Um dieses Tutorial zu absolvieren, benötigen Sie Folgendes:

      • Eine lokale Entwicklungsumgebung für Python 3 mit mindestens 1 GB RAM. Unter How to Install and Set Up a Local Programming Environment for Python 3 (Installieren und Einrichten einer lokalen Programmierumgebung für Python 3) finden Sie Informationen darüber, wie Sie die benötigten Konfigurationen vornehmen.
      • Eine funktionierende Webcam zur Nutzung der Bilderkennung in Echtzeit.
      • (Empfohlen) Build an Emotion-Based Dog Filter (Erstellen eines emotionsbasierten Hundes); dieses Tutorial wird zwar nicht explizit verwendet, aber es wird dasselbe Wissen vermittelt und darauf aufgebaut.

      Schritt 1 – Erstellen des Projekts und Installieren von Abhängigkeiten

      Wir wollen einen Arbeitsbereich für dieses Projekt erstellen und die Abhängigkeiten installieren, die wir benötigen.

      Beginnen Sie mit den Linux-Distributionen, indem Sie Ihre Systempaketverwaltung vorbereiten und das Python3 virtualenv-Paket installieren. Verwenden Sie Folgendes:

      • apt-get update
      • apt-get upgrade
      • apt-get install python3-venv

      Wir nennen unseren Arbeitsbereich SignLanguage (Gebärdensprache):

      Navigieren Sie zum Verzeichnis SignLanguage:

      Erstellen Sie dann eine neue virtuelle Umgebung für das Projekt:

      • python3 -m venv signlanguage

      Aktivieren Sie Ihre Umgebung:

      • source signlanguage/bin/activate

      Installieren Sie anschließend PyTorch, ein Deep-Learning-Framework für Python, das wir in diesem Tutorial verwenden werden.

      Auf macOS installieren Sie Pytorch mit dem folgenden Befehl:

      • python -m pip install torch==1.2.0 torchvision==0.4.0

      Auf Linux und Windows verwenden Sie die folgenden Befehle für einen reinen CPU-Build:

      • pip install torch==1.2.0+cpu torchvision==0.4.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
      • pip install torchvision

      Installieren Sie nun vorgefertigte Binärdateien für OpenCV, numpy und onnx, die als Bibliotheken für Computer Vision, lineare Algebra, den Export des KI-Modells und die Ausführung des KI-Modells dienen. OpenCV bietet Hilfsfunktionen wie Bilddrehung und numpy bietet Hilfsfunktionen für lineare Algebra an, z. B. eine Matrixinversion:

      • python -m pip install opencv-python==3.4.3.18 numpy==1.14.5 onnx==1.6.0 onnxruntime==1.0.0

      Auf Linux-Distributionen müssen Sie libSM.so installieren:

      • apt-get install libsm6 libxext6 libxrender-dev

      Wenn die Abhängigkeiten installiert wurden, erstellen wir die erste Version unseres Gebärdensprachenübersetzers: einen Gebärdensprachen-Classifier.

      Schritt 2 — Vorbereiten des Datensatzes für die Klassifikation der Gebärdensprache

      In diesen nächsten drei Abschnitten erstellen Sie einen Gebärdensprachen-Classifier mithilfe eines neuronalen Netzes. Ihr Ziel besteht darin, ein Modell zu erstellen, das ein Bild einer Hand als Eingabe annimmt und einen Buchstaben ausgibt.

      Für das Erstellen eines Klassifizierungsmodells für das maschinelle Lernen sind Sie die folgenden drei Schritte erforderlich:

      1. Vorbearbeiten der Daten: Wenden Sie one-hot encoding (One-Hot-Kodierung) auf Ihre Labels an und umschließen Sie Ihre Daten mit PyTorch-Tensoren. Trainieren Sie Ihr Modell auf angereicherten Daten, um es auf „unübliche“ Eingabedaten vorzubereiten, z. B. eine außermittige oder eine gedrehte Hand.
      2. Legen Sie das Modell fest und trainieren Sie es: Richten Sie ein neuronales Netz mit PyTorch ein. Legen Sie die Hyperparameter für das Training fest (z. B. wie lange das Training dauern soll) und führen Sie ein stochastisches Gradientenverfahren durch. Variieren Sie zudem einen bestimmten Hyperparameter für das Training: Learning Rate Schedule. Dadurch wird die Modellgenauigkeit erhöht.
      3. Führen Sie eine Vorhersage mit dem Modell aus: Bewerten Sie das neuronale Netz anhand Ihrer Validierungsdaten, um dessen Genauigkeit zu erfassen. Exportieren Sie dann das Modell in ein Format namens ONNX, um höhere Inferenzgeschwindigkeiten zu erreichen.

      In diesem Abschnitt des Tutorials führen Sie Schritt 1 von 3 durch. Sie werden die Daten herunterladen, ein Dataset-Objekt erstellen, das wiederholt auf Ihre Daten angewendet wird, und abschließend noch die Data Augmentation anwenden. Am Ende dieses Schritts verfügen Sie über ein Programm, mit dem Sie auf Bilder und Labels in Ihrem Datensatz zugreifen können, um Ihr Modell zu füttern.

      Laden Sie zuerst den Datensatz in Ihr aktuelles Arbeitsverzeichnis herunter:

      Anmerkung: Auf makOS ist wget standardmäßig nicht verfügbar. Installieren Sie dazu HomeBrew, indem Sie diesem DigitalOcean Tutorial folgen. Führen Sie dann brew install wget aus.

      • wget https://assets.digitalocean.com/articles/signlanguage_data/sign-language-mnist.tar.gz

      Entzippen Sie die Zip-Datei, die das Verzeichnis data/ enthält:

      • tar -xzf sign-language-mnist.tar.gz

      Erstellen Sie eine neue Datei namens step_2_dataset.py:

      Importieren Sie wie zuvor die erforderlichen Hilfsfunktionen und erstellen Sie die Klasse, die Ihre Daten enthalten soll. Erstellen Sie die Trainings- und Testdaten zum Zwecke der Datenverarbeitung. Sie implementieren die Dataset-Schnittstelle von PyTorch, damit Sie die integrierte Daten-Pipeline von PyTorch laden und für den Datensatz Ihrer Gebärdensprachenklassifikation verwenden können:

      step_2_dataset.py

      from torch.utils.data import Dataset
      from torch.autograd import Variable
      import torch.nn as nn
      import numpy as np
      import torch
      
      import csv
      
      
      class SignLanguageMNIST(Dataset):
          """Sign Language classification dataset.
      
          Utility for loading Sign Language dataset into PyTorch. Dataset posted on
          Kaggle in 2017, by an unnamed author with username `tecperson`:
          https://www.kaggle.com/datamunge/sign-language-mnist
      
          Each sample is 1 x 1 x 28 x 28, and each label is a scalar.
          """
          pass
      

      Löschen Sie den Platzhalter pass in der Klasse SignLanguageMNIST. Fügen Sie an seiner Stelle eine Methode hinzu, um ein Label Mapping zu generieren:

      step_2_dataset.py

          @staticmethod
          def get_label_mapping():
              """
              We map all labels to [0, 23]. This mapping from dataset labels [0, 23]
              to letter indices [0, 25] is returned below.
              """
              mapping = list(range(25))
              mapping.pop(9)
              return mapping
      

      Die Labels reichen von 0 bis 25. Die Buchstaben J (9) und Z (25) sind jedoch ausgeschlossen. Das bedeutet, dass es nur 24 gültige Label-Werte gibt. Damit der Satz aller von 0 ausgehenden Label-Werte zusammenhängend ist, werden alle Labels [0, 23] zugeordnet. Dieses Mapping von den Datensätzen [0, 23] bis zu den Buchstabenindizes [0, 25] wird mithilfe der Methode get_label_mapping herbeigeführt.

      Als Nächstes fügen Sie eine Methode hinzu, um Labels und Beispielproben aus einer CSV-Datei zu extrahieren. Im Folgenden wird davon ausgegangen, dass jede Zeile mit dem label startet, auf das 784-Pixelwerte folgen. Diese 784 Pixelwerte repräsentieren ein 28x28 Bild:

      step_2_dataset.py

          @staticmethod
          def read_label_samples_from_csv(path: str):
              """
              Assumes first column in CSV is the label and subsequent 28^2 values
              are image pixel values 0-255.
              """
              mapping = SignLanguageMNIST.get_label_mapping()
              labels, samples = [], []
              with open(path) as f:
                  _ = next(f)  # skip header
                  for line in csv.reader(f):
                      label = int(line[0])
                      labels.append(mapping.index(label))
                      samples.append(list(map(int, line[1:])))
              return labels, samples
      

      Eine Erklärung darüber, wie diese 784 Werte ein Bild repräsentieren, finden Sie unter Build an Emotion-Based Dog Filter, Step 4 (Erstellen eines emotionsbasierten Hundes, Schritt 4).

      Beachten Sie, dass jede Zeile im csv.reader-Iterable eine Liste von Zeichenfolgen ist; die Aufrufe int und map(int, ...) wandeln alle Zeichenfolgen in Ganzzahlen um. Fügen Sie direkt unter unserer statischen Methode eine Funktion hinzu, die unseren Datenbehälter initialisieren wird:

      step_2_dataset.py

          def __init__(self,
                  path: str="data/sign_mnist_train.csv",
                  mean: List[float]=[0.485],
                  std: List[float]=[0.229]):
              """
              Args:
                  path: Path to `.csv` file containing `label`, `pixel0`, `pixel1`...
              """
              labels, samples = SignLanguageMNIST.read_label_samples_from_csv(path)
              self._samples = np.array(samples, dtype=np.uint8).reshape((-1, 28, 28, 1))
              self._labels = np.array(labels, dtype=np.uint8).reshape((-1, 1))
      
              self._mean = mean
              self._std = std
      

      Diese Funktion startet mit dem Laden von Samples und Labels. Dann umschließt sie die Daten mit NumPy-Arrays. Die mittlere und Standardabweichung wird kurz im folgenden Abschnitt __getitem__ erklärt.

      Fügen Sie direkt nach der Funktion __init__ eine Funktion __len__ hinzu. Diese Methode wird für das Dataset benötigt, um zu ermitteln, wann das Iterieren über die Daten beendet werden muss.

      step_2_dataset.py

      ...
          def __len__(self):
              return len(self._labels)
      

      Fügen Sie abschließend die Methode __getitem__ hinzu, die ein Wörterbuch zurückgibt, das das Sample und das Label enthält:

      step_2_dataset.py

          def __getitem__(self, idx):
              transform = transforms.Compose([
                  transforms.ToPILImage(),
                  transforms.RandomResizedCrop(28, scale=(0.8, 1.2)),
                  transforms.ToTensor(),
                  transforms.Normalize(mean=self._mean, std=self._std)])
      
              return {
                  'image': transform(self._samples[idx]).float(),
                  'label': torch.from_numpy(self._labels[idx]).float()
              }
      

      Sie verwenden eine Technik namens Data Augmentation, bei der Samples während des Trainings gestört werden, um die Robustheit des Modells gegenüber diesen Störungen zu erhöhen. Hierfür wird insbesondere das Bild über RandomResizedCrop in variierenden Werten und an verschiedenen Stellen eingezoomt. Beachten Sie, dass sich das Einzoomen nicht auf die finale Gebärdensprachenklasse auswirken sollte. So wird das Label nicht transformiert. Sie normalisieren die Eingaben zusätzlich, damit die Bildwerte wie erwartet auf den Bereich [0, 1] neu skaliert werden anstatt auf [0, 255]; verwenden Sie bei der Normalisierung den Datensatz _mean und _std, um dies zu erreichen.

      Ihre abgeschlossene Klasse SignLanguageMNIST sieht wie folgt aus:

      step_2_dataset.py

      from torch.utils.data import Dataset
      from torch.autograd import Variable
      import torchvision.transforms as transforms
      import torch.nn as nn
      import numpy as np
      import torch
      
      from typing import List
      
      import csv
      
      
      class SignLanguageMNIST(Dataset):
          """Sign Language classification dataset.
      
          Utility for loading Sign Language dataset into PyTorch. Dataset posted on
          Kaggle in 2017, by an unnamed author with username `tecperson`:
          https://www.kaggle.com/datamunge/sign-language-mnist
      
          Each sample is 1 x 1 x 28 x 28, and each label is a scalar.
          """
      
          @staticmethod
          def get_label_mapping():
              """
              We map all labels to [0, 23]. This mapping from dataset labels [0, 23]
              to letter indices [0, 25] is returned below.
              """
              mapping = list(range(25))
              mapping.pop(9)
              return mapping
      
          @staticmethod
          def read_label_samples_from_csv(path: str):
              """
              Assumes first column in CSV is the label and subsequent 28^2 values
              are image pixel values 0-255.
              """
              mapping = SignLanguageMNIST.get_label_mapping()
              labels, samples = [], []
              with open(path) as f:
                  _ = next(f)  # skip header
                  for line in csv.reader(f):
                      label = int(line[0])
                      labels.append(mapping.index(label))
                      samples.append(list(map(int, line[1:])))
              return labels, samples
      
          def __init__(self,
                  path: str="data/sign_mnist_train.csv",
                  mean: List[float]=[0.485],
                  std: List[float]=[0.229]):
              """
              Args:
                  path: Path to `.csv` file containing `label`, `pixel0`, `pixel1`...
              """
              labels, samples = SignLanguageMNIST.read_label_samples_from_csv(path)
              self._samples = np.array(samples, dtype=np.uint8).reshape((-1, 28, 28, 1))
              self._labels = np.array(labels, dtype=np.uint8).reshape((-1, 1))
      
              self._mean = mean
              self._std = std
      
          def __len__(self):
              return len(self._labels)
      
          def __getitem__(self, idx):
              transform = transforms.Compose([
                  transforms.ToPILImage(),
                  transforms.RandomResizedCrop(28, scale=(0.8, 1.2)),
                  transforms.ToTensor(),
                  transforms.Normalize(mean=self._mean, std=self._std)])
      
              return {
                  'image': transform(self._samples[idx]).float(),
                  'label': torch.from_numpy(self._labels[idx]).float()
              }
      

      Wie zuvor überprüfen Sie unsere Datensatz-Hilfsfunktionen, indem Sie den Datensatz SignLanguageMNIST laden. Fügen Sie am Ende Ihrer Datei hinter der Klasse SignLanguageMNIST den folgenden Code hinzu:

      step_2_dataset.py

      def get_train_test_loaders(batch_size=32):
          trainset = SignLanguageMNIST('data/sign_mnist_train.csv')
          trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True)
      
          testset = SignLanguageMNIST('data/sign_mnist_test.csv')
          testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False)
          return trainloader, testloader
      

      Dieser Code initialisiert den Datensatz mithilfe der Klasse SignLanguageMNIST. Für die Trainings- und Validierungssätze wird dann der Datensatz mit einem DataLoader umschlossen. Dadurch wird der Datensatz für den späteren Gebrauch in ein Iterable umgewandelt.

      Nun überprüfen Sie, ob die Datensatz-Hilfsfunktionen funktionieren. Erstellen Sie einen Sample-Datensatz-Loader mithilfe von DataLoader und drucken Sie das erste Element dieses Loaders aus. Fügen Sie Folgendes am Ende der Datei hinzu:

      step_2_dataset.py

      if __name__ == '__main__':
          loader, _ = get_train_test_loaders(2)
          print(next(iter(loader)))
      

      Sie können überprüfen, ob Ihre Datei mit der Datei step_2_dataset in diesem (repository) übereinstimmt. Beenden Sie Ihren Editor und führen Sie das Skript mit Folgendem aus:

      Dadurch werden folgende Tensoren paarweise ausgegeben. Unsere Datenpipeline gibt zwei Samples und zwei Labels aus. Dies zeigt an, dass unsere Datenpipeline eingerichtet ist und bereit ist, fortzufahren:

      Output

      {'image': tensor([[[[ 0.4337, 0.5022, 0.5707, ..., 0.9988, 0.9646, 0.9646], [ 0.4851, 0.5536, 0.6049, ..., 1.0502, 1.0159, 0.9988], [ 0.5364, 0.6049, 0.6392, ..., 1.0844, 1.0844, 1.0673], ..., [-0.5253, -0.4739, -0.4054, ..., 0.9474, 1.2557, 1.2385], [-0.3369, -0.3369, -0.3369, ..., 0.0569, 1.3584, 1.3242], [-0.3712, -0.3369, -0.3198, ..., 0.5364, 0.5364, 1.4783]]], [[[ 0.2111, 0.2796, 0.3481, ..., 0.2453, -0.1314, -0.2342], [ 0.2624, 0.3309, 0.3652, ..., -0.3883, -0.0629, -0.4568], [ 0.3309, 0.3823, 0.4337, ..., -0.4054, -0.0458, -1.0048], ..., [ 1.3242, 1.3584, 1.3927, ..., -0.4054, -0.4568, 0.0227], [ 1.3242, 1.3927, 1.4612, ..., -0.1657, -0.6281, -0.0287], [ 1.3242, 1.3927, 1.4440, ..., -0.4397, -0.6452, -0.2856]]]]), 'label': tensor([[24.], [11.]])}

      Sie haben nun sichergestellt, dass Ihre Datenpipeline funktioniert. Damit ist der erste Schritt – die Verarbeitung Ihrer Daten – abgeschlossen. Nun beinhaltet sie Data Augmentation für eine erhöhte Modellstabilität. Als Nächstes definieren Sie das neuronale Netz und den Optimierer.

      Schritt 3 – Erstellen und Trainieren des Gebärdensprachen-Classifiers mittels Deep Learning

      Mit einer funktionierenden Datenpipeline definieren Sie nun ein Modell und trainieren es anhand der Daten. Insbesondere erstellen Sie ein neuronales Netz mit sechs Schichten, definieren einen Verlust, einen Optimierer und optimieren abschließend die Verlustfunktion für die Voraussagen mit Ihrem neuronalen Netz. Am Ende dieses Schritts verfügen Sie über einen funktionierenden Gebärdensprachen-Klassifizierer.

      Erstellen Sie eine neue Datei namens step_3_train.py:

      Importieren Sie die erforderlichen Dienstprogramme:

      step_3_train.py

      from torch.utils.data import Dataset
      from torch.autograd import Variable
      import torch.nn as nn
      import torch.nn.functional as F
      import torch.optim as optim
      import torch
      
      from step_2_dataset import get_train_test_loaders
      

      Definieren Sie ein neuronales PyTorch-Netz, das drei Convolutional Layers (faltende Schichten) enthält, gefolgt von drei vollständig zusammenhängenden Schichten. Fügen Sie dies am Ende Ihres bestehenden Skripts hinzu:

      step_3_train.py

      class Net(nn.Module):
          def __init__(self):
              super(Net, self).__init__()
              self.conv1 = nn.Conv2d(1, 6, 3)
              self.pool = nn.MaxPool2d(2, 2)
              self.conv2 = nn.Conv2d(6, 6, 3)
              self.conv3 = nn.Conv2d(6, 16, 3)
              self.fc1 = nn.Linear(16 * 5 * 5, 120)
              self.fc2 = nn.Linear(120, 48)
              self.fc3 = nn.Linear(48, 24)
      
          def forward(self, x):
              x = F.relu(self.conv1(x))
              x = self.pool(F.relu(self.conv2(x)))
              x = self.pool(F.relu(self.conv3(x)))
              x = x.view(-1, 16 * 5 * 5)
              x = F.relu(self.fc1(x))
              x = F.relu(self.fc2(x))
              x = self.fc3(x)
              return x
      

      Initialisieren Sie nun das neuronale Netz, definieren Sie eine Verlustfunktion und legen Sie Hyperparameter zur Optimierung fest, indem Sie am Ende des Skripts den folgenden Code hinzufügen:

      step_3_train.py

      def main():
          net = Net().float()
          criterion = nn.CrossEntropyLoss()
          optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)
      

      Schließlich trainieren Sie es für zwei Epochen:

      step_3_train.py

      def main():
          net = Net().float()
          criterion = nn.CrossEntropyLoss()
          optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)
      
          trainloader, _ = get_train_test_loaders()
          for epoch in range(2):  # loop over the dataset multiple times
              train(net, criterion, optimizer, trainloader, epoch)
          torch.save(net.state_dict(), "checkpoint.pth")
      

      Sie definieren eine Epoche, die eine Iteration des Trainings ist, bei der jedes Trainings-Sample genau einmal verwendet wurde. Am Ende der Hauptfunktion werden die Modellparameter in einer Datei namens „checkpoint.pth“ gespeichert.

      Fügen Sie am Ende Ihres Skripts den folgenden Code hinzu, um Bild und Label aus dem Datensatz-Loader zu extrahieren und dann jede mit einer PyTorch Variable zu umschließen:

      step_3_train.py

      def train(net, criterion, optimizer, trainloader, epoch):
          running_loss = 0.0
          for i, data in enumerate(trainloader, 0):
              inputs = Variable(data['image'].float())
              labels = Variable(data['label'].long())
              optimizer.zero_grad()
      
              # forward + backward + optimize
              outputs = net(inputs)
              loss = criterion(outputs, labels[:, 0])
              loss.backward()
              optimizer.step()
      
              # print statistics
              running_loss += loss.item()
              if i % 100 == 0:
                  print('[%d, %5d] loss: %.6f' % (epoch, i, running_loss / (i + 1)))
      

      Dieser Code führt auch die Vorwärtsrechnung und dann die Fehlerrückführung über den Verlust und das neuronale Netz aus.

      Fügen Sie am Ende Ihrer Datei Folgendes hinzu, um die Funktion main aufzurufen:

      step_3_train.py

      if __name__ == '__main__':
          main()
      

      Prüfen Sie nochmals, ob Ihre Datei dem Folgenden entspricht:

      step_3_train.py

      from torch.utils.data import Dataset
      from torch.autograd import Variable
      import torch.nn as nn
      import torch.nn.functional as F
      import torch.optim as optim
      import torch
      
      from step_2_dataset import get_train_test_loaders
      
      
      class Net(nn.Module):
          def __init__(self):
              super(Net, self).__init__()
              self.conv1 = nn.Conv2d(1, 6, 3)
              self.pool = nn.MaxPool2d(2, 2)
              self.conv2 = nn.Conv2d(6, 6, 3)
              self.conv3 = nn.Conv2d(6, 16, 3)
              self.fc1 = nn.Linear(16 * 5 * 5, 120)
              self.fc2 = nn.Linear(120, 48)
              self.fc3 = nn.Linear(48, 25)
      
          def forward(self, x):
              x = F.relu(self.conv1(x))
              x = self.pool(F.relu(self.conv2(x)))
              x = self.pool(F.relu(self.conv3(x)))
              x = x.view(-1, 16 * 5 * 5)
              x = F.relu(self.fc1(x))
              x = F.relu(self.fc2(x))
              x = self.fc3(x)
              return x
      
      
      def main():
          net = Net().float()
          criterion = nn.CrossEntropyLoss()
          optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)
      
          trainloader, _ = get_train_test_loaders()
          for epoch in range(2):  # loop over the dataset multiple times
              train(net, criterion, optimizer, trainloader, epoch)
          torch.save(net.state_dict(), "checkpoint.pth")
      
      
      def train(net, criterion, optimizer, trainloader, epoch):
          running_loss = 0.0
          for i, data in enumerate(trainloader, 0):
              inputs = Variable(data['image'].float())
              labels = Variable(data['label'].long())
              optimizer.zero_grad()
      
              # forward + backward + optimize
              outputs = net(inputs)
              loss = criterion(outputs, labels[:, 0])
              loss.backward()
              optimizer.step()
      
              # print statistics
              running_loss += loss.item()
              if i % 100 == 0:
                  print('[%d, %5d] loss: %.6f' % (epoch, i, running_loss / (i + 1)))
      
      
      if __name__ == '__main__':
          main()
      

      Speichern und schließen Sie sie. Starten Sie dann unser Proof-of-Concept-Training, indem Sie Folgendes ausführen:

      Während das neuronale Netz trainiert wird, sehen Sie ein Ergebnis, das dem Folgenden ähnelt:

      Output

      [0, 0] loss: 3.208171 [0, 100] loss: 3.211070 [0, 200] loss: 3.192235 [0, 300] loss: 2.943867 [0, 400] loss: 2.569440 [0, 500] loss: 2.243283 [0, 600] loss: 1.986425 [0, 700] loss: 1.768090 [0, 800] loss: 1.587308 [1, 0] loss: 0.254097 [1, 100] loss: 0.208116 [1, 200] loss: 0.196270 [1, 300] loss: 0.183676 [1, 400] loss: 0.169824 [1, 500] loss: 0.157704 [1, 600] loss: 0.151408 [1, 700] loss: 0.136470 [1, 800] loss: 0.123326

      Um die Verluste niedrig zu halten, können Sie die Anzahl der Epochen auf 5, 10 oder sogar 20 erhöhen. Nach einer bestimmten Trainingszeit wird sich der Netzverlust trotz einer Steigerung der Trainingszeit nicht mehr verringern. Geben Sie einen Learning Rate Schedule vor, der die Lernrate im Laufe der Zeit verringert, um das Problem zu umgehen, das mit der zunehmenden Trainingszeit einhergeht. Wenn Sie verstehen wollen, warum das funktioniert, sehen Sie sich die Visualisierung von Distill an unter „Why Momentum Really Works“ („Warum das Momentum wirklich funktioniert“).

      Ändern Sie Ihre Funktion main mit den folgenden zwei Zeilen ab, definieren Sie einen Scheduler und rufen Sie scheduler.step auf. Ändern Sie außerdem die Anzahl der Epochen in 12:

      step_3_train.py

      def main():
          net = Net().float()
          criterion = nn.CrossEntropyLoss()
          optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)
          scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
      
          trainloader, _ = get_train_test_loaders()
          for epoch in range(12):  # loop over the dataset multiple times
              train(net, criterion, optimizer, trainloader, epoch)
              scheduler.step()
          torch.save(net.state_dict(), "checkpoint.pth")
      

      Überprüfen Sie, ob Ihre Datei mit der Datei aus Schritt 3 in diesem Repository übereinstimmt. Die Ausführung des Trainings dauert etwa 5 Minuten. Ihre Ausgabe wird in etwa wie folgt aussehen:

      Output

      [0, 0] loss: 3.208171 [0, 100] loss: 3.211070 [0, 200] loss: 3.192235 [0, 300] loss: 2.943867 [0, 400] loss: 2.569440 [0, 500] loss: 2.243283 [0, 600] loss: 1.986425 [0, 700] loss: 1.768090 [0, 800] loss: 1.587308 ... [11, 0] loss: 0.000302 [11, 100] loss: 0.007548 [11, 200] loss: 0.009005 [11, 300] loss: 0.008193 [11, 400] loss: 0.007694 [11, 500] loss: 0.008509 [11, 600] loss: 0.008039 [11, 700] loss: 0.007524 [11, 800] loss: 0.007608

      Der erhaltene Verlust beträgt 0,007608, was 3 Größenordnungen kleiner als der anfängliche Verlust von 3,20 ist. Damit wird der zweite Schritt unseres Workflows abgeschlossen, in dem wir das neuronale Netz eingerichtet und trainiert haben. Doch auch ein kleiner Verlust hat eine Bedeutung, wenn auch nur eine sehr kleine. Um die Leistung des Modells in Perspektive zu setzen, werden wir seine Genauigkeit berechnen – der Prozentsatz der Bilder, die das Modell richtig klassifiziert hat.

      Schritt 4 – Bewerten des Gebärdensprachen-Classifiers

      Sie werden nun Ihren Gebärdensprachen-Klassifizierer bewerten, indem Sie seine Genauigkeit im Validierungssatz berechnen, ein Satz von Bildern, die das Modell während des Trainings nicht gesehen hat. Dadurch erhalten wir ein besseres Bild über die Leistung des Modells als durch den endgültigen Verlustwert. Zudem fügen Sie Dienstprogramme hinzu, um unser trainiertes Modell am Ende des Trainings zu speichern, und laden unser vorab trainiertes Modell, während die Inferenz durchgeführt wird.

      Erstellen Sie eine neue Datei namens step_4_evaluate.py.

      Importieren Sie die erforderlichen Hilfsfunktionen:

      step_4_evaluate.py

      from torch.utils.data import Dataset
      from torch.autograd import Variable
      import torch.nn as nn
      import torch.nn.functional as F
      import torch.optim as optim
      import torch
      import numpy as np
      
      import onnx
      import onnxruntime as ort
      
      from step_2_dataset import get_train_test_loaders
      from step_3_train import Net
      

      Definieren Sie als Nächstes eine Hilfsfunktion, um die Leistung des neuronalen Netzes zu bewerten. Die folgende Funktion vergleicht den vom neuronalen Netz vorhergesagten Buchstaben mit dem tatsächlichen Buchstaben:

      step_4_evaluate.py

      def evaluate(outputs: Variable, labels: Variable) -> float:
          """Evaluate neural network outputs against non-one-hotted labels."""
          Y = labels.numpy()
          Yhat = np.argmax(outputs, axis=1)
          return float(np.sum(Yhat == Y))
      

      outputs ist eine Liste von Klassenwahrscheinlichkeiten für jedes Sample. Beispielsweise können Outputs für ein einziges Sample [0,1, 0,3, 0,4,] betragen. labels ist eine Liste von Label-Klassen. Die Label-Klasse kann beispielsweise 3 sein.

      Y = ... wandelt die Labels in ein NumPy-Array um. Als Nächstes konvertiert Yhat = np.argmax(...) die Wahrscheinlichkeiten der Klasse outputs in vorausgesagte Klassen. Die Liste der Klassenwahrscheinlichkeiten [0,1, 0,3, 0,4, 0,2] würde die vorausgesagte Klasse 2 ergeben, da der Indexwert 2 von 0,4 der größte Wert ist.

      Da Y und Yhat nun Klassen sind, können Sie sie vergleichen. Yhat == Y prüft, ob die vorhergesagte Klasse mit der Label-Klasse übereinstimmt, und np.sum(...) ist ein Trick, der die Anzahl der truth-y-Werte berechnet. Anders ausgedrückt: np.sum gibt die Anzahl der Samples aus, die richtig klassifiziert wurden.

      Fügen Sie die zweite Funktion batch_evaluate hinzu, die die erste Funktion evaluate auf alle Bilder anwendet:

      step_4_evaluate.py

      def batch_evaluate(
              net: Net,
              dataloader: torch.utils.data.DataLoader) -> float:
          """Evaluate neural network in batches, if dataset is too large."""
          score = n = 0.0
          for batch in dataloader:
              n += len(batch['image'])
              outputs = net(batch['image'])
              if isinstance(outputs, torch.Tensor):
                  outputs = outputs.detach().numpy()
              score += evaluate(outputs, batch['label'][:, 0])
          return score / n
      

      Batch ist eine Gruppe von Bildern, die als ein einzelner Tensor gespeichert werden. Zuerst erhöhen Sie die Gesamtzahl der Bilder, die Sie evaluieren (n) um die Anzahl der Bilder in diesem Batch. Als Nächstes führen Sie in dem neuronalen Netz eine Inferenz mit diesem Batch von Bildern aus, outputs = net(...). Die Typenprüfung if isinstance(...) konvertiert die Ergebnisse in einen NumPy-Array bei Bedarf. Schließlich verwenden Sie evaluate, um die Anzahl der richtig klassifizierten Samples zu berechnen. Am Ende der Funktion berechnen Sie den prozentualen Anteil der Samples, die Sie richtig klassifiziert haben, score / n.

      Fügen Sie abschließend das folgende Skript hinzu, um die vorherigen Hilfsfunktionen zu nutzen:

      step_4_evaluate.py

      def validate():
          trainloader, testloader = get_train_test_loaders()
          net = Net().float()
      
          pretrained_model = torch.load("checkpoint.pth")
          net.load_state_dict(pretrained_model)
      
          print('=' * 10, 'PyTorch', '=' * 10)
          train_acc = batch_evaluate(net, trainloader) * 100.
          print('Training accuracy: %.1f' % train_acc)
          test_acc = batch_evaluate(net, testloader) * 100.
          print('Validation accuracy: %.1f' % test_acc)
      
      
      if __name__ == '__main__':
          validate()
      

      Dadurch wird ein vorab trainiertes neuronales Netz geladen und seine Leistung auf dem bereitgestellten Gebärdensprachen-Datensatz bewertet. Das Skript gibt hier insbesondere Genauigkeit über die Bilder aus, die Sie für das Training verwendet haben, und einen separaten Satz von Bildern, die Sie für Testzwecke aufgehoben haben und die validation set heißen.

      Als Nächstes exportieren Sie das PyTorch in eine ONNX-Binärdatei. Diese Binärdatei kann dann in der Produktion verwendet werden, um mit Ihrem Modell eine Inferenz auszuführen. Am wichtigsten ist, dass der Code, der diese Binärdatei ausführt, keine Kopie der ursprünglichen Netzwerkdefinition benötigt. Fügen Sie am Ende der Funktion validate Folgendes hinzu:

      step_4_evaluate.py

          trainloader, testloader = get_train_test_loaders(1)
      
          # export to onnx
          fname = "signlanguage.onnx"
          dummy = torch.randn(1, 1, 28, 28)
          torch.onnx.export(net, dummy, fname, input_names=['input'])
      
          # check exported model
          model = onnx.load(fname)
          onnx.checker.check_model(model)  # check model is well-formed
      
          # create runnable session with exported model
          ort_session = ort.InferenceSession(fname)
          net = lambda inp: ort_session.run(None, {'input': inp.data.numpy()})[0]
      
          print('=' * 10, 'ONNX', '=' * 10)
          train_acc = batch_evaluate(net, trainloader) * 100.
          print('Training accuracy: %.1f' % train_acc)
          test_acc = batch_evaluate(net, testloader) * 100.
          print('Validation accuracy: %.1f' % test_acc)
      

      Dadurch wird das ONNX-Modell exportiert, das exportierte Modell überprüft und dann eine Inferenz mit dem exportierten Modell ausgeführt. Überprüfen Sie nochmals, ob Ihre Datei mit der Datei aus Schritt 4 in diesem Repository übereinstimmt.

      step_4_evaluate.py

      from torch.utils.data import Dataset
      from torch.autograd import Variable
      import torch.nn as nn
      import torch.nn.functional as F
      import torch.optim as optim
      import torch
      import numpy as np
      
      import onnx
      import onnxruntime as ort
      
      from step_2_dataset import get_train_test_loaders
      from step_3_train import Net
      
      
      def evaluate(outputs: Variable, labels: Variable) -> float:
          """Evaluate neural network outputs against non-one-hotted labels."""
          Y = labels.numpy()
          Yhat = np.argmax(outputs, axis=1)
          return float(np.sum(Yhat == Y))
      
      
      def batch_evaluate(
              net: Net,
              dataloader: torch.utils.data.DataLoader) -> float:
          """Evaluate neural network in batches, if dataset is too large."""
          score = n = 0.0
          for batch in dataloader:
              n += len(batch['image'])
              outputs = net(batch['image'])
              if isinstance(outputs, torch.Tensor):
                  outputs = outputs.detach().numpy()
              score += evaluate(outputs, batch['label'][:, 0])
          return score / n
      
      
      def validate():
          trainloader, testloader = get_train_test_loaders()
          net = Net().float().eval()
      
          pretrained_model = torch.load("checkpoint.pth")
          net.load_state_dict(pretrained_model)
      
          print('=' * 10, 'PyTorch', '=' * 10)
          train_acc = batch_evaluate(net, trainloader) * 100.
          print('Training accuracy: %.1f' % train_acc)
          test_acc = batch_evaluate(net, testloader) * 100.
          print('Validation accuracy: %.1f' % test_acc)
      
          trainloader, testloader = get_train_test_loaders(1)
      
          # export to onnx
          fname = "signlanguage.onnx"
          dummy = torch.randn(1, 1, 28, 28)
          torch.onnx.export(net, dummy, fname, input_names=['input'])
      
          # check exported model
          model = onnx.load(fname)
          onnx.checker.check_model(model)  # check model is well-formed
      
          # create runnable session with exported model
          ort_session = ort.InferenceSession(fname)
          net = lambda inp: ort_session.run(None, {'input': inp.data.numpy()})[0]
      
          print('=' * 10, 'ONNX', '=' * 10)
          train_acc = batch_evaluate(net, trainloader) * 100.
          print('Training accuracy: %.1f' % train_acc)
          test_acc = batch_evaluate(net, testloader) * 100.
          print('Validation accuracy: %.1f' % test_acc)
      
      
      if __name__ == '__main__':
          validate()
      

      Führen Sie Folgendes aus, um den Checkpoint vom letzten Schritt zu verwenden und zu evaluieren:

      • python step_4_evaluate.py

      Dadurch erhalten Sie eine ähnliche Ausgabe wie die Folgende, die nicht nur bestätigt, dass Ihr exportiertes Modell funktioniert, sondern auch Ihr ursprüngliches PyTorch-Modell bestätigt:

      Output

      ========== PyTorch ========== Training accuracy: 99.9 Validation accuracy: 97.4 ========== ONNX ========== Training accuracy: 99.9 Validation accuracy: 97.4

      Ihr neuronales Netz erreicht eine Trainingsgenauigkeit von 99,9 % und eine Validierungsgenauigkeit von 97,4 %. Diese Lücke zwischen Trainings- und Validierungsgenauigkeit deutet auf eine Überanpassung Ihres Modells hin. Das heißt, dass Ihr Modell die Trainingsdaten gespeichert hat, anstatt generalisierbare Muster zu erlernen. Weiterführende Informationen zu den Implikationen und Ursachen der Überanpassung finden Sie in Understanding Bias-Variance Tradeoffs (Das Spannungsfeld von Verzerrungsvarianzen verstehen).

      Nun haben wir einen Gebärdensprachen-Klassifizierer fertiggestellt. Im Grunde genommen kann unser Modell die Gebärden fast immer korrekt erkennen und voneinander unterscheiden. Da dies bereits ein recht gutes Modell ist, fahren wir nun mit der letzten Stufe unserer Anwendung fort. Wir werden diesen Gebärdensprachen-Classifier in einer Webcam-Anwendung in Echtzeit einsetzen.

      Schritt 5 – Verknüpfen der Kameraaufzeichnungen

      Ihr nächstes Ziel besteht darin, die Kamera des Computers mit Ihrem Gebärdensprachen-Klassifizierer zu verknüpfen. Sie erfassen die Eingangsdaten der Kamera, klassifizieren die angezeigte Gebärdensprache und melden dann die klassifizierte Gebärde an den Benutzer zurück.

      Erstellen Sie nun ein Python-Skript für die Gesichtserkennung. Erstellen Sie die Datei step_6_camera.py mit nano oder Ihrem bevorzugten Texteditor:

      Fügen Sie in der Datei den folgenden Code hinzu:

      step_5_camera.py

      """Test for sign language classification"""
      import cv2
      import numpy as np
      import onnxruntime as ort
      
      def main():
          pass
      
      if __name__ == '__main__':
          main()
      

      Dieser Code importiert OpenCV, die Ihre Bildprogramme enthält, und die ONNX-Laufzeit. Das ist alles, was Sie mit Ihrem Modell in der Inferenz ausführen müssen. Der Rest des Codes ist eine typische Python-Programmvorgabe.

      Ersetzen Sie nun pass in der Funktion main durch den folgenden Code, der einen Gebärdensprachen-Classifier mit den zuvor trainierten Parametern initialisiert. Fügen Sie zudem ein Mapping zwischen den Indizes und den Buchstaben sowie den Bildstatistiken hinzu:

      step_5_camera.py

      def main():
          # constants
          index_to_letter = list('ABCDEFGHIKLMNOPQRSTUVWXY')
          mean = 0.485 * 255.
          std = 0.229 * 255.
      
          # create runnable session with exported model
          ort_session = ort.InferenceSession("signlanguage.onnx")
      

      Sie werden Elemente dieses Testskripts aus der offiziellen OpenCV verwenden. Aktualisieren Sie insbesondere den Körper der Funktion main. Zuerst initialisieren Sie ein VideoCapture-Objekt, das so eingestellt ist, dass es Live-Einspeisungen von der Kamera Ihres Computers erfassen kann. Platzieren Sie das ans Ende der Funktion main:

      step_5_camera.py

      def main():
          ...
          # create runnable session with exported model
          ort_session = ort.InferenceSession("signlanguage.onnx")
      
          cap = cv2.VideoCapture(0)
      

      Fügen Sie dann eine while-Schleife hinzu, die bei jedem Zeitschritt von der Kamera liest:

      step_5_camera.py

      def main():
          ...
          cap = cv2.VideoCapture(0)
          while True:
              # Capture frame-by-frame
              ret, frame = cap.read()
      

      Schreiben Sie eine Hilfsfunktion, die das zentrale Cropping für das Kamerabild übernimmt. Platzieren Sie diese Funktion vor main:

      step_5_camera.py

      def center_crop(frame):
          h, w, _ = frame.shape
          start = abs(h - w) // 2
          if h > w:
              frame = frame[start: start + w]
          else:
              frame = frame[:, start: start + h]
          return frame
      

      Führen Sie als Nächstes das zentrale Cropping für das Kamerabild durch, konvertieren Sie es in Graustufen, normalisieren Sie es and ändern Sie die Größe auf 28x28. Platzieren Sie dies in die while-Schleife innerhalb der Funktion main:

      step_5_camera.py

      def main():
          ...
          while True:
              # Capture frame-by-frame
              ret, frame = cap.read()
      
              # preprocess data
              frame = center_crop(frame)
              frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
              x = cv2.resize(frame, (28, 28))
              x = (frame - mean) / std
      

      Führen Sie noch innerhalb der while-Schleife eine Inferenz mit der ONNX-Laufzeit aus. Konvertieren Sie die Ausgaben in einen Klassenindex und dann in einen Buchstaben:

      step_5_camera.py

              ...
              x = (frame - mean) / std
      
              x = x.reshape(1, 1, 28, 28).astype(np.float32)
              y = ort_session.run(None, {'input': x})[0]
      
              index = np.argmax(y, axis=1)
              letter = index_to_letter[int(index)]
      

      Zeigen Sie den vorhergesagten Buchstaben innerhalb des Bildrahmens und das Bild wieder dem Benutzer an:

      step_5_camera.py

              ...
              letter = index_to_letter[int(index)]
      
              cv2.putText(frame, letter, (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 2.0, (0, 255, 0), thickness=2)
              cv2.imshow("Sign Language Translator", frame)
      

      Fügen Sie am Ende der while-Schleife diesen Code hinzu, um zu prüfen, ob der Benutzer das Zeichen q wählt und falls das der Fall ist, beenden Sie die Anwendung. Diese Zeile hält das Programm für 1 Millisekunde an. Fügen Sie Folgendes hinzu:

      step_5_camera.py

              ...
              cv2.imshow("Sign Language Translator", frame)
      
              if cv2.waitKey(1) & 0xFF == ord('q'):
                  break
      

      Lösen Sie abschließend die Aufnahme aus und schließen Sie alle Fenster. Platzieren Sie sie außerhalb der while-Schleife, um die Funktion main zu beenden.

      step_5_camera.py

      ...
      
          while True:
              ...
              if cv2.waitKey(1) & 0xFF == ord('q'):
                  break
      
      
          cap.release()
          cv2.destroyAllWindows()
      

      Überprüfen Sie nochmals, ob Ihre Datei mit dem folgenden oder diesem Repository übereinstimmt:

      step_5_camera.py

      import cv2
      import numpy as np
      import onnxruntime as ort
      
      
      def center_crop(frame):
          h, w, _ = frame.shape
          start = abs(h - w) // 2
          if h > w:
              return frame[start: start + w]
          return frame[:, start: start + h]
      
      
      def main():
          # constants
          index_to_letter = list('ABCDEFGHIKLMNOPQRSTUVWXY')
          mean = 0.485 * 255.
          std = 0.229 * 255.
      
          # create runnable session with exported model
          ort_session = ort.InferenceSession("signlanguage.onnx")
      
          cap = cv2.VideoCapture(0)
          while True:
              # Capture frame-by-frame
              ret, frame = cap.read()
      
              # preprocess data
              frame = center_crop(frame)
              frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
              x = cv2.resize(frame, (28, 28))
              x = (x - mean) / std
      
              x = x.reshape(1, 1, 28, 28).astype(np.float32)
              y = ort_session.run(None, {'input': x})[0]
      
              index = np.argmax(y, axis=1)
              letter = index_to_letter[int(index)]
      
              cv2.putText(frame, letter, (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 2.0, (0, 255, 0), thickness=2)
              cv2.imshow("Sign Language Translator", frame)
      
              if cv2.waitKey(1) & 0xFF == ord('q'):
                  break
      
          cap.release()
          cv2.destroyAllWindows()
      
      if __name__ == '__main__':
          main()
      

      Schließen Sie Ihre Datei und führen Sie das Skript aus.

      Sobald das Skript ausgeführt wird, wird ein Fenster mit der Live-Einspeisung der Webcam angezeigt. Der vorhergesagte Gebärdensprachenbuchstabe wird oben links angezeigt. Halten Sie die Hand hoch und machen Sie Ihre Lieblingsgebärde, um Ihren Classifier in Aktion zu sehen. Hier sind einige Beispiel-Ergebnisse, die den Buchstaben L und D zeigen.

      Screenshot Ihres Sample-OpenCV-Programms für den Fingerbuchstaben ‚L‘.
       Screenshot Ihres Sample-OpenCV-Programms für den Fingerbuchstaben ,D‘.

      Beachten Sie während des Tests, dass der Hintergrund für diesen Übersetzer ziemlich klar sein muss, damit er funktioniert. Dies bringt die Sauberkeit des Datensatzes leider mit sich. Würde der Datensatz Bilder von Handzeichen mit verschiedenen Hintergründen enthalten, hätte das Netz kein Problem mit rauschenden Hintergründen. Der Datensatz bietet jedoch leere Hintergründe und ziemlich zentrierte Hände. Die Webcam funktioniert daher am besten, wenn die Hand ebenfalls zentriert ist und sich vor einem leeren Hintergrund befindet.

      Damit ist die Übersetzungsanwendung für die Gebärdensprache vollendet.

      Zusammenfassung

      In diesem Tutorial haben Sie einen Übersetzer für die amerikanische Gebärdensprache mittels Computer Vision und einem Modell für maschinelles Lernen entwickelt. Sie haben vor allem neue Aspekte des Trainings eines Modells für maschinelles Lernen gesehen – genauer gesagt Data Augmentation für die Modellstabilität, Learning Rate Schedules für geringere Verluste und Exportvorgänge von KI-Modellen mithilfe von ONNX zu Produktionszwecken. Dies führte schlussendlich zu der Schaffung einer Echtzeit-Computer-Vision-Anwendung, die Gebärdensprache mithilfe einer Pipeline, die Sie erstellt haben, in Buchstaben übersetzt. Es sollte allerdings bedacht werden, dass der finale Klassifizierer instabil ist. Glücklicherweise gibt es jedoch Methoden, die man einzeln oder auch zusammen einsetzen kann, um gegen diese Instabilität vorzugehen. Diese stellen wir nachfolgend vor. Die folgenden Themen beinhalten weiterführende Erläuterungen zu Verbesserung Ihrer Anwendung:

      • Generalisierung: Hierbei handelt es sich keineswegs um einen Unterbereich von Computer Vision, sondern um ein beständiges Problem, das im Grunde bei jedem Aspekt zum Thema maschinelles Lernen auftritt. Siehe Understanding Bias-Variance Tradeoffs​​​ (Das Spannungsfeld von Verzerrungsvarianzen verstehen)​​​
      • Domain Adaptation (Domänenanpassung): Angenommen, Ihr Modell ist für Domäne A trainiert (z. B. sonnige Umgebungen). Können Sie das Modell in diesem Fall auf Domäne B umstellen (z. B. wolkige Umgebungen)?
      • Adversarial Examples (gegnerische Beispiele): Angenommen ein Kontrahent erstellt absichtlich Bilder, um Ihr Modell zu täuschen. Wie können Sie solche Bilder gestalten? Wie können Sie gegen solche Bilder vorgehen?



      Source link

      So konfigurieren Sie Apache HTTP mit MPM Event und PHP-FPM unter Ubuntu 18.04


      Der Autor hat den COVID-19 Relief Fund dazu ausgewählt, eine Spende im Rahmen des Programms Write for DOnations zu erhalten.

      Einführung

      Der Apache-HTTP-Webserver wurde im Laufe der Jahre weiterentwickelt, damit er in verschiedenen Umgebungen arbeitet und verschiedene Anforderungen erfüllt. Ein wichtiges Problem, das Apache HTTP wie jeder andere Webserver auch lösen muss, ist die Handhabung verschiedener Prozesse bei der Bearbeitung von http-basierten Anfragen. Dazu zählt das Öffnen eines Sockets, das die Anforderung verarbeitet, das Offenhalten der Verbindung für eine bestimmte Zeit, die Handhabung neuer Ereignisse, die während dieser Verbindung eintreten und die Rückgabe des produzierten Contents durch ein Programm, dass in einer bestimmten Sprache geschrieben wurde (wie PHP, Perl oder Python). Diese Aufgaben werden von einem Multi-Processing-Module (MPM) ausgeführt und gesteuert.

      Apache HTTP ist mit drei verschiedenen MPM ausgestattet:

      • Prefork: Für jede eingehende Verbindung, die den Server erreicht, wird ein neuer Vorgang erstellt. Jeder Vorgang ist isoliert von den anderen und es wird kein Speicher zwischen ihnen geteilt, selbst dann, wenn sie in der Ausführung identische Anrufe an einem bestimmten Punkt ausführen. Auf diese Weise können Sie mit Bibliotheken verknüpfte Anwendungen, die Thread-Ausführungen nicht unterstützen, sicher ausführen – meist ältere Anwendungen oder Bibliotheken.
      • Worker: Ein Elternprozess ist für das Starten eines Bündels von Kindprozessen verantwortlich, von denen einige neu eingehende Verbindungen erfassen und andere den angeforderten Content bereitstellen. Für jeden Prozess gibt es einen dazugehörigen Thread (ein einzelner Thread kann jeweils eine Verbindung verwalten), sodass ein Prozess mit mehreren Anfragen gleichzeitig umgehen kann. Diese Methode für die Handhabung von Verbindungen fördert eine bessere Ressourcennutzung und gewährleistet die Aufrechterhaltung der Stabilität. Das ist auf das Bündel von verfügbaren Prozessen zurückzuführen, bei denen oft frei verfügbare Threads bereitstehen, die neue Verbindungen sofort bedienen können.
      • Event: Basierend auf Worker geht dieses MPM noch einen Schritt weiter, indem es die Art und Weise optimiert, wie der Elternprozess Aufgaben für die Kindprozesse und für die Threads, die damit verknüpft sind, vorgibt. Eine Verbindung bleibt für 5 Sekunden standardmäßig geöffnet und schließt sich bei jedem neuen Ereignis, das eintritt; das ist der Standardwert für die Keep-Alive-Anweisung, der den mit ihm verknüpften Thread beibehält. Das Event MPM ermöglicht dem Prozess das Verwalten von Threads, damit einige Threads für die Verwaltung neuer eingehender Verbindungen bereitstehen, während andere weiterhin mit den Live-Verbindungen verknüpft sind. Die Ressourcennutzung und Leistungsfähigkeit wird dadurch verbessert, dass die den Threads zugewiesenen Aufgaben neu verteilt werden können.

      Mit dem MPM Event-Modul ist ein schnelles Multi-Processing-Modul auf dem Apache-HTTP-Webserver verfügbar.

      PHP-FPM ist der FastCGI-Prozessmanager für PHP. Das FastCGI-Protokoll basiert auf dem Common Gateway Interface (CGI), einem Protokoll, das zwischen Anwendungen und Webservern wie Apache HTTP steht. Dadurch können Entwickler Anwendungen schreiben, ohne das Verhalten der Webserver berücksichtigen zu müssen. Die Programme führen ihre Prozesse unabhängig aus und übergeben ihr Produkt über dieses Protokoll an den Webserver. Jede neue Verbindung, die von einer Anwendung verarbeitet werden muss, erstellt einen neuen Prozess.

      Durch die Kombination von MPM Event in Apache HTTP mit dem PHP FastCGI-Prozessmanager (PHP-FPM) kann eine Website schneller laden und mehr gleichzeitige Verbindungen mit weniger Ressourcen verarbeiten.

      In diesem Tutorial verbessern Sie die Leistung des LAMP-Stacks, indem Sie das standardmäßige Multi-Processing-Module von Prefork auf Event umstellen und den PHP-FPM-Prozessmanager für die Handhabung des PHP-Codes nutzen anstelle des klassischen mod_php in Apache HTTP.

      Voraussetzungen

      Bevor Sie diese Anleitung beginnen, benötigen Sie Folgendes:

      Schritt 1 — Umstellen des Multi-Processing-Module

      Ubuntu übernimmt Skripte, um Apache-HTTP-Module über die eigene übergeordnete Distribution Debian zu aktivieren oder zu deaktivieren. Sie werden dieses Toolset in diesem Schritt verwenden, um das Prefork-Modul zu deaktivieren und das Event-Modul zu aktivieren.

      In diesem Schritt halten Sie Apache HTTP an, deaktivieren das Modul PHP 7.2, das mit dem Prefork-Modul verknüpft ist, und deaktivieren anschließend Prefork, um das Event-Modul unmittelbar aktivieren zu können.

      Zuerst halten Sie den Apache-HTTP-Dienst an:

      • sudo systemctl stop apache2

      Nun können Sie das Modul PHP 7.2 deaktivieren, das mit dem Prefork-Modul in Verbindung steht:

      Deaktivieren Sie dann das Prefork MPM-Modul:

      • sudo a2dismod mpm_prefork

      Nun Aktivieren Sie das Event MPM-Modul:

      Sie haben das MPM von Prefork auf Event umgestellt und die Modulverbindung PHP 7.2 zwischen PHP und Apache HTTP entfernt. Im nächsten Schritt installieren Sie das php-fpm-Modul sowie die verwandten Bibliotheken und Proxy-Module. Sie konfigurieren Apache HTTP so, dass es auch mit PHP kommunizieren kann.

      Schritt 2 — Konfigurieren von Apache HTTP für die Nutzung des FastCGI-Prozesses

      In dieser Phase haben Sie die Verarbeitung von Verbindungen durch Apache HTTP umgestellt, indem Sie sie von dem Prefork-MPM auf Event verlagert haben. Im Zuge dessen haben Sie jedoch das PHP-Modul deaktiviert, das Apache HTTP mit jedem Programm verbunden hatte, das mit PHP ausgeführt wird.

      In diesem Schritt installieren Sie den PHP-FPM-Prozessor, damit Apache HTTP wieder PHP-Programme verarbeiten kann. Außerdem installieren Sie die Abhängigkeitsbibliotheken und aktivieren die Module, damit beide reibungslos und schneller zusammenarbeiten können als zuvor.

      Installieren Sie zuerst php-fpm. Der folgende Befehl installiert das PHP-FPM und aktiviert automatisch den Dienst php7.2-fpm, der in systemd integriert ist, sodass der Dienst beim Booten gestartet wird:

      Apache HTTP und PHP benötigen für die Kommunikation eine Bibliothek, die diese Funktion ermöglicht. Nun installieren Sie libapache2-mod-fcgid, das als Schnittstelle zwischen Programmen mit Webservern dient und Apache-HTTP-spezifisch ist. Diese Kommunikation erfolgt über ein UNIX-Socket.

      Installieren Sie diese Bibliothek:

      • sudo apt install libapache2-mod-fcgid

      Sie haben php-fpm und das libapache2-mod-fcgid installiert, aber noch keines davon aktiviert.

      Aktivieren Sie zuerst das php-fpm-Modul mit folgendem Befehl:

      Aktivieren Sie in einem zweiten Schritt das Apache HTTP-Proxy-Modul:

      Aktivieren Sie in einem dritten Schritt das FastCGI-Proxy-Modul auf Apache HTTP:

      Hinweis: Sie können die Konfiguration dieser Interaktion zwischen PHP-Programmen und Apache HTTP über einen UNIX-Socket mit Folgendem lesen:

      • cat /etc/apache2/conf-enabled/php7.2-fpm.conf

      Nun wurden alle Vorkehrungen getroffen, damit Sie Apache HTTP starten können. Führen Sie eine Konfigurationsüberprüfung durch:

      • sudo apachectl configtest

      Output

      Syntax OK

      Danach können Sie mit dem Neustart von Apache HTTP fortfahren, da es beim Installieren der FastCGI-Bibliothek libapache2-mod-fcgid automatisch gestartet wurde:

      • sudo systemctl restart apache2

      Sie haben das php-fpm-Modul installiert und Apache HTTP so konfiguriert, dass es damit funktioniert. Zudem haben Sie ermöglicht, dass die erforderlichen Module für das FastCGI-Protokoll funktionieren, und die entsprechenden Dienste gestartet.

      Nachdem Apache das Event MPM-Modul aktiviert hat und PHP-FPM verfügbar ist und ausgeführt wird, ist es an der Zeit sicherzustellen, das alles wie geplant funktioniert.

      Schritt 3 — Testen Ihrer Konfiguration

      Führen Sie einige Tests aus, um zu prüfen, ob die Konfigurationsänderungen angewendet wurden. Beim ersten Test wird geprüft, welches Multi-Processing-Modul Apache HTTP verwendet. Beim zweiten Test wird sichergestellt, dass PHP den FPM-Manager verwendet.

      Überprüfen Sie den Apache-HTTP-Server, indem Sie den folgenden Befehl ausführen:

      • sudo apachectl -M | grep 'mpm'

      Sie erhalten folgende Ausgabe:

      Output

      mpm_event_module (shared)

      Für das Proxy-Modul und FastCGI können Sie diese Prozedur wiederholen:

      • sudo apachectl -M | grep 'proxy'

      Die Ausgabe zeigt Folgendes:

      Output

      proxy_module (shared) proxy_fcgi_module (shared)

      Wenn Sie die gesamte Liste der Module sehen möchten, können Sie den zweiten Teil des Befehls nach -M entfernen.

      Nun ist es Zeit zu prüfen, ob PHP den FastCGI-Prozessmanager verwendet. Dazu schreiben Sie ein kleines PHP-Skript, das Ihnen alle Informationen zeigt, die mit PHP in Verbindung stehen.

      Führen Sie den folgenden Befehl aus, um eine Datei zu schreiben, deren Name wie folgt lautet:

      • sudo nano /var/www/your_domain/info.php

      Fügen Sie den folgenden Inhalt in die Datei info.php ein:

      info.php

      <?php phpinfo(); ?>
      

      Rufen Sie nun die URL Ihres Servers auf und fügen Sie info.php am Ende hinzu: http://your_domain/info.php.

      Der Server-API-Eintrag lautet FPM/FastCGI.

      PHP Screen the Server API entry FPM/FastCGI

      Löschen Sie die Datei info.php nach diesem Test, damit keine Informationen über den Server veröffentlicht werden:

      • sudo rm /var/www/yourdomain.com/info.php

      Sie haben den Betriebszustand des MPM-Moduls und der Module, die für die Handhabung von FastCGI zuständig sind, sowie die Handhabung des PHP-Codes überprüft.

      Zusammenfassung

      Sie haben Ihren ursprünglichen LAMP-Stack optimiert, sodass sich die Anzahl der Verbindungen zur Erstellung neuer Apache HTTP-Prozesse erhöht hat, PHP-FPM den PHP-Code effizienter verwaltet und sich die Ressourcennutzung insgesamt verbessert.

      Weitere Informationen zu den verschiedenen Modulen und verwandten Projekten finden Sie in der Projekt-Dokumentation zum Apache HTTP-Server.



      Source link

      So erstellen Sie einen Minecraft-Server unter Ubuntu 20.04


      Der Autor wählte den Tech Education Fund, um eine Spende im Rahmen des Programms Write for DOnations zu erhalten.

      Einführung

      Minecraft ist ein beliebtes Sandkasten-Videospiel. Es wurde ursprünglich im Jahr 2009 veröffentlicht und ermöglicht Spielern in einer Block-3D-Welt zu bauen, zu erforschen, zu gestalten und zu überleben. Ende 2019 war es das zweitbeste Videospiel aller Zeiten. In diesem Tutorial erstellen Sie Ihren eigenen Minecraft-Server, damit Sie und Ihre Freunde zusammen spielen können. Insbesondere installieren Sie die erforderlichen Softwarepakete, um Minecraft auszuführen, konfigurieren den Server für die Ausführung und stellen das Spiel dann bereit.

      Alternativ können Sie den One-Click Minecraft: Java Edition-Server von DigitalOcean als weiteren Installationspfad erkunden.

      Dieses Tutorial verwendet die Java-Version von Minecraft. Wenn Sie über den Microsoft App-Store Ihre Version von Minecraft gekauft haben, können Sie keine Verbindung mit diesem Server herstellen. Die meisten Versionen von Minecraft, die auf Spielekonsolen wie PlayStation 4, Xbox One oder Nintendo Switch gekauft wurden, sind auch die Microsoft-Version von Minecraft. Diese Konsolen können auch keine Verbindung zu dem in diesem Tutorial erstellten Server herstellen. Hier können Sie die Java-Version von Minecraft erhalten.

      Voraussetzungen

      Um diesen Leitfaden auszuführen, benötigen Sie:

      Schritt 1 – Installieren der erforderlichen Softwarepakete und Konfigurieren der Firewall

      Nachdem Ihr Server initialisiert wurde, müssen Sie zunächst Java installieren. Sie benötigen es, um Minecraft auszuführen.

      Aktualisieren Sie den Paketindex für den APT-Paketmanager:

      Installieren Sie als Nächstes die OpenJDK-Version 8 von Java, insbesondere die kopflose JRE. Dies ist eine minimale Version von Java, die die Unterstützung für GUI-Anwendungen entfernt. Das macht es ideal für die Ausführung von Java-Anwendungen auf einem Server:

      • sudo apt install openjdk-8-jre-headless

      Sie müssen auch eine Software namens screen verwenden, um abnehmbare Serversitzungen zu erstellen. Auf screen können Sie eine Terminalsitzung erstellen und von dieser trennen, sodass der darauf gestartete Prozess ausgeführt wird. Dies ist wichtig, da dies die Sitzung beenden und Ihren Server stoppen würde, wenn Sie Ihren Server starten und dann Ihr Terminal schließen würden. Installieren Sie screen jetzt:

      Nachdem Sie die Pakete installiert haben, müssen wir die Firewall so einstellen, dass sie Traffic gestattet, der auf unserem Minecraft-Server eingeht. Bei der Ersteinrichtung des Servers haben Sie nur den Traffic von SSH zugelassen. Nun müssen Sie auch den Traffic zulassen, der über Port 25565 eingeht. Das ist der Standardport, den Minecraft für die Zulassung von Verbindungen verwendet. Fügen Sie die erforderliche Firewall-Regel hinzu, indem Sie den folgenden Befehl ausführen:

      Nachdem Sie nun Java installiert und Ihre Firewall richtig konfiguriert haben, laden Sie den Minecraft-Server von der Minecraft-Website herunter.

      Schritt 2 – Herunterladen der letzten Version von Minecraft

      Jetzt müssen Sie die aktuelle Version des Minecraft-Servers herunterladen. Sie können dies tun, indem Sie zur Minecraft-Website navigieren und den Link Download minecraft_server kopieren. X.X.X.jar, wobei die X die neueste Version des Servers sind.

      Sie können jetzt wget und den kopierten Link verwenden, um den Server herunterzuladen:

      • wget https://launcher.mojang.com/v1/objects/bb2b6b1aefcd70dfd1892149ac3a215f6c636b07/server.jar

      Wenn Sie beabsichtigen, Ihren Minecraft-Server zu aktualisieren, oder wenn Sie verschiedene Versionen von Minecraft ausführen möchten, benennen Sie die heruntergeladene server.jar in minecraft_server _ 1.15.2.jar um und stimmen Sie die hervorgehobenen Versionsnummern mit der jeweiligen heruntergeladenen Version ab:

      • mv server.jar minecraft_server_1.15.2.jar

      Wenn Sie eine ältere Version von Minecraft herunterladen möchten, finden Sie diese archiviert auf mcversions.net. Dieses Tutorial konzentriert sich jedoch auf die aktuelle neueste Version. Nachdem Sie Ihren Download durchgeführt haben, beginnen wir mit der Konfiguration Ihres Minecraft-Servers.

      Schritt 3 – Konfigurieren und Ausführen des Minecraft-Servers

      Nachdem Sie die Minecraft-JAR-Datei heruntergeladen haben, können Sie es ausführen.

      Starten Sie zunächst eine Bildschirmsitzung, indem Sie den Befehl screen ausführen:

      Wenn Sie das angezeigte Banner gelesen haben, drücken Sie die LEERTASTE. Auf screen wird wie gewohnt eine Terminalsitzung angezeigt. Diese Sitzung ist jetzt abnehmbar. Dies bedeutet, dass Sie hier einen Befehl starten und ausführen können.

      Sie können nun Ihre ursprüngliche Konfiguration ausführen. Seien Sie nicht beunruhigt, wenn dieser nächste Befehl einen Fehler auslöst. Minecraft hat seine Installation so konzipiert, dass Benutzer zuerst der Lizenzvereinbarung des Unternehmens zustimmen müssen. Sie tun dies als Nächstes:

      • java -Xms1024M -Xmx1024M -jar minecraft_server_1.15.2.jar nogui

      Bevor wir die Ausgabe dieses Befehls untersuchen, schauen wir uns all diese Befehlszeilenargumente genauer an, die Ihren Server optimieren:

      • Xms1024M – hiermit wird der Server so konfiguriert, dass er mit 1024 MB oder 1 GB RAM ausgeführt wird. Sie können dieses Limit erhöhen, wenn Ihr Server mit mehr RAM beginnen soll. Sowohl M für Megabytes als auch G für Gigabytes werden als Optionen unterstützt. Beispiel: Xms2G startet den Server mit 2 Gigabyte RAM.

      • Xmx1024M – hiermit wird der Server so konfiguriert, dass höchstens 1024 MB RAM verwendet werden. Sie können dieses Limit erhöhen, wenn Ihr Server größer ausgeführt werden soll, mehr Spieler zugelassen werden sollen oder wenn Sie der Meinung sind, dass Ihr Server langsam läuft.

      • jar – diese Flagge gibt an, welche Server-JAR-Datei ausgeführt werden soll.

      • nogui – dies weist den Server an, keine GUI zu starten, da dies ein Server ist und Sie keine grafische Benutzeroberfläche haben.

      Wenn Sie diesen Befehl zum ersten Mal ausführen, der normalerweise Ihren Server startet, wird stattdessen der folgende Fehler generiert:

      Output

      [22:05:31] [22:05:31] [main/ERROR]: Failed to load properties from file: server.properties [22:05:31] [main/WARN]: Failed to load eula.txt [22:05:31] [main/INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.

      Diese Fehler wurden generiert, weil der Server zwei für die Ausführung erforderliche Dateien nicht finden konnte: die EULA (Endbenutzer-Lizenzvereinbarung) in eula.txt und die Konfigurationsdatei server.properties. Da der Server diese Dateien nicht finden konnte, wurden sie glücklicherweise in Ihrem aktuellen Arbeitsverzeichnis erstellt.

      Öffnen Sie zunächst eula.txt in nano oder Ihrem bevorzugten Texteditor:

      Innerhalb dieser Datei sehen Sie einen Link zur Minecraft EULA. Kopieren Sie die URL:

      ~/eula.txt

      #By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).
      #Tue Mar 24 22:05:31 UTC 2020
      eula=false
      

      Öffnen Sie die URL in Ihrem Webbrowser und lesen Sie die Vereinbarung. Kehren Sie dann zu Ihrem Texteditor zurück und suchen Sie die letzte Zeile in eula.txt. Ändern Sie hier eula=false in eula=true. Speichern und schließen Sie jetzt die Datei.

      Nachdem Sie die EULA akzeptiert haben, ist es an der Zeit, den Server gemäß Ihren Spezifikationen zu konfigurieren.

      In Ihrem aktuellen Arbeitsverzeichnis finden Sie auch die neu erstellte Datei server.properties. Diese Datei enthält alle Konfigurationsoptionen für Ihren Minecraft-Server. Eine detaillierte Liste aller Servereigenschaften finden Sie im offiziellen Minecraft-Wiki. Sie ändern diese Datei mit Ihren bevorzugten Einstellungen, bevor Sie Ihren Server starten. Dieses Tutorial behandelt die grundlegenden Eigenschaften:

      Ihre Datei wird wie folgt aussehen:

      ~/server.properties

      #Minecraft server properties
      #Thu Apr 30 23:42:29 UTC 2020
      spawn-protection=16
      max-tick-time=60000
      query.port=25565
      generator-settings=
      force-gamemode=false
      allow-nether=true
      enforce-whitelist=false
      gamemode=survival
      broadcast-console-to-ops=true
      enable-query=false
      player-idle-timeout=0
      difficulty=easy
      spawn-monsters=true
      broadcast-rcon-to-ops=true
      op-permission-level=4
      pvp=true
      snooper-enabled=true
      level-type=default
      hardcore=false
      enable-command-block=false
      max-players=20
      network-compression-threshold=256
      resource-pack-sha1=
      max-world-size=29999984
      function-permission-level=2
      rcon.port=25575
      server-port=25565
      server-ip=
      spawn-npcs=true
      allow-flight=false
      level-name=world
      view-distance=10
      resource-pack=
      spawn-animals=true
      white-list=false
      rcon.password=
      generate-structures=true
      online-mode=true
      max-build-height=256
      level-seed=
      prevent-proxy-connections=false
      use-native-transport=true
      motd=A Minecraft Server
      enable-rcon=false
      

      Sehen wir uns einige der wichtigsten Eigenschaften in dieser Liste genauer an:

      • Schwierigkeitsgrad (Standard einfach) – hiermit wird der Schwierigkeitsgrad des Spiels festgelegt, z. B. wie viel Schaden verursacht wird und wie sich die Elemente auf Ihren Spieler auswirken. Die Optionen sind peaceful (friedlich), easy (einfach), normal und hard (schwer).

      • gamemode (standardmäßig survival (überleben)) – hiermit wird der Spielmodus festgelegt. Die Optionen sind überleben, kreativ, Abenteuer und Zuschauer.

      • Ebenenname (Standard Welt) – hiermit wird der Name Ihres Servers festgelegt, der im Client angezeigt wird. Zeichen wie das Apostroph müssen möglicherweise mit einem Backslash versehen werden.

      • motd (Standard Ein Minecraft-Server) – die Meldung, die in der Serverliste des Minecraft-Clients angezeigt wird.

      • pvp (Standard true) – aktiviert den Kampf zwischen Spieler und Spieler. Wenn der Wert auf true gesetzt ist, können die Spieler kämpfen und sich gegenseitig Schaden zufügen.

      Wenn Sie die gewünschten Optionen festgelegt haben, speichern und schließen Sie die Datei.

      Nachdem Sie EULA in true geändert und Ihre Einstellungen konfiguriert haben, können Sie Ihren Server erfolgreich starten.

      Lassen Sie uns wie beim letzten Mal Ihren Server mit 1024 MB RAM starten. Lassen Sie uns Minecraft erst jetzt auch die Möglichkeit geben, bei Bedarf bis zu 4 GB RAM zu verwenden. Denken Sie daran, dass Sie diese Nummer gerne an Ihre Servereinschränkungen oder Benutzeranforderungen anpassen können:

      • java -Xms1024M -Xmx4G -jar minecraft_server_1.15.2.jar nogui

      Geben Sie der Initialisierung einige Momente. Bald wird Ihr neuer Minecraft-Server eine ähnliche Ausgabe produzieren:

      Output

      [21:08:14] [Server thread/INFO]: Starting minecraft server version 1.15.2 [21:08:14] [Server thread/INFO]: Loading properties [21:08:14] [Server thread/INFO]: Default game type: SURVIVAL [21:08:14] [Server thread/INFO]: Generating keypair [21:08:15] [Server thread/INFO]: Starting minecraft server on *:25565

      Sobald der Server betriebsbereit ist, wird die folgende Ausgabe angezeigt:

      Output

      [21:15:37] [Server thread/INFO]: Done (30.762s)! For help, type "help"

      Ihr Server wird jetzt ausgeführt und Sie wurden in das Kontrollfeld des Serveradministrators verschoben. Geben Sie jetzt Hilfe ein:

      Eine Ausgabe wie diese wird angezeigt:

      Output

      [21:15:37] [Server thread/INFO]: /advancement (grant|revoke) [21:15:37] [Server thread/INFO]: /ban <targets> [<reason>] [21:15:37] [Server thread/INFO]: /ban-ip <target> [<reason>] [21:15:37] [Server thread/INFO]: /banlist [ips|players] ...

      Von diesem Terminal aus können Sie Administratorbefehle ausführen und Ihren Minecraft-Server steuern. Verwenden Sie jetzt screen, um Ihren neuen Server auch nach dem Abmelden am Laufen zu halten. Dann können Sie sich mit Ihrem Minecraft-Client verbinden und ein neues Spiel starten.

      Schritt 4 – Server am Laufen halten

      Nachdem Sie nun Ihren Server eingerichtet haben, möchten Sie, dass er auch nach dem Trennen von Ihrer SSH-Sitzung ausgeführt wird. Da Sie zuvor screen verwendet haben, können Sie sich von dieser Sitzung trennen, indem Sie Strg + A + D drücken. Jetzt befinden Sie sich wieder in Ihrer ursprünglichen Shell.

      Führen Sie diesen Befehl aus, um alle Ihre Bildschirmsitzungen anzuzeigen:

      Sie erhalten eine Ausgabe mit der ID Ihrer Sitzung, die Sie benötigen, um diese Sitzung fortzusetzen:

      Output

      There is a screen on: 26653.pts-0.minecraft (03/25/20 21:18:31) (Detached) 1 Socket in /run/screen/S-root.

      Um Ihre Sitzung fortzusetzen, übergeben Sie die Flagge -r an den Befehl screen und geben Sie dann Ihre Sitzungs-ID ein:

      Wenn Sie bereit sind, sich von Ihrem Server abzumelden, trennen Sie sich mit Strg + A + D von der Sitzung und melden Sie sich dann ab.

      Schritt 5 – Herstellen einer Verbindung zu Ihrem Server über den Minecraft-Client

      Nachdem Ihr Server nun betriebsbereit ist, stellen wir über den Minecraft-Client eine Verbindung zu ihm her. Dann können Sie spielen!

      Starten Sie Ihre Kopie von Minecraft Java Edition und wählen Sie im Menü Multiplayer.

      Wählen Sie im Menü Multiplayer

      Als Nächstes müssen Sie einen Server hinzufügen, zu dem eine Verbindung hergestellt werden soll. Klicken Sie daher auf die Schaltfläche Server hinzufügen.

      Klicken Sie auf die Schaltfläche Server hinzufügen

      Geben Sie im angezeigten Bildschirm Serverinformationen bearbeiten Ihrem Server einen Namen und geben Sie die IP-Adresse Ihres Servers ein. Dies ist dieselbe IP-Adresse, die Sie für die Verbindung über SSH verwendet haben.

      Benennen Sie Ihren Server und geben Sie die IP-Adresse ein

      Nachdem Sie Ihren Servernamen und Ihre IP-Adresse eingegeben haben, kehren Sie zum Multiplayer-Bildschirm zurück, auf dem Ihr Server nun aufgelistet wird.

      Wählen Sie Ihren Server aus und klicken Sie auf Server beitreten

      Ab jetzt wird Ihr Server immer in dieser Liste angezeigt. Wählen Sie ihn aus und klicken Sie auf Server beitreten.

      Genießen Sie das Spiel!

      Sie befinden sich auf Ihrem Server und können spielen!

      Zusammenfassung

      Sie haben jetzt einen Minecraft-Server unter Ubuntu 20.04, auf dem Sie und alle Ihre Freunde spielen können! Viel Spaß beim Erkunden, Basteln und Überleben in einer barbarischen 3D-Welt. Und denken Sie daran: Achten Sie auf Störende.



      Source link