Chương 3·Bài 3.2

MLP và backpropagation

Phép XOR của hai bit không tách được bằng một đường thẳng: hai điểm (0, 0), (1, 1) cho 0 và hai điểm (0, 1), (1, 0) cho 1 nằm chéo nhau. Vì vậy model tuyến tính như logistic regression không học được XOR. MLP (multilayer perceptron) xếp nhiều lớp tuyến tính, xen giữa là một hàm phi tuyến gọi là activation, để các lớp đầu tạo ra đặc trưng mới cho lớp sau. Để huấn luyện MLP cần tính đạo hàm của loss theo trọng số ở mọi lớp; thuật toán làm việc đó là backpropagation, nội dung chính của bài.

Vì sao thêm một lớp?

Với đầu vào x1,x2x_1,x_2 thuộc {0,1}\{0,1\}, XOR có nhãn 1 tại (0,1),(1,0)(0,1),(1,0) và nhãn 0 ở hai góc còn lại. Một đường thẳng không tách được hai cặp góc đối diện. Đây là giới hạn của kiến trúc: train lâu hơn cũng không chữa được.

XOR: không đường thẳng nào tách được; qua lớp ẩn ReLU thì tách được.0101?đầu vào (x₁, x₂)ReLU01012(0,1) và (1,0)(1,1)lớp ẩn (h₁, h₂)
XOR: không đường thẳng nào tách được; qua lớp ẩn ReLU thì tách được.
Lớp ẩn dồn các điểm lên một đường, ReLU gập phần âm, rồi một đường thẳng tách được.

Tạo hai đặc trưng h1=ReLU⁡(x1+x2)h_1=\operatorname{ReLU}(x_1+x_2) và h2=ReLU⁡(x1+x2−1)h_2=\operatorname{ReLU}(x_1+x_2-1), với ReLU⁡(z)=max⁡(0,z)\operatorname{ReLU}(z)=\max(0,z). Khi tổng là 0, 1, 2, hai đặc trưng lần lượt là (0,0),(1,0),(2,1)(0,0),(1,0),(2,1). Công thức y^=h1−2h2\hat y=h_1-2h_2 cho 0, 1, 0, đúng XOR. Đây là một mạng được đặt trọng số bằng tay, chưa phải mạng đã học.

Python
import numpy as np
import torch

torch.set_num_threads(1)
torch.manual_seed(11)
np.set_printoptions(precision=4, suppress=True)
X_xor = np.array([[0., 0.], [0., 1.], [1., 0.], [1., 1.]])
hidden = np.maximum(X_xor @ np.ones((2, 2)) + [0., -1.], 0.)
print(hidden)
print(hidden @ np.array([1., -2.]))

Dòng cuối cần cho 0, 1, 1, 0. Hidden layer đã biến bốn góc thành những vị trí mà lớp sau kết hợp được: hai góc (0,1),(1,0)(0,1),(1,0) cùng rơi vào điểm (h1,h2)=(1,0)(h_1,h_2)=(1,0), còn góc (1,1)(1,1) bị đẩy ra (2,1)(2,1).

Hỏi nhanh

Giữ nguyên hai đặc trưng h1h_1, h2h_2 của mạng XOR đặt tay, chỉ đổi đầu ra thành y^=h1−h2\hat y = h_1 - h_2. Với bốn đầu vào (0,0)(0,0), (0,1)(0,1), (1,0)(1,0), (1,1)(1,1), mạng cho ra hàm nào?

Nếu bỏ activation, hai lớp gộp lại: (XW1+b1)W2+b2=X(W1W2)+(b1W2+b2)(XW_1+b_1)W_2+b_2=X(W_1W_2)+(b_1W_2+b_2), vẫn là một lớp linear. Thêm tham số mà không thêm phi tuyến không giải quyết được XOR.

Xếp nhiều lớp như vậy là được một mạng nơ-ron nhiều lớp (multilayer perceptron, MLP). Các lớp nằm giữa đầu vào và đầu ra gọi là lớp ẩn; nhiều lớp ẩn thì gọi là mạng sâu.

