وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

حل مسائل توالی با LSTM در Keras: قسمت 2

0 5
زمان لازم برای مطالعه: 10 دقیقه


این قسمت دوم و پایانی از سری مقالات دو قسمتی است روی حل مسائل توالی با LSTM در قسمت 1 مجموعه، روش حل مسائل توالی یک به یک و چند به یک را با استفاده از LSTM توضیح دادم. در این قسمت روش حل مسائل توالی یک به چند و چند به چند را از طریق LSTM در Keras خواهید دید.

زیرنویس تصویر یک مثال کلاسیک از مشکلات توالی یک به چند است که در آن شما یک تصویر واحد به عنوان ورودی دارید و باید توضیحات تصویر را در قالب یک دنباله کلمه پیش بینی کنید. به طور مشابه، پیش‌بینی بازار سهام برای روزهای X بعدی، که در آن ورودی قیمت سهام روزهای Y قبلی است، یک مثال کلاسیک از مشکلات توالی چند به چند است.

در این مقاله نمونه های بسیار ابتدایی مشکلات یک به چند و چند به چند را مشاهده خواهید کرد. با این حال، مفاهیم آموخته شده در این مقاله، پایه و اساس حل مشکلات توالی پیشرفته، مانند پیش بینی قیمت سهام و شرح خودکار تصاویر را که در مقالات آینده خواهیم دید، ایجاد خواهد کرد.

مشکلات توالی یک به چند

مسائل توالی یک به چند نوع مشکلات دنباله ای هستند که در آن داده های ورودی دارای یک مرحله زمانی هستند و خروجی شامل بردار چند مقدار یا چندین مرحله زمانی است. در این بخش، روش حل مسائل توالی یک به چند را در جایی که ورودی دارای یک ویژگی واحد است، خواهیم دید. سپس حرکت خواهیم کرد روی برای مشاهده روش کار با ورودی چند ویژگی برای حل مشکلات توالی یک به چند.

مشکلات توالی یک به چند با یک ویژگی واحد

بیایید ابتدا یک مجموعه داده ایجاد کنیم و مشکلی را که در این بخش حل می کنیم، درک کنیم.

ایجاد مجموعه داده

اسکریپت زیر کتابخانه های مورد نیاز را وارد می کند:

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
from keras.layers import Bidirectional

import pandas as pd
import numpy as np
import re

import matplotlib.pyplot as plt

و اسکریپت زیر مجموعه داده را ایجاد می کند:

X = list()
Y = list()
X = (x+3 for x in range(-2, 43, 3))

for i in X:
    output_vector = list()
    output_vector.append(i+1)
    output_vector.append(i+2)
    Y.append(output_vector)

print(X)
print(Y)

در اینجا خروجی است:

(1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43)
((2, 3), (5, 6), (8, 9), (11, 12), (14, 15), (17, 18), (20, 21), (23, 24), (26, 27), (29, 30), (32, 33), (35, 36), (38, 39), (41, 42), (44, 45))

ورودی ما شامل 15 نمونه با یک گام زمانی و یک مقدار ویژگی است. برای هر مقدار در نمونه ورودی، بردار خروجی مربوطه شامل دو عدد صحیح بعدی است. به عنوان مثال، اگر ورودی 4 باشد، بردار خروجی حاوی مقادیر 5 و 6 خواهد بود. بنابراین، مسئله یک مسئله ساده توالی یک به چند است.

اسکریپت زیر داده های ما را همانطور که توسط LSTM لازم است تغییر شکل می دهد:

X = np.array(X).reshape(15, 1, 1)
Y = np.array(Y)

اکنون می توانیم مدل های خود را آموزش دهیم. ما LSTM های ساده و پشته ای را آموزش خواهیم داد.

راه حل از طریق LSTM ساده

model = Sequential()
model.add(LSTM(50, activation='relu', input_shape=(1, 1)))
model.add(Dense(2))
model.compile(optimizer='adam', loss='mse')
model.fit(X, Y, epochs=1000, validation_split=0.2, batch_size=3)

زمانی که مدل آموزش داده شد، می‌توانیم پیش‌بینی کنیم روی داده های تست:

test_input = array((10))
test_input = test_input.reshape((1, 1, 1))
test_output = model.predict(test_input, verbose=0)
print(test_output)

داده های تست حاوی مقدار 10 است. در خروجی باید بردار حاوی 11 و 12 را دریافت کنیم. خروجی که دریافت کردم (10.982891 12.109697) است که در واقع بسیار نزدیک به خروجی مورد انتظار است.

