[ad_1]
Đây là điều mà bất cứ ai đã dành nhiều thời gian làm việc với máy biến áp và luôn chú ý đến bản thân sẽ nghe thấy hàng trăm lần. Cả hai đều hoàn toàn đúng, tất cả chúng ta đều đã trải qua điều này khi bạn cố gắng tăng kích thước ngữ cảnh của mô hình của mình, mọi thứ đột nhiên dừng lại. Nhưng đồng thời, dường như hầu như mỗi tuần, lại có một mô hình hiện đại mới với độ dài bối cảnh phá kỷ lục mới. (Gemini có độ dài bối cảnh là 2 triệu mã thông báo!)
Có rất nhiều phương pháp phức tạp như RingAttention giúp việc đào tạo có độ dài bối cảnh cực kỳ dài trong các hệ thống phân tán lớn có thể thực hiện được, nhưng điều tôi quan tâm hôm nay là một câu hỏi đơn giản hơn.
Chúng ta có thể đi được bao xa chỉ với sự chú ý tuyến tính?
Đây sẽ là một chuyến tham quan hơi dài dòng nhưng hãy kiên nhẫn với tôi khi chúng ta đề cập đến một số điểm chính trước khi đi sâu vào kết quả.
Về cơ bản chúng ta có thể tóm tắt cơ chế chú ý truyền thống với hai điểm chính:
- Đầu tiên, biểu thức chú ý softmax điển hình lấy tích của truy vấn và ma trận khóa, chuẩn hóa để đảm bảo độ ổn định, sau đó lấy softmax (hàng thông minh) để lấy điểm chú ý giữa mỗi phần tử của chuỗi.
- Thứ hai, độ phức tạp về thời gian bị chi phối bởi tích số chấm N2 và tích số bên trong softmax là hệ số giới hạn. Đó là nơi chúng tôi tính toán điểm chú ý.
Điều này được thể hiện dưới hình thức truyền thống như:
Hóa ra nếu chúng ta hỏi những người bạn toán học của mình, chúng ta có thể nghĩ về điều này hơi khác một chút. Softmax có thể được coi là một trong nhiều cách mô tả phân phối xác suất liên quan đến các mã thông báo với nhau. Chúng ta có thể sử dụng bất kỳ thước đo tương tự nào mà chúng ta thích (tích số chấm là một trong những thước đo đơn giản nhất) và miễn là chúng ta chuẩn hóa nó, chúng ta sẽ ổn.
Nói điều này hơi cẩu thả là sự chú ý, vì trên thực tế, đó chỉ là sự chú ý mà chúng ta biết và yêu thích khi hàm tương tự là cấp số nhân của tích chấm của các truy vấn và khóa (được đưa ra bên dưới) như chúng ta tìm thấy trong softmax. Nhưng đây chính là điểm thú vị, nếu thay vì sử dụng biểu thức này thì giá như chúng ta có thể ước chừng nó thì sao?
Chúng ta có thể cho rằng có một số bản đồ đặc trưng “phi” mang lại cho chúng tôi một kết quả gần như tương tự như việc lấy số mũ của tích chấm. Và điều quan trọng nhất là viết biểu thức như thế này cho phép chúng ta thực hiện theo thứ tự của các phép nhân ma trận.
bên trong giấy họ đề xuất Đơn vị tuyến tính hàm mũ (ELU) làm bản đồ đặc trưng do một số thuộc tính hữu ích:
- Đối với các giá trị trên 0, ELU(x) cho kết quả tuyến tính, mặc dù không giống với hàm mũ nhưng vẫn giữ nguyên thứ tự tương đối giữa các điểm.
- Đối với các giá trị nhỏ hơn hoặc bằng 0, số hạng mũ duy trì tính chất liên tục của hàm và đảm bảo độ dốc không biến mất.
Chúng ta sẽ không dành quá nhiều thời gian cho vấn đề này ở đây, nhưng điều này đã được xác minh khá tốt bằng thực nghiệm là một xấp xỉ hợp lý đối với hàm softmax.
Điều này cho phép chúng ta làm là thay đổi thứ tự thực hiện các thao tác. Trước tiên, chúng ta có thể lấy sản phẩm của bản đồ đặc trưng Okay với V để tạo khối KV, sau đó là sản phẩm có Q. Tích hình vuông sẽ vượt quá kích thước kích thước mô hình thay vì độ dài chuỗi.
Đặt tất cả những điều này lại với nhau thành biểu thức chú ý tuyến tính sẽ cho chúng ta:
Trong đó chúng ta chỉ cần tính các thuật ngữ trong ngoặc một lần cho mỗi hàng truy vấn.
(Nếu bạn muốn tìm hiểu cách mặt nạ thông thường phù hợp với điều này và cách tính toán độ dốc, hãy xem bài báo. Hoặc xem không gian này để biết một weblog trong tương lai.)
Trường hợp toán học rất chắc chắn, nhưng cá nhân tôi cho đến khi nhìn thấy một số điểm chuẩn thì tôi luôn có chút nghi ngờ.
Hãy bắt đầu bằng cách xem các đoạn mã để mô tả từng thuật ngữ này. Sự chú ý của softmax sẽ trông rất quen thuộc, chúng tôi không làm bất cứ điều gì cầu kỳ ở đây.
class TraditionalAttention(nn.Module):
def __init__(self, d_k):
tremendous(TraditionalAttention, self).__init__()
self.d_k = d_kdef ahead(self, Q, Okay, V):
Z = torch.sqrt(torch.tensor(self.d_k, gadget=Q.gadget, dtype=torch.float32))
scores = torch.matmul(Q, Okay.transpose(-2, -1)) / Z
attention_weights = F.softmax(scores, dim=-1)
output = torch.matmul(attention_weights, V)
return output
Sau đó, để thu hút sự chú ý tuyến tính, chúng tôi bắt đầu bằng cách lấy ma trận Truy vấn, Khóa và Giá trị, sau đó áp dụng ánh xạ tính năng ELU(x) cho Truy vấn và Khóa. Sau đó chúng ta sử dụng ký hiệu einsum để thực hiện phép nhân.
class LinearAttention(nn.Module):
def __init__(self):
tremendous(LinearAttention, self).__init__()
self.eps = 1e-6def elu_feature_map(self, x):
return F.elu(x) + 1
def ahead(self, Q, Okay, V):
Q = self.elu_feature_map(Q)
Okay = self.elu_feature_map(Okay)
KV = torch.einsum("nsd,nsd->ns", Okay, V)
# Compute the normalizer
Z = 1/(torch.einsum("nld,nd->nl", Q, Okay.sum(dim=1))+self.eps)
# Lastly compute and return the brand new values
V = torch.einsum("nld,ns,nl->nd", Q, KV, Z)
return V.contiguous()
Nhìn thấy điều này được viết bằng mã là tốt và tốt, nhưng nó thực sự có ý nghĩa gì về mặt thực nghiệm? Chúng ta đang nói đến mức tăng hiệu suất ở mức độ nào? Có thể khó đánh giá được mức độ tăng tốc khi chuyển từ nút cổ chai bậc hai sang nút cổ chai tuyến tính, vì vậy tôi đã thực hiện thí nghiệm sau.
Chúng ta sẽ sử dụng một lớp chú ý duy nhất, với kích thước mô hình d_k cố định là 64 và đánh giá thời gian thực hiện để chuyển tiếp một tập hợp chuỗi có kích thước lô 32. Biến duy nhất cần thay đổi sẽ là độ dài chuỗi, kéo dài từ 128 đến 6000 (độ dài ngữ cảnh GPT-3 để tham khảo nếu 2048). Mỗi lần chạy được thực hiện 100 lần để lấy giá trị trung bình và độ lệch chuẩn, đồng thời các thử nghiệm được chạy bằng GPU Nvidia T4.
Đối với một thí nghiệm đơn giản như vậy, kết quả khá ấn tượng.
Kết quả cho thấy ngay cả một ví dụ về đồ chơi cực kỳ nhỏ cũng có thể đạt được tốc độ lên tới 60 lần.
Cuộc thảo luận
Có một vài điểm rõ ràng ở đây:
- Ưu điểm của sự chú ý tuyến tính là rất lớn – về tốc độ, thông lượng cao hơn luôn là một điều tốt. Hoặc về mặt yêu cầu bộ nhớ để xử lý các chuỗi dài. Trong môi trường bộ nhớ thấp, đây có thể là một lợi thế lớn.
- Biểu đồ tỷ lệ có một điểm gấp khúc đáng ngạc nhiên – khiến chúng tôi nghi ngờ có một số tối ưu hóa cấp thấp hơn đang diễn ra ở đây, nghĩa là tỷ lệ dự kiến không hoàn toàn thực tế. Vì vậy, chúng ta cần coi kết quả này là một chút muối.
Để hoàn thiện cũng đừng nhầm điều này là nói “sự chú ý tuyến tính nhanh hơn 60 lần đối với các mô hình nhỏ”. Trong thực tế, các lớp chuyển tiếp nguồn cấp dữ liệu thường là một phần lớn hơn của các tham số trong Transformer và mã hóa/giải mã cũng thường là thành phần có kích thước giới hạn. Nhưng trong vấn đề được xác định chặt chẽ này, khá ấn tượng!
[ad_2]
Source link