Гузариш ба мундариҷа
Мавзӯи 4 аз 6

Қабатҳо ва моделҳо

Қабатҳо барои чӣ лозиманд

Ҳазорҳо вазни алоҳидаро дастӣ тавсиф кардан нороҳат аст. torch.nn қабатҳои тайёр медиҳад: ҳар кадом тензорро гирифта, табдил медиҳад ва параметрҳои омӯзишпазири худро нигоҳ медорад. Аз қабатҳо модел, қоидаи табдили аломатҳои вуруд ба пешгӯиҳо, сохта мешавад.

Барои тасвир шабака пикселҳоро ба намоиши пинҳонӣ ва баъд ба баҳои синфҳо табдил медиҳад. Шаклҳо ва параметрҳоро меомӯзем; вазнҳои тасодуфӣ ҳанӯз омӯзиш мехоҳанд.

1. Қабати хаттӣ

nn.Linear(in_features, out_features) ҷамъҳои вазндори вурудҳоро ҳисоб мекунад. Ҳар баромад вазнҳо ва ҷойивазкунии (bias) худро дорад. Барои ду вуруд як баромад чунин аст: w₁x₁ + w₂x₂ + b. Барои равшанӣ параметрҳоро ба ҷойи ибтидосозии тасодуфӣ ошкоро мегузорем.

import torch
from torch import nn
layer = nn.Linear(2, 1)
with torch.no_grad():
    layer.weight.copy_(torch.tensor([[2.0, -1.0]]))
    layer.bias.fill_(0.5)
x = torch.tensor([[3.0, 4.0], [1.0, 2.0]])
print(layer(x).tolist())
print(tuple(layer.weight.shape), tuple(layer.bias.shape))

Натиҷа:

[[2.5], [0.5]]
(1, 2) (1,)

Сатри аввал 2·3 − 4 + 0.5 = 2.5 ва дуюм 2·1 − 2 + 0.5 = 0.5 дод. Матритсаи вазнҳо шакли (out_features, in_features) дорад, пас формулаи умумӣ x @ weight.T + bias аст. Вуруди (N, in_features) ба (N, out_features) табдил меёбад: ҳамон қабат ба ҳар сатри баста мустақилона татбиқ мешавад.

Шумораи параметрҳо бо bias: in_features · out_features + out_features. Ададҳо ҳисоб мешаванд, на зарфҳо. Бо bias=False ҷойивазкунӣ нест; одатан параметрҳоро омӯзиш интихоб мекунад.

2. Чаро ғайрихаттӣ будан лозим аст

Пайвасти танҳо қабатҳои хаттӣ табдили аффинӣ мемонад ва ба як қабат ҷамъбаст мешавад. Барои тавсифи вобастагиҳои мураккабтар байни табдилҳо функсияи фаъолсозӣ мегузоранд. ReLU қиматҳои манфиро ба сифр иваз карда, мусбатҳоро нигоҳ медорад.

import torch
from torch import nn
x = torch.tensor([-3.0, 0.0, 2.5])
print(nn.ReLU()(x).tolist())
print(nn.ReLU()(x).max().item())

Натиҷа:

[0.0, 0.0, 2.5]
2.5

ReLU қиматҳоро аз боло бо як маҳдуд намекунад: 2.5 ҳамон 2.5 монд. Он вазни омӯзишпазир надорад. Қабати охирини таснифгар одатан логитҳо (logits), баҳои озоди синфҳоро медиҳад, ки метавонанд манфӣ бошанд. Фаъолсозии баромад ба масъала вобаста аст; барои тасниф бо CrossEntropyLoss логитҳоро бе ReLU ва softmax мегузоранд.

3. Пайдарпаии қабатҳо

nn.Sequential баромади ҳар модулро ба модули навбатӣ медиҳад. Аввал ду аломат ба се қимати пинҳонӣ табдил меёбад, баъд фаъолсозӣ шаклро нигоҳ медорад ва қабати охир ду баҳо медиҳад. Сохтор ва андозаро месанҷем ва ба қиматҳои тасодуфӣ маънои ҷавоби омӯхташударо намедиҳем.

import torch
from torch import nn
model = nn.Sequential(nn.Linear(2, 3), nn.ReLU(), nn.Linear(3, 2))
x = torch.zeros(4, 2)
print([type(layer).__name__ for layer in model])
print(tuple(model(x).shape))

Натиҷа:

['Linear', 'ReLU', 'Linear']
(4, 2)

Андозаҳо дар ҳар сарҳад бояд мувофиқ бошанд: шумораи баромади як Linear ба шумораи вуруди қабати дигар баробар аст. Андозаи баста нигоҳ дошта мешавад. Пеш аз иҷро занҷири шаклҳоро нависед: (4, 2) → (4, 3) → (4, 3) → (4, 2).

4. Параметрҳо дар куҷо нигоҳ дошта мешаванд

Параметр тензори махсусест, ки модул барои омӯзиш сабт мекунад. named_parameters() ҷуфтҳои ном ва тензор, parameters() танҳо тензорҳоро медиҳад. numel() шумораи ададҳоро дар тензори муайян нишон медиҳад.

from torch import nn
layer = nn.Linear(3, 2)
for name, p in layer.named_parameters():
    print(name, tuple(p.shape), p.numel(), p.requires_grad)