راه حل از طریق Stacked LSTM

اسکریپت های زیر LSTM ها را روی هم چیده اند روی داده های ما را پیش بینی می کند روی نکات آزمون:

model = Sequential()
model.add(LSTM(50, activation='relu', return_sequences=True, input_shape=(1, 1)))
model.add(LSTM(50, activation='relu'))
model.add(Dense(2))
model.compile(optimizer='adam', loss='mse')
history = model.fit(X, Y, epochs=1000, validation_split=0.2, verbose=1, batch_size=3)

test_output = model.predict(test_input, verbose=0)
print(test_output)

پاسخ (11.00432 11.99205) است که بسیار نزدیک به خروجی واقعی است.

راه حل از طریق دو جهته LSTM

اسکریپت زیر یک LSTM دو طرفه را آموزش می دهد روی داده های ما و سپس پیش بینی می کند روی مجموعه تست

from keras.layers import Bidirectional

model = Sequential()
model.add(Bidirectional(LSTM(50, activation='relu'), input_shape=(1, 1)))
model.add(Dense(2))
model.compile(optimizer='adam', loss='mse')

history = model.fit(X, Y, epochs=1000, validation_split=0.2, verbose=1, batch_size=3)
test_output = model.predict(test_input, verbose=0)
print(test_output)

خروجی ای که دریافت کردم (11.035181 12.082813) است.

مشکلات توالی یک به چند با چندین ویژگی

در این بخش مشکلات توالی یک به چند را مشاهده خواهیم کرد که در آن نمونه های ورودی یک مرحله زمانی، اما دو ویژگی دارند. خروجی بردار دو عنصر خواهد بود.

ایجاد مجموعه داده

مثل همیشه، اولین قدم ایجاد مجموعه داده است:

nums = 25

X1 = list()
X2 = list()
X = list()
Y = list()

X1 = ((x+1)*2 for x in range(25))
X2 = ((x+1)*3 for x in range(25))

for x1, x2 in zip(X1, X2):
    output_vector = list()
    output_vector.append(x1+1)
    output_vector.append(x2+1)
    Y.append(output_vector)

X = np.column_stack((X1, X2))
print(X)

مجموعه داده ورودی ما به این صورت است:

(( 2  3)
 ( 4  6)
 ( 6  9)
 ( 8 12)
 (10 15)
 (12 18)
 (14 21)
 (16 24)
 (18 27)
 (20 30)
 (22 33)
 (24 36)
 (26 39)
 (28 42)
 (30 45)
 (32 48)
 (34 51)
 (36 54)
 (38 57)
 (40 60)
 (42 63)
 (44 66)
 (46 69)
 (48 72)
 (50 75))

می توانید ببینید که هر مرحله زمانی ورودی شامل دو ویژگی است. خروجی یک بردار خواهد بود که شامل دو عنصر بعدی است که با دو ویژگی در مرحله زمانی نمونه ورودی مطابقت دارند. به عنوان مثال، برای نمونه ورودی (2, 3)، خروجی خواهد بود (3, 4)، و غیره روی.

بیایید داده های خود را دوباره شکل دهیم:

X = np.array(X).reshape(25, 1, 2)
Y = np.array(Y)

راه حل از طریق LSTM ساده

model = Sequential()
model.add(LSTM(50, activation='relu', input_shape=(1, 2)))
model.add(Dense(2))
model.compile(optimizer='adam', loss='mse')
model.fit(X, Y, epochs=1000, validation_split=0.2, batch_size=3)

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

test_input = array((40, 60))
test_input = test_input.reshape((1, 1, 2))
test_output = model.predict(test_input, verbose=0)
print(test_output)

ورودی (40، 60)، خروجی باید (41، 61) باشد. خروجی پیش بینی شده توسط LSTM ساده ما (40.946873 60.941723) است که بسیار نزدیک به خروجی مورد انتظار است.

راه حل از طریق Stacked LSTM

model = Sequential()
model.add(LSTM(50, activation='relu', return_sequences=True, input_shape=(1, 2)))
model.add(LSTM(50, activation='relu'))
model.add(Dense(2))
model.compile(optimizer='adam', loss='mse')
history = model.fit(X, Y, epochs=1000, validation_split=0.2, verbose=1, batch_size=3)

test_input = array((40, 60))
test_input = test_input.reshape((1, 1, 2))
test_output = model.predict(test_input, verbose=0)
print(test_output)

