5 điểm bởi GN⁺ 2025-11-03 | 1 bình luận | Chia sẻ qua WhatsApp
  • Lan truyền ngược (backpropagation) là cốt lõi của việc huấn luyện mạng nơ-ron, nhưng nếu không hiểu cơ chế hoạt động bên trong, có thể phát sinh những lỗi ngoài dự đoán do cấu trúc “trừu tượng hóa bị rò rỉ (leaky abstraction)”
  • Các hàm kích hoạt sigmoid hoặc tanh có thể khiến việc huấn luyện dừng lại do tiêu biến gradient (vanishing gradient) nếu khởi tạo trọng số sai
  • ReLU có thể gây ra hiện tượng ReLU chết (dead ReLU), trong đó nơ-ron bị vô hiệu hóa vĩnh viễn khi đầu vào nhỏ hơn hoặc bằng 0
  • Trong RNN, việc lặp lại phép nhân ma trận có thể gây ra bùng nổ gradient (exploding gradient); để tránh điều này cần dùng gradient clipping hoặc LSTM
  • Nếu không hiểu cách lan truyền ngược hoạt động, thì dù framework có tự động xử lý, khả năng debug và cải thiện mô hình vẫn sẽ suy giảm đáng kể

Sự cần thiết phải hiểu lan truyền ngược

  • Trong khóa học CS231n của Stanford, bài tập được thiết kế để sinh viên tự triển khai lan truyền thuận và lan truyền ngược
    • Một số sinh viên phàn nàn rằng điều này không cần thiết vì các framework như TensorFlow đã tự động tính lan truyền ngược
  • Tuy nhiên, lan truyền ngược không phải là một sự trừu tượng hóa hoàn chỉnh mà là một sự trừu tượng hóa bị rò rỉ; nếu không hiểu hoạt động bên trong, sẽ rất khó xác định nguyên nhân khiến việc huấn luyện thất bại
  • Thái độ đơn giản cho rằng “framework sẽ tự lo hết” dẫn đến suy giảm năng lực thiết kế mô hình và debug

Tiêu biến gradient trong sigmoid

  • Các hàm phi tuyến sigmoid hoặc tanh sẽ rơi vào trạng thái bão hòa (saturation) khi giá trị đầu vào lớn, khiến đầu ra tiến gần 0 hoặc 1
    • Lúc này gradient cục bộ z(1-z)* trở thành 0, khiến sự lan truyền gradient bị chặn trong quá trình lan truyền ngược
  • Gradient lớn nhất của sigmoid là 0.25, nên sau mỗi lần đi qua, tín hiệu giảm xuống còn 1/4 hoặc ít hơn
  • Kết quả là tốc độ học của các tầng thấp hơn chậm hơn rõ rệt so với các tầng phía trên
  • Vì vậy, khi dùng các tầng sigmoid, cần đặc biệt chú ý đến khởi tạo trọng số và tiền xử lý dữ liệu

Vấn đề ReLU chết

  • ReLU là hàm đưa đầu ra về 0 khi đầu vào nhỏ hơn hoặc bằng 0
    • Nếu đầu ra của nơ-ron bằng 0 ở bước lan truyền thuận, thì khi lan truyền ngược gradient cũng bằng 0, khiến nơ-ron đó bị vô hiệu hóa vĩnh viễn
  • Trong quá trình huấn luyện, cập nhật trọng số quá lớn hoặc learning rate cao có thể khiến nơ-ron bị kẹt ở “trạng thái chết”
  • Cũng có trường hợp sau khi huấn luyện, một phần đáng kể nơ-ron trong toàn bộ mạng chỉ xuất ra 0
  • Vì vậy khi dùng ReLU, điều chỉnh learning ratechiến lược khởi tạo là rất quan trọng

Bùng nổ gradient trong RNN

  • Trong RNN đơn giản, cùng một ma trận trạng thái ẩn (Whh) được nhân lặp đi lặp lại ở mỗi bước thời gian
    • Khi lan truyền ngược, gradient sẽ hội tụ về 0 hoặc tăng vô hạn tùy theo độ lớn của eigenvalue của ma trận này
  • |b| < 1 thì xảy ra tiêu biến gradient, còn |b| > 1 thì xảy ra bùng nổ gradient
  • Để ngăn điều này, người ta thường áp dụng gradient clipping hoặc dùng kiến trúc LSTM

