Uygulamanızı spam filtreleme Makine Öğrenimi modeli kullanacak şekilde güncelleme

1. Başlamadan önce

Bu codelab'de, önceki Mobil metin sınıflandırması ile çalışmaya başlama codelab'lerinde oluşturduğunuz uygulamayı güncelleyeceksiniz.

Ön koşullar

  • Bu codelab, makine öğrenimi konusunda yeni olan deneyimli geliştiriciler için tasarlanmıştır.
  • Kod laboratuvarı, sıralı bir yolun parçasıdır. Temel mesajlaşma tarzı uygulama oluşturma veya Yorum spam'i makine öğrenimi modeli oluşturma başlıklı makaleleri henüz tamamlamadıysanız lütfen durup bunları şimdi tamamlayın.

[Geliştireceğiniz veya öğreneceğiniz]

  • Önceki adımlarda oluşturduğunuz özel modeli uygulamanıza nasıl entegre edeceğinizi öğreneceksiniz.

İhtiyacınız olanlar

2. Mevcut Android uygulamasını açma

1. Codelab'i uygulayarak veya bu deposunu kopyalayıp uygulamayı TextClassificationStep1 adresinden yükleyerek bu kodu alabilirsiniz.

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

Bu dosyayı TextClassificationOnMobile->Android yolunda bulabilirsiniz.

Bitmiş kodunu TextClassificationStep2 olarak da kullanabilirsiniz.

Uygulama açıldıktan sonra 2. adıma geçebilirsiniz.

3. Model dosyasını ve meta verilerini içe aktarma

Yorum spam'i makine öğrenimi modeli oluşturma kod laboratuvarında bir .TFLITE modeli oluşturdunuz.

Model dosyasını indirmeniz gerekir. Kod deposuna sahip değilseniz bu codelab'in depoundan alabilirsiniz. Modele buradan erişebilirsiniz.

Öğe dizini oluşturarak projenize ekleyin.

  1. Proje gezginini kullanarak en üstte Android'in seçili olduğundan emin olun.
  2. Uygulama klasörünü sağ tıklayın. Yeni > Dizin'i seçin.

d7c3e9f21035fc15.png

  1. Yeni Dizin iletişim kutusunda src/main/assets'i seçin.

2137f956a1ba4ef0.png

Uygulamada yeni bir assets klasörü olduğunu göreceksiniz.

