برای استفاده از مدل یادگیری ماشینی فیلتر کننده هرزنامه، برنامه خود را به روز کنید

1. قبل از شروع

در این لبه کد، برنامه‌ای را که در نسخه قبلی شروع کرده‌اید با کدهای دسته‌بندی نوشتار تلفن همراه به‌روزرسانی می‌کنید.

پیش نیازها

  • این کد لبه برای توسعه دهندگان باتجربه و تازه به یادگیری ماشین طراحی شده است.
  • آزمایشگاه کد بخشی از یک مسیر متوالی است. اگر قبلاً ساختن یک برنامه سبک پیام‌رسانی اولیه یا ایجاد مدل یادگیری ماشین هرزنامه نظرات را تکمیل نکرده‌اید، لطفاً این کار را متوقف کرده و همین الان انجام دهید.

آنچه می خواهید [بسازید یا یاد بگیرید]

  • شما یاد خواهید گرفت که چگونه مدل سفارشی خود را در برنامه خود که در مراحل قبلی ساخته شده است، ادغام کنید.

آنچه شما نیاز دارید

2. برنامه اندروید موجود را باز کنید

می‌توانید کد این کار را با دنبال کردن Codelab 1 یا با شبیه‌سازی این مخزن و بارگیری برنامه از TextClassificationStep1 دریافت کنید.

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

این را می توانید در مسیر TextClassificationOnMobile->Android پیدا کنید.

کد تمام شده نیز به عنوان TextClassificationStep2 برای شما در دسترس است.

پس از باز شدن، آماده رفتن به مرحله 2 هستید.

3. فایل مدل و فراداده را وارد کنید

در آزمایشگاه کد مدل یادگیری ماشین هرزنامه Build a comment، یک مدل TFLITE. ایجاد کردید.

شما باید فایل مدل را دانلود می کردید. اگر آن را ندارید، می توانید آن را از مخزن این کد لبه دریافت کنید و مدل در اینجا موجود است.

با ایجاد یک فهرست دارایی، آن را به پروژه خود اضافه کنید.

  1. با استفاده از ناوبر پروژه، مطمئن شوید که Android در بالا انتخاب شده است.
  2. روی پوشه برنامه کلیک راست کنید. New > Directory را انتخاب کنید.

d7c3e9f21035fc15.png

  1. در گفتگوی فهرست جدید ، src/main/assets را انتخاب کنید.

2137f956a1ba4ef0.png

خواهید دید که یک پوشه دارایی جدید اکنون در برنامه موجود است.

ae858835e1a90445.png

  1. دارایی های راست کلیک کنید.
  2. در منوی باز شده، (در مک) Reveal را در Finder خواهید دید. آن را انتخاب کنید. (در ویندوز نشان می دهد در اکسپلورر ، در اوبونتو نشان می دهد در فایل ها .)

e61aaa3b73c5ab68.png

Finder برای نشان دادن مکان فایل ها ( فایل اکسپلورر در ویندوز، فایل ها در لینوکس) راه اندازی می شود.

  1. فایل های labels.txt ، model.tflite و vocab را در این دایرکتوری کپی کنید.

14f382cc19552a56.png

  1. به Android Studio بازگردید و آنها را در پوشه دارایی های خود در دسترس خواهید دید.

150ed2a1d2f7a10d.png

4. برای استفاده از TensorFlow Lite، build.gradle خود را به روز کنید

برای استفاده از TensorFlow Lite و کتابخانه‌های وظیفه TensorFlow Lite که از آن پشتیبانی می‌کنند، باید فایل build.gradle خود را به‌روزرسانی کنید.

پروژه های اندروید اغلب بیش از یک دارند، بنابراین حتما سطح یک برنامه را پیدا کنید. در کاوشگر پروژه در نمای اندروید، آن را در بخش Gradle Scripts خود پیدا کنید. همانطور که در اینجا نشان داده شده است، مورد صحیح با .app برچسب گذاری می شود:

6426051e614bc42f.png

شما باید دو تغییر در این فایل ایجاد کنید. اولین مورد در بخش وابستگی ها در پایین است. یک implementation متن برای کتابخانه وظیفه TensorFlow Lite اضافه کنید، مانند این:

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

