Parametre Yönetimi
==================
Bir mimari seçip hiper parametrelerimizi belirledikten sonra, hedefimiz
yitim işlevimizi en aza indiren parametre değerlerini bulmak olduğu
eğitim döngüsüne geçiyoruz. Eğitimden sonra, gelecekteki tahminlerde
bulunmak için bu parametrelere ihtiyacımız olacak. Ek olarak, bazen
parametreleri başka bir bağlamda yeniden kullanmak, modelimizi başka bir
yazılımda yürütülebilmesi için diske kaydetmek veya bilimsel anlayış
kazanma umuduyla incelemek için ayıklamak isteyeceğiz.
Çoğu zaman, ağır işlerin üstesinden gelmek için derin öğrenme
çerçevelerine dayanarak, parametrelerin nasıl beyan edildiğine ve
değiştirildiğine dair işin esas ayrıntıları görmezden gelebileceğiz.
Bununla birlikte, standart katmanlara sahip yığılmış mimarilerden
uzaklaştığımızda, bazen parametreleri bildirme ve onların üstünde oynama
yabani otlarına girmemizi gerekecektir. Bu bölümde aşağıdakileri ele
alıyoruz:
- Hata ayıklama, teşhis ve görselleştirmeler için parametrelere erişim.
- Parametre ilkletme.
- Parametreleri farklı model bileşenleri arasında paylaşma.
Tek bir gizli katmana sahip bir MLP'ye odaklanarak başlıyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
from mxnet import init, np, npx
from mxnet.gluon import nn
npx.set_np()
net = nn.Sequential()
net.add(nn.Dense(8, activation='relu'))
net.add(nn.Dense(1))
net.initialize() # Varsayılan ilkleme yöntemini kullan
X = np.random.uniform(size=(2, 4))
net(X) # İleri hesaplama
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[0.0054572 ],
[0.00488594]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import torch
from torch import nn
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))
X = torch.rand(size=(2, 4))
net(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[-0.4043],
[-0.3974]], grad_fn=
)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import tensorflow as tf
net = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(4, activation=tf.nn.relu),
tf.keras.layers.Dense(1),
])
X = tf.random.uniform((2, 4))
net(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Parametre Erişimi
-----------------
Zaten bildiğiniz modellerden parametrelere nasıl erişileceğiyle
başlayalım. Bir model ``Sequential`` sınıfı aracılığıyla
tanımlandığında, ilk olarak herhangi bir katmana, bir listeymiş gibi
modelde üzerinden indeksleme ile erişebiliriz. Her katmanın
parametreleri, özelliklerinde uygun bir şekilde bulunur. Tam bağlı
ikinci katmanın parametrelerini aşağıdaki gibi irdeleyebiliriz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(net[1].params)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
dense1_ (
Parameter dense1_weight (shape=(1, 8), dtype=float32)
Parameter dense1_bias (shape=(1,), dtype=float32)
)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(net[2].state_dict())
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
OrderedDict([('weight', tensor([[ 0.0882, -0.0851, -0.0998, -0.0520, 0.1348, 0.3360, -0.1585, -0.1034]])), ('bias', tensor([-0.3121]))])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(net.layers[2].weights)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
[, ]
.. raw:: html
.. raw:: html
Çıktı bize birkaç önemli şey gösteriyor. İlk olarak, bu tam bağlı
katman, sırasıyla o katmanın ağırlıklarına ve ek girdilerine karşılık
gelen iki parametre içerir. Her ikisi de tek hassas basamaklı kayan
virgüllü sayı (float32) olarak saklanır. Parametrelerin adlarının,
yüzlerce katman içeren bir ağda bile, her katmanın parametrelerini
benzersiz şekilde tanımlamamıza izin verdiğini unutmayın.
Hedeflenen Parametreler
~~~~~~~~~~~~~~~~~~~~~~~
Her parametrenin, parametre sınıfının bir örneği olarak temsil
edildiğine dikkat edin. Parametrelerle yararlı herhangi bir şey yapmak
için önce altta yatan sayısal değerlere erişmemiz gerekir. Bunu yapmanın
birkaç yolu var. Bazıları daha basitken diğerleri daha geneldir.
Aşağıdaki kod, bir parametre sınıfı örneği döndüren ikinci sinir ağı
katmanından ek girdiyi dışarı çıkarır ve dahası bu parametrenin değerine
erişim sağlar.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(type(net[1].bias))
print(net[1].bias)
print(net[1].bias.data())
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Parameter dense1_bias (shape=(1,), dtype=float32)
[0.]
Parametreler; değer, gradyanlar ve ek bilgiler içeren karmaşık
nesnelerdir. Bu nedenle değerleri açıkça talep etmemiz gerekiyor.
Değere ek olarak, her parametre gradyana erişmemize de izin verir. Henüz
bu ağ için geri yaymayı çağırmadığımız için, ağ ilk durumundadır.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net[1].weight.grad()
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[0., 0., 0., 0., 0., 0., 0., 0.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(type(net[2].bias))
print(net[2].bias)
print(net[2].bias.data)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Parameter containing:
tensor([-0.3121], requires_grad=True)
tensor([-0.3121])
Parametreler; değer, gradyanlar ve ek bilgiler içeren karmaşık
nesnelerdir. Bu nedenle değerleri açıkça talep etmemiz gerekiyor.
Değere ek olarak, her parametre gradyana erişmemize de izin verir. Henüz
bu ağ için geri yaymayı çağırmadığımız için, ağ ilk durumundadır.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net[2].weight.grad == None
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
True
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(type(net.layers[2].weights[1]))
print(net.layers[2].weights[1])
print(tf.convert_to_tensor(net.layers[2].weights[1]))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tf.Tensor([0.], shape=(1,), dtype=float32)
.. raw:: html
.. raw:: html
Bütün Parametrelere Bir Kerede Erişim
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tüm parametrelerde işlem yapmamız gerektiğinde, bunlara tek tek erişmek
bıktırıcı olabilir. Her bir alt bloğun parametrelerini dışarı çıkarmayı
tüm ağaç boyunca tekrarlamamız gerekeceğinden, daha karmaşık bloklarla
(örneğin, iç içe geçmiş bloklarla) çalıştığımızda durum özellikle
kullanışsızca büyüyebilir. Aşağıda, ilk tam bağlı katmanın
parametrelerine erişmeye karşılık tüm katmanlara erişmeyi gösteriyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(net[0].collect_params())
print(net.collect_params())
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
dense0_ (
Parameter dense0_weight (shape=(8, 4), dtype=float32)
Parameter dense0_bias (shape=(8,), dtype=float32)
)
sequential0_ (
Parameter dense0_weight (shape=(8, 4), dtype=float32)
Parameter dense0_bias (shape=(8,), dtype=float32)
Parameter dense1_weight (shape=(1, 8), dtype=float32)
Parameter dense1_bias (shape=(1,), dtype=float32)
)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(*[(name, param.shape) for name, param in net[0].named_parameters()])
print(*[(name, param.shape) for name, param in net.named_parameters()])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
('weight', torch.Size([8, 4])) ('bias', torch.Size([8]))
('0.weight', torch.Size([8, 4])) ('0.bias', torch.Size([8])) ('2.weight', torch.Size([1, 8])) ('2.bias', torch.Size([1]))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(net.layers[1].weights)
print(net.get_weights())
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
[, ]
[array([[ 0.31354207, -0.2002306 , 0.04489189, 0.65902776],
[-0.3884784 , -0.41679087, -0.8219113 , -0.44252217],
[-0.6896628 , -0.19932956, 0.6800088 , 0.0731557 ],
[-0.27203923, -0.7259777 , -0.19643682, 0.3815747 ]],
dtype=float32), array([0., 0., 0., 0.], dtype=float32), array([[ 0.34046865],
[-0.7770064 ],
[-0.46259564],
[-0.86495763]], dtype=float32), array([0.], dtype=float32)]
.. raw:: html
.. raw:: html
Bu bize ağın parametrelerine erişmenin aşağıdaki gibi başka bir yolunu
sağlar:
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net.collect_params()['dense1_bias'].data()
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([0.])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net.state_dict()['2.bias'].data
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([-0.3121])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net.get_weights()[1]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([0., 0., 0., 0.], dtype=float32)
.. raw:: html
.. raw:: html
İçiçe Bloklardan Parametreleri Toplama
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Birden çok bloğu iç içe yerleştirirsek, parametre adlandırma
kurallarının nasıl çalıştığını görelim. Bunun için önce blok üreten bir
fonksiyon tanımlıyoruz (tabiri caizse bir blok fabrikası) ve sonra
bunları daha büyük bloklar içinde birleştiriyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def block1():
net = nn.Sequential()
net.add(nn.Dense(32, activation='relu'))
net.add(nn.Dense(16, activation='relu'))
return net
def block2():
net = nn.Sequential()
for _ in range(4):
# Burada iç içe konuyor
net.add(block1())
return net
rgnet = nn.Sequential()
rgnet.add(block2())
rgnet.add(nn.Dense(10))
rgnet.initialize()
rgnet(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[-6.3465846e-09, -1.1096752e-09, 6.4161787e-09, 6.6354140e-09,
-1.1265507e-09, 1.3284951e-10, 9.3619388e-09, 3.2229084e-09,
5.9429879e-09, 8.8181435e-09],
[-8.6219423e-09, -7.5150686e-10, 8.3133251e-09, 8.9321128e-09,
-1.6740003e-09, 3.2405989e-10, 1.2115976e-08, 4.4926449e-09,
8.0741742e-09, 1.2075874e-08]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def block1():
return nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
nn.Linear(8, 4), nn.ReLU())
def block2():
net = nn.Sequential()
for i in range(4):
# Burada iç içe konuyor
net.add_module(f'block {i}', block1())
return net
rgnet = nn.Sequential(block2(), nn.Linear(4, 1))
rgnet(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[0.3051],
[0.3051]], grad_fn=
)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def block1(name):
return tf.keras.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(4, activation=tf.nn.relu)],
name=name)
def block2():
net = tf.keras.Sequential()
for i in range(4):
# Burada iç içe konuyor
net.add(block1(name=f'block-{i}'))
return net
rgnet = tf.keras.Sequential()
rgnet.add(block2())
rgnet.add(tf.keras.layers.Dense(1))
rgnet(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Ağı tasarladığımıza göre, şimdi nasıl düzenlendiğini görelim.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(rgnet.collect_params)
print(rgnet.collect_params())
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
32, Activation(relu))
(1): Dense(32 -> 16, Activation(relu))
)
(1): Sequential(
(0): Dense(16 -> 32, Activation(relu))
(1): Dense(32 -> 16, Activation(relu))
)
(2): Sequential(
(0): Dense(16 -> 32, Activation(relu))
(1): Dense(32 -> 16, Activation(relu))
)
(3): Sequential(
(0): Dense(16 -> 32, Activation(relu))
(1): Dense(32 -> 16, Activation(relu))
)
)
(1): Dense(16 -> 10, linear)
)>
sequential1_ (
Parameter dense2_weight (shape=(32, 4), dtype=float32)
Parameter dense2_bias (shape=(32,), dtype=float32)
Parameter dense3_weight (shape=(16, 32), dtype=float32)
Parameter dense3_bias (shape=(16,), dtype=float32)
Parameter dense4_weight (shape=(32, 16), dtype=float32)
Parameter dense4_bias (shape=(32,), dtype=float32)
Parameter dense5_weight (shape=(16, 32), dtype=float32)
Parameter dense5_bias (shape=(16,), dtype=float32)
Parameter dense6_weight (shape=(32, 16), dtype=float32)
Parameter dense6_bias (shape=(32,), dtype=float32)
Parameter dense7_weight (shape=(16, 32), dtype=float32)
Parameter dense7_bias (shape=(16,), dtype=float32)
Parameter dense8_weight (shape=(32, 16), dtype=float32)
Parameter dense8_bias (shape=(32,), dtype=float32)
Parameter dense9_weight (shape=(16, 32), dtype=float32)
Parameter dense9_bias (shape=(16,), dtype=float32)
Parameter dense10_weight (shape=(10, 16), dtype=float32)
Parameter dense10_bias (shape=(10,), dtype=float32)
)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(rgnet)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Sequential(
(0): Sequential(
(block 0): Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=4, bias=True)
(3): ReLU()
)
(block 1): Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=4, bias=True)
(3): ReLU()
)
(block 2): Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=4, bias=True)
(3): ReLU()
)
(block 3): Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=4, bias=True)
(3): ReLU()
)
)
(1): Linear(in_features=4, out_features=1, bias=True)
)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
print(rgnet.summary())
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
sequential_2 (Sequential) (2, 4) 80
dense_6 (Dense) (2, 1) 5
=================================================================
Total params: 85
Trainable params: 85
Non-trainable params: 0
_________________________________________________________________
None
.. raw:: html
.. raw:: html
Katmanlar hiyerarşik olarak iç içe olduğundan, iç içe geçmiş listeler
aracılığıyla dizinlenmiş gibi bunlara da erişebiliriz. Örneğin, birinci
ana bloğa, içindeki ikinci alt bloğa ve bunun içindeki ilk katmanın ek
girdisine aşağıdaki şekilde erişebiliriz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
rgnet[0][1][0].bias.data()
.. 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., 0., 0., 0., 0., 0., 0., 0., 0.])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
rgnet[0][1][0].bias.data
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([-0.2715, 0.3849, 0.4326, 0.4178, 0.4517, -0.2524, 0.2472, -0.1414])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
rgnet.layers[0].layers[1].layers[1].weights[1]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Parametre İlkleme
-----------------
Artık parametrelere nasıl erişeceğimizi bildiğimize göre, onları nasıl
doğru şekilde ilkleteceğimize bakalım. Uygun ilkleme ihtiyacını
:numref:`sec_numerical_stability` içinde tartıştık. Derin öğrenme
çerçevesi katmanlarına varsayılan rastgele ilklemeler sağlar. Bununla
birlikte, ağırlıklarımızı öteki farklı protokollere göre ilkletmek
istiyoruz. Çerçeve, en sık kullanılan protokolleri sağlar ve ayrıca
özelleştirilmiş bir ilkletici oluşturmaya izin verir.
.. raw:: html
.. raw:: html
Varsayılan olarak, MXNet ağırlık parametrelerini :math:`U[-0.07, 0.07]`
tekdüze dağılımdan rasgele çekerek ilkler ve ek girdileri sıfırlar.
MXNet'in ``init`` modülü önceden ayarlı çeşitli ilkleme yöntemleri
sağlar.
.. raw:: html
.. raw:: html
Varsayılan olarak PyTorch, girdi ve çıktı boyutuna göre hesaplanan bir
aralıktan çekerek ağırlık ve ek girdi matrislerini tekdüze olarak
başlatır. PyTorch'un ``nn.init`` modülü önceden ayarlı çeşitli ilkleme
yöntemleri sağlar.
.. raw:: html
.. raw:: html
Varsayılan olarak Keras, girdi ve çıktı boyutuna göre hesaplanan bir
aralıktan çekerek ağırlık matrislerini tekdüze olarak ilkletir ve ek
girdi parametrelerinin tümü sıfır olarak atanır. TensorFlow, hem kök
modülde hem de ``keras.initializers`` modülünde çeşitli ilkleme
yöntemleri sağlar.
.. raw:: html
.. raw:: html
Yerleşik İlkletme
~~~~~~~~~~~~~~~~~
Yerleşik ilkleticileri çağırarak ilkleyelim. Aşağıdaki kod, tüm ağırlık
parametrelerini standart sapması 0.01 olan Gauss rastgele değişkenler
olarak ilkletirken ek girdi parametreleri de 0 olarak atanır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
# Burada 'force_reinit', daha önce ilklenmiş olsalar bile parametrelerin
# yeniden ilklenmesini sağlar
net.initialize(init=init.Normal(sigma=0.01), force_reinit=True)
net[0].weight.data()[0]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([-0.00324057, -0.00895028, -0.00698632, 0.01030831])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def init_normal(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, mean=0, std=0.01)
nn.init.zeros_(m.bias)
net.apply(init_normal)
net[0].weight.data[0], net[0].bias.data[0]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(tensor([ 0.0006, -0.0043, 0.0077, -0.0008]), tensor(0.))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(
4, activation=tf.nn.relu,
kernel_initializer=tf.random_normal_initializer(mean=0, stddev=0.01),
bias_initializer=tf.zeros_initializer()),
tf.keras.layers.Dense(1)])
net(X)
net.weights[0], net.weights[1]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(,
)
.. raw:: html
.. raw:: html
Ayrıca tüm parametreleri belirli bir sabit değere ilkleyebiliriz
(örneğin, 1 gibi).
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net.initialize(init=init.Constant(1), force_reinit=True)
net[0].weight.data()[0]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([1., 1., 1., 1.])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def init_constant(m):
if type(m) == nn.Linear:
nn.init.constant_(m.weight, 1)
nn.init.zeros_(m.bias)
net.apply(init_constant)
net[0].weight.data[0], net[0].bias.data[0]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(tensor([1., 1., 1., 1.]), tensor(0.))
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(
4, activation=tf.nn.relu,
kernel_initializer=tf.keras.initializers.Constant(1),
bias_initializer=tf.zeros_initializer()),
tf.keras.layers.Dense(1),
])
net(X)
net.weights[0], net.weights[1]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
(,
)
.. raw:: html
.. raw:: html
Ayrıca belirli bloklar için farklı ilkleyiciler uygulayabiliriz.
Örneğin, aşağıda ilk katmanı Xavier ilkleyicisi ile ilkliyoruz ve ikinci
katmanı sabit 42 değeri ile ilkliyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net[0].weight.initialize(init=init.Xavier(), force_reinit=True)
net[1].initialize(init=init.Constant(42), force_reinit=True)
print(net[0].weight.data()[0])
print(net[1].weight.data())
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
[-0.17594433 0.02314097 -0.1992535 0.09509248]
[[42. 42. 42. 42. 42. 42. 42. 42.]]
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def xavier(m):
if type(m) == nn.Linear:
nn.init.xavier_uniform_(m.weight)
def init_42(m):
if type(m) == nn.Linear:
nn.init.constant_(m.weight, 42)
net[0].apply(xavier)
net[2].apply(init_42)
print(net[0].weight.data[0])
print(net[2].weight.data)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([-0.0983, 0.5310, -0.2538, 0.6591])
tensor([[42., 42., 42., 42., 42., 42., 42., 42.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(
4,
activation=tf.nn.relu,
kernel_initializer=tf.keras.initializers.GlorotUniform()),
tf.keras.layers.Dense(
1, kernel_initializer=tf.keras.initializers.Constant(42)),
])
net(X)
print(net.layers[1].weights[0])
print(net.layers[2].weights[0])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Özelleştirilmiş İlkleme
~~~~~~~~~~~~~~~~~~~~~~~
Bazen, ihtiyaç duyduğumuz ilkletme yöntemleri derin öğrenme çerçevesi
tarafından sağlanmayabilir. Aşağıdaki örnekte, herhangi bir ağırlık
parametresi :math:`w` için aşağıdaki garip dağılımı kullanarak bir
ilkleyici tanımlıyoruz:
.. math::
\begin{aligned}
w \sim \begin{cases}
U(5, 10) & \text{ olasılık değeri } \frac{1}{4} \\
0 & \text{ olasılık değeri } \frac{1}{2} \\
U(-10, -5) & \text{ olasılık değeri } \frac{1}{4}
\end{cases}
\end{aligned}
.. raw:: html
.. raw:: html
Burada ``Initializer`` sınıfının bir alt sınıfını tanımlıyoruz.
Genellikle, yalnızca bir tensör bağımsız değişkeni (``data``) alan ve
ona istenen ilkletilmiş değerleri atayan ``_init_weight`` işlevini
uygulamamız gerekir.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
class MyInit(init.Initializer):
def _init_weight(self, name, data):
print('Init', name, data.shape)
data[:] = np.random.uniform(-10, 10, data.shape)
data *= np.abs(data) >= 5
net.initialize(MyInit(), force_reinit=True)
net[0].weight.data()[:2]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Init dense0_weight (8, 4)
Init dense1_weight (1, 8)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[ 0. , -0. , -0. , 8.522827 ],
[ 0. , -8.828651 , -0. , -5.6012006]])
.. raw:: html
.. raw:: html
Yine, ``net``'e uygulamak için bir ``my_init`` işlevi uyguluyoruz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def my_init(m):
if type(m) == nn.Linear:
print("Init", *[(name, param.shape)
for name, param in m.named_parameters()][0])
nn.init.uniform_(m.weight, -10, 10)
m.weight.data *= m.weight.data.abs() >= 5
net.apply(my_init)
net[0].weight[:2]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Init weight torch.Size([8, 4])
Init weight torch.Size([1, 8])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[ 0.0000, -8.7999, 9.7935, 8.7815],
[-0.0000, 0.0000, -0.0000, 5.8831]], grad_fn=)
.. raw:: html
.. raw:: html
Burada ``Initializer``'ın bir alt sınıfını tanımlıyoruz ve şekil ve veri
türüne göre istenen bir tensörü döndüren ``__call__`` işlevini
uyguluyoruz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
class MyInit(tf.keras.initializers.Initializer):
def __call__(self, shape, dtype=None):
data=tf.random.uniform(shape, -10, 10, dtype=dtype)
factor=(tf.abs(data) >= 5)
factor=tf.cast(factor, tf.float32)
return data * factor
net = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(
4,
activation=tf.nn.relu,
kernel_initializer=MyInit()),
tf.keras.layers.Dense(1),
])
net(X)
print(net.layers[1].weights[0])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Her zaman parametreleri doğrudan ayarlama seçeneğimiz olduğunu
unutmayın.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net[0].weight.data()[:] += 1
net[0].weight.data()[0, 0] = 42
net[0].weight.data()[0]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([42. , 1. , 1. , 9.522827])
İleri düzey kullanıcılar için bir hatırlatma: Parametreleri bir
``autograd`` (otomatik türev) kapsamında ayarlamak istiyorsanız,
otomatik türev alma mekanizmalarının karıştırılmasını önlemek için
``set_data``'yı kullanmanız gerekir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net[0].weight.data[:] += 1
net[0].weight.data[0, 0] = 42
net[0].weight.data[0]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([42.0000, -7.7999, 10.7935, 9.7815])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net.layers[1].weights[0][:].assign(net.layers[1].weights[0] + 1)
net.layers[1].weights[0][0, 0].assign(42)
net.layers[1].weights[0]
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Bağlı Parametreler
------------------
Genellikle, parametreleri birden çok katmanda paylaşmak isteriz. Bunu
biraz daha zekice bir şekilde nasıl yapacağımızı görelim. Aşağıda yoğun
(dense) bir katman ayırıyoruz ve ardından onun parametrelerini de
özellikle başka bir katmanınkileri ayarlamak için kullanıyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net = nn.Sequential()
# Parametrelerine atıfta bulunabilmemiz için paylaşılan katmana bir ad
# vermemiz gerekiyor
shared = nn.Dense(8, activation='relu')
net.add(nn.Dense(8, activation='relu'),
shared,
nn.Dense(8, activation='relu', params=shared.params),
nn.Dense(10))
net.initialize()
X = np.random.uniform(size=(2, 20))
net(X)
# Parametrelerin aynı olup olmadığını kontrol edin
print(net[1].weight.data()[0] == net[2].weight.data()[0])
net[1].weight.data()[0, 0] = 100
# Aynı değere sahip olmak yerine aslında aynı nesne olduklarından emin olun
print(net[1].weight.data()[0] == net[2].weight.data()[0])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
[ True True True True True True True True]
[ True True True True True True True True]
Bu örnek, ikinci ve üçüncü katmanın parametrelerinin birbirine bağlı
olduğunu göstermektedir. Sadece eşit değiller, tamamen aynı tensörle
temsil ediliyorlar. Bu yüzden parametrelerden birini değiştirirsek
diğeri de değişir. Merak edebilirsiniz, parametreler bağlı olduğunda
gradyanlara ne olur? Model parametreleri gradyanlar içerdiğinden, ikinci
ve üçüncü gizli katmanların gradyanları geri yayma sırasında birbiriyle
toplanır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
# Parametrelerine atıfta bulunabilmemiz için paylaşılan katmana bir ad
# vermemiz gerekiyor
shared = nn.Linear(8, 8)
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
shared, nn.ReLU(),
shared, nn.ReLU(),
nn.Linear(8, 1))
net(X)
# Parametrelerin aynı olup olmadığını kontrol edin
print(net[2].weight.data[0] == net[4].weight.data[0])
net[2].weight.data[0, 0] = 100
# Aynı değere sahip olmak yerine aslında aynı nesne olduklarından emin olun
print(net[2].weight.data[0] == net[4].weight.data[0])
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([True, True, True, True, True, True, True, True])
tensor([True, True, True, True, True, True, True, True])
Bu örnek, ikinci ve üçüncü katmanın parametrelerinin birbirine bağlı
olduğunu göstermektedir. Sadece eşit değiller, tamamen aynı tensörle
temsil ediliyorlar. Bu yüzden parametrelerden birini değiştirirsek
diğeri de değişir. Merak edebilirsiniz, parametreler bağlı olduğunda
gradyanlara ne olur? Model parametreleri gradyanlar içerdiğinden, ikinci
ve üçüncü gizli katmanların gradyanları geri yayma sırasında birbiriyle
toplanır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
# tf.keras biraz farklı davranır. Yinelenen katmanı otomatik olarak kaldırır.
shared = tf.keras.layers.Dense(4, activation=tf.nn.relu)
net = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
shared,
shared,
tf.keras.layers.Dense(1),
])
net(X)
# Parametrelerin farklı olup olmadığını kontrol edin
print(len(net.layers) == 3)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
True
.. raw:: html
.. raw:: html
Özet
----
- Model parametrelerine erişmek, ilklemek ve onları bağlamak için
birkaç farklı yol var.
- Özelleştirilmiş ilkleme kullanabiliriz.
Alıştırmalar
------------
1. :numref:`sec_model_construction` içinde tanımlanan ``FancyMLP``
modelini kullanınız ve çeşitli katmanların parametrelerine erişiniz.
2. Farklı ilkleyicileri keşfetmek için ilkleme modülü dökümanına
bakınız.
3. Paylaşılan bir parametre katmanı içeren bir MLP oluşturunuz ve onu
eğitiniz. Eğitim sürecinde, her katmanın model parametrelerini ve
gradyanlarını gözlemleyiniz.
4. Parametreleri paylaşmak neden iyi bir fikirdir?
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html