Kod ayrıntıları: İnsan beynini simüle etmek için Python ile RNN oluşturun

Bir cümleyi anladığınızda, her seferinde içindeki kelimeyi ve cümleyi kesinlikle yeniden anlamayacaksınız! Bunu anlamak kolaydır: insanlar hafızaya sahip oldukları için, bir makaleyi okurken, metin içeriğini bu kelimelerle ilgili önceki anlayışımıza göre kavrayacağız.

Peki, algoritma bu özelliği kopyalayabilir mi? Aslında en yakın teknoloji Sinir Ağı'dır (NN). Ne yazık ki, geleneksel NN bunu yapamaz. Örneğin: Bir videoda daha sonra ne olacağını tahmin etmek istediğinizde, geleneksel sinir ağlarının doğru sonuçlar üretmesi zordur.

Tekrarlayan Sinir Ağı (RNN) kavramı burada devreye giriyor. Günümüzde RNN, derin öğrenme alanında giderek daha popüler hale geliyor. RNN'nin bazı pratik uygulamaları şunları içerir:

· Konuşma tanıma

· Makine çevirisi

· Müzik oluşturma

· Elyazısı tanıma

· Dilbilgisi öğrenimi

Bu makale, tipik bir RNN modelinin temel unsurlarını hızlı bir şekilde gözden geçirecek, ardından problem ifadesini belirleyecek ve son olarak Python'da RNN modelini sıfırdan uygulayarak sorunu çözecektir.

Flashback: Tekrarlayan sinir ağları kavramının bir incelemesi

Tekrarlayan sinir ağları kavramını hızlıca gözden geçirelim.

Belirli bir şirketin hisse senetleri gibi sekans verileri örneklerini kullanacağız. Basit bir makine öğrenme modeli veya yapay sinir ağı, hisse senedi sayısı ve açılış değeri gibi bazı özelliklere göre hisse senedi fiyatlarını tahmin etmeyi öğrenebilir. Ayrıca fiyat, hisse senedinin önceki hafta ve haftalarda ne kadar iyi performans gösterdiğine de bağlıdır. Tüccarlar için, bu tarihsel veriler aslında tahminin ana belirleyicileridir.

Geleneksel ileri beslemeli sinir ağlarında, tüm test durumları bağımsız olarak kabul edilir. Hisse senedi fiyatlarını tahmin ederken, bunun uygunsuz olduğunu görebiliyor musunuz? NN modeli, önceki hisse senedi fiyatlarını dikkate almaz - iyi bir fikir değil!

Zamana duyarlı verilerle karşılaştığımızda, başka bir konsepte - Tekrarlayan Sinir Ağına (RNN) güvenebiliriz!

Tipik bir RNN şuna benzer:

Bu ilk bakışta korkutucu görünebilir. Ancak bir kez başladıktan sonra işler kolaylaşmaya başladı:

Şimdi, bu ağların hisse senedi fiyatlarının trendini nasıl değerlendirdiğini daha kolay hayal edebiliriz, bu da günün fiyatını tahmin etmeye yardımcı olur. Burada, t (h_t) zamanındaki her tahmin önceki tüm tahminlere ve onlardan öğrenilen bilgilere bağlıdır. Oldukça basit, değil mi?

RNN, dizi işlemenin amacını büyük ölçüde çözebilir, ancak tamamen çözemez.

Metin, sıra verilerinin başka bir güzel örneğidir. Belirli bir metinden sonra görünecek kelimeleri veya cümleleri tahmin edebilmek çok faydalı bir varlık olabilir. Modelin Shakespeare'in sonelerini yazabileceğini umuyoruz!

Şimdi, kısa veya küçük ortamlar söz konusu olduğunda RNN'ler harikadır. Fakat bir hikaye yapabilmek ve hatırlayabilmek için modelin tıpkı bir insan beyni gibi sekansın arkasındaki arka planı anlayabilmesi gerekir.

Sekans tahmini için RNN kullanın

Bu yazıda, sıra tahmin problemleriyle başa çıkmak için RNN kullanacağız. Bunun için en basit görevlerden biri sinüs dalgası tahminidir. Sekans, görünür eğilimler içerir ve sezgisel yöntemler kullanılarak kolayca çözülebilir. Sinüs dalgası şuna benzer:

Bu sorunu çözmek için ilk olarak sıfırdan tekrarlayan bir sinir ağı tasarlayacağız. RNN modeli de diğer dizi problemlerine uygulayabilmemiz için iyi bir genelleme yapabilmelidir.

