Sezen Aksu Şarkısı Yazan Yapay Zeka Diyorum!

Andrew Ng

“Artificial Intelligence is the new electricity.”
~Andrew Ng

Profil Resmi

Tuncer Ergin

Birkaç gün önce, LSTM RNN’yi (Long Short Term Memory Recurrent Neural Networks) öğrenmeye karar verdim, hali hazırda Andrew NG tarafından verilen kursu aldığım için teorik olarak bilgim bulunmaktaydı fakat kodlama konusunda eksiklerim olduğunun ve bunu bir proje yaparak öğrenmenin iyi bir fikir olacağını düşündüm.

LSTM RNN’nin çok sayıda uygulaması vardır. Ben her zaman metin verilerinin nasıl işleneceğini, bir metinin duygusunun analizini, şiir ve şarkı yazdırmasını öğrenmek istediğim için projeyi bu konulardan birisi üzerinde yapmaya karar verdim ve Sezen Aksunun şarkılarını öğrenip yine Sezen Aksu gibi şarkı yazan bir model oluşturmaya karar verdim.

Peki Nedir Bu LSTM Tekrarlayan Sinir Ağları?

LSTM recurrent neural network içinde döngülerin bulunduğu bir ağ türü olmakla birlikte bilgilerin kendi içinde tutulmasını ve bir sonraki düğüme aktrılmasına izin verir. Her bir düğüme LSTM(Long short term memory) denir.

LSTM ünitesindeki bir hücre, input, output ve forget kapılarından oluşmaktadır. Hücre, keyfi zaman aralıklarında değerleri hatırlar ve üç geçit, hücrenin içine ve dışına bilgi akışını düzenler. LSTM RNN hakkında daha fazla bilgi almak isterseniz size şu makaleleri tavsiye ederim. Understanding LSTM Networks ve Long short-term memory Ayrıca maddi durumunuza ve ingilizce seviyenize göre Andrew NG’nin Coursera’da bulabileceğiniz Deep Learning Specialization kursunu şiddetle tavsiye ederim.

LSTM RNN Uygulamaları

LSTM Recurrent neural networks birçok uygulamada kullanılmaktadır, aşağıdakiler en popüler olanlardır:

  • Doğal dil işleme
  • Doğal dil oluşturma
  • Metin sınıflandırma
  • Video to text
  • Çeviri uygulaması
  • ...

LSTM ve RNN hakkında biraz bilgimiz olduğuna göre artık projemize başlayabiliriz.

Öncelikle modeli oluşturmak için iki farklı yöntem izleyeceğiz.

  • Sıfırdan kendi modelimizi oluşturma
  • Textgenrnn kütüphanesi ile model oluşturma

Verisetinin oluşturulması

Sezen aksunun şarkılarının sözlerinin yer aldığı bir veri setini bulamadım, bunun yerine yabancı birçok şarkıcının veriseti internette bulunmakta, bende sezen aksuya olan hayranlığımdan dolayı kendi verisetimi oluşturmaya karar verdim. Fakat sezen aksunun birçok şarkısı var ve her bir şarkının sözlerini tek tek kopyala yapıştır yapmak yerine neredeyse birçok şarkısının sözlerinin yer aldığı bir siteden verileri çekmeye karar verdim.

Beautiful Soup

BeautifulSoup, HTML veya XML dosyalarını işlemek için oluşturulmuş güçlü ve hızlı bir kütüphanedir. Bu modül ile bir kaynak içerisindeki HTML kodlarını ayrıştırıp sadece istediğimiz alandaki verileri alabiliriz.

Ben bu sitedeki verileri almayı planladım. Dilerseniz adım adım nasıl yapıldığına bakalım.

Bu işlem sonucunda aşağıdak gibi şarkıa adlarını ve her bir şarkının sözlerinin bulunduğu şarkı adreslerini elde ederiz.

Şarkı adları ve adresleri

Şimdi her bir şarkının adresine gidip sözleri csv dosyasına kaydedelim

Yukarıdaki kod ile Sezen Aksu.csv dosyası oluşturduk. Daha sonra her bir şarkı için bir döngü oluşturduk, bu döngü her bir şarkının sözlerinin bulunduğu sayfaya gidecek ve bu sayfa içindeki sözlerin bulunduğu divi seçip şarkı sözlerini kaydedecek, fakat burada bizim istediğimiz şey sözlerin tümünü tek seferde değil satır satır kaydetmek, bu sebeple her bir satır için ikinci bir döngü oluşturdum. daha sonra her bir <br> tagı arasındaki sözleri sırası ile kaydettim.

Verisetinin önizlemesi

Verisetini hazırladığımmıza göre artık projeye başlayabiliriz. Önce gerekli kütüphaneleri import edelim.

