از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
Python برای NLP: ایجاد مدلهای طبقهبندی چند داده با Keras
سرفصلهای مطلب
این هجدهمین مقاله از سری مقالات من است روی پایتون برای NLP. در مقاله قبلی خود، روش ایجاد یک مدل تحلیل احساسات فیلم مبتنی بر یادگیری عمیق را با استفاده از پایتون توضیح دادم. کراس کتابخانه در آن مقاله، دیدیم که چگونه میتوانیم تحلیل احساسات نظرات کاربران را در مورد فیلمهای مختلف انجام دهیم روی IMDB. ما از متن بررسی برای پیش بینی احساسات استفاده کردیم.
با این حال، در کارهای طبقه بندی متن، می توانیم از اطلاعات غیر متنی نیز برای طبقه بندی متن استفاده کنیم. به عنوان مثال، جنسیت ممکن است تأثیر داشته باشد روی احساس بررسی علاوه بر این، ملیت ها ممکن است بر افکار عمومی در مورد یک فیلم خاص تأثیر بگذارند. بنابراین، این اطلاعات مرتبط، همچنین به عنوان فراداده شناخته می شود، همچنین می تواند برای بهبود دقت مدل آماری استفاده شود.
در این مقاله، ما بر اساس مفاهیمی که در دو مقاله اخیر مطالعه کردیم، میپردازیم و خواهیم دید که چگونه میتوان یک سیستم طبقهبندی متن ایجاد کرد که نظرات کاربران را در مورد مشاغل مختلف در یکی از سه دسته از پیش تعریفشده یعنی «خوب»، «بد» طبقهبندی کند. “، و “متوسط”. با این حال، علاوه بر متن بررسی، از فراداده مربوط به بررسی برای انجام طبقهبندی استفاده خواهیم کرد. از آنجایی که ما دو نوع ورودی متفاوت داریم یعنی ورودی متنی و ورودی عددی، باید یک مدل ورودی چندگانه ایجاد کنیم. ما از Keras Functional API استفاده خواهیم کرد زیرا از چندین ورودی و چند مدل خروجی پشتیبانی می کند.
پس از مطالعه این مقاله، میتوانید یک مدل یادگیری عمیق در Keras ایجاد کنید که قادر به پذیرش چندین ورودی، به هم پیوستن دو خروجی و سپس انجام طبقهبندی یا رگرسیون با استفاده از ورودی تجمیع است.
قبل از اینکه به جزئیات ایجاد چنین مدلی بپردازیم، اجازه دهید ابتدا به طور خلاصه مجموعه داده ای را که قرار است استفاده کنیم مرور کنیم.
مجموعه داده
مجموعه داده های این مقاله را می توانید از اینجا دانلود کنید لینک کاگل. مجموعه داده شامل چندین فایل است، اما ما فقط به آن علاقه داریم yelp_review.csv
فایل. این فایل حاوی بیش از 5.2 میلیون بررسی در مورد مشاغل مختلف از جمله رستوران ها، کافه ها، دندانپزشکان، پزشکان، سالن های زیبایی و غیره است. برای اهداف خود، ما فقط از 50000 رکورد اول برای آموزش مدل خود استفاده خواهیم کرد. مجموعه داده را در دستگاه محلی خود دانلود کنید.
اول بیایید import تمام کتابخانه هایی که در این مقاله قبل از وارد کردن مجموعه داده استفاده خواهیم کرد.
from numpy import array
from keras.preprocessing.text import one_hot
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers.core import Activation, Dropout, Dense
from keras.layers import Flatten, LSTM
from keras.layers import GlobalMaxPooling1D
from keras.models import Model
from keras.layers.embeddings import Embedding
from sklearn.model_selection import train_test_split
from keras.preprocessing.text import Tokenizer
from keras.layers import Input
from keras.layers.merge import Concatenate
import pandas as pd
import numpy as np
import re
به عنوان اولین قدم، باید مجموعه داده را بارگذاری کنیم. اسکریپت زیر این کار را انجام می دهد:
yelp_reviews = pd.read_csv("/content/drive/My Drive/yelp_review_short.csv")
مجموعه داده شامل یک ستون است Stars
که دارای رتبه بندی برای مشاغل مختلف است. ستون “ستاره ها” می تواند مقادیری بین 1 تا 5 داشته باشد. ما یک ستون جدید اضافه می کنیم reviews_score
به مجموعه داده ما اگر نظر کاربر دارای مقدار 1 در است Stars
ستون، reviews_score
ستون یک مقدار رشته ای خواهد داشت bad
. اگر امتیاز 2 یا 3 باشد Stars
ستون، reviews_score
ستون حاوی یک مقدار خواهد بود average
. در نهایت، رتبه بررسی 4 یا 5 دارای مقدار مربوطه خواهد بود good
در reviews_score
ستون
اسکریپت زیر این پیش پردازش را انجام می دهد:
bins = (0,1,3,5)
review_names = ('bad', 'average', 'good')
yelp_reviews('reviews_score') = pd.cut(yelp_reviews('stars'), bins, labels=review_names)
در مرحله بعد، تمام مقادیر NULL را از دیتافریم خود حذف می کنیم و اراده می کنیم print شکل و هدر مجموعه داده
yelp_reviews.isnull().values.any()
print(yelp_reviews.shape)
yelp_reviews.head()
در خروجی مشاهده خواهید کرد (50000,10)
، به این معنی که مجموعه داده ما شامل 50000 رکورد با 10 ستون است. هدر از yelp_reviews
دیتافریم به شکل زیر است:
می توانید 10 ستونی را که دیتافریم ما شامل می شود، از جمله ستون هایی که به تازگی اضافه شده است، مشاهده کنید reviews_score
ستون این text
ستون حاوی متن بررسی است در حالی که useful
ستون حاوی مقدار عددی است که نشان دهنده تعداد افرادی است که این بررسی را مفید می دانند. به طور مشابه، funny
و cool
ستون ها شامل تعداد افرادی است که نظرات را پیدا کرده اند funny
یا cool
، به ترتیب.
بیایید به طور تصادفی یک بررسی را انتخاب کنیم. اگر به بررسی چهارم (بررسی با نمایه 3) نگاه کنید، دارای 4 ستاره است و از این رو به عنوان علامت گذاری شده است. good
. بیایید متن کامل این بررسی را مشاهده کنیم:
print(yelp_reviews("text")(3))
خروجی به صورت زیر است:
Love coming here. Yes the place always needs the floor swept but when you give out peanuts in the shell how won't it always be a bit dirty.
The food speaks for itself, so good. Burgers are made to order and the meat is put روی the grill when you order your sandwich. Getting the small burger just means 1 patty, the regular is a 2 patty burger which is twice the deliciousness.
Getting the Cajun fries adds a bit of spice to them and whatever size you order they always throw more fries (a lot more fries) into the bag.
شما به وضوح می بینید که این یک بررسی مثبت است.
حالا بیایید تعداد را رسم کنیم good
، average
، و bad
بررسی ها
import seaborn as sns
sns.countplot(x='reviews_score', data=yelp_reviews)
از طرح بالا مشهود است که اکثر بررسی ها خوب هستند و پس از آن میانگین نقدها قرار دارند. تعداد نقدهای منفی بسیار کم است.
ما داده های خود را از قبل پردازش کرده ایم و اکنون در این مقاله سه مدل ایجاد می کنیم. مدل اول فقط از ورودیهای متنی برای پیشبینی اینکه آیا بازبینی است استفاده میکند good
، average
، یا bad
. در مدل دوم از متن استفاده نمی کنیم. ما فقط از اطلاعات متا مانند useful
، funny
، و cool
برای پیش بینی احساس بررسی در نهایت، مدلی ایجاد خواهیم کرد که ورودی های متعددی مانند متن و اطلاعات متا را برای طبقه بندی متن می پذیرد.
ایجاد یک مدل فقط با ورودی های متن
اولین گام، تعریف تابعی است که داده های متنی را پاک می کند.
def preprocess_text(sen):
sentence = re.sub('(^a-zA-Z)', ' ', sen)
sentence = re.sub(r"\s+(a-zA-Z)\s+", ' ', sentence)
sentence = re.sub(r'\s+', ' ', sentence)
return sentence
از آنجایی که در این مدل فقط از متن استفاده می کنیم، تمام بررسی های متن را فیلتر کرده و در لیست ذخیره می کنیم. مرورهای متن با استفاده از preprocess_text
تابع، که علائم نگارشی و اعداد را از متن حذف می کند.
X = ()
sentences = list(yelp_reviews("text"))
for sen in sentences:
X.append(preprocess_text(sen))
y = yelp_reviews('reviews_score')
ما X
متغیر در اینجا شامل بررسی متن است در حالی که y
متغیر شامل موارد مربوطه است reviews_score
ارزش های. این reviews_score
ستون دارای داده در قالب متن است. ما باید متن را به یک بردار رمزگذاری شده یک داغ تبدیل کنیم. ما می توانیم استفاده کنیم to_categorical
روش از keras.utils
مدول. با این حال، ابتدا باید متن را با استفاده از برچسب به عدد صحیح تبدیل کنیم LabelEncoder
تابع از sklearn.preprocessing
مدول.
from sklearn import preprocessing
label_encoder = preprocessing.LabelEncoder()
y = label_encoder.fit_transform(y)
بیایید اکنون داده های خود را به مجموعه های آزمایشی و آموزشی تقسیم کنیم:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
اکنون میتوانیم برچسبهای آموزشی و آزمایشی را به بردارهای رمزگذاری شده یکطرفه تبدیل کنیم:
from keras.utils import to_categorical
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
در مقاله ام توضیح دادم روی تعبیههای کلمهای که دادههای متنی باید به نوعی شکل عددی تبدیل شوند تا بتوانند توسط الگوریتمهای آماری مانند مدلهای یادگیری ماشینی و عمیق استفاده شوند. یکی از راه های تبدیل متن به اعداد از طریق جاسازی کلمه است. اگر از روش پیاده سازی جاسازی کلمه از طریق Keras بی اطلاع هستید، به شدت توصیه می کنم قبل از حرکت این مقاله را بخوانید. روی به بخش های بعدی کد.
اولین گام در جاسازی کلمات، تبدیل کلمات به نمایه های عددی مربوط به آنهاست. برای این کار می توانیم از Tokenizer
کلاس از Keras.preprocessing.text
مدول.
tokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(X_train)
X_train = tokenizer.texts_to_sequences(X_train)
X_test = tokenizer.texts_to_sequences(X_test)
جملات می توانند طول های متفاوتی داشته باشند، و بنابراین دنباله هایی که توسط the برگردانده می شوند Tokenizer
کلاس نیز از طول های متغیر تشکیل شده است. ما مشخص می کنیم که حداکثر طول دنباله 200 باشد (البته می توانید هر عددی را امتحان کنید). برای جملاتی که طول آنها کمتر از 200 است، شاخص های باقیمانده با صفر پر می شوند. برای جملاتی که طول آنها بیشتر از 200 باشد، شاخص های باقیمانده کوتاه می شوند.
به اسکریپت زیر نگاه کنید:
vocab_size = len(tokenizer.word_index) + 1
maxlen = 200
X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)
X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)
بعد، ما باید داخلی را بارگذاری کنیم دستکش جاسازی کلمات
from numpy import array
from numpy import asarray
from numpy import zeros
embeddings_dictionary = dict()
for line in glove_file:
records = line.split()
word = records(0)
vector_dimensions = asarray(records(1:), dtype='float32')
embeddings_dictionary (word) = vector_dimensions
glove_file.close()
در نهایت یک ماتریس جاسازی ایجاد می کنیم که در آن ردیف ها برابر با تعداد کلمات موجود در واژگان (به اضافه 1) خواهد بود. تعداد ستون ها 100 خواهد بود زیرا هر کلمه در جاسازی کلمه GloVe که بارگذاری کردیم به عنوان یک بردار 100 بعدی نشان داده می شود.
embedding_matrix = zeros((vocab_size, 100))
for word, index in tokenizer.word_index.items():
embedding_vector = embeddings_dictionary.get(word)
if embedding_vector is not None:
embedding_matrix(index) = embedding_vector
پس از اتمام مرحله embedding کلمه، ما آماده ایجاد مدل خود هستیم. ما از API عملکردی Keras برای ایجاد مدل خود استفاده خواهیم کرد. اگرچه مدلهای ورودی تکی مانند مدلی که اکنون ایجاد میکنیم را میتوان با استفاده از API متوالی نیز توسعه داد، اما همانطور که در بخش بعدی میخواهیم یک مدل ورودی چندگانه را توسعه دهیم که فقط با استفاده از API عملکردی Keras قابل توسعه است، ما به تابعی میمانیم. API در این بخش نیز وجود دارد.
ما یک مدل بسیار ساده با یک لایه ورودی (لایه جاسازی)، یک لایه LSTM با 128 نورون و یک لایه متراکم ایجاد خواهیم کرد که به عنوان لایه خروجی نیز عمل خواهد کرد. از آنجایی که ما 3 خروجی ممکن داریم، تعداد نورون ها 3 و تابع فعال سازی خواهد بود softmax
. ما استفاده خواهیم کرد categorical_crossentropy
به عنوان تابع ضرر ما و adam
به عنوان تابع بهینه سازی
deep_inputs = Input(shape=(maxlen,))
embedding_layer = Embedding(vocab_size, 100, weights=(embedding_matrix), trainable=False)(deep_inputs)
LSTM_Layer_1 = LSTM(128)(embedding_layer)
dense_layer_1 = Dense(3, activation='softmax')(LSTM_Layer_1)
model = Model(inputs=deep_inputs, outputs=dense_layer_1)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=('acc'))
اجازه دهید print خلاصه مدل ما:
print(model.summary())
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 200) 0
_________________________________________________________________
embedding_1 (Embedding) (None, 200, 100) 5572900
_________________________________________________________________
lstm_1 (LSTM) (None, 128) 117248
_________________________________________________________________
dense_1 (Dense) (None, 3) 387
=================================================================
Total params: 5,690,535
Trainable params: 117,635
Non-trainable params: 5,572,900
در نهایت، اجازه می دهد print بلوک دیاگرام شبکه عصبی ما:
from keras.utils import plot_model
plot_model(model, to_file='model_plot1.png', show_shapes=True, show_layer_names=True)
پرونده model_plot1.png
در مسیر فایل محلی شما ایجاد خواهد شد. اگر تصویر را باز کنید به شکل زیر در می آید:
می بینید که مدل دارای 1 لایه ورودی، 1 لایه تعبیه شده، 1 LSTM و یک لایه متراکم است که به عنوان لایه خروجی نیز عمل می کند.
حال بیایید مدل خود را آموزش دهیم:
history = model.fit(X_train, y_train, batch_size=128, epochs=10, verbose=1, validation_split=0.2)
مدل آموزش داده خواهد شد روی 80 درصد از داده های قطار و اعتبارسنجی خواهد شد روی 20 درصد از داده های قطار. نتایج برای 10 دوره به شرح زیر است:
Train روی 32000 samples, validate روی 8000 samples
Epoch 1/10
32000/32000 (==============================) - 81s 3ms/step - loss: 0.8640 - acc: 0.6623 - val_loss: 0.8356 - val_acc: 0.6730
Epoch 2/10
32000/32000 (==============================) - 80s 3ms/step - loss: 0.8508 - acc: 0.6618 - val_loss: 0.8399 - val_acc: 0.6690
Epoch 3/10
32000/32000 (==============================) - 84s 3ms/step - loss: 0.8461 - acc: 0.6647 - val_loss: 0.8374 - val_acc: 0.6726
Epoch 4/10
32000/32000 (==============================) - 82s 3ms/step - loss: 0.8288 - acc: 0.6709 - val_loss: 0.7392 - val_acc: 0.6861
Epoch 5/10
32000/32000 (==============================) - 82s 3ms/step - loss: 0.7444 - acc: 0.6804 - val_loss: 0.6371 - val_acc: 0.7311
Epoch 6/10
32000/32000 (==============================) - 83s 3ms/step - loss: 0.5969 - acc: 0.7484 - val_loss: 0.5602 - val_acc: 0.7682
Epoch 7/10
32000/32000 (==============================) - 82s 3ms/step - loss: 0.5484 - acc: 0.7623 - val_loss: 0.5244 - val_acc: 0.7814
Epoch 8/10
32000/32000 (==============================) - 86s 3ms/step - loss: 0.5052 - acc: 0.7866 - val_loss: 0.4971 - val_acc: 0.7950
Epoch 9/10
32000/32000 (==============================) - 84s 3ms/step - loss: 0.4753 - acc: 0.8032 - val_loss: 0.4839 - val_acc: 0.7965
Epoch 10/10
32000/32000 (==============================) - 82s 3ms/step - loss: 0.4539 - acc: 0.8110 - val_loss: 0.4622 - val_acc: 0.8046
می بینید که دقت آموزشی نهایی مدل 81.10 درصد است در حالی که دقت اعتبارسنجی 80.46 است. تفاوت بسیار کوچک است و بنابراین ما فرض می کنیم که مدل ما بیش از حد مناسب نیست روی داده های آموزشی
حال بیایید عملکرد مدل خود را ارزیابی کنیم روی مجموعه تست:
score = model.evaluate(X_test, y_test, verbose=1)
print("Test Score:", score(0))
print("Test Accuracy:", score(1))
خروجی به شکل زیر است:
10000/10000 (==============================) - 37s 4ms/step
Test Score: 0.4592904740810394
Test Accuracy: 0.8101
در نهایت، بیایید مقادیر از دست دادن و دقت را برای مجموعه های آموزشی و آزمایشی ترسیم کنیم:
import matplotlib.pyplot as plt
plt.plot(history.history('acc'))
plt.plot(history.history('val_acc'))
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(('train','test'), loc='upper left')
plt.show()
plt.plot(history.history('loss'))
plt.plot(history.history('val_loss'))
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(('train','test'), loc='upper left')
plt.show()
شما باید دو نمودار زیر را ببینید:
شما می توانید خطوط را برای دقت آموزش و تست و تلفات بسیار نزدیک به یکدیگر مشاهده کنید که به این معنی است که مدل بیش از حد مناسب نیست.
در این بخش، یک مدل طبقه بندی ایجاد می کنیم که از اطلاعات موجود در آن استفاده می کند useful
، funny
، و cool
ستون های بررسی yelp. از آنجایی که دادههای این ستونها به خوبی ساختار یافتهاند و حاوی هیچ الگوی ترتیبی یا فضایی نیستند، میتوانیم از شبکههای عصبی متصل متراکم ساده برای پیشبینی استفاده کنیم.
بیایید میانگین شمارش ها را ترسیم کنیم useful
، funny
، و cool
بررسی ها در مقابل نمره بازبینی
import seaborn as sns
sns.barplot(x='reviews_score', y='useful', data=yelp_reviews)
از خروجی، میتوانید ببینید که میانگین تعداد نظرات بهعنوان علامتگذاری شده است useful
برای نقدهای بد، بالاترین رتبه است و پس از آن میانگین نظرات و نقدهای خوب قرار دارند.
حالا بیایید میانگین شمارش را رسم کنیم funny
بررسی ها:
sns.barplot(x='reviews_score', y='funny', data=yelp_reviews)
خروجی نشان می دهد که مجدداً، میانگین تعداد نظرات به عنوان علامت گذاری شده است funny
بالاترین برای بررسی های بد است.
در نهایت، بیایید مقدار میانگین را ترسیم کنیم cool
ستون مقابل reviews_score
ستون ما انتظار داریم که میانگین شمارش برای cool
ستون برای بررسی های خوب بالاترین خواهد بود زیرا مردم اغلب نظرات مثبت یا خوب را به عنوان جالب علامت گذاری می کنند:
sns.barplot(x='reviews_score', y='cool', data=yelp_reviews)
همانطور که انتظار می رود، میانگین cool
شمارش برای بررسی خوب بالاترین است. از این اطلاعات، می توانیم با خیال راحت فرض کنیم که تعداد مقادیر برای useful
، funny
، و cool
ستون ها تا حدودی با reviews_score
ستون ها. بنابراین، ما سعی خواهیم کرد از داده های این سه ستون برای آموزش الگوریتم خود استفاده کنیم که مقدار را برای reviews_score
ستون
بیایید این سه ستون را از مجموعه داده خود فیلتر کنیم:
yelp_reviews_meta = yelp_reviews(('useful', 'funny', 'cool'))
X = yelp_reviews_meta.values
y = yelp_reviews('reviews_score')
در مرحله بعد، ما برچسبهای خود را به مقادیر رمزگذاری شده تبدیل میکنیم و سپس دادههای خود را به مجموعههای قطار و آزمایش تقسیم میکنیم:
from sklearn import preprocessing
label_encoder = preprocessing.LabelEncoder()
y = label_encoder.fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
from keras.utils import to_categorical
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
مرحله بعدی ایجاد مدل ما است. مدل ما از چهار لایه تشکیل شده است (شما می توانید هر عددی را امتحان کنید): لایه ورودی، دو لایه پنهان متراکم با 10 نورون و عملکردهای فعال سازی ReLU، و در نهایت یک لایه متراکم خروجی با 3 نورون و تابع فعال سازی softmax. تابع ضرر و بهینه ساز خواهد بود categorical_crossentropy
و adam
، به ترتیب.
اسکریپت زیر مدل را تعریف می کند:
input2 = Input(shape=(3,))
dense_layer_1 = Dense(10, activation='relu')(input2)
dense_layer_2 = Dense(10, activation='relu')(dense_layer_1)
output = Dense(3, activation='softmax')(dense_layer_2)
model = Model(inputs=input2, outputs=output)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=('acc'))
اجازه دهید print خلاصه مدل:
print(model.summary())
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 3) 0
_________________________________________________________________
dense_1 (Dense) (None, 10) 40
_________________________________________________________________
dense_2 (Dense) (None, 10) 110
_________________________________________________________________
dense_3 (Dense) (None, 3) 33
=================================================================
Total params: 183
Trainable params: 183
Non-trainable params: 0
در نهایت، بلوک دیاگرام برای مدل را می توان از طریق اسکریپت زیر ایجاد کرد:
from keras.utils import plot_model
plot_model(model, to_file='model_plot2.png', show_shapes=True, show_layer_names=True)
حالا اگر در را باز کنید model_plot2.png
فایل از مسیر فایل محلی شما، به صورت زیر است:
حالا بیایید مدل و print مقادیر دقت و ضرر برای هر دوره:
history = model.fit(X_train, y_train, batch_size=16, epochs=10, verbose=1, validation_split=0.2)
Train روی 32000 samples, validate روی 8000 samples
Epoch 1/10
32000/32000 (==============================) - 8s 260us/step - loss: 0.8429 - acc: 0.6649 - val_loss: 0.8166 - val_acc: 0.6734
Epoch 2/10
32000/32000 (==============================) - 7s 214us/step - loss: 0.8203 - acc: 0.6685 - val_loss: 0.8156 - val_acc: 0.6737
Epoch 3/10
32000/32000 (==============================) - 7s 217us/step - loss: 0.8187 - acc: 0.6685 - val_loss: 0.8150 - val_acc: 0.6736
Epoch 4/10
32000/32000 (==============================) - 7s 220us/step - loss: 0.8183 - acc: 0.6695 - val_loss: 0.8160 - val_acc: 0.6740
Epoch 5/10
32000/32000 (==============================) - 7s 227us/step - loss: 0.8177 - acc: 0.6686 - val_loss: 0.8149 - val_acc: 0.6751
Epoch 6/10
32000/32000 (==============================) - 7s 219us/step - loss: 0.8175 - acc: 0.6686 - val_loss: 0.8157 - val_acc: 0.6744
Epoch 7/10
32000/32000 (==============================) - 7s 216us/step - loss: 0.8172 - acc: 0.6696 - val_loss: 0.8145 - val_acc: 0.6733
Epoch 8/10
32000/32000 (==============================) - 7s 214us/step - loss: 0.8175 - acc: 0.6689 - val_loss: 0.8139 - val_acc: 0.6734
Epoch 9/10
32000/32000 (==============================) - 7s 215us/step - loss: 0.8169 - acc: 0.6691 - val_loss: 0.8160 - val_acc: 0.6744
Epoch 10/10
32000/32000 (==============================) - 7s 216us/step - loss: 0.8167 - acc: 0.6694 - val_loss: 0.8138 - val_acc: 0.6736
از خروجی، می توانید ببینید که مدل ما همگرا نیست و مقادیر دقت در تمام دوره ها بین 66 و 67 باقی می ماند.
بیایید ببینیم که مدل چگونه عمل می کند روی مجموعه تست:
score = model.evaluate(X_test, y_test, verbose=1)
print("Test Score:", score(0))
print("Test Accuracy:", score(1))
10000/10000 (==============================) - 0s 34us/step
Test Score: 0.8206425309181213
Test Accuracy: 0.6669
ما میتوانیم print مقادیر از دست دادن و دقت برای مجموعه های آموزشی و آزمایشی از طریق اسکریپت زیر:
import matplotlib.pyplot as plt
plt.plot(history.history('acc'))
plt.plot(history.history('val_acc'))
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(('train','test'), loc='upper left')
plt.show()
plt.plot(history.history('loss'))
plt.plot(history.history('val_loss'))
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(('train','test'), loc='upper left')
plt.show()
از خروجی، می توانید ببینید که مقادیر دقت نسبتاً کمتر است. از این رو، می توان گفت که مدل ما کمتر برازنده است. دقت را می توان با افزایش تعداد لایه های متراکم یا با افزایش تعداد دوره ها افزایش داد، با این حال من آن را به شما واگذار می کنم.
بیا حرکت کنیم روی به آخرین و مهمترین بخش این مقاله که در آن از چندین ورودی از انواع مختلف برای آموزش مدل خود استفاده خواهیم کرد.
ایجاد یک مدل با ورودی های متعدد
در بخشهای قبلی، روش آموزش مدلهای یادگیری عمیق با استفاده از دادههای متنی یا متا را دیدیم. اگر بخواهیم اطلاعات متنی را با هم ترکیب کنیم چه؟ با اطلاعات متا و استفاده از آن به عنوان ورودی مدل خود؟ ما می توانیم این کار را با استفاده از API عملکردی Keras انجام دهیم. در این قسمت دو مدل فرعی ایجاد می کنیم.
اولین مدل فرعی ورودی متنی را در قالب بررسی متنی می پذیرد. این مدل فرعی از یک لایه شکل ورودی، یک لایه جاسازی و یک لایه LSTM از 128 نورون تشکیل شده است. مدل فرعی دوم ورودی را به شکل متا اطلاعات از طرف می پذیرد useful
، funny
، و cool
ستون ها. مدل فرعی دوم نیز از سه لایه تشکیل شده است. یک لایه ورودی و دو لایه متراکم.
خروجی لایه LSTM زیرمدل اول و خروجی لایه متراکم دوم از زیرمدل دوم به یکدیگر متصل می شوند و به عنوان ورودی پیوسته به لایه متراکم دیگری با 10 نورون استفاده می شوند. در نهایت، لایه متراکم خروجی دارای سه نورون مربوط به هر نوع بررسی خواهد بود.
بیایید ببینیم چگونه می توانیم چنین مدل پیوسته ای ایجاد کنیم.
ابتدا باید دو نوع ورودی مختلف ایجاد کنیم. برای انجام این کار، مانند شکل زیر، داده های خود را به یک مجموعه ویژگی و مجموعه برچسب تقسیم می کنیم:
X = yelp_reviews.drop('reviews_score', axis=1)
y = yelp_reviews('reviews_score')
این X
متغیر شامل مجموعه ویژگی است، در حالی که y
متغیر شامل مجموعه برچسب است. ما باید برچسب های خود را به بردارهای رمزگذاری شده یک داغ تبدیل کنیم. ما می توانیم این کار را با استفاده از رمزگذار برچسب و کد انجام دهیم to_categorical
عملکرد از keras.utils
مدول. ما همچنین داده های خود را به مجموعه های آموزشی و ویژگی ها تقسیم می کنیم.
from sklearn import preprocessing
label_encoder = preprocessing.LabelEncoder()
y = label_encoder.fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
from keras.utils import to_categorical
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
اکنون مجموعه برچسب ما به شکل مورد نیاز است. از آنجایی که تنها یک خروجی وجود خواهد داشت، بنابراین نیازی به آن نداریم process مجموعه برچسب ما با این حال، چندین ورودی برای مدل وجود خواهد داشت. بنابراین، ما باید مجموعه ویژگی های خود را از قبل پردازش کنیم.
ابتدا بیایید ایجاد کنیم preproces_text
تابعی که برای پیش پردازش مجموعه داده ما استفاده می شود:
def preprocess_text(sen):
sentence = re.sub('(^a-zA-Z)', ' ', sen)
sentence = re.sub(r"\s+(a-zA-Z)\s+", ' ', sentence)
sentence = re.sub(r'\s+', ' ', sentence)
return sentence
به عنوان اولین قدم، ورودی متنی را برای مجموعه آموزشی و تست ایجاد می کنیم. به اسکریپت زیر نگاه کنید:
X1_train = ()
sentences = list(X_train("text"))
for sen in sentences:
X1_train.append(preprocess_text(sen))
اکنون X1_train
حاوی ورودی متنی مجموعه آموزشی است. به طور مشابه، اسکریپت زیر داده های ورودی متنی را برای مجموعه آزمایشی پیش پردازش می کند:
X1_test = ()
sentences = list(X_test("text"))
for sen in sentences:
X1_test.append(preprocess_text(sen))
اکنون باید ورودی متنی مجموعه های آموزشی و تست را با استفاده از جاسازی کلمه به شکل عددی تبدیل کنیم. اسکریپت زیر این کار را انجام می دهد:
tokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(X1_train)
X1_train = tokenizer.texts_to_sequences(X1_train)
X1_test = tokenizer.texts_to_sequences(X1_test)
vocab_size = len(tokenizer.word_index) + 1
maxlen = 200
X1_train = pad_sequences(X1_train, padding='post', maxlen=maxlen)
X1_test = pad_sequences(X1_test, padding='post', maxlen=maxlen)
ما دوباره از جاسازی کلمه GloVe برای ایجاد بردار کلمات استفاده خواهیم کرد:
from numpy import array
from numpy import asarray
from numpy import zeros
embeddings_dictionary = dict()
glove_file = open('/content/drive/My Drive/glove.6B.100d.txt', encoding="utf8")
for line in glove_file:
records = line.split()
word = records(0)
vector_dimensions = asarray(records(1:), dtype='float32')
embeddings_dictionary(word) = vector_dimensions
glove_file.close()
embedding_matrix = zeros((vocab_size, 100))
for word, index in tokenizer.word_index.items():
embedding_vector = embeddings_dictionary.get(word)
if embedding_vector is not None:
embedding_matrix(index) = embedding_vector
ما ورودی متنی خود را از قبل پردازش کرده ایم. نوع دوم ورودی متا اطلاعات موجود در useful
، funny
، و cool
ستون ها. ما این ستون ها را از مجموعه ویژگی فیلتر می کنیم تا ورودی متا برای آموزش الگوریتم ها ایجاد کنیم. به اسکریپت زیر نگاه کنید:
X2_train = X_train(('useful', 'funny', 'cool')).values
X2_test = X_test(('useful', 'funny', 'cool')).values
حال بیایید دو لایه ورودی خود را ایجاد کنیم. لایه ورودی اول برای وارد کردن ورودی متنی و لایه ورودی دوم برای ورود اطلاعات متا از سه ستون استفاده می شود.
input_1 = Input(shape=(maxlen,))
input_2 = Input(shape=(3,))
می بینید که اولین لایه ورودی است input_1
برای ورودی متنی استفاده می شود. اندازه شکل به شکل جمله ورودی تنظیم شده است. برای لایه ورودی دوم، شکل مربوط به سه ستون است.
بیایید اکنون اولین مدل فرعی را ایجاد کنیم که داده ها را از اولین لایه ورودی می پذیرد:
embedding_layer = Embedding(vocab_size, 100, weights=(embedding_matrix), trainable=False)(input_1)
LSTM_Layer_1 = LSTM(128)(embedding_layer)
به طور مشابه، اسکریپت زیر یک مدل فرعی دوم ایجاد می کند که ورودی لایه ورودی دوم را می پذیرد:
dense_layer_1 = Dense(10, activation='relu')(input_2)
dense_layer_2 = Dense(10, activation='relu')(dense_layer_1)
اکنون دو مدل فرعی داریم. کاری که می خواهیم انجام دهیم این است که خروجی زیرمدل اول را با خروجی زیرمدل دوم به هم پیوند دهیم. خروجی از مدل فرعی اول، خروجی از مدل فرعی است LSTM_Layer_1
و به طور مشابه، خروجی از زیرمدل دوم، خروجی از مدل فرعی است dense_layer_2
. ما می توانیم استفاده کنیم Concatenate
کلاس از keras.layers.merge
ماژول برای به هم پیوستن دو ورودی
اسکریپت زیر مدل نهایی ما را ایجاد می کند:
concat_layer = Concatenate()((LSTM_Layer_1, dense_layer_2))
dense_layer_3 = Dense(10, activation='relu')(concat_layer)
output = Dense(3, activation='softmax')(dense_layer_3)
model = Model(inputs=(input_1, input_2), outputs=output)
می بینید که اکنون مدل ما لیستی از ورودی ها با دو آیتم دارد. اسکریپت زیر مدل را کامپایل می کند و خلاصه آن را چاپ می کند:
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=('acc'))
print(model.summary())
خلاصه مدل به شرح زیر است:
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_1 (InputLayer) (None, 200) 0
__________________________________________________________________________________________________
input_2 (InputLayer) (None, 3) 0
__________________________________________________________________________________________________
embedding_1 (Embedding) (None, 200, 100) 5572900 input_1(0)(0)
__________________________________________________________________________________________________
dense_1 (Dense) (None, 10) 40 input_2(0)(0)
__________________________________________________________________________________________________
lstm_1 (LSTM) (None, 128) 117248 embedding_1(0)(0)
__________________________________________________________________________________________________
dense_2 (Dense) (None, 10) 110 dense_1(0)(0)
__________________________________________________________________________________________________
concatenate_1 (Concatenate) (None, 138) 0 lstm_1(0)(0)
dense_2(0)(0)
__________________________________________________________________________________________________
dense_3 (Dense) (None, 10) 1390 concatenate_1(0)(0)
__________________________________________________________________________________________________
dense_4 (Dense) (None, 3) 33 dense_3(0)(0)
==================================================================================================
Total params: 5,691,721
Trainable params: 118,821
Non-trainable params: 5,572,900
در نهایت، می توانیم مدل کامل شبکه را با استفاده از اسکریپت زیر رسم کنیم:
from keras.utils import plot_model
plot_model(model, to_file='model_plot3.png', show_shapes=True, show_layer_names=True)
اگر در را باز کنید model_plot3.png
فایل، باید نمودار شبکه زیر را ببینید:
شکل بالا به وضوح توضیح می دهد که چگونه چندین ورودی را در یک ورودی برای ایجاد مدل خود الحاق کرده ایم.
حالا بیایید مدل خود را آموزش دهیم و نتایج را ببینیم:
history = model.fit(x=(X1_train, X2_train), y=y_train, batch_size=128, epochs=10, verbose=1, validation_split=0.2)
در اینجا نتیجه 10 دوره است:
Train روی 32000 samples, validate روی 8000 samples
Epoch 1/10
32000/32000 (==============================) - 155s 5ms/step - loss: 0.9006 - acc: 0.6509 - val_loss: 0.8233 - val_acc: 0.6704
Epoch 2/10
32000/32000 (==============================) - 154s 5ms/step - loss: 0.8212 - acc: 0.6670 - val_loss: 0.8141 - val_acc: 0.6745
Epoch 3/10
32000/32000 (==============================) - 154s 5ms/step - loss: 0.8151 - acc: 0.6691 - val_loss: 0.8086 - val_acc: 0.6740
Epoch 4/10
32000/32000 (==============================) - 155s 5ms/step - loss: 0.8121 - acc: 0.6701 - val_loss: 0.8039 - val_acc: 0.6776
Epoch 5/10
32000/32000 (==============================) - 154s 5ms/step - loss: 0.8027 - acc: 0.6740 - val_loss: 0.7467 - val_acc: 0.6854
Epoch 6/10
32000/32000 (==============================) - 155s 5ms/step - loss: 0.6791 - acc: 0.7158 - val_loss: 0.5764 - val_acc: 0.7560
Epoch 7/10
32000/32000 (==============================) - 154s 5ms/step - loss: 0.5333 - acc: 0.7744 - val_loss: 0.5076 - val_acc: 0.7881
Epoch 8/10
32000/32000 (==============================) - 154s 5ms/step - loss: 0.4857 - acc: 0.7973 - val_loss: 0.4849 - val_acc: 0.7970
Epoch 9/10
32000/32000 (==============================) - 154s 5ms/step - loss: 0.4697 - acc: 0.8034 - val_loss: 0.4709 - val_acc: 0.8024
Epoch 10/10
32000/32000 (==============================) - 154s 5ms/step - loss: 0.4479 - acc: 0.8123 - val_loss: 0.4592 - val_acc: 0.8079
برای ارزیابی مدل خود، باید هر دو ورودی تست را به آن پاس کنیم evaluate
عملکرد مطابق شکل زیر:
score = model.evaluate(x=(X1_test, X2_test), y=y_test, verbose=1)
print("Test Score:", score(0))
print("Test Accuracy:", score(1))
در اینجا نتیجه است:
10000/10000 (==============================) - 18s 2ms/step
Test Score: 0.4576087875843048
Test Accuracy: 0.8053
دقت تست ما 80.53٪ است که کمی کمتر از اولین مدل ما است که فقط از ورودی متنی استفاده می کند. این نشان می دهد که اطلاعات متا در yelp_reviews
برای پیش بینی احساسات خیلی مفید نیست.
به هر حال، اکنون می دانید که چگونه مدل های ورودی چندگانه برای طبقه بندی متن در Keras ایجاد کنید!
در نهایت، اجازه دهید در حال حاضر print از دست دادن و دقت برای مجموعه های آموزشی و آزمایشی:
import matplotlib.pyplot as plt
plt.plot(history.history('acc'))
plt.plot(history.history('val_acc'))
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(('train','test'), loc='upper left')
plt.show()
plt.plot(history.history('loss'))
plt.plot(history.history('val_loss'))
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(('train','test'), loc='upper left')
plt.show()
میبینید که تفاوتها برای مقادیر تلفات و دقت بین مجموعههای آموزشی و تست حداقل است، بنابراین مدل ما بیش از حد مناسب نیست.
افکار نهایی و بهبودها
در این مقاله، ما یک شبکه عصبی بسیار ساده ساختیم زیرا هدف مقاله توضیح چگونگی ایجاد یک مدل یادگیری عمیق است که ورودی های متعدد از انواع مختلف را می پذیرد.
در زیر برخی از نکاتی وجود دارد که می توانید برای بهبود عملکرد مدل طبقه بندی متن دنبال کنید:
- ما فقط از 50000 رکورد از 5.2 میلیون رکورد در این مقاله استفاده کردیم زیرا محدودیت های سخت افزاری داشتیم. می توانید سعی کنید مدل خود را آموزش دهید روی تعداد رکوردهای بالاتری داشته باشید و ببینید آیا می توانید عملکرد بهتری داشته باشید یا خیر.
- سعی کنید LSTM و لایه های متراکم بیشتری را به مدل اضافه کنید. اگر مدل بیش از حد مناسب است، سعی کنید ترک تحصیل را اضافه کنید.
- سعی کنید عملکرد بهینه ساز را تغییر دهید و مدل را با تعداد دوره های بالاتر آموزش دهید.
لطفا نتایج خود را همراه با پیکربندی شبکه عصبی در قسمت نظرات به اشتراک بگذارید. خیلی دوست دارم ببینم چقدر خوب اجرا میکنی
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-20 20:57:04