ae858835e1a90445.png

  1. Öğeler'i sağ tıklayın.
  2. Açılan menüde (Mac'te) Finder'da Göster'i görürsünüz. Uygulamayı seçin. (Windows'da Gezgin'de Göster, Ubuntu'da Dosyalar'da Göster ifadesi gösterilir.)

e61aaa3b73c5ab68.png

Dosyaların konumunu göstermek için Finder (Windows'da Dosya Gezgini, Linux'da Dosyalar) açılır.

  1. labels.txt, model.tflite ve vocab dosyalarını bu dizine kopyalayın.

14f382cc19552a56.png

  1. Android Studio'ya geri döndüğünüzde bu öğeleri assets klasörünüzde bulabilirsiniz.

150ed2a1d2f7a10d.png

4. build.gradle dosyanızı TensorFlow Lite'ı kullanacak şekilde güncelleyin

TensorFlow Lite'ı ve onu destekleyen TensorFlow Lite görev kitaplıklarını kullanmak için build.gradle dosyanızı güncellemeniz gerekir.

Android projelerinde genellikle birden fazla düzey bulunur. Bu nedenle, uygulama düzeyini bulduğunuzdan emin olun. Android görünümündeki proje gezgininde Gradle Komut Dosyaları bölümünde bulabilirsiniz. Doğru URL, burada gösterildiği gibi .app ile etiketlenir:

6426051e614bc42f.png

Bu dosyada iki değişiklik yapmanız gerekir. İlki, en alttaki bağımlılıklar bölümündedir. TensorFlow Lite görev kitaplığı için şu şekilde bir metin implementation ekleyin:

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

Bu makale yazıldıktan sonra sürüm numarası değişmiş olabilir. En son sürüm için https://www.tensorflow.org/lite/inference_with_metadata/task_library/nl_classifier adresini kontrol edin.

Görev kitaplıkları için de minimum SDK sürümü 21 olmalıdır. Bu ayarı android > default config bölümünde bulun ve 21 olarak değiştirin:

c100b68450b8812f.png

Tüm bağımlılıklarınız mevcut, şimdi kodlamaya başlamanın zamanı geldi.

5. Yardımcı sınıf ekleme

Uygulamanızın modeli kullandığı çıkarım mantığını kullanıcı arayüzünden ayırmak için model çıkarımıyla ilgilenecek başka bir sınıf oluşturun. Buna "yardımcı" sınıfı diyebilirsiniz.

  1. MainActivity kodunuzun bulunduğu paket adını sağ tıklayın.
  2. Yeni > Paket'i seçin.

d5911ded56b5df35.png

  1. Ekranın ortasında paket adını girmenizi isteyen bir iletişim kutusu görürsünüz. Mevcut paket adının sonuna ekleyin. (Burada yardımcılar olarak adlandırılır.)

3b9f1f822f99b371.png

  1. Bu işlem tamamlandıktan sonra proje gezgininde helpers klasörünü sağ tıklayın.
  2. Yeni > Java Sınıfı'nı seçin ve sınıfı TextClassificationClient olarak adlandırın. Dosyayı bir sonraki adımda düzenleyeceksiniz.

TextClassificationClient yardımcı sınıfınız şöyle görünür (paket adınız farklı olabilir.)

package com.google.devrel.textclassificationstep1.helpers;

public class TextClassificationClient {
}
  1. Dosyayı şu kodla güncelleyin:
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;
    }

}

Bu sınıf, TensorFlow Lite yorumlayıcısı için bir sarmalayıcı sağlar. Sarmalayıcı, modeli yükler ve uygulamanız ile model arasında veri alışverişini yönetmenin karmaşıklığını soyutlar.

load() yönteminde, model yolundan yeni bir NLClassifier türü oluşturulur. Model yolu, modelin adıdır (model.tflite). NLClassifier türü, metin görevleri kitaplıklarının bir parçasıdır ve dizenizi jetonlara dönüştürerek, doğru sıra uzunluğunu kullanarak, modele ileterek ve sonuçları ayrıştırarak size yardımcı olur.

(Bu konular hakkında daha fazla bilgi için "Yorum spam'i makine öğrenimi modeli oluşturma" başlıklı makaleyi tekrar inceleyin.)

Sınıflandırma, sınıflandırma yönteminde yapılır; burada bir dize iletirsiniz ve bir List değeri döndürülür. Bir dizenin spam olup olmadığını belirlemek istediğiniz içeriği sınıflandırmak için makine öğrenimi modelleri kullanırken, tüm yanıtların atanan olasılıklarla döndürülmesi yaygındır. Örneğin, spam gibi görünen bir iletiyi gönderirseniz spam olma olasılığı ve spam olmama olasılığı içeren 2 yanıt alırsınız. Spam/Spam değil kategorileri olduğundan, döndürülen List bu olasılıkları içerir. Bu bilgileri daha sonra ayrıştıracaksınız.

Yardımcı sınıfı oluşturduğunuza göre MainActivity dosyanıza dönün ve metninizi sınıflandırmak için bu sınıfı kullanacak şekilde güncelleyin. Bunu bir sonraki adımda göreceksiniz.

6. Metni sınıflandırma

MainActivity hesabınızda ilk olarak yeni oluşturduğunuz yardımcıları içe aktarmanız gerekir.

  1. MainActivity.kt dosyasının en üstüne, diğer içe aktarma dosyalarıyla birlikte şunları ekleyin:
import com.google.devrel.textclassificationstep2.helpers.TextClassificationClient
import org.tensorflow.lite.support.label.Category
  1. Ardından, yardımcıları yükleyebilirsiniz. onCreate dosyasında, setContentView satırından hemen sonra yardımcı sınıfı oluşturmak ve yüklemek için aşağıdaki satırları ekleyin:
val client = TextClassificationClient(applicationContext)
client.load()

Düğmenizin onClickListener şu anda aşağıdaki gibi görünmesi gerekir:

btnSendText.setOnClickListener {
     var toSend:String = txtInput.text.toString()
     txtOutput.text = toSend
 }
  1. Aşağıdaki gibi güncelleyin:
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()
}

Bu değişiklik, kullanıcının girdisini oluşturmaktan onu önce sınıflandırmaya kadar işlevi değiştirir.

  1. Bu satırda, kullanıcının girdiği dizeyi alıp modele ileterek sonuçları alırsınız:
var results:List<Category> = client.classify(toSend)

Yalnızca 2 kategori vardır: False ve True

. (TensorFlow bunları alfabetik olarak sıralar. Bu nedenle False 0. öğe, True ise 1. öğe olur.)

  1. Değerin True olma olasılığının puanını almak için results[1].score değerine şu şekilde bakabilirsiniz:
    val score = results[1].score
  1. Doğru kategorisinin puanı eşik değerinin (0,8) üzerindeyse mesajın spam olduğunu belirttiğiniz bir eşik değeri (bu durumda 0,8) seçin. Aksi takdirde, ileti spam değildir ve gönderilmesi güvenlidir:
    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. Modelin nasıl kullanıldığını burada görebilirsiniz. "Alışveriş yapmak için blogumu ziyaret edin!" iletisi yüksek olasılıkla spam olarak işaretlenmişti:

1fb0b5de9e566e.png

Buna karşılık, "Hey, eğlenceli bir eğitim, teşekkürler!" ifadesinin spam olma olasılığının çok düşük olduğu anlaşılıyor:

73f38bdb488b29b3.png

7. TensorFlow Lite Modelini kullanmak için iOS Uygulamanızı güncelleme

1. Codelab'i uygulayarak veya bu deposunu kopyalayıp uygulamayı TextClassificationStep1 adresinden yükleyerek bu kodu alabilirsiniz. Bu dosyayı TextClassificationOnMobile->iOS yolunda bulabilirsiniz.

Bitmiş kodunu TextClassificationStep2 olarak da kullanabilirsiniz.

Yorum spam'i makine öğrenimi modeli oluşturma kod laboratuvarında, kullanıcının bir UITextView alanına mesaj yazmasına ve bu mesajın filtrelenmeden bir çıkışa aktarılmasına olanak tanıyan çok basit bir uygulama oluşturdunuz.

Şimdi bu uygulamayı, göndermeden önce metindeki yorum spam'ini algılamak için TensorFlow Lite modeli kullanacak şekilde güncelleyeceksiniz. Metni bir çıkış etiketinde oluşturarak bu uygulamada göndermeyi simüle edin (ancak gerçek bir uygulamada bülten tahtası, sohbet veya benzer bir şey olabilir).

Başlamak için 1. adımdaki uygulamaya ihtiyacınız vardır. Bu uygulamayı depodan klonlayabilirsiniz.

TensorFlow Lite'i dahil etmek için CocoaPods'u kullanacaksınız. Bu araçlar yüklü değilse https://cocoapods.org/ adresindeki talimatları uygulayarak yükleyebilirsiniz.

  1. CocoaPods'u yükledikten sonra, TextClassification uygulamasının .xcproject klasörünün aynısında Podfile adlı bir dosya oluşturun. Bu dosyanın içeriği şöyle görünmelidir:
target 'TextClassificationStep2' do
  use_frameworks!

  # Pods for NLPClassifier
    pod 'TensorFlowLiteSwift'

end

İlk satırda "TextClassificationStep2" yerine uygulamanızın adı olmalıdır.

Terminal'i kullanarak ilgili dizine gidin ve pod install komutunu çalıştırın. İşlem başarılı olursa Pods adlı yeni bir dizin ve sizin için yeni bir .xcworkspace dosyası oluşturulur. Gelecekte .xcproject yerine bu adı kullanacaksınız.

