🏷️sec_calculus
Tìm diện tích của một đa giác vẫn là một bí ẩn cho tới ít nhất fig_circle_area
, một đa giác nội tiếp với càng nhiều cạnh bằng nhau thì càng xấp xỉ đúng hình tròn.
Quy trình này còn được biết đến như phương pháp vét kiệt.
Phương pháp vét kiệt chính là khởi nguồn của giải tích tích phân (sẽ được miêu tả trong :numref:sec_integral_calculus
).
Hơn subsec_norms_and_objectives
, các bài toán như vậy vô cùng phổ biến trong học sâu.
Trong học sâu, chúng ta huấn luyện các mô hình, cập nhật chúng liên tục để chúng ngày càng tốt hơn khi học với nhiều dữ liệu hơn. Thông thường, trở nên tốt hơn tương đương với cực tiểu hoá một hàm mất mát, một điểm số sẽ trả lời câu hỏi "mô hình của ta đang tệ tới mức nào?" Câu hỏi này lắt léo hơn ta tưởng nhiều. Mục đích cuối cùng mà ta muốn là mô hình sẽ hoạt động tốt trên dữ liệu mà nó chưa từng nhìn thấy. Nhưng chúng ta chỉ có thể khớp mô hình trên dữ liệu mà ta đang có thể thấy. Do đó ta có thể chia việc huấn luyện mô hình thành hai vấn đề chính: i) tối ưu hoá: quy trình huấn luyện mô hình trên dữ liệu đã thấy. ii) tổng quát hoá: dựa trên các nguyên tắc toán học và sự uyên thâm của người huấn luyện để tạo ra các mô hình mà tính hiệu quả của nó vượt ra khỏi tập dữ liệu huấn luyện.
Để giúp bạn hiểu các bài toán tối ưu hóa và các phương pháp tối ưu hóa trong các chương sau, ở đây chúng tôi sẽ cung cấp một chương ngắn vỡ lòng về các kĩ thuật giải tích vi phân thông dụng trong học sâu.
Chúng ta bắt đầu bằng việc đề cập tới khái niệm đạo hàm, một bước quan trọng của hầu hết các thuật toán tối ưu trong học sâu. Trong học sâu, ta thường chọn những hàm mất mát khả vi theo các tham số của mô hình. Nói đơn giản, với mỗi tham số, ta có thể xác định hàm mất mát tăng hoặc giảm nhanh như thế nào khi tham số đó tăng hoặc giảm chỉ một lượng cực nhỏ.
Giả sử ta có một hàm
eq_derivative
nếu giới hạn này tồn tại.
Nếu eq_derivative
như là tốc độ thay đổi tức thời của hàm
Để minh họa cho khái niệm đạo hàm, hãy thử với một ví dụ.
Định nghĩa
%matplotlib inline
from d2l import mxnet as d2l
from IPython import display
from mxnet import np, npx
npx.set_np()
def f(x):
return 3 * x ** 2 - 4 * x
Cho eq_derivative
tiến về
def numerical_lim(f, x, h):
return (f(x + h) - f(x)) / h
h = 0.1
for i in range(5):
print('h=%.5f, numerical limit=%.5f' % (h, numerical_lim(f, 1, h)))
h *= 0.1
Hãy làm quen với một vài ký hiệu cùng được dùng để biểu diễn đạo hàm.
Cho
với ký hiệu
-
$DC = 0$ ($C$ là một hằng số), -
$Dx^n = nx^{n-1}$ (quy tắc số mũ,$n$ là số thực bất kỳ), -
$De^x = e^x$ , $D\ln(x) = 1/x.$
Để lấy đạo hàm của một hàm được tạo từ vài hàm đơn giản hơn, ví dụ như từ những hàm thông dụng ở trên, có thể dùng các quy tắc hữu dụng dưới đây.
Giả sử hàm
quy tắc tổng
quy tắc nhân
và quy tắc đạo hàm phân thức
Bây giờ ta có thể áp dụng các quy tắc ở trên để tìm đạo hàm
Để minh họa cách hiểu này của đạo hàm, ta sẽ dùng matplotlib
, một thư viện vẽ biểu đồ thông dụng trong Python.
Ta cần định nghĩa một số hàm để cấu hình thuộc tính của các biểu đồ được tạo ra bởi matplotlib
.
Trong đoạn mã sau, hàm use_svg_display
chỉ định matplotlib
tạo các biểu đồ ở dạng svg để có được chất lượng ảnh sắc nét hơn.
# Saved in the d2l package for later use
def use_svg_display():
"""Use the svg format to display a plot in Jupyter."""
display.set_matplotlib_formats('svg')
Ta định nghĩa hàm set_figsize
để chỉ định kích thước của biểu đồ.
Lưu ý rằng ở đây ta đang dùng trực tiếp d2l.plt
do câu lệnh from matplotlib import pyplot as plt
đã được đánh dấu để lưu vào gói d2l
trong phần Lời nói đầu.
# Saved in the d2l package for later use
def set_figsize(figsize=(3.5, 2.5)):
"""Set the figure size for matplotlib."""
use_svg_display()
d2l.plt.rcParams['figure.figsize'] = figsize
Hàm set_axes
sau cấu hình thuộc tính của các trục biểu đồ tạo bởi matplotlib
.
# Saved in the d2l package for later use
def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):
"""Set the axes for matplotlib."""
axes.set_xlabel(xlabel)
axes.set_ylabel(ylabel)
axes.set_xscale(xscale)
axes.set_yscale(yscale)
axes.set_xlim(xlim)
axes.set_ylim(ylim)
if legend:
axes.legend(legend)
axes.grid()
Với ba hàm cấu hình biểu đồ trên, ta định nghĩa hàm plot
để vẽ nhiều đồ thị một cách nhanh chóng vì ta sẽ cần minh họa khá nhiều đồ thị xuyên suốt cuốn sách.
# Saved in the d2l package for later use
def plot(X, Y=None, xlabel=None, ylabel=None, legend=[], xlim=None,
ylim=None, xscale='linear', yscale='linear',
fmts=['-', 'm--', 'g-.', 'r:'], figsize=(3.5, 2.5), axes=None):
"""Plot data points."""
d2l.set_figsize(figsize)
axes = axes if axes else d2l.plt.gca()
# Return True if X (ndarray or list) has 1 axis
def has_one_axis(X):
return (hasattr(X, "ndim") and X.ndim == 1 or isinstance(X, list)
and not hasattr(X[0], "__len__"))
if has_one_axis(X):
X = [X]
if Y is None:
X, Y = [[]] * len(X), X
elif has_one_axis(Y):
Y = [Y]
if len(X) != len(Y):
X = X * len(Y)
axes.cla()
for x, y, fmt in zip(X, Y, fmts):
if len(x):
axes.plot(x, y, fmt)
else:
axes.plot(y, fmt)
set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend)
Giờ ta có thể vẽ đồ thị của hàm số
x = np.arange(0, 3, 0.1)
plot(x, [f(x), 2 * x - 3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])
Cho tới giờ, ta đã làm việc với đạo hàm của các hàm một biến. Trong học sâu, các hàm lại thường phụ thuộc vào nhiều biến. Do đó, ta cần mở rộng ý tưởng của đạo hàm cho các hàm nhiều biến đó.
Cho
Để tính
Chúng ta có thể ghép các đạo hàm riêng của mọi biến trong một hàm nhiều biến để thu được vector gradient của hàm số đó.
Giả sử rằng đầu vào của hàm
Biểu thức
Cho
- Với mọi
$\mathbf{A} \in \mathbb{R}^{m \times n}$ ,$\nabla_{\mathbf{x}} \mathbf{A} \mathbf{x} = \mathbf{A}^\top$ , - Với mọi
$\mathbf{A} \in \mathbb{R}^{n \times m}$ ,$\nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} = \mathbf{A}$ , - Với mọi
$\mathbf{A} \in \mathbb{R}^{n \times n}$ ,$\nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} \mathbf{x} = (\mathbf{A} + \mathbf{A}^\top)\mathbf{x}$ , -
$\nabla_{\mathbf{x}} |\mathbf{x} |^2 = \nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{x} = 2\mathbf{x}$ .
Tương tự, với bất kỳ ma trận
Tuy nhiên, những gradient như thế có thể khó để tính toán. Đó là bởi vì các hàm nhiều biến trong học sâu đa phần là những hàm hợp, nên ta không thể áp dụng các quy tắc đề cập ở trên để lấy vi phân cho những hàm này. May mắn thay, quy tắc dây chuyền cho phép chúng ta lấy vi phân của các hàm hợp.
Trước tiên, chúng ta hãy xem xét các hàm một biến.
Giả sử hai hàm
Giờ ta sẽ xét trường hợp tổng quát hơn đối với các hàm nhiều biến.
Giả sử một hàm khả vi
cho mỗi
- Vi phân và tích phân là hai nhánh con của giải tích, trong đó vi phân được ứng dụng rộng rãi trong các bài toán tối ưu hóa của học sâu.
- Đạo hàm có thể được hiểu như là tốc độ thay đổi tức thì của một hàm số đối với các biến số. Nó cũng là độ dốc của đường tiếp tuyến với đường cong của hàm.
- Gradient là một vector có các phần tử là đạo hàm riêng của một hàm nhiều biến theo tất cả các biến số của nó.
- Quy tắc dây chuyền cho phép chúng ta lấy vi phân của các hàm hợp.
dịch đoạn phía trên
- Vẽ đồ thị của hàm số
$y = f(x) = x^3 - \frac{1}{x}$ và đường tiếp tuyến của nó tại$x = 1$ . - Tìm gradient của hàm số
$f(\mathbf{x}) = 3x_1^2 + 5e^{x_2}$ . - Gradient của hàm
$f(\mathbf{x}) = |\mathbf{x}|_2$ là gì? - Có thể dùng quy tắc dây chuyền cho trường hợp sau đây không:
$u = f(x, y, z)$ , với$x = x(a, b)$ ,$y = y(a, b)$ và$z = z(a, b)$ ?
Bản dịch trong trang này được thực hiện bởi:
- Đoàn Võ Duy Thanh
- Lê Khắc Hồng Phúc
- Phạm Hồng Vinh
- Vũ Hữu Tiệp
- Nguyễn Cảnh Thướng
- Phạm Minh Đức
- Tạ H. Duy Nguyên