.. 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