למידת מכונה - סיווג טקסטים באמצעות sklearn

מחבר:
בתאריך:

במדריך זה נלמד כיצד לסווג טקסטים לקבוצות באמצעות sklearn. אני משתמש ב-sklearn מכיוון שעבור הטקסטים שעליהם ערכתי את הניסוי הגעתי לתוצאות טובות בהרבה כשהשתמשתי ב-sklearn מאשר ב-Keras.

סיווג טקטסים באמצעות sklearn למידת מכונה

לחצו על הקישור להורדת קובץ פייתון המכיל את הקוד במדריך: קוד המדריך להורדה.

 

הכנת סביבת העבודה

נייבא את הספריות שישמשו אותנו במדריך.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

 

ייבוא מסד הנתונים

מסד הנתונים שבו נשתמש הוא 20 newsgroups הכולל טקסטים מ-20 קבוצות דיון באינטרנט. הטקסטים מחולקים לקבוצות. את הנתונים נייבא מ-sklearn.

# https://scikit-learn.org/0.19/datasets/twenty_newsgroups.html
from sklearn.datasets import fetch_20newsgroups

לצורך המדריך בחרתי ב-4 קבוצות דיון מתוך ה-20:

  • rec.autos
  • sci.med
  • comp.os.ms-windows.misc
  • comp.windows.x
categories = ['rec.autos','sci.med','comp.os.ms-windows.misc','comp.windows.x']
 
newsgroups_train = fetch_20newsgroups(subset='train', shuffle=True, categories=categories)
newsgroups_test = fetch_20newsgroups(subset='test', shuffle=True, categories=categories)

3 הקבוצות הראשונות נבדלות זו מזו אבל השלישית והרביעית דומות כי שתיהם עוסקות במערכת הפעלה "חלונות".

 

2. סקירת מסד הנתונים

נבדוק אילו קבוצות ייבאנו:

list(newsgroups_train.target_names)
['comp.os.ms-windows.misc', 'comp.windows.x', 'rec.autos', 'sci.med']

כמה דוגמאות יש לנו בקבוצת המבחן וכמה בקבוצת הביקורת?

print(newsgroups_train.filenames.shape)
print(newsgroups_test.filenames.shape)
(2372,)
(1581,)

איך נראות התגיות?

newsgroups_train.target[:10]
array([2, 1, 2, 2, 1, 3, 2, 1, 0, 0])

כל קטגוריה (קבוצת דיון) מיוצגת על ידי מספר מ-0 עד 3.

מעניין אם גם קבוצת הביקורת מתויגת?

newsgroups_test.target[:10]
array([0, 0, 1, 1, 1, 0, 0, 2, 2, 0])

כן, גם קבוצת הביקורת מתויגת.

מעניין איך נראית דוגמה בודדת.

print(newsgroups_train.data[0])
From: etjet@levels.unisa.edu.au
Subject: Aussie needs info on car shows
Reply-To: johnt@spri.levels.unisa.edu.au
Organization: University of South Australia
Lines: 54



Hi from Australia,

I am a car enthusiast in Australia.
 
I am particularly interested in American Muscle cars of the 
1960s and 1970s. ALL MAKES: AMC, Ford, Chrysler/Mopar, GM.

I will be in the USA for 6 weeks from May 2nd to -June 14 1993.

I was wondering if anyone could send me any information of 
car shows, swap meets, drag meets, model car shows etc. during this period.
Can anybody tell me when the Pomona Swap meet is on this year?