ممکن است شماره نسخه از زمانی که این نوشته شده است تغییر کرده باشد، بنابراین حتماً https://www.tensorflow.org/lite/inference_with_metadata/task_library/nl_classifier را بررسی کنید.

کتابخانه‌های کار همچنین به حداقل نسخه SDK 21 نیاز دارند. این تنظیم را در android > default config پیدا کنید و آن را به 21 تغییر دهید:

c100b68450b8812f.png

شما اکنون تمام وابستگی های خود را دارید، پس وقت آن است که کدنویسی را شروع کنید!

5. یک کلاس کمکی اضافه کنید

برای جدا کردن منطق استنتاج ، جایی که برنامه شما از مدل استفاده می‌کند، از رابط کاربری، کلاس دیگری برای استنتاج مدل ایجاد کنید. به این کلاس "کمک" می گوییم.

  1. روی نام بسته ای که کد MainActivity شما در آن قرار دارد کلیک راست کنید.
  2. جدید > بسته را انتخاب کنید.

d5911ded56b5df35.png

  1. یک گفتگو در مرکز صفحه مشاهده خواهید کرد که از شما می خواهد نام بسته را وارد کنید. آن را در انتهای نام بسته فعلی اضافه کنید. (در اینجا به آن کمک کننده می گویند.)

3b9f1f822f99b371.png

  1. پس از انجام این کار، روی پوشه helpers در پروژه اکسپلورر کلیک راست کنید.
  2. New > Java Class را انتخاب کنید و آن را TextClassificationClient بنامید. در مرحله بعد فایل را ویرایش خواهید کرد.

کلاس کمکی TextClassificationClient شما به این شکل خواهد بود (اگرچه نام بسته شما ممکن است متفاوت باشد.)

package com.google.devrel.textclassificationstep1.helpers;

public class TextClassificationClient {
}
  1. فایل را با این کد به روز کنید:
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;
    }

}

این کلاس یک پوشش برای مفسر TensorFlow Lite ارائه می‌کند، مدل را بارگیری می‌کند و پیچیدگی مدیریت تبادل داده بین برنامه شما و مدل را خلاصه می‌کند.

در متد load() یک نوع NLClassifier جدید را از مسیر مدل نمونه سازی می کند. مسیر مدل به سادگی نام مدل، model.tflite است. نوع NLClassifier بخشی از کتابخانه‌های وظایف متنی است و با تبدیل رشته خود به نشانه‌ها، استفاده از طول دنباله صحیح، ارسال آن به مدل و تجزیه نتایج به شما کمک می‌کند.

(برای جزئیات بیشتر در مورد این موارد، دوباره به ساخت مدل یادگیری ماشین هرزنامه نظرات مراجعه کنید.)

طبقه‌بندی در متد طبقه‌بندی انجام می‌شود، جایی که شما یک رشته را به آن ارسال می‌کنید و یک List برمی‌گرداند. هنگام استفاده از مدل‌های یادگیری ماشین برای طبقه‌بندی محتوایی که می‌خواهید تعیین کنید آیا رشته‌ای هرزنامه است یا نه، معمولاً همه پاسخ‌ها با احتمالات اختصاص داده شده برگردانده می‌شوند. به عنوان مثال، اگر پیامی مانند هرزنامه برای آن ارسال کنید، لیستی از 2 پاسخ دریافت خواهید کرد. یکی با احتمال اینکه اسپم است و یکی با احتمال اینکه اینطور نیست. هرزنامه/غیر هرزنامه دسته‌هایی هستند، بنابراین List بازگشتی حاوی این احتمالات است. بعداً آن را تجزیه خواهید کرد.

اکنون که کلاس کمکی دارید، به MainActivity خود برگردید و آن را به روز کنید تا از آن برای طبقه بندی متن خود استفاده کنید. در مرحله بعد خواهید دید!

6. متن را طبقه بندی کنید

در MainActivity خود ابتدا می خواهید کمک هایی را که ایجاد کرده اید وارد کنید!

  1. در بالای MainActivity.kt ، به همراه واردات دیگر، اضافه کنید:
import com.google.devrel.textclassificationstep2.helpers.TextClassificationClient
import org.tensorflow.lite.support.label.Category
  1. در مرحله بعد، می خواهید کمک کننده ها را بارگیری کنید. در onCreate ، بلافاصله بعد از خط setContentView ، این خطوط را برای نمونه سازی و بارگذاری کلاس کمکی اضافه کنید:
