7. Akustik Öznitelikler ile Otomatik Enstrüman Tanıma#

Open In Colab

7.1. Otomatik ses sınıflandırma#

Otomatik ses sınıflandırma, verilen bir ses kaydının tanımlanmış kategorilerden hangisine ait olduğunun otomatik bulunması işlemidir ve giderek artan sayıda uygulamada kullanılmaktadır. Bu uygulamalara örnek olarak çevresel ses sınıflandırma, konuşma tanıma (bu problemde kaydın küçük kesitleri sınıflandırılmaktadır), hastalık tespiti için kalp sesi sınıflandırması gibi örnekler verilebilir. Bu bölümde amacımız otomatik enstrüman sesi sınıflandırması problemi üzerinden otomatik ses sınıflandırması sistem tasarımı problemini ele almak ve ilgili okuyuculara bu konu için bir başlangıç noktası sağlamaktır. İçerik, araştırma materyalinden çok eğitim materyali olarak düşünülmelidir. Bu konudaki güncel araştırmalara ulaşmak için Google Scholar üzerinden makalelere erişmenizi ve incelemenizi öneririz.

Herhangi bir makine öğrenmesi problemini ele alırken öncelikle aşağıdaki adımları izlemeliyiz:

  • Hedeflenen uygulamanın ya da araştırma probleminin sınırlarının net bir şekilde tanımlanması

  • Test edilecek modellerin listelenmesi

  • Ölçme ve değerlendirme kriterlerinin belirlenmesi

  • Kullanılacak verilerin elde edilmesi, etiketlerin incelenmesi ve veriler üzerinde yapılacak ön işlemlere karar verilmesi

Bu konuları ele almadan önce ilgili konuda literatür taraması yapmak, en azından güncel bir literatür özet makalesi okumakta büyük fayda vardır.

Yukarıdaki maddeleri ele alırken, “Evrensel kümemiz nedir?”, “Hangi verileri toplayabilirim?”, “Topladığım verilerin güvenilir etiketleri var mı? Yoksa bu etiketleri nasıl toplar/edinirim?” sorularını da sürekli olarak sorgulamalıyız.

Akis

Şekil 7.1: Veri uzayı ve tasarım öğeleri

Bu problemde sınırları şu şekilde belirledik:

  • Gürültüsüz stüdyo ortamında monofonik olarak (tek enstrümanla icra edilen) izole nota seslendirmeleri olarak kaydedilmiş seslerin otomatik sınıflandırması üzerine çalışacağız. Nota seslendirmelerini 4 farklı kategoride (flüt, klarinet, viyolin, vibrafon) sınıflandıracağız.

  • sklearn kütüphanesinde mevcut bir dizi otomatik sınıflandırıcı modelini test edip karşılaştıracağız

  • Ölçüt olarak standart otomatik sınıflandırma ölçütlerini kullanılacağız (kesinlik, doğruluk, vb.)

  • Veri kümesi olarak bir konservatuvar sitesinde bulunan verileri kullanacağız the IOWA:MIS dataset Bu veri setinin seçerken etiketlerin dosya isimlerinde mevcut olması ve ekstra etiketleme emeğine ihtiyaç duymamasına dikkat ettik.

7.2. Bölüm organizasyonu#

Daha kolay takip edilebilmesi için bölümü üç aşamaya ayırdık.

  1. Veri inceleme ve ön işleme: Öncelikle verileri indirip inceleyecek, içeriğini anlamaya çalışacak ve testlerde kullanılabilmesi için bir dizi ön işleme adımına tabi tutacağız. Veriler üzerine inceleme yapmak problemin doğasını anlamak için kullanılmasını şiddetle tavsiye ettiğimiz bir yöntemdir. Uygun temsillerin ve modellerin seçilebilmesi için önemli bir gerekliliktir.

  2. Öznitelik hesaplama: Her bir örnek/kayıt için öznitelikleri hesaplayacak ve öznitelik uzayında bazı incelemeler yapacağız. Daha iyi sonuçlar alabilmek için öznitelikler üzerinde uygulayabileceğimiz bir dizi ön işleme adımını ele alacağız.

  3. Sınıflandırıcı tasarımı ve testleri: Bu noktada sklearn kütüphanesinde varolan hazır tasarımları kullanacak ve veriler üzerinde performanslarını karşılaştıracağız.

Temel kütüphaneleri yükleyerek kodumuza başlayabiliriz:

%%capture --no-display
# Kütüphanelerin yüklenmesi
import os
import matplotlib.pyplot as plt
import numpy as np
import IPython
import warnings
warnings.filterwarnings('ignore')

# Ses verisi okuma ve öznitelik kestirimi için Essentia paketinin kurulumu
import importlib.util
if importlib.util.find_spec('essentia') is None:
  !pip install essentia
import essentia.standard as ess

# Rasgelelik kontrolü için 'seed' ekleyelim
np.random.seed(0)
[   INFO   ] MusicExtractorSVM: no classifier models were configured by default

7.3. Ham verinin toplanıp incelenmesi#

Dosyaların indirilmesi: Öncelikle internetten zip dosyalarını indirip içindekileri ‘instrument’ isimli bir klasörde toplayalım.

%%capture --no-display
%%capture --no-stderr
%%capture --no-stdout
# UIOWA:MIS veri kümesinden örneklerin indirilmesi
import urllib.request
import zipfile
import os
import sys
import shutil

# UIOWA:MIS veri kümesi bağlantı adresleri
baglantilar = {
    'flute': 'http://theremin.music.uiowa.edu/sound%20files/MIS/Woodwinds/flute/flute.nonvib.ff.zip',
    'violin': 'http://theremin.music.uiowa.edu/sound%20files/MIS/Strings/violin2012/Violin.arco.mono.1644.1.zip',
    'vibraphone': 'http://theremin.music.uiowa.edu/sound%20files/MIS%20Pitches%20-%202014/Percussion/Vibraphone/Vibraphone.dampen.ff.stereo.zip',
    'clarinet': 'http://theremin.music.uiowa.edu/sound%20files/MIS/Woodwinds/Ebclarinet/EbClar.ff.zip'
}

veri_klasoru = 'instrument'
if not os.path.exists(veri_klasoru):  # klasör yok ise oluşturalım
    os.mkdir(veri_klasoru)
for enstruman, url in baglantilar.items():
    print(enstruman, 'için dosyaları indiriyor')
    hedef_klasor = os.path.join(veri_klasoru, enstruman)
    # enstrüman için altklasör yok ise oluşturalım
    if not os.path.exists(hedef_klasor):
        os.mkdir(hedef_klasor)
    dosya_ismi = url.split('/')[-1]
    urllib.request.urlretrieve(url, dosya_ismi)
    # Zip dosyasının açılması
    zip_ref = zipfile.ZipFile(dosya_ismi, 'r')
    zip_ref.extractall(hedef_klasor)
    zip_ref.close()
    os.remove(dosya_ismi)  # açılmış zip dosyasının silinmesi
    print('Veri indirildi, açıldı ve yerleştirildi: ', hedef_klasor)
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
/tmp/ipykernel_9512/2020053402.py in <module>
     24         os.mkdir(hedef_klasor)
     25     dosya_ismi = url.split('/')[-1]
---> 26     urllib.request.urlretrieve(url, dosya_ismi)
     27     # Zip dosyasının açılması
     28     zip_ref = zipfile.ZipFile(dosya_ismi, 'r')

~/miniconda3/envs/KitapYazim/lib/python3.9/urllib/request.py in urlretrieve(url, filename, reporthook, data)
    266 
    267             while True:
--> 268                 block = fp.read(bs)
    269                 if not block:
    270                     break

~/miniconda3/envs/KitapYazim/lib/python3.9/http/client.py in read(self, amt)
    461             # Amount is given, implement using readinto
    462             b = bytearray(amt)
--> 463             n = self.readinto(b)
    464             return memoryview(b)[:n].tobytes()
    465         else:

~/miniconda3/envs/KitapYazim/lib/python3.9/http/client.py in readinto(self, b)
    505         # connection, and the user is reading more bytes than will be provided
    506         # (for example, reading in 1k chunks)
--> 507         n = self.fp.readinto(b)
    508         if not n and b:
    509             # Ideally, we would raise IncompleteRead if the content-length

~/miniconda3/envs/KitapYazim/lib/python3.9/socket.py in readinto(self, b)
    702         while True:
    703             try:
--> 704                 return self._sock.recv_into(b)
    705             except timeout:
    706                 self._timeout_occurred = True

~/miniconda3/envs/KitapYazim/lib/python3.9/ssl.py in recv_into(self, buffer, nbytes, flags)
   1239                   "non-zero flags not allowed in calls to recv_into() on %s" %
   1240                   self.__class__)
-> 1241             return self.read(nbytes, buffer)
   1242         else:
   1243             return super().recv_into(buffer, nbytes, flags)

~/miniconda3/envs/KitapYazim/lib/python3.9/ssl.py in read(self, len, buffer)
   1097         try:
   1098             if buffer is not None:
-> 1099                 return self._sslobj.read(len, buffer)
   1100             else:
   1101                 return self._sslobj.read(len)

KeyboardInterrupt: 

### Enstrüman dosya listelerinin toplanması

Klasöre çıkarttığımız dosyaların listesini oluşturmalıyız. Dosyalara sırasıyla bu liste üzerinden erişeceğiz.

veri_klasoru = 'instrument'
# Her enstrüman için dosya listesi taşıyacak kütüphane tanımlayıp kullanalım
enstruman_dosyalari = dict()
# Tüm alt klasörler içerisindeki .aif, .aiff dosyalarının listesini toplama
# Enstrüman etiketi dosya isminde mevcut, bu bilgiyi dosya isminden çekeceğiz
for kok_klasor, klasorler, dosyalar in os.walk(veri_klasoru):
    for dosya in dosyalar:
        # .ff. içeren ses dosyalarını kullanacağız
        if (dosya.endswith('.aif') or dosya.endswith('.aiff')) and '.ff.' in dosya:
            dosya_ismi = os.path.join(kok_klasor, dosya)
            enstruman = dosya.split('.')[0]
            # bu kontrol MACOS'te ._ ile başlayan dosya adları düşünülerek eklendi
            if len(enstruman) > 0:
                if enstruman not in enstruman_dosyalari:
                    enstruman_dosyalari[enstruman] = [dosya_ismi]
                else:
                    enstruman_dosyalari[enstruman].append(dosya_ismi)

# Oluşturduğumuz dosya listesine bakalım
enstruman_dosyalari
{'Vibraphone': ['instrument/vibraphone/Vibraphone.dampen.ff.Bb5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Ab5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Ab4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Db3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.E5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Db5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.E6.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Eb6.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Gb5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.G4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Gb4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.F5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.F3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Bb3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.D6.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Eb4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.A3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.C3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Eb5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Db4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.B4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Ab3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Gb3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.D3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.A4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Bb4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.F6.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.C5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.G3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.D5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Db6.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.A5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.E3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.D4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.E4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.C6.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.F4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.G5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.C4.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.B3.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.B5.stereo.aif',
  'instrument/vibraphone/Vibraphone.dampen.ff.Eb3.stereo.aif'],
 'EbClar': ['instrument/clarinet/EbClar.ff.C4B4.aiff',
  'instrument/clarinet/EbClar.ff.C6A6.aiff',
  'instrument/clarinet/EbClar.ff.G3B3.aiff',
  'instrument/clarinet/EbClar.ff.C5B5.aiff'],
 'Violin': ['instrument/violin/Violin.arco.ff.sulG.G3B3.mono.aif',
  'instrument/violin/Violin.arco.ff.sulD.D4B4.mono.aif',
  'instrument/violin/Violin.arco.ff.sulE.E5B5.mono.aif',
  'instrument/violin/Violin.arco.ff.sulA.C5B5.mono.aif',
  'instrument/violin/Violin.arco.ff.sulG.C4B4.mono.aif',
  'instrument/violin/Violin.arco.ff.sulD.C5B5.mono.aif',
  'instrument/violin/Violin.arco.ff.sulA.C6Ab6.mono.aif',
  'instrument/violin/Violin.arco.ff.sulD.C6.mono.aif',
  'instrument/violin/Violin.arco.ff.sulE.C7E7.mono.aif',
  'instrument/violin/Violin.arco.ff.sulA.A4B4.mono.aif',
  'instrument/violin/Violin.arco.ff.sulG.C5D5.mono.aif',
  'instrument/violin/Violin.arco.ff.sulE.C6B6.mono.aif'],
 'flute': ['instrument/flute/flute.nonvib.ff.C7Db7.aiff',
  'instrument/flute/flute.nonvib.ff.B3B4.aiff',
  'instrument/flute/flute.nonvib.ff.C5B5.aiff',
  'instrument/flute/flute.nonvib.ff.C6B6.aiff']}

