Anwendung zur Verwendung eines Spamfiltermodells für maschinelles Lernen aktualisieren

1. Hinweis

In diesem Codelab aktualisieren Sie die App, die Sie in den vorherigen Codelabs für die mobile Textklassifizierung erstellt haben.

Vorbereitung

  • Dieses Codelab wurde für erfahrene Entwickler entwickelt, die noch keine Erfahrung mit maschinellem Lernen haben.
  • Das Codelab ist Teil eines sequenzierten Pfads. Wenn Sie es noch nicht getan haben: Eine App im einfachen Messaging-Stil entwickeln oder ein Modell für maschinelles Lernen für Kommentar-Spam erstellen, sollten Sie dies jetzt tun.

Inhalt des Kurses [erweitern oder lernen]

  • Sie erfahren, wie Sie Ihr benutzerdefiniertes Modell in Ihre App integrieren, die in den vorherigen Schritten erstellt wurde.

Voraussetzungen

2. Vorhandene Android-App öffnen

Sie können den Code dafür abrufen, indem Sie Codelab 1 ausführen oder dieses Repository klonen und die App aus TextClassificationStep1 laden.

git clone https://github.com/googlecodelabs/odml-pathways

Sie finden sie im Pfad TextClassificationOnMobile->Android.

Der fertige Code ist auch als TextClassificationStep2 verfügbar.

Anschließend können Sie mit Schritt 2 fortfahren.

3. Modelldatei und Metadaten importieren

Im Codelab zum Erstellen eines Kommentar-Spam-Modells für maschinelles Lernen haben Sie ein TFLITE-Modell erstellt.

Sie sollten die Modelldatei heruntergeladen haben. Wenn Sie das Modell nicht haben, können Sie es im Repository für dieses Codelab abrufen. Das Modell ist hier verfügbar.

Fügen Sie sie Ihrem Projekt hinzu, indem Sie ein Asset-Verzeichnis erstellen.

  1. Achten Sie darauf, dass im Projektnavigator oben Android ausgewählt ist.
  2. Klicken Sie mit der rechten Maustaste auf den Ordner app. Wählen Sie Neu > Verzeichnis:

d7c3e9f21035fc15.png

  1. Wählen Sie im Dialogfeld Neues Verzeichnis die Option src/main/assets aus.

2137f956a1ba4ef0.png

Sie sehen, dass in der App jetzt ein neuer Ordner assets verfügbar ist.

ae858835e1a90445.png

  1. Klicken Sie mit der rechten Maustaste auf Assets.
  2. Auf dem Mac befindet sich ein Menü mit der Option Im Finder anzeigen. Wählen Sie sie aus. (Unter Windows lautet die Option Im Explorer anzeigen, unter Ubuntu In Dateien anzeigen.)

e61aaa3b73c5ab68.png

Der Finder wird gestartet, um den Speicherort der Dateien anzuzeigen (Datei-Explorer unter Windows, Dateien unter Linux).

  1. Kopieren Sie die Dateien labels.txt, model.tflite und vocab in dieses Verzeichnis.

14f382cc19552a56.png

  1. Kehren Sie zu Android Studio zurück. Sie sind dann im Ordner assets verfügbar.

150ed2a1d2f7a10d.png

4. Build.gradle-Datei zur Verwendung von TensorFlow Lite aktualisieren

Wenn Sie TensorFlow Lite und die entsprechenden TensorFlow Lite-Aufgabenbibliotheken verwenden möchten, müssen Sie Ihre build.gradle-Datei aktualisieren.

Android-Projekte enthalten oft mehr als ein Projekt. Achten Sie daher darauf, die App-Ebene 1 zu finden. Sie finden ihn im Projekt-Explorer in der Android-Ansicht im Abschnitt Gradle Scripts (Gradle-Skripts). Die richtige Datei erhält das Label .app, wie hier gezeigt:

6426051e614bc42f.png

Sie müssen an dieser Datei zwei Änderungen vornehmen. Die erste befindet sich unten im Abschnitt dependencies. Fügen Sie einen Text wie implementation für die TensorFlow Lite-Aufgabenbibliothek hinzu:

