این صفحه به‌وسیله ‏Cloud Translation API‏ ترجمه شده است.
Switch to English

طبقه بندی متن اصلی

مشاهده در TensorFlow.org در Google Colab اجرا کنید مشاهده منبع در GitHub بارگیری نوت بوک

این آموزش طبقه بندی متن را با شروع از پرونده های متنی ساده ذخیره شده روی دیسک نشان می دهد. برای انجام تجزیه و تحلیل احساسات در مجموعه داده IMDB ، به یک طبقه بندی دودویی آموزش می دهید. در پایان نوت بوک ، یک تمرین برای شما وجود دارد که می توانید در آن یک طبقه بندی کننده چند کلاس را آموزش دهید تا برچسب سؤال برنامه نویسی در Stack Overflow را پیش بینی کند.

 import matplotlib.pyplot as plt
import os
import re
import shutil
import string
import tensorflow as tf

from tensorflow.keras import layers
from tensorflow.keras import losses
from tensorflow.keras import preprocessing
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization
 
 print(tf.__version__)
 
2.3.0

تجزیه و تحلیل احساسات

این نوت بوک یک مدل تجزیه و تحلیل احساسات را آموزش می دهد تا بررسی فیلم ها را بر اساس متن بررسی ، مثبت یا منفی طبقه بندی کند. این یک نمونه از طبقه بندی باینری دو طبقه است ، یک نوع مهم و کاربردی از مسئله یادگیری ماشین.

شما می توانید از مجموعه داده های مرور بزرگ فیلم استفاده کنید که حاوی متن 50،000 بررسی فیلم از بانک اطلاعات اینترنتی فیلم است . اینها به 25،000 بررسی برای آموزش و 25،000 بررسی برای آزمایش تقسیم می شوند. مجموعه های آموزشی و تست متعادل هستند ، به این معنی که تعداد قابل توجهی از بررسی های مثبت و منفی دارند.

مجموعه داده IMDB را بارگیری و اکتشاف کنید

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

 url = "https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz"

dataset = tf.keras.utils.get_file("aclImdb_v1.tar.gz", url,
                                    untar=True, cache_dir='.',
                                    cache_subdir='')

dataset_dir = os.path.join(os.path.dirname(dataset), 'aclImdb')
 
Downloading data from https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
84131840/84125825 [==============================] - 7s 0us/step

 os.listdir(dataset_dir)
 
['imdb.vocab', 'train', 'test', 'README', 'imdbEr.txt']
 train_dir = os.path.join(dataset_dir, 'train')
os.listdir(train_dir)
 
['urls_pos.txt',
 'neg',
 'labeledBow.feat',
 'pos',
 'urls_neg.txt',
 'unsup',
 'unsupBow.feat',
 'urls_unsup.txt']

aclImdb/train/pos و aclImdb/train/neg حاوی پرونده های متنی زیادی هستند که هرکدام یک بررسی فیلم واحد هستند. بیایید نگاهی به یکی از آنها بیندازیم.

 sample_file = os.path.join(train_dir, 'pos/1181_9.txt')
with open(sample_file) as f:
  print(f.read())
 
Rachel Griffiths writes and directs this award winning short film. A heartwarming story about coping with grief and cherishing the memory of those we've loved and lost. Although, only 15 minutes long, Griffiths manages to capture so much emotion and truth onto film in the short space of time. Bud Tingwell gives a touching performance as Will, a widower struggling to cope with his wife's death. Will is confronted by the harsh reality of loneliness and helplessness as he proceeds to take care of Ruth's pet cow, Tulip. The film displays the grief and responsibility one feels for those they have loved and lost. Good cinematography, great direction, and superbly acted. It will bring tears to all those who have lost a loved one, and survived.

مجموعه داده را بارگیری کنید

در مرحله بعد ، دیسک خاموش را بارگذاری کرده و آن را در قالب مناسب برای آموزش آماده خواهید کرد. برای این کار از ابزار مفید text_dataset_from_directory استفاده می کنید ، که انتظار می رود یک ساختار دایرکتوری به شرح زیر باشد.

 main_directory/