Veri kümemizi oluşturduk, şimdi süreç tasarımına yönelebiliriz

Akış 2

Şekil 7.2: Otomatik sınıflandırıcı tasarımı ara adımları

7.3.1. Ham verilerin ön incelemesi ve ön işlemesi#

İlk olarak bazı örnekleri çizdirip incelemekte fayda var. İşe başlamadan mutlaka verinin içerisinde ne olduğuna bakılıp ön işleme adımlarını tanımlamak gerekir. Her enstrümandan birer örnek çizdirip inceleyelim. Örnekleme frekansı olarak standart audio-CD formatındaki gibi 44100Hz seçelim.

# Essentia kütüphanesi ses kaydını farklı örnekleme frekanslarında okumaya imkan tanıyor
# örnekleme frekansı olarak 44100Hz (audio-CD standardı) kullanalım
fs = 44100

enstruman_sayisi = len(enstruman_dosyalari.keys())
print('Örnek dalga formu çizimi')
plt.figure(1, figsize=(5 * enstruman_sayisi, 3))
dosya_endeksi = 0  # klasörlerdeki ilk örnekleri kullanalım
for i, enstruman in enumerate(enstruman_dosyalari.keys()):
    ornek_dosya = enstruman_dosyalari[enstruman][dosya_endeksi]
    # Ses kaydının dosyadan ses dizisine okunması
    ses = ess.MonoLoader(filename=ornek_dosya, sampleRate=fs)()
    # Çizim oluşturan kod satırları
    plt.subplot(1, enstruman_sayisi, (i+1))
    plt.plot(ses)
    plt.title(enstruman)
    plt.xlabel('zaman(örnek sayısı)')
Örnek dalga formu çizimi
../_images/07_OtomatikEnstrumanTanima_21_1.png

Şekil 7.3: Veri örnekleri

Veriden bir dizi örnek dinlemekte fayda var.

# Vibrafon klasöründeki ilk kayıt
IPython.display.Audio(
    ess.MonoLoader(
        filename=enstruman_dosyalari['Vibraphone'][0],
        sampleRate=fs)(),
    rate=fs)
# Flüt klasöründeki ilk kayıt
IPython.display.Audio(
    ess.MonoLoader(
        filename=enstruman_dosyalari['flute'][0],
        sampleRate=fs)(),
    rate=fs)

Bazı kayıtlarda tek nota kaydı varken bazılarında birden fazla nota kaydı var. Her bir notayı bölütleyip veri örneklerimiz olarak kullanalım.

Bölütleme işlemi için sessizlik kısımlarını tespit etmemiz gerekiyor. Bunun için sinyali küçük kesitlere bölüp her bir kesitin sessizlik olup olmadığına karar vermeliyiz. Bu işlem için bölütlerin enerjilerini belirlediğimiz bir eşik değeri ile kıyaslayabiliriz.

7.3.2. Ham veri ön işleme: Bölütleme ve normalizasyon işlemleri#

Verinin yapısına, içeriğine ve etiketlerine bağlı olarak yapılması gereken birçok işlem olabilir. Altta önce bölütleme, sonra da genlik normalizasyonu işlemlerini ele alacağız.

# Ham veri ön işleme parametrelerinin tanımlanması

# kayıttan alınacak kesit uzunluğu (örnek sayısı cinsinden)
pencere_boyutu = 4096 * 4
# ardışık kesitler arası uzaklık (örnek sayısı cinsinden)
kaydirma_miktari = 4096 * 2
enerji_esik_orani = 0.01
# Birden fazla paramete kullanırken bu parametreleri tek bir sözlük içerisine
# yerleştirip kullanmak daha anlaşılır bir kod yazmamıza yardım edebilir
parametreler = {
    'fs': fs,
    'pencere_boyutu': pencere_boyutu,
    'kaydirma_miktari': kaydirma_miktari,
    'enerji_esik_orani': enerji_esik_orani
}
def dosya_bolutle(dosya_ismi, parametreler):
    '''
    Enerji eşik değeri kullanarak kaydın sessiz bölgelerinden bölünmesini 
    sağlayacak sınırları tespit eder. Öncelikle kayıt küçük parçalara bölünerek
    her kesit için enerji hesaplanmakta ardından bu enerji değerlerinin eşik
    değeriyle karşılaştırılması sonucu kesitin sesli mi sessiz mi olduğuna karar
    verilmektedir. Bu bilgi bolut_karar_fonk içerisinde 0 ve 1 değerleriyle 
    belirtilmektedir. 0-1 ve 1-0 geçişleri ise kayıtların sınırlarını bulmakta
    kullanılmakta, bunun için bolut_karar_fonk'nun türevi işlenmektedir
    '''
    ses = ess.MonoLoader(filename=dosya_ismi, sampleRate=fs)()
    enerjiler = []  # kesitlerin enerji değerlerini bir listede tutacağız
    # Pencereleme ve her veri penceresi için enerji hesabı
    for frame in ess.FrameGenerator(
            ses,
            frameSize=pencere_boyutu,
            hopSize=kaydirma_miktari,
            startFromZero=True):
        enerjiler.append(ess.Energy()(frame))
    # listeden numpy-array'e dönüştürme:
    # bu adım diziler üzerinde alttaki işlemleri yapabilmek için gerekli
    enerjiler = np.array(enerjiler)
    # Genlik normalizasyonu
    enerjiler = enerjiler / np.max(enerjiler)

    # Enerji esik oranini kullanarak bolutleme sınırlarının belirlenmesi
    bolut_karar_fonk = np.zeros_like(enerjiler)
    # sessiz kesitler 0, sesli kesitler 1 olarak atanıyor
    bolut_karar_fonk[enerjiler > enerji_esik_orani] = 1
    # Fark fonksiyonu kullanacağımız için başa 0 ekliyoruz
    bolut_karar_fonk = np.insert(bolut_karar_fonk, 0, 0)
    fark_fonksiyonu = np.diff(bolut_karar_fonk)
    # Baslangic endeksleri: 0'dan 1'e geçiş
    baslangic_endeksleri = np.nonzero(fark_fonksiyonu > 0)[
        0] * kaydirma_miktari
    # Bitis endeksleri: 1'den 0'a geçiş
    bitis_endeksleri = np.nonzero(fark_fonksiyonu < 0)[
        0] * kaydirma_miktari
    return (ses, enerjiler, bolut_karar_fonk,
            baslangic_endeksleri, bitis_endeksleri)

Her enstrüman için 3 örnek dosyada bölütleme işlemini kontrol için sınırları ses verileriyle beraber çizdirelim

enstruman_sayisi = len(enstruman_dosyalari)
print('Bölütleme işlemi: örnek dosyalar')

ornek_dosya_sayisi = 3
for dosya_endeksi in range(ornek_dosya_sayisi):
    plt.figure(dosya_endeksi, figsize=(5 * enstruman_sayisi, ornek_dosya_sayisi))
    for i, enstruman in enumerate(enstruman_dosyalari.keys()):
        ornek_dosya = enstruman_dosyalari[enstruman][dosya_endeksi]
        (ses, enerjiler, bolut_karar_fonk, baslangic_endeksleri,
         bitis_endeksleri) = dosya_bolutle(ornek_dosya, parametreler)
        # Çizimlerin oluşturulması
        plt.subplot(1, enstruman_sayisi, (i+1))
        plt.title(enstruman)
        plt.plot(ses, label='ses dalgası')
        plt.plot(np.arange(enerjiler.size) * kaydirma_miktari,
                 enerjiler, 'g', label='enerjiler')
        plt.plot(np.arange(bolut_karar_fonk.size) * kaydirma_miktari,
                 bolut_karar_fonk, 'r', label='bölüt karar fonksiyonu')
        plt.vlines(baslangic_endeksleri, ymin=-0.5, ymax=0,
                   colors='b', linestyles='solid', label='Bölüt başlangıcı')
        plt.vlines(bitis_endeksleri, ymin=-0.5, ymax=0, colors='k',
                   linestyles='dashed', label='Bölüt bitişi')

plt.legend(loc='best')
Bölütleme işlemi: örnek dosyalar
<matplotlib.legend.Legend at 0x7fab447e8cd0>
../_images/07_OtomatikEnstrumanTanima_32_2.png ../_images/07_OtomatikEnstrumanTanima_32_3.png ../_images/07_OtomatikEnstrumanTanima_32_4.png

Şekil 7.4: Bölütleme işleme sonucu örnekleri (otomatik bulunan sınırlar sıfır değerinden aşağıya doğru inen dikitlerle gösterilmiştir)

Bölütleme sınırları makul görünüyor. Şimdi tanımladığımız fonksiyonu kullanarak:

  • Dosyalarda bölütleme işlemini yapalım

  • Her bölütü genlik normalizasyonuna tabi tutup ayrı bir dosyaya kaydedelim

Bölütler için ayrı bir alt klasör segments oluşturup dosyaları onun içerisine yerleştireceğiz.

bolutler_klasoru = os.path.join(veri_klasoru, 'segments')
if not os.path.exists(bolutler_klasoru):  # klasör yok ise oluşturalım
    os.mkdir(bolutler_klasoru)

bolut_dosyalari = []
for enstruman, dosyalar in enstruman_dosyalari.items():
    dosya_sayaci = 0
    for ornek_dosya in dosyalar:
        (ses, enerjiler, bolut_karar_fonk, baslangic_endeksleri,
         bitis_endeksleri) = dosya_bolutle(ornek_dosya, parametreler)
        # Bölütleme, normalizasyon ve dosyaya yazma
        for baslangic, bitis in zip(baslangic_endeksleri, bitis_endeksleri):
            # bölütlemede hata sonucu çok kısa kesitler oluşabilir,
            # sadece 1/3 saniye'den uzun olanları tutalım
            if bitis - baslangic > fs/3:
                ses_seg = ses[baslangic: bitis]
                # Küçük bir sessizlik bolumu bolut olarak alınmış olabilir,
                # enerjisini kontrol ederek düşükse dışarıda bırakalım
                if np.max(np.abs(ses_seg)) > 0.05:
                    # Genlik normalizasyonu
                    ses_seg = ses_seg / np.max(np.abs(ses_seg))
                    dosya_ismi = os.path.join(
                        bolutler_klasoru, 
                        enstruman + '_' + str(dosya_sayaci) + '.wav')
                    ess.MonoWriter(filename=dosya_ismi,
                                   format='wav', sampleRate=fs)(ses_seg)
                    dosya_sayaci += 1
                    bolut_dosyalari.append(dosya_ismi)

print(len(bolut_dosyalari), 'adet bölütlenmiş dosya oluşturuldu')
193 adet bölütlenmiş dosya oluşturuldu
# Ihtiyaç duyarsanız (yanlış işlemle çok sayıda dosya oluşturduysanız)
# bu fonksiyonu bir klasör içerisindeki tüm dosyaları silmek için kullanabilirsiniz
def klasoru_temizle(ana_klasor):
    '''Verilen klasordeki tum dosyalari siler'''
    for root, dirs, files in os.walk(ana_klasor):
        for dosya in files:
            dosya_ismi = os.path.join(root, dosya)
            os.remove(dosya_ismi)
            print(dosya_ismi, 'silindi')

# klasoru_temizle(bolutler_klasoru)

Bölütlenmiş dosyalar oluşturuldu, data/instrument/segments klasörünü kontrol edebilirsiniz

7.4. Öznitelik çıkarımı#

Şimdi bölütlenmiş her bir ses dosyası için öznitelikler hesaplayıp kategori/etiket/enstrüman bilgisi ile beraber tek bir veri dosyası içerisine yazabiliriz. Öznitelik çıkarımı için Essentia kütüphanesinin MusicExtractor fonksiyonunu kullanacağız.

Öncelikle tek bir dosya için çalıştırıp verdiği çıktıyı inceleyelim:

import essentia.standard as es

dosya = bolut_dosyalari[0]  # listeden ilk dosyayı kullanalım
oznitelikler, oznitelik_pencereler = es.MusicExtractor(
    lowlevelSilentFrames='drop',
    lowlevelFrameSize=2048,
    lowlevelHopSize=1024,
    lowlevelStats=['mean', 'stdev'])(dosya)

Essentia-MusicExtractor çok sayıda temel özniteliği hızlı bir şekilde hesaplayıp çıktı olarak verir. Biz, kodumuzun ve gösterimlerimizin kısa ve anlaşılır olması için, bunların içerisinde tek bir skaler değerle temsil edilen düşük seviye (low-level) öznitelikleri kullanacağız ve diğer öznitelikleri dışarıda bırakacağız.

skaler_oznitelikler = [
    descriptor for descriptor in oznitelikler.descriptorNames()
    if 'lowlevel' in descriptor and isinstance(oznitelikler[descriptor], float)
]
print('Kullanılacak oznitelikler:\n' + '\n'.join(skaler_oznitelikler))
Kullanılacak oznitelikler:
lowlevel.average_loudness
lowlevel.barkbands_crest.mean
lowlevel.barkbands_crest.stdev
lowlevel.barkbands_flatness_db.mean
lowlevel.barkbands_flatness_db.stdev
lowlevel.barkbands_kurtosis.mean
lowlevel.barkbands_kurtosis.stdev
lowlevel.barkbands_skewness.mean
lowlevel.barkbands_skewness.stdev
lowlevel.barkbands_spread.mean
lowlevel.barkbands_spread.stdev
lowlevel.dissonance.mean
lowlevel.dissonance.stdev
lowlevel.dynamic_complexity
lowlevel.erbbands_crest.mean
lowlevel.erbbands_crest.stdev
lowlevel.erbbands_flatness_db.mean
lowlevel.erbbands_flatness_db.stdev
lowlevel.erbbands_kurtosis.mean
lowlevel.erbbands_kurtosis.stdev
lowlevel.erbbands_skewness.mean
lowlevel.erbbands_skewness.stdev
lowlevel.erbbands_spread.mean
lowlevel.erbbands_spread.stdev
lowlevel.hfc.mean
lowlevel.hfc.stdev
lowlevel.loudness_ebu128.integrated
lowlevel.loudness_ebu128.loudness_range
lowlevel.loudness_ebu128.momentary.mean
lowlevel.loudness_ebu128.momentary.stdev
lowlevel.loudness_ebu128.short_term.mean
lowlevel.loudness_ebu128.short_term.stdev
lowlevel.melbands_crest.mean
lowlevel.melbands_crest.stdev
lowlevel.melbands_flatness_db.mean
lowlevel.melbands_flatness_db.stdev
lowlevel.melbands_kurtosis.mean
lowlevel.melbands_kurtosis.stdev
lowlevel.melbands_skewness.mean
lowlevel.melbands_skewness.stdev
lowlevel.melbands_spread.mean
lowlevel.melbands_spread.stdev
lowlevel.pitch_salience.mean
lowlevel.pitch_salience.stdev
lowlevel.silence_rate_20dB.mean
lowlevel.silence_rate_20dB.stdev
lowlevel.silence_rate_30dB.mean
lowlevel.silence_rate_30dB.stdev
lowlevel.silence_rate_60dB.mean
lowlevel.silence_rate_60dB.stdev
lowlevel.spectral_centroid.mean
lowlevel.spectral_centroid.stdev
lowlevel.spectral_complexity.mean
lowlevel.spectral_complexity.stdev
lowlevel.spectral_decrease.mean
lowlevel.spectral_decrease.stdev
lowlevel.spectral_energy.mean
lowlevel.spectral_energy.stdev
lowlevel.spectral_energyband_high.mean
lowlevel.spectral_energyband_high.stdev
lowlevel.spectral_energyband_low.mean
lowlevel.spectral_energyband_low.stdev
lowlevel.spectral_energyband_middle_high.mean
lowlevel.spectral_energyband_middle_high.stdev
lowlevel.spectral_energyband_middle_low.mean
lowlevel.spectral_energyband_middle_low.stdev
lowlevel.spectral_entropy.mean
lowlevel.spectral_entropy.stdev
lowlevel.spectral_flux.mean
lowlevel.spectral_flux.stdev
lowlevel.spectral_kurtosis.mean
lowlevel.spectral_kurtosis.stdev
lowlevel.spectral_rms.mean
lowlevel.spectral_rms.stdev
lowlevel.spectral_rolloff.mean
lowlevel.spectral_rolloff.stdev
lowlevel.spectral_skewness.mean
lowlevel.spectral_skewness.stdev
lowlevel.spectral_spread.mean
lowlevel.spectral_spread.stdev
lowlevel.spectral_strongpeak.mean
lowlevel.spectral_strongpeak.stdev
lowlevel.zerocrossingrate.mean
lowlevel.zerocrossingrate.stdev

Tüm dosyalar için öznitelik çıkarımı işleminin yapıp, skaler öznitelikleri alıp elde ettiğimiz tüm verileri data.csv isimli bir dosyaya yazalım.

Bu tercihimiz şuna dayanıyor: birçok makine öğrenmesi veri kümesi satırların örnekleri, sütunların öznitelikleri içerdiği tablolar şeklinde saklanıp paylaşılıyor. Örnekler için bakınız: Kaggle verileri, UC Irvine Machine Learning Repository.

Çalıştığımız alanda kullanılan formatlarla uyumlu format tercih etmek, araç ve veri paylaşımını, bu sayede başka araştırmacılarla işbirliğini kolaylaştıracaktır.

Yaygın tercih son kolonda etiket bilgisinin bulunması olduğu için biz de öyle yapacağız.

# Her dosya için oznitelik çıkarımı ve data.csv dosyasına yazım işlemi
# data.csv dosyasında her satır bir örneği temsil edecek,
# önce öznitelikleri, en sonda da sınıf bilgisini içerecek
veri_dosyasi = os.path.join(bolutler_klasoru, 'data.csv')
dosya_sayaci = 0
with open(veri_dosyasi, 'w') as yazici:
    # İlk kolon olarak öznitelik isimlerini,
    # son kolon olarak sınıf bilgisini temsilen 'enstruman' yazalım
    yazilacak_satir = ','.join(
        skaler_oznitelikler + ['enstruman']).replace('lowlevel.', '') + '\n'
    yazici.write(yazilacak_satir)
    for dosya in bolut_dosyalari:
        if '.wav' in dosya:
            dosya_sayaci += 1
            if dosya_sayaci % 20 == 0:  # 20 dosyada bir ekrana bilgi yazdır
                print(dosya_sayaci,
                      'adet dosya işlendi, işlenmekte olan dosya: ', dosya)
            oznitelikler, oznitelik_pencereler = es.MusicExtractor(
                lowlevelSilentFrames='drop',
                lowlevelFrameSize=2048,
                lowlevelHopSize=1024,
                lowlevelStats=['mean', 'stdev'])(dosya)
            secilmis_oznitelikler = [
                oznitelikler[oznitelik_ismi]
                for oznitelik_ismi in skaler_oznitelikler]
            # sınıf bilgisinin dosya isminden elde edilmesi
            enstruman = dosya.split('/')[-1].split('_')[0].lower()
            yazilacak_satir = str(secilmis_oznitelikler)[
                1:-1] + ',' + enstruman + '\n'
            yazici.write(yazilacak_satir)
print(dosya_sayaci, 'adet dosya işlendi')
20 adet dosya işlendi, işlenmekte olan dosya:  instrument/segments/Vibraphone_19.wav
40 adet dosya işlendi, işlenmekte olan dosya:  instrument/segments/Vibraphone_39.wav
60 adet dosya işlendi, işlenmekte olan dosya:  instrument/segments/EbClar_17.wav
80 adet dosya işlendi, işlenmekte olan dosya:  instrument/segments/EbClar_37.wav
100 adet dosya işlendi, işlenmekte olan dosya:  instrument/segments/Violin_18.wav
120 adet dosya işlendi, işlenmekte olan dosya:  instrument/segments/Violin_38.wav
140 adet dosya işlendi, işlenmekte olan dosya:  instrument/segments/Violin_58.wav
160 adet dosya işlendi, işlenmekte olan dosya:  instrument/segments/flute_2.wav
180 adet dosya işlendi, işlenmekte olan dosya:  instrument/segments/flute_22.wav
193 adet dosya işlendi

7.4.1. Özniteliklerin incelenmesi ve ön işlemesi#

Dosyalar için hesaplanan bütün öznitelikler, her biri bir satırda olacak şekilde tek bir dosyaya yazıldı: data.csv. Bu temsilde kolonlar öznitelikleri, satırlar da her bir örneği/dosyayı temsil etmekte. Bu, makine öğrenmesi verilerinde sıkça kullanılan bir düzendir.

Verileri yükleyip incelemeye başlayalım. Bunun için pandas kütüphanesi kullanacağız.

import pandas as pd

# Verilerin okunması
tablo = pd.read_csv(veri_dosyasi)
# Verinin baş kısmının görüntülenmesi
tablo.head()
average_loudness barkbands_crest.mean barkbands_crest.stdev barkbands_flatness_db.mean barkbands_flatness_db.stdev barkbands_kurtosis.mean barkbands_kurtosis.stdev barkbands_skewness.mean barkbands_skewness.stdev barkbands_spread.mean ... spectral_rolloff.stdev spectral_skewness.mean spectral_skewness.stdev spectral_spread.mean spectral_spread.stdev spectral_strongpeak.mean spectral_strongpeak.stdev zerocrossingrate.mean zerocrossingrate.stdev enstruman
0 0.990684 24.955116 3.647825 0.536830 0.119398 289.010223 132.418945 4.110642 6.952480 0.616870 ... 217.607498 6.032936 1.900585 3004128.250 4737389.5 3.668774 2.720361 0.042567 0.007204 vibraphone
1 0.990684 26.435593 1.601422 0.636219 0.147186 1055.020752 482.626892 14.076157 10.212609 0.358621 ... 70.797035 9.389044 2.429082 1778017.125 2592701.5 3.698664 2.426341 0.039608 0.009589 vibraphone
2 0.990684 23.885178 5.053813 0.520682 0.141888 262.656921 122.478897 9.697014 4.188370 1.247010 ... 440.509766 7.501504 2.710040 3043914.750 4758099.5 2.022717 1.253518 0.025333 0.019186 vibraphone
3 0.990684 23.565981 4.597108 0.425580 0.135100 59.750126 54.249290 -6.715064 3.709975 8.052089 ... 1236.714355 5.807158 2.171984 2031814.125 1917425.5 5.219349 3.358985 0.101094 0.015830 vibraphone
4 0.990684 26.508205 1.411997 0.623173 0.146127 2803.306152 1543.358643 29.534590 15.452468 0.362204 ... 31.129938 9.847502 3.322612 2524568.750 5650975.5 2.772293 2.281401 0.033519 0.012665 vibraphone

5 rows × 85 columns

Kolonların doğru şekilde öznitelik adlarıyla isimlendirildiğini (ilk 84 kolon), son kolonda kategori/sınıf bilgisi olduğunu görüyoruz.

Bir veri tablosu yüklediğinizde işlemlere başlamadan verinin içerisinde NaN değerler olup olmadığını kontrol etmemizde fayda var. Eğer NaN değerler varsa bunları temizlememiz lazım. Bunun için kullanabileceğimiz stratejilere diğer bölümlerde değineceğiz.

# .isnull()'ın döndürdüğü True/False değerleri içeren 
# matrisin toplamı sıfırdan farklı ise True (yani NaN) değer vardır
print(tablo.isnull().sum().sum())
0

Gözlem: Nan değer yok, devam edebiliriz …

Verilerin öznitelik uzayında nasıl dağıldığını incelemek de çok faydalı olacaktır. İki örnek çizim görelim

import seaborn as sns
sns.relplot(x='melbands_flatness_db.mean', y='spectral_centroid.mean',
            hue='enstruman', style='enstruman', data=tablo)
sns.relplot(x='spectral_complexity.mean', y='spectral_flux.stdev',
            hue='enstruman', style='enstruman', data=tablo)