Also, any places to visit (eg. car museums, private collections, 
your collection? etc. Any bit of information is appreciated!

I am also interested in finding some model cars (scale Models). 
I am intersted in 1968-1974 AMC cars. Of particular interest is:
1968-1970 AMX
1968-1974 Javelin
and others

If you have any kits, plastics, diecast etc and are interested in selling them,
tell me, I will be interested.

I can also send/bring you models of Australian High performance cars if 
you are interested.


Please reply by email to: johnt@spri.levels.unisa.edu.au


Thanks,

John Tsimbinos 

הקוד הבא הופך את המידע שהורדנו ל-dataframe של pandas בגלל שזו צורת אחסון מידע נוחה יותר לעבודה.

נהפוך את דוגמאות האימון ל-dataframe:

df_train = pd.DataFrame({'text': newsgroups_train.data, 'cat': newsgroups_train.target})

כנ"ל את דוגמאות המבחן:

df_test = pd.DataFrame({'text': newsgroups_test.data, 'cat': newsgroups_test.target})

נציץ ב-dataframe:

df_train.head()
text cat
0 From: etjet@levels.unisa.edu.au\nSubject: Auss... 2
1 From: yuri@physics.heriot-watt.ac.UK (Yuri Rzh... 1
2 From: rmt6r@faraday.clas.Virginia.EDU (Roy Mat... 2
3 From: kvk@questor.sw.stratus.com (Ken Koellner... 2
4 From: ben@dbsm.oz.au (Benjamin Stephen Kelley)... 1
5 From: roos@Operoni.Helsinki.FI (Christophe Roo... 3
6 From: mobasser@vu-vlsi.ee.vill.edu (Bijan Moba... 2
7 From: "Derrick J. Brashear" <db74+@andrew.cmu.... 1
8 Subject: Re: Win31 & doublespace\nFrom: edowdy... 0
9 From: santos@mickey.ai.kyutech.ac.jp (Rafael &... 0

ננקה דוגמאות חסרות:

# remove rows with na values
df_train.dropna(inplace=True)
df_test.dropna(inplace=True)

 

טוקנים, טקסטים וקורפוס

כאן המקום להגדיר שלושה מושגים שהם חיוניים להבנת למידת מכונה מסוג NLP (לימוד שפה טבעית). 

  1. טוקן - היחידה המשמעותית הקטנה ביותר של NLP. טוקנים הם בד"כ מילים, אבל יכולים להיות גם אותיות בודדות. מתחלק ל-ngrams (מילים בודדות) ו-bigrams (כל טוקן מורכב משתי מילים סמוכות).
  2. טקסט - אוסף של טוקנים.
  3. קורפוס - אוסף של טקסטים.

 

הכנת המידע באמצעות טוקניזציה ווקטוריזציה

טוקניזציה מפרקת את כל המידע בקורפוס למילים בודדות ללא סימני פיסוק, כל האותיות קטנות. התוצאה של הטוקניזציה היא אוצר מילים (vocabulary). וקטוריזציה הופכת את המילים למספרים, ואת הטקסטים למערכים של מספרים. וקטוריזציה היא חיונית כי המודלים של למידת מכונה יודעים לעבוד רק עם וקטורים מספריים.

 

יש 3 אפשרויות עיקריות לוקטוריזציה של טקסטים:

  1. Count embedding - כל טוקן מקבל ערך מספרי על פי מספר הפעמים שהוא מופיע בטקטסט. לדוגמה, אם המילה "car" מופיעה בטקטסט 3 פעמים היא תקבל את הערך 3, ואם לא מופיעה תקבל 0.
  2. One hot encoding - כל טוקן מקבל ערך מספרי 1 או 0. 1 אם המילה נמצאת בטקסט, ו-0 במידה והמילה לא קיימת.
  3. TfIdf - הטוקנים מקבלים ערך נמוך עבור מילים נפוצות שמופיעות בהרבה טקסטים עקב תרומתם המועטה לאבחנה בין קטגוריות. קחו לדוגמה את המילה "את" בעברית היא נפוצה בכל הטקסטים ולכן היא לא טובה בתור טוקן שמבחין בין הקטגוריות אז כדאי שהתרומה שלה תהיה אפסית.

את משימות הטוקניזציה והוקטוריזציה יבצע בשבילנו האובייקט TfidfVectorizer של sklearn.

# https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html
from sklearn.feature_extraction.text import TfidfVectorizer
 
vectorizer = TfidfVectorizer()

נאמן את האובייקט vectorizer על הטקסטים של קבוצת האימון באמצעות המתודה fit:

# Fit the vectors
vectorizer.fit(df_train.text)
TfidfVectorizer(analyzer='word', binary=False, decode_error='strict',
                dtype=, encoding='utf-8',
                input='content', lowercase=True, max_df=1.0, max_features=None,
                min_df=1, ngram_range=(1, 1), norm='l2', preprocessor=None,
                smooth_idf=True, stop_words=None, strip_accents=None,
                sublinear_tf=False, token_pattern='(?u)\\b\\w\\w+\\b',
                tokenizer=None, use_idf=True, vocabulary=None)

האובייקט יצר טוקן מספרי עבור כל אחת מהמילים באוצר המילים.

# explore the vocabulary and the vector object
dict = vectorizer.vocabulary_
print(dict)
{'from': 28062, 'etjet': 25943, 'levels': 37137, 'unisa': 59220, 'edu': 25002, 'au': 15835,...}

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

נמצא את הטוקן שמזהה את אחת המילים באוצר המילים:

# get the token that represents a word
print(dict['software'])
54349

את המילה "software" מייצג טוקן שמספרו 54349.

יש בד"כ שני שלבים לעבודה עם אובייקטים של sklearn :

  1. אימון באמצעות fit על דוגמאות האימון
  2. התאמה באמצעות transform

נשתמש במודל המאומן כדי להפוך את הטקסטים לוקטורים.

vector = vectorizer.transform(df_train.text)

מעניין איך נראים הוקטורים שיצרנו מהטקסטים.

print(vector)
2372x66291 sparse matrix of type 'class 'numpy.float64'
	with 378607 stored elements in Compressed Sparse Row format

מטריקס של 2,372 וקטורים המיוצגים על ידי 66,291 טוקנים. כל אחד מהווקטורים מייצג את אחד הטקסטים.

print(vector.toarray())
[[0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 ...
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]]

זה מה שמכונה sparse vector - כל אחד מהטקסטים כולל רק חלק קטן מ-66,000 המילים במילון, ולכן רק חלק קטן מהפריטים בכל מערך המייצג טקסט מקבלים ערך מספרי. כל היתר מקבלים 0.

כדי לקבל תחושה על איך זה עובד בואו נקודד סט נתונים קטן הכולל 4 טקסטים קצרים.

# vectorize a small dataset to see how it is encoded
my_corpus = ['Ferrari windows are made of shielded glass', 
             'Windows is the most popular OS', 
             'I prefer glass tubes to plastic',
             'Get thee to a nunnery']
my_vectors = vectorizer.transform(my_corpus)

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

# see the sparse matrix that the vectorizer generated
print(my_vectors)
(0, 62219)	0.23766555944806722
  (0, 44921)	0.11131141519510553
  (0, 39223)	0.3563798241076208
  (0, 29335)	0.5744239632158175
  (0, 27035)	0.6683365537548597
  (0, 15416)	0.1657758518814847
  (1, 62219)	0.31080749467790547
  (1, 57039)	0.1349211253420249
  (1, 47577)	0.6605584584484411
  (1, 45529)	0.5377441261912266
  (1, 41737)	0.3670381919737468
  (1, 33674)	0.15802447449740742
  (2, 58116)	0.5754042324654695
  (2, 57498)	0.08826410734339618
  (2, 47845)	0.41681449933315023
  (2, 47274)	0.5050725937979209
  (2, 29335)	0.4819613726800033
  (3, 57498)	0.43858398912530766
  (3, 29051)	0.8986902049554851

הטוקנים שמקורם בטקסט הראשון נמצאים בדוגמה שהאינדקס שלה 0. נסתכל על התוצאה עבור הדוגמה הראשונה בלבד:

print(my_vectors[0])
(0, 62219)	0.23766555944806722
(0, 44921)	0.11131141519510553
(0, 39223)	0.3563798241076208
(0, 29335)	0.5744239632158175
(0, 27035)	0.6683365537548597
(0, 15416)	0.1657758518814847

כל אחד מהטוקנים מייצג מילה. בגלל שזה לא פרקטי להדפיס מערך בן למעלה מ- 66,000 פריטים, מה שאנחנו רואים הם רק הפריטים שאינם אפס בתוך כל אחד מהמערכים. לדוגמה, הטוקן הראשון נמצא במקום 62,219 וערכו 0.23766555944806722

אחרי שראינו איך לקודד טקסטים לוקטורים נראה איך ללכת הפוך כדי לשחזר את הטקסטים מהמערכים.

 

שחזור טקסטים מהווקטורים

הפונקציה הבאה משחזרת את הטקסטים מרשימת הטוקנים שהיא מקבלת. 

  • המשתנה dict הוא אוצר המילים.
  • המשתנה tokens הוא מערך הטוקנים להמרה.
def tokens_to_text(dict={}, tokens=[]):
  words = []
 
  for token in tokens:
    for key, val in dict.items():
      if val == token:
        words.append(key)
 
  return ' '.join(words)

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

# But the function is not enough because we also
# need to convert the sparse matrix to coo
Mc = my_vectors.tocoo()
 
print(Mc.row)
print(Mc.col)
[0 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 3 3]
[62219 44921 39223 29335 27035 15416 62219 57039 47577 45529 41737 33674
 58116 57498 47845 47274 29335 57498 29051]

נשחזר את הטקסטים הקצרים שלנו:

vect_text0 = [k for k,v in zip(Mc.col, Mc.row) if v == 0]
print(vect_text0)
print(tokens_to_text(dict, vect_text0))
[62219, 44921, 39223, 29335, 27035, 15416]
windows of made glass ferrari are
vect_text1 = [k for k,v in zip(Mc.col, Mc.row) if v == 1]
print(vect_text1)
print(tokens_to_text(dict, vect_text1))
[62219, 57039, 47577, 45529, 41737, 33674]
windows the popular os most is
vect_text2 = [k for k,v in zip(Mc.col, Mc.row) if v == 2]
print(vect_text2)
print(tokens_to_text(dict, vect_text2))
[58116, 57498, 47845, 47274, 29335]
tubes to prefer plastic glass

אפשר ללמוד מהמרת הטוקנים לטקסטים את הדברים הבאים:

  • בתהליך וקטוריזציה באמצעות tfIdf אבד סדר המילים.
  • לא כל המילים קיימות באוצר המילים. לדוגמה, אני לא מצליח לשחזר את המילה "I" (אני).
  • האלגוריתם לא מתייחס למשמעות הסמנטית של המילים מפני שהמילה windows בהקשר של מכוניות ומערכת הפעלה מקבלים את אותו הטוקן (62219).

מה בנוגע לטקסט שרובו לא נמצא באוצר המילים? את הטקסט הבא לקחתי משייקספיר כי הוא מכיל מילים ארכאיות שכבר אינם בשימוש.

# e.g. 'Get thee to a nunnery' (Shakespeare)
vect_text3 = [k for k,v in zip(Mc.col, Mc.row) if v == 3]
print(vect_text3)
print(tokens_to_text(dict, vect_text3))
[57498, 29051]
to get

נשארנו עם 2 מילים נפוצות שלא משאירות דבר מהמשמעות המקורית כי המילים בהם השתמש שייקספיר לא קיימות באוצר המילים. זה לקח חשוב כי אם נרצה לעבוד על טקסטים בתחום מסוים נצטרך לאמן את המודל שלנו על קורפוס מתאים.

 

אימון המודל

נאמן את המודל על קבוצת דוגמאות האימון (df_train). המודל הוא MultinomialNB שמבוסס על התיאורמה של Bayes בתוספת הנחה שהמשתנים הם עצמאים.

הגעתי למודל ע"פ תרשים הזרימה הבא Choosing the right estimator שמגיע מהתיעוד של sklearn.

from sklearn.naive_bayes import MultinomialNB
 
# Build the classifier
clf = MultinomialNB()
 
# Train the classifier on the train corpus
clf.fit(vector, df_train.cat)
MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)

 

הערכת המודל על קבוצת האימון

הדרך הנכונה להעריך את ביצועי המודל שלנו היא באמצעות בחינת מידת הדיוק בסיווג של דוגמאות שהוא לא נחשף אליהם - דוגמאות המבחן (df_test). את זה נעשה בסעיף הבא.

בסעיף הנוכחי נבדוק את דיוק המודל בסיווג דוגמאות האימון (df_train) כדי לברר שאין בעיות מהותיות. לדוגמה, בבדיקה זו אנו עשויים לגלות שהמודל נוטה לסווג באופן שגוי את אחת הקטגוריות. זה מידע חשוב שבו אנחנו יכולים להשתמש כדי לשפר את המודל. לדוגמה, על ידי שינוי המודל או על ידי תוספת דוגמאות.

הקוד הבא מורה למודל לחזות את הקטגוריות של קבוצת האימון.

# Predict the train vectors
pred_train = clf.predict(vector)
print(pred_train)
[2 1 2 ... 0 0 2]

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

# Evaluate the model
from sklearn.metrics import accuracy_score, f1_score
 
acc_train = accuracy_score(df_train.cat, pred_train)
f1_train = f1_score(df_train.cat, pred_train, average='macro')
 
print('Classification accuracy train: {:.2f}'.format(acc_train))
print('Classification F1 train: {:.2f}'.format(f1_train))

המדד הפשוט ביותר להערכת ביצועי המודל המסווג (classifier) הוא דיוק (accuracy), שהוא היחס בין הסיווגים הנכונים לבין סך כל הסיווגים. במקרה שלנו, מידת דיוק של 99% מעידה על סיווג קרוב למושלם.

מדד F1 לוקח בחשבון את השגיאות משני הסוגים (recall ו-precision) וערך קרוב ל-1 מעיד גם הוא על שיעור שגיאה נמוך מאוד.

מעניין האם ישנם קטגוריות שתרמו לשגיאה יותר מאחרות.

הפונקציה הבאה תייצר confusion_matrix ותעזור לנו בזיהוי מקור השגיאות:

# https://gist.github.com/hitvoice/36cf44689065ca9b927431546381a3f7
from sklearn.metrics import confusion_matrix
 
import seaborn as sns
 
def cm_analysis(y_true, y_pred, filename, labels, ymap=None, figsize=(10,10)):
    """
    Generate matrix plot of confusion matrix with pretty annotations.
    The plot image is saved to disk.
    args: 
      y_true:    true label of the data, with shape (nsamples,)
      y_pred:    prediction of the data, with shape (nsamples,)
      filename:  filename of figure file to save
      labels:    string array, name the order of class labels in the confusion matrix.
                 use `clf.classes_` if using scikit-learn models.
                 with shape (nclass,).
      ymap:      dict: any -> string, length == nclass.
                 if not None, map the labels & ys to more understandable strings.
                 Caution: original y_true, y_pred and labels must align.
      figsize:   the size of the figure plotted.
    """
    if ymap is not None:
        y_pred = [ymap[yi] for yi in y_pred]
        y_true = [ymap[yi] for yi in y_true]
        labels = [ymap[yi] for yi in labels]
    cm = confusion_matrix(y_true, y_pred, labels=labels)
    cm_sum = np.sum(cm, axis=1, keepdims=True)
    cm_perc = cm / cm_sum.astype(float) * 100
    annot = np.empty_like(cm).astype(str)
    nrows, ncols = cm.shape
    for i in range(nrows):
        for j in range(ncols):
            c = cm[i, j]
            p = cm_perc[i, j]
            if i == j:
                s = cm_sum[i]
                annot[i, j] = '%.1f%%\n%d/%d' % (p, c, s)
            elif c == 0:
                annot[i, j] = ''
            else:
                annot[i, j] = '%.1f%%\n%d' % (p, c)
    cm = pd.DataFrame(cm, index=labels, columns=labels)
    cm.index.name = 'Actual'
    cm.columns.name = 'Predicted'
    fig, ax = plt.subplots(figsize=figsize)
    sns.heatmap(cm, annot=annot, fmt='', ax=ax)
    plt.savefig(filename)

נזין את הפונקציה בנתונים שלנו:

ymap = {k:v for k,v in zip(range(0,4), newsgroups_train.target_names)}
cm_analysis(df_train.cat, pred_train, 'cm', range(0,4), ymap=ymap)

classification matrix news groups

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

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

misclassified_texts = df_train.text[df_train.cat != pred_train]
misclassified_targets = pred_train[df_train.cat != pred_train]
actual_targets = df_train.cat[df_train.cat != pred_train]

misclassified_targets_names = [ymap[i] for i in misclassified_targets]
actual_targets_names = [ymap[i] for i in actual_targets]

# explore all the misclassified samples
[{'txt':tx,'false_t':ft,'true_t':tt} for tx,ft,tt in zip(misclassified_texts,misclassified_targets_names,actual_targets_names)]

 

הערכת המודל על קבוצת המבחן

כדי להעריך את ביצועי המודל חשוב לבחון אותו על דוגמאות שהוא לא נחשף אליהם במהלך האימון. לשם כך, שמרנו בצד את קבוצת המבחן. הקוד הבא יעריך את את הדיוק בקבוצת המבחן:

vector_test = vectorizer.transform(df_test.text)
 
clf.fit(vector_test, df_test.cat)
pred_test = clf.predict(vector_test)
 
acc_test = accuracy_score(df_test.cat, pred_test)
f1_test = f1_score(df_test.cat, pred_test, average='macro')
 
print('Total accuracy classification score: {:.2f}'.format(acc_test))
print('Total F1 classification score: {:.2f}'.format(f1_test))
Total accuracy classification score: 0.99
Total F1 classification score: 0.99

דיוק של 99% בקבוצת המבחן.

הקוד הבא יאפשר לנו לראות את הדוגמאות שהמודל שגה בסיווגם:

misclassified_texts = df_test.text[df_test.cat != pred_test]
misclassified_targets = pred_test[df_test.cat != pred_test]
actual_targets = df_test.cat[df_test.cat != pred_test]
 
misclassified_targets_names = [ymap[i] for i in misclassified_targets]
actual_targets_names = [ymap[i] for i in actual_targets]
 
# explore all the misclassified samples
[{'txt':tx,'false_t':ft,'true_t':tt} for tx,ft,tt in zip(misclassified_texts,misclassified_targets_names,actual_targets_names)]

 

סיווג באמצעות pipeline

ניתן לשלב את הוקטוריזציה עם המודל המסווג לתוך pipeline:

from sklearn.pipeline import make_pipeline
 
classifier = make_pipeline(TfidfVectorizer(), MultinomialNB())

נאמן את המודל על קבוצת האימון:

classifier.fit(df_train.text, df_train.cat)
Pipeline(memory=None,
         steps=[('tfidfvectorizer',
                 TfidfVectorizer(analyzer='word', binary=False,
                                 decode_error='strict',
                                 dtype=,
                                 encoding='utf-8', input='content',
                                 lowercase=True, max_df=1.0, max_features=None,
                                 min_df=1, ngram_range=(1, 1), norm='l2',
                                 preprocessor=None, smooth_idf=True,
                                 stop_words=None, strip_accents=None,
                                 sublinear_tf=False,
                                 token_pattern='(?u)\\b\\w\\w+\\b',
                                 tokenizer=None, use_idf=True,
                                 vocabulary=None)),
                ('multinomialnb',
                 MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True))],
         verbose=False)

נעריך את הביצועים על קבוצת המבחן:

pred_test = classifier.predict(df_test.text)
 
acc_test = accuracy_score(df_test.cat, pred_test)
f1_test = f1_score(df_test.cat, pred_test, average='macro')
 
print('Total accuracy classification score: {:.2f}'.format(acc_test))
print('Total F1 classification score: {:.2f}'.format(f1_test))

והתוצאה היא:

Total accuracy classification score: 0.91
Total F1 classification score: 0.91

מסיבה לא ברורה דיוק הסיווג באמצעות ה-pipeline (0.91) נמוך יותר מאשר בקוד ללא pipeline.

 

לסיכום

ראינו ש-sklearn מצליח לסווג ללא בעיות את הטקסטים. במקביל, אני מנסה לסווג בעזרת Keras המשתמש בארכיטקטורות של CNN ו-RNN. בשבועות הקרובים אפרסם את תוצאות הניסויים.

לכל המדריכים בנושא של למידת מכונה

 

אהבתם? לא אהבתם? דרגו!

0 הצבעות, ממוצע 0 מתוך 5 כוכבים

 

 

הוסף תגובה חדשה

 

= 5 + 2