layer.requires_grad_(False)
print([p.requires_grad for p in layer.parameters()])

Натиҷа:

weight (2, 3) 6 True
bias (2,) 2 True
[False, False]

Ду тензор ҳашт адад доранд: шаш вазн ва ду ҷойивазкунӣ. requires_grad_(False) параметрҳоро ях мекунад. Одатан ин пеш аз сохтани оптимизатор танзим мешавад; ҳангоми яхкунӣ дар миёни омӯзиш градиентҳои пешинаро ба назар гиред.

5. nn.Module-и худ

Вақте ҳисоб аз занҷири сода берун меравад, синфи вориси nn.Module месозанд. Дар __init__ аввал super().__init__()-ро даъват карда, зермодулҳо ё параметрҳоро дар атрибутҳо нигоҳ медоранд. Методи forward ҳисобро тавсиф мекунад. Модули дорои як зарбкунандаи омӯзишпазирро мебинем.

import torch
from torch import nn
class Scale(nn.Module):
    def __init__(self):
        super().__init__()
        self.factor = nn.Parameter(torch.tensor(2.0))

    def forward(self, x):
        return x * self.factor

model = Scale()
print(model(torch.tensor([1.0, 3.0])).tolist())
print([name for name, p in model.named_parameters()])

Натиҷа:

[2.0, 6.0]
['factor']

nn.Parameter параметри factor-ро барои оптимизатор сабт мекунад; тензори одӣ ин корро намекунад. model(x)-ро даъват кунед: механизми nn.Module методи forward-ро оғоз мекунад. Ҳосилаи зарбро autograd худаш меёбад.

Қабатҳоро як бор дар __init__ созед: қабатҳои нав дар forward дар ҳар даъват вазнҳои нави тасодуфӣ медоданд.

6. Тасвирҳо ва меҳвари баста

Қабати хаттӣ аломатҳоро дар меҳвари охир интизор аст. Тасвир метавонад чанд меҳвари фазоӣ дошта бошад; онҳоро якҷо карда, барои ҳар намуна сатри алоҳида мемонанд. flatten меҳварҳоро аз меҳвари муайяншуда якҷо мекунад. Оғоз аз 1 меҳвари 0-ро бетағйир мегузорад.

import torch
x = torch.zeros(3, 2, 2)
print(tuple(x.flatten(start_dim=1).shape))
print(tuple(x.flatten().shape))

Натиҷа:

(3, 4)
(12,)

Се намуна ҳар кадом чор аломат доранд. flatten() онҳоро ба як вектор часпонд. Ҳатто як тасвирро одатан ҳамчун бастаи андозааш 1 медиҳанд.

Дар дохил чӣ рӯй медиҳад

Модел ба хатти коркард бо шартҳои муайяни шакл монанд аст. PyTorch дарахти зермодулҳо ва параметрҳоро сабт мекунад; model.parameters() онро мегузарад. Гузариши мустақим графи autograd месозад. Модел вазнҳоро нигоҳ дошта, ба оптимизатор медиҳад.

Хатоҳои маъмул ва ислоҳи онҳо

  1. Андозаҳои номувофиқ. Қабати дорои се вуруд панҷ аломатро намегирад. Ҳангоми зарби матритсаҳо хато рӯй медиҳад; андозаи вуруд ё меъмориро ислоҳ кунед:
import torch
from torch import nn
layer = nn.Linear(3, 2)
try:
    layer(torch.zeros(4, 5))
except RuntimeError as e:
    print(type(e).__name__)
print(tuple(layer(torch.zeros(4, 3)).shape))

Натиҷа:

RuntimeError
(4, 2)
  1. Гум шудани меҳвари баста. x.flatten() ҳамаи намунаҳоро якҷо мекунад. Оғози якҷокунии меҳварҳоро муайян кунед ва санҷед, ки андозаи баста меҳвари аввал монд.

  2. Фаъолсозии зиёдатӣ дар логитҳо. ReLU баъди баромади таснифгар баҳои манфиро мебурад. Баромадро дар шакле гузоред, ки функсияи хато интизор аст.

  3. Ҳисоби зарфҳо ба ҷойи ададҳо. Дар мисол len(list(layer.parameters())) ду аст, на ҳашт. numel()-и ҳар тензорро, аз ҷумла bias, бинед; барои параметрҳои омӯзишпазир requires_grad-ро низ санҷед.

  4. Фаромӯш шудани super().init(). Таъйини қабат пеш аз ибтидосозии nn.Module хатои сабт медиҳад. Аввал синфи асосиро ибтидосозӣ карда, баъд қабатҳоро дар атрибутҳо созед.

Ёддошт

Восита Вазифа
nn.Linear(a, b) a аломатро ба b табдил дода, вазн ва bias-ро нигоҳ медорад
nn.ReLU() Қиматҳои манфиро ба сифр иваз мекунад
nn.Sequential(...) Модулҳоро ба занҷир мепайвандад
named_parameters() Номҳо ва тензорҳои параметрҳоро нишон медиҳад
p.numel() Ададҳои дохили параметрро мешуморад
requires_grad_(False) Параметрҳоро ях мекунад
nn.Module, forward Модели худро тавсиф мекунанд
flatten(start_dim=...) Меҳварҳои интихобшударо якҷо мекунад