implementation 'org.tensorflow:tensorflow-lite-task-text:0.1.0'

Die Versionsnummer hat sich möglicherweise seit der Erstellung geändert. Überprüfen Sie daher regelmäßig https://www.tensorflow.org/lite/inference_with_metadata/task_library/nl_classifier.

Für die Aufgabenbibliotheken ist außerdem mindestens SDK-Version 21 erforderlich. Diese Einstellung findest du unter android > default config und ändern Sie den Wert in 21:

c100b68450b8812f.png

Da Sie jetzt alle Abhängigkeiten haben, können Sie mit dem Programmieren beginnen.

5. Hilfsklasse hinzufügen

Um die Inferenzlogik, bei der Ihre App das Modell verwendet, von der Benutzeroberfläche zu trennen, erstellen Sie eine weitere Klasse zur Verarbeitung der Modellinferenz. Nennen Sie das „Hilfsprogramm“. .

  1. Klicken Sie mit der rechten Maustaste auf den Paketnamen, in dem sich Ihr MainActivity-Code befindet.
  2. Wählen Sie Neu > Paket.

d5911ded56b5df35.png

  1. In der Mitte des Bildschirms wird ein Dialogfeld angezeigt, in dem Sie aufgefordert werden, den Paketnamen einzugeben. Fügen Sie es am Ende des aktuellen Paketnamens ein. (In diesem Fall wird es als Hilfsmittel bezeichnet.)

3b9f1f822f99b371.png

  1. Klicken Sie anschließend mit der rechten Maustaste auf den Ordner helpers im Projekt-Explorer.
  2. Wählen Sie Neu > Java-Klasse und mit dem Namen TextClassificationClient. Im nächsten Schritt bearbeiten Sie die Datei.

Ihre TextClassificationClient-Hilfsklasse sieht so aus, wobei der Name Ihres Pakets anders sein kann.

package com.google.devrel.textclassificationstep1.helpers;

public class TextClassificationClient {
}
  1. Aktualisieren Sie die Datei mit diesem Code:
package com.google.devrel.textclassificationstep2.helpers;

import android.content.Context;
import android.util.Log;
import java.io.IOException;
import java.util.List;

import org.tensorflow.lite.support.label.Category;
import org.tensorflow.lite.task.text.nlclassifier.NLClassifier;

public class TextClassificationClient {
    private static final String MODEL_PATH = "model.tflite";
    private static final String TAG = "CommentSpam";
    private final Context context;

    NLClassifier classifier;

    public TextClassificationClient(Context context) {
        this.context = context;
    }

    public void load() {
        try {
            classifier = NLClassifier.createFromFile(context, MODEL_PATH);
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }
    }

    public void unload() {
        classifier.close();
        classifier = null;
    }

    public List<Category> classify(String text) {
        List<Category> apiResults = classifier.classify(text);
        return apiResults;
    }

}

Diese Klasse stellt einen Wrapper für den TensorFlow Lite-Interpreter bereit, lädt das Modell und abstrahiert die komplexe Verwaltung des Datenaustauschs zwischen Ihrer App und dem Modell.

In der Methode load() wird ein neuer NLClassifier-Typ aus dem Modellpfad instanziiert. Der Modellpfad ist einfach der Name des Modells: model.tflite. Der Typ NLClassifier ist Teil der Textaufgabenbibliotheken. Er hilft Ihnen, Ihren String in Tokens zu konvertieren, die richtige Sequenzlänge zu verwenden, ihn an das Modell zu übergeben und die Ergebnisse zu parsen.

Weitere Informationen dazu finden Sie unter „Modell für maschinelles Lernen für Kommentar-Spam erstellen“.