...class_a/
......a_text_1.txt
......a_text_2.txt
...class_b/
......b_text_1.txt
......b_text_2.txt
 

برای تهیه یک مجموعه داده برای طبقه بندی باینری ، به دو پوشه در دیسک نیاز دارید که مربوط به class_a و class_b . اینها بررسی های مثبت و منفی فیلم خواهد بود که می توانید در aclImdb/train/pos و aclImdb/train/neg . از آنجا که مجموعه داده IMDB حاوی پوشه های اضافی است ، شما آنها را قبل از استفاده از این ابزار حذف خواهید کرد.

 remove_dir = os.path.join(train_dir, 'unsup')
shutil.rmtree(remove_dir)
 

در مرحله بعدی ، شما از ابزار text_dataset_from_directory برای ایجاد یک برچسب tf.data.Dataset . tf.data مجموعه ای قدرتمند از ابزارها برای کار با داده است.

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

مجموعه داده IMDB قبلاً به قطار و آزمون تقسیم شده است ، اما فاقد یک مجموعه اعتبارسنجی است. بیایید با استفاده از استدلال validation_split زیر ، یک مجموعه اعتبارسنجی را با استفاده از تقسیم 80:20 از داده های آموزش ایجاد کنیم.

 batch_size = 32
seed = 42

raw_train_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/train', 
    batch_size=batch_size, 
    validation_split=0.2, 
    subset='training', 
    seed=seed)
 
Found 25000 files belonging to 2 classes.
Using 20000 files for training.

همانطور که در بالا مشاهده می کنید ، 25000 نمونه در پوشه آموزش وجود دارد که از آنها 80٪ (یا 20،000) برای آموزش استفاده خواهید کرد. همانطور که در یک لحظه مشاهده خواهید کرد ، می توانید با انتقال یک مجموعه داده به طور مستقیم به model.fit ، یک مدل را آموزش model.fit . اگر تازه وارد tf.data ، می توانید از مجموعه داده تکرار کرده و چند نمونه را به شرح زیر چاپ کنید.

 for text_batch, label_batch in raw_train_ds.take(1):
  for i in range(3):
    print("Review", text_batch.numpy()[i])
    print("Label", label_batch.numpy()[i])
 
Review b'"Pandemonium" is a horror movie spoof that comes off more stupid than funny. Believe me when I tell you, I love comedies. Especially comedy spoofs. "Airplane", "The Naked Gun" trilogy, "Blazing Saddles", "High Anxiety", and "Spaceballs" are some of my favorite comedies that spoof a particular genre. "Pandemonium" is not up there with those films. Most of the scenes in this movie had me sitting there in stunned silence because the movie wasn\'t all that funny. There are a few laughs in the film, but when you watch a comedy, you expect to laugh a lot more than a few times and that\'s all this film has going for it. Geez, "Scream" had more laughs than this film and that was more of a horror film. How bizarre is that?<br /><br />*1/2 (out of four)'
Label 0
Review b"David Mamet is a very interesting and a very un-equal director. His first movie 'House of Games' was the one I liked best, and it set a series of films with characters whose perspective of life changes as they get into complicated situations, and so does the perspective of the viewer.<br /><br />So is 'Homicide' which from the title tries to set the mind of the viewer to the usual crime drama. The principal characters are two cops, one Jewish and one Irish who deal with a racially charged area. The murder of an old Jewish shop owner who proves to be an ancient veteran of the Israeli Independence war triggers the Jewish identity in the mind and heart of the Jewish detective.<br /><br />This is were the flaws of the film are the more obvious. The process of awakening is theatrical and hard to believe, the group of Jewish militants is operatic, and the way the detective eventually walks to the final violent confrontation is pathetic. The end of the film itself is Mamet-like smart, but disappoints from a human emotional perspective.<br /><br />Joe Mantegna and William Macy give strong performances, but the flaws of the story are too evident to be easily compensated."
Label 0
Review b'Great documentary about the lives of NY firefighters during the worst terrorist attack of all time.. That reason alone is why this should be a must see collectors item.. What shocked me was not only the attacks, but the"High Fat Diet" and physical appearance of some of these firefighters. I think a lot of Doctors would agree with me that,in the physical shape they were in, some of these firefighters would NOT of made it to the 79th floor carrying over 60 lbs of gear. Having said that i now have a greater respect for firefighters and i realize becoming a firefighter is a life altering job. The French have a history of making great documentary\'s and that is what this is, a Great Documentary.....'
Label 1

