.. raw:: html
.. raw:: html
.. raw:: html
Đọc/Ghi tệp
===========
.. raw:: html
Đến nay, ta đã thảo luận về cách xử lý dữ liệu và cách xây dựng, huấn
luyện, kiểm tra những mô hình học sâu. Tuy nhiên, có thể đến một lúc nào
đó ta sẽ cảm thấy hài lòng với những gì thu được và muốn lưu lại kết quả
để sau này sử dụng trong những bối cảnh khác nhau (thậm chí có thể đưa
ra dự đoán khi triển khai). Ngoài ra, khi vận hành một quá trình huấn
luyện dài hơi, cách tốt nhất là lưu kết quả trung gian một cách định kỳ
(điểm kiểm tra) nhằm đảm bảo rằng ta sẽ không mất kết quả tính toán sau
nhiều ngày nếu chẳng may ta vấp phải dây nguồn của máy chủ. Vì vậy, đã
đến lúc chúng ta học cách đọc và lưu trữ đồng thời các vector trọng số
riêng lẻ cùng toàn bộ các mô hình. Mục này sẽ giải quyết cả hai vấn đề
trên.
.. raw:: html
Đọc và Lưu các ``ndarray``
--------------------------
.. raw:: html
Đối với ``ndarray`` riêng lẻ, ta có thể sử dụng trực tiếp các hàm
``load`` và ``save`` để đọc và ghi tương ứng. Cả hai hàm đều yêu cầu ta
cung cấp tên, và hàm ``save`` yêu cầu đầu vào với biến đã được lưu.
.. code:: python
from mxnet import np, npx
from mxnet.gluon import nn
npx.set_np()
x = np.arange(4)
npx.save('x-file', x)
.. raw:: html
Bây giờ, chúng ta có thể đọc lại dữ liệu từ các tệp được lưu vào trong
bộ nhớ.
.. code:: python
x2 = npx.load('x-file')
x2
.. parsed-literal::
:class: output
[array([0., 1., 2., 3.])]
.. raw:: html
MXNet đồng thời cho phép ta lưu một danh sách các ``ndarray`` và đọc lại
chúng vào trong bộ nhớ.
.. code:: python
y = np.zeros(4)
npx.save('x-files', [x, y])
x2, y2 = npx.load('x-files')
(x2, y2)
.. parsed-literal::
:class: output
(array([0., 1., 2., 3.]), array([0., 0., 0., 0.]))
.. raw:: html
Ta còn có thể ghi và đọc một từ điển ánh xạ từ một chuỗi sang một
``ndarray``. Điều này khá là thuận tiện khi chúng ta muốn đọc hoặc ghi
tất cả các trọng số của một mô hình.
.. code:: python
mydict = {'x': x, 'y': y}
npx.save('mydict', mydict)
mydict2 = npx.load('mydict')
mydict2
.. parsed-literal::
:class: output
{'x': array([0., 1., 2., 3.]), 'y': array([0., 0., 0., 0.])}
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
Tham số mô hình Gluon
---------------------
.. raw:: html
Khả năng lưu từng vector trọng số đơn lẻ (hoặc các ``ndarray`` tensor
khác) là hữu ích nhưng sẽ mất nhiều thời gian nếu chúng ta muốn lưu (và
sau đó nạp lại) toàn bộ mô hình. Dù sao, chúng ta có thể có hàng trăm
nhóm tham số rải rác xuyên suốt mô hình. Vì lý do đó mà Gluon cung cấp
sẵn tính năng lưu và nạp toàn bộ các mạng. Một chi tiết quan trọng cần
lưu ý là chức năng này chỉ lưu các *tham số* của mô hình, không phải là
toàn bộ mô hình. Điều đó có nghĩa là nếu ta có một MLP ba tầng, ta cần
chỉ rõ *kiến trúc* này một cách riêng lẻ. Lý do là vì bản thân các mô
hình có thể chứa mã nguồn bất kỳ, chúng không được thêm vào tập tin một
cách dễ dàng như các tham số (có một cách thực hiện điều này cho các mô
hình đã được biên dịch, chi tiết kĩ thuật đọc thêm trong `tài liệu
MXNet `__). Vì vậy, để khôi phục lại một mô hình
thì chúng ta cần xây dựng kiến trúc của nó từ mã nguồn rồi nạp các tham
số từ ổ cứng vào kiến trúc này. Việc khởi tạo trễ
(:numref:`sec_deferred_init`) lúc này rất có lợi vì ta chỉ cần định
nghĩa một mô hình mà không cần gán giá trị cụ thể cho tham số. Như
thường lệ, hãy bắt đầu với một MLP quen thuộc.
.. code:: python
class MLP(nn.Block):
def __init__(self, **kwargs):
super(MLP, self).__init__(**kwargs)
self.hidden = nn.Dense(256, activation='relu')
self.output = nn.Dense(10)
def forward(self, x):
return self.output(self.hidden(x))
net = MLP()
net.initialize()
x = np.random.uniform(size=(2, 20))
y = net(x)
.. raw:: html
Tiếp theo, chúng ta lưu các tham số của mô hình vào tệp ``mlp.params``.
Những khối Gloun hỗ trợ phương thức từ hàm ``save_parameter`` nhằm ghi
tất cả các tham số vào ổ cứng được cung cấp với một chuỗi những tên tệp.
.. code:: python
net.save_parameters('mlp.params')
.. raw:: html
Để khôi phục mô hình, chúng ta tạo một đối tượng khác dựa trên mô hình
MLP gốc. Thay vì khởi tạo ngẫu nhiên những tham số mô hình, ta đọc các
tham số được lưu trực tiếp trong tập tin. Và thật thuận tiện, ta đã có
thể nạp các tham số vào khối thông qua phương thức từ hàm
``load_parameters``.
.. code:: python
clone = MLP()
clone.load_parameters('mlp.params')
.. raw:: html
Vì cả hai đối tượng của mô hình có cùng bộ tham số, kết quả tính toán
với cùng đầu vào ``x`` sẽ như nhau. Hãy kiểm chứng điều này.
.. code:: python
yclone = clone(x)
yclone == y
.. parsed-literal::
:class: output
array([[ True, True, True, True, True, True, True, True, True,
True],
[ True, True, True, True, True, True, True, True, True,
True]])
.. raw:: html
.. raw:: html
.. raw:: html
Tóm tắt
-------
.. raw:: html
- Hàm ``save`` và ``load`` có thể được sử dụng để thực hiện việc xuất
nhập tập tin cho các đối tượng ``ndarray``.
- Hàm ``load_parameters`` và ``save_parameters`` cho phép ta lưu toàn
bộ tập tham số của một mạng trong Gluon.
- Việc lưu kiến trúc này phải được hoàn thiện trong chương trình thay
vì trong các tham số.
.. raw:: html
Bài tập
-------
.. raw:: html
1. Nếu không cần phải triển khai các mô hình huấn luyện sang một thiết
bị khác, theo bạn thì lợi ích thực tế của việc lưu các tham số mô
hình là gì?
2. Giả sử chúng ta muốn sử dụng lại chỉ một phần của một mạng nào đó để
phối hợp với một mạng của một kiến trúc *khác*. Trong trường hợp ta
muốn sử dụng hai lớp đầu tiên của mạng trước đó vào trong một mạng
mới, bạn sẽ làm thể nào để thực hiện được việc này?
3. Làm thế nào để bạn có thể lưu kiến trúc mạng và các tham số? Có những
hạn chế nào khi bạn tận dụng kiến trúc này?
.. 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
- Nguyễn Duy Du
- Phạm Minh Đức
- Lê Khắc Hồng Phúc
- Nguyễn Văn Cường
- Phạm Hồng Vinh