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 zur Einführung in die mobile Textklassifizierung erstellt haben.

Vorbereitung

  • Dieses Codelab richtet sich an erfahrene Entwickler, die neu im Bereich Machine Learning sind.
  • Das Codelab ist Teil eines strukturierten Pfades. 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.

Was Sie [entwickeln oder lernen]

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

Voraussetzungen

2. Vorhandene Android-App öffnen

Sie können den Code dafür in Codelab 1 abrufen oder dieses Repository klonen und die App von 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.

Sobald das Fenster geöffnet ist, können Sie mit Schritt 2 fortfahren.

3. Modelldatei und Metadaten importieren

Im Codelab zum Erstellen eines ML-Modells für Kommentarspam haben Sie ein .TFLITE-Modell erstellt.

Sie sollten die Modelldatei heruntergeladen haben. Wenn Sie es noch nicht haben, können Sie es im Repository für dieses Codelab herunterladen. Das Modell finden Sie hier.

Fügen Sie es Ihrem Projekt hinzu, indem Sie ein Assets-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 aus.

d7c3e9f21035fc15.png

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

2137f956a1ba4ef0.png

In der App ist jetzt der neue Ordner Assets verfügbar.

ae858835e1a90445.png

  1. Klicken Sie mit der rechten Maustaste auf Assets.
  2. Im Menü, das sich öffnet, sehen Sie auf einem Mac die Option Im Finder anzeigen. Wählen Sie sie aus. Unter Windows wird Im Explorer anzeigen angezeigt, unter Ubuntu In Dateien anzeigen.

e61aaa3b73c5ab68.png

Der Finder wird geöffnet, 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. Wenn Sie zu Android Studio zurückkehren, sehen Sie sie im Ordner assets.

150ed2a1d2f7a10d.png

4. build.gradle für die Verwendung von TensorFlow Lite aktualisieren

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

Android-Projekte haben oft mehrere Ebenen. Achten Sie daher darauf, die Ebene 1 der App zu finden. Sie finden sie im Projekt-Explorer in der Android-Ansicht im Abschnitt Gradle-Scripts. Die richtige Datei ist mit .app gekennzeichnet, wie hier zu sehen:

6426051e614bc42f.png

Sie müssen zwei Änderungen an dieser Datei vornehmen. Die erste befindet sich unten im Abschnitt Abhängigkeiten. Fügen Sie einen Text-implementation für die TensorFlow Lite-Aufgabenbibliothek hinzu, z. B. so:

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

Die Versionsnummer hat sich seit der Erstellung dieses Artikels möglicherweise geändert. Die aktuelle Version finden Sie unter https://www.tensorflow.org/lite/inference_with_metadata/task_library/nl_classifier.

Für die Aufgabenbibliotheken ist außerdem mindestens die SDK-Version 21 erforderlich. Suchen Sie diese Einstellung unter android > default config und ändern Sie sie zu 21:

c100b68450b8812f.png

Sie haben jetzt alle Abhängigkeiten. Jetzt können Sie mit dem Codieren beginnen.

5. Hilfsklasse hinzufügen

Wenn Sie die Inferenzlogik, in der Ihre App das Modell verwendet, von der Benutzeroberfläche trennen möchten, erstellen Sie eine weitere Klasse, die die Modellinferenz verarbeitet. Nennen Sie diese Klasse „Hilfsklasse“.

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

d5911ded56b5df35.png

  1. In der Mitte des Bildschirms wird ein Dialogfeld angezeigt, in dem Sie den Paketnamen eingeben müssen. Fügen Sie ihn am Ende des aktuellen Paketnamens hinzu. (Hier werden sie als Hilfsfunktionen bezeichnet.)

3b9f1f822f99b371.png

  1. Klicken Sie dann im Projekt-Explorer mit der rechten Maustaste auf den Ordner helpers.
  2. Wählen Sie Neu > Java-Klasse aus und nennen Sie die Klasse TextClassificationClient. Sie bearbeiten die Datei im nächsten Schritt.

Ihre TextClassificationClient-Hilfsklasse sieht dann so aus (Ihr Paketname kann abweichen).

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 Komplexität der Verwaltung des Datenaustauschs zwischen Ihrer App und dem Modell.

In der load()-Methode 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 umzuwandeln, die richtige Sequenzlänge zu verwenden, ihn an das Modell weiterzugeben und die Ergebnisse zu analysieren.

Weitere Informationen dazu finden Sie im Hilfeartikel „Ein Modell für maschinelles Lernen zum Erkennen von Kommentar-Spam erstellen“.