توجه کنید که این بررسی ها حاوی متن خام هستند (با علائم نگارشی و برچسب های گاه به گاه HTML مانند <br/> ). در بخش زیر نحوه رسیدگی به این موارد را نشان می دهید.

برچسب ها 0 یا 1 هستند. برای دیدن اینکه کدام یک از اینها با بررسی فیلم مثبت و منفی مطابقت دارد ، می توانید ویژگی class_names را در مجموعه داده بررسی کنید.

 print("Label 0 corresponds to", raw_train_ds.class_names[0])
print("Label 1 corresponds to", raw_train_ds.class_names[1])
 
Label 0 corresponds to neg
Label 1 corresponds to pos

بعد ، یک مجموعه داده اعتبار سنجی و آزمایش ایجاد می کنید. شما برای تأیید اعتبار ، از 5،000 بررسی باقی مانده از مجموعه آموزش استفاده خواهید کرد.

 raw_val_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/train', 
    batch_size=batch_size, 
    validation_split=0.2, 
    subset='validation', 
    seed=seed)
 
Found 25000 files belonging to 2 classes.
Using 5000 files for validation.

 raw_test_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/test', 
    batch_size=batch_size)
 
Found 25000 files belonging to 2 classes.

مجموعه داده ها را برای آموزش آماده کنید

در مرحله بعد ، داده ها را با استفاده از لایه preprocessing.TextVectorization مفید.TextVectorization بصورت استاندارد ، علامت گذاری و وکتورسازی می کنید.

استاندارد سازی به پیش پردازش متن اشاره دارد ، به طور معمول برای حذف نگارشی یا عناصر HTML برای ساده کردن مجموعه داده. Tokenization به تقسیم رشته ها به نشانه ها (مثلاً تقسیم یک جمله به کلمات فردی ، با تقسیم بر فضای سفید) اطلاق می شود. بردارسازی به تبدیل نشانه ها به اعداد اشاره دارد تا بتوان آنها را به یک شبکه عصبی تبدیل کرد. همه این کارها با این لایه قابل انجام است.

همانطور که در بالا دیدید ، این بررسی ها حاوی برچسب های مختلف HTML مانند <br /> . این برچسب ها توسط استاندارد ساز پیش فرض در لایه TextVectorization حذف نمی شوند (که متن را به صورت پیش فرض به کم کردن خط و نوار تبدیل می کند ، اما HTML را نوار نمی کند). برای حذف HTML ، یک تابع استاندارد سازی سفارشی خواهید نوشت.

 def custom_standardization(input_data):
  lowercase = tf.strings.lower(input_data)
  stripped_html = tf.strings.regex_replace(lowercase, '<br />', ' ')
  return tf.strings.regex_replace(stripped_html,
                                  '[%s]' % re.escape(string.punctuation),
                                  '')
 

بعد ، شما یک لایه TextVectorization ایجاد خواهید کرد. شما از این لایه برای استاندارد سازی ، نشانه گذاری و وکتورسازی داده های ما استفاده خواهید کرد. شما output_mode روی int می کنید تا شاخص های عدد صحیح منحصر به فردی برای هر نشانه ایجاد کنید.

توجه داشته باشید که شما از تابع پیش فرض تقسیم و عملکرد استاندارد سازی سفارشی که در بالا تعریف کرده اید استفاده می کنید. شما همچنین می توانید برخی از ثابت ها را مانند مدل ، حداکثر sequence_length ، که باعث می شود لایه به sequence_length مقادیر دقیقاً دنباله_سنجی یا sequence_length را کاهش دهد.

 max_features = 10000
