Mengupdate aplikasi untuk menggunakan model Machine Learning pemfilteran spam

1. Sebelum memulai

Dalam codelab ini, Anda akan mengupdate aplikasi yang Anda bangun di codelab Mulai menggunakan klasifikasi teks seluler sebelumnya.

Prasyarat

  • Codelab ini dirancang untuk developer berpengalaman yang baru mengenal machine learning.
  • Codelab adalah bagian dari jalur berurutan. Jika Anda belum menyelesaikan Membangun aplikasi gaya pesan dasar atau Membangun model machine learning spam komentar, berhentilah dan lakukan sekarang.

Yang akan Anda [bangun atau pelajari]

  • Anda akan mempelajari cara mengintegrasikan model kustom ke dalam aplikasi, yang dibuat pada langkah sebelumnya.

Yang Anda butuhkan

2. Buka Aplikasi Android yang Sudah Ada

Anda bisa mendapatkan kode untuk ini dengan mengikuti Codelab 1, atau dengan meng-clone repo ini dan memuat aplikasi dari TextClassificationStep1.

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

Anda dapat menemukannya di jalur TextClassificationOnMobile->Android.

Kode selesai juga tersedia untuk Anda sebagai TextClassificationStep2.

Setelah terbuka, Anda siap untuk melanjutkan ke langkah 2.

3. Mengimpor Metadata dan File Model

Dalam codelab model machine learning membangun spam komentar, Anda telah membuat model .TFLITE.

Anda seharusnya sudah mendownload file model. Jika tidak memilikinya, Anda bisa mendapatkannya dari repo untuk codelab ini, dan modelnya tersedia di sini.

Tambahkan aset ke project Anda dengan membuat direktori aset.

  1. Dengan menggunakan navigator project, pastikan Android dipilih di bagian atas.
  2. Klik kanan folder app. Pilih Baru > Direktori.

d7c3e9f21035fc15.png

  1. Dalam dialog New Directory, pilih src/main/assets.

2137f956a1ba4ef0.pngS

Anda akan melihat folder aset baru yang kini tersedia di aplikasi.

ae858835e1a90445.png

  1. Klik kanan assets.
  2. Pada menu yang terbuka, Anda akan melihat (di Mac) Pengungkapan di Finder. Pilihlah. (Di Windows akan tertulis Show in Explorer, di Ubuntu akan tertulis Show in Files.)

e61aaa3b73c5ab68.png

Finder akan diluncurkan untuk menampilkan lokasi file (File Explorer di Windows, Files di Linux).

  1. Salin file labels.txt, model.tflite, dan vocab ke direktori ini.

14f382cc19552a56.pngS

  1. Kembali ke Android Studio, dan Anda akan melihatnya tersedia di folder aset.

150ed2a1d2f7a10d.pngS

4. Mengupdate build.gradle untuk menggunakan TensorFlow Lite

Untuk menggunakan TensorFlow Lite, dan library tugas TensorFlow Lite yang mendukungnya, Anda harus mengupdate file build.gradle.

Project Android sering kali memiliki lebih dari satu project, jadi pastikan untuk menemukan aplikasi level satu. Di project explorer dalam tampilan Android, temukan di bagian Gradle Scripts Anda. Aplikasi yang benar akan diberi label .app seperti yang ditunjukkan di sini:

6426051e614bc42f.pngS

Anda harus membuat dua perubahan pada file ini. Yang pertama ada di bagian Dependency di bagian bawah. Tambahkan teks implementation untuk library tugas TensorFlow Lite, seperti ini:

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

Nomor versi mungkin telah berubah sejak ini ditulis, jadi pastikan untuk memeriksa https://www.tensorflow.org/lite/inference_with_metadata/task_library/nl_classifier untuk mengetahui versi terbaru.

Library tugas juga memerlukan versi SDK minimum 21. Temukan setelan ini di android > default config, dan ubah menjadi 21:

c100b68450b8812f.png

Anda sekarang memiliki semua dependensi Anda, jadi saatnya untuk memulai coding.

5. Menambahkan Kelas Bantuan

Untuk memisahkan logika inferensi, tempat aplikasi Anda menggunakan model, dari antarmuka pengguna, buat class lain untuk menangani inferensi model. Sebut ini "helper" (pembantu) .

  1. Klik kanan nama paket tempat kode MainActivity Anda berada.
  2. Pilih Baru > Package (Paket).

d5911ded56b5df35.png

  1. Anda akan melihat dialog di tengah layar yang meminta Anda untuk memasukkan nama paket. Tambahkan di akhir nama paket saat ini. (Di sini, fitur ini disebut helpers.)

