.. _sec_mlp: Multilayer Perceptrons ====================== Trong :numref:`chap_linear`, chúng tôi giới thiệu hồi quy softmax (:numref:`sec_softmax`), thực hiện thuật toán từ đầu (:numref:`sec_softmax_scratch`) và sử dụng API cấp cao (:numref:`sec_softmax_concise`), và đào tạo phân loại để nhận ra 10 loại quần áo từ hình ảnh có độ phân giải thấp. Trên đường đi, chúng tôi đã học cách wrangle dữ liệu, ép buộc đầu ra của chúng tôi vào một phân phối xác suất hợp lệ, áp dụng một chức năng mất mát thích hợp và giảm thiểu nó đối với các tham số của mô hình của chúng tôi. Bây giờ chúng ta đã thành thạo các cơ chế này trong bối cảnh các mô hình tuyến tính đơn giản, chúng ta có thể khởi động khám phá các mạng thần kinh sâu, lớp mô hình tương đối phong phú mà cuốn sách này chủ yếu quan tâm. Các lớp ẩn ---------- Chúng tôi đã mô tả sự biến đổi affine trong :numref:`subsec_linear_model`, là một biến đổi tuyến tính được thêm vào bởi một sự thiên vị. Để bắt đầu, hãy nhớ lại kiến trúc mô hình tương ứng với ví dụ hồi quy softmax của chúng tôi, minh họa trong :numref:`fig_softmaxreg`. Mô hình này ánh xạ đầu vào của chúng tôi trực tiếp đến đầu ra của chúng tôi thông qua một biến đổi affine duy nhất, tiếp theo là một hoạt động softmax. Nếu nhãn của chúng tôi thực sự có liên quan đến dữ liệu đầu vào của chúng tôi bằng cách chuyển đổi affine, thì cách tiếp cận này sẽ là đủ. Nhưng tuyến tính trong biến đổi affine là một giả định \* mạnh mẽ\*. Mô hình tuyến tính có thể đi sai ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ví dụ, tuyến tính ngụ ý giả định *yếu hơn* về *monotonicity*: rằng bất kỳ sự gia tăng tính năng nào của chúng tôi phải luôn gây ra sự gia tăng sản lượng của mô hình của chúng tôi (nếu trọng lượng tương ứng là dương) hoặc luôn làm giảm sản lượng của mô hình của chúng tôi (nếu trọng lượng tương ứng là âm). Đôi khi điều đó có ý nghĩa. Ví dụ, nếu chúng tôi đang cố gắng dự đoán liệu một cá nhân có trả nợ hay không, chúng ta có thể tưởng tượng một cách hợp lý rằng giữ tất cả đều bằng nhau, một người nộp đơn có thu nhập cao hơn sẽ luôn có nhiều khả năng trả nợ hơn một người có thu nhập thấp hơn. Trong khi đơn điệu, mối quan hệ này có khả năng không liên quan đến xác suất trả nợ. Tăng thu nhập từ 0 lên 50 nghìn có khả năng tương ứng với mức tăng khả năng trả nợ lớn hơn mức tăng từ 1 triệu lên 1.05 triệu. Một cách để xử lý điều này có thể là xử lý trước dữ liệu của chúng tôi sao cho tuyến tính trở nên hợp lý hơn, ví dụ, bằng cách sử dụng logarit thu nhập làm tính năng của chúng tôi. Lưu ý rằng chúng ta có thể dễ dàng đưa ra các ví dụ vi phạm tính đơn điệu. Nói ví dụ rằng chúng ta muốn dự đoán xác suất tử vong dựa trên nhiệt độ cơ thể. Đối với những người có nhiệt độ cơ thể trên 37° C (98,6° F), nhiệt độ cao hơn cho thấy nguy cơ cao hơn. Tuy nhiên, đối với những người có nhiệt độ cơ thể dưới 37° C, nhiệt độ cao hơn cho thấy nguy cơ thấp hơn! Trong trường hợp này, chúng tôi cũng có thể giải quyết vấn đề với một số tiền xử lý thông minh. Cụ thể, chúng ta có thể sử dụng khoảng cách từ 37° C làm tính năng của chúng tôi. Nhưng những gì về việc phân loại hình ảnh của mèo và chó? Có nên tăng cường độ của pixel tại vị trí (13, 17) luôn tăng (hoặc luôn giảm) khả năng hình ảnh mô tả một chú chó? Sự phụ thuộc vào một mô hình tuyến tính tương ứng với giả định ngầm rằng yêu cầu duy nhất để phân biệt mèo so với chó là đánh giá độ sáng của từng pixel. Cách tiếp cận này cam chịu thất bại trong một thế giới nơi đảo ngược một hình ảnh bảo tồn danh mục. Tuy nhiên, mặc dù sự vô lý rõ ràng của tuyến tính ở đây, so với các ví dụ trước đây của chúng tôi, nó là ít rõ ràng rằng chúng tôi có thể giải quyết vấn đề với một sửa chữa tiền xử lý đơn giản. Đó là do ý nghĩa của bất kỳ pixel nào phụ thuộc theo những cách phức tạp vào bối cảnh của nó (các giá trị của các pixel xung quanh). Mặc dù có thể tồn tại một đại diện của dữ liệu của chúng tôi có thể tính đến các tương tác có liên quan giữa các tính năng của chúng tôi, trên đó một mô hình tuyến tính sẽ phù hợp, chúng tôi chỉ đơn giản là không biết cách tính toán nó bằng tay. Với các mạng nơ-ron sâu, chúng tôi đã sử dụng dữ liệu quan sát để cùng tìm hiểu cả một biểu diễn thông qua các lớp ẩn và một bộ dự đoán tuyến tính hoạt động dựa trên biểu diễn đó. Kết hợp các lớp ẩn ~~~~~~~~~~~~~~~~~~ Chúng ta có thể khắc phục những hạn chế này của các mô hình tuyến tính và xử lý một lớp hàm tổng quát hơn bằng cách kết hợp một hoặc nhiều lớp ẩn. Cách dễ nhất để làm điều này là xếp chồng nhiều lớp được kết nối hoàn toàn lên nhau. Mỗi lớp nạp vào lớp phía trên nó, cho đến khi chúng ta tạo ra các đầu ra. Chúng ta có thể nghĩ về :math:`L-1` lớp đầu tiên là đại diện của chúng ta và lớp cuối cùng là bộ dự đoán tuyến tính của chúng ta. Kiến trúc này thường được gọi là một *multilayer perceptron*, thường được viết tắt là *MLP*. Dưới đây, chúng tôi mô tả một MLP diagrammatically (:numref:`fig_mlp`). .. _fig_mlp: .. figure:: ../img/mlp.svg An MLP with a hidden layer of 5 hidden units. MLP này có 4 đầu vào, 3 đầu ra và lớp ẩn của nó chứa 5 đơn vị ẩn. Vì lớp đầu vào không liên quan đến bất kỳ tính toán nào, việc tạo ra kết quả đầu ra với mạng này đòi hỏi phải thực hiện các tính toán cho cả hai lớp ẩn và đầu ra; do đó, số lớp trong MLP này là 2. Lưu ý rằng các lớp này đều được kết nối hoàn toàn. Mỗi đầu vào ảnh hưởng đến mọi tế bào thần kinh trong lớp ẩn, và mỗi lần lượt ảnh hưởng đến mọi tế bào thần kinh trong lớp đầu ra. Tuy nhiên, theo đề xuất của :numref:`subsec_parameterization-cost-fc-layers`, chi phí tham số hóa của MLP với các lớp được kết nối hoàn toàn có thể cao, điều này có thể thúc đẩy sự cân bằng giữa tiết kiệm tham số và hiệu quả mô hình ngay cả khi không thay đổi kích thước đầu vào hoặc đầu ra :cite:`Zhang.Tay.Zhang.ea.2021`. Từ tuyến tính đến phi tuyến ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Như trước đây, bởi ma trận :math:`\mathbf{X} \in \mathbb{R}^{n \times d}`, chúng tôi biểu thị một minibatch gồm :math:`n` ví dụ trong đó mỗi ví dụ có :math:`d` đầu vào (tính năng). Đối với một MLP một lớp ẩn có lớp ẩn có :math:`h` đơn vị ẩn, biểu thị bằng :math:`\mathbf{H} \in \mathbb{R}^{n \times h}` các đầu ra của lớp ẩn, đó là *đại diện ẩn*. Trong toán học hoặc mã, :math:`\mathbf{H}` còn được gọi là một biến thể \* ẩn lớp\* hoặc một biến \* hidden\*. Vì các lớp ẩn và đầu ra đều được kết nối hoàn toàn, chúng ta có trọng lượng lớp ẩn :math:`\mathbf{W}^{(1)} \in \mathbb{R}^{d \times h}` và thiên vị :math:`\mathbf{b}^{(1)} \in \mathbb{R}^{1 \times h}` và trọng lượng lớp đầu ra :math:`\mathbf{W}^{(2)} \in \mathbb{R}^{h \times q}` và thiên vị :math:`\mathbf{b}^{(2)} \in \mathbb{R}^{1 \times q}`. Chính thức, chúng tôi tính toán các đầu ra :math:`\mathbf{O} \in \mathbb{R}^{n \times q}` của MLP một lớp ẩn như sau: .. math:: \begin{aligned} \mathbf{H} & = \mathbf{X} \mathbf{W}^{(1)} + \mathbf{b}^{(1)}, \\ \mathbf{O} & = \mathbf{H}\mathbf{W}^{(2)} + \mathbf{b}^{(2)}. \end{aligned} Lưu ý rằng sau khi thêm lớp ẩn, mô hình của chúng tôi bây giờ yêu cầu chúng tôi theo dõi và cập nhật các bộ tham số bổ sung. Vì vậy, những gì chúng ta đã đạt được trong trao đổi? Bạn có thể ngạc nhiên khi tìm hiểu điều đó - trong mô hình được xác định ở trên —\* chúng tôi không đạt được gì cho sự cố của chúng tôi\*! Lý do là đơn giản. Các đơn vị ẩn ở trên được đưa ra bởi một hàm affine của các đầu vào, và các đầu ra (pre-softmax) chỉ là một hàm affine của các đơn vị ẩn. Một hàm affine của một hàm affine tự nó là một hàm affine. Hơn nữa, mô hình tuyến tính của chúng tôi đã có khả năng đại diện cho bất kỳ chức năng affine nào. Chúng ta có thể xem sự tương đương chính thức bằng cách chứng minh rằng đối với bất kỳ giá trị nào của trọng lượng, chúng ta chỉ có thể thu gọn lớp ẩn, mang lại một mô hình một lớp tương đương với các tham số :math:`\mathbf{W} = \mathbf{W}^{(1)}\mathbf{W}^{(2)}` và :math:`\mathbf{b} = \mathbf{b}^{(1)} \mathbf{W}^{(2)} + \mathbf{b}^{(2)}`: .. math:: \mathbf{O} = (\mathbf{X} \mathbf{W}^{(1)} + \mathbf{b}^{(1)})\mathbf{W}^{(2)} + \mathbf{b}^{(2)} = \mathbf{X} \mathbf{W}^{(1)}\mathbf{W}^{(2)} + \mathbf{b}^{(1)} \mathbf{W}^{(2)} + \mathbf{b}^{(2)} = \mathbf{X} \mathbf{W} + \mathbf{b}. Để nhận ra tiềm năng của các kiến trúc đa lớp, chúng ta cần thêm một thành phần quan trọng: chức năng kích hoạt\* phi tuyến \* :math:`\sigma` được áp dụng cho mỗi đơn vị ẩn sau khi chuyển đổi affine. Các đầu ra của các chức năng kích hoạt (ví dụ, :math:`\sigma(\cdot)`) được gọi là *kích hoạt*. Nói chung, với các chức năng kích hoạt tại chỗ, không còn có thể thu gọn MLP của chúng ta thành một mô hình tuyến tính: .. math:: \begin{aligned} \mathbf{H} & = \sigma(\mathbf{X} \mathbf{W}^{(1)} + \mathbf{b}^{(1)}), \\ \mathbf{O} & = \mathbf{H}\mathbf{W}^{(2)} + \mathbf{b}^{(2)}.\\ \end{aligned} Vì mỗi hàng trong :math:`\mathbf{X}` tương ứng với một ví dụ trong minibatch, với một số lạm dụng ký hiệu, chúng tôi xác định tính phi tuyến :math:`\sigma` để áp dụng cho các đầu vào của nó theo kiểu hàng, tức là một ví dụ tại một thời điểm. Lưu ý rằng chúng ta đã sử dụng ký hiệu cho softmax theo cùng một cách để biểu thị một hoạt động theo hàng trong :numref:`subsec_softmax_vectorization`. Thông thường, như trong phần này, các chức năng kích hoạt mà chúng ta áp dụng cho các lớp ẩn không chỉ đơn thuần là hàng, mà là elementwise. Điều đó có nghĩa là sau khi tính toán phần tuyến tính của lớp, chúng ta có thể tính toán từng kích hoạt mà không cần nhìn vào các giá trị được thực hiện bởi các đơn vị ẩn khác. Điều này đúng đối với hầu hết các chức năng kích hoạt. Để xây dựng các MLP chung hơn, chúng ta có thể tiếp tục xếp chồng các lớp ẩn như vậy, ví dụ, :math:`\mathbf{H}^{(1)} = \sigma_1(\mathbf{X} \mathbf{W}^{(1)} + \mathbf{b}^{(1)})` và :math:`\mathbf{H}^{(2)} = \sigma_2(\mathbf{H}^{(1)} \mathbf{W}^{(2)} + \mathbf{b}^{(2)})`, một trên đỉnh khác, mang lại các mô hình biểu cảm hơn bao giờ hết. Phổ Approximators ~~~~~~~~~~~~~~~~~ MLP có thể nắm bắt các tương tác phức tạp giữa các đầu vào của chúng ta thông qua các tế bào thần kinh ẩn của chúng, phụ thuộc vào các giá trị của từng đầu vào. Chúng ta có thể dễ dàng thiết kế các nút ẩn để thực hiện tính toán tùy ý, ví dụ, các phép toán logic cơ bản trên một cặp đầu vào. Hơn nữa, đối với một số lựa chọn nhất định của chức năng kích hoạt, người ta biết rằng MLPlà gần đúng phổ quát. Ngay cả với một mạng lưới một lớp ẩn, cho đủ nút (có thể vô lý nhiều), và tập hợp đúng trọng lượng, chúng ta có thể mô hình hóa bất kỳ chức năng, mặc dù thực sự học chức năng đó là phần cứng. Bạn có thể nghĩ về mạng thần kinh của bạn như là một chút giống như ngôn ngữ lập trình C. Ngôn ngữ, giống như bất kỳ ngôn ngữ hiện đại nào khác, có khả năng thể hiện bất kỳ chương trình có thể tính toán nào. Nhưng thực sự đến với một chương trình đáp ứng thông số kỹ thuật của bạn là phần khó khăn. Hơn nữa, chỉ vì một mạng lưới một lớp ẩn *có thể* học bất kỳ chức năng nào không có nghĩa là bạn nên cố gắng giải quyết tất cả các vấn đề của mình với các mạng một lớp ẩn. Trên thực tế, chúng ta có thể xấp xỉ nhiều chức năng nhỏ gọn hơn nhiều bằng cách sử dụng các mạng sâu hơn (so với rộng hơn). Chúng tôi sẽ đề cập đến những lập luận nghiêm ngặt hơn trong các chương tiếp theo. .. _subsec_activation-functions: Chức năng kích hoạt ------------------- Các chức năng kích hoạt quyết định xem một tế bào thần kinh có nên được kích hoạt hay không bằng cách tính tổng trọng số và thêm thiên vị với nó. Chúng là các toán tử khác biệt để chuyển đổi tín hiệu đầu vào thành đầu ra, trong khi hầu hết chúng thêm tính phi tuyến tính. Bởi vì các chức năng kích hoạt là nền tảng cho việc học sâu, hãy để chúng tôi khảo sát ngắn gọn một số chức năng kích hoạt phổ biến. .. raw:: html