Ben Colab üzerinde çalıştığım için verisetini projeye dahil etmem gerekli fakat siz lokal jupyter notebook üzerinde çalışıyorsanız verisetini upload etmenize gerek yok.

Verisetini projeye dahil ettik. Şimdi verisetini düzenleme kısmına geçelim. Modelin eğitimi için sadece şarkı sözleri gerekli o halde sadece şarkı sözlerini seçelim ve her bir şarkının sözlerini kendi içinde birleşecek şekilde kaydedelim.

Şimdi LSTM RNN’de kullanmak için sözleri bir metin dosyasına kaydedelim:

İstenen verileri verisetinden aldıktan sonra, ön işleme(preprocesing) işelmi yapalım.

Şarkı sözlerinin önişlenmesi

1. Şarkının küçük harfe dönüştürülmesi
2. Harflerin eşlenmesi

İki tane sözlük(dictionary) oluşturalım, bir tanesi her bir karakterin int karşılığı diğeri ise her bir int değerin karakter karşılığını tutsun.

Toplam char ve benzersiz char sayısı:

Toplam karakter sayısı : 340460 
Unique karakter sayısı : 61
3. Verisetinin Input ve Target olarak oluşturulması

LSTM RNN’i beslemek için verisetini input ve target olarak ayarlayalım:

4. Verisetinin son işleminin tamamlanması
Modelin eğitilebilmesi için verilerin son işlemlerini gerçekleştirelim.
Bu işlemler:
  • Verilerin yeniden şekillendirilmesi
  • Normalize edilmesi
  • One hot encoding
Verisetini oluşturup düzenlediğimize göre artık eğitim ve test olarak ikiye ayırabiliriz.
Verilerin %10’unu test için ayırdık. Artık LSTM RNN modelini oluşturmaya başlayabiliriz.

Modelin Oluşturulması

Modeli oluşturmadan önce LSTM ve CuDNNLSTM arasındaki farkı bakalım:
Aralarındaki en temel fark, LSTM cpu kullanırken CuDNNLSTM gpu kullanır, buda CuDNNLSTM’in daha hızlı olduğu anlamına gelir. (yaklaşık x15 kat daha hızlı)

Bu nedenle LSTM yerine CuDNNLSTM’i tercih ediyoruz.

Eğer colab üzerinde çalışıyorsanız runtime ayarlarından GPU’yu seçmeyi unutmayın, eğer lokal jupyter notebook üzerinde çalışıyorsanız Nvidia tarafından geliştirilen cuda ve CuDNN kütüphanelerini yüklemeyi unutmayın.

Kurulum işlemleri tamamlandıktan sonra modeli oluşturmaya başlayabiliriz.
Öncelikle ardışık bir model inşa edelim, giriş katmanı olarak 512 nörondan oluşan ve [32,1] adet giriş verisi alan bir katman tanımlayalım, daha sonra aşırı öğrenme yani overfitting’i önlemek için bir adet batc norm ve arkasına yine 512 adet nörondan oluşan bir gizli CuDNNLSTM katmanı ekleyelim. 
Oluşturulan 2 boyutlu veriyi 1 boyutlu bir diziye dönüştürmek için flatten katmanı ekleyelim, daha sonra sınıflandırma işlemini yapmak için bir adet 61 adet nörondan oluşan ve ativasyon fonksiyonunu ‘softmax’ olarak belirlediğimiz dense katmanı ekleyelim.

Modeli oluşturduk, şimdi modeli şu parametreler ile derleyelim:

  • optimizer= ‘adam’
  • loss= ‘categorical_crossentropy’
  • metrics= ‘accuracy’
