در این پست که از سری آموزش رایگان TensorFlow است، به دسته بندی متن ها به دو گروه “مثبت” و “منفی” می پردازیم. این مثالی از دسته بندی باینری ( Binary-Classification ) یا همان دو کلاسه ( Two-Class-Classification ) است. دسته بندی باینری، یکی از مهمترین مسائل قابل طرح در یادگیری ماشین بوده و پیاده سازی های فراوانی از آن انجام شده است.
اولین و مهمترین چیزی که برای یک سیستم یادگیری ماشین وجود دارد، داده است. ما در این آموزش از دیتاست IMDB dataset استفاده میکنیم. این دیتاست شامل 50000 بررسی کاربران است که از سایت imdb جمع آوری شده است. ما داده ها را به دو دسته 25 هزار تایی برای آموزش و تست تقسیم می کنیم. این دو دسته 25 هزار تایید با هم برابر هستند، یعنی تعداد نظرات منفی و مثبت برابر اند.
خوب کد زدن را شروع میکنیم. وارد گوگل درایو خود شده و یک ipynb ایجاد کنید. به گفته منبع در نسخه های 1.13 و 1.14 تا 1.16 دیتاست پیش فرض keras.datasets.imdb شکسته است(ناقص خودمان) و برای همین نسخه nightly از TensorFlow نصب می کنیم :
!pip install -q tf_nightly
سپس از طریق Keras که یک API سطح بالا برای کار کردن با TensorFlow است، استفاده می کنیم :
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
from tensorflow import keras
import numpy as np
print(tf.__version__)
دانلود دیتاست:
خوشبختانه دیتاست IMDB به صورت پیشفرض با TensorFlow نصب می شود. خوبی دیتاست انتخابی ما، این است که قبلاً از پیش پردازش شده است و بررسی ها (توالی کلمات) به توالی اعداد صحیح تبدیل شده است. هر عدد صحیح یک کلمه خاص را در یک فرهنگ لغت نشان می دهد.کد زیر دیتاست IMDB را در دستگاه شما بارگیری می کند:
imdb = keras.datasets.imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)
آرگومان num_words = 10000 کلمه متداول در داده های آموزش را نگه می دارد. کلمات نادر برای کنترل اندازه داده ها قابل کنترل نیست.
دادهای موجود را بهتر بشناسید:
همیشه به خاطر داشته باشید در یادگیری با مربی ، شما باید تقریبا همه داده های مسئله را بدانید و بشناسید. پس بیایید زمانی را برای درک فرمت داده ها کنار بگذاریم. مجموعه داده از پیش پردازش شده است: هر نمونه مجموعه ای از اعداد صحیح است که کلمات بررسی فیلم را نشان می دهد. هر برچسب یک عدد صحیح یا 0 یا 1 است ، که در آن 0 بررسی منفی است و 1 یک بررسی مثبت است.
print("Training entries: {}, labels: {}".format(len(train_data), len(train_labels)))
متن بررسی ها به عدد صحیح تبدیل شده است ، جایی که هر عدد صحیح یک کلمه خاص را در یک فرهنگ لغت نشان می دهد. در اینجا نگاه اول به نظر می رسد:
print(train_data[30])
بررسی فیلم ممکن است طول های مختلفی داشته باشد. کد زیر تعداد کلمات را در بررسی های اول و دوم نشان می دهد. از آنجا که ورودی به شبکه عصبی باید به همان طول باشد ، باید بعداً این مسئله را برطرف کنیم.
تبدیل داده های عددی به کلمات:
ممکن است دانستن چگونگی تبدیل اعداد صحیح به متن مفید باشد. در اینجا ، ما برای جستجوی یک شیء فرهنگ لغت که شامل عدد صحیح به نقشه برداری رشته است ، یک تابع کمک کننده ایجاد خواهیم کرد. اکنون می توانیم از تابع decode_review برای نمایش متن برای اولین بار استفاده کنیم :
word_index = imdb.get_word_index()
word_index = {k:(v+3) for k,v in word_index.items()}
word_index["<PAD>"] = 0
word_index["<START>"] = 1
word_index["<UNK>"] = 2 # unknown
word_index["<UNUSED>"] = 3
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
def decode_review(text):
return ' '.join([reverse_word_index.get(i, '?') for i in text])
decode_review(train_data[30])
آماده سازی داده ها:
بررسی ها – آرایه اعداد صحیح – باید قبل از تغذیه به شبکه عصبی به Tensor تبدیل شوند. این تبدیل می تواند از دو طریق انجام شود. ما از راه دوم استفاده می کنیم.
- آرایه ها را به بردارهای 0 و 1 تبدیل کنید که نشانگر وقوع کلمه است. به عنوان مثال ، دنباله [3 ، 5] به یک وکتور 10،000 بعدی تبدیل می شود .در این وکتور همه شاخص ها صفر هستند به جز شاخص های 3 و 5 ، که همگی یک هستند. سپس این لایه را اولین لایه شبکه خود قرار دهید – یک لایه متراکم – که می تواند داده های بردار نقطه شناور (Floating point) را کنترل کند. این رویکرد به میزان مموری سیستم شما حساس است ، اما به ماتریس اندازه num_words * num_reviews نیاز است.
- روش دیگر ، ما می توانیم آرایه ها را بکشیم تا همه آنها طول یکسانی داشته باشند ، سپس یک تانسور عدد صحیح از شکل max_length * num_reviews ایجاد کنیم. ما می توانیم از لایه تعبیه شده ای استفاده کنیم که بتواند از این شکل به عنوان اولین لایه در شبکه ما استفاده کند.
از آنجا که بررسی فیلم باید به همان طول باشد ، ما از تابع pad_sequences برای استاندارد سازی طول استفاده خواهیم کرد:
train_data = keras.preprocessing.sequence.pad_sequences(train_data,value=word_index["<PAD>"],padding='post',maxlen=256)
test_data = keras.preprocessing.sequence.pad_sequences(test_data, value=word_index["<PAD>"],padding='post', maxlen=256)
ایجاد مدل در TensorFlow :
شبکه عصبی با ایجاد لایه ها ایجاد می شود – این امر نیاز به دو تصمیم اصلی در زمینه معماری دارد. 1- چه تعداد لایه در مدل استفاده شود؟ 2-یه تعداد واحد مخفی در هر لایه وجود داشته باشد؟
در این مثال ، داده های ورودی شامل آرایه ای از شاخص های word است. برچسب های پیش بینی شده 0 یا 1 هستند. بیایید برای این مشکل مدلی بسازیم:
vocab_size = 10000
model = keras.Sequential()
model.add(keras.layers.Embedding(vocab_size, 16))
model.add(keras.layers.GlobalAveragePooling1D())
model.add(keras.layers.Dense(16, activation=tf.nn.relu))
model.add(keras.layers.Dense(1, activation=tf.nn.sigmoid))
model.summary()
برای ساخت مدل دسته بندی ، لایه ها به صورت متوالی انباشته می شوند:
- اولین لایه یک لایه Embedding است. این لایه واژگان رمزگذاری شده عدد صحیح را در بر می گیرد و بردار تعبیه شده برای هر شاخص کلمه را جستجو می کند. این بردارها به عنوان آموزش مدل یاد می گیرند. بردارها ابعادی به آرایه خروجی اضافه می کنند. ابعاد حاصله عبارتند از: (batch, sequence, embedding) .
- در مرحله بعد ، یک لایه GlobalAavingPooling1D با اندازه گیری بیش از بعد دنباله ، بردار خروجی با طول ثابت را نشان می دهد. این به مدل اجازه می دهد تا با ساده ترین روش ممکن ، ورودی از طول متغیر را کنترل کند.
- این بردار خروجی با طول ثابت از طریق یک لایه کاملاً متصل (fully-connected Dense layer ) با 16 واحد پنهان لوله گذاری(piped )می شود.
- لایه آخر با یک گره خروجی متراکم متصل است. با استفاده از تابع فعال سازی سیگموئید (sigmoid activation function) ، خروجی این بخش یک مقدار شناور بین 0 و 1 است که یک احتمال یا سطح اطمینان(حدس شبکه ما) را نشان می دهد.
لایه پنهان در TensorFlow:
مدل فوق دارای دو لایه میانی یا “پنهان” ، بین ورودی و خروجی است. تعداد خروجی ها (واحد ها ، گره ها یا نورون ها) ابعاد فضای بازنمایی لایه است.اگر یک مدل واحدهای پنهان تر (فضای نمایشی با ابعاد بالاتر) و / یا لایه های بیشتری داشته باشد ، آنگاه شبکه می تواند بازنمایی های پیچیده تری را یاد بگیرد. با این حال ، این شبکه از نظر محاسباتی گرانتر عمل می کند و ممکن است منجر به یادگیری الگوهای ناخواسته شود. به این کار overfitting گفته می شود .
توابع loss و بهینه ساز (Optimizer) :
یک مدل یادگیرنده به یک تابع loss و یک تابع Optimizer برای آموزش نیاز دارد. از آنجا که این یک مشکل طبقه بندی باینری است و مدل یک احتمال را می دهد (یک لایه تک واحدی با فعال سازی سیگموئید) ، ما از تابع از loss به نام binary_crossentropy استفاده خواهیم کرد. البته توابع loss دیگری نیز وجود دارد. اما ، به طور کلی ، binary_crossentropy برای برخورد با احتمالات بهتر است .حالا مدل را اجرا بگیرید :
model.compile(optimizer='adam', loss='binary_crossentropy',metrics=['acc'])
یک مجموعه اعتبار سنجی ایجاد کنید :
هنگام آموزش ، می خواهیم صحت مدل را در داده هایی که قبلاً دیده نشده است ، بررسی کنیم. با جدا کردن 10،000 نمونه از داده های اصلی آموزش ، می توانیم یک مجموعه اعتبار سنجی ایجاد کنید. (چرا اکنون از مجموعه تست استفاده نمی کنیم؟ هدف ما این است که فقط با استفاده از داده های آموزش ، مدل خود را توسعه داده و تنظیم کنیم ، سپس فقط یک بار از داده های آزمون استفاده کنیم تا دقت خود را ارزیابی کنیم):
x_val = train_data[:10000]
partial_x_train = train_data[10000:]
y_val = train_labels[:10000]
partial_y_train = train_labels[10000:]
آموزش دادن به مدل :
مدل را برای 40 دوره در ریز-دسته (mini-batches) از نمونه های 512 تایی آموزش دهید. این 40 تکرار در تمام نمونه های موجود در Tensor های x_train و y_train است. در حین آموزش ، می بایست از loss و صحت یادگیری روی 10،000 نمونه را اعتبار سنجی کنید:
history = model.fit(partial_x_train,
partial_y_train,
epochs=40,
batch_size=512,
validation_data=(x_val, y_val),
verbose=1)
رستاخیز 😀
بیایید ببینیم مدل چگونه عمل می کند. دو مقدار بازگردانده می شوند. loss (عددی که نشان دهنده خطای ما است ، مقادیر پایین بهتر هستند) و دقت:
results = model.evaluate(test_data, test_labels)
print(results)
تا اینجای کار بسه خیلی طولانی شد کد بالا حدودا 87 درصد تشخیص درست میده . به نظرتون چه طور این درصد رو افزایش بدیم ؟