Die Klassifizierung wird in der Methode „classify“ durchgeführt, bei der Sie einen String übergeben. Daraufhin wird eine List zurückgegeben. 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 Sie beispielsweise eine Nachricht übergeben, die wie Spam aussieht, erhalten Sie 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. „Spam“ und „Kein Spam“ sind Kategorien. Daher enthält die zurückgegebene List diese Wahrscheinlichkeiten. Das werden Sie später herausfinden.

Nachdem Sie die Hilfsklasse erstellt haben, kehren Sie zu MainActivity zurück und aktualisieren Sie sie, damit der Text damit klassifiziert werden kann. Das sehen Sie im nächsten Schritt.

6. 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 Hilfsfunktionen. 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 sie 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 zurück:
var results:List<Category> = client.classify(toSend)

Es gibt nur zwei Kategorien: False und True.

. (TensorFlow sortiert sie alphabetisch, sodass „False“ als Element 0 und „True“ als Element 1 angezeigt wird.)

  1. Um den Wert für die Wahrscheinlichkeit zu erhalten, dass der Wert True ist, können Sie sich results[1].score so 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 handelt es sich nicht um Spam und die Nachricht kann 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 können Sie sich das Modell in Aktion ansehen. Die Nachricht „Besuche meinen Blog, um etwas zu kaufen!“ wurde als Spam eingestuft:

1fb0b5de9e566e.png

Umgekehrt wurde die Wahrscheinlichkeit, dass es sich dabei um Spam handelt, als sehr gering eingestuft:

73f38bdb488b29b3.png

7. iOS-App für die Verwendung des TensorFlow Lite-Modells aktualisieren

Sie können den Code dafür in Codelab 1 herunterladen oder dieses Repository klonen und die App von TextClassificationStep1 laden. Sie finden sie im Pfad TextClassificationOnMobile->iOS.

Der fertige Code ist auch als TextClassificationStep2 verfügbar.

Im Codelab zum Erstellen eines Machine-Learning-Modells für Kommentarspam haben Sie eine sehr einfache App erstellt, mit der Nutzer eine Nachricht in ein UITextView eingeben und ohne Filterung an eine Ausgabe weitergeben konnten.

Sie aktualisieren diese App jetzt so, dass vor dem Senden ein TensorFlow Lite-Modell verwendet wird, um Kommentarspam im Text zu erkennen. Simulieren Sie einfach das Senden in dieser App, indem Sie den Text in einem Ausgabelabel rendern. Eine echte App könnte jedoch ein Bulletin Board, einen Chat oder etwas Ähnliches haben.

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

Zur Einbindung von TensorFlow Lite verwenden Sie CocoaPods. Falls 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 im selben Verzeichnis wie die .xcproject für die TextClassification-App eine Datei mit dem Namen Podfile. Der Inhalt dieser Datei sollte so aussehen:
target 'TextClassificationStep2' do
  use_frameworks!

  # Pods for NLPClassifier
    pod 'TensorFlowLiteSwift'

end

Der Name Ihrer App sollte in der ersten Zeile stehen, anstelle von „TextClassificationStep2“.

Wechseln Sie im Terminal zu diesem Verzeichnis und führen Sie pod install aus. Wenn der Vorgang erfolgreich war, wird ein neues Verzeichnis mit dem Namen Pods und eine neue .xcworkspace-Datei erstellt. Sie verwenden diese in Zukunft anstelle der .xcproject.

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

8. Modell- und Wortschatzdateien hinzufügen

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

  1. Ziehen Sie sie per Drag-and-drop aus dem Finder in das Projektfenster, um sie Ihrem Projekt hinzuzufügen. Achten Sie darauf, dass die Option Zielen hinzufügen aktiviert ist:

1ee9eaa00ee79859.png

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

b63502b23911fd42.png

  1. Prü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 obigen Screenshot ist das das blaue Symbol TextClassificationStep2) und sehen Sie sich den Tab 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 einer bestimmten Reihe von Namen und Werten, die beim Training des Modells erlernt werden. Beachten Sie, dass die meisten Modelle unterschiedliches Vokabular haben und dass es wichtig ist, dass Sie das Vokabular für Ihr Modell verwenden, das zum Zeitpunkt des Trainings generiert wurde. Dies ist die vocab.txt-Datei, die Sie Ihrer App gerade hinzugefügt haben.