<seaborn.axisgrid.FacetGrid at 0x7fab2f94ad50>
../_images/07_OtomatikEnstrumanTanima_53_1.png ../_images/07_OtomatikEnstrumanTanima_53_2.png

Şekil 7.5: İki boyutlu öznitelik uzayında verilerin görselleştirilmesi

Bu tür grafikler oluşturup incelerken amacımız verinin hangi eksenlerde/özniteliklerde birbirinden rahat ayrılabileceğini öngörmek. Örneğin üstteki grafikte spectral_flux_stdev özniteliğinin vibrafon örneklerini diğerlerinden ayırmada faydalı olacağını öngörebiliyoruz; o eksende veri dağılımında bir ayrılma gözlenebiliyor. Öznitelik uzayında veriler ne kadar iç içe ise o kadar zor bir otomatik sınıflandırma problemi ile yüzyüzeyiz demektir.

Benzer grafikleri son 6 öznitelik üzerinden olası tüm ikililer için çizdirelim ve farklı kategorilerdeki verilerin bir arada gruplanıp gruplanmadığını gözleyelim.

sns.pairplot(tablo.iloc[:, -7:], hue='enstruman')
<seaborn.axisgrid.PairGrid at 0x7fab2f873b50>
../_images/07_OtomatikEnstrumanTanima_56_1.png

Şekil 7.6: İki boyutlu öznitelik uzayında verilerin görselleştirilmesi. (Diyagonalde iki boyut için de aynı öznitelik kullanıldığı için dağılım grafikleri sunulmaktadır.)

Bir sonraki adımda özniteliklerin istatistiksel özelliklerini inceleyelim.

# Veriye dair "Descriptive statistics"
tablo.describe()
average_loudness barkbands_crest.mean barkbands_crest.stdev barkbands_flatness_db.mean barkbands_flatness_db.stdev barkbands_kurtosis.mean barkbands_kurtosis.stdev barkbands_skewness.mean barkbands_skewness.stdev barkbands_spread.mean ... spectral_rolloff.mean spectral_rolloff.stdev spectral_skewness.mean spectral_skewness.stdev spectral_spread.mean spectral_spread.stdev spectral_strongpeak.mean spectral_strongpeak.stdev zerocrossingrate.mean zerocrossingrate.stdev
count 193.000000 193.000000 193.000000 193.000000 193.000000 193.000000 193.000000 193.000000 193.000000 193.000000 ... 193.000000 193.000000 193.000000 193.000000 1.930000e+02 1.930000e+02 193.000000 193.000000 193.000000 193.000000
mean 0.986378 18.737075 3.533494 0.430367 0.102611 283.950441 628.912498 3.632873 4.466255 9.637900 ... 1540.656583 760.391840 3.335840 1.303501 3.089807e+06 2.443487e+06 3.835344 2.347946 0.055322 0.022904
std 0.006414 4.673740 1.205451 0.079073 0.040251 999.686998 2476.937780 6.138561 7.892060 6.017747 ... 710.809230 561.415954 1.765828 0.898021 8.214676e+05 1.145174e+06 2.399718 1.485965 0.023783 0.015384
min 0.944595 7.485431 1.186291 0.260509 0.030590 -1.065718 0.525588 -7.482044 0.199631 0.358621 ... 448.608398 5.137959 0.950112 0.320255 1.384233e+06 3.002179e+05 0.805183 0.336106 0.017263 0.005875
25% 0.982277 15.009152 2.775762 0.367775 0.072194 5.696008 11.835285 0.806964 1.204419 5.727079 ... 1003.193909 388.462433 2.298174 0.673137 2.620608e+06 1.742066e+06 1.990636 1.165608 0.038632 0.012656
50% 0.990684 18.754087 3.416813 0.422366 0.098511 11.744920 29.479961 1.685290 2.010876 8.556026 ... 1378.125000 627.297546 2.775611 0.956109 3.019486e+06 2.246092e+06 3.288788 2.212921 0.051336 0.018890
75% 0.990684 22.895193 4.060770 0.488050 0.125469 57.957664 69.372818 3.784954 3.243660 13.196887 ... 2060.806641 990.779724 3.632514 1.734663 3.373299e+06 2.829660e+06 5.056057 3.150032 0.067383 0.027325
max 0.990684 26.508205 8.019904 0.636219 0.264137 9113.940430 22528.574219 33.979153 56.715878 26.559134 ... 4256.789551 2818.890381 9.847502 5.231009 6.583575e+06 6.047924e+06 11.551766 11.142886 0.162156 0.109800

8 rows × 84 columns

Gözlem: Özniteliklerin dinamik aralıkları çok farklı, normalize etmeliyiz. Bazı öznitelikler (örneğin average_loudness) bu problem için kullanılması anlamsız veya hemen hemen sabit değerler içeriyor. Varyansı düşük öznitelikleri dışarıda bırakabiliriz.

Varyansı ortalama değerinin binde birinin altında olan kolonları dışarıda bırakalım.

dusuk_varyansli_oznitelikler = []
for kolon in tablo.columns:
    if kolon != 'enstruman':
        varyans = np.var(tablo[kolon])
        if varyans < np.mean(tablo[kolon]) * 0.001:
            print(
                kolon, ':\tvaryans =', np.var(tablo[kolon]),
                'ortalama =', np.mean(tablo[kolon]))
            dusuk_varyansli_oznitelikler.append(kolon)

print('Öznitelikler atılmadan önceki boyut:', tablo.shape)
tablo = tablo.drop(columns=dusuk_varyansli_oznitelikler)
skaler_secilmis_oznitelikler = list(tablo.columns)[:-1]
print('Öznitelikler atıldıktan sonraki boyut:', tablo.shape)
average_loudness :	varyans = 4.0925312732997144e-05 ortalama = 0.986378416187405
silence_rate_20dB.mean :	varyans = 3.3036432587549685e-06 ortalama = 0.9998688265449642
silence_rate_30dB.mean :	varyans = 7.037403313105313e-05 ortalama = 0.9991705213803701
spectral_decrease.stdev :	varyans = 6.4385830677640396e-18 ortalama = 3.731881534079091e-09
spectral_rms.mean :	varyans = 1.943454793577788e-06 ortalama = 0.004050059194575192
spectral_rms.stdev :	varyans = 2.65605378621194e-07 ortalama = 0.0019590600805086383
Öznitelikler atılmadan önceki boyut: (193, 85)
Öznitelikler atıldıktan sonraki boyut: (193, 79)

7.4.2. Özniteliklerin ön işlemesi#

Sınıflandırıcı modelimizi eğitmeye başlamadan önce öznitelik verimiz üzerinde uygulayabileceğimiz ön işleme adımlarına değinelim.

#### Normalizasyon

Öznitelik normalizasyonu makine öğrenmesi modelinin eğitilebilmesi için gerekli ön adımlardan birisidir. Özniteliklerin normalize edilmemesi (öznitelikler arasında büyük boyut farklılıklarının olması) optimizasyon sürecinde modelin iç parametrelerinin iyileştirilmesini zorlaştırmaktadır. Verimize baktığımızda örneğin melbands_kurtosis.mean ile melbands_flatness_db.mean büyüklükleri arasında 6000 kat civarında fark olduğunu gözlüyoruz. Öncelikle bu farklılıkları gidermeliyiz.

Çok farklı normalizasyon stratejileri mevcuttur ve kullanılan modele uygun bir strateji tercih edilmelidir. Bu konuda kısa bir özet incelemek isterseniz: Normalization Techniques At A Glance ya da Compare the effect of different scalers on data with outliers sayfalarını inceleyebilirsiniz. Bu bölümde yaygın kullanılan yöntemlerden birisi olan “Standard scaling”i sklearn kütüphanesinde gerçeklendiği şekliyle kullanacağız.

# sklearn kütüphanesinin preprocessing araçları ile normalizasyon
from sklearn import preprocessing

yeni_tablo = tablo.copy()
normalizasyon_araci = preprocessing.StandardScaler()
# aracının egitimi ve uygulanması (son kolon hariç)
yeni_tablo.iloc[:, :-1] = normalizasyon_araci.fit_transform(
    tablo.iloc[:, :-1].values)
yeni_tablo.describe()
barkbands_crest.mean barkbands_crest.stdev barkbands_flatness_db.mean barkbands_flatness_db.stdev barkbands_kurtosis.mean barkbands_kurtosis.stdev barkbands_skewness.mean barkbands_skewness.stdev barkbands_spread.mean barkbands_spread.stdev ... spectral_rolloff.mean spectral_rolloff.stdev spectral_skewness.mean spectral_skewness.stdev spectral_spread.mean spectral_spread.stdev spectral_strongpeak.mean spectral_strongpeak.stdev zerocrossingrate.mean zerocrossingrate.stdev
count 1.930000e+02 1.930000e+02 1.930000e+02 1.930000e+02 193.000000 193.000000 193.000000 1.930000e+02 1.930000e+02 1.930000e+02 ... 1.930000e+02 1.930000e+02 1.930000e+02 1.930000e+02 1.930000e+02 1.930000e+02 193.000000 1.930000e+02 1.930000e+02 1.930000e+02
mean 3.497490e-16 -7.363137e-17 -5.062157e-16 -7.363137e-17 0.000000 0.000000 0.000000 1.840784e-17 1.380588e-17 -1.196510e-16 ... 1.288549e-16 -9.203921e-18 3.681569e-17 -5.522353e-17 -1.656706e-16 -3.681569e-17 0.000000 1.840784e-17 7.363137e-17 -3.497490e-16
std 1.002601e+00 1.002601e+00 1.002601e+00 1.002601e+00 1.002601 1.002601 1.002601 1.002601e+00 1.002601e+00 1.002601e+00 ... 1.002601e+00 1.002601e+00 1.002601e+00 1.002601e+00 1.002601e+00 1.002601e+00 1.002601 1.002601e+00 1.002601e+00 1.002601e+00
min -2.413679e+00 -1.952222e+00 -2.153696e+00 -1.793942e+00 -0.285847 -0.254355 -1.815381 -5.420284e-01 -1.545996e+00 -1.593183e+00 ... -1.540341e+00 -1.348765e+00 -1.354567e+00 -1.097750e+00 -2.081652e+00 -1.876435e+00 -1.266000 -1.357416e+00 -1.604452e+00 -1.109786e+00
25% -7.997059e-01 -6.302225e-01 -7.936345e-01 -7.576492e-01 -0.279065 -0.249777 -0.461551 -4.143808e-01 -6.515713e-01 -6.398669e-01 ... -7.580944e-01 -6.642076e-01 -5.891650e-01 -7.037727e-01 -5.726574e-01 -6.140950e-01 -0.770718 -7.977397e-01 -7.035951e-01 -6.678179e-01
50% 3.649523e-03 -9.704619e-02 -1.014457e-01 -1.021422e-01 -0.272999 -0.242635 -0.318095 -3.119293e-01 -1.802482e-01 -1.189795e-01 ... -2.292518e-01 -2.376855e-01 -3.180864e-01 -3.878472e-01 -8.582672e-02 -1.728193e-01 -0.228351 -9.110318e-02 -1.680577e-01 -2.615907e-01
75% 8.919907e-01 4.385478e-01 7.313823e-01 5.693651e-01 -0.226651 -0.226487 0.024839 -1.553174e-01 5.929533e-01 4.127230e-01 ... 7.336749e-01 4.114366e-01 1.684453e-01 4.813732e-01 3.460025e-01 3.380943e-01 0.510013 5.411782e-01 5.084298e-01 2.881321e-01
max 1.667046e+00 3.731449e+00 2.610067e+00 4.023387e+00 8.855727 8.864420 4.956407 6.637749e+00 2.819201e+00 4.780104e+00 ... 3.831122e+00 3.676155e+00 3.697188e+00 4.384887e+00 4.264142e+00 3.155688e+00 3.223917 5.934067e+00 4.503764e+00 5.663165e+00

8 rows × 78 columns

Gözlem: Öznitelikler normalize edildi. Şimdi tablomuzu makine öğrenmesi araçlarının kabul ettiği matrislere dönüştürebiliriz

ÖNEMLİ: Problemin ve verinin doğasına bağlı olarak özniteliklere uygulanması gereken çok sayıda işlem olabilir. Örneğin boyut azaltma işlemlerine ihtiyaç duyulabilir. Defterimizin karmaşıklığını artırmamak için ön işlemeyi normalizasyon ile sınırlı tuttuk.