Ví dụ clipping sai trong mã DQN

  • Trong một bản triển khai DQN dựa trên TensorFlow, có đoạn mã dùng tf.clip_by_value để clip trực tiếp delta (sai số Q)
    • Cách này khiến khi delta vượt ra ngoài phạm vi, gradient trở thành 0 và việc huấn luyện dừng lại
  • Mục tiêu thực sự là gradient clipping, nên thay vào đó cần dùng Huber loss
    • Trong mã ví dụ, Huber loss được triển khai bằng cách kết hợp có điều kiện giữa tf.squaretf.abs
  • Vấn đề này đã được báo cáo qua GitHub issue và được sửa ngay lập tức

Kết luận

  • Lan truyền ngược không chỉ là một công cụ tự động hóa đơn thuần mà là một cơ chế gán tín dụng (credit assignment), có thể dẫn tới những hệ quả phức tạp
  • Nếu không hiểu cơ chế bên trong, bạn sẽ đối mặt với sự bất ổn của mô hình, thất bại trong huấn luyện và giới hạn khi debug
  • Lan truyền ngược không khó về mặt toán học, và có thể học một cách trực quan qua khóa học và bài tập CS231n
  • Hiểu lan truyền ngược sẽ cải thiện đáng kể khả năng thiết kế mạng nơ-ron và giải quyết vấn đề
  • Thay vì phụ thuộc hoàn toàn vào tính năng autodiff của framework, điều quan trọng là nắm được luồng thực tế của lan truyền ngược