Một nơ-ron ngưỡng, ra 1 khi w1x1+w2x2+b>0w_1x_1 + w_2x_2 + b > 0, tính được AND, OR hay NAND; ví dụ w=(−1,−1)w = (-1, -1), b=1.5b = 1.5 cho NAND. Nhưng nó chỉ vẽ được một đường, nên XOR cần ít nhất hai nơ-ron ẩn. Cũng vậy, muốn biết một điểm có nằm trong tam giác không, dùng ba nơ-ron ẩn, mỗi cái kiểm một cạnh, rồi nơ-ron ra làm phép AND.

Đường thẳng trong mặt phẳng tách được mọi cách gán nhãn của 3 điểm không thẳng hàng, nhưng không với 4 điểm: bốn góc XOR là ví dụ, và bỏ đi một góc thì ba góc còn lại lại tách được.

Model linear chỉ đúng 57% trên XOR; thêm 8 neuron ẩn ReLU thì học được.linear (không lớp ẩn) · train 57%MLP 2 → 8 → 1 · train 100%
Model linear chỉ đúng 57% trên XOR; thêm 8 neuron ẩn ReLU thì học được.

Hỏi nhanh

Mạng 2→100→12 \to 100 \to 1 gồm hai lớp linear nối thẳng, không có activation ở giữa. Mạng này biểu diễn được những hàm nào?

Forward có bảng shape

Ta thống nhất mẫu nằm ở hàng. Một batch XX có shape (B, d), hidden width hh, đầu ra cc:

Z1=XW1+b1,H=ReLU⁡(Z1),P=HW2+b2.Z_1=XW_1+b_1,\qquad H=\operatorname{ReLU}(Z_1),\qquad P=HW_2+b_2.
Tên Shape Ý nghĩa
W1,b1W_1,b_1 (d, h), (h,) Tạo hidden feature
Z1,HZ_1,H (B, h) Trước và sau activation
W2,b2W_2,b_2 (h, c), (c,) Tạo đầu ra
P,YP,Y (B, c) Dự đoán và target

Trong NumPy ta dùng cách viết hàng như bảng này. torch.nn.Linear(d,h) lưu weight shape (h,d) và thực hiện X weight⊤+bX\,\text{weight}^\top+b. Hai quy ước cùng đúng; khi chuyển trọng số tự viết sang Linear, cần chuyển vị. Nếu copy thẳng ma trận vuông thì shape vẫn hợp lệ nhưng nội dung có thể sai.

Mỗi nơ-ron của lớp nối với mọi đầu vào của lớp trước, nên gọi là lớp kết nối đầy đủ (fully connected); nn.Linear(10, 3) là lớp 10 vào, 3 ra. Số trọng số giữa hai lớp bằng số vào nhân số ra, cộng thêm số ra nếu có bias: mạng 30→4→3→130 \to 4 \to 3 \to 1 không bias có 120+12+3=135120 + 12 + 3 = 135 trọng số.

Forward phải lưu X,Z1,HX,Z_1,H cho backward, vì đạo hàm phụ thuộc chúng. Đó là nguồn chi phí activation memory: nhớ giá trị trung gian để khỏi tính lại. Backprop là thuật toán đi ngược các phép, còn autograd là cơ chế thư viện xây graph và gọi đạo hàm phù hợp.

Hỏi nhanh

Lớp đầu đã được cài bằng NumPy theo quy ước hàng, Z=XW1Z = XW_1, với W1 có shape (3, 3). Chép thẳng W1 vào weight của torch.nn.Linear(3, 3) rồi chạy. Chuyện gì xảy ra?

Từ loss về lớp đầu

Để dễ kiểm, ta dùng hồi quy một đầu ra c=1c=1 và J=1B∑i(Pi−Yi)2J=\frac1B\sum_i(P_i-Y_i)^2. Bài 3.3 sẽ đổi sang loss phân loại. Đặt G2=∂J/∂P=2(P−Y)/BG_2=\partial J/\partial P=2(P-Y)/B, shape (B,1). Với lớp linear cuối:

