.. raw:: html .. raw:: html .. raw:: html .. _sec_batch_norm: Chuẩn hoá theo batch ==================== .. raw:: html Huấn luyện mạng nơ-ron sâu không hề đơn giản, để chúng hội tụ trong khoảng thời gian chấp nhận được là một câu hỏi khá hóc búa. Trong phần này, chúng ta giới thiệu chuẩn hóa theo batch (*Batch Normalization - BN*) :cite:`Ioffe.Szegedy.2015`, một kỹ thuật phổ biến và hiệu quả nhằm tăng tốc độ hội tụ của mạng học sâu một cách ổn định. Cùng với các khối phần dư (*residual block*) được đề cập ở :numref:`sec_resnet` — BN giúp dễ dàng hơn trong việc huấn luyện mạng học sâu với hơn 100 tầng. .. raw:: html Huấn luyện mạng học sâu ----------------------- .. raw:: html Để thấy mục đích của việc chuẩn hóa theo batch, hãy cùng xem xét lại một vài vấn đề phát sinh trên thực tế khi huấn luyện các mô hình học máy và đặc biệt là mạng nơ-ron. .. raw:: html 1. Những lựa chọn tiền xử lý dữ liệu khác nhau thường tạo nên sự khác biệt rất lớn trong kết quả cuối cùng. Hãy nhớ lại việc áp dụng perceptron đa tầng để dự đoán giá nhà (:numref:`sec_kaggle_house`). Việc đầu tiên khi làm việc với dữ liệu thực tế là chuẩn hóa các đặc trưng đầu vào để chúng có giá trị trung bình bằng *không* và phương sai bằng *một*. Thông thường, việc chuẩn hóa này hoạt động tốt với các bộ tối ưu vì giá trị các tham số tiên nghiệm có cùng một khoảng tỷ lệ. 2. Khi huấn luyện các mạng thường gặp như Perceptron đa tầng hay CNN, các giá trị kích hoạt ở các tầng trung gian có thể nhận các giá trị với mức độ biến thiên lớn- dọc theo các tầng từ đầu vào đến đầu ra, qua các nút ở cùng một tầng, và theo thời gian do việc cập nhật giá trị tham số. Những nhà phát minh kỹ thuật chuẩn hoá theo batch cho rằng sự thay đổi trong phân phối của những giá trị kích hoạt có thể cản trở sự hội tụ của mạng. Dễ thấy rằng nếu một tầng có các giá trị kích hoạt lớn gấp 100 lần so với các tầng khác, thì cần phải có các điều chỉnh bổ trợ trong tốc độ học. 3. Mạng nhiều tầng có độ phức tạp cao và dễ gặp vấn đề quá khớp. Điều này cũng đồng nghĩa rằng kỹ thuật điều chuẩn càng trở nên quan trọng. .. raw:: html .. raw:: html .. raw:: html Chuẩn hoá theo batch được áp dụng cho từng tầng riêng lẻ (hoặc có thể cho tất cả các tầng) và hoạt động như sau: Trong mỗi vòng lặp huấn luyện, tại mỗi tầng, đầu tiên tính giá trị kích hoạt như thường lệ. Sau đó chuẩn hóa những giá trị kích hoạt của mỗi nút bằng việc trừ đi giá trị trung bình và chia cho độ lệch chuẩn. Cả hai đại lượng này được ước tính dựa trên số liệu thống kê của minibatch hiện tại. Chính vì *chuẩn hóa* dựa trên các số liệu thống kê của *batch* nên kỹ thuật này có tên gọi *chuẩn hoá theo batch*. .. raw:: html Lưu ý rằng, khi áp dụng BN với những minibatch có kích thước 1, mô hình sẽ không học được gì. Vì sau khi trừ đi giá trị trung bình, mỗi nút ẩn sẽ nhận giá trị :math:`0`! Dễ dàng suy luận ra là BN chỉ hoạt động hiệu quả và ổn định với kích thước minibatch đủ lớn. Cần ghi nhớ rằng, khi áp dụng BN là lựa chọn kích thước minibatch quan trọng hơn so với trường hợp không áp dụng BN. .. raw:: html BN chuyển đổi những giá trị kích hoạt tại tầng :math:`x` nhất định theo công thức sau: .. math:: \mathrm{BN}(\mathbf{x}) = \mathbf{\gamma} \odot \frac{\mathbf{x} - \hat{\mathbf{\mu}}}{\hat\sigma} + \mathbf{\beta} .. raw:: html Ở đây, :math:`\hat{\mathbf{\mu}}` là giá trị trung bình và :math:`\hat{\mathbf{\sigma}}` là độ lệch chuẩn của các mẫu trong minibatch. Sau khi áp dụng BN, những giá trị kích hoạt của minibatch có giá trị trung bình bằng không và phương sai đơn vị. Vì việc lựa chọn phương sai đơn vị (so với một giá trị đặc biệt khác) là tuỳ ý, nên chúng ta thường thêm vào từng cặp tham số tương ứng là hệ số tỷ lệ :math:`\mathbf{\gamma}` và độ chệch :math:`\mathbf{\beta}`. Do đó, độ lớn giá trị kích hoạt ở những tầng trung gian không thể phân kỳ trong quá trình huấn luyện vì BN chủ động chuẩn hoá chúng theo giá trị trung bình và phương sai cho trước (thông qua :math:`\mathbf{\mu}` và :math:`\sigma`). Qua trực giác và thực nghiệm, dùng BN có thể cho phép chọn tốc độ học nhanh hơn. .. raw:: html .. raw:: html .. raw:: html Ký hiệu một minibatch là :math:`\mathcal{B}`, chúng ta tính :math:`\hat{\mathbf{\mu}}_\mathcal{B}` và :math:`\hat\sigma_\mathcal{B}` theo công thức sau: .. math:: \hat{\mathbf{\mu}}_\mathcal{B} \leftarrow \frac{1}{|\mathcal{B}|} \sum_{\mathbf{x} \in \mathcal{B}} \mathbf{x} \text{ và } \hat{\mathbf{\sigma}}_\mathcal{B}^2 \leftarrow \frac{1}{|\mathcal{B}|} \sum_{\mathbf{x} \in \mathcal{B}} (\mathbf{x} - \mathbf{\mu}_{\mathcal{B}})^2 + \epsilon .. raw:: html Lưu ý rằng chúng ta thêm hằng số rất nhỏ :math:`\epsilon > 0` vào biểu thức tính phương sai để đảm bảo tránh phép chia cho 0 khi chuẩn hoá, ngay cả khi giá trị ước lượng phương sai thực nghiệm bằng không. Các ước lượng :math:`\hat{\mathbf{\mu}}_\mathcal{B}` và :math:`\hat{\mathbf{\sigma}}_\mathcal{B}` giúp đương đầu với vấn đề khi cần mở rộng số tầng của mạng (mạng học sâu hơn) bằng việc sử dụng nhiễu khi tính giá trị trung bình và phương sai. Bạn có thể nghĩ rằng nhiễu sẽ là vấn đề đáng ngại. Nhưng thực ra, nhiễu lại đem đến lợi ích. .. raw:: html Và đây là chủ đề thường xuất hiện trong học sâu. Vì những lý do vẫn chưa được giải thích rõ bằng lý thuyết, nhiều nguồn nhiễu khác nhau trong việc tối ưu hoá thường dẫn đến huấn luyện nhanh hơn và giảm quá khớp. Trong khi những nhà lý thuyết học máy truyền thống có thể bị vướng mắc ở việc định rõ điểm này, những thay đổi do nhiễu dường như hoạt động giống một dạng điều chuẩn. Trong một số nghiên cứu sơ bộ, :cite:`Teye.Azizpour.Smith.2018` và :cite:`Luo.Wang.Shao.ea.2018` đã lần lượt chỉ ra các thuộc tính của BN liên quan tới tiên nghiệm Bayesian (*Bayesian prior*) và các lượng phạt (*penalty*). Cụ thể, nghiên cứu này làm sáng tỏ lý do BN hoạt động tốt nhất với các minibatch có kích cỡ vừa phải, trong khoảng 50 - 100. .. raw:: html Cố định một mô hình đã được huấn luyện, bạn có thể nghĩ rằng chúng ta nên sử dụng toàn bộ tập dữ liệu để ước tính giá trị trung bình và phương sai. Và đúng là như vậy. Bởi lẽ khi huấn luyện xong, tại sao ta lại muốn cùng một hình ảnh lại được phân loại khác nhau phụ thuộc vào batch chứa hình ảnh này? Trong quá trình huấn luyện, những tính toán chính xác như vậy không khả thi vì giá trị kích hoạt cho tất cả các điểm dữ liệu thay đổi mỗi khi cập nhật mô hình. Tuy nhiên, một khi mô hình đã được huấn luyện xong, chúng ta có thể tính được giá trị trung bình và phương sai của mỗi tầng dựa trên toàn bộ tập dữ liệu. Thực ra đây là tiêu chuẩn thực hành cho các mô hình sử dụng chuẩn hóa theo batch và do đó các tầng BN của MXNet hoạt động khác nhau giữa *chế độ huấn luyện* (chuẩn hoá bằng số liệu thống kê của minibatch) và *chế độ dự đoán* (chuẩn hoá bằng số liệu thống kê của toàn bộ tập dữ liệu) .. raw:: html Bây giờ chúng ta đã sẵn sàng để xem chuẩn hoá theo batch hoạt động thế nào trong thực tế. .. raw:: html .. raw:: html .. raw:: html .. raw:: html .. raw:: html Tầng chuẩn hoá theo batch ------------------------- .. raw:: html Thực hiện việc chuẩn hóa theo batch cho tầng kết nối đầy đủ và tầng tích chập hơi khác nhau một chút. Chúng ta sẽ thảo luận cả hai trường hợp trên. Nhớ rằng một khác biệt lớn của BN so với những tầng khác là vì BN cần số liệu thống kê trên toàn minibatch, chúng ta không thể bỏ qua kích thước batch như đã làm với các tầng khác. .. raw:: html Tầng kết nối đầy đủ ~~~~~~~~~~~~~~~~~~~ .. raw:: html Khi áp dụng BN cho tầng kết nối đầy đủ, ta thường chèn BN sau bước biến đổi affine và trước hàm kích hoạt phi tuyến. Kí hiệu đầu vào của tầng là :math:`\mathbf{x}`, hàm biến đổi tuyến tính là :math:`f_{\theta}(\cdot)` (với trọng số là :math:`\theta`), hàm kích hoạt là :math:`\phi(\cdot)`, và phép tính BN là :math:`\mathrm{BN}_{\mathbf{\beta}, \mathbf{\gamma}}` với tham số :math:`\mathbf{\beta}` và :math:`\mathbf{\gamma}`, chúng ta sẽ biểu diễn việc tính toán tầng kết nối đầy đủ :math:`\mathbf{h}` khi chèn lớp BN vào như sau: .. math:: \mathbf{h} = \phi(\mathrm{BN}_{\mathbf{\beta}, \mathbf{\gamma}}(f_{\mathbf{\theta}}(\mathbf{x}) ) ) .. raw:: html Nhắc lại rằng giá trị trung bình và phương sai sẽ được tính toán trên *chính* minibatch :math:`\mathcal{B}` mà sẽ được biến đổi. Cũng cần lưu ý rằng hệ số tỷ lệ :math:`\mathbf{\gamma}` và độ chệch :math:`\mathbf{\beta}` là những tham số cần được học cùng với bộ tham số quen thuộc :math:`\mathbf{\theta}`. .. raw:: html Tầng tích chập ~~~~~~~~~~~~~~ .. raw:: html Tương tự với tầng tích chập, chúng ta áp dụng BN sau phép tích chập và trước hàm kích hoạt phi tuyến. Khi áp dụng phép tích chập cho đầu ra nhiều kênh, chúng ta cần thực hiện chuẩn hóa theo batch cho *mỗi* đầu ra của những kênh này, và mỗi kênh sẽ có riêng cho nó các tham số tỉ lệ và độ chệch, cả hai đều là các số vô hướng. Giả sử các minibatch có kích thước :math:`m`, đầu ra cho mỗi kênh của phép tích chập có chiều cao :math:`p` và chiều rộng :math:`q`. Với tầng tích chập, ta sẽ thực hiện mỗi phép chuẩn hoá theo batch trên :math:`m \cdot p \cdot q` phần tử trên từng kênh đầu ra cùng lúc. Vì thế trên từng kênh, ta sử dụng giá trị trên tất cả các vị trí không gian để tính trung bình :math:`\hat{\mathbf{\mu}}` và phương sai :math:`\hat{\mathbf{\sigma}}` và sau đó dùng hai giá trị này để chuẩn hóa các giá trị tại mỗi vị trí không gian trên kênh đó. .. raw:: html .. raw:: html .. raw:: html Chuẩn hoá theo Batch trong Quá trình Dự đoán ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. raw:: html Như đã đề cập trước đó, BN thường hoạt động khác nhau trong chế độ huấn luyện và chế độ dự đoán. Thứ nhất, nhiễu trong :math:`\mu` và :math:`\sigma` phát sinh từ việc chúng được xấp xỉ trên các minibatch không còn là nhiễu được mong muốn một khi ta đã huấn luyện xong mô hình. Thứ hai, trong nhiều trường hợp sẽ là xa xỉ khi tính toán các con số thống kê sau mỗi lần chuẩn hoá theo batch, ví dụ, khi cần áp dụng mô hình để đưa ra một kết quả dự đoán mỗi lần. .. raw:: html Thông thường, sau khi huấn luyện, chúng ta sử dụng toàn bộ tập dữ liệu để tính toán các con số thống kê của các giá trị kích hoạt và sau đó cố định chúng tại thời điểm dự đoán. Do đó, BN hoạt động khác nhau trong quá trình huấn luyện và kiểm tra. Lưu ý rằng dropout cũng có tính chất này. .. raw:: html .. raw:: html .. raw:: html Lập trình từ đầu ---------------- .. raw:: html Dưới đây, chúng ta lập trình tầng chuẩn hoá theo batch chỉ dùng ``ndarray``. .. code:: python from d2l import mxnet as d2l from mxnet import autograd, np, npx, init from mxnet.gluon import nn npx.set_np() def batch_norm(X, gamma, beta, moving_mean, moving_var, eps, momentum): # Use autograd to determine whether the current mode is training mode or # prediction mode if not autograd.is_training(): # If it is the prediction mode, directly use the mean and variance # obtained from the incoming moving average X_hat = (X - moving_mean) / np.sqrt(moving_var + eps) else: assert len(X.shape) in (2, 4) if len(X.shape) == 2: # When using a fully connected layer, calculate the mean and # variance on the feature dimension mean = X.mean(axis=0) var = ((X - mean) ** 2).mean(axis=0) else: # When using a two-dimensional convolutional layer, calculate the # mean and variance on the channel dimension (axis=1). Here we # need to maintain the shape of X, so that the broadcast operation # can be carried out later mean = X.mean(axis=(0, 2, 3), keepdims=True) var = ((X - mean) ** 2).mean(axis=(0, 2, 3), keepdims=True) # In training mode, the current mean and variance are used for the # standardization X_hat = (X - mean) / np.sqrt(var + eps) # Update the mean and variance of the moving average moving_mean = momentum * moving_mean + (1.0 - momentum) * mean moving_var = momentum * moving_var + (1.0 - momentum) * var Y = gamma * X_hat + beta # Scale and shift return Y, moving_mean, moving_var .. raw:: html Giờ ta có thể tạo một tầng ``BatchNorm`` đúng cách. Tầng này sẽ duy trì những tham số thích hợp tương ứng với tỉ lệ ``gamma`` và độ chệch ``beta``, hai tham số này sẽ được cập nhật trong quá trình huấn luyện. Thêm vào đó, tầng BN sẽ duy trì giá trị trung bình động của trung bình và phương sai để sử dụng về sau khi ở chế độ dự đoán. Tham số ``num_features`` truyền vào ``BatchNorm`` là số đầu ra của tầng kết nối đầy đủ hoặc số kênh đầu ra của tầng tích chập. Tham số ``num_dims`` bằng 2 nếu là tầng kết nối đầy đủ và bằng 4 nếu là tầng tích chập. .. raw:: html .. raw:: html .. raw:: html Tạm để thuật toán sang một bên và tập trung vào khuôn mẫu thiết kế (*design pattern*) của việc lập trình. Thông thường, ta lập trình phần toán trong một hàm riêng biệt, ví dụ như ``batch_norm``. Sau đó, ta tích hợp chức năng này vào một tầng tùy chỉnh, với mã nguồn chủ yếu giải quyết các vấn đề phụ trợ như di chuyển dữ liệu đến thiết bị phù hợp, cấp phát và khởi tạo biến, theo dõi các giá trị trung bình động (của trung bình và phương sai trong trường hợp này), v.v. Khuôn mẫu này giúp tách biệt việc tính toán khỏi các đoạn mã rập khuôn. Cũng lưu ý rằng để thuận tiện khi lập trình BN từ đầu, ta không tự động suy ra kích thước đầu vào, do đó ta cần chỉ định số lượng đặc trưng xuyên suốt. Tầng ``BatchNorm`` của Gluon sẽ hỗ trợ việc tự động này bằng khởi tạo trễ. .. code:: python class BatchNorm(nn.Block): def __init__(self, num_features, num_dims, **kwargs): super(BatchNorm, self).__init__(**kwargs) if num_dims == 2: shape = (1, num_features) else: shape = (1, num_features, 1, 1) # The scale parameter and the shift parameter involved in gradient # finding and iteration are initialized to 0 and 1 respectively self.gamma = self.params.get('gamma', shape=shape, init=init.One()) self.beta = self.params.get('beta', shape=shape, init=init.Zero()) # All the variables not involved in gradient finding and iteration are # initialized to 0 on the CPU self.moving_mean = np.zeros(shape) self.moving_var = np.zeros(shape) def forward(self, X): # If X is not on the CPU, copy moving_mean and moving_var to the # device where X is located if self.moving_mean.ctx != X.ctx: self.moving_mean = self.moving_mean.copyto(X.ctx) self.moving_var = self.moving_var.copyto(X.ctx) # Save the updated moving_mean and moving_var Y, self.moving_mean, self.moving_var = batch_norm( X, self.gamma.data(), self.beta.data(), self.moving_mean, self.moving_var, eps=1e-12, momentum=0.9) return Y .. raw:: html Sử dụng LeNet với Chuẩn hóa theo Batch -------------------------------------- .. raw:: html Để biết cách áp dụng ``BatchNorm`` trên thực tế, bên dưới ta áp dụng cho mô hình LeNet truyền thống (:numref:`sec_lenet`). Nhắc lại rằng BN thường được sử dụng sau tầng tích chập và tầng kết nối đầy đủ và trước hàm kích hoạt tương ứng. .. code:: python net = nn.Sequential() net.add(nn.Conv2D(6, kernel_size=5), BatchNorm(6, num_dims=4), nn.Activation('sigmoid'), nn.MaxPool2D(pool_size=2, strides=2), nn.Conv2D(16, kernel_size=5), BatchNorm(16, num_dims=4), nn.Activation('sigmoid'), nn.MaxPool2D(pool_size=2, strides=2), nn.Dense(120), BatchNorm(120, num_dims=2), nn.Activation('sigmoid'), nn.Dense(84), BatchNorm(84, num_dims=2), nn.Activation('sigmoid'), nn.Dense(10)) .. raw:: html Như thường lệ, ta sẽ huấn luyện trên bộ dữ liệu Fashion-MNIST. Đoạn mã này gần tương tự với đoạn mã khi lần đầu huấn luyện LeNet (:numref:`sec_lenet`). Điểm khác biệt chính là tốc độ học lớn hơn đáng kể. .. code:: python lr, num_epochs, batch_size = 1.0, 10, 256 train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size) d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr) .. parsed-literal:: :class: output loss 0.244, train acc 0.909, test acc 0.871 6812.0 examples/sec on gpu(0) .. figure:: output_batch-norm_vn_e8f877_7_1.svg .. raw:: html Chúng ta hãy xem tham số tỷ lệ ``gamma`` và tham số dịch chuyển ``beta`` đã học được tại tầng chuẩn hóa theo batch đầu tiên. .. code:: python net[1].gamma.data().reshape(-1,), net[1].beta.data().reshape(-1,) .. parsed-literal:: :class: output (array([2.7302992, 1.5029924, 2.1892326, 1.6283315, 2.1436832, 1.9183377], ctx=gpu(0)), array([ 1.9165307 , 0.27995437, -2.2910244 , -1.2921289 , -0.10231688, -0.24934599], ctx=gpu(0))) .. raw:: html .. raw:: html .. raw:: html .. raw:: html .. raw:: html Lập trình súc tích ------------------ .. raw:: html So với lớp ``BatchNorm`` tự định nghĩa thì lớp\ ``BatchNorm`` định nghĩa trong ``nn`` của Gluon dễ sử dụng hơn. Trong Gluon, ta không cần chỉ rõ ``num_features`` và ``num_dims``. Thay vào đó, các giá trị này sẽ được tự động suy ra trong quá trình khởi tạo trễ. Ngoại trừ điểm đó, đoạn mã trông giống hệt đoạn mã phía trên. .. code:: python net = nn.Sequential() net.add(nn.Conv2D(6, kernel_size=5), nn.BatchNorm(), nn.Activation('sigmoid'), nn.MaxPool2D(pool_size=2, strides=2), nn.Conv2D(16, kernel_size=5), nn.BatchNorm(), nn.Activation('sigmoid'), nn.MaxPool2D(pool_size=2, strides=2), nn.Dense(120), nn.BatchNorm(), nn.Activation('sigmoid'), nn.Dense(84), nn.BatchNorm(), nn.Activation('sigmoid'), nn.Dense(10)) .. raw:: html Chúng ta sử dụng cùng các siêu tham số như trước để huấn luyện mô hình. Như thường lệ, biến thể dùng Gluon này chạy nhanh hơn nhiều vì được biên dịch thành C++/CUDA trong khi đoạn mã tùy chỉnh của chúng ta phải qua thông dịch bằng Python. .. code:: python d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr) .. parsed-literal:: :class: output loss 0.254, train acc 0.906, test acc 0.868 12456.2 examples/sec on gpu(0) .. figure:: output_batch-norm_vn_e8f877_13_1.svg .. raw:: html Tranh luận ---------- .. raw:: html Theo trực giác, chuẩn hóa theo batch được cho là làm cảnh quan tối ưu (*optimization landscape*) mượt mà hơn. Tuy nhiên, cần cẩn thận phân biệt giữa suy đoán theo trực giác và lời giải thích thực sự cho các hiện tượng quan sát thấy khi huấn luyện các mô hình học sâu. Hãy nhớ lại rằng ngay từ đầu ta thậm chí không rõ tại sao các mạng nơ-ron sâu đơn giản hơn (như Perceptron đa tầng và CNN truyền thống) lại có thể khái quát tốt như vậy. Ngay cả với dropout và điều chuẩn L2, chúng vẫn linh hoạt đến mức khả năng khái quát hóa trên dữ liệu chưa nhìn thấy của chúng không thể giải thích được bằng các điều kiện bảo đảm sự khái quát hóa trong lý thuyết học truyền thống. .. raw:: html Trong bài báo gốc khi đề xuất phương pháp chuẩn hóa theo batch, các tác giả ngoài việc giới thiệu một công cụ mạnh mẽ và hữu ích đã đưa ra lời giải thích lý do BN hoạt động tốt: bằng cách giảm *sự dịch chuyển hiệp biến nội bộ - internal covariate shift*. Có thể hiểu ý các tác giả về *sự dịch chuyển hiệp biến nội bộ* giống với cách giải thích ở trên-rằng phân phối của giá trị kích hoạt thay đổi trong quá trình huấn luyện. Tuy nhiên, có hai vấn đề với cách giải thích này: (1) Sự dịch chuyển phân phối này rất khác so với *sự dịch chuyển hiệp biến*, việc đặt tên như vậy có sự nhầm lẫn. (2) Cách giải thích này vẫn chưa đủ cụ thể và chặt chẽ, vẫn để ngỏ câu hỏi: *chính xác thì tại sao kỹ thuật này hoạt động?* Xuyên suốt cuốn sách này, chúng tôi hướng đến việc truyền đạt những kinh nghiệm thực tế để xây dựng các mạng nơ-ron sâu. Tuy nhiên, chúng tôi tin rằng cần phân biệt rõ những kinh nghiệm dựa trên trực giác này với những bằng chứng khoa học rõ ràng. Cuối cùng, khi đã thành thạo tài liệu này và bắt đầu viết các nghiên cứu của riêng mình, bạn cần phân biệt rõ ràng giữa khẳng định và linh cảm. .. raw:: html Nối tiếp thành công của BN, cách giải thích của kỹ thuật này thông qua khái niệm *sự dịch chuyển hiệp biến nội bộ* liên tục xuất hiện trong các tranh luận, các tài liệu kỹ thuật và trên các diễn đàn về cách trình bày nghiên cứu học máy. Trong một bài phát biểu đáng nhớ được đưa ra khi nhận giải thưởng **Test of Time Award** tại hội nghị NeurIPS 2017, Ali Rahimi đã sử dụng *sự dịch chuyển hiệp biến nội bộ* như một tiêu điểm trong một cuộc tranh luận so sánh thực hành học sâu hiện đại với thuật giả kim. Sau đó, cách giải thích này đã được xem xét lại một cách chi tiết trong một bài báo về các xu hướng đáng lo ngại trong học máy :cite:`Lipton.Steinhardt.2018`. Trong các tài liệu kỹ thuật, các tác giả khác (:cite:`Santurkar.Tsipras.Ilyas.ea.2018`) đã đề xuất các giải thích thay thế cho sự thành công của BN, dù phần nào đó trái ngược với cách giải thích trong bài báo gốc. .. raw:: html .. raw:: html .. raw:: html Chúng tôi lưu ý rằng *sự dịch chuyển hiệp biến nội bộ* không đáng bị chỉ trích, có hàng ngàn lập luận mơ hồ được đưa ra mỗi năm trong nhiều tài liệu kỹ thuật về học máy. Việc nó trở thành tâm điểm của những cuộc tranh luận rất có thể là do sự phổ biến của nó trong cộng đồng học máy. Chuẩn hóa theo batch là một phương pháp quan trọng, được áp dụng trong gần như tất cả các bộ phân loại hình ảnh đã được triển khai, mang lại hàng chục ngàn trích dẫn cho bài báo giới thiệu kĩ thuật này. .. raw:: html Tóm tắt ------- .. raw:: html - Trong quá trình huấn luyện mô hình, chuẩn hóa theo batch liên tục điều chỉnh đầu ra trung gian của mạng nơ-ron theo giá trị trung bình và độ lệch chuẩn của minibatch, giúp các giá trị này ổn định hơn. - Chuẩn hóa theo batch có chút khác biệt khi áp dụng cho tầng kết nối đầy đủ và tầng tích chập. - Giống như tầng dropout, tầng chuẩn hóa theo batch sẽ tính ra kết quả khác nhau trong chế độ huấn luyện và chế độ dự đoán. - Chuẩn hóa theo batch có nhiều tác dụng phụ có lợi, chủ yếu là về điều chuẩn. Tuy nhiên, cách giải thích ban đầu về việc giảm sự dịch chuyển hiệp biến dường như không hợp lý. .. raw:: html Bài tập ------- .. raw:: html 1. Trước khi chuẩn hóa theo batch, có thể loại bỏ phép biến đổi affine trong tầng kết nối đầy đủ hoặc tham số độ chệch trong phép tích chập không? - Tìm một phép biến đổi tương đương được áp dụng trước tầng kết nối đầy đủ. - Sự cải tiến này có hiệu quả không, tại sao? 2. So sánh tốc độ học của LeNet khi có sử dụng và không sử dụng chuẩn hóa theo batch. - Vẽ đồ thị biểu diễn sự giảm xuống của lỗi huấn luyện và lỗi kiểm tra. - Về miền hội tụ thì sao? Có thể chọn tốc độ học lớn tới đâu? 3. Chúng ta có cần chuẩn hóa theo batch trong tất cả các tầng không? Hãy thử nghiệm điều này. 4. Có thể thay thế Dropout bằng BN không? Sẽ có thay đổi như thế nào? 5. Giữ nguyên các hệ số ``beta`` và ``gamma`` (thêm tham số ``grad_req='null'`` khi xây dựng mạng để không tính gradient) rồi quan sát và phân tích kết quả. 6. Đọc tài liệu của Gluon về ``BatchNorm`` để xem các ứng dụng khác của chuẩn hóa theo batch. 7. Ý tưởng nghiên cứu: nghĩ về các phép biến đổi chuẩn hóa khác có thể áp dụng. Bạn có thể áp dụng biến đổi tích phân xác suất (*probability integral transform*) không? Còn ước lượng ma trận hiệp phương sai hạng tối đa thì sao? .. raw:: html .. raw:: html Thảo luận --------- - `Tiếng Anh `__ - `Tiếng Việt `__ Những người thực hiện --------------------- Bản dịch trong trang này được thực hiện bởi: - Đoàn Võ Duy Thanh - Đinh Đắc - Lê Khắc Hồng Phúc - Nguyễn Văn Cường - Trần Yến Thy - Phạm Minh Đức - Nguyễn Cảnh Thướng - Phạm Hồng Vinh