Có hai cách thường dùng để sử dụng autograd, qua symbolic differentiation như là Theano hoặc reverse differentiation như là Pytorch. SINGA dùng cách Pytorch, lưu trữ computation graph rồi áp dụng backward propagation tự động sau khi forward propagation. Thuật toán autograd được giải thích cụ thể ở đây. Chúng tôi giải thích các modules liên quan trong Singa và đưa ra ví dụ để minh hoạ cách sử dụng.
Autograd gồm ba classes với tên gọi singa.tensor.Tensor
, singa.autograd.Operation
, và singa.autograd.Layer
. Trong phần tiếp theo của văn kiện này, chúng tôi dùng tensor, operation và layer để chỉ một chương trình (instance) trong class tương ứng.
Ba tính năng của Tensor được sử dụng bởi autograd,
.creator
là một chương trình Operation
. Chương trình này lưu trữ tác vụ tạo ra Tensor instance..requires_grad
là một biến kiểu bool. Biến được sử dụng để chỉ rằng thuật toán autograd cần tính ra độ dốc (gradient) của tensor. (như owner). Ví dụ, khi chạy backpropagation, thì cần phải tính ra độ dốc của tensor cho ma trận trọng lượng (weight matrix) của lớp tuyến tính (linear layer) và bản đồ tính năng (feature map) của convolution layer (không phải lớp cuối)..stores_grad
là một biến kiểu bool. Biến được sử dụng để chỉ rằng độ dốc của owner tensor cần được lưu và tạo ra bởi hàm backward. Ví dụ, độ dốc của feature maps được tính thông qua backpropagation, nhưng không được bao gồm trong kết quả của hàm backward.Lập trình viên có thể thay đổi requires_grad
và stores_grad
của chương trình Tensor. Ví dụ nếu hàm sau để là True, độ dốc tương ứng sẽ được bao gồm trong kết quả của hàm backward. Cần lưu ý rằng nếu stores_grad
để là True, thì requires_grad
cũng phải là True, và ngược lại.
Hàm chạy một hoặc một vài chương trình Tensor
instances ở đầu vào, sau đó đầu ra là một hoặc một vài chương trình Tensor
instances. Ví dụ, hàm ReLU có thể được sử dụng như một subclass của một hàm Operation cụ thể. Khi gọi một chương trình Operation
(sau cài đặt), cần thực hiện hai bước sau:
creator
của tensor đầu vào..forward()
Có hai hàm thành viên cho forwarding và backwarding, vd. .forward()
và .backward()
. Đầu vào là Tensor.data
(thuộc loại CTensor
), và đầu ra là Ctensor
. Nếu muốn thêm một hàm operation thì subclass operation
cần chạy riêng .forward()
và .backward()
. Hàm backward()
được tự động gọi bởi hàm backward()
của autograd trong quá trình chạy backward để thực hiện độ dốc của đầu vào (theo mục require_grad
).
Với các hàm yêu cầu tham số (parameter), chúng tôi gói chúng lại thành một class mới, Layer
. Ví dụ hàm convolution operation thì được nhóm vào trong convolution layer. Layer
quản lý (hoặc lưu trữ) các tham số và sẽ gọi các hàm Operation
tương ứng để thực hiện việc chuyển đổi.
Chúng tôi cung cấp nhiều ví dụ trong mục ví dụ. Chúng tôi đưa ra giải thích cụ thể trong hai ví dụ tiêu biểu ở đây.
Code dưới đây áp dụng model MLP, chỉ dùng hàm Operation (không dùng hàm Layer).
from singa.tensor import Tensor from singa import autograd from singa import opt
Tham số tensors được tạo bởi cả requires_grad
và stores_grad
ở giá trị True
.
w0 = Tensor(shape=(2, 3), requires_grad=True, stores_grad=True) w0.gaussian(0.0, 0.1) b0 = Tensor(shape=(1, 3), requires_grad=True, stores_grad=True) b0.set_value(0.0) w1 = Tensor(shape=(3, 2), requires_grad=True, stores_grad=True) w1.gaussian(0.0, 0.1) b1 = Tensor(shape=(1, 2), requires_grad=True, stores_grad=True) b1.set_value(0.0)
inputs = Tensor(data=data) # data matrix target = Tensor(data=label) # label vector autograd.training = True # cho training sgd = opt.SGD(0.05) # optimizer for i in range(10): x = autograd.matmul(inputs, w0) # matrix multiplication x = autograd.add_bias(x, b0) # add the bias vector x = autograd.relu(x) # ReLU activation operation x = autograd.matmul(x, w1) x = autograd.add_bias(x, b1) loss = autograd.softmax_cross_entropy(x, target) for p, g in autograd.backward(loss): sgd.update(p, g)
Ví dụ sau đây áp dụng CNN model sử dụng các lớp (layers) tạo từ autograd module.
conv1 = autograd.Conv2d(1, 32, 3, padding=1, bias=False) bn1 = autograd.BatchNorm2d(32) pooling1 = autograd.MaxPool2d(3, 1, padding=1) conv21 = autograd.Conv2d(32, 16, 3, padding=1) conv22 = autograd.Conv2d(32, 16, 3, padding=1) bn2 = autograd.BatchNorm2d(32) linear = autograd.Linear(32 * 28 * 28, 10) pooling2 = autograd.AvgPool2d(3, 1, padding=1)
Hàm trong forward pass sẽ được tự đông lưu cho backward propagation.
def forward(x, t): # x là input data (batch hình ảnh) # t là label vector (batch số nguyên) y = conv1(x) # Conv layer y = autograd.relu(y) # ReLU operation y = bn1(y) # BN layer y = pooling1(y) # Pooling Layer # hai convolution layers song song y1 = conv21(y) y2 = conv22(y) y = autograd.cat((y1, y2), 1) # cat operation y = autograd.relu(y) # ReLU operation y = bn2(y) y = pooling2(y) y = autograd.flatten(y) # flatten operation y = linear(y) # Linear layer loss = autograd.softmax_cross_entropy(y, t) # operation return loss, y
autograd.training = True for epoch in range(epochs): for i in range(batch_number): inputs = tensor.Tensor(device=dev, data=x_train[ i * batch_sz:(1 + i) * batch_sz], stores_grad=False) targets = tensor.Tensor(device=dev, data=y_train[ i * batch_sz:(1 + i) * batch_sz], requires_grad=False, stores_grad=False) loss, y = forward(inputs, targets) # forward the net for p, gp in autograd.backward(loss): # auto backward sgd.update(p, gp)
Ví dụ sau áp dụng CNN model sử dụng Model API.
Model class được định nghĩa là subclass của Model. Theo đó, tất cả các hàm operations được sử dụng trong bước training sẽ tạo thành một computational graph và được phân tích. Hàm operation trong graph sẽ được lên lịch trình và thực hiện hiệu quả. Layers cũng có thể được bao gồm trong model class.
class MLP(model.Model): # model là subclass của Model def __init__(self, data_size=10, perceptron_size=100, num_classes=10): super(MLP, self).__init__() # taọ operators, layers và các object khác self.relu = layer.ReLU() self.linear1 = layer.Linear(perceptron_size) self.linear2 = layer.Linear(num_classes) self.softmax_cross_entropy = layer.SoftMaxCrossEntropy() def forward(self, inputs): # định nghĩa forward function y = self.linear1(inputs) y = self.relu(y) y = self.linear2(y) return y def train_one_batch(self, x, y): out = self.forward(x) loss = self.softmax_cross_entropy(out, y) self.optimizer(loss) return out, loss def set_optimizer(self, optimizer): # đính kèm optimizer self.optimizer = optimizer
# tạo hàm model instance model = MLP() # tạo optimizer và đính vào model sgd = opt.SGD(lr=0.005, momentum=0.9, weight_decay=1e-5) model.set_optimizer(sgd) # input và target placeholders cho model tx = tensor.Tensor((batch_size, 1, IMG_SIZE, IMG_SIZE), dev, tensor.float32) ty = tensor.Tensor((batch_size, num_classes), dev, tensor.int32) # tổng hợp model trước khi training model.compile([tx], is_train=True, use_graph=True, sequential=False) # train model theo bước lặp (iterative) for b in range(num_train_batch): # generate the next mini-batch x, y = ... # Copy the data into input tensors tx.copy_from_numpy(x) ty.copy_from_numpy(y) # Training with one batch out, loss = model(tx, ty)
# xác định đường dẫn để lưu checkpoint checkpointpath="checkpoint.zip" # lưu checkpoint model.save_states(fpath=checkpointpath)
# xác định đường dẫn để lưu checkpoint checkpointpath="checkpoint.zip" # lưu checkpoint import os if os.path.exists(checkpointpath): model.load_states(fpath=checkpointpath)
Xem tại đây để thêm thông tin chi tiết về Python API.