∂J∂W2=H⊤G2,∂J∂b2=∑iG2,i.\frac{\partial J}{\partial W_2}=H^\top G_2,\qquad \frac{\partial J}{\partial b_2}=\sum_iG_{2,i}.

Đạo hàm theo hidden là G2W2⊤G_2W_2^\top. Khi có nhiều đầu ra, mỗi hidden neuron nối tới tất cả nên ảnh hưởng tới loss qua nhiều đường; chain rule cộng đóng góp của các đường ấy, và phép nhân ma trận làm sẵn phép cộng này.

Gradient theo W1W_1 cần ∂J/∂Z1\partial J/\partial Z_1. Đại lượng này phụ thuộc mọi lớp phía sau nên chỉ có khi backward đổ về; còn đạo hàm cục bộ của activation thì tính được ngay lúc forward.

Qua ReLU, phần có Z1<0Z_1<0 không đổi đầu ra khi xê dịch nhỏ nên gradient bằng 0; phần Z1>0Z_1>0 đi qua nguyên vẹn:

G1=(G2W2⊤)⊙1[Z1>0],∂J∂W1=X⊤G1,∂J∂b1=∑iG1,i.G_1=(G_2W_2^\top)\odot\mathbf{1}[Z_1>0],\qquad \frac{\partial J}{\partial W_1}=X^\top G_1,\qquad \frac{\partial J}{\partial b_1}=\sum_iG_{1,i}.

⊙\odot là nhân từng phần tử, không phải nhân ma trận. Vài hệ quả và quy ước:

  • Tại đúng 0, ReLU không có đạo hàm; ta và PyTorch chọn gradient 0. Khi kiểm bằng sai phân, tránh đặt điểm đúng chỗ gãy ấy.
  • Nếu loss lấy trung bình trên nhiều đầu ra cc, hệ số sẽ là 2/(Bc)2/(Bc); công thức ở đây dùng c=1c=1.
  • Gradient của trọng số nối đầu vào jj với nơ-ron ii bằng 0 khi xj=0x_j = 0 hoặc khi nơ-ron đó đóng (zi<0z_i < 0), bất kể gradient đổ về là bao nhiêu.
  • Với nn.Linear, weight có shape (out, in) và Y=XW⊤+bY = XW^\top + b, nên ∂L/∂W=G⊤X\partial L/\partial W = G^\top X với G=∂L/∂YG = \partial L/\partial Y.

Vì gradient của một nơ-ron đi qua chính trọng số của nó, nếu mọi trọng số của một lớp bằng nhau thì các nơ-ron trong lớp nhận cùng gradient và mãi giống nhau; khởi tạo ngẫu nhiên là để phá đối xứng ấy.

Hình dưới vẽ đường đi ấy cho mạng 2→3→12\to3\to1 sẽ dựng bằng PyTorch ở mục dùng thư viện: gradient từ JJ về PP, nhân W2⊤W_2^\top để về HH, qua cổng ReLU′ rồi mới tới lớp đầu.

Forward đi từ trái sang; gradient đi ngược từ J, qua W₂ᵀ và cổng ReLU′.X(B, 2)H(B, 3)P(B, 1)JG₂ = 2(P − Y)/B· W₂ᵀ ⊙ 1[Z₁ > 0]Xᵀ G₁ → dW₁
Forward đi từ trái sang; gradient đi ngược từ J, qua W₂ᵀ và cổng ReLU′.

Hỏi nhanh

H có shape (5, 4), G2 có shape (5, 1). Gradient theo W2 có shape gì?