1 bình luận

 
GN⁺ 2025-11-03
Ý kiến Hacker News
  • Có vẻ backpropagation đang bị mang tiếng xấu một cách không công bằng ở đây
    Thực ra, cuộc thảo luận này nói về việc gradient và các biến thể gradient descent là những lớp trừu tượng không hoàn hảo đến mức nào trong quá trình tối ưu hóa hơn là về bản thân backprop
    Backprop chỉ là một thuật toán để tính đạo hàm của hàm hợp, còn những vấn đề như gradient biến mất khi chồng nhiều sigmoid lên nhau không phải lỗi của backprop mà là đặc tính của chính hàm đó
    Lý do người ta bắt mọi người tự cài đặt backward pass là để họ trực tiếp tính đạo hàm và cảm nhận được các số hạng mũ tác động như thế nào

    • Tôi hiểu ý bạn, nhưng trong trường hợp này tôi nghĩ cái “đính chính nhỏ” đó không mấy hữu ích
      Điểm mấu chốt là trong một số tình huống, không thể trừu tượng hóa các chi tiết của backprop (bao gồm cả việc tính gradient)
      Đặc biệt là khi dùng gradient descent, còn với những thuật toán tối ưu toàn cục khác thì có thể vấn đề sẽ nhẹ hơn
      Vì trong thực tế hiện nay backprop là cách duy nhất để tính gradient trong deep learning, nên sự rò rỉ của lớp trừu tượng này là điều có thật
    • Đây không phải đính chính nhỏ nhặt, mà là phản biện hoàn toàn chính đáng đối với một khung khái niệm sai
      Tôi tôn trọng đóng góp của Karpathy, nhưng các bài viết và bài giảng của anh ấy thường làm mờ ranh giới khái niệm, dễ gây hiểu lầm
      Với trình độ của anh ấy, người ta có quyền kỳ vọng độ chính xác cao hơn
  • Đóng góp của Karpathy cho giáo dục deep learning thật sự rất lớn
    Từ những bài viết ngắn đến bài viết kinh điển về RNN, rồi các bài giảng trên YouTube và các dự án GitHub đều rất xuất sắc
    nanochat được công bố gần đây cũng là một ví dụ tuyệt vời; những ví dụ hoàn chỉnh, nhỏ gọn và rõ ràng như vậy giúp người học rất nhiều

    • Tôi đã giới thiệu bài viết của Karpathy cho các đồng nghiệp đang đào sâu vào LLM, nhưng khá bất ngờ là họ không hứng thú
      Sau này tôi nhận ra họ quan tâm đến việc tin tưởng và tận dụng LLM hơn là hiểu nó
      Trên thực tế, họ hứng thú với những bàn luận mang tính viễn tưởng kiểu “xã hội nơi máy móc thông minh làm mọi việc” hơn là nguyên lý vận hành của LLM
    • Cách Karpathy làm việc khá thú vị
      Thay vì chỉ đơn giản “hỏi ChatGPT”, anh ấy tự tìm kiếm, đọc code và phát hiện bug
      Cách tiếp cận mang tính khám phá như vậy mới là học thật sự
  • Trong chương trình thạc sĩ, tôi từng làm bài tập tự cài đặt backprop dựa trên một bài báo
    Đó là việc viết forward và backward pass chỉ bằng các phép toán toán học, và là trải nghiệm học tập tốt nhất của tôi năm đó
    Đây là kiểu bài tập mà tự mình thường sẽ không làm, nhưng khi bị buộc phải làm thì nó giúp ích cực kỳ nhiều

    • Sự khác biệt về mức độ hiểu giữa chỉ đọc bài báo và trực tiếp hiện thực bằng code là cực lớn
    • Tôi từng tự cài đặt nó bằng Java hồi cấp ba, và phần khó nhất là tự viết phép nhân ma trận
      Tôi còn làm cả UI để trực quan hóa việc trọng số và bias thay đổi như thế nào trong quá trình học
    • Không biết bài báo đó có được công khai không
  • Tôi từng thắc mắc về mối quan hệ giữa backprop và optimizer
    SGD chỉ đơn giản di chuyển theo hướng gradient, nhưng các optimizer cao cấp như Adam không dùng trực tiếp gradient mà áp dụng chuẩn hóa, momentum, clipping, v.v.
    Vậy thì việc tính gradient chính xác có thực sự cần thiết không, hay chỉ cần biết đại khái hướng đi là đủ?

    • Trên thực tế, gradient được xấp xỉ bằng minibatch nhỏ, nên mỗi bước đều có nhiễu, nhưng chính nhiễu đó lại giúp cải thiện hiệu năng
      Có các nghiên cứu liên quan như các bài báo về nhiễu trong SGD, nghiên cứu trực quan hóa
      Nhưng chỉ xác định hướng một cách đại khái là rất nguy hiểm — vì độ cong của hàm loss (Hessian) thay đổi rất mạnh
    • “Có cần gradient chính xác không, hay chỉ cần biết hướng?” là một câu hỏi rất cũ
      Thực tế, stochastic gradient descent ra đời từ chính ý tưởng này, và xa hơn nữa còn có những hướng tiếp cận như Direct Feedback Alignment
      Bài tổng hợp của Ben Recht về mối quan hệ giữa tối ưu hóa và reinforcement learning cũng rất đáng xem
    • Backprop thực hiện tính đạo hàm chính xác ở mức độ chính xác số học
      Điều quan trọng không phải giá trị của hàm loss mà là hình dạng của gradient và độ cong
      Optimizer như Adam dùng xấp xỉ bậc một để ước lượng độ nhạy theo tỷ lệ của từng tham số rồi điều chỉnh gradient
      Tối ưu hóa bậc cao hơn là bất khả thi với các hàm phi tuyến như ReLU
    • Việc điều chỉnh gradient không phải là “fudge”
      Đó là biện pháp cần thiết để giải quyết vấn đề vanishing gradient
      Trong không gian nhiều chiều, sai số nhỏ cũng có thể gây ảnh hưởng lớn, nên việc tính gradient chính xác là cực kỳ quan trọng
    • Bản thân giải tích không khó
      Vấn đề là phải tính “hướng đại khái” đó bằng cách nào
      Ngay cả các optimizer nâng cao như AdamW cũng vẫn lấy gradient làm cốt lõi
  • Vào khoảng năm 2016, có vẻ người ta dùng các mẹo như gradient clipping thường xuyên hơn nhiều
    Ví dụ, trong bài báo năm 2013 của Alex Graves Sequence Generation with RNNs, ông cũng nói đã dùng clipping để ngăn gradient bùng nổ trong LSTM
    Tôi cũng cảm nhận được tầm quan trọng của backprop đến mức từng học một khóa chuyên sâu chỉ về PyTorch autograd

    • Có lẽ ngày trước có nhiều mẹo như vậy vì người ta thử nghiệm đủ loại kiến trúc mạng khác nhau
      Giờ đây framework đã hỗ trợ clipping, và mức độ hiểu biết về các vấn đề huấn luyện cũng cao hơn
      Nhưng bản thân vấn đề không hề biến mất — ReLU hay GELU vẫn là hàm kích hoạt mặc định, và việc huấn luyện LLM vẫn còn khá giống “nghệ thuật đen”
      Smol Training Playbook của Hugging Face là bằng chứng cho điều đó
  • Về lâu dài, tôi nghĩ có thể sẽ có lợi nếu huấn luyện một mô hình bền vững trước sự đa dạng của hàm kích hoạt
    Ví dụ, nếu thay ngẫu nhiên giữa ReLU, Swish, GELU khi huấn luyện thì có thể thu được một dạng hiệu ứng regularization giống như dropout
    Làm như vậy thì khi suy luận, ta thậm chí có thể đổi sang hàm có chi phí tính toán rẻ nhất

  • Tiêu đề gốc “Yes you should understand backprop” rõ ràng và hay hơn nhiều

    • Chính vì backprop là một lớp trừu tượng bị rò rỉ, nên việc tự tay tính để xây dựng trực giác là rất quan trọng
      Nếu để code làm thay quá nhiều, rất dễ rơi vào ảo tưởng rằng nó hoạt động như phép màu
      Trải nghiệm tự tay tính convolution và backprop hồi cao học đã giúp tôi rất nhiều
  • Câu hỏi “framework đã tự tính backward pass rồi thì tại sao còn phải tự viết?”
    có logic đáng lo ngại kiểu như “đã có máy tính cầm tay thì tại sao còn phải học phép cộng?”

    • Cũng có phản biện
      Cũng như hiểu compiler, thuật toán sắp xếp hay cách transistor hoạt động đều hữu ích, việc học backprop cũng có giá trị
      Tuy nhiên thời gian học là hữu hạn, nên điểm mấu chốt là học thứ này có lợi hơn những chủ đề khác hay không
      Backprop đáng để học vì nếu không hiểu cách nó vận hành bên trong thì rất khó nhận ra các chế độ lỗi tiềm ẩn
      Tôi cũng đã tự cài đặt nó nhiều lần, và nó có độ phức tạp vừa đủ để đánh giá một ngôn ngữ mới
  • Khi mới học deep learning, backprop từng cho tôi cảm giác như phép màu
    Nhưng sau khi tự cài đặt, tôi nhận ra nó chỉ là một chuỗi phép tính đơn giản, và nhờ vậy tôi tự tin hơn nhiều khi debug hay tìm nguyên nhân loss bị đình trệ
    Nếu ai đang học deep learning thì tôi khuyên ít nhất một lần hãy tự hiện thực bằng tay

  • Cũng có quan điểm ngược lại
    Tôi không nghĩ sinh viên nhất thiết phải cài đặt backprop bằng NumPy
    Vấn đề rò rỉ của BackProp nên để các nhà nghiên cứu giải quyết bằng optimizer mới, còn developer chỉ cần tìm hyperparameter tốt là được

    • Nhưng mục tiêu của đại học là đào tạo sinh viên thành nhà nghiên cứu
    • Nói rằng “chỉ cần chọn optimizer tốt là được” là một hiểu lầm
      Một phần vấn đề phát sinh từ thiết kế mô hình hoặc vòng lặp huấn luyện
      Ví dụ, gradient clipping không phải mặc định trong hầu hết framework
      Bài viết này hướng đến độc giả là nhà nghiên cứu hoặc quan tâm theo góc nhìn học thuật
    • Vấn đề không nằm ở optimizer mà ở đặc tính đạo hàm của hàm kích hoạt
      Nếu không hiểu gradient của các hàm như Sigmoid hay ReLU hoạt động ra sao, bạn sẽ không thể xử lý vấn đề bùng nổ hoặc tiêu biến
    • Nếu là một môn CS ở Stanford thì việc tự hiện thực các nguyên lý nền tảng là điều hiển nhiên
      Muốn tạo ra kiến trúc mô hình mới thì phải hiểu backprop hoạt động thế nào, nếu không việc huấn luyện sẽ thất bại hoặc hiệu năng suy giảm
    • Vấn đề là không biết rằng mình không biết
      Chỉ khi xuyên qua lớp trừu tượng, bạn mới phát hiện ra những vùng mù thật sự (unknown unknowns)