İşlem başarısız olduysa lütfen Podfile'ı .xcproject ile aynı dizinde bulundurduğunuzdan emin olun. Yanlış dizinde bulunan pod dosyası veya yanlış hedef ad genellikle bu sorunun başlıca nedenidir.

8. Model ve kelime listesi dosyalarını ekleme

Modeli TensorFlow Lite Model Maker ile oluşturduğunuzda modeli (model.tflite olarak) ve sözlüğünü (vocab.txt olarak) dışa aktarabildiniz.

  1. Bu araçları Finder'dan proje pencerenize sürükleyip bırakarak projenize ekleyin. Hedeflere ekle seçeneğinin işaretli olduğundan emin olun:

1ee9eaa00ee79859.png

İşlemi tamamladığınızda bunları projenizde görürsünüz:

b63502b23911fd42.png

  1. Projenizi seçerek (yukarıdaki ekran görüntüsünde TextClassificationStep2 adlı mavi simge) ve Derleme Aşamaları sekmesine bakarak bunların pakete eklendiğinden (böylece bir cihaza dağıtılacağından) emin olun:

20b7cb603d49b457.png

9. Kelime hazinesini yükleme

NLP sınıflandırması yapılırken model, vektörlere kodlanmış kelimelerle eğitilir. Model, kelimeleri model eğitilirken öğrenilen belirli bir ad ve değer kümesiyle kodlar. Çoğu modelin kelime dağarcığının farklı olacağını ve eğitim sırasında oluşturulan modelinizin kelime dağarcığınızı kullanmanızın önemli olduğunu lütfen unutmayın. Bu, uygulamanıza yeni eklediğiniz vocab.txt dosyasıdır.

Kodlamaları görmek için dosyayı Xcode'da açabilirsiniz. "Şarkı" gibi kelimeler 6, "aşk" gibi kelimeler ise 12 olarak kodlanır. Sıralama aslında sıklık sırasıdır. Dolayısıyla, veri kümesinde en sık kullanılan kelime "I", ardından "check" (kontrol et) gelir.

Kullanıcılarınız kelimeleri yazdığında, onları sınıflandırılacak modele göndermeden önce bu kelime dağarcığıyla kodlamanız gerekir.

Bu kodu inceleyelim. Kelime hazinesini yükleyerek başlayın.

  1. Sözlüğü depolayacak sınıf düzeyinde bir değişken tanımlayın:
var words_dictionary = [String : Int]()
  1. Ardından, sınıfta sözlüğü bu sözlüğe yüklemek için bir func oluşturun:
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. Bu komutu, viewDidLoad içinden çağırarak çalıştırabilirsiniz:
override func viewDidLoad() {
    super.viewDidLoad()
    txtInput.delegate = self
    loadVocab()
}

10. Bir dizeyi jeton dizisine dönüştürme

Kullanıcılarınız kelimeleri cümle olarak yazar ve bu kelime bir dizeye dönüşür. Sözlükte yer alan cümledeki her kelime, kelimenin sözlükte tanımlandığı anahtar değerine kodlanır.

NLP modelleri genellikle sabit bir sıra uzunluğunu kabul eder. ragged tensors kullanılarak oluşturulan modellerde istisnalar olsa da çoğu durumda bu sorunun düzeltildiğini görürsünüz. Modelinizi oluştururken bu uzunluğu belirtmişsinizdir. iOS uygulamanızda da aynı uzunlukta bir resim kullandığınızdan emin olun.

Daha önce kullandığınız TensorFlow Lite Model Maker için Colab'da varsayılan değer 20 idi. Bu değeri burada da ayarlayın:

let SEQUENCE_LENGTH = 20

Dizeyi alıp küçük harfe dönüştürecek ve noktalama işaretlerini kaldıracak olan bu func öğesini ekleyin:

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
}

Sıranın Int32 olacağını unutmayın. TensorFlow Lite'e değer aktarırken düşük düzey bellekle uğraşacağınız ve TensorFlow Lite, bir dize dizisindeki tam sayıları 32 bitlik tam sayılar olarak değerlendireceği için bu yöntem kasıtlı olarak seçilmiştir. Bu, modele dize aktarma konusunda hayatınızı (biraz) kolaylaştırır.