Die Klassifizierung erfolgt in der classify-Methode, wobei Sie ihr einen String übergeben. Sie gibt ein List zurück. Wenn Sie mithilfe von Modellen für maschinelles Lernen Inhalte klassifizieren möchten, bei denen Sie feststellen möchten, ob es sich bei einem String um Spam handelt, werden in der Regel alle Antworten mit zugewiesenen Wahrscheinlichkeiten zurückgegeben. Wenn du beispielsweise eine Nachricht weitergibst, die wie Spam aussieht, erhältst du eine Liste mit zwei Antworten: eine mit der Wahrscheinlichkeit, dass es sich um Spam handelt, und eine mit der Wahrscheinlichkeit, dass es sich nicht um Spam handelt. Die Kategorien „Spam“ und „Kein Spam“ sind Kategorien, daher enthält die zurückgegebene List diese Wahrscheinlichkeiten. Das werden Sie später parsen.

Nachdem Sie nun die Hilfsklasse haben, kehren Sie zu MainActivity zurück und aktualisieren Sie sie, um Ihren Text damit zu klassifizieren. Das erhalten Sie im nächsten Schritt.

6. Den Text klassifizieren

In Ihrem MainActivity müssen Sie zuerst die gerade erstellten Hilfsprogramme importieren.

  1. Fügen Sie oben in MainActivity.kt zusammen mit den anderen Importen Folgendes hinzu:
import com.google.devrel.textclassificationstep2.helpers.TextClassificationClient
import org.tensorflow.lite.support.label.Category
  1. Als Nächstes laden Sie die Hilfsprogramme. Fügen Sie in onCreate direkt nach der Zeile setContentView diese Zeilen hinzu, um die Hilfsklasse zu instanziieren und zu laden:
val client = TextClassificationClient(applicationContext)
client.load()

Die onClickListener deiner Schaltfläche sollte jetzt so aussehen:

btnSendText.setOnClickListener {
     var toSend:String = txtInput.text.toString()
     txtOutput.text = toSend
 }
  1. Aktualisieren Sie ihn so:
btnSendText.setOnClickListener {
    var toSend:String = txtInput.text.toString()
    var results:List<Category> = client.classify(toSend)
    val score = results[1].score
    if(score>0.8){
        txtOutput.text = "Your message was detected as spam with a score of " + score.toString() + " and not sent!"
    } else {
        txtOutput.text = "Message sent! \nSpam score was:" + score.toString()
    }
    txtInput.text.clear()
}

Dadurch ändert sich die Funktionalität, sodass sie nicht mehr nur die Eingabe des Nutzers ausgeben, sondern zuerst die Eingabe klassifiziert.

  1. Mit dieser Zeile übergeben Sie den vom Nutzer eingegebenen String an das Modell und erhalten Ergebnisse:
var results:List<Category> = client.classify(toSend)

Es gibt nur zwei Kategorien: False und True.

. (TensorFlow sortiert sie alphabetisch, sodass "False" Element 0 und "True" Element 1 ist.)

  1. Um den Wert für die Wahrscheinlichkeit zu ermitteln, dass der Wert True ist, können Sie sich results[1].score wie folgt ansehen:
    val score = results[1].score
  1. Sie haben einen Schwellenwert ausgewählt (in diesem Fall 0,8). Wenn der Wert für die Kategorie Wahr über dem Schwellenwert (0,8) liegt, handelt es sich bei der Nachricht um Spam. Andernfalls ist es kein Spam und die Nachricht kann sicher gesendet werden:
    if(score>0.8){
        txtOutput.text = "Your message was detected as spam with a score of " + score.toString() + " and not sent!"
    } else {
        txtOutput.text = "Message sent! \nSpam score was:" + score.toString()
    }
  1. Hier sehen Sie das Modell in Aktion. Die Nachricht "Besuchen Sie meinen Blog, um Sachen zu kaufen!" wurde als hohe Wahrscheinlichkeit von Spam gemeldet:

1fb0b5de9e566e.png

Und umgekehrt sagten sie: „Das macht Spaß, danke!“ als sehr geringe Wahrscheinlichkeit für Spam eingestuft wurde:

73f38bdb488b29b3.png

7. iOS-App zur Verwendung des TensorFlow Lite-Modells aktualisieren

Sie können den Code dafür abrufen, indem Sie Codelab 1 ausführen oder dieses Repository klonen und die App aus TextClassificationStep1 laden. Sie finden sie im Pfad TextClassificationOnMobile->iOS.