Tính thử trên một mẫu x=2x=2, y=0y=0, mạng một hidden neuron: w1=0.5,b1=0,w2=2,b2=0w_1=0.5,b_1=0,w_2=2,b_2=0. Forward có z1=1,h=1,p=2,J=4z_1=1,h=1,p=2,J=4. Bắt đầu từ đầu ra: dJ/dp=4dJ/dp=4, nên dJ/dw2=4h=4dJ/dw_2=4h=4 và dJ/db2=4dJ/db_2=4. Truyền về hidden cho dJ/dh=4w2=8dJ/dh=4w_2=8; ReLU đang mở vì z1>0z_1>0, nên dJ/dw1=8x=16dJ/dw_1=8x=16, dJ/db1=8dJ/db_1=8.

Các gradient dùng trọng số trước cập nhật. Nếu sửa w2w_2 rồi mới tính gradient lớp đầu, đang trộn hai mạng khác nhau trong cùng lượt backward. Tính đủ gradient trước, cập nhật tất cả sau. Khi một neuron âm ở mọi mẫu, gradient qua ReLU của nó bằng 0; vấn đề này sẽ nối sang activation ở bài tiếp.

Forward 2 → 1 → 2 → 4; backward nhân dần 4 → 8 → 16.2x1h = ReLU(0.5x)2p = 2h4J = (p − 0)²16dJ/dw₁8dJ/dh4dJ/dp× w₂ = 2× x = 2 (ReLU mở)2(p − y)
Forward 2 → 1 → 2 → 4; backward nhân dần 4 → 8 → 16.

Hỏi nhanh

Mạng một mẫu có h=ReLU(w1x)h = \mathrm{ReLU}(w_1x), p=w2hp = w_2h, L=(p−y)2L = (p - y)^2. Tại x=3x = 3, w1=1w_1 = 1, w2=1w_2 = 1, y=1y = 1, gradient ∂L/∂w1\partial L/\partial w_1 bằng bao nhiêu?

Cài nhỏ bằng NumPy

Ta kiểm trên hai mẫu, hai hidden neuron và điểm không nằm ở chỗ gãy. Tách forward/backward thành hàm để cùng một code phục vụ tính gradient và thử loss sau cập nhật:

Python
X = np.array([[1., 2.], [2., -1.]])
Y = np.array([[1.], [0.]])
params = [np.array([[.2, -.3], [.4, .1]]), np.array([.1, .2]),
          np.array([[.5], [-.4]]), np.array([.05])]

def forward(params):
    W1, b1, W2, b2 = params
    Z1 = X @ W1 + b1
    H = np.maximum(Z1, 0)
    P = H @ W2 + b2
    return P, (Z1, H)

def objective(params):
    P, _ = forward(params)
    assert P.shape == Y.shape
    return np.mean((P - Y) ** 2)

def backward(params):
    P, (Z1, H) = forward(params)
    G2 = 2 * (P - Y) / len(X)
    G1 = (G2 @ params[2].T) * (Z1 > 0)
    return [X.T @ G1, G1.sum(axis=0), H.T @ G2, G2.sum(axis=0)]

print(forward(params)[0].ravel())
print(round(objective(params), 6))
for g in backward(params):
    print(g)

Hai dự đoán là 0.560.56 và 0.100.10, nên loss tính tay (0.442+0.102)/2=0.1018(0.44^2+0.10^2)/2=0.1018. Kiểm từng ma trận gradient cùng shape với trọng số tương ứng. Chẳng hạn dJ/dW2dJ/dW_2 hàng đầu bằng 1.1(−0.44)+0.1(0.10)=−0.4741.1(-0.44)+0.1(0.10)=-0.474; đây là tổng hai đường đóng góp qua hai mẫu. Ở batch này Z1=[1.10.10.1−0.5]Z_1=\begin{bmatrix}1.1&0.1\\0.1&-0.5\end{bmatrix}: neuron ẩn thứ hai đóng ở mẫu thứ hai, và mask (Z1 > 0) chặn gradient qua đúng ô đó.