Modeli derledikten sonra model detaylarını görmek için model.summary() kodunu kullanabiliriz.
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input (CuDNNLSTM) (None, 32, 512) 1054720
_________________________________________________________________
BatchNorm (BatchNormalizatio (None, 32, 512) 2048
_________________________________________________________________
CuDNNLSTM (CuDNNLSTM) (None, 32, 512) 2101248
_________________________________________________________________
Flatten (Flatten) (None, 16384) 0
_________________________________________________________________
FullyConnected (Dense) (None, 61) 999485
_________________________________________________________________
output (Activation) (None, 61) 0
=================================================================
Total params: 4,157,501
Trainable params: 4,156,477
Non-trainable params: 1,024
_________________________________________________________________

Modeli tanımladık, şimdi callbacks’leri tanımlayalım. 
Peki nedir bu callback? Callback her epoch’tan sonra cağrılan bir fonksiyondur.

Ben 3 farklı callback tanımladım, bunlar;

  • Her epochtan sonra modelin kayıp fonksiyonunda iyileştime olmuşsa modeli kaydetmeye yarayan checkpoint.
  • Modelin gelişimi anlık ve grafiksel olarak gelişimini tensorboard ekranından görmek için tensorboard. (verilerin bulunduğu dosyada cmd açın ve tensorboard — logdir=logs/ komutunu çalıştırın, daha sonra browserdan http://localhost:6006/#scalars adresini açın. Artık model eğitilirken modelin gelişimini anlık olarak görebilirsiniz.)
  • Modelin gelişim gösteremediği 3 epochtan sonra daha fazla eğitime devam edip zaman kaybeymek yerine eğitimi bitirmeye yarayan early_stopping.

Artık modeli eğitmeye başlayabiliriz.

Eğitim

Modeli eğitirken birden çok parametre kullanırız. Bu parametreler modelin aşırı öğrenmesini engellemek için veya modelin eğitiminin hızı için çok önemlidir. Ben birden çok parametre üzerinde oynamalar yaparak optimum halini bulmaya çalıştım, tabi bu uzun bir süre gerektirdi, siz de parametreler ile oynayarak daha iyi sonuçlar üretebilirsiniz.
Train on 306385 samples, validate on 34043 samples
Epoch 1/150
306385/306385 [==============================] - 121s 394us/step - loss: 3.0673 - acc: 0.1379 - val_loss: 2.9531 - val_acc: 0.1634

Epoch 00001: loss improved from inf to 3.06729, saving model to Sezen-Aksu-Epoch_01-Acc_0.14-Val_Acc_0.16.hdf5
Epoch 2/150
306385/306385 [==============================] - 120s 392us/step - loss: 2.8149 - acc: 0.1774 - val_loss: 2.8241 - val_acc: 0.1720
.
.
.
Epoch 95/150
306385/306385 [==============================] - 121s 394us/step - loss: 0.0760 - acc: 0.9936 - val_loss: 0.5620 - val_acc: 0.9041

Epoch 00095: loss improved from 0.07969 to 0.07599, saving model to Sezen-Aksu-Epoch_95-Acc_0.99-Val_Acc_0.90.hdf5
Epoch 00095: early stopping

Eğitim sırasında başarım oranı gelişen modeli checkpoint sayesinde kaydettik, daha sonraki aşamalarda modeli tekrar eğitmek yerine kaydedilen modeli kullanabiliriz.

Model Ağırlıklarının yüklenmesi

Eğitilmiş model yüklendikten sonra yeni şarkılar yazdırılmaya başlanabilir.

Şarkı sözü oluşturma

Modelin şarkı sözüoluşturnası için sezen aksu şarkılarından rastele bir şarkı öbeği seçeceğiz, ardından eğitilmiş modelimiz bu şarkı öbeğine göre karakterler üretip şarkı yazmaya çalışacak.

Çıktı:
Seçilen söz : 
"gitme dur daha şimdiden deliler "

gibi özledim
i̇kimiz içinde doğru olan böylesi git
i̇nan bana sandığın kadar bile haçırım var
van yaylar
hayırsıl tüsü dklerin dükülden girki gelen kardığınmeyin
bereen o çücül tür gelme
teni gördüm uan
bir dünya bir tırd gön eelir
yat oomadak tenenen aşkın oldum dilere gamiı yon
yuruş malpi ee göl
Bitti

Rahat bir şekilde görebilirsiniz ki üretilen sözler gerçek değil ve birçok yazım hatası var. Parametreler ile oynayarak belki daha iyi bir sonuç üretebilirsiniz fakat eğitim süresi hesaba katılırsa epeyce bir vakit gerekli olduğunu tahmin edebilirsiniz.

Textgenrnn keras ve tensorflow ile geliştirilmiş bir char-rnn kütüphanesidir. bu kütüphane ile karakter veya kelime seviyesinde yeni veriler üretebilirsiniz.

Nasıl kullanılıdığı ve yeni bir modelin nasıl oluşturulduğuna kendi sayfasından bakabilirsiniz

Ben yine google colab üzerinde çalıştığım için bazı ekstra modüller kullanıyorum, eğer siz lokalde çalışıyosanız 1. ve 2. satırı kullanmanıza gerek yok.

Birinci yöntemle verisetini kendimiz kod ile temizlemiş ve kullanmıştık. Bu yöntem kendi içerisinde verisetini temizleyemediği için verisetini kendimiz manuel olarak temizlememiz gerekli. Kod ile uğraşmak yerine csv dosyasını açıp şarkı sözlerinin bulunduğu kolon hariç tüm kolonları sildim, bu sayede model sadece şarkı sözlerini öğrenecek.

Textgenrnn modeli, modelin oluşturulması ve eğitilmesi için birçok parametre almakta. Bu parametreler az çok isminden alaşılmaktalar fakat anlamadığınız veya detaylı kullanımını görmek istediğiniz parametreler için modülün kendi kütüphanesine gözatabilirsiniz.

____________________________________________________________________
Layer (type) Output Shape Param #
Connected to
====================================================================
input (InputLayer) (None, 15) 0
____________________________________________________________________
embedding (Embedding) (None, 15, 100) 6200
input[0][0]
____________________________________________________________________
dropout (SpatialDropout1D) (None, 15, 100) 0
embedding[0][0]
____________________________________________________________________
rnn_1 (Bidirectional) (None, 15, 64) 34304
dropout[0][0]
____________________________________________________________________
rnn_2 (Bidirectional) (None, 15, 64) 25088
rnn_1[0][0]
____________________________________________________________________
rnn_3 (Bidirectional) (None, 15, 64) 25088
rnn_2[0][0]
____________________________________________________________________
rnn_4 (Bidirectional) (None, 15, 64) 25088
rnn_3[0][0]
____________________________________________________________________
rnn_concat (Concatenate) (None, 15, 356) 0
dropout[0][0]

rnn_1[0][0]

rnn_2[0][0]

rnn_3[0][0]

rnn_4[0][0]
____________________________________________________________________
attention (AttentionWeightedAve (None, 356) 356
rnn_concat[0][0]
____________________________________________________________________
output (Dense) (None, 62) 22134
attention[0][0]
====================================================================
Total params: 138,258
Trainable params: 138,258
Non-trainable params: 0
____________________________________________________________________
####################
Temperature: 0.2
####################
Bir gün ayrılık kapımı çektim bir de atmadın
Bir gün ayrılık kapımı çektim bir derdiniz bir de alda
Sen seç artık bıktım senden çek git Allahaşkına
Bir kadeh kalbini
Bir deli rüzgar savurdu beni sevilmeyi
Bir tek içten gülüşüne gibi söyle biraz
Bir kadını bir çiçek açtı ile öterek de vardır
Bir kıvılcım yeter ben hep yakarsam da
Bir karanlık sevgilim özlemle
Bir kahrefes kaldı
Bir daha göre değil yaşlanmaz, düşüncemiyimle beni
Bir daha güç de ben bu yüzden
Bir kıvılcım yeter ben sana kaldım
Bir gün ayrılık korkuları
Bir kıvılcım yeter ben hazırım bak
####################
Temperature: 0.5
####################
İster güneş ol yak beni
"Sen misin başları gibi korkmadan ki bir şarkılarım hıranlıktan
Ama sen özlerim daha hey yavrum şinanay
O beni değiştirir ayrılık kapımı çektim bu yalnızca çok önemli bir korker herkes gibi hey
Kolay olmayacak elbet var yüreğin
Ben duygularım beni
Anlamak için doğru budur en saklarıma
Bir gün gelir demirleri yüreğini artık benim
Hani haber bekliyorum
Seni içime çekilir soldu
Aşkımıza aşk değilim
Ben sana tellerini versem
Haydi gel gel kolları boynuma dola
"Ben seni öyle sevmez oldum teşi
İnan bize hava halimden
####################
Temperature: 1.0
####################
Ayrılmak inanmam içim şimdi günahlı teninde
Pardon dalsalarsın
O-kudum-da
"İnsan, sevgi kokuyorsun
Çaplaya olmaz ki düşün
Allahsın o gençliğimim bana herkes kötü günde hayat
Ümidimin içine dayanırsın
Gün dezdim bir yaşam
Hani herkes aradım dema bitmez öğütür
Ayaraklarım hemen
Savaşma seviş beğeler
Bu şarkılar sıcak ama şakan kaygın ah barılarda
Boynu bükükleri sen yapacağım
Sen ağlama dolan kaldım
Yüz çizgiden içimde

Temperature değerinin düşük olaması şarkı sözünün gerçek şarkı sözleri ile benzerlik gösterdiği anlamına gelirken bu değerin yüksek olması, sözlerin tamamen yeni yazıldığı anlamına gelir.

Eğer iyi bir model tasarlanır ve temperature değeri 1 olarak seçildiğinde oluşturulan şarkı sözü anlamlı ve gerçekçi oluyorsa gerçek dünyada kullanabilrsiniz.

Textgenrnn ile kolay bir şekilde model oluşturulduğunu gördünüz. Sözler tam anlamıyla gerçeksi olmasa da kendi oluşturduğumuz modele göre nispeten daha iyi sonuç verdiğini gözlemledik. Sizde başka bir sanatçının şarkısını veya bir yazarın kitaplarını veriseti olarak kullanarak yeni projeler üretebilirsiniz.

Bir sonraki aşamada LSTM ile şarkı ritimlerini oluşturmayı düşünüyorum.

Belkide oluşturulan bir şarkı sözü ve ritim ile gerçek bir şarkı oluşturulabilir.

Kodların tamamına buradan erişebilirsiniz 💻