Der fertige Code ist auch als TextClassificationStep2 verfügbar.

Im Codelab zum Erstellen von Kommentar-Spam-Modellen für maschinelles Lernen haben Sie eine sehr einfache Anwendung erstellt, mit der Nutzer Nachrichten in UITextView eingeben und ohne Filter an eine Ausgabe übergeben können.

Jetzt aktualisieren Sie diese App, um ein TensorFlow Lite-Modell zu verwenden, um Kommentar-Spam im Text vor dem Senden zu erkennen. Simulieren Sie einfach das Senden in dieser App, indem Sie den Text in einem Ausgabelabel rendern. Eine echte App könnte aber eine Pinnwand, einen Chat oder Ähnliches haben.

Sie benötigen die App aus Schritt 1, die Sie aus dem Repository klonen können.

Zur Einbindung von TensorFlow Lite verwenden Sie CocoaPods. Wenn Sie diese noch nicht installiert haben, können Sie dies mithilfe der Anleitung unter https://cocoapods.org/ tun.

  1. Nachdem Sie CocoaPods installiert haben, erstellen Sie eine Datei namens Podfile im selben Verzeichnis wie .xcproject für die TextClassification-App. Der Inhalt dieser Datei sollte wie folgt aussehen:
target 'TextClassificationStep2' do
  use_frameworks!

  # Pods for NLPClassifier
    pod 'TensorFlowLiteSwift'

end

Der Name Ihrer App sollte in der ersten Zeile und nicht in „TextClassificationStep2“ stehen.

Wechseln Sie über Terminal zu diesem Verzeichnis und führen Sie pod install aus. Ist der Vorgang erfolgreich, haben Sie ein neues Verzeichnis namens Pods und eine neue .xcworkspace-Datei für Sie. Sie verwenden diese in Zukunft anstelle des .xcproject.

Wenn der Fehler fehlgeschlagen ist, prüfen Sie, ob sich die Podfile-Datei im selben Verzeichnis befindet, in dem sich auch .xcproject befand. Meist ist die Podfile-Datei im falschen Verzeichnis oder der falsche Zielname die Hauptursache.

8. Modell- und Vokab-Dateien hinzufügen

Als Sie das Modell mit dem TensorFlow Lite Model Maker erstellt haben, konnten Sie das Modell (als model.tflite) und das Vokabular (als vocab.txt) ausgeben.

  1. Füge sie deinem Projekt hinzu, indem du sie per Drag-and-drop aus dem Finder in dein Projektfenster ziehst. Achten Sie darauf, dass Zu Zielen hinzufügen aktiviert ist:

1ee9eaa00ee79859.png

Wenn Sie fertig sind, sollten sie in Ihrem Projekt angezeigt werden:

b63502b23911fd42.png

  1. Überprüfen Sie noch einmal, ob sie dem Bundle hinzugefügt wurden, damit sie auf einem Gerät bereitgestellt werden. Wählen Sie dazu Ihr Projekt aus (im Screenshot oben ist das blaue Symbol TextClassificationStep2) und sehen Sie sich den Tab Build Phases (Build-Phasen) an:

20b7cb603d49b457.png

9. Vokabular laden

Bei der NLP-Klassifizierung wird das Modell mit in Vektoren codierten Wörtern trainiert. Das Modell codiert Wörter mit einem bestimmten Satz von Namen und Werten, die beim Trainieren des Modells erlernt werden. Beachten Sie, dass die meisten Modelle unterschiedliches Vokabular haben. Es ist daher wichtig, dass Sie das Vokabular für Ihr Modell verwenden, das zum Zeitpunkt des Trainings generiert wurde. Dies ist die Datei vocab.txt, die Sie Ihrer App gerade hinzugefügt haben.

Sie können die Datei in Xcode öffnen, um die Codierungen anzuzeigen. Wörter wie „Lied“ mit der Codierung 6 und "love" auf 12. Die Reihenfolge entspricht der Häufigkeitsreihenfolge, also „I“. war das häufigste Wort im Dataset, gefolgt von „check“.

