Tệp I/O ======= Cho đến nay chúng tôi đã thảo luận về cách xử lý dữ liệu và cách xây dựng, đào tạo và kiểm tra các mô hình học sâu. Tuy nhiên, tại một số điểm, chúng tôi hy vọng sẽ đủ hạnh phúc với các mô hình đã học mà chúng tôi sẽ muốn lưu kết quả để sử dụng sau này trong các bối cảnh khác nhau (thậm chí có thể đưa ra dự đoán trong triển khai). Ngoài ra, khi chạy một quá trình đào tạo dài, thực hành tốt nhất là lưu định kỳ kết quả trung gian (checkpointing) để đảm bảo rằng chúng tôi không mất vài ngày giá trị tính toán nếu chúng ta đi qua dây nguồn của máy chủ của chúng tôi. Vì vậy, đã đến lúc học cách tải và lưu trữ cả vectơ trọng lượng riêng lẻ và toàn bộ mô hình. Phần này giải quyết cả hai vấn đề. Tải và tiết kiệm Tensors ------------------------ Đối với hàng chục cá nhân, chúng ta có thể gọi trực tiếp các hàm ``load`` và ``save`` để đọc và viết chúng tương ứng. Cả hai chức năng yêu cầu chúng tôi cung cấp một tên, và ``save`` yêu cầu như là đầu vào biến được lưu. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. 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
.. raw:: html
.. code:: python import torch from torch import nn from torch.nn import functional as F x = torch.arange(4) torch.save(x, 'x-file') .. raw:: html
.. raw:: html
.. code:: python import numpy as np import tensorflow as tf x = tf.range(4) np.save('x-file.npy', x) .. raw:: html
.. raw:: html
Bây giờ chúng ta có thể đọc dữ liệu từ tệp được lưu trữ trở lại vào bộ nhớ. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python x2 = npx.load('x-file') x2 .. parsed-literal:: :class: output [array([0., 1., 2., 3.])] .. raw:: html
.. raw:: html
.. code:: python x2 = torch.load('x-file') x2 .. parsed-literal:: :class: output tensor([0, 1, 2, 3]) .. raw:: html
.. raw:: html
.. code:: python x2 = np.load('x-file.npy', allow_pickle=True) x2 .. parsed-literal:: :class: output array([0, 1, 2, 3], dtype=int32) .. raw:: html
.. raw:: html
Chúng ta có thể lưu trữ một danh sách các hàng chục và đọc lại vào bộ nhớ. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. 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
.. raw:: html
.. code:: python y = torch.zeros(4) torch.save([x, y],'x-files') x2, y2 = torch.load('x-files') (x2, y2) .. parsed-literal:: :class: output (tensor([0, 1, 2, 3]), tensor([0., 0., 0., 0.])) .. raw:: html
.. raw:: html
.. code:: python y = tf.zeros(4) np.save('xy-files.npy', [x, y]) x2, y2 = np.load('xy-files.npy', allow_pickle=True) (x2, y2) .. parsed-literal:: :class: output (array([0., 1., 2., 3.]), array([0., 0., 0., 0.])) .. raw:: html
.. raw:: html
Chúng ta thậm chí có thể viết và đọc một từ điển bản đồ từ chuỗi đến tensors. Điều này thuận tiện khi chúng ta muốn đọc hoặc viết tất cả các trọng lượng trong một mô hình. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. 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
.. code:: python mydict = {'x': x, 'y': y} torch.save(mydict, 'mydict') mydict2 = torch.load('mydict') mydict2 .. parsed-literal:: :class: output {'x': tensor([0, 1, 2, 3]), 'y': tensor([0., 0., 0., 0.])} .. raw:: html
.. raw:: html
.. code:: python mydict = {'x': x, 'y': y} np.save('mydict.npy', mydict) mydict2 = np.load('mydict.npy', allow_pickle=True) mydict2 .. parsed-literal:: :class: output array({'x': , 'y': }, dtype=object) .. raw:: html
.. raw:: html
Tải và lưu thông số mô hình --------------------------- Tiết kiệm vectơ trọng lượng riêng lẻ (hoặc các hàng chục khác) rất hữu ích, nhưng nó trở nên rất tẻ nhạt nếu chúng ta muốn lưu (và sau đó tải) toàn bộ mô hình. Rốt cuộc, chúng ta có thể có hàng trăm nhóm tham số rắc khắp. Vì lý do này, khung học sâu cung cấp các chức năng tích hợp để tải và lưu toàn bộ mạng. Một chi tiết quan trọng cần lưu ý là điều này lưu mô hình *tham số* chứ không phải toàn bộ mô hình. Ví dụ: nếu chúng ta có MLP 3 lớp, chúng ta cần chỉ định kiến trúc riêng biệt. Lý do cho điều này là bản thân các mô hình có thể chứa mã tùy ý, do đó chúng không thể được serialized như một cách tự nhiên. Do đó, để khôi phục lại một mô hình, chúng ta cần tạo kiến trúc trong mã và sau đó tải các tham số từ đĩa. Hãy để chúng tôi bắt đầu với MLP.quen thuộc của chúng tôi .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. 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
.. raw:: html
.. code:: python class MLP(nn.Module): def __init__(self): super().__init__() self.hidden = nn.Linear(20, 256) self.output = nn.Linear(256, 10) def forward(self, x): return self.output(F.relu(self.hidden(x))) net = MLP() X = torch.randn(size=(2, 20)) Y = net(X) .. raw:: html
.. raw:: html
.. code:: python class MLP(tf.keras.Model): def __init__(self): super().__init__() self.flatten = tf.keras.layers.Flatten() self.hidden = tf.keras.layers.Dense(units=256, activation=tf.nn.relu) self.out = tf.keras.layers.Dense(units=10) def call(self, inputs): x = self.flatten(inputs) x = self.hidden(x) return self.out(x) net = MLP() X = tf.random.uniform((2, 20)) Y = net(X) .. raw:: html
.. raw:: html
Tiếp theo, chúng ta lưu trữ các tham số của mô hình dưới dạng tệp với tên “mlp.params”. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python net.save_parameters('mlp.params') .. raw:: html
.. raw:: html
.. code:: python torch.save(net.state_dict(), 'mlp.params') .. raw:: html
.. raw:: html
.. code:: python net.save_weights('mlp.params') .. raw:: html
.. raw:: html
Để khôi phục mô hình, chúng tôi khởi tạo một bản sao của mô hình MLP ban đầu. Thay vì khởi tạo ngẫu nhiên các tham số model, chúng ta đọc các tham số được lưu trữ trong tập tin trực tiếp. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python clone = MLP() clone.load_parameters('mlp.params') .. raw:: html
.. raw:: html
.. code:: python clone = MLP() clone.load_state_dict(torch.load('mlp.params')) clone.eval() .. parsed-literal:: :class: output MLP( (hidden): Linear(in_features=20, out_features=256, bias=True) (output): Linear(in_features=256, out_features=10, bias=True) ) .. raw:: html
.. raw:: html
.. code:: python clone = MLP() clone.load_weights('mlp.params') .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Vì cả hai trường hợp đều có cùng tham số mô hình, kết quả tính toán của cùng một đầu vào ``X`` phải giống nhau. Hãy để chúng tôi xác minh điều này. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python Y_clone = clone(X) Y_clone == 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
.. code:: python Y_clone = clone(X) Y_clone == Y .. parsed-literal:: :class: output tensor([[True, True, True, True, True, True, True, True, True, True], [True, True, True, True, True, True, True, True, True, True]]) .. raw:: html
.. raw:: html
.. code:: python Y_clone = clone(X) Y_clone == Y .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Tóm tắt ------- - Các chức năng ``save`` và ``load`` có thể được sử dụng để thực hiện I/O tệp cho các đối tượng tensor. - Chúng ta có thể lưu và tải toàn bộ bộ tham số cho một mạng thông qua một từ điển tham số. - Lưu kiến trúc phải được thực hiện trong mã chứ không phải trong các tham số. Bài tập ------- 1. Ngay cả khi không cần triển khai các mô hình được đào tạo cho một thiết bị khác, lợi ích thiết thực của việc lưu trữ các thông số mô hình là gì? 2. Giả sử rằng chúng ta chỉ muốn sử dụng lại các phần của mạng để được kết hợp vào một mạng của một kiến trúc khác nhau. Làm thế nào bạn sẽ đi về sử dụng, nói hai lớp đầu tiên từ một mạng trước đó trong một mạng mới? 3. Làm thế nào bạn sẽ đi về lưu kiến trúc mạng và các tham số? Bạn sẽ áp đặt những hạn chế nào đối với kiến trúc? .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html