7.4.2.1. Veri örnek sayısını dengeleme#

Şimdi elimizdeki veri kümesinin kategorilere düşen örnek sayıları açısından dengeli olup olmadığına bakalım:

yeni_tablo.enstruman.value_counts()
violin        76
vibraphone    42
ebclar        39
flute         36
Name: enstruman, dtype: int64

Gözlem: Verilerimiz kategorilere ait örnek sayıları açısından dengeli değil, bazı kategorilerde diğerlerine göre daha fazla sayıda örnek var. Bir dengeleme işlemi uygulamakta fayda var. Dengeli olmayan veri kümeleri üzerinde de makine öğrenmesi testleri tasarlayabiliriz. Fakat örneği karmaşıklaştırmamak için bu konuyu bu bölümde ele almayacağız.

Kategorilere ait veri sayılarının dengelenmesi için farklı stratejiler uygulanabilir. Sık kullanılan iki yöntem alttaki figürlerde özetlenmiştir. Fazla olan örnekleri atarak denge kurulmasına “undersampling” ismi verilir ve bu bölümde bu teknik kullanılmıştır. Diğer bir alternatif az örnek bulunan kategoriye yeni örnekleri ya varolan örnekleri doğrudan kopyalayarak, ya da kategorisini bozmadan değiştirip kopyalayarak dengeyi sağlamaktır.

Balancing

Şekil 7.7: Veri dengeleme yöntemleri

En az sayıda örnek içeren küme flüt kümesi (36 örnek). Her kümede rasgele seçilmiş 36 örnek tutup gerisini dışarıda bırakarak örnek kümemizi dengeleyelim.

en_az_sayi = yeni_tablo.enstruman.value_counts()['flute']
violin_tablo = yeni_tablo[yeni_tablo.enstruman ==
                          'violin'].sample(n=en_az_sayi, random_state=0)
vibraphone_tablo = yeni_tablo[yeni_tablo.enstruman ==
                              'vibraphone'].sample(n=en_az_sayi, random_state=0)
ebclar_tablo = yeni_tablo[yeni_tablo.enstruman ==
                          'ebclar'].sample(n=en_az_sayi, random_state=0)
flute_tablo = yeni_tablo[yeni_tablo.enstruman == 'flute']
# Oluşturduğumuz küçültülmüş kümeleri birleştirelim
yeni_tablo = pd.concat(
    [ebclar_tablo, flute_tablo, violin_tablo, vibraphone_tablo])
# Dağılıma tekrar bakabiliriz
yeni_tablo.enstruman.value_counts()
ebclar        36
flute         36
violin        36
vibraphone    36
Name: enstruman, dtype: int64

7.5. Otomatik sınıflandırıcı eğitimi ve testi#

7.5.1. Öznitelikler ve etiketler için matrislerin formatlanması#

Öznitelikler (“inputs”, X) ve etiketler (“outputs”, y) için matrislerin formatlanması

Şimdi sınıflandırıcıların giriş-çıkış formatlarına uygun matrisleri hazırlayabiliriz. Giriş-çıkış formatlarını öğrenmek için scikit-learn dokümantasyonunu veya örneklerini inceleyebilirsiniz.

# Son kolon dışındaki kolonlar öznitelikleri içeriyor
# girdi matrisimiz (X) bu kolonlardan oluşacak.
X = yeni_tablo.iloc[:, :-1].values
# Çıktılar etiket bilgilerini içeriyor olacak. Bu bilgiler son kolonda bulunuyor.
# Sınıflandırıcı eğitiminde kullanabilmek için enstrüman ismi şeklinde
# saklanan bu bilgileri sayısal bilgilere dönüştürmemiz gerekli.

# enstruman verisini kategorik tür veriye dönüştürelim
yeni_tablo.enstruman = pd.Categorical(yeni_tablo.enstruman)
# her kategoriyi bir tam sayı olarak temsil edelim
y = np.array(yeni_tablo.enstruman.cat.codes)

print('İlk örneğin öznitelikleri:', X[0])
print('İlk örneğin etiketi:', y[0])

# Değerler: ebclar: 0, flute: 1, vibraphone: 2, violin: 3
print('Tüm etiket bilgileri:', y)
İlk örneğin öznitelikleri: [-0.4414347  -1.06871023 -0.59960443 -0.91132223 -0.27606381 -0.23232526
 -0.45138147 -0.22668588 -0.1121437  -0.28435331 -0.06325772 -0.14552512
  0.25726921 -0.32207451 -0.41512103 -0.9939726  -0.17804692 -0.50878155
 -0.86485942 -0.54866474 -1.31789831 -0.09244342  0.09912435  0.81744038
 -0.2809432   0.60497683  0.          0.63874899 -0.11270043  0.76832921
  0.         -1.26799778  0.1019887  -0.71195111 -1.04006459 -0.20598719
 -0.20330652 -0.29274    -0.23560128  0.14261715 -0.52647709  0.79948739
 -0.50821474 -0.07216878 -0.10154773 -0.64453122 -0.55969605 -0.68663291
  0.13648369  0.85922032  0.47382536 -1.52409208  1.50343256  0.23421587
 -0.40555442 -0.30418492 -0.17158886 -0.12661445  1.23797144  0.47120161
  0.44908563 -0.14400193  0.67301449 -0.41980772 -1.08669669 -0.58897149
 -0.45517733 -0.66206745 -0.85835363 -0.74775545 -0.29746722 -0.78064147
  0.40118828 -0.15235071  0.73555497 -0.07508544 -0.41698906 -0.81288885]
İlk örneğin etiketi: 0
Tüm etiket bilgileri: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3
 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]

7.5.2. Verinin eğitim ve test alt-kümelerine bölünmesi#

Veri setimizin bir kısmını sınıflandırıcıyı eğitirken, başka bir kısmını da eğittiğimiz sınıflandırıcıyı test etmek için kullanacağız.

# sklearn kütüphanesi train_test_split fonksiyonu ile veri setinin bölünmesi
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.33, random_state=42)

print('Eğitim kümesindeki öznitelikler matrisi boyutu:', X_train.shape,
      '\nEğitim kümesindeki etiket matrisi boyutu:', y_train.shape)
print('Test kümesindeki öznitelikler matrisi boyutu:', X_test.shape,
      '\nTest kümesindeki etiket matrisi boyutu:', y_test.shape)
Eğitim kümesindeki öznitelikler matrisi boyutu: (96, 78) 
Eğitim kümesindeki etiket matrisi boyutu: (96,)
Test kümesindeki öznitelikler matrisi boyutu: (48, 78) 
Test kümesindeki etiket matrisi boyutu: (48,)

### Makine öğrenmesi metodunun tanımlanması ve eğitilmesi

Şimdi bir makine öğrenmesi modeli eğitebiliriz. Bir destek vektör makinesi sınıflandırıcısı tanımlayıp eğitelim.

from sklearn import svm
# tanımlama adımı
clf = svm.SVC(gamma=1 / (X_train.shape[-1] * X_train.var()), random_state=0)
# eğitim adımı
clf.fit(X_train, y_train)
SVC(gamma=0.015687177800161187, random_state=0)

### Eğitilen modelin test edilmesi

Modelimiz eğitildiğine göre test verileri üzerinden testimizi yapabiliriz. Bunun için test kümesinin özniteliklerini sınıflandırıcıya vererek etiketi tahmin etmesini isteyeceğiz. Ardından tahmin edilen bu değerler ile gerçek etiketleri karşılaştıracağız.

# sınıflandırıcı aracılığyla özniteliklerden etiketlerin tahmin edilmesi
y_pred = clf.predict(X_test)

# Tahmin edilen etiketler ile gerçek etiketleri karşılaştıralım
tahmin_dogruluk_matrisi = y_test == y_pred

print(tahmin_dogruluk_matrisi)

# Verimiz dengeli olduğu için "accuracy" ölçütü sınıflandırıcımızın 
# performansını temsil eden önemli ölçütlerden birisi olarak düşünülebilir.
accuracy = np.sum(tahmin_dogruluk_matrisi)/len(tahmin_dogruluk_matrisi)
print('accuracy:', accuracy)
[ True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True False  True  True  True  True  True
  True  True  True  True  True  True False  True  True  True  True  True]
accuracy: 0.9583333333333334

Gözlem: Burada gözlediğimiz değer bize sistem performansı açısından önemli bir bilgi verse de bu değeri etkileyen farkında olmadığımız faktörler olabilir. Testimizin zayıf olduğu noktaları dikkatlice düşünmeli ve sonuçla beraber bunları raporlamalıyız. Örneğin veri kümemizdeki örnek sayısı gerçek dünyayı temsil edemeyecek kadar az. Bu sebeple gerçek bir uygulamada bu sınıflandırıcının başarısının yukarıda raporlanan düzeydekinden farklı olacağını bilmeliyiz.

Ayrıca testlerimizde yanlılık oluşturacak önemli bir faktör var!!: Örneklerimizi oluştururken dosyalardan parçalar aldık. Rasgele parçaları kararak yaptığımız testlerde eğitim kümesindeki ve test kümesindeki parçalar birbirlerinden farklı olmakla beraber aynı dosyalardan gelebiliyorlardı. Oysaki test kümesi ile eğitim kümesi arasında bu tür bağların olmaması gerekir. Sizin fark ettiğiniz başka sorunlar var mı?

!!! İlk testte 0.9 üzeri bir sonuç elde ettiyseniz özellikle şüphelenin: Kodunuzu kontrol edin. Test kümenizdeki verilerin gerçek uygulama koşullarında elde edilecek verileri temsil edip etmediğini sorgulayın. Test ve eğitim kümeleri arasında olası bağları sorgulayın.

Son adım olarak karıştırma matrisini (confusion matrix) çizdirip inceleyelim.

from sklearn.metrics import confusion_matrix
import seaborn as sns

siniflar = np.unique(yeni_tablo.enstruman)
conf_mat = pd.DataFrame(confusion_matrix(y_test, y_pred),
                        columns=siniflar, index=siniflar)
conf_mat.index.name = 'Gerçek etiket'
conf_mat.columns.name = 'Tahmin edilen'
plt.figure(figsize=(7, 3))
sns.set(font_scale=1.2)
sns.heatmap(conf_mat, cmap='Blues', annot_kws={'size': 12}, annot=True)
<matplotlib.axes._subplots.AxesSubplot at 0x7fab2dbcb990>
../_images/07_OtomatikEnstrumanTanima_94_1.png

Şekil 7.8: Karıştırma matrisi

#### Eğittiğimiz sistemin verili bir ses dosyası üzerinde etiketleme işlemi için kullanılması

Eğitim ve test işlemlerini yaparak bir sınıflandırıcı hazırladık. Şimdi ise tasarlanmış bir sınıflandırıcının kullanım demosunu yapmak için veri kümemizdeki tüm örnekleri bu sınıflandırıcıdan geçireceğiz.

# Etiket değer-isim tablosu
siniflar = {0: 'ebclar', 1: 'flute', 2: 'vibraphone', 3: 'violin'}


def enstruman_tani(dosya, skaler_oznitelik_isimleri, normalizasyon_araci, siniflar, siniflandirici):
    '''
    Verili bir ses dosyasının hangi enstrümanın kaydı olduğunu tahmin eder ve
    çıktı olarak enstrüman ismini verir
    '''
    # Dosyanın özniteliklerinin hesaplanması
    oznitelikler, oznitelik_pencereler = es.MusicExtractor(
        lowlevelSilentFrames='drop', lowlevelFrameSize=2048,
        lowlevelHopSize=1024, lowlevelStats=['mean', 'stdev'])(dosya)
    # Özniteliklerin bir alt-kümesini kullanmıştık, onları seçelim
    secilmis_oznitelikler = [oznitelikler['lowlevel.'+oznitelik_ismi]
                             for oznitelik_ismi in skaler_oznitelik_isimleri]
    # Öznitelik değerlerine normalizasyon adımında tanımlanmış oranları uygulayalım
    oranlanmis_oznitelikler = normalizasyon_araci.transform(
        np.array(secilmis_oznitelikler).reshape(1, -1))

    # Sınıflandırıcı etiketi tahmin etsin
    y_pred = siniflandirici.predict(oranlanmis_oznitelikler)

    return siniflar[y_pred[0]]