3b9f1f822f99b371.pngS

  1. Setelah selesai, klik kanan folder helpers di penjelajah project.
  2. Pilih Baru > Java Class, lalu beri nama TextClassificationClient. Anda akan mengedit file di langkah berikutnya.

Class bantuan TextClassificationClient akan terlihat seperti ini (meskipun nama paket Anda mungkin berbeda.)

package com.google.devrel.textclassificationstep1.helpers;

public class TextClassificationClient {
}
  1. Perbarui file dengan kode ini:
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;
    }

}

Class ini akan menyediakan wrapper ke penafsir TensorFlow Lite, yang memuat model dan memisahkan kompleksitas pengelolaan pertukaran data antara aplikasi dan model Anda.

Dalam metode load(), instance jenis NLClassifier baru akan dibuat dari jalur model. Jalur model hanyalah nama model, model.tflite. Jenis NLClassifier adalah bagian dari library tugas teks dan membantu Anda dengan mengonversi string menjadi token, menggunakan panjang urutan yang benar, meneruskannya ke model, dan mengurai hasilnya.

(Untuk mengetahui detail selengkapnya tentang hal ini, buka kembali model Machine learning spam komentar.)

Klasifikasi dilakukan dalam metode klasifikasi, tempat Anda meneruskan string ke metode tersebut, dan akan menampilkan List. Saat menggunakan model Machine Learning untuk mengklasifikasikan konten di mana Anda ingin menentukan apakah string merupakan spam atau bukan, biasanya semua jawaban akan ditampilkan, dengan probabilitas yang ditetapkan. Misalnya, jika Anda meneruskan pesan yang terlihat seperti spam, Anda akan mendapatkan daftar berisi 2 jawaban; satu dengan kemungkinan bahwa itu adalah spam, dan satu lagi dengan kemungkinan bahwa itu bukan spam. Spam/Bukan Spam adalah kategori, sehingga List yang ditampilkan akan berisi probabilitas ini. Anda akan menguraikannya nanti.

Setelah memiliki class bantuan, kembali ke MainActivity dan perbarui agar menggunakan class ini untuk mengklasifikasikan teks. Anda akan melihatnya di langkah berikutnya.

6. Mengklasifikasikan Teks

Di MainActivity, pertama-tama Anda perlu mengimpor helper yang baru saja dibuat.

  1. Di bagian atas MainActivity.kt, bersama dengan impor lainnya, tambahkan:
import com.google.devrel.textclassificationstep2.helpers.TextClassificationClient
import org.tensorflow.lite.support.label.Category
  1. Selanjutnya, Anda akan memuat helper. Di onCreate, tepat setelah baris setContentView, tambahkan baris berikut untuk membuat instance dan memuat class helper:
val client = TextClassificationClient(applicationContext)
client.load()

Saat ini, onClickListener tombol Anda seharusnya terlihat seperti ini:

btnSendText.setOnClickListener {
     var toSend:String = txtInput.text.toString()
     txtOutput.text = toSend
 }
  1. Perbarui agar terlihat seperti ini:
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()
}

Fungsi ini mengubah fungsi, dari hanya menghasilkan output input pengguna, menjadi mengklasifikasikan input pengguna terlebih dahulu.

  1. Dengan baris ini, Anda akan mengambil string yang dimasukkan pengguna dan meneruskannya ke model, untuk mendapatkan hasil yang ditampilkan:
var results:List<Category> = client.classify(toSend)

Hanya ada 2 kategori, False dan True

. (TensorFlow mengurutkannya menurut abjad, jadi False adalah item 0, dan True adalah item 1.)

  1. Untuk mendapatkan skor probabilitas nilai True, Anda dapat melihat hasil[1].score seperti ini:
    val score = results[1].score
  1. Memilih nilai minimum (dalam kasus ini 0,8), yang berarti Anda mengatakan bahwa jika skor untuk kategori Benar di atas nilai batas (0,8), maka pesan adalah spam. Jika tidak, pesan tersebut bukan spam dan pesan aman untuk dikirim:
    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. Lihat cara kerja model di sini. Pesan "Kunjungi blog saya untuk membeli barang!" ditandai sebagai berkemungkinan besar melakukan spam:

1fb0b5de9e566e.pngS

Dan sebaliknya, "Hai, tutorial yang menyenangkan, terima kasih!" memiliki kemungkinan yang sangat rendah untuk menjadi spam:

73f38bdb488b29b3.pngS

7. Update Aplikasi iOS Anda untuk menggunakan Model TensorFlow Lite

Anda bisa mendapatkan kode untuk ini dengan mengikuti Codelab 1, atau dengan meng-clone repo ini dan memuat aplikasi dari TextClassificationStep1. Anda dapat menemukannya di jalur TextClassificationOnMobile->iOS.