خروجی در این مورد: (40.978477 60.994644)

راه حل از طریق دو جهته LSTM

from keras.layers import Bidirectional

model = Sequential()
model.add(Bidirectional(LSTM(50, activation='relu'), input_shape=(1, 2)))
model.add(Dense(2))
model.compile(optimizer='adam', loss='mse')

history = model.fit(X, Y, epochs=1000, validation_split=0.2, verbose=1, batch_size=3)
test_output = model.predict(test_input, verbose=0)
print(test_output)

خروجی به دست آمده: (41.0975 61.159065)

مشکلات توالی چند به چند

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

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

مدل رمزگذار-رمزگشا

برای حل چنین مشکلات توالی، مدل رمزگذار – رمزگشا طراحی شده است. مدل رمزگذار-رمزگشا اساساً یک نام فانتزی برای معماری شبکه عصبی با دو لایه LSTM است.

لایه اول به عنوان یک لایه رمزگذار کار می کند و دنباله ورودی را رمزگذاری می کند. رمزگشا همچنین یک لایه LSTM است که سه ورودی را می پذیرد: دنباله کدگذاری شده از رمزگذار LSTM، حالت پنهان قبلی و ورودی فعلی. در طول آموزش، خروجی واقعی در هر مرحله زمانی برای آموزش مدل رمزگذار-رمزگشا استفاده می شود. هنگام انجام پیش بینی ها، خروجی رمزگذار، حالت پنهان فعلی و خروجی قبلی به عنوان ورودی برای پیش بینی در هر مرحله زمانی استفاده می شود. این مفاهیم زمانی قابل درک تر می شوند که آنها را در عمل در بخش بعدی مشاهده کنید.

مشکلات توالی چند به چند با یک ویژگی

در این بخش، مشکلات توالی چند به چند را از طریق مدل رمزگذار-رمزگشا حل خواهیم کرد، که در آن هر مرحله زمانی در نمونه ورودی دارای یک ویژگی است.

بیایید ابتدا مجموعه داده خود را ایجاد کنیم.

ایجاد مجموعه داده

X = list()
Y = list()
X = (x for x in range(5, 301, 5))
Y = (y for y in range(20, 316, 5))

X = np.array(X).reshape(20, 3, 1)
Y = np.array(Y).reshape(20, 3, 1)

ورودی X شامل 20 نمونه است که هر نمونه شامل 3 مرحله زمانی با یک ویژگی است. یک نمونه ورودی به این صورت است:

(((  5)
  ( 10)
  ( 15))

می بینید که نمونه ورودی شامل 3 مقدار است که اساساً 3 مضرب 5 متوالی هستند. دنباله خروجی مربوطه برای نمونه ورودی بالا به شرح زیر است:

((( 20)
  ( 25)
  ( 30))

خروجی شامل سه مضرب 5 متوالی بعدی است. می توانید ببینید که خروجی در این حالت با آنچه در قسمت های قبلی دیده ایم متفاوت است. برای مدل رمزگذار-رمزگشا، خروجی باید به فرمت سه بعدی حاوی تعداد نمونه، مراحل زمانی و ویژگی ها نیز تبدیل شود. این به این دلیل است که رمزگشا در هر مرحله زمانی یک خروجی تولید می کند.

ما مجموعه داده خود را ایجاد کرده ایم. مرحله بعدی آموزش مدل های ما است. ما مدل های LSTM پشته ای و LSTM دو طرفه را در بخش های زیر آموزش خواهیم داد.

راه حل از طریق Stacked LSTM

اسکریپت زیر مدل رمزگذار-رمزگشا را با استفاده از LSTM های پشته ای ایجاد می کند:

from keras.layers import RepeatVector
from keras.layers import TimeDistributed

model = Sequential()


model.add(LSTM(100, activation='relu', input_shape=(3, 1)))


model.add(RepeatVector(3))


model.add(LSTM(100, activation='relu', return_sequences=True))

model.add(TimeDistributed(Dense(1)))
model.compile(optimizer='adam', loss='mse')

print(model.summary())

در اسکریپت فوق اولین لایه LSTM لایه رمزگذار است.

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

بعد یک لایه رمزگشا داریم. از آنجایی که خروجی به صورت یک گام زمانی است که فرمت سه بعدی است return_sequences برای مدل رمزگشا تنظیم شده است True. را TimeDistributed لایه برای پیش بینی جداگانه خروجی برای هر مرحله زمانی استفاده می شود.

خلاصه مدل برای مدل رمزگذار-رمزگشا ایجاد شده در اسکریپت بالا به شرح زیر است:

Layer (type)                 Output Shape              Param #
=================================================================
lstm_40 (LSTM)               (None, 100)               40800
_________________________________________________________________
repeat_vector_7 (RepeatVecto (None, 3, 100)            0
_________________________________________________________________
lstm_41 (LSTM)               (None, 3, 100)            80400
_________________________________________________________________
time_distributed_7 (TimeDist (None, 3, 1)              101
=================================================================
Total params: 121,301
Trainable params: 121,301
Non-trainable params: 0

می بینید که بردار تکرار فقط خروجی رمزگذار را تکرار می کند و هیچ پارامتری برای آموزش ندارد.

اسکریپت زیر مدل رمزگذار-رمزگشای فوق را آموزش می دهد.

history = model.fit(X, Y, epochs=1000, validation_split=0.2, verbose=1, batch_size=3)

بیایید یک نقطه آزمایش ایجاد کنیم و ببینیم آیا مدل رمزگذار-رمزگشا ما قادر به پیش‌بینی خروجی چند مرحله‌ای است یا خیر. اسکریپت زیر را اجرا کنید:

test_input = array((300, 305, 310))
test_input = test_input.reshape((1, 3, 1))
test_output = model.predict(test_input, verbose=0)
print(test_output)

دنباله ورودی ما شامل سه مقدار مرحله زمانی 300، 305 و 310 است. خروجی باید سه مضرب بعدی 5 یعنی 315، 320 و 325 باشد. من خروجی زیر را دریافت کردم:

(((316.02878)
  (322.27145)
  (328.5536 )))

می بینید که خروجی به صورت سه بعدی است.

راه حل از طریق دو جهته LSTM

بیایید اکنون مدل رمزگذار-رمزگشا را با LSTM های دو طرفه ایجاد کنیم و ببینیم آیا می توانیم نتایج بهتری بگیریم:

from keras.layers import RepeatVector
from keras.layers import TimeDistributed

model = Sequential()
model.add(Bidirectional(LSTM(100, activation='relu', input_shape=(3, 1))))
model.add(RepeatVector(3))
model.add(Bidirectional(LSTM(100, activation='relu', return_sequences=True)))
model.add(TimeDistributed(Dense(1)))
model.compile(optimizer='adam', loss='mse')

history = model.fit(X, Y, epochs=1000, validation_split=0.2, verbose=1, batch_size=3)

اسکریپت فوق مدل رمزگذار-رمزگشا را از طریق LSTM دوطرفه آموزش می دهد. حالا بیایید پیش بینی کنیم روی نقطه آزمون یعنی (300، 305، 310).

test_output = model.predict(test_input, verbose=0)
print(test_output)

در اینجا خروجی است:

(((315.7526 )
  (321.47153)
  (327.94025)))

خروجی ای که من از طریق LSTM های دوطرفه دریافت کردم بهتر از آن چیزی است که از طریق مدل رمزگذار-رمزگشا مبتنی بر LSTM انباشته شده دریافت کردم.

مشکلات توالی چند به چند با چندین ویژگی

همانطور که ممکن است تا به حال حدس زده باشید، در مسائل توالی چند به چند، هر مرحله زمانی در نمونه ورودی حاوی چندین ویژگی است.

ایجاد مجموعه داده

بیایید یک مجموعه داده ساده برای مشکل خود ایجاد کنیم:

X = list()
Y = list()
X1 = (x1 for x1 in range(5, 301, 5))
X2 = (x2 for x2 in range(20, 316, 5))
Y = (y for y in range(35, 331, 5))

X = np.column_stack((X1, X2))

در اسکریپت بالا دو لیست ایجاد می کنیم X1 و X2. لیست X1 شامل تمام مضرب های 5 از 5 تا 300 (شامل) و لیست است X2 شامل تمام مضرب های 5 از 20 تا 315 (شامل). در نهایت، لیست Y، که اتفاقاً خروجی شامل تمام مضرب های 5 بین 35 و 330 (شامل) است. لیست ورودی نهایی X یک ادغام ستونی از X1 و X2.

مثل همیشه، باید ورودی خود را تغییر دهیم X و خروجی Y قبل از اینکه بتوان از آنها برای آموزش LSTM استفاده کرد.

X = np.array(X).reshape(20, 3, 2)
Y = np.array(Y).reshape(20, 3, 1)

می توانید ورودی را ببینید X به 20 نمونه از سه مرحله زمانی با 2 ویژگی تغییر شکل داده است که در آن خروجی به ابعاد مشابه اما با 1 ویژگی تغییر شکل داده است.

اولین نمونه از ورودی به این صورت است:

(( 5  20)
( 10  25)
( 15  30))

ورودی شامل 6 مضرب متوالی از عدد صحیح 5 است که هر کدام سه مضرب در دو ستون هستند. در اینجا خروجی مربوط به نمونه ورودی بالا آمده است:

(( 35)
( 40)
( 45))

همانطور که می بینید، خروجی شامل سه مضرب 5 متوالی بعدی است.

بیایید اکنون مدل رمزگذار-رمزگشای خود را برای یادگیری دنباله بالا آموزش دهیم. ابتدا یک رمزگذار رمزگذار مبتنی بر LSTM انباشته شده را آموزش خواهیم داد.

راه حل از طریق Stacked LSTM

اسکریپت زیر مدل LSTM انباشته شده را آموزش می دهد. می بینید که شکل ورودی اکنون (3، 2) مربوط به سه مرحله زمانی و دو ویژگی در ورودی است.

from keras.layers import RepeatVector
from keras.layers import TimeDistributed

model = Sequential()
model.add(LSTM(100, activation='relu', input_shape=(3, 2)))
model.add(RepeatVector(3))
model.add(LSTM(100, activation='relu', return_sequences=True))
model.add(TimeDistributed(Dense(1)))
model.compile(optimizer='adam', loss='mse')

history = model.fit(X, Y, epochs=1000, validation_split=0.2, verbose=1, batch_size=3)

بیایید اکنون یک نقطه آزمایش ایجاد کنیم که برای پیش بینی استفاده می شود.

X1 = (300, 305, 310)
X2 = (315, 320, 325)

test_input = np.column_stack((X1, X2))

test_input = test_input.reshape((1, 3, 2))
print(test_input)

نقطه تست به این صورت است:

(((300 315)
  (305 320)
  (310 325)))

خروجی واقعی نقطه تست بالا (330، 335، 340) است. بیایید ببینیم پیش‌بینی‌های مدل چیست:

test_output = model.predict(test_input, verbose=0)
print(test_output)

خروجی پیش بینی شده این است:

(((324.5786 )
  (328.89658)
  (335.67603)))

خروجی از درست بودن فاصله زیادی دارد.

راه حل از طریق دو جهته LSTM

بیایید اکنون مدل رمزگذار-رمزگشا را بر اساس آموزش دهیم روی LSTM های دو طرفه و ببینید آیا می توانیم نتایج بهبود یافته ای دریافت کنیم. اسکریپت زیر مدل را آموزش می دهد.

from keras.layers import RepeatVector
from keras.layers import TimeDistributed

model = Sequential()
model.add(Bidirectional(LSTM(100, activation='relu', input_shape=(3, 2))))
model.add(RepeatVector(3))
model.add(Bidirectional(LSTM(100, activation='relu', return_sequences=True)))
model.add(TimeDistributed(Dense(1)))
model.compile(optimizer='adam', loss='mse')

history = model.fit(X, Y, epochs=1000, validation_split=0.2, verbose=1, batch_size=3)

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

test_output = model.predict(test_input, verbose=0)
print(test_output)

در اینجا خروجی است:

(((330.49133)
  (335.35327)
  (339.64398)))

خروجی به دست آمده بسیار نزدیک به خروجی واقعی است (330، 335، 340). بنابراین LSTM دوطرفه ما از LSTM ساده بهتر عمل کرد.

نتیجه

این قسمت دوم مقاله من است روی “حل مسائل توالی با LSTM در کراس” (قسمت 1 اینجا). در این مقاله روش حل مسائل توالی یک به چند و چند به چند را در LSTM دیدید. همچنین دیدید که چگونه می توان از مدل رمزگذار-رمزگشا برای پیش بینی خروجی های چند مرحله ای استفاده کرد. مدل رمزگذار-رمزگشا در انواع برنامه های پردازش زبان طبیعی مانند ترجمه ماشین عصبی و توسعه ربات چت استفاده می شود.

در مقاله پیش رو شاهد کاربرد مدل رمزگذار-رمزگشا در NLP خواهیم بود.

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-20 09:50:04

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید