In [ ]:
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Bu egitim kitapciginda makine ogrenmesini kullanarak zambak ciceklerini turlerine gore siniflandirmayi ogrenecegiz. Bunun icin TensorFlow'un eager modunu kullanacagiz:
Burada yuksek-seviye TensorFlow kapsamlarini kullanacagiz:
Bu kitapcigi bircok TensorFlow programi gibi planladik:
TensorFlow'da dahil olmak uzere gerekli Python birimlerini iceri alalim ve eager modunu aktiflestirelim. Eager modu sayesinde TensorFlow operasyonlari aninda degerlendirir ve daha sonra yurutulecek bir computational graph(Hesap grafigi) olusturmak yerine somut degerler cikartir. Bu REPL ya da 'python'un etkilesimli konsoluna cok benzer. Eager modu Tensorlow >=1.8'da bulunmaktadir.
Eager modu bir kere aktive edildiginde ayni program icinde kapatilamaz. Detaylar icin eager modu rehberine bakiniz.
In [ ]:
import os
import matplotlib.pyplot as plt
import tensorflow.compat.v1 as tf
print("TensorFlow version: {}".format(tf.__version__))
print("Eager execution: {}".format(tf.executing_eagerly()))
Buldugunuz her zambak cicegini siniflandirmayi amaclayan bir botanikci oldugunuzu hayal edin. Makine ogrenmesi bunu istatistiksel olarak yapmanizi saglayan algoritmalar saglar. Ornegin, iyi bir makine ogrenmesi programi cicekleri resimlerine bakarak siniflandirabilir. Biz burada daha mutevazi bir yol izleyip zambaklari canak yapraklarinin ve tac yapraklarinin uzunluguna ve capina gore siniflandiracagiz.
300'den fazla zambak turu bulunmasina ragmen programimiz bunlardan ucunu siniflandiracak:
|
|
|
Figure 1. Iris setosa (by Radomil, CC BY-SA 3.0), Iris versicolor, (by Dlanglois, CC BY-SA 3.0), and Iris virginica (by Frank Mayfield, CC BY-SA 2.0). |
Sansimiza bir 120 zambak cicegi veri seti tac ve canak yapragi olculeri ile olusturulmus. Bu makine ogrenmesi siniflandirma problemine acemi olanlar icin populer bir veri setidir.
Veri seti dosyasini indirelim ve bu Python programi tarafindan kullanilabilecek yapiya cevirelim.
tf.keras.utils.get_file fonksiyonunu kullanarak egitim veri setini indirelim. Bu yontem indirilen dosyanin dosya yolunu geri dondurur.
In [ ]:
train_dataset_url = "https://storage.googleapis.com/download.tensorflow.org/data/iris_training.csv"
train_dataset_fp = tf.keras.utils.get_file(fname=os.path.basename(train_dataset_url),
origin=train_dataset_url)
print("Local copy of the dataset file: {}".format(train_dataset_fp))
In [ ]:
!head -n5 {train_dataset_fp}
Veri setine bu acidan baktigimizda sunlara dikkat edelim:
Simdi bu kodu yazalim:
In [ ]:
# CSV dosyasindaki sutun sirasi
column_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species']
feature_names = column_names[:-1]
label_name = column_names[-1]
print("Features: {}".format(feature_names))
print("Label: {}".format(label_name))
Her etiket bir dizgi adiyla baglantilidir (ornegin, "setosa"), ama makine ogrenmesi genellikler sayilarla calisir. Etiket sayilari su sekilde isimlerle eslestirilebilir:
0: Iris setosa1: Iris versicolor2: Iris virginicaOzellikler ve etiketlerle ilgili daha fazla bilgi almak istiyorsaniz buraya bakiniz.
In [ ]:
class_names = ['Iris setosa', 'Iris versicolor', 'Iris virginica']
tf.data.Dataseti olusturalimTensorFlow'un Dataset API'si veriyi modele yuklerken gorulen bircok durumu halledebilir. Veriyi okumak ve egitim icin uygun sekle sokmak icin yuksek-seviye bir API'dir. Detayli bilgi icin buraya bakiniz.
CSV bicimli metin dosyasi olarak elimizde olan veri setini make_csv_dataset fonksiyonunu kullanarak veriyi uygun sekle sokabiliriz. Bu fonksiyon egitim modelleri icin veri urettigi icin, varsayilan davranis verinin karistirilip (shuffle=True, shuffle_buffer_size=10000), veri setinin sonsuza kadar tekrarlanmasidir (num_epochs=None). Burada ayrica batch_size degistirgesini de belirtiyoruz.
In [ ]:
batch_size = 32
train_dataset = tf.contrib.data.make_csv_dataset(
train_dataset_fp,
batch_size,
column_names=column_names,
label_name=label_name,
num_epochs=1)
make_csv_dataset fonksiyonu (features, label) ikilisinden olusan bir tf.data.Dataset dondurur. Burada features bir sozluktur: {'feature_name': deger}
Eager modu aktive edildiginde bu 'Dataset' nesnesi yinelenebilir. Simdi ozelliklere goz atalim:
In [ ]:
features, labels = next(iter(train_dataset))
features
Benzer ozelliklerin bir araya getirildigine yani batched edildigine dikkat edelim. Her ornegin sutunlari eslestigi ozellik dizisine eklenir. batch_size degerini bu ozellik dizilerinde bulunan ornek sayisina esleyelim.
Bu 'batch'ten birkac ozelligi grafik halinde gosterirseniz gruplasmayi gorebilirsiniz:
In [ ]:
plt.scatter(features['petal_length'].numpy(),
features['sepal_length'].numpy(),
c=labels.numpy(),
cmap='viridis')
plt.xlabel("Petal length")
plt.ylabel("Sepal length")
plt.show()
Model olustuma basamagini kolaylastirmak icin, ozellik sozlugunu (batch_size, num_features) sekli olan bir diziye cevirecek bir fonksiyon yazalim.
Bu fonksiyon tensor dizisindeki degerleri alarak belirli boyuttaki birlestirilmis tensoru olusturan tf.stack yontemini kullanir.
In [ ]:
def pack_features_vector(features, labels):
"""Ozellikleri tek bir diziye paketleyelimPack the features into a single array."""
features = tf.stack(list(features.values()), axis=1)
return features, labels
Sonrasinda tf.data.Dataset.map yontemi ile her (features,label) ikisindeki featuresi egitim veri setine paketleyelim:
In [ ]:
train_dataset = train_dataset.map(pack_features_vector)
Dataset icindeki ozellik elemani simdi (batch_size, num_features) sekli olan dizilerdir. Ilk birkac ornege bakalim:
In [ ]:
features, labels = next(iter(train_dataset))
print(features[:5])
Model ozelliklerle etiketler arasindaki etkilesimdir. Zambak siniflandirmasi probleminde ise modelimiz tac yaprak ve canak yaprak olculeri ile tahmin edilen Zambak turleri arasindaki iliskiyi belirler. Bazi basit modeller birkac satir matematiksel islemle aciklanabilirken kompleks makine ogrenmesi modellerini aciklamak cok sayida degistirgenin bulunmasi sebebiyle cok zordur.
Makine ogrenmesini kullanmadan Zambak turleri ve ozellikleri arasindaki iliskiyi kurabilir miydiniz? Yani kosullu deyimler gibi geleneksel programlama tekniklerini kullanarak bir model olusturabilir miydiniz? Eger verileri yeteri kadar inceleyip elimizdeki olculerle Zambak turleri arasindaki iliskiyi bulabilirseniz belki modeli olusturabilirsiniz. Bu karisik veri setlerinde neredeyse imkansiz hale gelir. Iyi bir makine ogrenmesi modelinizi sizin yerinize olusturur. Eger dogru makine ogrenmesi modeline dogru ornekleri verebilirseniz program sizin yerinize bu iliskiyi belirler.
Simdi egitmek icin modelimizi secmeliyiz. Bircok model cesidi bulunur ve dogru modeli secmek deneyim gerektirir. Bu egitim sinir aglarini kullanarak Zambak siniflandirmasi problemini cozer. Sinir aglari ozelliklerle etiketler arasindaki kompleks iliskiyi bulabilir. Bir ya da birden fazla sakli katmanlar (hidden layers) seklinde organize olmus iyi yapilandirilmis bir grafiktir. Her sakli katman bir ya da birden fazla sinirden olusmustur. Bircok sinir agi kategorisi vardir ve bu program yogun (dense), ya da tamamen birbirine bagli sinir agini (fully-connected neural network) kullanir: bir katmandaki sinirler bir onceki katmandaki butun sinirlerden girdi baglantilarini alir. Asagidaki Sekil 2'de bir girdi katmani, iki sakli katman ve bir cikti katmanindan olusan yogun sinir aginin bir ornegini gorebilirsiniz:
|
|
|
Sekil 2. Ozellikleri, sakli katmanlari ve tahminleri olan bir sinir agi. |
Sekildeki modeli egitip etiketlenmemis bir ornek verdigimizde bize bu ornegin Zambak turlerinden birisi olup olmadigina yonelik bir tahmin yurutur. Bu tahmine cikarsama (inference) adi verilir. Bu ornekteki ciktilarin degerlerinin toplami 1.0 idir. Sekildeki tahminler ise soyledir: Iris setosa icin 0.02, Iris versicolor icin 0.95 ve Iris virginica icin 0.03. Bu modelimizin yuzde 95 olasikla etiketsiz ornegi Iris versicolor olarak tahmin ettigi anlamina gelir.
TensorFlow tf.keras API'si modelleri ve katmanlari olusturmak icin tavsiye edilen yontemdir. Keras her seyin birbirine baglanmasini hallederken sizin modeli olusturmaniz ve test etmeniz kolaylasir.
tf.keras.Sequential modeli dogrusal katman yiginidir. Yapicisi katman ornegi listesini alir. Ornegimizde bu liste her biri 10 dugumden olusan 2 Yogun (Dense) katman ve etiket tahminlerini temsil eden 3 dugumden olusan bir cikti katmanini kapsar. Ilk katmanin gereken degistirgesi input_shape, veri setindeki ozelliklere denk gelir.
In [ ]:
model = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation=tf.nn.relu, input_shape=(4,)), # girdi sekli gereklidir
tf.keras.layers.Dense(10, activation=tf.nn.relu),
tf.keras.layers.Dense(3)
])
Aktiflestirme fonksiyonu (activation function) katamnada bulunan her dugumun cikti seklini belirler. Bu tur dogrusal olmayan iliskiler onemlidir cunku onlar olmadan modelimiz tek katmanli gibi davranirdi. Bircok aktiflestirme turu bulunur, fakat gizli tabakalar icin ReLU yaygin olarak kullanilir.
Sakli katmanlarin ve sinirlerin sayisi problemin turune ve veri setine gore degisir. Makine ogrenmesinin butun alanlarinda oldugu gibi bunu yapmak biraz deneyim, biraz bilgi ve biraz test etme gerektirir. Genel bir kural koymamiz gerekirse sakli katman ve sinir sayisi arttikca modelimiz genelde daha guclenir, fakat boyle bir modeli verimli sekilde egitmek icin daha cok veriye ihtiyacimiz vardir.
In [ ]:
predictions = model(features)
predictions[:5]
In [ ]:
tf.nn.softmax(predictions[:5])
tf.argmaxi siniflar arasindan gecirerek tahmin edilen sinifin dizinini bulabiliriz. Fakat, modelimiz daha egitilmedigi icin tahminler iyi degildir.
In [ ]:
print("Prediction: {}".format(tf.argmax(predictions, axis=1)))
print(" Labels: {}".format(labels))
Egitim makine ogrenmesi modelinin derece derece eniyilestirilmesi ya da modelin veri setini ogrenmesi asamasidir. Hedef egitim veri setinin yapisini iyice ogrenerek bilinmeyen veri hakkinda tahmin yapabilmektir. Eger egitim setini cok iyi ogrenirse tahminler sadece bu veri setinde calisacak ve genelestirilemez olacaktir. Bu probleme asiri uyum (overfitting) adi verilir—bu tipki sorunun cozumunu anlamak yerine cevaplari ezberlemeye benzer.
Zambak siniflandirmasi problemi gozetimli makine ogrenmesi ornegidir: model etiketleri olan orneklerle egitilir. Gozetimsiz makine ogrenmesinde ise, orneklerin etiketleri yoktur. Etiket yerine model ozellikler arasindaki deseni bulmaya calisir.
Egitim ve degerlendirme asamalari modelin kaybini hesaplamalidir. Bu modelin tahminlerinin istenen etiketlerle farkini yani modelin ne kadar kotu calistigini hesaplar. Bu degeri kucultmeyi ve eniyilestirmeyi isteriz.
Modelimiz tf.keras.losses.categorical_crossentropy fonksiyonu ile kaybi hesaplar. Bu fonksiyon modelin sinif tahminlerini ve istenen etiketleri alir ve butun orneklerin kayip degerlerinin ortalamasini dondurur.
In [ ]:
def loss(model, x, y):
y_ = model(x)
return tf.losses.sparse_softmax_cross_entropy(labels=y, logits=y_)
l = loss(model, features, labels)
print("Loss test: {}".format(l))
tf.GradientTape kapsamini kullanarak modelimizi eniyilestirecek olan egimleri hesaplayabiliriz. Bu konuda daha cok ornek icin eager modu kitapcigina buradan bakabilirsiniz.
In [ ]:
def grad(model, inputs, targets):
with tf.GradientTape() as tape:
loss_value = loss(model, inputs, targets)
return loss_value, tape.gradient(loss_value, model.trainable_variables)
Eniyilestirici kayip fonkiyonunu en aza indirgemek icin hesaplanan egim degerlerini modelin degiskenlerine uygular. Kayip fonksiyonunu kivrimli bir yuzey olarak dusunebilirsini (Sekil 3) ve biz bu seklin en dusuk noktasini uzerinden gecerek bulmak istiyoruz. Egimler bizi en dik tirmanislara yonlendirir, bu yuzden biz ters yone dogru giderek tepeden asagiya hareket edecegiz. Her grup (batch) icin kayip ve egim degerlerini etkilesimli olarak hesaplayip egitim sirasinda modelimizi ayarlayacagiz. Modelimiz kaybi dusurmek icin yavas yavas agirliklar ve sapmalarin en iyi birlesimini bulacaktir. Kayip degeri ne kadar dusuk olursa modelimizin tahminleri o kadar iyi olur.
|
|
|
Sekil 3. Eniyilestirme algoritmalarinin zamanla 3D duzlemde goruntulenmesi. (Kaynak: Stanford class CS231n, MIT License, Goruntu: Alec Radford) |
TensorFlow'un egitim icin bircok eniyilestirme algoritmasi bulunmaktadir. Burada stochastic gradient descent (SGD) algoritmasini gerceklestiren tf.train.GradientDescentOptimizer kullaniyoruz. learning_rate degeri her yinelemede basamak degerini asagi ceker. Bu daha iyi sonuc almak icin degistireceginiz bir hyperparameter idir.
Eniyilestiriciyi (optimizer) ve global_step sayacini kuralim:
In [ ]:
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
global_step = tf.Variable(0)
Bunu bir eniyilestirme basamagini hesaplamak icin kullanacagiz:
In [ ]:
loss_value, grads = grad(model, features, labels)
print("Step: {}, Initial Loss: {}".format(global_step.numpy(),
loss_value.numpy()))
optimizer.apply_gradients(zip(grads, model.trainable_variables), global_step)
print("Step: {}, Loss: {}".format(global_step.numpy(),
loss(model, features, labels).numpy()))
Butun parcalar yerine geldigine gore modelimizi egitebiliriz! Egitim dongusu veri setindeki ornekleri modelimize vererek daha iyi tahminde bulunmasini saglar. Asagida egitim basamaklarini gorebilirsiniz:
x) ve etiketlerini (y) yakalayalim.eniyiseltirici (optimizer) kullanarak modelin degiskenlerini guncelleyelim.num_epochs degiskeni veri setinin ustunden kac dongu gececegini belirler. Bu icgudulerimize ters gelse de modeli daha uzun egitmek daha iyi bir model elde edecegimiz anlamina gelmez. num_epochs ayarlacabileceginiz bir hyperparameter'dir. Dogru devir sayisini secmek hem deneyim hem de test etmeyi gerektirir.
In [ ]:
## Not: Bu hucreyi tekrar calistirinca ayni model degiskenleri kullanilir
from tensorflow import contrib
tfe = contrib.eager
# sonuclari ileride goruntulemek icin tutalim
train_loss_results = []
train_accuracy_results = []
num_epochs = 201
for epoch in range(num_epochs):
epoch_loss_avg = tfe.metrics.Mean()
epoch_accuracy = tfe.metrics.Accuracy()
# Egitim dongusu - 32ser topluluk kullanarak
for x, y in train_dataset:
# Modeli eniyilestireliml
loss_value, grads = grad(model, x, y)
optimizer.apply_gradients(zip(grads, model.trainable_variables),
global_step)
# Ilerlemeyi takip edelim
epoch_loss_avg(loss_value) # su anki topluluk kaybini ekleyelim
# tahmin edilen etiketle asil etiketi karsilastir
epoch_accuracy(tf.argmax(model(x), axis=1, output_type=tf.int32), y)
# devri bitirelim
train_loss_results.append(epoch_loss_avg.result())
train_accuracy_results.append(epoch_accuracy.result())
if epoch % 50 == 0:
print("Epoch {:03d}: Loss: {:.3f}, Accuracy: {:.3%}".format(epoch,
epoch_loss_avg.result(),
epoch_accuracy.result()))
Modelin egitim surecini yazdirmak yardimci olsa da bu sureci gorebilmek daha da faydalidir. TensorBoard, TensorFlow ile gelen guzel bir goruntuleme aracidir, fakat basit cizimleri matplotlib birimi ile de yapabiliriz.
Bu cizimleri yorumlamak biraz deneyim gerektirir, fakat asil gormek istedigimiz sey kayip degerinin dusmesi ve dogruluk degerinin yukselmesidir.
In [ ]:
fig, axes = plt.subplots(2, sharex=True, figsize=(12, 8))
fig.suptitle('Training Metrics')
axes[0].set_ylabel("Loss", fontsize=14)
axes[0].plot(train_loss_results)
axes[1].set_ylabel("Accuracy", fontsize=14)
axes[1].set_xlabel("Epoch", fontsize=14)
axes[1].plot(train_accuracy_results)
plt.show()
Modelimizi egittigimize gore basarimi ustune istatistikleri alabiliriz.
Degerlendirme modelin tahminlerini ne kadar etkili yaptiginin belirlenmesi anlamina gelir. Zambak siniflandirmasinda modelin etkililigini belirlemek icin birkac canak yaprak ve tac yaprak olculerini modelimize verelim ve modelimize bunlarin hangi ture ait oldugunu tahmin etmesini soralim. Sonra modelin tahmini ile asil etiketi karsilastiralim. Ornegin, girdinin yarisinda dogru tahminde bulunan bir modelin dogruluk degeri 0.5 idir. Sekil 4'te 5 tahminden 4'unu tutturarak yuzde 80 dogruluk degerine sahip biraz daha etkili bir modeli gorebilirsiniz:
| Example features | Label | Model prediction | |||
|---|---|---|---|---|---|
| 5.9 | 3.0 | 4.3 | 1.5 | 1 | 1 |
| 6.9 | 3.1 | 5.4 | 2.1 | 2 | 2 |
| 5.1 | 3.3 | 1.7 | 0.5 | 0 | 0 |
| 6.0 | 3.4 | 4.5 | 1.6 | 1 | 2 |
| 5.5 | 2.5 | 4.0 | 1.3 | 1 | 1 |
|
Sekil 4. Yuzde 80 dogruluk degeri olan bir Zambak siniflandiricisi. | |||||
Modelin degerlendirilmesi modelin egitilmesine benzer. En buyuk fark orneklerin egitim setinden farkli bir test setinden gelmesidir. Modelin etkililigini adil sekilde degerlendirebilmek icin test orneklerinin egitim orneklerinden farkli olmasi gerekmektedir.
Test Dataset ile egitim Datasetnin kurulumu birbirine benzer. CSV metin dosyasini indirelim ve degerleri ayristiralim, sonra da siralarini karistiralim:
In [ ]:
test_url = "https://storage.googleapis.com/download.tensorflow.org/data/iris_test.csv"
test_fp = tf.keras.utils.get_file(fname=os.path.basename(test_url),
origin=test_url)
In [ ]:
test_dataset = tf.contrib.data.make_csv_dataset(
test_fp,
batch_size,
column_names=column_names,
label_name='species',
num_epochs=1,
shuffle=False)
test_dataset = test_dataset.map(pack_features_vector)
Egitim asamasindan farkli olarak, model test verisinin sadece tek bir devrini degerlendirir. Asagidaki kod hucresinde test setindeki her ornegi yineleyerek modelin tahmini ile asil etiketi karsilastiriyoruz. Boylece modelin dogrulugunu butun test setinde olcmus olacagiz.
In [ ]:
test_accuracy = tfe.metrics.Accuracy()
for (x, y) in test_dataset:
logits = model(x)
prediction = tf.argmax(logits, axis=1, output_type=tf.int32)
test_accuracy(prediction, y)
print("Test set accuracy: {:.3%}".format(test_accuracy.result()))
Ornegin son topluluktaki degere bakarak modelin genelde dogru oldugunu gorebiliriz:
In [ ]:
tf.stack([y,prediction],axis=1)
Bir modeli egittik ve Zambak turlerini siniflandirma da mukemmel olmasa da iyi oldugunu "kanitladik". Simdi bu modeli etiketsiz ornekler, yani ozellikleri bulunan ama etiketleri olmayan ornekler, ustunde tahmin yurutmek icin kullanalim.
Gercek hayatta, etiketsiz ornekler aplikasyonlar, CSV metinleri, ve veri besleyiciler gibi bircok farkli kaynaktan gelebilir. Simdilik biz tahmin yurutmek icin etiketsiz ornekleri kendimiz verecegiz. Hatirlarsaniz, etiket rakamlarini su sekilde isimlerle eslemistik:
0: Iris setosa1: Iris versicolor2: Iris virginica
In [ ]:
predict_dataset = tf.convert_to_tensor([
[5.1, 3.3, 1.7, 0.5,],
[5.9, 3.0, 4.2, 1.5,],
[6.9, 3.1, 5.4, 2.1]
])
predictions = model(predict_dataset)
for i, logits in enumerate(predictions):
class_idx = tf.argmax(logits).numpy()
p = tf.nn.softmax(logits)[class_idx]
name = class_names[class_idx]
print("Example {} prediction: {} ({:4.1f}%)".format(i, name, 100*p))