# Her bir dosyanın otomatik sınıflandırılma işlemleri
for dosya in bolut_dosyalari:
    enstruman_tahmini = enstruman_tani(
        dosya, skaler_secilmis_oznitelikler, normalizasyon_araci, siniflar, clf)

    # Çıktıyı dosya ismiyle beraber yazdıralım
    print(dosya, ' dosyası sınıflandırma sonucu: ', enstruman_tahmini)
instrument/segments/Vibraphone_0.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_1.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_2.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_3.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_4.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_5.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_6.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_7.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_8.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_9.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_10.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_11.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_12.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_13.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_14.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_15.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_16.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_17.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_18.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_19.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_20.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_21.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_22.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_23.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_24.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_25.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_26.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_27.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_28.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_29.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_30.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_31.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_32.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_33.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_34.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_35.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_36.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_37.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_38.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_39.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_40.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/Vibraphone_41.wav  dosyası sınıflandırma sonucu:  vibraphone
instrument/segments/EbClar_0.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_1.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_2.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_3.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/EbClar_4.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/EbClar_5.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_6.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/EbClar_7.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_8.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_9.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_10.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_11.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_12.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_13.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_14.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_15.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_16.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_17.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_18.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_19.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_20.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_21.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_22.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_23.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_24.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_25.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_26.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_27.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_28.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_29.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_30.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_31.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_32.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_33.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_34.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_35.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_36.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_37.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/EbClar_38.wav  dosyası sınıflandırma sonucu:  ebclar
instrument/segments/Violin_0.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_1.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_2.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_3.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_4.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_5.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_6.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_7.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_8.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_9.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_10.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_11.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_12.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_13.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_14.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_15.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_16.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_17.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_18.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_19.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_20.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_21.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_22.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_23.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_24.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_25.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_26.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_27.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_28.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_29.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_30.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_31.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_32.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_33.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_34.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_35.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_36.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_37.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_38.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_39.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_40.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_41.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_42.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_43.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_44.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_45.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_46.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_47.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_48.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_49.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_50.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_51.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_52.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_53.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_54.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_55.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_56.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_57.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_58.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_59.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_60.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_61.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_62.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_63.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_64.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_65.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_66.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_67.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_68.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_69.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_70.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_71.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_72.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_73.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_74.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/Violin_75.wav  dosyası sınıflandırma sonucu:  violin
instrument/segments/flute_0.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_1.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_2.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_3.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_4.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_5.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_6.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_7.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_8.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_9.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_10.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_11.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_12.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_13.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_14.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_15.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_16.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_17.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_18.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_19.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_20.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_21.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_22.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_23.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_24.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_25.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_26.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_27.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_28.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_29.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_30.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_31.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_32.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_33.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_34.wav  dosyası sınıflandırma sonucu:  flute
instrument/segments/flute_35.wav  dosyası sınıflandırma sonucu:  flute

7.5.3. Birden fazla sınıflandırıcının karşılaştırılması#

Makine öğrenmesi problemlerini çalışırken hangi sınıflandırıcının probleme daha uygun olduğuna karar vermemiz gerekir. Çoğunlukla uygulanan yöntem, bir dizi sınıflandırıcıyı test etmek ve başarıları üzerinden sınıflandırıcıları karşılaştırmaktır. Şimdi birden fazla sınıflandırıcının bu problem üzerinde performansını karşılaştıracağız.

Birden fazla sınıflandırıcı karşılaştırmalı olarak test edildiğinde ya da bir sınıflandırıcının sonuçları farklı tasarım parametreleriyle incelendiğinde verilerin nasıl eğitim ve test kümelerine bölünmesi gerektiği üzerine dikkatlice düşünülmesi gereken bir noktadır. Genel prensip olarak test verisi hiçbir karar alma sürecinde kullanılmamalıdır. Çünkü test verisi sistemin karşılaşmadığı gerçek uygulama verilerini temsil eder. Ne bir modelin tasarım parametrelerine karar verirken, ne de çeşitli makine öğrenmesi modelleri arasında seçim yaparken test verisini kullanmalıyız. Bu durumda, eğitim kümemizde ikinci bir bölme işlemi yapmaya ihtiyaç duyarız (veri kümesinin train-validation-test olarak ayrılma ihtiyacı konusunda ilgili Wikipedia sayfasını okuyabilirsiniz). Bu bölme işlemi için tek seferde rasgele yapılacak bir bölünmede yapılacak seçimler her rasgele bölünmede farklı sonuç vereceği için tek eğitim-test yerine çok sayıda eğitim-test deneyi tasarlamakta fayda vardır. “Cros validation” ismi verilen bu süreci iyi anlamak ve doğru uygulamak deneylerimizin güvenilirliği açısından büyük önem arz etmektedir.

Şekil 7.9: Çapraz doğrulama süreci

# https://scikit-learn.org/stable/auto_examples/classification/plot_classifier_comparison.html
# bu implementasyon yukarıdaki örnekten esinlenerek oluşturulmuştur
# cross validasyonda kullanacağımız sınıflandırıcıları import edelim
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.gaussian_process.kernels import RBF
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.datasets import make_moons, make_circles, make_classification
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import warnings
warnings.filterwarnings('ignore')  # uyarıları bastıralım

siniflandiricilar = [
    KNeighborsClassifier(3),
    SVC(kernel='linear', C=0.025, random_state=0),
    SVC(gamma=1 / (X_train.shape[-1] * X_train.var()), random_state=0),
    GaussianProcessClassifier(1.0 * RBF(1.0), random_state=0),
    MLPClassifier(alpha=1, max_iter=1000, random_state=0),
    GaussianNB()]

isimler = ['KNN', 'Linear SVM', 'RBF SVM',
           'Gaussian Process', 'Neural Net', 'Naive Bayes']

# Test skorlarını saklamak için listeler oluşturalım
skorlar = {}
for isim in isimler:
    skorlar[isim] = []

# Veri setimizi eğitim ve test için ayıralım
X_train_val, X_test, y_train_val, y_test = train_test_split(
    X, y, test_size=0.20, random_state=0)

# daha güvenilir sonuçlar için testimizi 10 kere tekrar edelim
test_sayisi = 10
for iterasyon in range(test_sayisi):
    x_train, x_val, y_train, y_val = train_test_split(
        X_train_val, y_train_val, test_size=1/test_sayisi, random_state=iterasyon)
    # verinin normalize edilmesi (eğitim verisinden öğrenilip, eğitim ve test verisine uygulanır)
    scaler = StandardScaler().fit(x_train)
    norm_x_train = scaler.transform(x_train)
    norm_x_val = scaler.transform(x_val)

    # her bir sınıflandırıcıyı test edelim
    for isim, siniflandirici in zip(isimler, siniflandiricilar):
        siniflandirici.fit(norm_x_train, y_train)
        skor = siniflandirici.score(norm_x_val, y_val)
        skorlar[isim].append(skor)

for isim, skor in skorlar.items():
    print('{0}:\taccuracy = {1:1.2f}, +-{2:1.2f},\tdeğerler: {3}'.format(
        isim, np.mean(skor), np.std(skor), np.around(skor, decimals=4)))
KNN:	accuracy = 0.93, +-0.10,	değerler: [0.8333 0.6667 1.     1.     1.     1.     1.     1.     0.9167 0.9167]
Linear SVM:	accuracy = 0.97, +-0.08,	değerler: [1.     0.75   0.9167 1.     1.     1.     1.     1.     1.     1.    ]
RBF SVM:	accuracy = 0.96, +-0.08,	değerler: [0.9167 0.75   1.     1.     1.     1.     0.9167 1.     1.     1.    ]
Gaussian Process:	accuracy = 0.80, +-0.18,	değerler: [1.     0.75   1.     0.75   1.     0.6667 0.9167 0.75   0.75   0.4167]
Neural Net:	accuracy = 0.97, +-0.07,	değerler: [1.   0.75 1.   1.   1.   1.   1.   1.   1.   1.  ]
Naive Bayes:	accuracy = 0.92, +-0.07,	değerler: [0.9167 1.     1.     0.9167 0.75   0.9167 1.     0.9167 0.9167 0.8333]

Bu karşılaştırma sonucunda tercih ettiğiniz bir sınıflandırıcı var ise test verisi üzerindeki performansını raporlayabilirsiniz.

from sklearn.metrics import classification_report

scaler = StandardScaler().fit(X_train_val)
norm_x_train_val = scaler.transform(X_train_val)
norm_x_test = scaler.transform(X_test)
selected_model = SVC(kernel='linear', C=0.025, random_state=0)
selected_model.fit(norm_x_train_val, y_train_val)
y_pred = selected_model.predict(norm_x_test)
print('Test verisi sayısı:', len(y_pred))
print(classification_report(y_test, y_pred))
Test verisi sayısı: 29
              precision    recall  f1-score   support

           0       1.00      0.86      0.92         7
           1       1.00      1.00      1.00         8
           2       1.00      1.00      1.00         9
           3       0.83      1.00      0.91         5

    accuracy                           0.97        29
   macro avg       0.96      0.96      0.96        29
weighted avg       0.97      0.97      0.97        29

İsterseniz Sklearn kütüphanesindeki çapraz doğrulama araçlarını da kullanabilirsiniz.

from sklearn.model_selection import cross_val_score
skorlar = {}
for isim, siniflandirici in zip(isimler, siniflandiricilar):
    skorlar[isim] = cross_val_score(
        siniflandirici, X_train_val, y_train_val, cv=5)
for isim, skor in skorlar.items():
    print(isim, '\t, skorlar: ', skor)
KNN 	, skorlar:  [1.         1.         0.95652174 1.         0.95652174]
Linear SVM 	, skorlar:  [1.         0.95652174 1.         0.95652174 1.        ]
RBF SVM 	, skorlar:  [1.         1.         0.91304348 0.91304348 0.95652174]
Gaussian Process 	, skorlar:  [1. 1. 1. 1. 1.]
Neural Net 	, skorlar:  [1.         1.         1.         0.95652174 1.        ]
Naive Bayes 	, skorlar:  [0.91304348 0.95652174 0.7826087  0.95652174 0.95652174]

Bu karşılaştırmayı tamamladıktan sonra modeller arasından birisini seçip şimdi test kümemiz üzerinde performansını raporlayabiliriz.

from sklearn.metrics import classification_report
scaler = StandardScaler().fit(X_train_val)
norm_x_train_val = scaler.transform(X_train_val)
norm_x_test = scaler.transform(X_test)
# Linear SVM modelini seçtik
selected_model = SVC(kernel='linear', C=0.025, random_state=0)
selected_model.fit(norm_x_train_val, y_train_val)
y_pred = selected_model.predict(norm_x_test)

siniflar = ['ebclar', 'flute', 'vibraphone', 'violin']
conf_mat = pd.DataFrame(confusion_matrix(y_test, y_pred),
                        columns=siniflar, index=siniflar)
conf_mat.index.name = 'Gerçek etiket'
conf_mat.columns.name = 'Tahmin edilen'
plt.figure(figsize=(7, 5))
sns.set(font_scale=1.2)
sns.heatmap(conf_mat, cmap='Blues', annot_kws={'size': 12}, annot=True)

print('Test kümesi örnek sayısı:', len(y_pred))
print(classification_report(y_test, y_pred, target_names=siniflar))
Test kümesi örnek sayısı: 29
              precision    recall  f1-score   support

      ebclar       1.00      0.86      0.92         7
       flute       1.00      1.00      1.00         8
  vibraphone       1.00      1.00      1.00         9
      violin       0.83      1.00      0.91         5

    accuracy                           0.97        29
   macro avg       0.96      0.96      0.96        29
weighted avg       0.97      0.97      0.97        29
../_images/07_OtomatikEnstrumanTanima_109_1.png

Şekil 7.10: Karıştırma matrisi

7.5.4. Peki derin öğrenme modellerini kullanabilir miyiz?#

Derin öğrenme modellerinin performansı veri sayısının fazla olduğu durumlarda konvansiyonel modelleri aşmaktadır. Elimizdeki veri boyutu küçük olduğu için derin öğrenme modellerinin daha yüksek başarı göstermesini beklemiyoruz. Yine de altta bir örnek sunuyoruz.

# Yine verimizi eğitim ve test altkümelerine bölerek başlayalım
X_train_val, X_test, y_train_val, y_test = train_test_split(
    X, y, test_size=0.20, random_state=1)