sequence_length = 250

vectorize_layer = TextVectorization(
    standardize=custom_standardization,
    max_tokens=max_features,
    output_mode='int',
    output_sequence_length=sequence_length)
 

در مرحله بعد ، شما متناسب با وضعیت لایه پیش پردازش با مجموعه داده ، adapt شوید. این امر باعث می شود تا مدل از رشته ها به عدد صحیح ساخته شود.

 # Make a text-only dataset (without labels), then call adapt
train_text = raw_train_ds.map(lambda x, y: x)
vectorize_layer.adapt(train_text)
 

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

 def vectorize_text(text, label):
  text = tf.expand_dims(text, -1)
  return vectorize_layer(text), label
 
 # retrieve a batch (of 32 reviews and labels) from the dataset
text_batch, label_batch = next(iter(raw_train_ds))
first_review, first_label = text_batch[0], label_batch[0]
print("Review", first_review)
print("Label", raw_train_ds.class_names[first_label])
print("Vectorized review", vectorize_text(first_review, first_label))
 
Review tf.Tensor(b'Silent Night, Deadly Night 5 is the very last of the series, and like part 4, it\'s unrelated to the first three except by title and the fact that it\'s a Christmas-themed horror flick.<br /><br />Except to the oblivious, there\'s some obvious things going on here...Mickey Rooney plays a toymaker named Joe Petto and his creepy son\'s name is Pino. Ring a bell, anyone? Now, a little boy named Derek heard a knock at the door one evening, and opened it to find a present on the doorstep for him. Even though it said "don\'t open till Christmas", he begins to open it anyway but is stopped by his dad, who scolds him and sends him to bed, and opens the gift himself. Inside is a little red ball that sprouts Santa arms and a head, and proceeds to kill dad. Oops, maybe he should have left well-enough alone. Of course Derek is then traumatized by the incident since he watched it from the stairs, but he doesn\'t grow up to be some killer Santa, he just stops talking.<br /><br />There\'s a mysterious stranger lurking around, who seems very interested in the toys that Joe Petto makes. We even see him buying a bunch when Derek\'s mom takes him to the store to find a gift for him to bring him out of his trauma. And what exactly is this guy doing? Well, we\'re not sure but he does seem to be taking these toys apart to see what makes them tick. He does keep his landlord from evicting him by promising him to pay him in cash the next day and presents him with a "Larry the Larvae" toy for his kid, but of course "Larry" is not a good toy and gets out of the box in the car and of course, well, things aren\'t pretty.<br /><br />Anyway, eventually what\'s going on with Joe Petto and Pino is of course revealed, and as with the old story, Pino is not a "real boy". Pino is probably even more agitated and naughty because he suffers from "Kenitalia" (a smooth plastic crotch) so that could account for his evil ways. And the identity of the lurking stranger is revealed too, and there\'s even kind of a happy ending of sorts. Whee.<br /><br />A step up from part 4, but not much of one. Again, Brian Yuzna is involved, and Screaming Mad George, so some decent special effects, but not enough to make this great. A few leftovers from part 4 are hanging around too, like Clint Howard and Neith Hunter, but that doesn\'t really make any difference. Anyway, I now have seeing the whole series out of my system. Now if I could get some of it out of my brain. 4 out of 5.', shape=(), dtype=string)
Label neg
Vectorized review (<tf.Tensor: shape=(1, 250), dtype=int64, numpy=
array([[1287,  313, 2380,  313,  661,    7,    2,   52,  229,    5,    2,
         200,    3,   38,  170,  669,   29, 5492,    6,    2,   83,  297,
         549,   32,  410,    3,    2,  186,   12,   29,    4,    1,  191,
         510,  549,    6,    2, 8229,  212,   46,  576,  175,  168,   20,
           1, 5361,  290,    4,    1,  761,  969,    1,    3,   24,  935,
        2271,  393,    7,    1, 1675,    4, 3747,  250,  148,    4,  112,
         436,  761, 3529,  548,    4, 3633,   31,    2, 1331,   28, 2096,
           3, 2912,    9,    6,  163,    4, 1006,   20,    2,    1,   15,
          85,   53,  147,    9,  292,   89,  959, 2314,  984,   27,  762,
           6,  959,    9,  564,   18,    7, 2140,   32,   24, 1254,   36,
           1,   85,    3, 3298,   85,    6, 1410,    3, 1936,    2, 3408,
         301,  965,    7,    4,  112,  740, 1977,   12,    1, 2014, 2772,
           3,    4,  428,    3, 5177,    6,  512, 1254,    1,  278,   27,
         139,   25,  308,    1,  579,    5,  259, 3529,    7,   92, 8981,
          32,    2, 3842,  230,   27,  289,    9,   35,    2, 5712,   18,
          27,  144, 2166,   56,    6,   26,   46,  466, 2014,   27,   40,
        2745,  657,  212,    4, 1376, 3002, 7080,  183,   36,  180,   52,
         920,    8,    2, 4028,   12,  969,    1,  158,   71,   53,   67,
          85, 2754,    4,  734,   51,    1, 1611,  294,   85,    6,    2,
        1164,    6,  163,    4, 3408,   15,   85,    6,  717,   85,   44,
           5,   24, 7158,    3,   48,  604,    7,   11,  225,  384,   73,
          65,   21,  242,   18,   27,  120,  295,    6,   26,  667,  129,
        4028,  948,    6,   67,   48,  158,   93,    1]])>, <tf.Tensor: shape=(), dtype=int32, numpy=0>)