Mask (Z₁ > 0) chặn gradient ở ô âm duy nhất.1.10.10.1−0.5Z₁>01110maskmẫu 2, neuron 2 đóng:gradient qua ô này bằng 0hàng là mẫu, cột là neuron ẩn
Mask (Z₁ > 0) chặn gradient ở ô âm duy nhất.

Hỏi nhanh

Hàm backward ở trên bị quên * (Z1 > 0). Với Z1Z_1 của batch này, những gradient nào bị sai?

Đối chiếu độc lập rồi mới học

Sai phân trung tâm ước lượng đạo hàm theo một phần tử tham số θk\theta_k bằng (J(θk+ε)−J(θk−ε))/(2ε)\big(J(\theta_k+\varepsilon)-J(\theta_k-\varepsilon)\big)/(2\varepsilon), giữ nguyên các phần tử khác. Mỗi phần tử tốn hai lần tính loss. Cách này chậm nhưng không dùng chung công thức nào với backward, giống lời giải brute force dùng để kiểm thuật toán tối ưu trong CP.

Ta dùng float64 và ε=10−5\varepsilon=10^{-5}: sai số của sai phân trung tâm cỡ ε2\varepsilon^2, sai số làm tròn của float64 còn nhỏ hơn, nên so với ngưỡng atol=1e-8 là đủ chặt. Với float32, sai số làm tròn bị khuếch đại khi chia cho 2ε2\varepsilon, nên khi kiểm hãy chuyển mạng tí hon sang float64. Mọi phần tử của Z1Z_1 cách 0 ít nhất 0.10.1, xa hơn nhiều so với bước xê dịch, nên phép thử không vượt qua chỗ gãy của ReLU.

Python
def numerical_gradient(params, eps=1e-5):
    answer = []
    for p in params:
        g = np.zeros_like(p)
        for index in np.ndindex(p.shape):
            old = p[index]
            p[index] = old + eps
            plus = objective(params)
            p[index] = old - eps
            minus = objective(params)
            p[index] = old
            g[index] = (plus - minus) / (2 * eps)
        answer.append(g)
    return answer

manual = backward(params)
numeric = numerical_gradient(params)
print('numeric match:', all(np.allclose(a, b, atol=1e-8)
                            for a, b in zip(manual, numeric)))

tp = [torch.tensor(p, dtype=torch.float64, requires_grad=True) for p in params]
tx, ty = torch.tensor(X), torch.tensor(Y)
pred = torch.relu(tx @ tp[0] + tp[1]) @ tp[2] + tp[3]
((pred - ty) ** 2).mean().backward()
print('autograd match:', all(np.allclose(g, p.grad.numpy(), atol=1e-10)
                            for g, p in zip(manual, tp)))
updated = [p - .05 * g for p, g in zip(params, manual)]
print(round(objective(params), 6), round(objective(updated), 6))

Hai dòng True nói backward khớp với hai cách tính độc lập tại bộ tham số đã chọn. Dòng cuối cho thấy một bước gradient descent với learning rate 0.050.05 đưa loss từ 0.10180.1018 xuống 0.0655130.065513. Hai loại bằng chứng này không thay được nhau. Loss giảm sau một bước chỉ cần hướng cập nhật đi xuống, nên một backward sai ở vài phần tử vẫn có thể làm loss giảm. Ngược lại, gradient đúng không hứa hội tụ tới nghiệm toàn cục, vì loss của mạng neural thường không lồi.

Hỏi nhanh

Mạng nhỏ ở trên có 9 phần tử tham số. Kiểm bằng sai phân trung tâm thì phải tính objective bao nhiêu lần? Với một MLP có 10610^6 tham số thì sao?

Hỏi nhanh

Gradient tính bằng NumPy trùng với autograd và với sai phân trên một batch nhỏ. Điều đó bảo đảm được gì?

Dùng thư viện ở đúng tầng

Khi đã hiểu cơ chế, bài thực tế viết torch.nn.Sequential(torch.nn.Linear(d,h), torch.nn.ReLU(), torch.nn.Linear(h,c)) để thư viện quản lý tham số và autograd lo phần backward. Trước khi train, nên hỏi lại mô hình hai điều: output có shape như dự tính không, và mạng có bao nhiêu tham số:

Python
model = torch.nn.Sequential(torch.nn.Linear(2, 3), torch.nn.ReLU(),
                            torch.nn.Linear(3, 1))
print(tuple(model(torch.zeros(4, 2)).shape))
print(sum(p.numel() for p in model.parameters()))

Đầu ra (4,1) là bốn dự đoán. Số tham số là 2⋅3+3+3⋅1+1=132\cdot3+3+3\cdot1+1=13, tính cả hai bias; layer ReLU không có tham số học. Hai lỗi hay gặp khi tự viết model:

  • Lớp con phải được gán làm thuộc tính của nn.Module hoặc đặt trong nn.ModuleList. Để trong list Python thường thì model.parameters() không thấy, optimizer không học và .to(device) cũng bỏ sót.
  • Dùng cùng một đối tượng lớp ở hai chỗ, như nn.Sequential(l, nn.ReLU(), l), là chia sẻ trọng số: parameters() chỉ đếm một lần và gradient cộng từ cả hai chỗ.

Đầu ra và loss phải đi cùng nhau: phân loại nhị phân dùng một logit với BCEWithLogitsLoss, nhiều lớp loại trừ nhau dùng cc logits với CrossEntropyLoss (bài 3.3).

Hỏi nhanh

Mạng hồi quy trả về pred shape (4, 1), giá trị đúng bằng target y = torch.tensor([1., 2., 3., 4.]) có shape (4,). Thế nhưng torch.nn.MSELoss()(pred, y) lại cho 2.52.5 thay vì 00. Vì sao?

Khi đi thi

  • Cho mạng học thuộc vài chục mẫu trước. Loss không về gần 0 thì lỗi nằm ở code, chưa phải ở hyperparameter.
  • Tự viết backward thì kiểm bằng sai phân trên mạng tí hon, dùng float64.
  • Chép trọng số sang nn.Linear thì nhớ chuyển vị, rồi so output hai bản trên vài mẫu.

Tóm tắt

  • Lớp ẩn tạo đặc trưng mới; activation là phần phi tuyến, thiếu nó thì nhiều lớp vẫn chỉ là một lớp linear.
  • Backprop đi ngược graph, nhân độ nhạy cục bộ và cộng các nhánh. Qua ReLU, gradient bị chặn ở các ô âm.
  • Gradient có cùng shape với tham số; tính đủ mọi gradient rồi mới cập nhật.
  • Kiểm backward bằng sai phân và autograd trên mạng tí hon trước khi train thật.

Kiểm tra cuối bài

Câu 1

Đề yêu cầu dựng một MLP chỉ gồm lớp linear và hàm ngưỡng Θ(z)=1\Theta(z) = 1 nếu z≥0z \ge 0, ngược lại bằng 0. Trọng số đặt tay, không huấn luyện. Đầu ra phải bằng 1 khi điểm (x,y)(x, y) nằm trong tam giác có đỉnh (0,0)(0,0), (3,1)(3,1), (1,5)(1,5), tính cả cạnh. Lớp ẩn có h1=Θ(3y−x)h_1 = \Theta(3y - x), h2=Θ(7−2x−y)h_2 = \Theta(7 - 2x - y), h3=Θ(5x−y)h_3 = \Theta(5x - y). Chọn neuron đầu ra.

Phỏng theoUSA-NA-AIO 2026 · Vòng 1 · Part 7.4

Câu 2

Mạng không có bias. z1=wAx1+wBx2z_1 = w_Ax_1 + w_Bx_2, a1=g(z1)a_1 = g(z_1). Từ a1a_1 tách ra hai nhánh: z2=wCa1z_2 = w_Ca_1, a2=g(z2)a_2 = g(z_2) và z3=wDa1z_3 = w_Da_1, a3=g(z3)a_3 = g(z_3). Cuối cùng z4=wEa2+wFa3z_4 = w_Ea_2 + w_Fa_3, y^=g(z4)\hat y = g(z_4). Đặt δ=∂ℓ/∂z4\delta = \partial\ell/\partial z_4. Biểu thức nào là ∂ℓ/∂a1\partial\ell/\partial a_1?

