.. _sec_ndarray:
Veri ile Oynama Yapmak
======================
Bir şeylerin yapılabilmesi için, verileri depolamak ve oynama yapmak
(manipule etmek) için bazı yollar bulmamız gerekiyor. Genellikle
verilerle ilgili iki önemli şey vardır: (i) Bunları elde etmek; ve (ii)
bilgisayar içine girdikten sonra bunları işlemek. Veri depolamanın bir
yolu olmadan onu elde etmenin bir anlamı yok, bu yüzden önce sentetik
(yapay) verilerle oynayarak ellerimizi kirletelim. Başlamak için, *gerey
(tensör)* olarak da adlandırılan :math:`n` boyutlu diziyi tanıtalım.
Python'da en çok kullanılan bilimsel hesaplama paketi olan NumPy ile
çalıştıysanız, bu bölümü tanıdık bulacaksınız. Hangi çerçeveyi
kullanırsanız kullanın, *tensör sınıfı* (MXNet'teki ``ndarray``, hem
PyTorch hem de TensorFlow'daki ``Tensor``), fazladan birkaç vurucu
özellik ile NumPy'nin ``ndarray``'ına benzer. İlk olarak, GPU hesaplama
hızlandırmayı iyi desteklerken, NumPy sadece CPU hesaplamasını
destekler. İkincisi, tensör sınıfı otomatik türev almayı destekler. Bu
özellikler, tensör sınıfını derin öğrenme için uygun hale getirir. Kitap
boyunca, tensörler dediğimizde, aksi belirtilmedikçe tensör sınıfının
örneklerinden bahsediyoruz.
Başlangıç
---------
Bu bölümde, sizi ayaklandırıp koşturmayı, kitapta ilerledikçe üstüne
koyarak geliştireceğiniz temel matematik ve sayısal hesaplama
araçlarıyla donatmayı amaçlıyoruz. Bazı matematiksel kavramları veya
kütüphane işlevlerini içselleştirmede zorlanıyorsanız, endişelenmeyin.
Aşağıdaki bölümlerde bu konular pratik örnekler bağlamında tekrar ele
alınacak ve yerine oturacak. Öte yandan, zaten biraz bilgi birikiminiz
varsa ve matematiksel içeriğin daha derinlerine inmek istiyorsanız, bu
bölümü atlayabilirsiniz.
.. raw:: html
.. raw:: html
Başlarken, MXNet'ten ``np`` (``numpy``) ve ``npx`` (``numpy_extension``)
modüllerini içe aktarıyoruz (import). Burada, np modülü, NumPy
tarafından desteklenen işlevleri içerirken, npx modülü, NumPy benzeri
bir ortamda derin öğrenmeyi güçlendirmek için geliştirilmiş bir dizi
uzantıyı içerir. Tensörleri kullanırken neredeyse her zaman ``set_np``
işlevini çağırırız: Bu, tensör işlemenin MXNet'in diğer bileşenlerine
uyumluluğu içindir.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
from mxnet import np, npx
npx.set_np()
.. raw:: html
.. raw:: html
Başlamak için ``torch``\ u içe aktarıyoruz. PyTorch olarak adlandırılsa
da, ``pytorch`` yerine ``torch``\ u içe aktarmamız gerektiğini
unutmayın.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import torch
.. raw:: html
.. raw:: html
Başlamak için, ``tensorflow``\ u içe aktarıyoruz. İsim biraz uzun olduğu
için, genellikle kısa bir takma ad olan ``tf`` ile içe aktarırız.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import tensorflow as tf
.. raw:: html
.. raw:: html
Bir tensör, (muhtemelen çok boyutlu) bir sayısal değerler dizisini
temsil eder. Bir eksende, tensöre *vektör* denir. İki eksende, tensöre
*matris* denir. İkiden fazla ekseni olan tensörlerin özel matematik
isimleri yoktur. :math:`k > 2` eksende, tensörlerin özel adları yoktur,
bu nesnelere :math:`k.` *dereceli tensörler* deriz.
.. raw:: html
.. raw:: html
MXNet, değerlerle önceden doldurulmuş yeni tensörler oluşturmak için
çeşitli işlevler sağlar. Örneğin, ``arange(n)``'yi çağırarak, 0'dan
başlayarak (dahil) ve ``n`` ile biten (dahil değil) eşit aralıklı
değerlerden oluşan bir vektör oluşturabiliriz. Varsayılan olarak, aralık
boyutu :math:`1`'dir. Aksi belirtilmedikçe, yeni tensörler ana bellekte
depolanır ve CPU tabanlı hesaplama için atanır.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x = np.arange(12)
x
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.])
.. raw:: html
.. raw:: html
PyTorch, değerlerle önceden doldurulmuş yeni tensörler oluşturmak için
çeşitli işlevler sağlar. Örneğin, ``arange(n)``'yi çağırarak, 0'dan
başlayarak (dahil) ve ``n`` ile biten (dahil değil) eşit aralıklı
değerlerden oluşan bir vektör oluşturabiliriz. Varsayılan olarak, aralık
boyutu :math:`1`'dir. Aksi belirtilmedikçe, yeni tensörler ana bellekte
depolanır ve CPU tabanlı hesaplama için atanır.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x = torch.arange(12, dtype=torch.float32)
x
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.])
.. raw:: html
.. raw:: html
TensorFlow, değerlerle önceden doldurulmuş yeni tensörler oluşturmak
için çeşitli işlevler sağlar. Örneğin, ``arange(n)``'yi çağırarak, 0'dan
başlayarak (dahil) ve ``n`` ile biten (dahil değil) eşit aralıklı
değerlerden oluşan bir vektör oluşturabiliriz. Varsayılan olarak, aralık
boyutu :math:`1`'dir. Aksi belirtilmedikçe, yeni tensörler ana bellekte
depolanır ve CPU tabanlı hesaplama için atanır.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x = tf.range(12, dtype=tf.float32)
x
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Bir tensörün *şekli*\ ne (her eksen boyunca uzunluk) ``shape``
özelliğini inceleyerek erişebiliriz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(12,)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
torch.Size([12])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x.shape
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
TensorShape([12])
.. raw:: html
.. raw:: html
Bir tensördeki toplam eleman sayısını, yani tüm şekil elemanlarının
çarpımını bilmek istiyorsak, boyutunu inceleyebiliriz. Burada bir
vektörle uğraştığımız için, ``shape`` (şeklinin) tek elemanı, vektör
boyutu ile aynıdır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x.size
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
12
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x.numel()
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
12
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
tf.size(x)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Eleman sayısını veya değerlerini değiştirmeden bir tensörün şeklini
değiştirmek için ``reshape`` işlevini çağırabiliriz. Örneğin, ``x``
tensörümüzü, (12,) şekilli bir satır vektöründen (3, 4) şekilli bir
matrise dönüştürebiliriz . Bu yeni tensör tam olarak aynı değerleri
içerir, ancak onları 3 satır ve 4 sütun olarak düzenlenmiş bir matris
olarak görür. Yinelemek gerekirse, şekil değişmiş olsa da, elemanlar
değişmemiştir. Boyutun yeniden şekillendirilme ile değiştirilmediğine
dikkat edin.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = x.reshape(3, 4)
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = x.reshape(3, 4)
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = tf.reshape(x, (3, 4))
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Her boyutu manuel olarak belirterek yeniden şekillendirmeye gerek
yoktur. Hedef şeklimiz (yükseklik, genişlik) şekilli bir matrisse, o
zaman genişliği bilirsek, yükseklik üstü kapalı olarak verilmiş olur.
Neden bölmeyi kendimiz yapmak zorunda olalım ki? Yukarıdaki örnekte, 3
satırlı bir matris elde etmek için, hem 3 satır hem de 4 sütun olması
gerektiğini belirttik. Neyse ki, tensörler, bir boyut eksik geri
kalanlar verildiğinde, kalan bir boyutu otomatik olarak çıkarabilir. Bu
özelliği, tensörlerin otomatik olarak çıkarımını istediğimiz boyuta
``-1`` yerleştirerek çağırıyoruz. Bizim durumumuzda, ``x.reshape(3, 4)``
olarak çağırmak yerine, eşit biçimde ``x.reshape(-1, 4)`` veya
``x.reshape(3, -1)`` olarak çağırabilirdik.
Tipik olarak, matrislerimizin sıfırlar, birler, diğer bazı sabitler veya
belirli bir dağılımdan rastgele örneklenmiş sayılarla başlatılmasını
isteriz. Tüm elemanları 0 olarak ayarlanmış ve (2, 3, 4) şeklindeki bir
tensörü temsil eden bir tensörü aşağıdaki şekilde oluşturabiliriz:
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
np.zeros((2, 3, 4))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
torch.zeros((2, 3, 4))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
tf.zeros((2, 3, 4))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Benzer şekilde, her bir eleman 1'e ayarlanmış şekilde tensörler
oluşturabiliriz:
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
np.ones((2, 3, 4))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],
[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
torch.ones((2, 3, 4))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],
[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
tf.ones((2, 3, 4))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Genellikle, bir tensördeki her eleman için değerleri bir olasılık
dağılımından rastgele örneklemek isteriz. Örneğin, bir sinir ağında
parametre görevi görecek dizileri oluşturduğumuzda, değerlerini
genellikle rastgele ilkletiriz. Aşağıdaki kod parçası (3, 4) şekilli bir
tensör oluşturur. Elemanlarının her biri ortalaması 0 ve standart
sapması 1 olan standart Gauss (normal) dağılımından rastgele örneklenir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
np.random.normal(0, 1, size=(3, 4))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[ 2.2122064 , 1.1630787 , 0.7740038 , 0.4838046 ],
[ 1.0434403 , 0.29956347, 1.1839255 , 0.15302546],
[ 1.8917114 , -1.1688148 , -1.2347414 , 1.5580711 ]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
torch.randn(3, 4)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[-0.5191, 0.0136, 0.9964, -0.6709],
[ 0.5979, -1.0787, 1.1654, 1.6462],
[-1.3329, 1.4749, -1.6688, 0.3651]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
tf.random.normal(shape=[3, 4])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Sayısal değerleri içeren bir Python listesi (veya liste listesi)
sağlayarak istenen tensördeki her eleman için kesin değerleri de
belirleyebiliriz. Burada, en dıştaki liste 0. eksene, içteki liste ise
1. eksene karşılık gelir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
np.array([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[2., 1., 4., 3.],
[1., 2., 3., 4.],
[4., 3., 2., 1.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[2, 1, 4, 3],
[1, 2, 3, 4],
[4, 3, 2, 1]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
tf.constant([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
İşlemler
--------
Bu kitap yazılım mühendisliği ile ilgili değildir. İlgi alanlarımız
basitçe dizilerden/dizilere veri okumak ve yazmakla sınırlı değildir. Bu
diziler üzerinde matematiksel işlemler yapmak istiyoruz. En basit ve en
kullanışlı işlemlerden bazıları *eleman yönlü (elementwise)*
işlemlerdir. Bunlar bir dizinin her elemanına standart bir sayıl işlem
uygular. İki diziyi girdi olarak alan işlevler için, eleman yönlü
işlemler iki diziden karşılık gelen her bir eleman çiftine standart bir
ikili operatör uygular. Sayıldan sayıla eşleşen herhangi bir
fonksiyondan eleman yönlü bir fonksiyon oluşturabiliriz.
Matematiksel gösterimde, böyle bir *tekli* skaler işlemi (bir girdi
alarak) :math:`f: \mathbb{R} \rightarrow \mathbb{R}` imzasıyla ifade
ederiz. Bu, işlevin herhangi bir gerçel sayıdan (:math:`\mathbb{R}`)
diğerine eşlendiği anlamına gelir. Benzer şekilde,
:math:`f: \mathbb{R}, \mathbb{R} \rightarrow \mathbb{R}` imzası ile bir
*ikili* skaler operatörü (iki gerçel girdi alarak ve bir çıktı verir)
belirtiriz. *Aynı şekilli* iki :math:`\mathbf{u}` ve :math:`\mathbf{v}`
vektörü ve :math:`f` ikili operatörü verildiğinde, tüm :math:`i`\ ler
için :math:`c_i \gets f(u_i, v_i)` diye ayarlayarak
:math:`\mathbf{c} = F(\mathbf{u},\mathbf{v})` vektörünü üretebiliriz;
burada :math:`c_i, u_i` ve :math:`v_i`, :math:`\mathbf{c}, \mathbf{u}`
ve :math:`\mathbf{v}` vektörlerinin :math:`i.` elemanlarıdır. Burada,
skaler fonksiyonu eleman yönlü bir vektör işlemini *yükselterek* vektör
değerli :math:`F: \mathbb{R}^d, \mathbb{R}^d \rightarrow \mathbb{R}^d`
ürettik.
Ortak standart aritmetik operatörler (``+``, ``-``, ``*``, ``/`` ve
``**``), rastgele şekile sahip herhangi bir benzer şekilli tensörler
için eleman yönlü işlemlere *yükseltilmiştir*. Aynı şekle sahip herhangi
iki tensör üzerinde eleman yönlü işlemleri çağırabiliriz. Aşağıdaki
örnekte, 5 öğeli bir grubu formüle etmek için virgül kullanıyoruz, her
öğe eleman yönlü bir işlemin sonucudur.
İşlemler
~~~~~~~~
Genel standart aritmatik işlemler (``+``, ``-``, ``*``, ``/``, ve
``**``) eleman yönlü işlemlere *yükseltilmiştir*.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x = np.array([1, 2, 4, 8])
y = np.array([2, 2, 2, 2])
x + y, x - y, x * y, x / y, x ** y # ** işlemi kuvvet almadır.
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(array([ 3., 4., 6., 10.]),
array([-1., 0., 2., 6.]),
array([ 2., 4., 8., 16.]),
array([0.5, 1. , 2. , 4. ]),
array([ 1., 4., 16., 64.]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
x + y, x - y, x * y, x / y, x ** y # ** işlemi kuvvet almadır.
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(tensor([ 3., 4., 6., 10.]),
tensor([-1., 0., 2., 6.]),
tensor([ 2., 4., 8., 16.]),
tensor([0.5000, 1.0000, 2.0000, 4.0000]),
tensor([ 1., 4., 16., 64.]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
x = tf.constant([1.0, 2, 4, 8])
y = tf.constant([2.0, 2, 2, 2])
x + y, x - y, x * y, x / y, x ** y # ** işlemi kuvvet almadır.
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(,
,
,
,
)
.. raw:: html
.. raw:: html
Kuvvet alma gibi tekli operatörler de dahil olmak üzere, çok daha fazla
işlem eleman yönlü olarak uygulanabilir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
np.exp(x)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([2.7182817e+00, 7.3890562e+00, 5.4598148e+01, 2.9809580e+03])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
torch.exp(x)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
tf.exp(x)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Eleman yönlü hesaplamalara ek olarak, vektör iç çarpımı ve matris
çarpımı dahil olmak üzere doğrusal cebir işlemleri de
gerçekleştirebiliriz. Doğrusal cebirin önemli parçalarını (varsayılmış
hiçbir ön bilgi olmadan) :numref:`sec_linear-algebra` içinde
açıklayacağız.
Ayrıca birden fazla tensörü bir araya getirip daha büyük bir tensör
oluşturmak için uçtan uca *istifleyebiliriz*. Sadece tensörlerin bir
listesini vermeli ve sisteme hangi eksende birleştireceklerini
söylemeliyiz. Aşağıdaki örnek, satırlar (eksen 0, şeklin ilk öğesi) ile
sütunlar (eksen 1, şeklin ikinci öğesi) boyunca iki matrisi
birleştirdiğimizde ne olacağını gösterir. İlk çıktı tensörünün eksen-0
uzunluğunun (:math:`6`) iki girdi tensörünün eksen-0 uzunluklarının
(:math:`3 + 3`) toplamı olduğunu görebiliriz; ikinci çıktı tensörünün
eksen-1 uzunluğu (:math:`8`) iki girdi tensörünün eksen-1 uzunluklarının
(:math:`4 + 4`) toplamıdır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = np.arange(12).reshape(3, 4)
Y = np.array([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
np.concatenate([X, Y], axis=0), np.concatenate([X, Y], axis=1)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[ 2., 1., 4., 3.],
[ 1., 2., 3., 4.],
[ 4., 3., 2., 1.]]),
array([[ 0., 1., 2., 3., 2., 1., 4., 3.],
[ 4., 5., 6., 7., 1., 2., 3., 4.],
[ 8., 9., 10., 11., 4., 3., 2., 1.]]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[ 2., 1., 4., 3.],
[ 1., 2., 3., 4.],
[ 4., 3., 2., 1.]]),
tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.],
[ 4., 5., 6., 7., 1., 2., 3., 4.],
[ 8., 9., 10., 11., 4., 3., 2., 1.]]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = tf.reshape(tf.range(12, dtype=tf.float32), (3, 4))
Y = tf.constant([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
tf.concat([X, Y], axis=0), tf.concat([X, Y], axis=1)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(,
)
.. raw:: html
.. raw:: html
Bazen, *mantıksal ifadeler* aracılığıyla bir ikili tensör oluşturmak
isteriz. Örnek olarak ``X == Y``'yi ele alalım. Her konum için, eğer
``X`` ve ``Y`` bu konumda eşitse, yeni tensördeki karşılık gelen girdi 1
değerini alır, yani mantıksal ifade ``X == Y`` o konumda doğrudur; aksi
halde o pozisyon 0 değerini alır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X == Y
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[False, True, False, True],
[False, False, False, False],
[False, False, False, False]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X == Y
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[False, True, False, True],
[False, False, False, False],
[False, False, False, False]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X == Y
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Tensördeki tüm elemanların toplanması, sadece bir elemanlı bir tensör
verir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X.sum()
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array(66.)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X.sum()
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor(66.)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
tf.reduce_sum(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
.. _subsec_broadcasting:
Yayma Mekanizması
-----------------
Yukarıdaki bölümde, aynı şekle sahip iki tensör üzerinde eleman yönlü
işlemlerin nasıl yapıldığını gördük. Belli koşullar altında, şekiller
farklı olsa bile, *yayma mekanizmasını* çağırarak yine de eleman yönlü
işlemler gerçekleştirebiliriz. Bu mekanizma şu şekilde çalışır: İlk
olarak, bir veya her iki diziyi elemanları uygun şekilde kopyalayarak
genişletin, böylece bu dönüşümden sonra iki tensör aynı şekle sahip
olur. İkincisi, sonuç dizileri üzerinde eleman yönlü işlemleri
gerçekleştirin.
Çoğu durumda, bir dizinin başlangıçta yalnızca 1 uzunluğuna sahip olduğu
bir eksen boyunca yayın yaparız, aşağıdaki gibi:
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
a = np.arange(3).reshape(3, 1)
b = np.arange(2).reshape(1, 2)
a, b
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(array([[0.],
[1.],
[2.]]),
array([[0., 1.]]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a, b
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(tensor([[0],
[1],
[2]]),
tensor([[0, 1]]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
a = tf.reshape(tf.range(3), (3, 1))
b = tf.reshape(tf.range(2), (1, 2))
a, b
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(,
)
.. raw:: html
.. raw:: html
``a`` ve ``b`` sırasıyla :math:`3\times1` ve :math:`1\times2` matrisler
olduğundan, onları toplamak istiyorsak şekilleri uyuşmaz. Her iki
matrisin girdilerini aşağıdaki gibi daha büyük bir :math:`3\times2`
matrisine *yayınlıyoruz*: Her ikisini de eleman yönlü eklemeden önce
``a`` matrisi için sütunlar çoğaltılır ve ``b`` matrisi için satırlar
çoğaltılır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
a + b
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[0., 1.],
[1., 2.],
[2., 3.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
a + b
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[0, 1],
[1, 2],
[2, 3]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
a + b
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
İndeksleme ve Dilimleme
-----------------------
Diğer tüm Python dizilerinde olduğu gibi, bir tensördeki öğelere
indeksle erişilebilir. Herhangi bir Python dizisinde olduğu gibi, ilk
öğenin dizini 0'dır ve aralıklar ilk öğeyi içerecek ancak son öğeden
*öncesi* eklenecek şekilde belirtilir. Standart Python listelerinde
olduğu gibi, öğelere, negatif endeksler kullanarak listenin sonuna
göreceli konumlarına göre erişebiliriz.
Böylece, ``[-1]`` son elemanı ve ``[1:3]`` ikinci ve üçüncü elemanları
aşağıdaki gibi seçer:
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X[-1], X[1:3]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(array([ 8., 9., 10., 11.]),
array([[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]]))
Okumanın ötesinde, indeksleri belirterek matrisin elemanlarını da
yazabiliriz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X[1, 2] = 9
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[ 0., 1., 2., 3.],
[ 4., 5., 9., 7.],
[ 8., 9., 10., 11.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X[-1], X[1:3]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(tensor([ 8., 9., 10., 11.]),
tensor([[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]]))
Okumanın ötesinde, indeksleri belirterek matrisin elemanlarını da
yazabiliriz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X[1, 2] = 9
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 9., 7.],
[ 8., 9., 10., 11.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X[-1], X[1:3]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(,
)
TensorFlow'daki ``tensörler`` (``Tensors``) değişmezdir, ve atanamazlar.
TensorFlow'daki ``değişkenler`` (``Variables``) atanmayı destekleyen
durumların değiştirilebilir kapsayıcılardır. TensorFlow'daki
gradyanların ``değişken`` (``Variable``) atamaları aracılığıyla geriye
doğru akmadığını unutmayın.
Tüm ``değişkenler``\ e (``Variable``) bir değer atamanın ötesinde, bir
``değişken``\ in (``Variable``) öğelerini indeksler belirterek
yazabiliriz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X_var = tf.Variable(X)
X_var[1, 2].assign(9)
X_var
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Birden fazla öğeye aynı değeri atamak istiyorsak, hepsini indeksleriz ve
sonra da değer atarız. Örneğin, ``[0:2, :]`` birinci ve ikinci satırlara
erişir, burada ``:`` Eksen 1 (sütun) boyunca tüm elemanları alır. Biz
burada matrisler için indekslemeyi tartışırken, anlatılanlar açıkça
vektörler ve 2'den fazla boyuttaki tensörler için de geçerlidir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X[0:2, :] = 12
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[12., 12., 12., 12.],
[12., 12., 12., 12.],
[ 8., 9., 10., 11.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X[0:2, :] = 12
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[12., 12., 12., 12.],
[12., 12., 12., 12.],
[ 8., 9., 10., 11.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X_var = tf.Variable(X)
X_var[0:2, :].assign(tf.ones(X_var[0:2,:].shape, dtype = tf.float32) * 12)
X_var
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Belleği Kaydetme
----------------
Koşulan işlemler, sonuçların tutulması için yeni bellek ayrılmasına
neden olabilir. Örneğin, ``Y = X + Y`` yazarsak, ``Y``'yi göstermek için
kullanılan tensörden vazgeçer ve bunun yerine yeni ayrılan bellekteki
``Y``'yi işaret ederiz. Aşağıdaki örnekte, bunu, bize bellekteki
referans edilen nesnenin tam adresini veren Python'un ``id()``
fonksiyonu ile gösteriyoruz. ``Y = Y + X`` komutunu çalıştırdıktan
sonra, ``id(Y)`` ifadesinin farklı bir yeri gösterdiğini göreceğiz.
Bunun nedeni, Python'un önce ``Y + X`` değerini hesaplayarak sonuç için
yeni bellek ayırması ve ardından ``Y``'yi bellekteki bu yeni konuma
işaret etmesidir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
onceki = id(Y)
Y = Y + X
id(Y) == onceki
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
False
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
onceki = id(Y)
Y = Y + X
id(Y) == onceki
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
False
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
onceki = id(Y)
Y = Y + X
id(Y) == onceki
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
False
.. raw:: html
.. raw:: html
Bu iki nedenden dolayı istenmez olabilir. Birincisi, her zaman gereksiz
yere bellek ayırmaya çalışmak istemiyoruz. Makine öğrenmesinde yüzlerce
megabayt parametreye sahip olabilir ve hepsini saniyede birkaç kez
güncelleyebiliriz. Genellikle, bu güncellemeleri *yerinde* yapmak
isteyeceğiz. İkinci olarak, birden çok değişkenden aynı parametrelere
işaret edebiliriz. Yerinde güncelleme yapmazsak, diğer referanslar hala
eski bellek konumuna işaret eder ve bu da kodumuzun bazı bölümlerinin
yanlışlıkla eski parametrelere atıfta bulunmasını olası kılar.
.. raw:: html
.. raw:: html
Neyse ki, yerinde işlemler yapmak kolaydır. Bir işlemin sonucunu daha
önce ayrılmış bir diziye dilim gösterimi ile atayabiliriz, örneğin,
``Y[:] = ``. Bu kavramı göstermek için, önce başka bir ``Y`` ile
aynı şekle sahip yeni bir ``Z`` matrisi yaratıyoruz ve bir blok
:math:`0` girdisi tahsis etmek üzere ``zeros_like``'i kullanıyoruz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
Z = np.zeros_like(Y)
print('id(Z):', id(Z))
Z[:] = X + Y
print('id(Z):', id(Z))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
id(Z): 140323095769024
id(Z): 140323095769024
``X`` değeri sonraki hesaplamalarda yeniden kullanılmazsa, işlemin
bellek yükünü azaltmak için ``X[:] = X + Y`` veya ``X += Y``
kullanabiliriz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
onceki = id(X)
X += Y
id(X) == onceki
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
True
.. raw:: html
.. raw:: html
Neyse ki, yerinde işlemler yapmak kolaydır. Bir işlemin sonucunu daha
önce ayrılmış bir diziye dilim gösterimi ile atayabiliriz, örneğin,
``Y[:] = ``. Bu kavramı göstermek için, önce başka bir ``Y`` ile
aynı şekle sahip yeni bir ``Z`` matrisi yaratıyoruz ve bir blok
:math:`0` girdisi tahsis etmek üzere ``zeros_like``'i kullanıyoruz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
Z = torch.zeros_like(Y)
print('id(Z):', id(Z))
Z[:] = X + Y
print('id(Z):', id(Z))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
id(Z): 139926018572912
id(Z): 139926018572912
``X`` değeri sonraki hesaplamalarda yeniden kullanılmazsa, işlemin
bellek yükünü azaltmak için ``X[:] = X + Y`` veya ``X += Y``
kullanabiliriz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
onceki = id(X)
X += Y
id(X) == onceki
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
True
.. raw:: html
.. raw:: html
``Değişkenler`` (``Variable``), TensorFlow'daki değişken durum
kapsayıcılarıdır. Model parametrelerinizi saklamanın bir yolunu
sağlarlar. Bir işlemin sonucunu ``atama`` ile bir ``değişken``\ e
atayabiliriz. Bu kavramı göstermek için, :math:`0` girdilerinden oluşan
bir blok ayırmak için ``zeros_like`` kullanarak, başka bir ``Y`` tensörü
ile aynı şekle sahip bir ``değişken`` ``Z`` oluşturuyoruz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
Z = tf.Variable(tf.zeros_like(Y))
print('id(Z):', id(Z))
Z.assign(X + Y)
print('id(Z):', id(Z))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
id(Z): 140695000075712
id(Z): 140695000075712
Durumu bir ``değişken``\ de kalıcı olarak sakladığınızda bile, model
parametreleriniz olmayan tensörler için aşırı bellek tahsislerden
kaçınarak bellek kullanımınızı daha da azaltmak isteyebilirsiniz.
TensorFlow ``Tensör``\ leri değişmez olduğundan ve gradyanlar
``değişken`` atamalarından akmadığından, TensorFlow, yerinde tek bir
işlemi yürütmek için açıktan bir yol sağlamaz.
Ancak TensorFlow, hesaplamayı çalıştırmadan önce derlenen ve optimize
edilen bir TensorFlow çizgesinin içine sarmak için ``tf.function``
dekoratörü sağlar. Bu, TensorFlow'un kullanılmayan değerleri budamasına
ve artık gerekmeyen önceki tahsisleri yeniden kullanmasına olanak tanır.
Bu, TensorFlow hesaplamalarının bellek yükünü en aza indirir.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
@tf.function
def computation(X, Y):
Z = tf.zeros_like(Y) # Bu kullanılmayan değer budanacaktır
A = X + Y # Daha fazla gerekmediğinde tahsisler yeniden kullanılacaktır
B = A + Y
C = B + Y
return C + Y
computation(X, Y)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Diğer Python Nesnelerine Dönüştürme
-----------------------------------
.. raw:: html
.. raw:: html
NumPy tensörüne (``ndarray``) dönüştürmek veya tam tersi kolaydır.
Dönüştürülen sonuç belleği paylaşmaz. Bu küçük sıkıntı aslında oldukça
önemlidir: CPU veya GPU'larda işlem yaparken, Python'un NumPy paketinin
aynı bellek yığınıyla başka bir şey yapmak isteyip istemediğini görmek
için hesaplamayı durdurmak istemezsiniz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
A = X.asnumpy()
B = np.array(A)
type(A), type(B)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(numpy.ndarray, mxnet.numpy.ndarray)
.. raw:: html
.. raw:: html
NumPy tensörüne (``ndarray``) dönüştürmek veya tam tersi kolaydır. Torch
Tensörü ve numpy dizisi, temeldeki bellek konumlarını paylaşacak ve
yerinde bir işlemle birini değiştirmek diğerini de değiştirecektir.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
A = X.numpy()
B = torch.from_numpy(A)
type(A), type(B)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(numpy.ndarray, torch.Tensor)
.. raw:: html
.. raw:: html
NumPy tensörüne (``ndarray``) dönüştürmek veya tam tersi kolaydır.
Dönüştürülen sonuç belleği paylaşmaz. Bu küçük sıkıntı aslında oldukça
önemlidir: CPU veya GPU'larda işlem yaparken, Python'un NumPy paketinin
aynı bellek yığınıyla başka bir şey yapmak isteyip istemediğini görmek
için hesaplamayı durdurmak istemezsiniz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
A = X.numpy()
B = tf.constant(A)
type(A), type(B)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(numpy.ndarray, tensorflow.python.framework.ops.EagerTensor)
.. raw:: html
.. raw:: html
1-boyutlu tensörünü bir Python skalerine (sayılına) dönüştürmek için
``item`` işlevini veya Python'un yerleşik işlevlerini çağırabiliriz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
a = np.array([3.5])
a, a.item(), float(a), int(a)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(array([3.5]), 3.5, 3.5, 3)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
a = torch.tensor([3.5])
a, a.item(), float(a), int(a)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(tensor([3.5000]), 3.5, 3.5, 3)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
a = tf.constant([3.5]).numpy()
a, a.item(), float(a), int(a)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(array([3.5], dtype=float32), 3.5, 3.5, 3)
.. raw:: html
.. raw:: html
Özet
----
- Derin öğrenme için veri depolamada ve oynama yapmada ana arayüz
tensördür (:math:`n`-boyutlu dizi). Temel matematik işlemleri,
yayınlama, indeksleme, dilimleme, bellek tasarrufu ve diğer Python
nesnelerine dönüştürme gibi çeşitli işlevler sağlar.
Alıştırmalar
------------
1. Bu bölümdeki kodu çalıştırın. Bu bölümdeki ``X == Y`` koşullu
ifadesini, ``X < Y`` veya ``X > Y`` olarak değiştirin ve sonra ne tür
bir tensör alabileceğinizi görün.
2. Yayın mekanizmasındaki öğeye göre çalışan iki tensörü, diğer
şekillerle, örneğin 3 boyutlu tensörler ile değiştirin. Sonuç
beklendiği gibi mi?
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html