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

1. Başlamadan önce

Bu codelab'de, önceki Mobil metin sınıflandırma codelab'lerini kullanmaya başlayın bölümünde oluşturduğunuz uygulamayı güncelleyeceksiniz.

Ön koşullar

  • Bu codelab, makine öğrenimine yeni başlayan deneyimli geliştiriciler için tasarlanmıştır.
  • Codelab, sıralı bir yolun bir parçasıdır. Temel mesajlaşma tarzı bir uygulama geliştirme veya Yorum spam'i makine öğrenimi modeli geliştirme işlemlerini henüz tamamlamadıysanız lütfen durun ve bu adımları ş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.

Gerekenler

2. Mevcut Android Uygulamasını Açın

Bunun kodunu, Codelab 1'i takip ederek veya bu depoyu klonlayıp TextClassificationStep1 üzerinden uygulamayı yükleyerek alabilirsiniz.

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

Bu adı TextClassificationOnMobile->Android yolunda bulabilirsiniz.

Tamamlanmış kodu TextClassificationStep2 olarak da kullanabilirsiniz.

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

3. Model Dosyasını ve Meta Verileri İçe Aktarma

Yorum spam'i makine öğrenimi model codelab'i oluşturma bölümünde bir .TFLITE modeli oluşturdunuz.

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

Bir öğe dizini oluşturarak projeyi projenize ekleyin.

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

d7c3e9f21035fc15.png

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

2137f956a1ba4ef0.png

Artık uygulamada yeni bir assets klasörünü göreceksiniz.

ae858835e1a90445.png

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

e61aaa3b73c5ab68.png

Finder, dosyaların konumunu (Windows'da Dosya Gezgini, Linux'ta Dosyalar) göstermek üzere başlatılır.

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

14f382cc19552a56.png

  1. Android Studio'ya dönün. Bunları assets klasörünüzde görürsünüz.

150ed2a1d2f7a10d.png

4. TensorFlow Lite'ı kullanmak için derleme.gradle dosyanızı 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 proje olur. Bu nedenle birinci düzey uygulama olduğundan emin olun. Android görünümündeki proje gezgininde bunu Gradle Komut Dosyaları bölümünde bulun. Doğru uygulama, burada gösterildiği gibi .app ile etiketlenir:

6426051e614bc42f.png

Bu dosyada iki değişiklik yapmanız gerekiyor. İlki, alt kısımdaki bağımlılıklar bölümündedir. TensorFlow Lite görev kitaplığı için implementation metnini şu şekilde ekleyin:

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

Sürüm numarası yazıldıktan sonra değişmiş olabilir. Bu nedenle, en güncel sürüm için https://www.tensorflow.org/lite/inference_with_metadata/task_library/nl_classifier sayfasını kontrol etmeyi unutmayın.

Ayrıca görev kitaplıkları için SDK'nın en az 21 sürümü olması gerekir. Bu ayarı android > default config 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 ekle

Uygulamanızın modeli kullandığı çıkarım mantığını kullanıcı arayüzünden ayırmak için model çıkarımını işleyecek başka bir sınıf oluşturun. Bunu "yardımcı" olarak adlandır sınıfını kullanır.

  1. MainActivity kodunuzun bulunduğu paket adını sağ tıklayın.
  2. Yeni > Paket.

d5911ded56b5df35.png

  1. Ekranın ortasında paket adını girmenizi isteyen bir iletişim kutusu görürsünüz. Geçerli paket adının sonuna ekleyin. (Burada, adı helpers olarak verilmiştir.)

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 TextClassificationClient olarak adlandırın. Dosyayı sonraki adımda düzenleyeceksiniz.