Kode selesai juga tersedia untuk Anda sebagai TextClassificationStep2.

Dalam codelab model machine learning membangun spam komentar, Anda membuat aplikasi sangat sederhana yang memungkinkan pengguna mengetik pesan ke dalam UITextView dan meneruskannya ke output tanpa pemfilteran apa pun.

Sekarang Anda akan mengupdate aplikasi tersebut untuk menggunakan model TensorFlow Lite guna mendeteksi spam komentar dalam teks sebelum mengirim. Cukup simulasikan pengiriman dalam aplikasi ini dengan merender teks dalam label output (tetapi aplikasi yang sebenarnya mungkin memiliki papan buletin, obrolan, atau sesuatu yang serupa).

Untuk memulai, Anda memerlukan aplikasi dari langkah 1, yang dapat di-clone dari repo.

Untuk menggabungkan TensorFlow Lite, Anda akan menggunakan CocoaPods. Jika belum menginstalnya, Anda dapat melakukannya dengan mengikuti petunjuk di https://cocoapods.org/.

  1. Setelah menginstal CocoaPods, buat file dengan nama Podfile di direktori yang sama dengan .xcproject untuk aplikasi TextClassification. Isi file ini akan terlihat seperti ini:
target 'TextClassificationStep2' do
  use_frameworks!

  # Pods for NLPClassifier
    pod 'TensorFlowLiteSwift'

end

Nama aplikasi Anda harus ada di baris pertama, bukan "TextClassificationStep2".

Dengan menggunakan Terminal, buka direktori tersebut lalu jalankan pod install. Jika berhasil, Anda akan memiliki direktori baru bernama Pods, dan file .xcworkspace baru yang dibuat untuk Anda. Anda akan menggunakannya pada masa mendatang, bukan .xcproject.

Jika gagal, pastikan Anda memiliki Podfile di direktori yang sama dengan .xcproject. Podfile di direktori yang salah, atau nama target yang salah, biasanya menjadi penyebab utamanya.

8. Menambahkan File Model dan Kosakata

Saat membuat model dengan TensorFlow Lite Model maker, Anda dapat menghasilkan output model (sebagai model.tflite) dan kosakata (sebagai vocab.txt).

  1. Tambahkan ke proyek Anda dengan menarik lalu melepasnya dari Finder ke jendela proyek Anda. Pastikan add to targets dicentang:

1ee9eaa00ee79859.pngS

Setelah selesai, Anda akan melihatnya di project Anda:

b63502b23911fd42.png

  1. Periksa kembali apakah project tersebut telah ditambahkan ke paket (agar dapat di-deploy ke perangkat) dengan memilih project Anda (di screenshot di atas, ikonnya adalah ikon biru TextClassificationStep2), dan lihat tab Build Phases:

20b7cb603d49b457.png

9. Memuat Kosakata

Saat melakukan klasifikasi NLP, model ini dilatih dengan kata yang dienkode menjadi vektor. Model mengenkode kata dengan kumpulan nama dan nilai tertentu yang dipelajari saat model dilatih. Perlu diketahui bahwa sebagian besar model akan memiliki kosakata yang berbeda, dan penting bagi Anda untuk menggunakan kosakata untuk model Anda yang dihasilkan pada saat pelatihan. Ini adalah file vocab.txt yang baru saja Anda tambahkan ke aplikasi.

Anda dapat membuka file di Xcode untuk melihat encoding. Kata-kata seperti "lagu" dikodekan menjadi 6 dan "{i>love<i}" ke 12. Urutannya sebenarnya adalah urutan frekuensi, jadi "I" adalah kata yang paling umum dalam {i>dataset<i}, diikuti dengan "{i>check<i}".

Saat pengguna mengetik kata, sebaiknya Anda mengenkode mereka dengan kosakata ini sebelum mengirimkannya ke model untuk diklasifikasikan.

Mari kita pelajari kode tersebut. Mulai dengan memuat kosakata.

  1. Tentukan variabel tingkat class untuk menyimpan kamus:
var words_dictionary = [String : Int]()
  1. Kemudian, buat func di class tersebut untuk memuat kosakata ke dalam kamus ini:
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. Anda dapat menjalankannya dengan memanggilnya dari dalam viewDidLoad:
override func viewDidLoad() {
    super.viewDidLoad()
    txtInput.delegate = self
    loadVocab()
}

10. Mengubah string menjadi urutan token

Pengguna akan mengetik kata sebagai kalimat yang akan menjadi string. Setiap kata dalam kalimat, jika ada dalam kamus, akan dienkode ke nilai kunci untuk kata tersebut sebagaimana didefinisikan dalam kosakata.