Bir sinüs dalgasına ait 50 sayıdan oluşan bir dizi verilen problemi aşağıdaki gibi formüle edeceğiz, serideki 51. sayıyı tahmin edeceğiz. Jupyter not defterini (veya seçtiğiniz IDE'yi) başlatma zamanı!

Python ile RNN Programlama

Adım 0: Veri hazırlama

Bu, herhangi bir veri bilimi projesinin kaçınılmaz ilk adımıdır - başka bir şey yapmadan önce verileri hazırlamak.

Ağ modelinin beklenen verileri nedir? Giriş olarak 50 uzunluğunda tek bir sıra kabul edecektir. Dolayısıyla, giriş verilerinin şekli şöyle olacaktır:

(number_of_records x length_of_sequence x types_of_sequences)

Burada, types_of_sequences 1'dir, çünkü yalnızca bir tür dizi sinüs dalgasına sahibiz.

Öte yandan, her kaydın çıktısının yalnızca bir değeri vardır. Bu elbette giriş dizisindeki 51. değerdir. Yani şekli şöyle olacak:

(number_of_records x types_of_sequences) # where types_of_sequences 1

Kodu inceleyelim. İlk önce gerekli kitaplıkları içe aktarın:

% pylab satır içi

matematik ithal etmek

Sinüs dalgası benzeri bir veri oluşturmak için Python matematik kütüphanesindeki sinüs fonksiyonunu kullanacağız:

sin_wave = np.array ()

Yeni oluşturulan sinüs dalgasını görselleştirin:

plt.plot (sin_wave)

Verileri aşağıdaki kod bloğunda oluşturacağız:

X =

Y =

seq_len = 50

num_records = len (sin_wave) -seq_len

aralıktaki i için (num_records-50):

X.append (sin_wave)

Y.append (sin_wave)

X = np.array (X)

X = np.expand_dims (X, eksen = 2)

Y = np.array (Y)

Y = np.expand_dims (Y, eksen = 1)

Baskı verilerinin şekli:

X.shape, Y.shape

((100, 50, 1), (100, 1))

Doğrulama verisi olarak 50 kaydı ayırmak istediğimiz için (num_records-50) için döngü yaptığımızı lütfen unutmayın. Artık bu doğrulama verilerini oluşturabiliriz:

X_val =

Y_val =

aralıktaki i için (num_records-50, num_records):

X_val.append (sin_wave)

Y_val.append (sin_wave)

X_val = np.array (X_val)

X_val = np.expand_dims (X_val, axis = 2)

Y_val = np.array (Y_val)

Y_val = np.expand_dims (Y_val, axis = 1)

Adım 1: RNN modeli için bir mimari oluşturun

Bir sonraki görev, RNN modelinde kullanılacak tüm gerekli değişkenleri ve fonksiyonları tanımlamaktır. Modelimiz bir girdi dizisini kabul edecek, onu 100 birimlik gizli bir katmanda işleyecek ve tek bir değer çıktısı üretecektir:

öğrenme_ hızı = 0.0001

nepoch = 25

T = 50 # dizi uzunluğu

hidden_dim = 100

output_dim = 1

bptt_truncate = 5

min_clip_value = -10

max_clip_value = 10

Ardından ağın ağırlığını tanımlayacağız:

U = np.random.uniform (0, 1, (gizli_dim, T))

W = np.random.uniform (0, 1, (gizli_dim, gizli_dim))

V = np.random.uniform (0, 1, (output_dim, hidden_dim))

burada,

· U, giriş ve gizli katmanlar arasındaki ağırlıkların ağırlık matrisidir

· V, gizli katman ile çıktı katmanı arasındaki ağırlıkların ağırlık matrisidir

· W, RNN katmanındaki (gizli katman) paylaşılan ağırlıkların ağırlık matrisidir

Son olarak, gizli katmanda kullanılacak sigmoid aktivasyon fonksiyonunu tanımlayacağız:

def sigmoid (x):

dönüş 1 / (1 + np.exp (-x))

2. Adım: Modeli eğitin

Artık modeli tanımladığımıza göre, sonunda sıra verileri üzerinde eğitime devam edebiliriz. Eğitim sürecini daha küçük adımlara ayırabiliriz, yani:

Adım 2.1: Eğitim verilerindeki kaybı kontrol edin

· Adım 2.1.1: İleriye doğru yayılma

· Adım 2.1.2: Hesaplama hatası

· Adım 2.2: Doğrulama verilerinin kaybını kontrol edin

· Adım 2.2.1: İleriye doğru yayılma

· Adım 2.2.2: Hesaplama hatası

· Adım 2.3: Gerçek eğitime başlayın

· Adım 2.3.1: İleriye doğru yayılma

· Adım 2.3.2: Geri yayılım hatası

· Adım 2.3.3: Ağırlığı güncelleyin

Bu adımları sonuna kadar tekrar etmemiz gerekiyor. Model aşırı donatılmaya başlarsa, lütfen durun! Ya da sadece dönem sayısını önceden tanımlayın.

Adım 2.1: Eğitim verilerindeki kaybı kontrol edin

Kayıp değerini elde etmek için RNN modelini ileriye aktaracağız ve kaydedilen tüm tahminlerin kare hatasını hesaplayacağız.

aralıktaki çağ için (nepoch):

# trendeki kaybı kontrol et

kayıp = 0.0

# tahmin almak için ileri geçiş yapın

aralıktaki i için (Y.shape):

x, y = X , Y # her kaydın girdi, çıktı değerlerini alın

prev_s = np.zeros ((hidden_dim, 1)) # burada, prev-s gizli katmanın önceki aktivasyonunun değeridir; tüm sıfırlar olarak başlatılır

aralıktaki t için (T):

new_input = np.zeros (x.shape) # daha sonra dizideki her zaman adımı için bir ileri geçiş yaparız

new_input = x # bunun için, o zaman adımı için tek bir girdi tanımlıyoruz

mulu = np.dot (U, new_input)

mulw = np.dot (W, önceki_s)

ekle = mulw + mulu

s = sigmoid (ekle)

mulv = np.dot (V, s)

prev_s = s

# hesaplama hatası

loss_per_record = (y-mulv) ** 2/2

kayıp + = loss_per_record

kayıp = kayıp / kayan (y.shape)

Adım 2.2: Doğrulama verilerinin kaybını kontrol edin

Doğrulama verilerinin kaybını hesaplamak için de aynı şeyi yapacağız (aynı döngüde):

# val üzerindeki kaybı kontrol et

val_loss = 0.0

aralıktaki i için (Y_val.shape):

x, y = X_val , Y_val

prev_s = np.zeros ((gizli_dim, 1))

aralıktaki t için (T):

new_input = np.zeros (x.shape)

new_input = x

mulu = np.dot (U, new_input)

mulw = np.dot (W, önceki_s)

ekle = mulw + mulu

s = sigmoid (ekle)

mulv = np.dot (V, s)

prev_s = s

loss_per_record = (y-mulv) ** 2/2

val_loss + = loss_per_record

val_loss = val_loss / float (y.shape)

print ('Dönem:', epoch + 1, ', Kayıp:', kayıp ', Değer Kaybı:', değer_ kaybı)

Aşağıdaki çıktıyı almalısınız:

Dönem: 1, Kayıp :, Değer Kaybı:

...

...

Adım 2.3: Gerçek eğitime başlayın

Şimdi ağın gerçek eğitimine başlayacağız. Burada, önce ileri geçiş, hatayı hesaplamak için kullanılır ve daha sonra, eğimi hesaplamak ve güncellemek için geri geçiş kullanılır.

Adım 2.3.1: İleri geçiş

İleri geçişte:

· Önce girdiyi girdi ve gizli katman arasındaki ağırlık ile çarpın

· Bu öğeyi RNN katmanında çarpmak için ağırlık ekleyin. Çünkü önceki zaman adımının bilgisini yakalamak istiyoruz

· Sigmoid aracılığıyla işlevi etkinleştirin

Bunu gizli katman ve çıktı katmanı arasındaki ağırlık ile çarpın

· Çıktı katmanında, değer doğrusal olarak etkinleştirilir, bu nedenle değer, etkinleştirme katmanından açıkça geçirilmez

· Mevcut katmanın durumunu ve önceki zaman adımının durumunu kod sözlüğüne kaydedin

Aşağıdakiler ileri geçiş kodudur (bunun önceki döngünün devamı olduğunu unutmayın):

# tren modeli

aralıktaki i için (Y.shape):

x, y = X , Y

katmanlar =

prev_s = np.zeros ((gizli_dim, 1))

dU = np.zeros (U.shape)

dV = np.zeros (V. şekli)

dW = np.zeros (W. şekli)

dU_t = np.zeros (U.shape)

dV_t = np.zeros (V.shape)

dW_t = np.zeros (W. şekli)

dU_i = np.zeros (U.shape)

dW_i = np.zeros (W. şekli)

# doğrudan geçiş

aralıktaki t için (T):

new_input = np.zeros (x.shape)

new_input = x

mulu = np.dot (U, new_input)

mulw = np.dot (W, önceki_s)

ekle = mulw + mulu

s = sigmoid (ekle)

mulv = np.dot (V, s)

layer.append ({'s': s, 'önceki_s': önceki_s})

prev_s = s

Adım 2.3.2: Geri yayılım hatası

İleri yayılma adımından sonra, her katmanın gradyanını ve geri yayılma hatasını hesaplıyoruz. Vanilya arka planı yerine kesilmiş geri yayılım (TBPTT) kullanacağız. Bu karmaşık gelebilir ama aslında çok basittir.

BPTT ve backprop arasındaki temel fark, RNN katmanındaki tüm zaman adımları için bir geri yayılım adımının gerçekleştirilmesidir. Bu nedenle, sıra uzunluğu 50 ise, geçerli zaman adımından önceki tüm zaman adımları geriye doğru yayılacaktır.

Doğru tahmin ettiyseniz, BPTT hesaplama açısından çok pahalı görünüyor. Bu nedenle, önceki tüm zaman adımlarını geri yaymak yerine, bilgi işlem gücünden tasarruf etmek için x zaman adımlarına kadar geri yayılırız. Bunun kavramsal olarak tüm veri noktaları yerine bir grup veri noktası içeren stokastik gradyan inişine benzer olduğunu düşünün.

Geri yayılma hatası kodu aşağıdadır:

# önceden türevi

dmulv = (mulv-y)

# geri geçiş

aralıktaki t için (T):

dV_t = np.dot (dmulv, np.transpose (katmanlar))

dsv = np.dot (np.transpose (V), dmulv)

ds = dsv

dadd = ekle * (1-ekle) * ds

dmulw = baba * np.ones_like (mulw)

dprev_s = np.dot (np.transpose (W), dmulw)

aralıktaki i için (t-1, max (-1, t-bptt_truncate-1), -1):

ds = dsv + dprev_s

dadd = ekle * (1-ekle) * ds

dmulw = baba * np.ones_like (mulw)

dmulu = baba * np.ones_like (mulu)

dW_i = np.dot (W, katmanlar)

dprev_s = np.dot (np.transpose (W), dmulw)

new_input = np.zeros (x.shape)

new_input = x

dU_i = np.dot (U, new_input)

dx = np.dot (np.transpose (U), dmulu)

dU_t + = dU_i

dW_t + = dW_i

dV + = dV_t

dU + = dU_t

dW + = dW_t

Adım 2.3.3: Ağırlıkları güncelleyin

Son olarak, ağırlık, hesaplanan ağırlık gradyanı kullanılarak güncellenir. Unutulmamalıdır ki, eğer kontrol edilmezlerse, eğim sıklıkla patlayacaktır. Bu, patlayıcı gradyan problemi adı verilen sinir ağlarını eğitmenin temel bir problemidir. Yani bir aralıkta kelepçelenmeleri gerekir, bunu yapabiliriz:

dU.max () ise > max_clip_value:

dU = max_clip_value

dV.max () ise > max_clip_value:

dV = max_clip_value

dW.max () ise > max_clip_value:

dW = max_clip_value

dU.min () ise < min_clip_value:

dU = min_clip_value

dV.min () ise < min_clip_value:

dV = min_clip_value

dW.min () ise < min_clip_value:

dW = min_clip_value

# Güncelleme

U - = öğrenme_ hızı * dU

V - = öğrenme_ hızı * dV

W - = öğrenme_ hızı * dW

Yukarıdaki modeli eğitirken şu çıktıyı aldım:

Dönem: 1, Kayıp :, Değer Kaybı:

Dönem: 2, Kayıp :, Değer Kaybı:

Dönem: 3, Kayıp :, Değer Kaybı:

Dönem: 4, Kayıp :, Değer Kaybı:

Epoch: 5, Loss :, Val Loss:

Dönem: 6, Kayıp :, Değer Kaybı:

Dönem: 7, Kayıp :, Değer Kaybı:

Dönem: 8, Kayıp :, Değer Kaybı:

Dönem: 9, Kayıp :, Değer Kaybı:

Dönem: 10, Kayıp :, Değer Kaybı:

Dönem: 11, Kayıp :, Değer Kaybı:

Dönem: 12, Kayıp :, Değer Kaybı:

Dönem: 13, Kayıp :, Değer Kaybı:

Dönem: 14, Kayıp :, Değer Kaybı:

Dönem: 15, Kayıp :, Değer Kaybı:

Dönem: 16, Kayıp :, Değer Kaybı:

Dönem: 17, Kayıp :, Değer Kaybı:

Dönem: 18, Kayıp :, Değer Kaybı:

Dönem: 19, Kayıp :, Değer Kaybı:

Dönem: 20, Kayıp :, Değer Kaybı:

Dönem: 21, Kayıp :, Değer Kaybı:

Dönem: 22, Kayıp :, Değer Kaybı:

Dönem: 23, Kayıp :, Değer Kaybı:

Dönem: 24, Kayıp :, Değer Kaybı:

Dönem: 25, Kayıp :, Değer Kaybı:

harika görünüyor! Tasarımda görsel bir his elde etmek için tahminler yapma ve bunları çizme zamanı.

3. Adım: Tahminleri alın

Tahminleri elde etmek için eğitimin ağırlıklarını ileri aktarın:

preds =

aralıktaki i için (Y.shape):

x, y = X , Y

prev_s = np.zeros ((gizli_dim, 1))

# Doğrudan geçiş

aralıktaki t için (T):

mulu = np.dot (U, x)

mulw = np.dot (W, önceki_s)

ekle = mulw + mulu

s = sigmoid (ekle)

mulv = np.dot (V, s)

prev_s = s

preds.append (mulv)

preds = np.array (preds)

Tahmini gerçek değerle çizin:

plt.plot (önsözler, 'g')

plt.plot (Y, 'r')

plt.show ()

Bu eğitim verileriyle ilgili. Modelin fazla uygun olup olmadığını nasıl anlarsınız? Daha önce oluşturulan doğrulama kümesi burada devreye girer:

preds =

aralıktaki i için (Y_val.shape):

x, y = X_val , Y_val

prev_s = np.zeros ((gizli_dim, 1))

# Her zaman adımı için ...

aralıktaki t için (T):

mulu = np.dot (U, x)

mulw = np.dot (W, önceki_s)

ekle = mulw + mulu

s = sigmoid (ekle)

mulv = np.dot (V, s)

prev_s = s

preds.append (mulv)

preds = np.array (preds)

plt.plot (önsözler, 'g')

plt.plot (Y_val, 'r')

plt.show ()

fena değil! Tahmin etkileyici görünüyor. Doğrulama verilerinin RMSE puanı da kabul edilebilir:

sklearn.metrics'ten import mean_squared_error

math.sqrt (mean_squared_error (Y_val * max_val, preds * max_val))

0,127191931509431

6G depolama + 16 milyon önde, kendisiyle doğal olarak gurur duyan somun cep telefonu 4 ay sonra 1399'a düştü
önceki
Çok güzel kokuyor! Yeni iPhone ile ilgili her türlü şikayet, ancak randevu sayısı inanılmaz
Sonraki
Bayern 3-1 Schalke, Lewandez üç gol attı, Gnabry arka arkaya gol attı
İPhone 8'de piyasaya sürüldükten sadece birkaç hafta sonra neden birden fazla pil kazası oluyor?
Intel Xe ayrık grafik konsept tasarımı: Optane SSD stili İki set LED ışık
Akıllı projeksiyon satışları patladı Yurtiçi akıllı projeksiyon pazarı ne kadar sürecek?
Android artık ücretsiz değil mi? Google'da büyük ince sinirler
Su geçirmez tableti onurlandırın Waterplay değerlendirmesi: 2399 yuan buna değer olduğunu düşünüyor musunuz?
İlk yarı-Bayern 2-1 Schalke, Lewandz attı + Oolong
İPhone XR'nin çerçevesi ve rengi, yurt içinde üretilen gövde üzerine püskürtülecek.
Ayrıntılı kod açıklaması: Web sitesinde ürünler nasıl daha popüler hale getirilir?
Bugünün temel sesi | Taobao hit istasyonu B! Gökyüzünü sarsan karlar elde etmek için ilahi operasyon
Piati ciddi şekilde yaralandı ve çıktı! Wu Lei, 30. dakikada evindeki çıkışını karşılamak için çıkış yaptı
MIUI10'un kararlı sürümü, 14 modeli destekleyen 10 Eylül'de piyasaya sürüldü
To Top