همانطور که در بالا مشاهده می کنید ، هر علامت توسط عدد صحیح جایگزین شده است. می توانید با تماس با .get_vocabulary() روی لایه ، توکن (رشته) را که هر یک از عدد صحیح ها با آنها مطابقت دارد ، جستجو کنید.

 print("1287 ---> ",vectorize_layer.get_vocabulary()[1287])
print(" 313 ---> ",vectorize_layer.get_vocabulary()[313])
print('Vocabulary size: {}'.format(len(vectorize_layer.get_vocabulary())))
 
1287 --->  silent
 313 --->  night
Vocabulary size: 10000

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

 train_ds = raw_train_ds.map(vectorize_text)
val_ds = raw_val_ds.map(vectorize_text)
test_ds = raw_test_ds.map(vectorize_text)
 

مجموعه داده برای عملکرد پیکربندی کنید

این دو روش مهمی هستند که باید هنگام بارگیری داده ها از آنها استفاده کنید تا مطمئن شوید I / O به انسداد تبدیل نمی شود.

.cache() بعد از بارگیری دیسک داده ها را در حافظه نگه می دارد. با این کار اطمینان حاصل می شود که در هنگام آموزش مدل ، مجموعه داده تبدیل به تنگنا نشود. اگر مجموعه داده شما برای جا به جایی حافظه بسیار بزرگ است ، می توانید از این روش برای ایجاد حافظه پنهان روی دیسک نیز استفاده کنید که خواندن آن نسبت به بسیاری از پرونده های کوچک کارآمدتر است.

.prefetch() پردازش داده ها و اجرای مدل را در هنگام آموزش همپوشانی می کند.

در راهنمای عملکرد داده ها می توانید اطلاعات بیشتری در مورد هر دو روش و همچنین نحوه ذخیره کردن داده ها به دیسک را یاد بگیرید.

 AUTOTUNE = tf.data.experimental.AUTOTUNE

train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
test_ds = test_ds.cache().prefetch(buffer_size=AUTOTUNE)
 

مدل را ایجاد کنید

زمان آن رسیده است که شبکه عصبی خود را ایجاد کنیم:

 embedding_dim = 16
 
 model = tf.keras.Sequential([
  layers.Embedding(max_features + 1, embedding_dim),
  layers.Dropout(0.2),
  layers.GlobalAveragePooling1D(),
  layers.Dropout(0.2),
  layers.Dense(1)])

model.summary()
 
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, None, 16)          160016    
_________________________________________________________________
dropout (Dropout)            (None, None, 16)          0         
_________________________________________________________________
global_average_pooling1d (Gl (None, 16)                0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 16)                0         
_________________________________________________________________
dense (Dense)                (None, 1)                 17        
=================================================================
Total params: 160,033
Trainable params: 160,033
Non-trainable params: 0
_________________________________________________________________

برای ساخت طبقه بندی ، لایه ها به صورت متوالی انباشته می شوند:

  1. اولین لایه یک لایه Embedding است. این لایه بررسی های رمزگذاری شده عدد صحیح را در بر می گیرد و برای هر شاخص کلمه یک بردار جاسازی کننده جستجو می کند. این بردارها به عنوان آموزش مدل یاد می گیرند. بردارها ابعادی به آرایه خروجی اضافه می کنند. ابعاد حاصله عبارتند از: (batch, sequence, embedding) . برای کسب اطلاعات بیشتر در مورد تعبیه ، به آموزش آموزش تعبیه واژه مراجعه کنید.
  2. در مرحله بعد ، یک لایه GlobalAveragePooling1D با اندازه گیری بیش از بعد دنباله ، بردار خروجی با طول ثابت را برای هر مثال برمی گرداند. این به مدل اجازه می دهد تا با ساده ترین روش ممکن ، ورودی از طول متغیر را کنترل کند.
  3. این بردار خروجی با طول ثابت از طریق یک لایه کاملاً متصل ( Dense ) با 16 واحد پنهان لوله گذاری می شود.
  4. لایه آخر با یک گره خروجی متراکم متصل است.

عملکرد و بهینه ساز از دست دادن

یک مدل به یک عملکرد ضرر و بهینه ساز برای آموزش نیاز دارد. از آنجا که این یک مشکل طبقه بندی باینری است و مدل یک احتمال را به همراه می آورد (یک لایه تک واحدی با فعال سازی سیگموئید) ، از توابع از دست دادن. losses.BinaryCrossentropy استفاده می کنید.

اکنون ، مدل را برای استفاده از بهینه ساز و عملکرد ضرر پیکربندی کنید:

 model.compile(loss=losses.BinaryCrossentropy(from_logits=True), optimizer='adam', metrics=tf.metrics.BinaryAccuracy(threshold=0.0))
 

آموزش مدل

شما با انتقال شیء dataset به متد fit ، مدل را آموزش می دهید.

 epochs = 10
history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=epochs)
 
Epoch 1/10
625/625 [==============================] - 3s 5ms/step - loss: 0.6632 - binary_accuracy: 0.6931 - val_loss: 0.6135 - val_binary_accuracy: 0.7752
Epoch 2/10
625/625 [==============================] - 3s 4ms/step - loss: 0.5472 - binary_accuracy: 0.8003 - val_loss: 0.4968 - val_binary_accuracy: 0.8220
Epoch 3/10
625/625 [==============================] - 3s 4ms/step - loss: 0.4434 - binary_accuracy: 0.8459 - val_loss: 0.4187 - val_binary_accuracy: 0.8486
Epoch 4/10
625/625 [==============================] - 3s 4ms/step - loss: 0.3770 - binary_accuracy: 0.8660 - val_loss: 0.3726 - val_binary_accuracy: 0.8622
Epoch 5/10
625/625 [==============================] - 2s 4ms/step - loss: 0.3349 - binary_accuracy: 0.8786 - val_loss: 0.3442 - val_binary_accuracy: 0.8678
Epoch 6/10
625/625 [==============================] - 2s 4ms/step - loss: 0.3046 - binary_accuracy: 0.8889 - val_loss: 0.3253 - val_binary_accuracy: 0.8722
Epoch 7/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2807 - binary_accuracy: 0.8977 - val_loss: 0.3118 - val_binary_accuracy: 0.8726
Epoch 8/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2609 - binary_accuracy: 0.9046 - val_loss: 0.3026 - val_binary_accuracy: 0.8762
Epoch 9/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2443 - binary_accuracy: 0.9123 - val_loss: 0.2961 - val_binary_accuracy: 0.8774
Epoch 10/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2309 - binary_accuracy: 0.9163 - val_loss: 0.2915 - val_binary_accuracy: 0.8804

مدل را ارزیابی کنید

بیایید ببینیم مدل چگونه عمل می کند. دو مقدار بازگردانده می شوند. ضرر (عددی که نشان دهنده خطای ما است ، مقادیر پایین بهتر هستند) و دقت.

 loss, accuracy = model.evaluate(test_ds)

print("Loss: ", loss)
print("Accuracy: ", accuracy)
 
782/782 [==============================] - 2s 3ms/step - loss: 0.3097 - binary_accuracy: 0.8740
Loss:  0.30967268347740173
Accuracy:  0.8740400075912476

این رویکرد نسبتاً ساده و بی تکلف به دقت حدود 86٪ دست می یابد.

با گذشت زمان نقشه ای از دقت و ضرر ایجاد کنید

model.fit() یک مورد History را که شامل یک فرهنگ لغت است با همه اتفاقاتی که در طول آموزش رخ داده است برمی گرداند:

 history_dict = history.history
history_dict.keys()
 
dict_keys(['loss', 'binary_accuracy', 'val_loss', 'val_binary_accuracy'])

چهار مدخل وجود دارد: یکی برای هر متریک نظارت شده در طول آموزش و اعتبار سنجی. شما می توانید از اینها برای ترسیم آموزش و از دست رفتن اعتبار سنجی برای مقایسه و همچنین دقت در آموزش و اعتبار سنجی استفاده کنید:

 acc = history_dict['binary_accuracy']
val_acc = history_dict['val_binary_accuracy']
loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(acc) + 1)