Model NLP biasanya menerima panjang urutan tetap. Ada pengecualian pada model yang di-build menggunakan ragged tensors, tetapi Anda akan mendapati bahwa masalah ini biasanya telah diperbaiki. Saat membuat model, Anda menentukan panjang ini. Pastikan Anda menggunakan durasi yang sama di aplikasi iOS.

Nilai default di Colab untuk TensorFlow Lite Model Maker yang Anda gunakan sebelumnya adalah 20. Jadi, siapkan juga di sini:

let SEQUENCE_LENGTH = 20

Tambahkan func ini yang akan mengambil string, mengubahnya menjadi huruf kecil, dan menghapus tanda baca:

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
}

Perhatikan bahwa urutannya adalah Int32. Ini sengaja dipilih karena ketika meneruskan nilai ke TensorFlow Lite, Anda akan berurusan dengan memori tingkat rendah, dan TensorFlow Lite memperlakukan bilangan bulat dalam urutan string sebagai bilangan bulat 32-bit. Hal ini akan mempermudah Anda saat meneruskan string ke model.

11. Lakukan Klasifikasi

Untuk mengklasifikasikan kalimat, kalimat tersebut harus dikonversi menjadi urutan token berdasarkan kata-kata dalam kalimat terlebih dahulu. Hal ini akan dilakukan pada langkah 9.

Sekarang Anda akan mengambil kalimat dan meneruskannya ke model, meminta model melakukan inferensi pada kalimat, dan mengurai hasilnya.

Tindakan ini akan menggunakan penafsir TensorFlow Lite, yang harus Anda impor:

import TensorFlowLite

Mulai dengan func yang mengambil urutan Anda, yang merupakan array jenis Int32:

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
  }

Tindakan ini akan memuat file model dari paket, dan memanggil penafsir dengannya.

Langkah berikutnya adalah menyalin memori dasar yang disimpan dalam urutan tersebut ke buffer bernama myData, sehingga dapat diteruskan ke tensor. Saat menerapkan pod TensorFlow Lite serta penafsir, Anda mendapatkan akses ke Tensor Type.

Mulai kode seperti ini (masih dalam klasifikasi func).

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

Jangan khawatir jika Anda mendapatkan error di copyingBufferOf. Hal ini akan diterapkan sebagai ekstensi nanti.

Sekarang saatnya mengalokasikan tensor pada penafsir, salin buffer data yang baru saja Anda buat ke tensor input, lalu panggil penafsir untuk melakukan inferensi:

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

Setelah pemanggilan selesai, Anda dapat melihat output penafsir untuk melihat hasilnya.

Data ini akan berupa nilai mentah (4 byte per neuron) yang harus Anda baca dan konversikan. Karena model khusus ini memiliki 2 neuron output, Anda harus membaca dalam 8 byte yang akan dikonversi menjadi Float32 untuk mengurai. Anda menangani memori tingkat rendah, sehingga 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) ?? []

Sekarang relatif mudah untuk mengurai data untuk menentukan kualitas spam. Model ini memiliki 2 output, yang pertama dengan probabilitas bahwa pesan bukan spam, yang kedua dengan probabilitas bahwa pesan tersebut bukan spam. Jadi, Anda dapat melihat results[1] untuk menemukan nilai spam:

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

Untuk memudahkan, berikut metode lengkapnya:

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. Menambahkan Ekstensi Swift

Kode di atas menggunakan ekstensi ke Jenis data untuk memungkinkan Anda menyalin bit mentah array Int32 ke dalam Data. Berikut adalah kode untuk ekstensi tersebut:

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

Ketika menangani memori tingkat rendah, Anda menggunakan "tidak aman" data, dan kode di atas mengharuskan Anda melakukan inisialisasi array data yang tidak aman. Ekstensi ini memungkinkan:

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. Menjalankan Aplikasi iOS

Jalankan dan uji aplikasi.

Jika semua berjalan lancar, Anda akan melihat aplikasi di perangkat Anda seperti ini:

74cbd28d9b1592ed.pngS

Tempat pesan "Beli buku saya untuk belajar trading online!" dikirim, aplikasi akan mengirimkan kembali peringatan yang terdeteksi spam dengan probabilitas 0,99%!

14. Selamat!

Sekarang, Anda telah membuat aplikasi sederhana yang memfilter teks untuk spam komentar menggunakan model yang dilatih dengan data yang digunakan untuk mengirim spam ke blog.

Langkah berikutnya dalam siklus proses developer umumnya adalah mengeksplorasi apa yang diperlukan untuk menyesuaikan model berdasarkan data yang ditemukan di komunitas Anda sendiri. Anda akan melihat cara melakukannya di aktivitas jalur berikutnya.