val client = TextClassificationClient(applicationContext)
client.load()

در حال حاضر، onClickListener دکمه شما باید به شکل زیر باشد:

btnSendText.setOnClickListener {
     var toSend:String = txtInput.text.toString()
     txtOutput.text = toSend
 }
  1. آن را به شکل زیر به روز کنید:
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()
}

این کارکرد را از خروجی دادن ورودی کاربر به طبقه‌بندی اول تغییر می‌دهد.

  1. با استفاده از این خط، رشته ای را که کاربر وارد کرده است می گیرید و به مدل ارسال می کنید و نتایج را به دست می آورید:
var results:List<Category> = client.classify(toSend)

فقط 2 دسته وجود دارد، False و True

. (TensorFlow آنها را بر اساس حروف الفبا مرتب می کند، بنابراین False مورد 0 و True مورد 1 خواهد بود.)

  1. برای بدست آوردن امتیاز احتمال True بودن مقدار، می توانید به نتایج[1].score به این شکل نگاه کنید:
    val score = results[1].score
  1. یک مقدار آستانه (در این مورد 0.8) انتخاب کردید، که در آن می گویید اگر امتیاز دسته True بالاتر از مقدار آستانه (0.8) باشد، پیام هرزنامه است. در غیر این صورت، هرزنامه نیست و ارسال پیام امن است:
    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. مدل در عمل را اینجا ببینید. پیام "برای خرید کالا از وبلاگ من دیدن کنید!" به عنوان یک احتمال بالا برای هرزنامه پرچم گذاری شد:

1fb0b5de9e566e.png

و برعکس، "هی، آموزش سرگرم کننده، متشکرم!" احتمال بسیار کم اسپم بودن وجود دارد:

73f38bdb488b29b3.png

7. برنامه iOS خود را برای استفاده از مدل TensorFlow Lite به روز کنید

می‌توانید کد این کار را با دنبال کردن Codelab 1 یا با شبیه‌سازی این مخزن و بارگیری برنامه از TextClassificationStep1 دریافت کنید. این را می توانید در مسیر TextClassificationOnMobile->iOS پیدا کنید.

کد تمام شده نیز به عنوان TextClassificationStep2 برای شما در دسترس است.

در آزمایشگاه کد مدل یادگیری ماشین هرزنامه Build a comment، شما یک برنامه بسیار ساده ایجاد کردید که به کاربر اجازه می‌دهد پیامی را در UITextView تایپ کند و آن را بدون فیلتر کردن به خروجی ارسال کند.

اکنون آن برنامه را به‌روزرسانی می‌کنید تا از یک مدل TensorFlow Lite برای تشخیص هرزنامه نظرات در متن قبل از ارسال استفاده کند. فقط ارسال را در این برنامه با رندر کردن متن در یک برچسب خروجی شبیه سازی کنید (اما یک برنامه واقعی ممکن است یک تابلوی اعلانات، یک چت یا چیزی مشابه داشته باشد).

برای شروع، به برنامه مرحله 1 نیاز دارید که می توانید آن را از مخزن کلون کنید.

برای ترکیب TensorFlow Lite، از CocoaPods استفاده خواهید کرد. اگر اینها را قبلاً نصب نکرده‌اید، می‌توانید با دستورالعمل‌های موجود در https://cocoapods.org/ این کار را انجام دهید.

  1. هنگامی که CocoaPods را نصب کردید، یک فایل با نام Podfile در همان دایرکتوری .xcproject . برای برنامه TextClassification ایجاد کنید. محتویات این فایل باید به شکل زیر باشد:
target 'TextClassificationStep2' do
  use_frameworks!

  # Pods for NLPClassifier
    pod 'TensorFlowLiteSwift'

end

نام برنامه شما باید به جای «TextClassificationStep2» در خط اول باشد.

با استفاده از ترمینال، به آن دایرکتوری بروید و pod install اجرا کنید. اگر موفقیت آمیز باشد، یک دایرکتوری جدید به نام Pods و یک فایل .xcworkspace جدید برای شما ایجاد می شود. در آینده به جای .xcproject از آن استفاده خواهید کرد.

