Layer adalah komponen komputasi yang dapat dirangkai menjadi model, dan torch.nn menyediakannya dalam bentuk siap pakai sehingga model jarang dibangun dari operasi tensor mentah. Topik ini menelusuri nn.Linear sebagai layer yang paling sering digunakan untuk data tabular, disusul fungsi aktivasi ReLU dan Sigmoid dalam dua bentuknya, yaitu sebagai module dan sebagai fungsi. Bagian akhir membahas nn.Sequential sebagai cara ringkas merangkai layer, beserta satu jebakan pada urutan layer yang melemahkan model tanpa menimbulkan error.
nn.Linear dan bentuk masukannya#
nn.Linear(in_features, out_features) menerapkan transformasi linear terhadap dimensi terakhir tensor masukannya. Transformasi tersebut dirumuskan sebagai berikut, dengan berupa matriks bobot dan berupa vektor bias.
Bentuk masukan yang dituntut adalah (N, in_features) dan keluarannya berbentuk (N, out_features), dengan N menyatakan jumlah sampel. Bobot tersimpan dengan bentuk (out_features, in_features), sedangkan bias dengan bentuk (out_features,). Urutan tersebut mengikuti rumus di atas, karena perkalian menuntut berbentuk (out_features, in_features).
import torch
import torch.nn as nn
torch.manual_seed(0)
linear = nn.Linear(in_features=4, out_features=3)
x = torch.randn(5, 4) # (N, in_features) = (5, 4)
y = linear(x)
print(y.shape)
print(linear.weight.shape)
print(linear.bias.shape)torch.Size([5, 3])
torch.Size([3, 4])
torch.Size([3])Keluaran torch.Size([5, 3]) sesuai prediksi, yaitu dimensi terakhir berubah dari 4 menjadi 3, sedangkan dimensi sampel tetap 5. Bentuk bobot torch.Size([3, 4]) dan bias torch.Size([3]) juga konsisten dengan anotasi pada diagram berikut.
Diagram di atas menegaskan pola yang berlaku untuk setiap Linear. Anotasi bentuk seperti ini diperiksa terlebih dahulu setiap kali layer dirangkai, karena ketidakcocokan bentuk antara layer merupakan salah satu sumber error yang sering muncul saat membangun model.
Fungsi aktivasi: module dan fungsi#
Layer Linear hanya mampu memetakan data secara linear. Fungsi aktivasi ditempatkan di antara layer untuk memberikan sifat non-linear, dan dua yang paling umum adalah ReLU dan sigmoid. ReLU mempertahankan nilai positif dan mengubah nilai negatif menjadi nol, sedangkan sigmoid memetakan setiap nilai ke rentang (0, 1).
Keduanya tersedia dalam dua bentuk. Sebagai module, nn.ReLU dan nn.Sigmoid digunakan seperti layer lain, yaitu ditetapkan sebagai atribut di __init__ atau menjadi anggota nn.Sequential. Sebagai fungsi, torch.relu dan torch.sigmoid dipanggil langsung terhadap tensor. Hasil kedua bentuk itu identik, sebagaimana diperiksa pada kode berikut.
import torch
import torch.nn as nn
x = torch.tensor([-1.5, 0.0, 2.0])
relu = nn.ReLU()
sigmoid = nn.Sigmoid()
print("nn.ReLU() :", relu(x))
print("torch.relu() :", torch.relu(x))
print("nn.Sigmoid() :", sigmoid(x))
print("torch.sigmoid:", torch.sigmoid(x))
print(relu(x).equal(torch.relu(x)))
print(sigmoid(x).equal(torch.sigmoid(x)))nn.ReLU() : tensor([0., 0., 2.])
torch.relu() : tensor([0., 0., 2.])
nn.Sigmoid() : tensor([0.1824, 0.5000, 0.8808])
torch.sigmoid: tensor([0.1824, 0.5000, 0.8808])
True
TrueKeluaran tersebut memperlihatkan perilaku keduanya pada nilai -1.5, 0.0, dan 2.0. ReLU memetakan dua nilai pertama menjadi nol, sedangkan sigmoid mengonversinya menjadi 0.1824, 0.5000, dan 0.8808 yang berada di rentang (0, 1). Dua baris terakhir bernilai True, sehingga bentuk module dan bentuk fungsi memberikan hasil yang sama persis. Pemilihan bentuknya merupakan persoalan gaya: module digunakan agar seragam dengan layer lain saat model dirangkai, sedangkan fungsi digunakan untuk komputasi singkat di dalam forward(). Berbeda dengan Linear, keduanya tidak membawa parameter yang dipelajari, sehingga penelusuran named_parameters() pada topik Parameter tidak pernah menampilkannya.
Urutan layer menentukan sifat model#
Urutan layer bukan sekadar urutan penulisan, melainkan penentu sifat matematis model. Dua layer Linear yang dipanggil berturut-turut tanpa aktivasi di antaranya membentuk pemetaan yang ekuivalen dengan satu layer Linear saja, sebab:
Ruas kanan berupa transformasi linear dengan bobot gabungan dan bias gabungan. Artinya, kemampuan menangkap pola non-linear hilang tanpa error apa pun, dan pelatihan tetap berjalan seperti biasa. Potongan kode berikut membuktikan ekuivalensi tersebut dengan menyusun bobot gabungannya secara manual.
import torch
import torch.nn as nn
torch.manual_seed(0)
fc1 = nn.Linear(4, 8)
fc2 = nn.Linear(8, 3)
x = torch.randn(5, 4)
y = fc2(fc1(x)) # dua transformasi linear berturut-turut, tanpa aktivasi
fc_gabungan = nn.Linear(4, 3)
with torch.no_grad():
fc_gabungan.weight.copy_(fc2.weight @ fc1.weight)
fc_gabungan.bias.copy_(fc2.weight @ fc1.bias + fc2.bias)
print(y.shape)
print(torch.allclose(y, fc_gabungan(x), atol=1e-6))torch.Size([5, 3])
Truetorch.allclose mengembalikan True, sehingga rangkaian dua layer itu benar-benar sama dengan satu layer yang bobotnya dikalikan. Karena itu, fungsi aktivasi non-linear wajib berada di antara layer-layer Linear. Perlu ditegaskan pula bahwa layer tidak dirangkai dengan operasi aritmetika antarobjek, misalnya perkalian fc1 * fc2. Rangkaian dibentuk dengan memanggil satu layer setelah layer lain, sebagaimana dilakukan di dalam forward().
nn.Sequential sebagai susunan ringkas#
nn.Sequential menerima sederetan module dan membungkusnya menjadi satu module tunggal. Saat objeknya dipanggil, keluaran setiap module menjadi masukan module berikutnya, dari kiri ke kanan. Cara ini ringkas untuk model yang alirannya lurus, sebab definisi __init__ dan forward() tidak perlu ditulis sendiri. Urutan argumen sekaligus menjadi urutan eksekusi, sehingga susunan Linear lalu ReLU menghasilkan model yang berbeda dengan ReLU lalu Linear.
import torch
import torch.nn as nn
torch.manual_seed(0)
model = nn.Sequential(
nn.Linear(4, 8),
nn.ReLU(),
nn.Linear(8, 3),
)
x = torch.randn(5, 4)
logits = model(x)
print(logits.shape)torch.Size([5, 3])Bentuk keluarannya sama dengan model pola kelas pada topik nn.Module, karena susunannya identik. Keterbatasan Sequential terletak pada bentuk alirannya: setiap module hanya menerima satu masukan dan menghasilkan satu keluaran. Begitu aliran data bercabang, disambung dengan operasi tambahan, atau membutuhkan logika khusus di tengah aliran, pola kelas dengan forward() yang ditulis secara manual kembali diperlukan.
Ringkasan#
nn.Linear(in_features, out_features)menerapkan pada dimensi terakhir, mengubah (N,in_features) menjadi (N,out_features), dengan bobot berbentuk (out_features,in_features) dan bias (out_features,).- ReLU dan sigmoid tersedia sebagai module (
nn.ReLU,nn.Sigmoid) maupun fungsi (torch.relu,torch.sigmoid), dan hasil keduanya identik. - Dua
Linearberturutan tanpa aktivasi kolaps menjadi satu pemetaan linear, sehingga aktivasi non-linear wajib di antara layer. nn.Sequentialmerangkai module berurutan menjadi satu objek, dengan syarat alirannya lurus dan bentuk antara module cocok.
Referensi#
- Deep Learning with PyTorch: A 60 Minute Blitz — PyTorch
— Tutorial resmi yang memperkenalkan
torch.nn, termasukLineardanReLU, pada bagian Neural Networks. - PyTorch Documentation — PyTorch
— Rujukan API
torch.nnuntuk layer dan fungsi aktivasi bawaan.