.. _sec_softmax_scratch:
Thực hiện hồi quy Softmax từ đầu
================================
Cũng giống như chúng tôi thực hiện hồi quy tuyến tính từ đầu, chúng tôi
tin rằng that hồi quy softmax là tương tự cơ bản và bạn nên biết các chi
tiết gory của và làm thế nào để thực hiện nó cho mình. Chúng tôi sẽ làm
việc với bộ dữ liệu Fashion-MNIST, vừa được giới thiệu trong
:numref:`sec_fashion_mnist`, thiết lập một bộ lặp dữ liệu với kích
thước lô 256.
.. raw:: html
.. raw:: html
.. code:: python
X = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
X.sum(0, keepdims=True), X.sum(1, keepdims=True)
.. parsed-literal::
:class: output
(array([[5., 7., 9.]]),
array([[ 6.],
[15.]]))
.. raw:: html
.. raw:: html
.. code:: python
X = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
X.sum(0, keepdim=True), X.sum(1, keepdim=True)
.. parsed-literal::
:class: output
(tensor([[5., 7., 9.]]),
tensor([[ 6.],
[15.]]))
.. raw:: html
.. raw:: html
.. code:: python
X = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
tf.reduce_sum(X, 0, keepdims=True), tf.reduce_sum(X, 1, keepdims=True)
.. parsed-literal::
:class: output
(,
)
.. raw:: html
.. raw:: html
Bây giờ chúng tôi đã sẵn sàng để thực hiện các hoạt động softmax. Nhớ
lại rằng softmax bao gồm ba bước: (i) chúng ta cấp mũ mỗi thuật ngữ (sử
dụng ``exp``); (ii) chúng ta tổng hợp trên mỗi hàng (chúng ta có một
hàng cho mỗi ví dụ trong lô) để lấy hằng số bình thường hóa cho mỗi ví
dụ; (iii) chúng ta chia mỗi hàng bằng hằng số bình thường hóa của nó,
đảm bảo rằng kết quả tổng thành 1. Trước khi nhìn vào mã, chúng ta hãy
nhớ lại cách này trông thể hiện như một phương trình:
.. math:: \mathrm{softmax}(\mathbf{X})_{ij} = \frac{\exp(\mathbf{X}_{ij})}{\sum_k \exp(\mathbf{X}_{ik})}.
Mẫu số, hoặc hằng số chuẩn hóa, đôi khi cũng được gọi là hàm phân vùng
\* (và logarit của nó được gọi là hàm logarit). Nguồn gốc của tên đó nằm
trong `vật lý thống
kê `__
trong đó một phương trình liên quan mô hình sự phân bố trên một nhóm các
hạt.
.. raw:: html
.. raw:: html
.. code:: python
def softmax(X):
X_exp = np.exp(X)
partition = X_exp.sum(1, keepdims=True)
return X_exp / partition # The broadcasting mechanism is applied here
.. raw:: html
.. raw:: html
.. code:: python
def softmax(X):
X_exp = torch.exp(X)
partition = X_exp.sum(1, keepdim=True)
return X_exp / partition # The broadcasting mechanism is applied here
.. raw:: html
.. raw:: html
.. code:: python
def softmax(X):
X_exp = tf.exp(X)
partition = tf.reduce_sum(X_exp, 1, keepdims=True)
return X_exp / partition # The broadcasting mechanism is applied here
.. raw:: html
.. raw:: html
Như bạn có thể thấy, đối với bất kỳ đầu vào ngẫu nhiên nào, chúng tôi
biến mỗi phần tử thành một số không âm. Hơn nữa, mỗi hàng tổng cộng lên
đến 1, như là cần thiết cho một xác suất.
.. raw:: html
.. raw:: html
.. code:: python
X = np.random.normal(0, 1, (2, 5))
X_prob = softmax(X)
X_prob, X_prob.sum(1)
.. parsed-literal::
:class: output
(array([[0.22376052, 0.06659239, 0.06583703, 0.29964197, 0.3441681 ],
[0.63209665, 0.03179282, 0.194987 , 0.09209415, 0.04902935]]),
array([1. , 0.99999994]))
.. raw:: html
.. raw:: html
.. code:: python
X = torch.normal(0, 1, (2, 5))
X_prob = softmax(X)
X_prob, X_prob.sum(1)
.. parsed-literal::
:class: output
(tensor([[0.2157, 0.0482, 0.0647, 0.4588, 0.2126],
[0.0683, 0.0946, 0.1220, 0.3124, 0.4028]]),
tensor([1.0000, 1.0000]))
.. raw:: html
.. raw:: html
.. code:: python
X = tf.random.normal((2, 5), 0, 1)
X_prob = softmax(X)
X_prob, tf.reduce_sum(X_prob, 1)
.. parsed-literal::
:class: output
(,
)
.. raw:: html
.. raw:: html
Lưu ý rằng mặc dù điều này có vẻ chính xác về mặt toán học, chúng tôi
hơi cẩu thả trong việc thực hiện bởi vì chúng tôi không thực hiện các
biện pháp phòng ngừa chống lại tràn số hoặc tràn do các yếu tố lớn hoặc
rất nhỏ của ma trận.
Xác định mô hình
----------------
Bây giờ chúng ta đã xác định hoạt động softmax, chúng ta có thể triển
khai mô hình hồi quy softmax. Đoạn mã dưới đây định nghĩa cách nhập liệu
được ánh xạ đến đầu ra thông qua mạng. Lưu ý rằng chúng ta làm phẳng
từng ảnh gốc trong lô thành một vectơ bằng hàm ``reshape`` trước khi
truyền dữ liệu qua mô hình của chúng ta.
.. raw:: html
.. raw:: html
.. code:: python
def net(X):
return softmax(np.dot(X.reshape((-1, W.shape[0])), W) + b)
.. raw:: html
.. raw:: html
.. code:: python
def net(X):
return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)
.. raw:: html
.. raw:: html
.. code:: python
def net(X):
return softmax(tf.matmul(tf.reshape(X, (-1, W.shape[0])), W) + b)
.. raw:: html
.. raw:: html
Xác định chức năng mất
----------------------
Tiếp theo, chúng ta cần thực hiện hàm mất chéo entropy, như được giới
thiệu trong :numref:`sec_softmax`. Đây có thể là chức năng mất mát phổ
biến nhất trong tất cả các học sâu bởi vì, tại thời điểm này, các vấn đề
phân loại vượt xa vấn đề hồi quy.
Nhớ lại rằng cross-entropy lấy khả năng log âm của xác suất dự đoán được
gán cho nhãn thật. Thay vì lặp qua các dự đoán bằng Python for-loop (có
xu hướng không hiệu quả), chúng ta có thể chọn tất cả các phần tử bằng
một toán tử duy nhất. Dưới đây, chúng ta tạo dữ liệu mẫu ``y_hat`` với 2
ví dụ về xác suất dự đoán trên 3 lớp và nhãn tương ứng của chúng ``y``.
Với ``y`` chúng ta biết rằng trong ví dụ đầu tiên, lớp đầu tiên là dự
đoán chính xác và trong ví dụ thứ hai, lớp thứ ba là sự thật. Sử dụng
``y`` làm chỉ số xác suất trong ``y_hat``, chúng ta chọn xác suất của
lớp đầu tiên trong ví dụ đầu tiên và xác suất của lớp thứ ba trong ví dụ
thứ hai.
.. raw:: html
.. raw:: html
.. code:: python
y = np.array([0, 2])
y_hat = np.array([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y_hat[[0, 1], y]
.. parsed-literal::
:class: output
array([0.1, 0.5])
.. raw:: html
.. raw:: html
.. code:: python
y = torch.tensor([0, 2])
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y_hat[[0, 1], y]
.. parsed-literal::
:class: output
tensor([0.1000, 0.5000])
.. raw:: html
.. raw:: html
.. code:: python
y_hat = tf.constant([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y = tf.constant([0, 2])
tf.boolean_mask(y_hat, tf.one_hot(y, depth=y_hat.shape[-1]))
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Bây giờ chúng ta có thể triển khai hàm mất chéo entropy một cách hiệu
quả chỉ với một dòng mã.
.. raw:: html
.. raw:: html
.. code:: python
def cross_entropy(y_hat, y):
return - np.log(y_hat[range(len(y_hat)), y])
cross_entropy(y_hat, y)
.. parsed-literal::
:class: output
array([2.3025851, 0.6931472])
.. raw:: html
.. raw:: html
.. code:: python
def cross_entropy(y_hat, y):
return - torch.log(y_hat[range(len(y_hat)), y])
cross_entropy(y_hat, y)
.. parsed-literal::
:class: output
tensor([2.3026, 0.6931])
.. raw:: html
.. raw:: html
.. code:: python
def cross_entropy(y_hat, y):
return -tf.math.log(tf.boolean_mask(
y_hat, tf.one_hot(y, depth=y_hat.shape[-1])))
cross_entropy(y_hat, y)
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Phân loại chính xác
-------------------
Với phân phối xác suất dự đoán ``y_hat``, chúng ta thường chọn lớp có
xác suất dự đoán cao nhất bất cứ khi nào chúng ta phải đưa ra một dự
đoán cứng. Thật vậy, nhiều ứng dụng yêu cầu chúng tôi đưa ra lựa chọn.
Gmail phải phân loại email thành “Chính”, “Xã hội”, “Cập nhật” hoặc
“Diễn đàn”. Nó có thể ước tính xác suất trong nội bộ, nhưng vào cuối
ngày, nó phải chọn một trong số các lớp học.
Khi dự đoán phù hợp với lớp nhãn ``y``, chúng là chính xác. Độ chính xác
phân loại là phần nhỏ của tất cả các dự đoán là chính xác. Mặc dù có thể
khó tối ưu hóa độ chính xác trực tiếp (nó không phân biệt được), nhưng
nó thường là biện pháp hiệu suất mà chúng tôi quan tâm nhất và gần như
chúng tôi sẽ luôn báo cáo khi đào tạo phân loại.
Để tính toán độ chính xác, chúng tôi làm như sau. Đầu tiên, nếu
``y_hat`` là một ma trận, chúng ta giả định rằng chiều thứ hai lưu trữ
điểm dự đoán cho mỗi lớp. Chúng tôi sử dụng ``argmax`` để có được lớp dự
đoán bằng chỉ số cho mục nhập lớn nhất trong mỗi hàng. Sau đó, chúng ta
so sánh lớp dự đoán với ``y`` elementwise. Vì toán tử bình đẳng ``==``
nhạy cảm với các kiểu dữ liệu, chúng tôi chuyển đổi kiểu dữ liệu của
``y_hat`` để khớp với ``y``. Kết quả là một tensor chứa các mục của 0
(false) và 1 (true). Lấy tổng sản lượng số dự đoán chính xác.
.. raw:: html
.. raw:: html
.. code:: python
def accuracy(y_hat, y): #@save
"""Compute the number of correct predictions."""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
y_hat = y_hat.argmax(axis=1)
cmp = y_hat.astype(y.dtype) == y
return float(cmp.astype(y.dtype).sum())
.. raw:: html
.. raw:: html
.. code:: python
def accuracy(y_hat, y): #@save
"""Compute the number of correct predictions."""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
y_hat = y_hat.argmax(axis=1)
cmp = y_hat.type(y.dtype) == y
return float(cmp.type(y.dtype).sum())
.. raw:: html
.. raw:: html
.. code:: python
def accuracy(y_hat, y): #@save
"""Compute the number of correct predictions."""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
y_hat = tf.argmax(y_hat, axis=1)
cmp = tf.cast(y_hat, y.dtype) == y
return float(tf.reduce_sum(tf.cast(cmp, y.dtype)))
.. raw:: html
.. raw:: html
Chúng tôi sẽ tiếp tục sử dụng các biến ``y_hat`` và ``y`` được xác định
trước đó như là phân phối xác suất dự đoán và nhãn, tương ứng. Chúng ta
có thể thấy lớp dự đoán của ví dụ đầu tiên là 2 (phần tử lớn nhất của
hàng là 0,6 với chỉ số 2), không phù hợp với nhãn thực tế, 0. Lớp dự
đoán của ví dụ thứ hai là 2 (phần tử lớn nhất của hàng là 0,5 với chỉ số
2), phù hợp với nhãn thực tế, 2. Do đó, tỷ lệ chính xác phân loại cho
hai ví dụ này là 0,5.
.. raw:: html
.. raw:: html
.. code:: python
accuracy(y_hat, y) / len(y)
.. parsed-literal::
:class: output
0.5
.. raw:: html
.. raw:: html
.. code:: python
accuracy(y_hat, y) / len(y)
.. parsed-literal::
:class: output
0.5
.. raw:: html
.. raw:: html
.. code:: python
accuracy(y_hat, y) / len(y)
.. parsed-literal::
:class: output
0.5
.. raw:: html
.. raw:: html
Tương tự, chúng ta có thể đánh giá độ chính xác cho bất kỳ model ``net``
nào trên một bộ dữ liệu được truy cập thông qua bộ lặp dữ liệu
``data_iter``.
.. raw:: html
.. raw:: html
.. code:: python
def evaluate_accuracy(net, data_iter): #@save
"""Compute the accuracy for a model on a dataset."""
metric = Accumulator(2) # No. of correct predictions, no. of predictions
for X, y in data_iter:
metric.add(accuracy(net(X), y), d2l.size(y))
return metric[0] / metric[1]
.. raw:: html
.. raw:: html
.. code:: python
def evaluate_accuracy(net, data_iter): #@save
"""Compute the accuracy for a model on a dataset."""
if isinstance(net, torch.nn.Module):
net.eval() # Set the model to evaluation mode
metric = Accumulator(2) # No. of correct predictions, no. of predictions
with torch.no_grad():
for X, y in data_iter:
metric.add(accuracy(net(X), y), y.numel())
return metric[0] / metric[1]
.. raw:: html
.. raw:: html
.. code:: python
def evaluate_accuracy(net, data_iter): #@save
"""Compute the accuracy for a model on a dataset."""
metric = Accumulator(2) # No. of correct predictions, no. of predictions
for X, y in data_iter:
metric.add(accuracy(net(X), y), d2l.size(y))
return metric[0] / metric[1]
.. raw:: html
.. raw:: html
Ở đây ``Accumulator`` là một lớp tiện ích để tích lũy tổng trên nhiều
biến. Trong hàm ``evaluate_accuracy`` trên, chúng ta tạo ra 2 biến trong
phiên bản ``Accumulator`` để lưu trữ cả số dự đoán đúng và số dự đoán,
tương ứng. Cả hai sẽ được tích lũy theo thời gian khi chúng ta lặp lại
tập dữ liệu.
.. code:: python
class Accumulator: #@save
"""For accumulating sums over `n` variables."""
def __init__(self, n):
self.data = [0.0] * n
def add(self, *args):
self.data = [a + float(b) for a, b in zip(self.data, args)]
def reset(self):
self.data = [0.0] * len(self.data)
def __getitem__(self, idx):
return self.data[idx]
Bởi vì chúng tôi đã khởi tạo mô hình ``net`` với trọng lượng ngẫu nhiên,
độ chính xác của mô hình này phải gần với đoán ngẫu nhiên, tức là 0,1
cho 10 lớp.
.. raw:: html
.. raw:: html
.. code:: python
evaluate_accuracy(net, test_iter)
.. parsed-literal::
:class: output
0.0811
.. raw:: html
.. raw:: html
.. code:: python
evaluate_accuracy(net, test_iter)
.. parsed-literal::
:class: output
0.1485
.. raw:: html
.. raw:: html
.. code:: python
evaluate_accuracy(net, test_iter)
.. parsed-literal::
:class: output
0.1334
.. raw:: html
.. raw:: html
Đào tạo
-------
Vòng đào tạo cho hồi quy softmax sẽ trông nổi bật quen thuộc nếu bạn đọc
thông qua việc thực hiện hồi quy tuyến tính của chúng tôi trong
:numref:`sec_linear_scratch`. Ở đây chúng tôi tái cấu trúc việc thực
hiện để làm cho nó có thể tái sử dụng. Đầu tiên, chúng ta định nghĩa một
hàm để đào tạo cho một kỷ nguyên. Lưu ý rằng ``updater`` là một hàm
chung để cập nhật các tham số mô hình, chấp nhận kích thước lô làm đối
số. Nó có thể là một trình bao bọc của hàm ``d2l.sgd`` hoặc chức năng
tối ưu hóa tích hợp của khung.
.. raw:: html
.. raw:: html
.. code:: python
def train_epoch_ch3(net, train_iter, loss, updater): #@save
"""Train a model within one epoch (defined in Chapter 3)."""
# Sum of training loss, sum of training accuracy, no. of examples
metric = Accumulator(3)
if isinstance(updater, gluon.Trainer):
updater = updater.step
for X, y in train_iter:
# Compute gradients and update parameters
with autograd.record():
y_hat = net(X)
l = loss(y_hat, y)
l.backward()
updater(X.shape[0])
metric.add(float(l.sum()), accuracy(y_hat, y), y.size)
# Return training loss and training accuracy
return metric[0] / metric[2], metric[1] / metric[2]
.. raw:: html
.. raw:: html
.. code:: python
def train_epoch_ch3(net, train_iter, loss, updater): #@save
"""The training loop defined in Chapter 3."""
# Set the model to training mode
if isinstance(net, torch.nn.Module):
net.train()
# Sum of training loss, sum of training accuracy, no. of examples
metric = Accumulator(3)
for X, y in train_iter:
# Compute gradients and update parameters
y_hat = net(X)
l = loss(y_hat, y)
if isinstance(updater, torch.optim.Optimizer):
# Using PyTorch in-built optimizer & loss criterion
updater.zero_grad()
l.mean().backward()
updater.step()
else:
# Using custom built optimizer & loss criterion
l.sum().backward()
updater(X.shape[0])
metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
# Return training loss and training accuracy
return metric[0] / metric[2], metric[1] / metric[2]
.. raw:: html
.. raw:: html
.. code:: python
def train_epoch_ch3(net, train_iter, loss, updater): #@save
"""The training loop defined in Chapter 3."""
# Sum of training loss, sum of training accuracy, no. of examples
metric = Accumulator(3)
for X, y in train_iter:
# Compute gradients and update parameters
with tf.GradientTape() as tape:
y_hat = net(X)
# Keras implementations for loss takes (labels, predictions)
# instead of (predictions, labels) that users might implement
# in this book, e.g. `cross_entropy` that we implemented above
if isinstance(loss, tf.keras.losses.Loss):
l = loss(y, y_hat)
else:
l = loss(y_hat, y)
if isinstance(updater, tf.keras.optimizers.Optimizer):
params = net.trainable_variables
grads = tape.gradient(l, params)
updater.apply_gradients(zip(grads, params))
else:
updater(X.shape[0], tape.gradient(l, updater.params))
# Keras loss by default returns the average loss in a batch
l_sum = l * float(tf.size(y)) if isinstance(
loss, tf.keras.losses.Loss) else tf.reduce_sum(l)
metric.add(l_sum, accuracy(y_hat, y), tf.size(y))
# Return training loss and training accuracy
return metric[0] / metric[2], metric[1] / metric[2]
.. raw:: html
.. raw:: html
Trước khi hiển thị việc thực hiện hàm đào tạo, chúng ta định nghĩa một
lớp tiện ích vẽ dữ liệu trong hoạt hình. Một lần nữa, nó nhằm mục đích
đơn giản hóa mã trong phần còn lại của cuốn sách.
.. code:: python
class Animator: #@save
"""For plotting data in animation."""
def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,
ylim=None, xscale='linear', yscale='linear',
fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,
figsize=(3.5, 2.5)):
# Incrementally plot multiple lines
if legend is None:
legend = []
d2l.use_svg_display()
self.fig, self.axes = d2l.plt.subplots(nrows, ncols, figsize=figsize)
if nrows * ncols == 1:
self.axes = [self.axes, ]
# Use a lambda function to capture arguments
self.config_axes = lambda: d2l.set_axes(
self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)
self.X, self.Y, self.fmts = None, None, fmts
def add(self, x, y):
# Add multiple data points into the figure
if not hasattr(y, "__len__"):
y = [y]
n = len(y)
if not hasattr(x, "__len__"):
x = [x] * n
if not self.X:
self.X = [[] for _ in range(n)]
if not self.Y:
self.Y = [[] for _ in range(n)]
for i, (a, b) in enumerate(zip(x, y)):
if a is not None and b is not None:
self.X[i].append(a)
self.Y[i].append(b)
self.axes[0].cla()
for x, y, fmt in zip(self.X, self.Y, self.fmts):
self.axes[0].plot(x, y, fmt)
self.config_axes()
display.display(self.fig)
display.clear_output(wait=True)
Chức năng đào tạo sau đây sau đó đào tạo một mô hình ``net`` trên một
tập dữ liệu đào tạo được truy cập qua ``train_iter`` cho nhiều kỷ
nguyên, được chỉ định bởi ``num_epochs``. Vào cuối mỗi kỷ nguyên, mô
hình được đánh giá trên một tập dữ liệu thử nghiệm truy cập qua
``test_iter``. Chúng tôi sẽ tận dụng lớp ``Animator`` để hình dung tiến
độ đào tạo.
.. code:: python
def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater): #@save
"""Train a model (defined in Chapter 3)."""
animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],
legend=['train loss', 'train acc', 'test acc'])
for epoch in range(num_epochs):
train_metrics = train_epoch_ch3(net, train_iter, loss, updater)
test_acc = evaluate_accuracy(net, test_iter)
animator.add(epoch + 1, train_metrics + (test_acc,))
train_loss, train_acc = train_metrics
assert train_loss < 0.5, train_loss
assert train_acc <= 1 and train_acc > 0.7, train_acc
assert test_acc <= 1 and test_acc > 0.7, test_acc
Là một triển khai từ đầu, chúng tôi sử dụng minibatch stochastic
gradient descent được định nghĩa trong :numref:`sec_linear_scratch` để
tối ưu hóa chức năng mất mát của mô hình với tốc độ học tập 0.1.
.. raw:: html
.. raw:: html
.. code:: python
lr = 0.1
def updater(batch_size):
return d2l.sgd([W, b], lr, batch_size)
.. raw:: html
.. raw:: html
.. code:: python
lr = 0.1
def updater(batch_size):
return d2l.sgd([W, b], lr, batch_size)
.. raw:: html
.. raw:: html
.. code:: python
class Updater(): #@save
"""For updating parameters using minibatch stochastic gradient descent."""
def __init__(self, params, lr):
self.params = params
self.lr = lr
def __call__(self, batch_size, grads):
d2l.sgd(self.params, grads, self.lr, batch_size)
updater = Updater([W, b], lr=0.1)
.. raw:: html
.. raw:: html
Bây giờ chúng ta đào tạo mô hình với 10 kỷ nguyên Lưu ý rằng cả số
epochs (``num_epochs``) và tốc độ học tập (``lr``) đều có thể điều chỉnh
các siêu tham số. Bằng cách thay đổi giá trị của chúng, chúng ta có thể
tăng độ chính xác phân loại của mô hình.
.. raw:: html
.. raw:: html
.. code:: python
num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)
.. figure:: output_softmax-regression-scratch_a48321_177_0.svg
.. raw:: html
.. raw:: html
.. code:: python
num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)
.. figure:: output_softmax-regression-scratch_a48321_180_0.svg
.. raw:: html
.. raw:: html
.. code:: python
num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)
.. figure:: output_softmax-regression-scratch_a48321_183_0.svg
.. raw:: html
.. raw:: html
Prediction
----------
Bây giờ việc đào tạo đã hoàn tất, mô hình của chúng tôi đã sẵn sàng để
phân loại một số hình ảnh Với một loạt các hình ảnh, chúng tôi sẽ so
sánh các nhãn thực tế của chúng (dòng đầu ra văn bản đầu tiên) và dự
đoán từ mô hình (dòng thứ hai của đầu ra văn bản).
.. raw:: html
.. raw:: html
.. code:: python
def predict_ch3(net, test_iter, n=6): #@save
"""Predict labels (defined in Chapter 3)."""
for X, y in test_iter:
break
trues = d2l.get_fashion_mnist_labels(y)
preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))
titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
d2l.show_images(
X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])
predict_ch3(net, test_iter)
.. figure:: output_softmax-regression-scratch_a48321_189_0.svg
.. raw:: html
.. raw:: html
.. code:: python
def predict_ch3(net, test_iter, n=6): #@save
"""Predict labels (defined in Chapter 3)."""
for X, y in test_iter:
break
trues = d2l.get_fashion_mnist_labels(y)
preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))
titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
d2l.show_images(
X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])
predict_ch3(net, test_iter)
.. figure:: output_softmax-regression-scratch_a48321_192_0.svg
.. raw:: html
.. raw:: html
.. code:: python
def predict_ch3(net, test_iter, n=6): #@save
"""Predict labels (defined in Chapter 3)."""
for X, y in test_iter:
break
trues = d2l.get_fashion_mnist_labels(y)
preds = d2l.get_fashion_mnist_labels(tf.argmax(net(X), axis=1))
titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
d2l.show_images(
tf.reshape(X[0:n], (n, 28, 28)), 1, n, titles=titles[0:n])
predict_ch3(net, test_iter)
.. figure:: output_softmax-regression-scratch_a48321_195_0.svg
.. raw:: html
.. raw:: html
Tóm tắt
-------
- Với hồi quy softmax, chúng ta có thể đào tạo các mô hình để phân loại
đa lớp.
- Vòng đào tạo của hồi quy softmax rất giống với trong hồi quy tuyến
tính: lấy và đọc dữ liệu, xác định mô hình và chức năng mất mát, sau
đó đào tạo các mô hình sử dụng các thuật toán tối ưu hóa. Như bạn sẽ
sớm tìm ra, hầu hết các mô hình học sâu phổ biến đều có các quy trình
đào tạo tương tự.
Bài tập
-------
1. Trong phần này, chúng tôi trực tiếp triển khai hàm softmax dựa trên
định nghĩa toán học của phép toán softmax. Những vấn đề này có thể
gây ra? Gợi ý: cố gắng tính toán kích thước của :math:`\exp(50)`.
2. Hàm ``cross_entropy`` trong phần này được thực hiện theo định nghĩa
của hàm mất chéo entropy. Điều gì có thể là vấn đề với việc thực hiện
này? Gợi ý: xem xét tên miền của logarit.
3. Những giải pháp bạn có thể nghĩ đến để khắc phục hai vấn đề ở trên?
4. Có phải luôn luôn là một ý tưởng tốt để trả lại nhãn có khả năng
nhất? Ví dụ, bạn sẽ làm điều này để chẩn đoán y tế?
5. Giả sử rằng chúng ta muốn sử dụng hồi quy softmax để dự đoán từ tiếp
theo dựa trên một số tính năng. Một số vấn đề có thể phát sinh từ một
từ vựng lớn là gì?
.. raw:: html
.. raw:: html
`Discussions `__
.. raw:: html
.. raw:: html
`Discussions `__
.. raw:: html
.. raw:: html
`Discussions `__
.. raw:: html
.. raw:: html