اگر شکست خورد، لطفاً مطمئن شوید که Podfile را در همان فهرستی که .xcproject . پادفایل در دایرکتوری اشتباه، یا نام هدف اشتباه، معمولاً مقصر اصلی هستند!

8. فایل های Model و Vocab را اضافه کنید

وقتی مدل را با TensorFlow Lite Model maker ایجاد کردید، می‌توانید مدل (به عنوان model.tflite ) و vocab (به عنوان vocab.txt ) را خروجی بگیرید.

  1. با کشیدن و رها کردن آنها از Finder در پنجره پروژه خود، آنها را به پروژه خود اضافه کنید. مطمئن شوید که افزودن به اهداف علامت زده شده است:

1ee9eaa00ee79859.png

وقتی کارتان تمام شد، باید آنها را در پروژه خود ببینید:

b63502b23911fd42.png

  1. با انتخاب پروژه خود (در تصویر بالا، نماد آبی TextClassificationStep2 است) و نگاهی به برگه Build Phases ، دوبار بررسی کنید که آنها به بسته اضافه شده باشند (به طوری که در یک دستگاه مستقر شوند):

20b7cb603d49b457.png

9. Vocab را بارگذاری کنید

هنگام انجام طبقه بندی NLP، مدل با کلمات رمزگذاری شده در بردارها آموزش داده می شود. این مدل کلمات را با مجموعه ای خاص از نام ها و مقادیری که با آموزش مدل یاد می گیرند، رمزگذاری می کند. لطفاً توجه داشته باشید که بیشتر مدل‌ها واژگان متفاوتی دارند و برای شما مهم است که از واژگانی برای مدل خود استفاده کنید که در زمان آموزش ایجاد شده است. این فایل vocab.txt است که به تازگی به برنامه خود اضافه کرده اید.

می توانید فایل را در Xcode باز کنید تا رمزگذاری ها را ببینید. کلماتی مانند "آهنگ" به 6 و "عشق" به 12 رمزگذاری می شوند. ترتیب در واقع ترتیب فرکانس است، بنابراین "من" رایج ترین کلمه در مجموعه داده بود و پس از آن "بررسی".

هنگامی که کاربر شما در کلمات تایپ می کند، قبل از ارسال آنها به مدلی که قرار است طبقه بندی شود، آنها را با این واژگان رمزگذاری کنید.

بیایید آن کد را بررسی کنیم. با بارگذاری واژگان شروع کنید.

  1. یک متغیر سطح کلاس برای ذخیره فرهنگ لغت تعریف کنید:
var words_dictionary = [String : Int]()
  1. سپس یک func در کلاس ایجاد کنید تا vocab در این فرهنگ لغت بارگیری شود:
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. می توانید با فراخوانی آن از داخل viewDidLoad این را اجرا کنید:
override func viewDidLoad() {
    super.viewDidLoad()
    txtInput.delegate = self
    loadVocab()
}

10. یک رشته را به دنباله ای از نشانه ها تبدیل کنید

کاربران شما کلمات را به عنوان یک جمله تایپ می کنند که تبدیل به یک رشته می شود. هر کلمه در جمله، اگر در فرهنگ لغت وجود داشته باشد، در مقدار کلیدی کلمه همانطور که در لغت تعریف شده است، رمزگذاری می شود.

یک مدل NLP معمولاً طول توالی ثابتی را می پذیرد. در مورد مدل‌هایی که با استفاده از ragged tensors ساخته شده‌اند استثناهایی وجود دارد، اما در بیشتر موارد خواهید دید که این مشکل برطرف شده است. وقتی مدل خود را ایجاد کردید، این طول را مشخص کردید. مطمئن شوید که از همان طول در برنامه iOS خود استفاده می کنید.

پیش‌فرض Colab for TensorFlow Lite Model Maker که قبلاً استفاده کردید 20 بود، بنابراین آن را در اینجا نیز تنظیم کنید:

let SEQUENCE_LENGTH = 20

این func اضافه کنید که رشته را می گیرد، آن را به حروف کوچک تبدیل می کند و هر علامت نگارشی را حذف می کند:

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
}