Phỏng theoCMU 10-601 · Exam 2 Practice · Q4.4

Câu 3

Với lin = torch.nn.Linear(2, 3), lin.weight và lin.bias có shape gì?

Câu 4

Ảnh xám 28×2828 \times 28 được duỗi thành vector, rồi đưa qua MLP 784→128→10784 \to 128 \to 10, cả hai lớp đều có bias. Mạng có bao nhiêu tham số?

Câu 5

Mạng một đầu vào: a1=w11x+b11a_1 = w_{11}x + b_{11}, a2=w12x+b12a_2 = w_{12}x + b_{12}, zj=ReLU(aj)z_j = \mathrm{ReLU}(a_j), a3=w21z1+w22z2+b21a_3 = w_{21}z_1 + w_{22}z_2 + b_{21}, y^=σ(a3)\hat y = \sigma(a_3). Loss là cross-entropy nhị phân, nên ∂L/∂a3=y^−y\partial L/\partial a_3 = \hat y - y. Ở một mẫu có a1=0.5a_1 = 0.5, a2=−0.2a_2 = -0.2, với w21=1w_{21} = 1, w22=−1w_{22} = -1. Gradient theo hai bias của lớp ẩn thế nào?

Phỏng theoCMU 10-601 · Exam 2 Practice · Q4.2(d)

Câu 6

Mạng một lớp ẩn: z1=w11x1+w12x2z_1 = w_{11}x_1 + w_{12}x_2, z2=w21x1+w22x2z_2 = w_{21}x_1 + w_{22}x_2, aj=f(zj)a_j = f(z_j) với ff là sigmoid. Đầu ra trước activation là z=v1a1+v2a2z = v_1a_1 + v_2a_2. Loss được cộng thêm số hạng phạt λz2\lambda z^2 cho từng mẫu. Đạo hàm của số hạng phạt này theo w11w_{11} là gì?

Phỏng theoMIT 6.036 · Final, Spring 2022 · Q2(a)

Câu 7

Loss MSE lấy trung bình trên BB mẫu và cc đầu ra, như mặc định của nn.MSELoss. Đạo hàm theo mỗi phần tử của PP bằng phần dư nhân với hệ số nào?

Câu 8

Hai mẫu cùng dùng một trọng số ww. Đạo hàm của loss từng mẫu theo ww là 66 và −2-2. Loss của batch là trung bình hai loss. Gradient theo ww bằng bao nhiêu?

Câu 9

Forward đã dùng W2 cũ. Trong backward tự viết, code cập nhật W2 trước rồi mới tính G1 = G2 @ W2.T. Sửa lỗi này thế nào?

Câu 10

Mạng một đầu vào, hai neuron ẩn sigmoid, đầu ra linear: y^=v1σ(w1x+c1)+v2σ(w2x+c2)+d\hat y = v_1\sigma(w_1x + c_1) + v_2\sigma(w_2x + c_2) + d. Khởi tạo hai neuron giống hệt nhau, tức w1=w2w_1 = w_2, c1=c2c_1 = c_2, v1=v2v_1 = v_2, rồi chạy batch gradient descent với MSE. Chuyện gì xảy ra?

Phỏng theoMIT 6.036 · Final, Spring 2022 · Q4(h)

Đọc thêm

  • D2L — Backpropagation: theo dõi các biến trung gian và quy tắc chuỗi trong mạng nhiều lớp.
  • Goodfellow, Bengio, Courville — Deep Learning, chương 6: đọc về feedforward network, khả năng biểu diễn và graph tính toán.
  • PyTorch 2.9 — Linear: kiểm quy ước weight và shape trước khi chuyển mô hình tự cài sang thư viện.