11. Sınıflandırmayı yapın

Bir cümlenin sınıflandırılabilmesi için önce cümledeki kelimelere göre bir jeton dizisine dönüştürülmesi gerekir. Bu işlem 9. adımda yapılmıştır.

Ardından cümleyi alıp modele iletecek, modelin cümleyle ilgili çıkarım yapmasını sağlayacak ve sonuçları ayrıştıracaksınız.

Bu işlem için TensorFlow Lite yorumlayıcısı kullanılır. Yorumlayıcıyı içe aktarmanız gerekir:

import TensorFlowLite

Int32 türünde bir dizi olan dizinizi alan bir func ile başlayın:

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
  }

Bu işlem, model dosyasını paketten yükler ve bir yorumlayıcıyı çağırır.

Sonraki adım, dizide depolanan temel belleği myData, adlı bir arabelleğe kopyalamaktır. Böylece tensöre iletilebilir. TensorFlow Lite kapsülünü ve yorumlayıcıyı uygularken bir Tensor türüne eriştiniz.

Kodu şu şekilde başlatın (hâlâ sınıflandırma func içinde):

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

copyingBufferOf sırasında hata alırsanız endişelenmeyin. Bu özellik daha sonra bir uzantı olarak uygulanacaktır.

Şimdi yorumlayıcıda tenzor ayırmanın, yeni oluşturduğunuz veri arabelleğini giriş tenzoruna kopyalamanın ve ardından çıkarım yapmak için yorumlayıcıyı çağırmanın zamanı geldi:

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()

Çağırma işlemi tamamlandıktan sonra sonuçları görmek için yorumlayıcının çıktısına bakabilirsiniz.

Bunlar, daha sonra okumanız ve dönüştürmeniz gereken ham değerler (nöron başına 4 bayt) olacaktır. Bu modelde 2 çıkış nöronu bulunduğundan, ayrıştırma için Float32'ye dönüştürülecek 8 bayt okumanız gerekir. Düşük seviyeli bellekle uğraştığınız için 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) ?? []

Spam kalitesini belirlemek için verileri ayrıştırmak artık nispeten daha kolay. Modelin 2 çıkışı vardır. Bunlardan ilki, ileti spam olmama olasılığını, ikincisi ise spam olma olasılığını belirtir. Bu nedenle, spam değerini bulmak için results[1] değerine bakabilirsiniz:

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

Kolaylık sağlaması açısından, yöntemin tamamını aşağıda bulabilirsiniz:

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 uzantılarını ekleme

Yukarıdaki kod, bir Int32 dizisinin ham bitlerini Data içine kopyalamanıza olanak tanımak için Veri türünün bir uzantısını kullanmıştır. İşte bu uzantının kodu:

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)
  }
}

Düşük düzeyli bellekle çalışırken "güvenli olmayan" veriler kullanırsınız ve yukarıdaki kodda bir güvenli olmayan veri dizisi başlatmanız gerekir. Bu uzantı sayesinde şunları yapabilirsiniz:

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 uygulamasını çalıştırma

Uygulamayı çalıştırın ve test edin.

Her şey yolunda giderse uygulamayı cihazınızda şu şekilde görürsünüz:

74cbd28d9b1592ed.png

"Online ticareti öğrenmek için kitabımı satın alın!" mesajının gönderildiği yerde uygulama %0, 99 olasılıklı bir spam tespit uyarısı gönderir.

14. Tebrikler!

Artık, bloglara spam göndermek için kullanılan verilerle eğitilmiş bir model kullanarak metni yorum spam'i açısından filtreleyen çok basit bir uygulama oluşturdunuz.

Tipik geliştirici yaşam döngüsünün bir sonraki adımı, modeli kendi topluluğunuzdaki verilere göre özelleştirmek için ne gerektiğini keşfetmektir. Bunu nasıl yapacağınızı bir sonraki yol haritası etkinliğinde göreceksiniz.