# "bo" is for "blue dot"
plt.plot(epochs, loss, 'bo', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()
 

png

 plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')

plt.show()
 

png

در این طرح ، نقاط نشان دهنده از دست دادن و دقت آموزش است ، و خطوط محکم ، از بین رفتن و صحت اعتبار هستند.

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

این در مورد از دست دادن اعتبار و صحت نیست - به نظر می رسد آنها قبل از دقت تمرین به اوج خود می رسند. این یک نمونه از اتصالات بیش از حد است: این مدل نسبت به داده هایی که قبلاً ندیده ، روی داده های آموزش بهتر عمل می کند. پس از این مرحله ، مدل بیش از حد بهینه سازی می کند و یادگیری های خاص برای داده های آموزشی را که برای آزمایش داده ها تعمیم ندارند ، بهینه سازی و یاد می گیرد.

در این مورد خاص ، می توانید با متوقف کردن تمرین ، در صورت افزایش صحت اعتبار ، دیگر مانع از اضافه شدن اتصالات شوید. یکی از راه های انجام این کار استفاده از پاسخ به تماس EarlyStopping است .

مدل را صادر کنید

در کد بالا ، قبل از تغذیه متن به مدل ، لایه TextVectorization به TextVectorization اعمال TextVectorization . اگر می خواهید مدل خود را قادر به پردازش رشته های خام (به عنوان مثال ، برای به کارگیری آن بکار بگیرید) ، می توانید لایه TextVectorization را در داخل مدل خود قرار دهید. برای این کار می توانید با استفاده از وزنه هایی که اخیراً آموزش داده اید ، یک مدل جدید ایجاد کنید.

 export_model = tf.keras.Sequential([
  vectorize_layer,
  model,
  layers.Activation('sigmoid')
])

export_model.compile(
    loss=losses.BinaryCrossentropy(from_logits=False), optimizer="adam", metrics=['accuracy']
)

# Test it with `raw_test_ds`, which yields raw strings
loss, accuracy = export_model.evaluate(raw_test_ds)
print(accuracy)
 
782/782 [==============================] - 3s 4ms/step - loss: 0.3097 - accuracy: 0.8740
0.8740400075912476

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

هنگام انتخاب جایی که می توانید لایه TextVectorization خود را بکار بگیرید ، تفاوت عملکردی وجود دارد. استفاده از آن در خارج از مدل شما ، شما را قادر می سازد هنگام پردازش در GPU ، پردازش CPU ناهمزمان و بافر کردن داده های خود را انجام دهید. بنابراین ، اگر شما در حال تدوین مدل خود در GPU هستید ، احتمالاً می خواهید با استفاده از این گزینه پیش بروید تا در حین تهیه مدل خود بهترین کارایی را داشته باشید ، سپس در هنگام آماده سازی برای استقرار ، به لایه TextVectorization داخل مدل خود بپردازید. .

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

تمرين: طبقه بندي چند كلاسي بر روي سؤالات سرریز Stack

این آموزش نحوه آموزش طبقه بندی کننده باینری را از ابتدا در مجموعه داده IMDB نشان داد. به عنوان یک تمرین ، می توانید این نوت بوک را برای آموزش یک طبقه بندی کننده چندکلاسی اصلاح کنید تا برچسب سؤال برنامه نویسی در Stack Overflow را پیش بینی کند.

ما مجموعه ای از داده ها را برای شما آماده کرده ایم که بتواند شامل چندین هزار سوال برنامه نویسی باشد (برای مثال ، "چگونه می توانید فرهنگ لغت را با ارزش در پایتون مرتب کنید؟") که در Stack Overflow ارسال شده است. هر کدام از اینها دقیقاً با یک برچسب (یا پایتون ، CSharp ، جاوا اسکریپت یا جاوا) مشخص شده اند. وظیفه شما این است که یک سؤال را به عنوان ورودی در نظر بگیرید و برچسب مناسب را در این مورد Python پیش بینی کنید.

مجموعه داده ای که با آنها کار خواهید کرد شامل چندین هزار سوال است که از مجموعه داده های بزرگتر عمومی Stack Overflow در BigQuery استخراج شده است ، که حاوی بیش از 17 میلیون ارسال است.

پس از بارگیری مجموعه داده ، متوجه می شوید که ساختار دایرکتوری مشابه با مجموعه داده IMDB که قبلاً با آنها کار کرده اید وجود دارد:

 train/
...python/
......0.txt
......1.txt
...javascript/
......0.txt
......1.txt
...csharp/
......0.txt
......1.txt
...java/
......0.txt
......1.txt
 

برای انجام این تمرین ، باید این نوت بوک را تغییر دهید تا با انجام مجموعه داده های Stack Overflow با داده های زیر کار کنید:

  1. در بالای نوت بوک خود ، کدی را که بارگیری داده های IMDB با کد را بارگیری می کند ، برای بارگیری مجموعه داده Stack Overflow که ما آماده کرده ایم ، به روز کنید. از آنجا که مجموعه داده Stack Overflow از ساختار پوشه مشابهی برخوردار است ، دیگر نیازی به اصلاحات نخواهید داشت.

  2. آخرین لایه مدل خود را برای خواندن Dense(4) ، زیرا اکنون چهار کلاس خروجی وجود دارد.

  3. وقتی مدل خود را کامپایل می کنید ، ضرر را به SparseCategoricalCrossentropy تغییر دهید. این تابع از دست دادن صحیح است که برای یک مسئله طبقه بندی چندکلاسی استفاده می شود ، هنگامی که برچسب ها برای هر کلاس عدد صحیح هستند (در مورد ما ، آنها می توانند 0 ، 1 ، 2 یا 3 باشند ).

  4. پس از اتمام این تغییرات ، می توانید یک طبقه بندی کننده چند کلاس را آموزش دهید.

اگر گیر کردید ، می توانید در اینجا یک راه حل پیدا کنید .

بیشتر بدانید

این آموزش طبقه بندی متن را از ابتدا معرفی کرد. برای کسب اطلاعات بیشتر در مورد گردش کار طبقه بندی متن به طور کلی ، توصیه می کنیم این راهنما را از Google Developers بخوانید.

 
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.