TextClassificationClient yardımcı sınıfınız şöyle görünecektir (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ına bir sarmalayıcı sağlayarak modeli yükler ve uygulamanız ile model arasındaki veri alışverişini yönetmenin karmaşıklığını soyutlar.

load() yönteminde bu işlem, model yolundan yeni bir NLClassifier türü oluşturur. Model yolu, basitçe modelin model.tflite adıdır. NLClassifier türü, metin görevleri kitaplıklarının bir parçasıdır. Dizenizi doğru sıra uzunluğunu kullanarak jetona dönüştürerek, 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 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 modellerini kullanırken tüm yanıtların belirli olasılıklarla döndürülmesi yaygın bir durumdur. Örneğin, spam gibi görünen bir ileti iletirseniz 2 yanıt içeren bir liste alırsınız; bir tanesi spam, diğeri spam olmasın. Spam/Spam değil kategorileri olduğundan, döndürülen List bu olasılıkları içerir. Daha sonra bunu ayrıştıracaksınız.

Artık yardımcı sınıfa sahip olduğunuza göre MainActivity sayfanıza geri 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 içinde ilk olarak oluşturduğunuz yardımcıları içe aktarmanız gerekir.

  1. MainActivity.kt öğesinin üst tarafına, diğer içe aktarma işlemleriyle birlikte şunu ekleyin:
import com.google.devrel.textclassificationstep2.helpers.TextClassificationClient
import org.tensorflow.lite.support.label.Category
  1. Ardından, yardımcıları yükleyebilirsiniz. onCreate içinde, setContentView satırının hemen sonrasına, yardımcı sınıfı örneklendirmek ve yüklemek için şu satırları ekleyin:
val client = TextClassificationClient(applicationContext)
client.load()

Şu anda, düğmenizin onClickListener özelliği aşağıdaki gibi görünmelidir:

btnSendText.setOnClickListener {
     var toSend:String = txtInput.text.toString()
     txtOutput.text = toSend
 }
  1. Aşağıdaki gibi görünecek şekilde 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 çıktıktan sonra sadece onu sınıflandırmak için gereken işlevi değiştirir.

  1. Bu satırla, kullanıcının girdiği dizeyi alıp modele geçirerek sonuçları geri 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ıraladığından Yanlış değeri öğe 0, Doğru değeri ise 1. öğe olur.)

  1. Değerin True olma olasılığının puanını öğrenmek için şu şekilde sonuçlar[1].puanına bakabilirsiniz:
    val score = results[1].score
  1. Bir eşik değeri (bu örnekte 0,8) seçtiniz. Bu değerde, Doğru kategorisinin puanı eşik değerinin (0,8) üzerindeyse iletinin spam olduğunu belirtir. Aksi takdirde ileti spam değildir ve güvenli bir şekilde gönderilebilir:
    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. Modeli çalışırken görün. "Satın almak için blogumu ziyaret edin!" mesajı , büyük olasılıkla spam olarak işaretlendi:

1fb0b5de9e566e.png

Öte yandan, "Eğlenceli bir eğitim, teşekkürler!" spam olma olasılığının çok düşük olduğu belirlendi:

73f38bdb488b29b3.png

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

Bunun kodunu, Codelab 1'i takip ederek veya bu depoyu klonlayıp TextClassificationStep1 üzerinden uygulamayı yükleyerek alabilirsiniz. Bu adı TextClassificationOnMobile->iOS yolunda bulabilirsiniz.

Tamamlanmış kodu TextClassificationStep2 olarak da kullanabilirsiniz.

"Yorum spam'i" makine öğrenimi modeli codelab'inde, kullanıcının UITextView bölümüne mesaj yazmasına ve herhangi bir filtreleme olmadan bir çıkışa iletmesine olanak tanıyan çok basit bir uygulama oluşturdunuz.

Şimdi bu uygulamayı, göndermeden önce metindeki yorum spam'lerini tespit etmek için TensorFlow Lite modeli kullanacak şekilde güncelleyeceksiniz. Metni çıkış etiketinde oluşturarak bu uygulamada gönderme simülasyonu yapın (ancak gerçek bir uygulamada bülten panosu, sohbet veya benzer bir şey bulunabilir).

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

TensorFlow Lite'ı dahil etmek için CocoaPods kullanırsınız. Henüz yapmadıysanız https://cocoapods.org/ adresindeki talimatları uygulayarak bu işlemi yapabilirsiniz.

  1. CocoaPods'u yükledikten sonra, TextClassification uygulaması için .xcproject ile aynı dizinde Podfile adlı bir dosya oluşturun. Bu dosyanın içeriği aşağıdaki gibi görünmelidir:
target 'TextClassificationStep2' do
  use_frameworks!

  # Pods for NLPClassifier
    pod 'TensorFlowLiteSwift'

end

Uygulamanızın adı "TextClassificationStep2" yerine ilk satırda olmalıdır.

Terminal'i kullanarak söz konusu dizine gidin ve pod install komutunu çalıştırın. İşlem başarılı olursa Kapsüller adında yeni bir dizininiz ve sizin için yeni bir .xcworkspace dosyası oluşturulur. İleride .xcproject yerine bu adı kullanacaksınız.

İşlem başarısız olduysa lütfen Podfile'ı .xcproject ile aynı dizinde bulundurduğunuzdan emin olun. Bu durumun ana nedeni genellikle yanlış dizindeki podfile' ya da yanlış hedef addır.

8. Model ve Vocab dosyalarını ekleme

Modeli TensorFlow Lite Model Maker ile oluşturduğunuzda modelin (model.tflite olarak) ve kelime öbeğinin (vocab.txt olarak) çıkışını yapabildiniz.

  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

İşiniz bittiğinde projenizde bu görevleri göreceksiniz:

b63502b23911fd42.png

  1. Projenizi seçerek (yukarıdaki ekran görüntüsünde mavi simgeyle TextClassificationStep2'dir) ve Derleme Aşamaları sekmesine bakarak bunların pakete eklendiklerini (bir cihaza dağıtılmaları için) tekrar kontrol edin:

20b7cb603d49b457.png

9. Kelime Bilgisi 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 grubuyla 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 az önce eklediğiniz vocab.txt dosyası.

Kodlamaları görmek için dosyayı Xcode'da açabilirsiniz. "Şarkı" gibi kelimeler 6 ve "aşk" olarak kodlanmıştır 12'ye. Sıra aslında sıklık sırası şeklindedir. Dolayısıyla "I" , veri kümesinde en sık kullanılan kelimeydi ve ardından "kontrol et" geldi.

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. Sözlüğü yükleyerek başlayın.

  1. Sözlüğün kaydedileceği sınıf düzeyinde bir değişken tanımlayın:
var words_dictionary = [String : Int]()
  1. Ardından, sözlüğü şu sözlüğe yüklemek için sınıfta 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 varsa cümledeki her kelime, kelime öbeğinde tanımlandığı şekilde kelimenin anahtar değerine kodlanır.

NLP modelleri genellikle sabit bir dizi uzunluğunu kabul eder. ragged tensors kullanılarak oluşturulan modellerle ilgili istisnalar vardır ancak çoğunlukla bu durumun düzeltilmiş olduğunu göreceksiniz. Modelinizi oluşturduğunuzda bu uzunluğu belirtmiştiniz. iOS uygulamanızda da aynı uzunluğu kullandığınızdan emin olun.

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

let SEQUENCE_LENGTH = 20

Dizeyi alacak, küçük harfe dönüştürecek ve noktalama işaretlerini çıkaracak şu func kodunu 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
}

Dizinin Int32'de olacağını unutmayın. Değerleri TensorFlow Lite'a aktarmak söz konusu olduğunda düşük seviyeli bellekle ilgileneceğiniz ve TensorFlow Lite'ın bir dize dizisindeki tam sayıları 32 bitlik tamsayılar olarak işlemesi nedeniyle bu kasten seçilmiştir. Bu, dizeleri modele geçirmek söz konusu olduğunda hayatınızı (biraz) kolaylaştıracaktır.

11. Sınıflandırmayı yapma

Bir cümlenin sınıflandırılması için öncelikle cümledeki kelimelere dayalı olarak bir dizi deyime dönüştürülmesi gerekir. Bu işlem 9. adımda yapılacaktır.

Şimdi cümleyi alıp modele iletecek, modelin cümleden çıkarımda bulunmasını sağlayacak ve sonuçları ayrıştıracaksınız.

Bu işlem, içe aktarmanız gereken TensorFlow Lite yorumlayıcısını kullanır:

import TensorFlowLite

Sıranızı alan bir func ile başlayın. Bu, Int32 türlerden oluşan bir dizidir:

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 çevirmen ç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 çevirmeni uygularken bir Tensor Türüne erişim elde ettiniz.

Kodu şu şekilde başlatın (hâlâ func sınıflandırmasında).

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

copyingBufferOf ile ilgili hata alırsanız endişelenmeyin. Bu, daha sonra bir uzantı olarak uygulanacaktır.

Şimdi sıra, yorumlayıcıya tensör ayırma, az önce oluşturduğunuz veri arabelleğini giriş tensörüne kopyalama ve çıkarımı yapması için yorumlayıcıyı çağırmaya 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ğrı tamamlandığında sonuçları görmek için çevirmenin çıkışı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 olduğundan, ayrıştırma için Kayma32'ye dönüştürülecek 8 bayt cinsinden okumanız gerekir. Düşük seviye bellekle uğraştığınızdan 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. İlkinin iletinin spam olmaması, ikincisinin ise iletinin spam olmaması olasılığı bulunur. Spam değerini bulmak için results[1] dosyasına 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 olması için yöntemin tamamı aşağıda verilmiştir:

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ı Ekleyin

Yukarıdaki kod, bir Int32 dizisinin ham bitlerini bir Data öğesine kopyalamanıza olanak tanımak için Veri türüne yönelik bir uzantı 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 seviye bellekle çalışırken "güvenli değil" verilerini içeriyorsa ve yukarıdaki kod güvenli olmayan bir veri dizisi başlatmanızı gerektiriyor. Bu uzantı şunları mümkün kılar:

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ırın

Uygulamayı çalıştırıp test edin.

Her şey yolunda gittiyse 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ı uygulama %0, 99 olasılıklı bir spam algılandı uyarısı gönderir.

14. Tebrikler!

Bloglara spam göndermek için kullanılan verilerle eğitilmiş bir model kullanarak yorum spam'lerini filtreleyen çok basit bir uygulama geliştirdiniz.

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