מדריך לסיווג טקסט ב-Android

המשימה 'מסווג טקסט של MediaPipe' מאפשרת לסווג טקסט לקבוצה של קטגוריות מוגדרות, כמו סנטימנט חיובי או שלילי. הקטגוריות קובעות את המודל שבו אתם משתמשים ואת אופן האימון של המודל. בהוראות האלה מוסבר איך להשתמש במסווג הטקסט באפליקציות ל-Android.

תוכלו לראות את המשימה הזו בהדגמה. למידע נוסף על היכולות, המודלים ואפשרויות התצורה של המשימה הזו, קראו את הסקירה הכללית.

קוד לדוגמה

הקוד לדוגמה של Text Classifier מספק הטמעה פשוטה של המשימה הזו לעיונכם. הקוד הזה יעזור לכם לבדוק את המשימה הזו ולהתחיל בבניית אפליקציה משלכם לסיווג טקסט. תוכלו לעיין בקוד לדוגמה של מסווג טקסט ב-GitHub.

הורדת הקוד

בהוראות הבאות מוסבר איך ליצור עותק מקומי של הקוד לדוגמה באמצעות כלי שורת הפקודה git.

כדי להוריד את הקוד לדוגמה:

  1. משכפלים את מאגר ה-Git באמצעות הפקודה הבאה:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. לחלופין, אפשר להגדיר את מכונת ה-Git לשימוש בקופה עם נפח נתונים נמוך, כדי שיהיו לכם רק את הקבצים של האפליקציה לדוגמה של Text Classifier:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/text_classification/android
    

במדריך ההגדרה ל-Android תוכלו למצוא הוראות להגדרה ולהפעלה של דוגמה עם Android Studio.

רכיבים עיקריים

הקבצים הבאים מכילים את הקוד החיוני לאפליקציה לדוגמה של סיווג טקסט:

  • TextClassifierHelper.kt – מפעיל את מסווג הטקסט ומטפל בבחירת המודל.
  • MainActivity.kt – יישום האפליקציה, כולל קריאה ל-TextClassifierHelper ול-ResultsAdapter.
  • ResultsAdapter.kt – טיפול ועיצוב של התוצאות.

הגדרה

בקטע הזה מתוארים שלבים עיקריים להגדרת סביבת הפיתוח ופרויקטים של קוד במיוחד לשימוש ב-Text Classifier. במדריך ההגדרה ל-Android תוכלו לקרוא מידע כללי על הגדרת סביבת הפיתוח לשימוש ב-MediaPipe Tasks, כולל הדרישות בנוגע לגרסת הפלטפורמה.

יחסי תלות

מסווג הטקסט משתמש בספריות com.google.mediapipe:tasks-text. מוסיפים את התלות הזאת לקובץ build.gradle של פרויקט פיתוח האפליקציה ל-Android. אפשר לייבא את יחסי התלות הנדרשים באמצעות הקוד הבא:

dependencies {
    implementation 'com.google.mediapipe:tasks-text:latest.release'
}

מודל

למשימה של MediaPipe Text Classifier נדרש מודל מאומן שתואם למשימה הזו. למידע נוסף על המודלים הזמינים למסווג טקסט, עיינו בסקירה הכללית על המשימות בקטע Models.

בוחרים ומורידים מודל, ולאחר מכן מאחסנים אותו בספריית הפרויקט assets:

<dev-project-root>/src/main/assets

משתמשים בשיטה BaseOptions.Builder.setModelAssetPath() כדי לציין את הנתיב שבו רוצים להשתמש. דוגמה לקוד זמינה בקטע הבא.

יצירת המשימה

השתמשו באחת מהפונקציות TextClassifier.createFrom...() של Text Classifier כדי להכין את המשימה להרצת מסקנות. אפשר להשתמש בפונקציה createFromFile() עם נתיב יחסי או מוחלט לקובץ המודל שעבר אימון. דוגמת הקוד הבאה ממחישה את השימוש בפונקציה TextClassifier.createFromOptions(). למידע נוסף על אפשרויות ההגדרה הזמינות, ראו אפשרויות תצורה.

הקוד הבא מדגים איך ליצור ולהגדיר את המשימה הזו.

// no directory path required if model file is in src/main/assets:
String currentModel = "text_classifier_model.tflite";

fun initClassifier() {
    val baseOptionsBuilder = BaseOptions.builder()
        .setModelAssetPath(currentModel)
    try {
        val baseOptions = baseOptionsBuilder.build()
        val optionsBuilder = TextClassifier.TextClassifierOptions.builder()
            .setBaseOptions(baseOptions)
        val options = optionsBuilder.build()
        textClassifier = TextClassifier.createFromOptions(context, options)
    } catch (e: IllegalStateException) { // exception handling
    }
}