# ..ve normalizasyon uygulayalım
scaler = StandardScaler().fit(X_train_val)
norm_x_train_val = scaler.transform(X_train_val)
norm_x_test = scaler.transform(X_test)

Sinir ağımız çıkış katmanında 4 (kategori sayısı kadar) nöron içerecek ve her nöron’un çıkışı ilgili örneğin o kategoriye ait olma olasılığını verecek. Bu, çıktının 0-1 arası değerler taşıyan 4 boyutlu bir vektör olduğu anlamına gelir. Eğitime başlayabilmek için elimizdeki etiket verilerini de bu temsile çevirmeliyiz. Örneğin: 'violin' sınıfına ait bir örnek 3 etiketi ile temsil ediliyor. Bunu yukarıda bahsedilen 4 boyutlu vektör şeklinde temsil ettiğimizde [0 0 0 1] vektörünü elde ederiz. Benzer şekilde bir 'ebclar' örneği için etiket 0 ve 4 boyutlu vektör temsili [1 0 0 0] olacaktır. Bu çeşit temsile one-hot encoding ismi verilmektedir. Bazen Türkçe makalelerde bu terim için “bir-sıcak temsil” gibi anlaşılması zor karşılıklar da kullanılmaktadır.

from sklearn.preprocessing import OneHotEncoder

onehot_encoder = OneHotEncoder(sparse=False)
y_train_val_onehot = onehot_encoder.fit_transform(
    y_train_val.reshape(len(y_train_val), 1))
y_test_onehot = onehot_encoder.fit_transform(y_test.reshape(len(y_test), 1))
print('One-hot encoding, y_train_val boyutu =', y_train_val_onehot.shape)
print('One-hot encoding, y_test boyutu =', y_test_onehot.shape)
One-hot encoding, y_train_val boyutu = (115, 4)
One-hot encoding, y_test boyutu = (29, 4)

Yapay sinir ağ modelimizi Keras kütüphanesini kullanarak tanımlayalım ve model özetini inceleyelim.

from keras.models import Sequential
from keras import layers


def model_olustur(oznitelik_sayisi):
    model = Sequential()

    # Giriş katmanı
    model.add(layers.BatchNormalization(
        name='InputLayer', input_shape=(oznitelik_sayisi,)))

    # 1. saklı katman
    model.add(layers.Dense(name='HiddenLayer_1', units=32))
    model.add(layers.BatchNormalization())
    model.add(layers.Activation('relu'))
    model.add(layers.Dropout(0.3))

    # 2. saklı katman
    model.add(layers.Dense(name='HiddenLayer_2', units=16))
    model.add(layers.BatchNormalization())
    model.add(layers.Activation('relu'))
    model.add(layers.Dropout(0.3))

    # Çıkış katmanı
    model.add(layers.Dense(name='Output_layer', units=4))
    model.add(layers.Activation('softmax'))

    return model


model = model_olustur(X_train_val.shape[1])
# model özetini inceleyelim
model.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 InputLayer (BatchNormalizat  (None, 78)               312       
 ion)                                                            
                                                                 
 HiddenLayer_1 (Dense)       (None, 32)                2528      
                                                                 
 batch_normalization (BatchN  (None, 32)               128       
 ormalization)                                                   
                                                                 
 activation (Activation)     (None, 32)                0         
                                                                 
 dropout (Dropout)           (None, 32)                0         
                                                                 
 HiddenLayer_2 (Dense)       (None, 16)                528       
                                                                 
 batch_normalization_1 (Batc  (None, 16)               64        
 hNormalization)                                                 
                                                                 
 activation_1 (Activation)   (None, 16)                0         
                                                                 
 dropout_1 (Dropout)         (None, 16)                0         
                                                                 
 Output_layer (Dense)        (None, 4)                 68        
                                                                 
 activation_2 (Activation)   (None, 4)                 0         
                                                                 
=================================================================
Total params: 3,628
Trainable params: 3,376
Non-trainable params: 252
_________________________________________________________________

Eğitim için bir optimizasyon algoritması seçip modeli derleyelim ve eğitimi başlatalım.

model.compile(optimizer='Adam', loss='categorical_crossentropy',
              metrics=['accuracy'])
summary = model.fit(X_train_val, y_train_val_onehot,
                    batch_size=32, epochs=100, validation_split=0.3, verbose=1,)