Wenn Ihr Nutzer Wörter eingibt, sollten Sie sie mit diesem Vokabular codieren, bevor Sie sie an das Modell zur Klassifizierung senden.

Sehen wir uns diesen Code genauer an. Beginnen Sie mit dem Laden des Vokabulars.

  1. Definieren Sie eine Variable auf Klassenebene, um das Wörterbuch zu speichern:
var words_dictionary = [String : Int]()
  1. Erstellen Sie dann eine func in der Klasse, um das Vokabular in dieses Wörterbuch zu laden:
func loadVocab(){
    // This func will take the file at vocab.txt and load it into a has table
    // called words_dictionary. This will be used to tokenize the words before passing them
    // to the model trained by TensorFlow Lite Model Maker
    if let filePath = Bundle.main.path(forResource: "vocab", ofType: "txt") {
        do {
            let dictionary_contents = try String(contentsOfFile: filePath)
            let lines = dictionary_contents.split(whereSeparator: \.isNewline)
            for line in lines{
                let tokens = line.components(separatedBy: " ")
                let key = String(tokens[0])
                let value = Int(tokens[1])
                words_dictionary[key] = value
            }
        } catch {
            print("Error vocab could not be loaded")
        }
    } else {
        print("Error -- vocab file not found")

    }
}
  1. Sie können ihn ausführen, indem Sie ihn in viewDidLoad aufrufen:
override func viewDidLoad() {
    super.viewDidLoad()
    txtInput.delegate = self
    loadVocab()
}

10. String in Tokensequenz umwandeln

Die Nutzer geben Wörter als Satz ein, der dann zu einer Zeichenfolge wird. Jedes Wort im Satz wird, sofern im Wörterbuch vorhanden, in den Schlüsselwert für das Wort codiert, wie im Vokabular definiert.

Ein NLP-Modell akzeptiert normalerweise eine feste Sequenzlänge. Es gibt Ausnahmen bei Modellen, die mit ragged tensors erstellt wurden. Diese sind aber in den meisten Fällen behoben. Diese Länge haben Sie beim Erstellen Ihres Modells angegeben. Achten Sie darauf, in Ihrer iOS-App dieselbe Länge zu verwenden.

Die Standardeinstellung im zuvor verwendeten Colab for TensorFlow Lite Model Maker war 20. Richten Sie diese daher auch hier ein:

let SEQUENCE_LENGTH = 20

Fügen Sie das folgende func hinzu, das den String in Kleinbuchstaben umwandelt und alle Satzzeichen entfernt:

func convert_sentence(sentence: String) -> [Int32]{
// This func will split a sentence into individual words, while stripping punctuation
// If the word is present in the dictionary it's value from the dictionary will be added to
// the sequence. Otherwise we'll continue

// Initialize the sequence to be all 0s, and the length to be determined
// by the const SEQUENCE_LENGTH. This should be the same length as the
// sequences that the model was trained for
  var sequence = [Int32](repeating: 0, count: SEQUENCE_LENGTH)
  var words : [String] = []
  sentence.enumerateSubstrings(
    in: sentence.startIndex..<sentence.endIndex,options: .byWords) {
            (substring, _, _, _) -> () in words.append(substring!) }
  var thisWord = 0
  for word in words{
    if (thisWord>=SEQUENCE_LENGTH){
      break
    }
    let seekword = word.lowercased()
    if let val = words_dictionary[seekword]{
      sequence[thisWord]=Int32(val)
      thisWord = thisWord + 1
    }
  }
  return sequence
}

Beachten Sie, dass als Sequenz eine Int32-Sequenz verwendet wird. Diese Option wird bewusst gewählt, da es bei der Übergabe von Werten an TensorFlow Lite um Low-Level-Arbeitsspeicher geht und TensorFlow Lite die Ganzzahlen in einer Zeichenfolgensequenz als 32-Bit-Ganzzahlen behandelt. Dies erleichtert Ihnen das Übergeben von Zeichenfolgen an das Modell (etwas).

11. Klassifizierung durchführen

Zum Klassifizieren eines Satzes muss er zuerst basierend auf den Wörtern im Satz in eine Reihe von Tokens umgewandelt werden. Dies erfolgt in Schritt 9.

Nun übergeben Sie den Satz an das Modell, lassen das Modell den Satz inferenzen und parsen die Ergebnisse.

Dadurch wird der TensorFlow Lite-Interpreter verwendet, den Sie importieren müssen:

import TensorFlowLite

Beginnen Sie mit einem func, der Ihre Sequenz annimmt. Dies war ein Array von Int32-Typen:

func classify(sequence: [Int32]){
  // Model Path is the location of the model in the bundle
  let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite")
  var interpreter: Interpreter
  do{
    interpreter = try Interpreter(modelPath: modelPath!)
  } catch _{
    print("Error loading model!")
    return
  }

Dadurch wird die Modelldatei aus dem Bundle geladen und damit ein Interpreter aufgerufen.

Im nächsten Schritt wird der in der Sequenz gespeicherte zugrunde liegende Arbeitsspeicher in einen Zwischenspeicher namens myData, kopiert, damit er an einen Tensor übergeben werden kann. Bei der Implementierung des TensorFlow Lite-Pods und des Interpreters haben Sie Zugriff auf einen Tensor-Typ erhalten.

Beginnen Sie den Code so (in der Klassifizierung func):

let tSequence = Array(sequence)
let myData = Data(copyingBufferOf: tSequence.map { Int32($0) })
let outputTensor: Tensor

Machen Sie sich keine Sorgen, wenn Sie bei copyingBufferOf eine Fehlermeldung erhalten. Diese wird später als Erweiterung implementiert.

Jetzt ist es an der Zeit, dem Interpreter Tensoren zuzuweisen, den soeben erstellten Datenpuffer in den Eingabetensor zu kopieren und dann den Interpreter aufzurufen, um die Inferenz auszuführen:

do {
  // Allocate memory for the model's input `Tensor`s.
  try interpreter.allocateTensors()

  // Copy the data to the input `Tensor`.
  try interpreter.copy(myData, toInputAt: 0)

  // Run inference by invoking the `Interpreter`.
  try interpreter.invoke()

Sobald der Aufruf abgeschlossen ist, können Sie sich die Ergebnisse in der Ausgabe des Interpreters ansehen.

Das sind Rohwerte (4 Byte pro Neuron), die Sie dann einlesen und umwandeln müssen. Da dieses spezielle Modell zwei Ausgabeneuronen hat, müssen Sie 8 Byte einlesen, die zum Parsen in Float32-Daten umgewandelt werden. Sie haben es mit wenig Arbeitsspeicher zu tun, daher der unsafeData.

// Get the output `Tensor` to process the inference results.
outputTensor = try interpreter.output(at: 0)
// Turn the output tensor into an array. This will have 2 values
// Value at index 0 is the probability of negative sentiment
// Value at index 1 is the probability of positive sentiment
let resultsArray = outputTensor.data
let results: [Float32] = [Float32](unsafeData: resultsArray) ?? []

Jetzt ist es relativ einfach, die Daten zu parsen, um die Spamqualität zu bestimmen. Das Modell hat zwei Ausgaben, die erste mit der Wahrscheinlichkeit, dass es sich bei der Nachricht nicht um Spam handelt, und die zweite mit der Wahrscheinlichkeit, dass es sich um eine Nachricht handelt. Sie können unter results[1] nachsehen, um den Spamwert zu ermitteln:

let positiveSpamValue = results[1]
var outputString = ""
if(positiveSpamValue>0.8){
    outputString = "Message not sent. Spam detected with probability: " + String(positiveSpamValue)
} else {
    outputString = "Message sent!"
}
txtOutput.text = outputString

Der Einfachheit halber finden Sie hier die vollständige Methode:

func classify(sequence: [Int32]){
  // Model Path is the location of the model in the bundle
  let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite")
  var interpreter: Interpreter
  do{
    interpreter = try Interpreter(modelPath: modelPath!)
    } catch _{
      print("Error loading model!")
      Return
  }
  
  let tSequence = Array(sequence)
  let myData = Data(copyingBufferOf: tSequence.map { Int32($0) })
  let outputTensor: Tensor
  do {
    // Allocate memory for the model's input `Tensor`s.
    try interpreter.allocateTensors()

    // Copy the data to the input `Tensor`.
    try interpreter.copy(myData, toInputAt: 0)

    // Run inference by invoking the `Interpreter`.
    try interpreter.invoke()

    // Get the output `Tensor` to process the inference results.
    outputTensor = try interpreter.output(at: 0)
    // Turn the output tensor into an array. This will have 2 values
    // Value at index 0 is the probability of negative sentiment
    // Value at index 1 is the probability of positive sentiment
    let resultsArray = outputTensor.data
    let results: [Float32] = [Float32](unsafeData: resultsArray) ?? []

    let positiveSpamValue = results[1]
    var outputString = ""
    if(positiveSpamValue>0.8){
      outputString = "Message not sent. Spam detected with probability: " + 
                      String(positiveSpamValue)
    } else {
      outputString = "Message sent!"
    }
    txtOutput.text = outputString

  } catch let error {
    print("Failed to invoke the interpreter with error: \(error.localizedDescription)")
  }
}

12. Swift-Erweiterungen hinzufügen

Im Code oben wurde eine Erweiterung des Datentyps verwendet, damit du die Rohbits eines Int32-Arrays in ein Data kopieren kannst. Hier ist der Code für diese Erweiterung:

extension Data {
  /// Creates a new buffer by copying the buffer pointer of the given array.
  ///
  /// - Warning: The given array's element type `T` must be trivial in that it can be copied bit
  ///     for bit with no indirection or reference-counting operations; otherwise, reinterpreting
  ///     data from the resulting buffer has undefined behavior.
  /// - Parameter array: An array with elements of type `T`.
  init<T>(copyingBufferOf array: [T]) {
    self = array.withUnsafeBufferPointer(Data.init)
  }
}

Bei unzureichendem Arbeitsspeicher verwenden Sie „unsicher“ und der obige Code erfordert, dass Sie ein Array unsicherer Daten initialisieren. Diese Erweiterung ermöglicht Folgendes:

extension Array {
  /// Creates a new array from the bytes of the given unsafe data.
  ///
  /// - Warning: The array's `Element` type must be trivial in that it can be copied bit for bit
  ///     with no indirection or reference-counting operations; otherwise, copying the raw bytes in
  ///     the `unsafeData`'s buffer to a new array returns an unsafe copy.
  /// - Note: Returns `nil` if `unsafeData.count` is not a multiple of
  ///     `MemoryLayout<Element>.stride`.
  /// - Parameter unsafeData: The data containing the bytes to turn into an array.
  init?(unsafeData: Data) {
    guard unsafeData.count % MemoryLayout<Element>.stride == 0 else { return nil }
    #if swift(>=5.0)
    self = unsafeData.withUnsafeBytes { .init($0.bindMemory(to: Element.self)) }
    #else
    self = unsafeData.withUnsafeBytes {
      .init(UnsafeBufferPointer<Element>(
        start: $0,
        count: unsafeData.count / MemoryLayout<Element>.stride
      ))
    }
    #endif  // swift(>=5.0)
  }
}

13. iOS-App ausführen

Anwendung ausführen und testen

Wenn alles gut gelaufen ist, sollte die App auf Ihrem Gerät wie folgt angezeigt werden:

74cbd28d9b1592ed.png

Die Meldung "Kaufen Sie mein Buch, um Online-Handel zu lernen!" gesendet wurde, sendet die App eine Spam-Meldung mit einer Wahrscheinlichkeit von 0,99 % zurück.

14. Glückwunsch!

Sie haben nun eine sehr einfache App erstellt, die mithilfe eines Modells, das mit Daten für Spam-Blogs trainiert wurde, Text nach Spam-Kommentaren filtert.

Der nächste Schritt im typischen Entwicklungslebenszyklus besteht darin, zu untersuchen, wie Sie das Modell anhand von Daten aus Ihrer eigenen Community anpassen können. Wie das geht, erfahren Sie in der nächsten Pfadaktivität.