כדי לראות דוגמה ליצירת משימה, אתם יכולים לראות את הקוד בדוגמה TextClassifierHelper class initClassifier().

אפשרויות הגדרה

המשימה כוללת את אפשרויות ההגדרה הבאות לאפליקציות ל-Android:

שם האפשרות תיאור טווח ערכים ערך ברירת מחדל
displayNamesLocale ההגדרה הזו מגדירה את השפה של התוויות שישמשו לשמות תצוגה שנמסרים במטא-נתונים של מודל המשימה, אם יש כאלה. ברירת המחדל היא en עבור אנגלית. אפשר להוסיף תוויות שהותאמו לשוק המקומי למטא-נתונים של מודל מותאם אישית באמצעות TensorFlow Lite Metadata Writer API קוד הלוקאל en
maxResults הפונקציה מגדירה את המספר המקסימלי האופציונלי של תוצאות מהסיווג הגבוה ביותר להחזרה. אם הערך קטן מ-0, יוחזרו כל התוצאות הזמינות. כל מספר חיובי -1
scoreThreshold השדה הזה מגדיר את סף הציון של החיזוי ששונה מהסף שצוין במטא-נתונים של המודל (אם יש כזה). תוצאות מתחת לערך הזה יידחו. כל מספר ממשי (float) לא הוגדרה
categoryAllowlist מגדיר את הרשימה האופציונלית של שמות הקטגוריות המותרות. אם השדה לא ריק, תוצאות סיווג ששם הקטגוריה שלהן לא נכלל בקבוצה הזו יסוננו. המערכת מתעלמת משמות כפולים או לא ידועים של קטגוריות. האפשרות הזו בלעדית ל-categoryDenylist ומשתמשת בשתי התוצאות כשגיאה. כל מחרוזת לא הוגדרה
categoryDenylist מגדיר את הרשימה האופציונלית של שמות קטגוריות אסורים. אם התוצאות לא ריקות, תוצאות הסיווג ששם הקטגוריה שלהן נכלל בקבוצה הזו יסוננו. המערכת מתעלמת משמות כפולים או לא ידועים של קטגוריות. האפשרות הזו בלעדית ל-categoryAllowlist, והשימוש בשתי האפשרויות האלה גורם לשגיאה. כל מחרוזת לא הוגדרה

הכנת הנתונים

מסווג טקסט פועל עם נתוני טקסט (String). המשימה מטפלת בעיבוד מראש של קלט הנתונים, כולל המרה לאסימונים ועיבוד מראש של tensor.

כל העיבודים מראש מטופלים בפונקציה classify(). אין צורך בעיבוד מראש נוסף של טקסט הקלט לפני כן.

String inputText = "The input text to be classified.";

מריצים את המשימה.

מסווג הטקסט משתמש בפונקציה TextClassifier.classify() כדי להריץ מסקנות. כדי למנוע את חסימת ה-thread של ממשק המשתמש ב-Android באפליקציה, צריך להשתמש בשרשור הפעלה נפרד.

הקוד הבא מדגים איך לבצע את העיבוד במודל המשימה באמצעות thread ביצוע נפרד.

    fun classify(text: String) {
        executor = ScheduledThreadPoolExecutor(1)

        executor.execute {
            val results = textClassifier.classify(text)
            listener.onResult(results)
        }
    }

כדי לראות דוגמה להרצת משימה, אתם יכולים לראות את הקוד בפונקציה TextClassifierHelper class classify().

טיפול בתוצאות והצגתן

הפלט של Text Classifier הוא TextClassifierResult, שמכיל את רשימת הקטגוריות האפשריות לטקסט הקלט. הקטגוריות מוגדרות על ידי המודל שבו משתמשים, כך שאם רוצים קטגוריות שונות, צריך לבחור מודל אחר או לאמן מחדש מודל קיים.

דוגמה לנתוני הפלט מהמשימה הזאת:

TextClassificationResult:
  Classification #0 (single classification head):
    ClassificationEntry #0:
      Category #0:
        category name: "positive"
        score: 0.8904
        index: 0
      Category #1:
        category name: "negative"
        score: 0.1096
        index: 1

התוצאה הזו התקבלה על ידי הרצת מסווג BERT על טקסט הקלט: "an imperfect but overall entertaining mystery".

תוכלו לראות דוגמה להצגת תוצאות במחלקה ResultsAdapter לדוגמה ובמחלקה הפנימית ViewHolder.