توجه داشته باشید که دنباله Int32 خواهد بود. این به عمد انتخاب شده است زیرا وقتی نوبت به ارسال مقادیر به TensorFlow Lite می‌رسد، با حافظه سطح پایین سروکار دارید و TensorFlow Lite اعداد صحیح را در یک رشته رشته‌ای به عنوان اعداد صحیح 32 بیتی در نظر می‌گیرد. این کار زندگی شما را (کمی) در انتقال رشته به مدل آسان تر می کند.

11. طبقه بندی را انجام دهید

برای طبقه بندی یک جمله، ابتدا باید آن را به دنباله ای از نشانه ها بر اساس کلمات موجود در جمله تبدیل کرد. این کار در مرحله 9 انجام خواهد شد.

اکنون جمله را می گیرید و آن را به مدل منتقل می کنید، مدل را در مورد جمله استنتاج می کنید و نتایج را تجزیه می کنید.

این از مفسر TensorFlow Lite استفاده می کند که باید آن را وارد کنید:

import TensorFlowLite

با func شروع کنید که دنباله شما را می گیرد، که آرایه ای از انواع 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
  }

این فایل مدل را از بسته بارگیری می کند و یک مفسر را با آن فراخوانی می کند.

گام بعدی این است که حافظه زیرین ذخیره شده در دنباله را در بافری به نام myData, کپی کنید تا بتوان آن را به یک تانسور ارسال کرد. هنگام پیاده سازی TensorFlow Lite pod و همچنین مفسر، به یک Tensor Type دسترسی پیدا کردید.

کد را به این شکل شروع کنید (هنوز در func طبقه بندی است.):

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

اگر در copyingBufferOf با خطا مواجه شدید نگران نباشید. این به عنوان یک افزونه بعداً اجرا خواهد شد.

اکنون زمان تخصیص تانسورها در مفسر فرا رسیده است، بافر داده ای را که به تازگی ایجاد کرده اید در تانسور ورودی کپی کنید و سپس مفسر را برای انجام استنتاج فراخوانی کنید:

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

هنگامی که فراخوانی کامل شد، می توانید برای دیدن نتایج به خروجی مفسر نگاه کنید.

این مقادیر خام (4 بایت در هر نورون) خواهد بود که باید آنها را بخوانید و تبدیل کنید. از آنجایی که این مدل خاص دارای 2 نورون خروجی است، باید 8 بایت را بخوانید که برای تجزیه به Float32 تبدیل می شود. شما با حافظه سطح پایین سر و کار دارید، بنابراین 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) ?? []

اکنون تجزیه داده ها برای تعیین کیفیت هرزنامه نسبتا آسان است. مدل دارای 2 خروجی است، اولی با احتمال اسپم نبودن پیام، دومی با احتمال اینکه پیام است. بنابراین می توانید برای یافتن مقدار هرزنامه به 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

برای راحتی، در اینجا روش کامل است:

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 را اضافه کنید

کد بالا از یک پسوند برای نوع داده استفاده می‌کرد تا به شما امکان کپی بیت‌های خام یک آرایه Int32 را در یک Data بدهد. در اینجا کد آن پسوند آمده است:

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

هنگامی که با حافظه سطح پایین سروکار دارید، از داده های "ناامن" استفاده می کنید و کد بالا به شما نیاز دارد تا آرایه ای از داده های ناامن را مقداردهی اولیه کنید. این پسوند این امکان را فراهم می کند:

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 را اجرا کنید

برنامه را اجرا و تست کنید.

اگر همه چیز خوب پیش رفت، باید برنامه را در دستگاه خود به این صورت مشاهده کنید:

74cbd28d9b1592ed.png

جایی که پیام «کتابم را بخر تا تجارت آنلاین یاد بگیری!» ارسال شد، برنامه یک هشدار تشخیص هرزنامه را با احتمال .99% پس می فرستد!

14. تبریک می گویم!

شما اکنون یک برنامه بسیار ساده ایجاد کرده اید که متن را برای هرزنامه نظرات با استفاده از مدلی که بر روی داده های مورد استفاده برای ارسال هرزنامه وبلاگ ها آموزش داده شده است، فیلتر می کند.

گام بعدی در چرخه عمر توسعه‌دهنده معمولی این است که سپس بررسی کنید که برای سفارشی کردن مدل بر اساس داده‌های موجود در جامعه خود چه چیزی لازم است. نحوه انجام این کار را در فعالیت مسیر بعدی خواهید دید.