Epoch 1/100
3/3 [==============================] - 1s 102ms/step - loss: 1.5135 - accuracy: 0.3500 - val_loss: 1.3719 - val_accuracy: 0.4000
Epoch 2/100
3/3 [==============================] - 0s 12ms/step - loss: 1.4488 - accuracy: 0.2500 - val_loss: 1.3210 - val_accuracy: 0.4000
Epoch 3/100
3/3 [==============================] - 0s 12ms/step - loss: 1.3733 - accuracy: 0.3875 - val_loss: 1.2762 - val_accuracy: 0.4286
Epoch 4/100
3/3 [==============================] - 0s 13ms/step - loss: 1.4244 - accuracy: 0.3375 - val_loss: 1.2323 - val_accuracy: 0.4571
Epoch 5/100
3/3 [==============================] - 0s 13ms/step - loss: 1.3501 - accuracy: 0.3625 - val_loss: 1.1904 - val_accuracy: 0.5143
Epoch 6/100
3/3 [==============================] - 0s 13ms/step - loss: 1.1919 - accuracy: 0.5000 - val_loss: 1.1547 - val_accuracy: 0.5143
Epoch 7/100
3/3 [==============================] - 0s 13ms/step - loss: 1.2286 - accuracy: 0.4625 - val_loss: 1.1234 - val_accuracy: 0.5429
Epoch 8/100
3/3 [==============================] - 0s 13ms/step - loss: 1.2509 - accuracy: 0.4750 - val_loss: 1.0930 - val_accuracy: 0.5714
Epoch 9/100
3/3 [==============================] - 0s 12ms/step - loss: 1.1725 - accuracy: 0.5250 - val_loss: 1.0623 - val_accuracy: 0.6286
Epoch 10/100
3/3 [==============================] - 0s 13ms/step - loss: 1.1217 - accuracy: 0.4625 - val_loss: 1.0346 - val_accuracy: 0.7143
Epoch 11/100
3/3 [==============================] - 0s 12ms/step - loss: 1.0851 - accuracy: 0.5375 - val_loss: 1.0087 - val_accuracy: 0.7429
Epoch 12/100
3/3 [==============================] - 0s 13ms/step - loss: 0.9780 - accuracy: 0.6000 - val_loss: 0.9849 - val_accuracy: 0.7429
Epoch 13/100
3/3 [==============================] - 0s 12ms/step - loss: 1.0266 - accuracy: 0.5125 - val_loss: 0.9620 - val_accuracy: 0.8000
Epoch 14/100
3/3 [==============================] - 0s 13ms/step - loss: 1.0325 - accuracy: 0.5375 - val_loss: 0.9392 - val_accuracy: 0.8857
Epoch 15/100
3/3 [==============================] - 0s 13ms/step - loss: 1.0339 - accuracy: 0.5875 - val_loss: 0.9192 - val_accuracy: 0.8857
Epoch 16/100
3/3 [==============================] - 0s 13ms/step - loss: 0.9071 - accuracy: 0.6375 - val_loss: 0.9002 - val_accuracy: 0.8857
Epoch 17/100
3/3 [==============================] - 0s 13ms/step - loss: 0.9056 - accuracy: 0.6875 - val_loss: 0.8818 - val_accuracy: 0.8857
Epoch 18/100
3/3 [==============================] - 0s 13ms/step - loss: 0.8924 - accuracy: 0.5750 - val_loss: 0.8638 - val_accuracy: 0.9143
Epoch 19/100
3/3 [==============================] - 0s 14ms/step - loss: 0.8865 - accuracy: 0.6125 - val_loss: 0.8462 - val_accuracy: 0.8857
Epoch 20/100
3/3 [==============================] - 0s 12ms/step - loss: 0.8866 - accuracy: 0.5875 - val_loss: 0.8295 - val_accuracy: 0.8857
Epoch 21/100
3/3 [==============================] - 0s 14ms/step - loss: 0.8623 - accuracy: 0.6875 - val_loss: 0.8141 - val_accuracy: 0.8857
Epoch 22/100
3/3 [==============================] - 0s 13ms/step - loss: 0.8480 - accuracy: 0.6625 - val_loss: 0.7979 - val_accuracy: 0.8571
Epoch 23/100
3/3 [==============================] - 0s 14ms/step - loss: 0.9122 - accuracy: 0.6625 - val_loss: 0.7836 - val_accuracy: 0.8571
Epoch 24/100
3/3 [==============================] - 0s 13ms/step - loss: 0.8503 - accuracy: 0.6875 - val_loss: 0.7682 - val_accuracy: 0.8571
Epoch 25/100
3/3 [==============================] - 0s 12ms/step - loss: 0.8125 - accuracy: 0.6625 - val_loss: 0.7538 - val_accuracy: 0.8857
Epoch 26/100
3/3 [==============================] - 0s 14ms/step - loss: 0.7832 - accuracy: 0.6875 - val_loss: 0.7400 - val_accuracy: 0.8857
Epoch 27/100
3/3 [==============================] - 0s 12ms/step - loss: 0.7844 - accuracy: 0.7250 - val_loss: 0.7261 - val_accuracy: 0.8857
Epoch 28/100
3/3 [==============================] - 0s 13ms/step - loss: 0.7541 - accuracy: 0.7250 - val_loss: 0.7123 - val_accuracy: 0.8857
Epoch 29/100
3/3 [==============================] - 0s 13ms/step - loss: 0.7586 - accuracy: 0.7125 - val_loss: 0.6984 - val_accuracy: 0.8857
Epoch 30/100
3/3 [==============================] - 0s 13ms/step - loss: 0.7488 - accuracy: 0.7625 - val_loss: 0.6850 - val_accuracy: 0.9143
Epoch 31/100
3/3 [==============================] - 0s 14ms/step - loss: 0.7178 - accuracy: 0.8000 - val_loss: 0.6722 - val_accuracy: 0.9143
Epoch 32/100
3/3 [==============================] - 0s 11ms/step - loss: 0.7270 - accuracy: 0.7375 - val_loss: 0.6584 - val_accuracy: 0.9143
Epoch 33/100
3/3 [==============================] - 0s 12ms/step - loss: 0.7905 - accuracy: 0.7000 - val_loss: 0.6453 - val_accuracy: 0.9143
Epoch 34/100
3/3 [==============================] - 0s 12ms/step - loss: 0.5966 - accuracy: 0.8000 - val_loss: 0.6331 - val_accuracy: 0.9143
Epoch 35/100
3/3 [==============================] - 0s 11ms/step - loss: 0.7158 - accuracy: 0.7875 - val_loss: 0.6202 - val_accuracy: 0.9143
Epoch 36/100
3/3 [==============================] - 0s 11ms/step - loss: 0.6890 - accuracy: 0.7625 - val_loss: 0.6084 - val_accuracy: 0.9143
Epoch 37/100
3/3 [==============================] - 0s 13ms/step - loss: 0.5968 - accuracy: 0.8500 - val_loss: 0.5958 - val_accuracy: 0.9143
Epoch 38/100
3/3 [==============================] - 0s 12ms/step - loss: 0.6282 - accuracy: 0.8375 - val_loss: 0.5831 - val_accuracy: 0.9143
Epoch 39/100
3/3 [==============================] - 0s 16ms/step - loss: 0.6008 - accuracy: 0.8375 - val_loss: 0.5717 - val_accuracy: 0.9143
Epoch 40/100
3/3 [==============================] - 0s 14ms/step - loss: 0.5922 - accuracy: 0.8500 - val_loss: 0.5605 - val_accuracy: 0.9143
Epoch 41/100
3/3 [==============================] - 0s 14ms/step - loss: 0.6129 - accuracy: 0.8375 - val_loss: 0.5495 - val_accuracy: 0.9143
Epoch 42/100
3/3 [==============================] - 0s 12ms/step - loss: 0.6096 - accuracy: 0.8500 - val_loss: 0.5392 - val_accuracy: 0.9143
Epoch 43/100
3/3 [==============================] - 0s 12ms/step - loss: 0.6508 - accuracy: 0.7875 - val_loss: 0.5293 - val_accuracy: 0.9143
Epoch 44/100
3/3 [==============================] - 0s 12ms/step - loss: 0.5670 - accuracy: 0.8500 - val_loss: 0.5208 - val_accuracy: 0.9143
Epoch 45/100
3/3 [==============================] - 0s 13ms/step - loss: 0.5490 - accuracy: 0.8500 - val_loss: 0.5113 - val_accuracy: 0.9143
Epoch 46/100
3/3 [==============================] - 0s 13ms/step - loss: 0.5881 - accuracy: 0.8500 - val_loss: 0.5027 - val_accuracy: 0.9143
Epoch 47/100
3/3 [==============================] - 0s 14ms/step - loss: 0.5366 - accuracy: 0.8375 - val_loss: 0.4942 - val_accuracy: 0.9143
Epoch 48/100
3/3 [==============================] - 0s 14ms/step - loss: 0.5600 - accuracy: 0.8500 - val_loss: 0.4851 - val_accuracy: 0.9143
Epoch 49/100
3/3 [==============================] - 0s 13ms/step - loss: 0.5034 - accuracy: 0.8750 - val_loss: 0.4757 - val_accuracy: 0.9143
Epoch 50/100
3/3 [==============================] - 0s 14ms/step - loss: 0.5060 - accuracy: 0.9000 - val_loss: 0.4671 - val_accuracy: 0.9143
Epoch 51/100
3/3 [==============================] - 0s 13ms/step - loss: 0.4861 - accuracy: 0.9000 - val_loss: 0.4589 - val_accuracy: 0.9143
Epoch 52/100
3/3 [==============================] - 0s 13ms/step - loss: 0.5248 - accuracy: 0.8875 - val_loss: 0.4495 - val_accuracy: 0.9143
Epoch 53/100
3/3 [==============================] - 0s 13ms/step - loss: 0.5119 - accuracy: 0.8375 - val_loss: 0.4406 - val_accuracy: 0.9143
Epoch 54/100
3/3 [==============================] - 0s 16ms/step - loss: 0.4923 - accuracy: 0.9000 - val_loss: 0.4320 - val_accuracy: 0.9143
Epoch 55/100
3/3 [==============================] - 0s 12ms/step - loss: 0.4797 - accuracy: 0.8875 - val_loss: 0.4253 - val_accuracy: 0.9143
Epoch 56/100
3/3 [==============================] - 0s 14ms/step - loss: 0.4271 - accuracy: 0.9500 - val_loss: 0.4194 - val_accuracy: 0.9143
Epoch 57/100
3/3 [==============================] - 0s 13ms/step - loss: 0.4333 - accuracy: 0.8750 - val_loss: 0.4126 - val_accuracy: 0.9143
Epoch 58/100
3/3 [==============================] - 0s 13ms/step - loss: 0.4301 - accuracy: 0.9375 - val_loss: 0.4044 - val_accuracy: 0.9143
Epoch 59/100
3/3 [==============================] - 0s 13ms/step - loss: 0.4452 - accuracy: 0.9250 - val_loss: 0.3959 - val_accuracy: 0.9143
Epoch 60/100
3/3 [==============================] - 0s 13ms/step - loss: 0.4825 - accuracy: 0.8875 - val_loss: 0.3879 - val_accuracy: 0.9143
Epoch 61/100
3/3 [==============================] - 0s 15ms/step - loss: 0.4277 - accuracy: 0.9500 - val_loss: 0.3800 - val_accuracy: 0.9143
Epoch 62/100
3/3 [==============================] - 0s 13ms/step - loss: 0.4276 - accuracy: 0.9000 - val_loss: 0.3719 - val_accuracy: 0.9143
Epoch 63/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3919 - accuracy: 0.9000 - val_loss: 0.3640 - val_accuracy: 0.9143
Epoch 64/100
3/3 [==============================] - 0s 13ms/step - loss: 0.4503 - accuracy: 0.8750 - val_loss: 0.3563 - val_accuracy: 0.9143
Epoch 65/100
3/3 [==============================] - 0s 13ms/step - loss: 0.4671 - accuracy: 0.8625 - val_loss: 0.3485 - val_accuracy: 0.9143
Epoch 66/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3758 - accuracy: 0.9250 - val_loss: 0.3403 - val_accuracy: 0.9143
Epoch 67/100
3/3 [==============================] - 0s 13ms/step - loss: 0.4164 - accuracy: 0.8875 - val_loss: 0.3329 - val_accuracy: 0.9143
Epoch 68/100
3/3 [==============================] - 0s 14ms/step - loss: 0.4217 - accuracy: 0.9000 - val_loss: 0.3262 - val_accuracy: 0.9143
Epoch 69/100
3/3 [==============================] - 0s 24ms/step - loss: 0.3352 - accuracy: 0.9250 - val_loss: 0.3200 - val_accuracy: 0.9143
Epoch 70/100
3/3 [==============================] - 0s 12ms/step - loss: 0.3736 - accuracy: 0.9000 - val_loss: 0.3156 - val_accuracy: 0.9143
Epoch 71/100
3/3 [==============================] - 0s 11ms/step - loss: 0.3398 - accuracy: 0.9125 - val_loss: 0.3132 - val_accuracy: 0.9143
Epoch 72/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3090 - accuracy: 0.9500 - val_loss: 0.3110 - val_accuracy: 0.9143
Epoch 73/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3415 - accuracy: 0.9375 - val_loss: 0.3103 - val_accuracy: 0.9143
Epoch 74/100
3/3 [==============================] - 0s 12ms/step - loss: 0.3263 - accuracy: 0.9625 - val_loss: 0.3075 - val_accuracy: 0.9143
Epoch 75/100
3/3 [==============================] - 0s 14ms/step - loss: 0.3712 - accuracy: 0.9000 - val_loss: 0.3040 - val_accuracy: 0.9143
Epoch 76/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3398 - accuracy: 0.9125 - val_loss: 0.3002 - val_accuracy: 0.9143
Epoch 77/100
3/3 [==============================] - 0s 12ms/step - loss: 0.3620 - accuracy: 0.9250 - val_loss: 0.2962 - val_accuracy: 0.9143
Epoch 78/100
3/3 [==============================] - 0s 12ms/step - loss: 0.3580 - accuracy: 0.9250 - val_loss: 0.2932 - val_accuracy: 0.9143
Epoch 79/100
3/3 [==============================] - 0s 15ms/step - loss: 0.3286 - accuracy: 0.9125 - val_loss: 0.2884 - val_accuracy: 0.9143
Epoch 80/100
3/3 [==============================] - 0s 14ms/step - loss: 0.3224 - accuracy: 0.9125 - val_loss: 0.2845 - val_accuracy: 0.9143
Epoch 81/100
3/3 [==============================] - 0s 16ms/step - loss: 0.2693 - accuracy: 0.9625 - val_loss: 0.2804 - val_accuracy: 0.9143
Epoch 82/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3583 - accuracy: 0.9250 - val_loss: 0.2775 - val_accuracy: 0.9143
Epoch 83/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3136 - accuracy: 0.9500 - val_loss: 0.2747 - val_accuracy: 0.9143
Epoch 84/100
3/3 [==============================] - 0s 15ms/step - loss: 0.3203 - accuracy: 0.9625 - val_loss: 0.2704 - val_accuracy: 0.9143
Epoch 85/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3295 - accuracy: 0.9625 - val_loss: 0.2666 - val_accuracy: 0.9143
Epoch 86/100
3/3 [==============================] - 0s 12ms/step - loss: 0.2985 - accuracy: 0.9125 - val_loss: 0.2628 - val_accuracy: 0.9143
Epoch 87/100
3/3 [==============================] - 0s 14ms/step - loss: 0.2263 - accuracy: 0.9875 - val_loss: 0.2598 - val_accuracy: 0.9143
Epoch 88/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3150 - accuracy: 0.9250 - val_loss: 0.2564 - val_accuracy: 0.9143
Epoch 89/100
3/3 [==============================] - 0s 12ms/step - loss: 0.2487 - accuracy: 0.9500 - val_loss: 0.2523 - val_accuracy: 0.9143
Epoch 90/100
3/3 [==============================] - 0s 12ms/step - loss: 0.2719 - accuracy: 0.9625 - val_loss: 0.2496 - val_accuracy: 0.9143
Epoch 91/100
3/3 [==============================] - 0s 12ms/step - loss: 0.2230 - accuracy: 0.9750 - val_loss: 0.2469 - val_accuracy: 0.9143
Epoch 92/100
3/3 [==============================] - 0s 12ms/step - loss: 0.2897 - accuracy: 0.9125 - val_loss: 0.2437 - val_accuracy: 0.9143
Epoch 93/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3229 - accuracy: 0.9500 - val_loss: 0.2400 - val_accuracy: 0.9143
Epoch 94/100
3/3 [==============================] - 0s 13ms/step - loss: 0.2892 - accuracy: 0.9500 - val_loss: 0.2388 - val_accuracy: 0.9143
Epoch 95/100
3/3 [==============================] - 0s 13ms/step - loss: 0.3308 - accuracy: 0.9000 - val_loss: 0.2377 - val_accuracy: 0.9143
Epoch 96/100
3/3 [==============================] - 0s 14ms/step - loss: 0.2644 - accuracy: 0.9625 - val_loss: 0.2340 - val_accuracy: 0.9143
Epoch 97/100
3/3 [==============================] - 0s 13ms/step - loss: 0.2811 - accuracy: 0.9500 - val_loss: 0.2308 - val_accuracy: 0.9143
Epoch 98/100
3/3 [==============================] - 0s 13ms/step - loss: 0.2228 - accuracy: 0.9875 - val_loss: 0.2276 - val_accuracy: 0.9143
Epoch 99/100
3/3 [==============================] - 0s 15ms/step - loss: 0.2361 - accuracy: 1.0000 - val_loss: 0.2250 - val_accuracy: 0.9143
Epoch 100/100
3/3 [==============================] - 0s 12ms/step - loss: 0.2398 - accuracy: 0.9500 - val_loss: 0.2215 - val_accuracy: 0.9143

Modelimiz eğitildi. 'accuracy' modelin eğitim verisini ne düzeyde sınıflandırabildiğini, 'val_accuracy' ise modelin validasyon verisini ne düzeyde sınıflandırabildiğini gösteriyor. İki değer de 1’e yakın, sonuç iyi görünüyor.

Bu modelden memnun olduğumuzu varsayalım ve son olarak test verisindeki başarıyı raporlayalım.

score = model.evaluate(X_test, y_test_onehot, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
Test loss: 0.2821633815765381
Test accuracy: 0.8620689511299133

Eğitim/öğrenme sürecinde her bir ‘epoch’ta çıktıların nasıl değiştiğinin görselleştirilmesi yaygın bir uygulamadır. Bu, eğitim için yapılan seçimler (optimizasyon algoritması, epoch sayısı, vb.) ve modelin eğitim verisini ezberleyip ezberlemediği konusunda gözlemler yapmamıza imkan tanır. Son olarak eğitim eğrilerini çizdirelim.

plt.plot(summary.history['accuracy'])
plt.plot(summary.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='lower right')
plt.show()

plt.plot(summary.history['loss'])
plt.plot(summary.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper right')
plt.show()
../_images/07_OtomatikEnstrumanTanima_123_0.png ../_images/07_OtomatikEnstrumanTanima_123_1.png

Şekil 7.11: Öğrenme eğrileri

7.6. Egzersiz/Ödev#

Bu bölümde otomatik enstrüman sınıflandırması için bir örnek gördünüz. Şimdi isterseniz başka bir veri kümesinde aynı deneyi tekrarlamayı deneyebilirsiniz. Bunun için CompMusic projesinde toplanmış verilerden Mridangam Stroke datasetini kullanabilirsiniz. Amaç 10 farklı vuruş sınıfını veya 6 farklı tonik sınıfını en yüksek doğruluk ile sınıflandırabilen bir sistemi tasarlamak.

Bu bölümde yapılana benzer şekilde tasarımınızı gerçekleştirdikten sonra isterseniz özniteliklere boyut azaltma (dimensionality reduction) tekniklerini uygulayıp performansa etkisini gözleyebilirsiniz.

Yazar: Barış Bozkurt, editör: Ahmet Uysal