Làm cho mạng train được, rồi khái quát hóa được
Mạng sáu lớp có loss kẹt ở ln 2, sửa từng phép đo một. Rồi double descent: 5.000 tham số trên 40 điểm.
Trên trang này
Mạng từ Chương 5 hoạt động. Nó có chín tham số, học được XOR, và gradient của nó khớp với PyTorch đến mười sáu chữ số thập phân.
Làm nó sâu sáu lớp và nó ngừng học hoàn toàn. Không phải chậm — hoàn toàn. Đây là một mạng sáu lớp trên bài toán phân loại hai vòng xoắn, được train trong 5000 bước:
step 1: loss 0.693147
step 5000: loss 0.693147
accuracy: 50.0 %Con số đó không tùy ý. là binary cross-entropy của một model luôn xuất xác suất cho mọi thứ, và 50 % là tung đồng xu trên một dataset cân bằng. Sau năm nghìn bước, mạng chưa dịch chuyển một chữ số nào. Không có gì crash, không cảnh báo nào xuất hiện, và gradient vẫn đúng tuyệt đối.
Chương này nói về khoảng cách giữa một mạng chạy được và một mạng hoạt động được. Nó có hai nửa trông như hai chủ đề khác nhau nhưng thực ra là cùng một việc: làm cho loss đi xuống, và làm cho nó đi xuống trên dữ liệu mà model chưa từng thấy.
Vì sao mạng sáu lớp đã chết
Liên kết đến mục: Vì sao mạng sáu lớp đã chếtBắt đầu bằng cách nhìn, thay vì đoán. Đẩy một batch input đi qua mạng và in độ lệch chuẩn của activation ở mỗi layer, rồi in độ lệch chuẩn của weight gradient:
def profile(model, x):
h = x
for layer in model:
h = layer(h)
if isinstance(layer, (nn.Tanh, nn.ReLU)):
print(f"activation std: {h.std().item():.4f}")
model(x).sum().backward()
for p in model.parameters():
if p.dim() == 2:
print(f"gradient std: {p.grad.std().item():.2e}")Ba cách khởi tạo, cùng kiến trúc, sáu layer :
| khởi tạo | activation std, layer 1→6 |
|---|---|
| normal, std | 0.0145 · 0.0016 · 0.0002 · 0.0000 · 0.0000 · 0.0000 |
| normal, std | 0.6573 · 0.9296 · 0.9585 · 0.9634 · 0.9637 · 0.9625 |
| Xavier | 0.1579 · 0.1493 · 0.1353 · 0.1333 · 0.1325 · 0.1403 |
| khởi tạo | gradient std, layer đầu → layer cuối |
|---|---|
| normal, std | 3.20e-06 · 4.97e-07 · … · 6.40e-06 |
| normal, std | 1.94e+03 · 2.28e+02 · 1.22e+02 · 4.43e+01 · 1.85e+01 · 7.30e+00 |
| Xavier | 2.31e+00 · 4.50e-01 · 4.26e-01 · 3.89e-01 · 4.39e-01 · 4.73e-01 |
Hàng đầu tiên là mạng ở trên, và nó không học chậm — nó không còn tín hiệu nào. Đến layer bốn, độ lệch chuẩn activation đã underflow về 0 ở bốn chữ số thập phân. Mọi input tạo ra cùng một output, output là một hằng số, và gradient của một hằng số thì không có gì. Weight được khởi tạo nhỏ để "cho an toàn", và nhỏ là chí mạng.
Hàng thứ hai là lỗi ngược lại, và đáng hiểu vì nó phản trực giác. Activation trông khỏe — quanh 0.96 — nhưng đó là bị bão hòa, ghim gần giới hạn của nó, đúng vùng mà Chương 5 đã đo là làm mất gần mười nghìn lần gradient. Vậy mà gradient lại khổng lồ: 1940 ở layer đầu tiên. Cả hai điều cùng đúng. Mỗi bước backward nhân với , và với 128 input ở unit variance, hệ số đó có gain khoảng , lấn át mức co lại từ đã bão hòa. Gradient tăng theo cấp số nhân khi đi ngược về. Đây là exploding gradient, và trong bất kỳ lần train thực nào, nó tạo ra các giá trị loss nan chỉ sau vài bước.
Hàng thứ ba là thứ bạn muốn: activation gần như giữ nguyên thang đo qua độ sâu, gradient gần như giữ nguyên thang đo qua độ sâu. Không gì chết, không gì nổ.
Chuẩn hóa, và cái nào sống sót
Liên kết đến mục: Chuẩn hóa, và cái nào sống sótKhởi tạo tốt sửa thang đo ở bước 0. Nó không giữ thang đo cố định: weight di chuyển, và đến bước năm nghìn, lập luận variance cẩn thận không còn áp dụng nữa.
Các layer chuẩn hóa cưỡng chế thang đo liên tục. Với một vector activation, trừ đi mean, chia cho standard deviation, rồi áp dụng một scale học được và shift để layer có thể hoàn tác việc chuẩn hóa nếu hóa ra đó là điều nó muốn:
Câu hỏi thật sự duy nhất là bạn lấy trung bình trên cái gì. Batch normalisation3 lấy và trên chiều batch, một thống kê cho mỗi feature. Layer normalisation4 lấy chúng trên các feature, một thống kê cho mỗi example.
Lựa chọn đó trông nhỏ nhưng quyết định gần như mọi thứ phía sau:
BatchNorm làm output của mỗi example phụ thuộc vào những example khác tình cờ nằm trong batch của nó. Khi train, đó là một regulariser nhẹ. Khi inference, không có batch, nên nó phải giữ running average của các thống kê thu được trong lúc train — nghĩa là layer hành xử khác nhau giữa chế độ training và evaluation, và quên chuyển chế độ là một trong những bug phổ biến nhất trong lĩnh vực này. Nó cũng suy giảm với batch nhỏ, và lúng túng với sequence có độ dài thay đổi, vì "mean trên batch tại vị trí 40" được tính từ bất kỳ số sequence nào tình cờ dài đến đó.
LayerNorm chuẩn hóa từng example độc lập. Không phụ thuộc batch, không running statistics, hành vi giống hệt khi training và inference, không quan tâm batch size, không quan tâm sequence length. Mỗi thuộc tính đó là yêu cầu chứ không phải tiện ích khi bạn đang tạo từng token một cho một user, cũng là nơi Chương 13 sẽ đi đến.
Đây là lý do LayerNorm là thứ bạn sẽ gặp lại trong Chương 9 không đổi: transformer block dùng nó, và dùng vì các lý do ở cột bên phải, không phải vì nó tốt hơn một cách trừu tượng.
Sửa từng thứ một, đó mới là skill thật sự
Liên kết đến mục: Sửa từng thứ một, đó mới là skill thật sựBốn ứng viên sửa mạng đã chết: Xavier initialisation, LayerNorm, residual connections, và Adam thay cho SGD. Cám dỗ là áp dụng cả bốn rồi đi tiếp. Làm vậy bạn sẽ không bao giờ biết cái nào quan trọng, và lần sau khi chuyện này xảy ra, bạn sẽ không có phương pháp — chỉ có nghi lễ.
Vì vậy hãy áp dụng từng cái một. Cùng seed, cùng dữ liệu, cùng kiến trúc, 800 bước:
| thứ được thêm vào | loss cuối | accuracy |
|---|---|---|
| không gì | 0.6931 | 50.0 % |
| Xavier initialisation | 0.5692 | 60.4 % |
| LayerNorm | 0.6230 | 61.5 % |
| residual connections | 0.6651 | 56.6 % |
| Adam | 0.6787 | 58.7 % |
| cả bốn | 0.0000 | 100.0 % |
Đọc bảng đó như cách bạn sẽ đọc lúc 2 giờ sáng, kết luận sẽ là: không thứ nào tự hoạt động, mọi thứ cùng hoạt động, vì vậy deep learning là giả kim thuật. Kết luận đó sai, và tìm ra vì sao là điều hữu ích nhất trong chương này.
Cho mỗi lần chạy ngân sách gấp sáu lần — 5000 bước thay vì 800 — và bức tranh thay đổi hoàn toàn:
| thứ được thêm vào | loss cuối @ 5000 | accuracy |
|---|---|---|
| không gì | 0.6931 | 50.0 % |
| Xavier initialisation | 0.0007 | 100.0 % |
| LayerNorm | 0.0002 | 100.0 % |
| residual connections | 0.6653 | 56.7 % |
| Adam | 0.6908 | 53.4 % |
| Xavier + Adam | 0.0000 | 100.0 % |
| Xavier + LayerNorm | 0.0001 | 100.0 % |
Giờ bức tranh sắc nét, và nó là một chẩn đoán chứ không phải một nghi lễ.
Chỉ khởi tạo đã sửa được. Chỉ chuẩn hóa đã sửa được. Mỗi thứ xử lý đúng căn bệnh — tín hiệu forward sụp về 0 — và một trong hai là đủ. Ở 800 bước, chúng chỉ trông như được điểm một phần, vì chúng đã giải quyết vấn đề và vẫn đang leo ra khỏi hố.
Residual connections và Adam không sửa được, ở bất kỳ ngân sách nào. Không phải vì chúng tệ, mà vì chúng chữa một bệnh khác. Residual connection cho gradient một đường vòng quanh layer đang chặn; điều đó cực kỳ đáng giá khi gradient là vấn đề, và vô giá trị khi tín hiệu forward đã bằng 0, vì đường tắt quanh một layer chết vẫn mang một giá trị chết. Adam rescale bước của từng parameter bằng lịch sử gradient riêng của nó; điều đó giúp khi gradient có độ lớn rất khác nhau, và không thể hồi sinh một mạng whose output không phụ thuộc vào input.
Và "không gì" vẫn đúng bằng 0.6931 sau năm nghìn bước. Không phải 0.6929. Nó không chậm; nó đã chết, và sự phân biệt đó giờ hiện rõ theo cách trước đây chưa có, vì bạn có hàng cho thấy một cách sửa thật sự hoạt động để so sánh.
Xứng đáng dùng PyTorch
Liên kết đến mục: Xứng đáng dùng PyTorchTừ đây trở đi khóa học này dùng PyTorch. Việc đó nên được giành lấy thay vì chỉ tuyên bố, nên đây là chính xác những gì nó làm mà bạn đã biết cách làm.
Optimiser là một quy tắc biến gradient thành cập nhật parameter. Plain gradient descent dùng gradient. Momentum dùng running average của nó, làm mượt nhiễu và tích tốc độ theo những hướng vẫn nhất quán:
v = beta * v + p.grad
p -= lr * v Adam5 giữ hai running average — của gradient và của gradient bình phương — rồi chia cái này cho căn bậc hai của cái kia, để mỗi parameter nhận một bước được scale theo độ lớn gradient gần đây của chính nó:
m = b1 * m + (1 - b1) * g # mean of the gradient
v = b2 * v + (1 - b2) * g * g # mean of the squared gradient
m_hat = m / (1 - b1 ** t) # bias correction: both averages start at zero
v_hat = v / (1 - b2 ** t)
p -= lr * m_hat / (v_hat.sqrt() + eps) Mười dòng. Chạy cả hai so với torch.optim trên cùng bài toán trong 50 bước:
SGD+momentum by hand [2.7781870365142822, -1.0304985046386719]
torch [2.7781870365142822, -1.0304983854293823] max |diff| = 1.19e-07
Adam by hand [0.4893140196800232, -0.46317872405052185]
torch [0.48931416869163513, -0.46317875385284424] max |diff| = 1.49e-07Giống hệt đến độ chính xác float32. torch.optim.Adam là năm dòng đó, cộng thêm nhiều thập kỷ chăm sóc edge case và một C++ kernel. Đó là cuộc trao đổi bạn thực hiện từ đây trở đi: không đổi hiểu biết lấy phép thuật, mà đổi những dòng bạn đã viết lấy tốc độ.
Vì sao Adam tồn tại: curvature
Liên kết đến mục: Vì sao Adam tồn tại: curvatureCách giải thích Adam thông thường là "adaptive per-parameter learning rates", đây là mô tả chứ không phải lý do. Lý do là hình học, và có thể đo được.
Lấy một loss có curvature khác nhau giữa các hướng: dốc ở một hướng, thoải ở hướng khác. SGD có một learning rate toàn cục, nên nó phải chọn một giá trị đủ nhỏ để ổn định ở hướng dốc nhất — và giá trị đó lại quá nhỏ cho hướng thoải, nơi tiến độ bò chậm. Đây là điều tạo ra bức tranh kinh điển của gradient descent đi ngoằn ngoèo xuống một thung lũng hẹp.
Hai tỷ lệ curvature, ba optimiser, 300 bước, và mỗi optimiser được cấp learning rate tốt nhất từ một sweep để không ai bị thiệt:
| tỷ lệ curvature | SGD | SGD + momentum | Adam |
|---|---|---|---|
| 10 : 1 | error 0.000002 | error 0.000000 | error 0.000000 |
| 1000 : 1 | error 1.925485 | error 0.001432 | error 0.000000 |
| diverged at (1000:1) | 4 of 8 rates | 4 of 8 rates | 0 of 6 rates |
Ở tỷ lệ mười, mọi thứ đều hoạt động và không có gì để bàn. Ở một nghìn, SGD thuần không thể đạt đáp án ở bất kỳ learning rate nào đã thử — kết quả tốt nhất vẫn là error 1.93 — và nó diverge thẳng ở một nửa số rate. Adam đáp đúng target và không diverge ở rate nào.
Cột cuối đó là lý do thực tế Adam là mặc định. Không phải Adam tìm được lời giải tốt hơn; trên các bài toán well-conditioned, SGD được tune thường khớp hoặc vượt nó. Mà là Adam ít nhạy hơn nhiều với learning rate bạn đã chọn, và các mạng thật có tỷ lệ curvature tệ hơn một nghìn rất nhiều trên hàng triệu parameter của chúng.
Hai mảnh nữa thuộc về đây và cả hai đều là một dòng. Gradient clipping rescale vector gradient bất cứ khi nào norm của nó vượt một ngưỡng, biến hàng "loss đột nhiên nhảy lên một giá trị khổng lồ" trong bảng chẩn đoán thành chuyện không đáng kể. Và learning rate schedules: một warmup ngắn từ gần 0 trong vài trăm bước đầu, vì ước lượng variance của Adam là rác cho đến khi nó đã thấy một số gradient và một bước đủ lớn dựa trên rác có thể phá hỏng khởi tạo; rồi cosine decay về 0, vì kết thúc một lần chạy với cùng step size như lúc bắt đầu nghĩa là rung quanh minimum thay vì ổn định vào đó.
Nửa thứ hai: model fit hoàn hảo nhưng không dự đoán được gì
Liên kết đến mục: Nửa thứ hai: model fit hoàn hảo nhưng không dự đoán được gìMọi thứ đến giờ là về việc làm loss giảm. Giờ đến nửa khó hơn, vì loss giảm không phải mục tiêu — nó là proxy cho mục tiêu, và proxy này thất bại theo một cách cụ thể và nổi tiếng.
Mười hai điểm từ một hàm trơn với một chút nhiễu. Fit các đa thức có bậc tăng dần:
| bậc | train RMSE | test RMSE |
|---|---|---|
| 1 | 0.764499 | 0.6985 |
| 3 | 0.252605 | 0.3031 |
| 5 | 0.164437 | 0.1568 |
| 9 | 0.088960 | 0.2347 |
| 11 | 0.000000 | 1.2094 |
Bậc 11 qua 12 điểm đi qua từng điểm một cách chính xác — train error bằng 0 đến sáu chữ số thập phân — và tệ hơn bậc 5 tám lần trên dữ liệu nó chưa thấy. Yêu cầu bậc 3 và bậc 11 dự đoán tại , ngay ngoài khoảng training:
degree 3: predicts -1.053 (truth -0.012)
degree 11: predicts +61.224 (truth -0.012)Sáu mươi mốt, trong khi đáp án xấp xỉ 0. Model không học hàm; nó học mười hai điểm, và giữa chúng nó làm bất cứ điều gì số học đòi hỏi.
Đây là overfitting, và đối lập của nó — bậc 1, không thể biểu diễn đường cong chút nào và tệ ở mọi nơi — là underfitting. Cách kể cổ điển chia expected error của một model thành ba phần: bias, lỗi do model quá cứng nhắc để biểu diễn sự thật; variance, lỗi do model quá linh hoạt đến mức đuổi theo nhiễu trong đúng sample này; và nhiễu không thể giảm, thứ không gì sửa được. Model đơn giản có bias, model linh hoạt có variance cao, và đơn thuốc cổ điển là tìm điểm ngọt ở giữa — bậc 5 trong bảng trên.
Các công cụ tiêu chuẩn đều tấn công thành phần variance:
- L2 regularisation (weight decay) thêm vào loss, kéo weight về 0 và làm hàm mượt hơn. Trong bảng trên, hệ số lớn nhất của bậc 11 gây ra thiệt hại; phạt độ lớn sẽ vô hiệu hóa nó.
- L1 thêm thay vào đó. Khác biệt không phải trang trí: gradient của L2 tỷ lệ với weight nên co lại khi weight co lại, tiến gần 0 mà không chạm tới, trong khi gradient của L1 là một hằng số tiếp tục đẩy đến cùng. Vì vậy L1 tạo ra weight chính xác bằng 0 — nó chọn feature. L2 tạo ra weight nhỏ. Dùng L2 khi bạn muốn độ mượt, L1 khi bạn muốn sparsity.
- Dropout7 đưa ngẫu nhiên một tập con activation về 0 ở mỗi training step, để không unit nào có thể dựa vào việc một unit cụ thể khác luôn có mặt.
- Early stopping theo dõi validation loss và dừng khi nó quay đầu đi lên.
- Data augmentation tạo thêm training example từ những cái bạn có, tấn công vấn đề từ gốc: overfitting là thiếu dữ liệu cũng nhiều như thừa parameter.
- Cross-validation chia dữ liệu theo cách và train lần, đổi lấy một ước lượng đáng tin cậy về test error khi bạn có quá ít dữ liệu để dành riêng một held-out set.
Double descent, hay vì sao phần trước không phải toàn bộ câu chuyện
Liên kết đến mục: Double descent, hay vì sao phần trước không phải toàn bộ câu chuyệnGiờ đến sự thật phá vỡ bức tranh.
Câu chuyện bias-variance nói rằng qua khỏi điểm ngọt, thêm parameter nghĩa là generalisation tệ hơn. Các language model hiện đại có nhiều parameter hơn rất xa so với mức các quy tắc cổ điển cho phép đối với lượng dữ liệu chúng thấy, và chúng generalise xuất sắc. Cả hai mệnh đề đều đúng, và hòa giải chúng là điều hữu ích nhất trong chương này.
Bốn mươi training point, input hai mươi chiều, random ReLU features, và số feature được quét từ 2 đến 5000 — với nghiệm minimum-norm được chọn bất cứ khi nào có nhiều nghiệm fit:
| train RMSE | test RMSE | |||
|---|---|---|---|---|
| 10 | 0.25 | 0.8822 | 1.2520 | 1.89 |
| 20 | 0.50 | 0.5962 | 1.1634 | 2.59 |
| 30 | 0.75 | 0.3896 | 1.5323 | 4.15 |
| 38 | 0.95 | 0.1769 | 3.7163 | 10.25 |
| 40 | 1.00 | 0.0000 | 5.8140 | 14.83 |
| 42 | 1.05 | 0.0000 | 3.1623 | 9.35 |
| 60 | 1.50 | 0.0000 | 1.1058 | 2.78 |
| 200 | 5.00 | 0.0000 | 0.6638 | 0.98 |
| 1500 | 37.50 | 0.0000 | 0.5859 | 0.33 |
| 5000 | 125.00 | 0.0000 | 0.5664 | 0.18 |
Đọc nó thành ba phần. Đến , câu chuyện cổ điển đúng hoàn toàn: error giảm, rồi bắt đầu tăng. Tại — interpolation threshold, nơi model có đúng đủ parameter để đi qua mọi training point — test error đạt đỉnh, ở 5.81, tệ gấp năm lần model nhỏ. Đỉnh đó là cảnh báo cổ điển, và nó có thật.
Rồi nó descends lần nữa. Và nó tiếp tục descends, qua , qua , cho đến , nơi test error 0.5664 tốt hơn mức tốt nhất mà bất kỳ model under-parameterised nào từng đạt được. Một model có 5000 parameter fit trên 40 điểm là model tốt nhất trong bảng.
Đây là double descent,89 và cơ chế hiện rõ ở cột cuối. Khi , có vô số thiết lập parameter fit training data chính xác, và bạn nhận được cái nào phụ thuộc vào cách bạn chọn. Nghiệm minimum-norm chọn cái nhỏ nhất, và cho thấy điều đó nghĩa là gì: nó đạt đỉnh 14.83 ngay tại threshold — nơi có đúng một nghiệm nội suy và bạn bị kẹt với nó, dù cực đoan đến đâu — rồi giảm đơn điệu khi tăng, vì nhiều parameter hơn nghĩa là có nhiều nghiệm nội suy hơn để chọn, nghĩa là nghiệm nhỏ nhất sẵn có trở nên nhỏ hơn. Tại , norm là 0.18, nhỏ hơn tám mươi lần so với tại threshold.
Vậy các parameter thêm vào không thêm độ phức tạp. Chúng thêm lựa chọn, và quy tắc chọn dùng lựa chọn đó để đổi lấy sự đơn giản. Regularisation không nằm trong loss function; nó nằm trong thuật toán. Gradient descent từ một khởi tạo nhỏ có bias đã được ghi nhận về phía các nghiệm norm nhỏ, đó là lý do hành vi này xuất hiện trong các mạng thật được train theo cách thông thường, chứ không chỉ trong đại số tuyến tính ở trên.
Hệ quả thực tế, thứ Chương 10 phụ thuộc vào: "model có nhiều parameter hơn dữ liệu, nên nó sẽ overfit" không phải một lập luận hợp lệ. Đó từng là quy tắc tốt khi model sống bên trái threshold. Mọi thứ thú vị bây giờ sống rất xa bên phải nó, nơi quy tắc đảo chiều.
Tiếp theo sẽ đi đâu
Liên kết đến mục: Tiếp theo sẽ đi đâuCác công cụ trong chương này đủ để train một mạng hoạt động trên dữ liệu bạn có thể đặt vào bảng: các hàng số, một cột nhãn.
Ngôn ngữ không phải vậy. Trước khi một model có thể dự đoán từ tiếp theo, phải có thứ gì đó quyết định "từ" là gì — và câu trả lời không phải chữ cái cũng không phải từ, mà là một vocabulary model học từ raw bytes của training data. Quyết định đó, được đưa ra một lần trước khi training bắt đầu, quyết định model có thể nói bao nhiêu thứ, một request tốn bao nhiêu chi phí, và vì sao các model có thể vượt qua kỳ thi luật lại không thể đếm đáng tin cậy số chữ cái trong strawberry.
Chương 7 xây dựng một tokenizer.
Nguồn và phương pháp
Liên kết đến mục: Nguồn và phương phápVề residual connections được dùng ở trên, xem He et al., Deep Residual Learning for Image Recognition (arXiv:1512.03385). Building makemore Part 3: Activations & Gradients, BatchNorm của Andrej Karpathy trình bày diagnostic bằng activation histogram trên một model thật và là phần thực hành hay nhất cho nửa đầu chương này. Các bài giảng 8 và 11–13 trong Learning From Data của Yaser Abu-Mostafa trình bày đúng lý thuyết generalisation cổ điển, bao gồm cả những phần chương này đã nén vào một đoạn.
Tài liệu tham khảo
Liên kết đến mục: Tài liệu tham khảo-
Glorot, X. và Bengio, Y. Understanding the difficulty of training deep feedforward neural networks. AISTATS (2010). Lập luận bảo toàn variance được tái hiện trong hộp ở trên. ↩
-
He, K., Zhang, X., Ren, S. và Sun, J. Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification. arXiv:1502.01852 (2015). ↩
-
Ioffe, S. và Szegedy, C. Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. arXiv:1502.03167 (2015). Lưu ý rằng cách giải thích "internal covariate shift" trong tiêu đề về sau đã bị tranh luận đáng kể; layer hoạt động, còn diễn giải ban đầu về lý do thì đang bị phản biện. ↩
-
Ba, J. L., Kiros, J. R. và Hinton, G. E. Layer Normalization. arXiv:1607.06450 (2016). ↩
-
Kingma, D. P. và Ba, J. Adam: A Method for Stochastic Optimization. arXiv:1412.6980 (2014). ↩
-
Loshchilov, I. và Hutter, F. Decoupled Weight Decay Regularization. arXiv:1711.05101 (2017). ↩
-
Srivastava, N., Hinton, G., Krizhevsky, A., Sutskever, I. và Salakhutdinov, R. Dropout: A Simple Way to Prevent Neural Networks from Overfitting. JMLR 15, pp. 1929–1958 (2014). ↩
-
Belkin, M., Hsu, D., Ma, S. và Mandal, S. Reconciling modern machine-learning practice and the classical bias–variance trade-off. PNAS 116(32), pp. 15849–15854 (2019). Bài báo đặt tên cho hiện tượng này. ↩
-
Nakkiran, P., Kaplun, G., Bansal, Y., Yang, T., Barak, B. và Sutskever, I. Deep Double Descent: Where Bigger Models and More Data Hurt. arXiv:1912.02292 (2019). Cho thấy hiệu ứng trong các deep network thật, và trên trục training time cũng như trục model size. ↩