Sie können die Datei in Xcode öffnen, um die Codierungen anzuzeigen. Wörter wie „Lied“ werden in 6 und „love“ auf 12 codiert. Die Reihenfolge ist tatsächlich die Reihenfolge der Häufigkeit. „Ich“ war also das häufigste Wort im Datensatz, gefolgt von „Prüfen“.

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

Sehen wir uns diesen Code an. Laden Sie zuerst das Vokabular.

  1. Definieren Sie eine Variable auf Klassenebene, um das Wörterbuch zu speichern:
var words_dictionary = [String : Int]()
  1. Erstellen Sie dann in der Klasse eine func, 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 den Befehl in viewDidLoad aufrufen:
override func viewDidLoad() {
    super.viewDidLoad()
    txtInput.delegate = self
    loadVocab()
}

10. Strings in eine Sequenz von Tokens umwandeln

Ihre Nutzer geben Wörter als Satz ein, der zu einem String 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 in der Regel eine feste Sequenzlänge. Es gibt Ausnahmen bei Modellen, die mit ragged tensors erstellt wurden, aber in den meisten Fällen ist das Problem behoben. Sie haben diese Länge beim Erstellen des Modells angegeben. Achten Sie darauf, dass Sie in Ihrer iOS-App dieselbe Länge verwenden.

Die Standardeinstellung in Colab für den TensorFlow Lite Model Maker, den Sie zuvor verwendet haben, war 20. Legen Sie diese Einstellung hier ebenfalls fest:

let SEQUENCE_LENGTH = 20

Fügen Sie func hinzu. Damit wird der String in Kleinbuchstaben konvertiert 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
}

Die Sequenz besteht aus Int32-Werten. Das ist eine bewusste Entscheidung, da Sie beim Übergeben von Werten an TensorFlow Lite mit Low-Level-Speicher zu tun haben und TensorFlow Lite die Ganzzahlen in einer Stringsequenz als 32‑Bit-Ganzzahlen behandelt. Das macht es (ein wenig) einfacher, Strings an das Modell zu übergeben.

11. Klassifizierung durchführen

Um einen Satz zu klassifizieren, muss er zuerst in eine Tokenfolge umgewandelt werden, die auf den Wörtern im Satz basiert. Dies erfolgt in Schritt 9.

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

Dazu 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 ein Interpreter damit aufgerufen.

Im nächsten Schritt wird der zugrunde liegende Speicher, der in der Sequenz gespeichert ist, in einen Puffer 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 Tensortyp erhalten.

Starten Sie den Code so (noch in der Funktion „classify“ func):

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

Keine Sorge, wenn bei copyingBufferOf ein Fehler auftritt. Diese wird später als Erweiterung implementiert.

Jetzt ist es an der Zeit, Tensoren für den Interpreter zuzuweisen, den gerade erstellten Datenpuffer in den Eingabe-Tensor zu kopieren und den Interpreter dann für die Inferenz aufzurufen:

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 die Ausführung 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 analysieren und die Spamqualität zu bestimmen. Das Modell hat zwei Ausgabewerte: der erste gibt die Wahrscheinlichkeit an, dass die Nachricht kein Spam ist, der zweite die Wahrscheinlichkeit, dass sie es ist. Den Spamwert finden Sie unter results[1]:

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 obigen Code wurde eine Erweiterung des Datentyps verwendet, damit die Rohbits eines Int32-Arrays in eine Data kopiert werden können. 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)
  }
}

Wenn Sie mit Low-Level-Speicher arbeiten, verwenden Sie „unsichere“ Daten. Im obigen Code müssen Sie ein Array mit unsicheren Daten initialisieren. Mit dieser Erweiterung ist Folgendes möglich:

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

Führen Sie die App aus und testen Sie sie.

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

74cbd28d9b1592ed.png

Wenn die Nachricht „Kaufen Sie mein Buch, um Online-Handel zu lernen!!“ gesendet wurde, sendet die App eine Spam-Warnung mit einer Wahrscheinlichkeit von 0,99 % zurück.

14. Glückwunsch!

Sie haben jetzt eine sehr einfache App erstellt, die Text mithilfe eines Modells, das mit Daten trainiert wurde, die zum Spammen von Blogs verwendet wurden, auf Kommentarspam filtert.

Im nächsten Schritt des typischen Entwicklerlebenszyklus geht es darum, herauszufinden, was erforderlich ist, um das Modell anhand der Daten in Ihrer eigenen Community anzupassen. Wie das geht, erfahren Sie in der nächsten Aktivität.