Chuyển đến nội dung chính

Hàm Tanh: Vì sao đầu ra lấy tâm tại 0 quan trọng với mạng nơ-ron

Hướng dẫn này giải thích trực giác toán học đằng sau hàm tanh, cách so sánh với sigmoid và ReLU, các ưu điểm và đánh đổi, cùng cách triển khai hiệu quả trong deep learning.
· 8 phút đọc

Khám phá cùng AI

Mạng nơ-ron của bạn đang mắc kẹt ở mức chính xác 60% và bạn không hiểu vì sao?

Bạn đã chỉnh learning rate, thêm nhiều tầng, và thử thay đổi batch size. Không gì hiệu quả. Training loss hầu như không nhúc nhích sau vài epoch đầu. Bạn bắt đầu nghi ngờ cả thiết lập: có lẽ dữ liệu tệ, có lẽ kiến trúc sai. Nhưng thực ra hàm kích hoạt đang đẩy mọi đầu ra theo một chiều, khiến mạng không thể học được các mẫu cân bằng.

Tanh (hyperbolic tangent) giải quyết điều này bằng cách lấy tâm đầu ra quanh 0, trong khoảng từ -1 đến 1. Điều đó giúp mô hình hội tụ nhanh hơn và giữ cho gradient lan truyền ngược một cách đối xứng.

Trong bài viết này, bạn sẽ biết tanh là gì, cách nó hoạt động về mặt toán học, khi nào nên dùng nó thay cho ReLU hoặc sigmoid, và cách triển khai trong PyTorch. Nếu bạn mới học deep learning, hãy xem hướng dẫn chi tiết của chúng tôi về hàm kích hoạt trong mạng nơ-ron.

Hàm Tanh là gì?

Hàm tanh ánh xạ mọi đầu vào thành một giá trị trong khoảng từ -1 đến 1.

Đó là một đường cong mượt, hình chữ S, được định nghĩa bởi công thức sau:

phương trình hàm tanh

Minh họa hàm Tanh

Hàm Tanh. Ảnh: Tác giả

Hàm có hành vi dễ dự đoán ở các giá trị cực trị. Khi bạn đưa vào một số dương lớn, đầu ra sẽ gần 1. Với một số âm lớn, bạn sẽ nhận được giá trị gần -1.

Xung quanh 0, tanh gần như tuyến tính. Điều này có nghĩa là gradient chảy mượt mà trong quá trình lan truyền ngược thay vì bị nén hoặc méo.

Để so sánh, sigmoid chỉ cho đầu ra dương trong khoảng 0 đến 1. Tanh cho cả số dương và âm. Nó giữ kích hoạt cân bằng quanh 0, giúp tối ưu hóa hội tụ nhanh hơn trong nhiều kiến trúc mạng.

Bạn sẽ thấy tanh được dùng nhiều nhất trong mạng hồi quy (recurrent) và bất cứ nơi nào các kích hoạt lấy tâm giúp cải thiện độ ổn định.

Thuộc tính Toán học và Tính toán

Tanh có một vài thuộc tính toán học mà mọi kỹ sư machine learning tương lai cần biết.

Mượt và khả vi

Tanh khả vi vô hạn và mượt ở mọi nơi.

Điều này quan trọng với tối ưu hóa dựa trên gradient. Bạn sẽ không gặp các góc nhọn như với ReLU, nơi đạo hàm nhảy từ 0 lên 1 ngay lập tức. Gradient mượt nghĩa là cập nhật trọng số dự đoán được hơn trong lan truyền ngược.

Đầu ra lấy tâm tại 0

Sigmoid cho đầu ra trong khoảng 0 đến 1. Tanh cho đầu ra trong khoảng -1 đến 1.

Khi các kích hoạt cân bằng quanh 0, mạng của bạn hội tụ nhanh hơn. Cập nhật trọng số không bị lệch về một phía, và gradient chảy đều hơn qua các tầng.

Giới hạn và ổn định

Khoảng đầu ra của tanh được cố định trong [-1, 1].

Những giới hạn này ngăn bất ổn số học. Nếu bạn làm việc với các mạng không chịu được kích hoạt bùng nổ, tanh giữ mọi thứ trong tầm kiểm soát mà không cần clipping hoặc xử lý đặc biệt.

Hành vi ở cực trị

Với giá trị dương lớn, tanh tiến gần 1. Với giá trị âm lớn, nó tiến gần -1.

Tính đối xứng này giữ các kích hoạt lấy tâm và ngăn dịch chuyển độ chệch (bias shift) như bạn thấy ở các hàm không lấy tâm như sigmoid. Trong mạng sâu, thuộc tính đó giúp cập nhật trọng số lan truyền đều hơn qua các tầng — mạng của bạn không phát triển ưu tiên cho giá trị dương hay âm.

Đạo hàm của tanh

Đạo hàm của tanh là:

đạo hàm của hàm tanh

Đồ thị đạo hàm Tanh

Đạo hàm Tanh. Ảnh: Tác giả.

Điều này có nghĩa gradient mạnh gần 0 nhưng thu nhỏ về biên khi hàm bão hòa. Khi tanh(x) gần 1 hoặc -1, đạo hàm tiến về 0, làm chậm việc học của các neuron đó.

Trong thực tế, bạn có việc học ổn định với đầu vào vừa phải nhưng có nguy cơ mất mát gradient khi đầu vào quá lớn hoặc quá nhỏ. Đây là lý do các mạng sâu thường ưu tiên ReLU — nó không bão hòa với giá trị dương.

Tanh so với các hàm khác

Tanh không phải là hàm kích hoạt duy nhất; hiểu cách nó so sánh với các lựa chọn khác giúp bạn chọn đúng cho mạng của mình.

Sigmoid là họ hàng gần của tanh. Thực tế, tanh chỉ là phiên bản co giãn và tịnh tiến của sigmoid:

Phương trình biểu diễn Tanh như sigmoid được co giãn và tịnh tiến

Trong đó σ(x) là hàm sigmoid.

Hình 3 - Hàm Sigmoid

Hàm Sigmoid. Ảnh: Tác giả

Điểm khác biệt chính là Sigmoid cho đầu ra từ 0 đến 1, trong khi tanh cho đầu ra từ -1 đến 1. Tính lấy tâm tại 0 giúp tanh hội tụ nhanh hơn trong hầu hết trường hợp.

ReLU đi theo một cách tiếp cận khác. Nó cho đầu ra 0 với đầu vào âm và giữ nguyên đầu vào dương. Điều này tạo độ thưa (sparsity), nghĩa là nhiều neuron không hoạt động, từ đó tăng tốc huấn luyện. Tuy nhiên, ReLU triệt tiêu gradient cho giá trị âm. Tanh không gặp vấn đề này vì nó duy trì gradient khác 0 với đầu vào âm. Nó bão hòa ở cả hai cực, có thể làm chậm học khi đầu vào quá lớn hoặc quá nhỏ.

Hình 4 - Hàm ReLU

Hàm ReLU. Ảnh: Tác giả

Softsign trông giống tanh. Cả hai đều là các đường cong mượt, hình chữ S. Nhưng tanh hội tụ nhanh hơn gần 0 vì độ dốc của nó lớn hơn. Điều này mang lại gradient mạnh hơn trong giai đoạn đầu huấn luyện, giúp mạng học nhanh trước khi đầu vào chạm vùng bão hòa.

Hình 5 - Hàm Softsign

Hàm Softsign. Ảnh: Tác giả

Tôi chỉ mới chạm bề mặt các hàm kích hoạt này. Nếu bạn quan tâm đến các lựa chọn thay thế cho Tanh và ReLU, hãy đọc hướng dẫn chuyên sâus về Softmax và Softplus.

Ưu điểm của Tanh

Nếu bạn đang cân nhắc có nên thử Tanh hay không, dưới đây là vài ưu điểm có thể giúp mô hình cuối cùng chính xác hơn.

Đầu ra lấy tâm tại 0

Tanh tạo ra đầu ra cân bằng quanh 0.

Điều này giảm thiên lệch trong cập nhật trọng số. Khi các kích hoạt lấy tâm quanh 0 thay vì lệch dương như sigmoid, gradient sẽ không kéo trọng số về một phía nhiều hơn phía kia. Kết quả là hội tụ nhanh hơn và quá trình huấn luyện ổn định hơn.

Gradient mạnh gần 0

Tanh có độ dốc lớn gần 0.

Điều này tạo gradient mạnh hơn trong lan truyền ngược so với sigmoid. Mạng của bạn học nhanh hơn ở giai đoạn đầu huấn luyện khi phần lớn kích hoạt nằm gần 0. Ngược lại, độ dốc nhẹ của Sigmoid khiến các cập nhật ban đầu yếu và chậm hơn.

Dòng chảy gradient mượt

Đạo hàm của tanh liên tục ở mọi nơi.

Không có bước nhảy đột ngột hay gián đoạn. Điều này mang lại tối ưu hóa ổn định hơn so với các hàm từng phần như ReLU, nơi đạo hàm chuyển đột ngột từ 0 sang 1 tại 0. Gradient mượt nghĩa là cập nhật trọng số có thể dự đoán suốt quá trình huấn luyện.

Lý tưởng cho mạng hồi quy

RNN, LSTM và GRU dựa vào tanh ở các tầng ẩn.

Các kiến trúc này cần duy trì trạng thái nội bộ mượt qua các bước thời gian. Tanh cho phép cả tín hiệu dương và âm đi qua trong khi vẫn giữ giá trị trong giới hạn. Sự cân bằng này ngăn kích hoạt bùng nổ và giúp mạng ghi nhớ thông tin qua các chuỗi dài hơn.

Hạn chế và đánh đổi

Trước khi vào phần mã, tôi sẽ đề cập đôi chỗ Tanh có thể chưa đáp ứng tốt.

Mất mát gradient

Khi đầu vào rời xa 0, gradient tiến gần 0.

Điều này xảy ra vì tanh bão hòa tại -1 và 1. Khi kích hoạt chạm các cực trị này, đạo hàm trở nên rất nhỏ và cập nhật trọng số chậm lại. Trong các mạng rất sâu, vấn đề này cộng dồn do gradient nhỏ dần khi lan truyền ngược qua từng tầng, đến mức việc học gần như dừng lại.

Huấn luyện chậm hơn

Tanh không tạo độ thưa.

Mỗi neuron đều hoạt động ở một mức độ nào đó, không như ReLU với đầu vào âm cho đầu ra 0. Điều này khiến mạng xử lý nhiều thông tin hơn mỗi lần truyền xuôi, nghe có vẻ tốt nhưng thực ra làm chậm. Độ thưa của ReLU khiến huấn luyện nhanh hơn vì neuron không hoạt động bỏ qua hoàn toàn tính toán.

Ít được tối ưu bởi phần cứng

Các framework hiện đại và bộ tăng tốc phần cứng ưu ái ReLU.

Phép toán tanh liên quan đến hàm mũ, tốn kém hơn so với phép max(0, x) đơn giản của ReLU. Các kernel GPU và chip AI chuyên dụng được tối ưu cho ReLU vì nó trở thành mặc định trong hầu hết kiến trúc. Điều này nghĩa là tanh sẽ chạy chậm hơn trên cùng phần cứng, ngay cả với kiến trúc mạng giống hệt.

Tanh trong PyTorch

PyTorch cung cấp sẵn triển khai hàm Tanh, nên bạn không phải viết lại từ đầu.

Đây là cách dùng nó như một hàm kích hoạt trong mạng nơ-ron đơn giản:

import torch
import torch.nn as nn

model = nn.Sequential(
    nn.Linear(10, 20),
    nn.Tanh(),
    nn.Linear(20, 1)
)

x = torch.randn(5, 10)
output = model(x)
print(output)
tensor([[ 0.0910],
               [-0.0994],
               [-0.0583],  
               [-0.2177],
               [-0.2546]], grad_fn=<AddmmBackward0>)

Bạn cũng có thể áp dụng tanh trực tiếp lên tensor:

x = torch.tensor([-2.0, -1.0, 0.0, 1.0, 2.0])
output = torch.tanh(x)
print(output)
tensor([-0.9640, -0.7616, 0.0000, 0.7616, 0.9640])

Hãy để ý đầu ra đối xứng quanh 0 — đầu vào âm cho đầu ra âm, và hàm xử lý hai phía như nhau. Phân phối cân bằng này giữ mạng ổn định trong huấn luyện và tránh dịch chuyển độ chệch mà bạn sẽ thấy với các hàm như sigmoid.

Khi nào dùng Tanh

Chọn hàm Tanh khi mô hình của bạn hưởng lợi từ các kích hoạt lấy tâm hoặc khi làm việc với mạng nhỏ hơn hay mạng hồi quy.

Đặc biệt hiệu quả khi:

  • Bạn đang huấn luyện RNN hoặc LSTM cần các kích hoạt cân bằng. Các kiến trúc này dựa vào Tanh để duy trì trạng thái nội bộ mượt qua các bước thời gian trong khi cho phép cả tín hiệu dương và âm đi qua.
  • Bạn đang mô hình hóa mục tiêu liên tục hoặc mượt. Dòng chảy gradient mượt của Tanh phù hợp khi đầu ra cần liên tục và có giới hạn, như dự đoán các giá trị tự nhiên nằm trong một khoảng.
  • Bạn muốn gradient ổn định, khả vi nhưng không cần độ thưa của ReLU. Nếu mạng của bạn không đủ sâu để hưởng lợi từ tốc độ của ReLU, Tanh mang lại hành vi huấn luyện dự đoán được hơn.

Ngược lại, tránh dùng Tanh trong các kiến trúc rất sâu nơi vấn đề mất mát gradient đáng lo ngại. ReLU hoặc GELU phù hợp hơn vì chúng không bão hòa với giá trị dương.

Kết luận

Tóm lại, hàm Tanh nằm giữa sự đơn giản của Sigmoid và tốc độ của ReLU.

Nó mượt, đối xứng và vẫn phù hợp trong deep learning, đặc biệt khi các kích hoạt cân bằng là yếu tố quan trọng. Bạn sẽ không thấy nó ở mọi kiến trúc hiện đại, nhưng nó có chỗ đứng khi bạn cần đầu ra lấy tâm và dòng gradient ổn định.

Nếu bạn chưa chắc có nên dùng Tanh hay không, hãy làm theo các nguyên tắc sau:

  • Dùng ReLU cho mạng lớn, sâu. Nó nhanh hơn, hoạt động tốt với phần cứng hiện đại và tránh mất mát gradient cho giá trị dương.
  • Dùng Tanh khi bạn cần ổn định, đối xứng và dòng gradient mượt. Tức là cho mạng hồi quy, kiến trúc nhỏ hơn, và các trường hợp mà kích hoạt lấy tâm giúp cải thiện hội tụ.

Hãy chạy thí nghiệm, so sánh kết quả và để dữ liệu quyết định hàm kích hoạt phù hợp nhất cho bài toán của bạn. Muốn học thêm? Hãy đăng ký lộ trình Machine Learning Scientist in Python để nắm vững học có giám sát, không giám sát và deep learning.

Dario Radečić

Tác giả

Dario Radečić

Chuyên gia Khoa học Dữ liệu Cấp cao, làm việc tại Croatia. Tác giả Công nghệ Hàng đầu với hơn 700 bài viết đã xuất bản, đạt trên 10 triệu lượt xem. Tác giả cuốn sách Tự động hóa Machine Learning với TPOT.
Dario Radečić

Tác giả

Dario Radečić

Chuyên gia Khoa học Dữ liệu Cấp cao, làm việc tại Croatia. Tác giả Công nghệ Hàng đầu với hơn 700 bài viết đã xuất bản, đạt trên 10 triệu lượt xem. Tác giả cuốn sách Tự động hóa Machine Learning với TPOT.

Câu hỏi thường gặp

Hàm kích hoạt tanh là gì?

Tanh (hyperbolic tangent) là một hàm kích hoạt ánh xạ mọi đầu vào thành giá trị trong khoảng -1 đến 1. Nó được định nghĩa là tanh(x) = (e^x - e^-x) / (e^x + e^-x) và tạo ra đường cong hình chữ S tương tự sigmoid. Khác biệt chính là tanh lấy tâm tại 0, nghĩa là cho ra cả giá trị dương và âm, giúp mạng nơ-ron hội tụ nhanh hơn trong huấn luyện.

Khi nào tôi nên dùng tanh thay vì ReLU?

Dùng tanh khi bạn xây dựng các mạng hồi quy (RNN, LSTM, GRU) cần kích hoạt cân bằng, lấy tâm tại 0. Nó cũng tốt hơn cho các mạng nhỏ hơn khi bạn cần gradient mượt, khả vi mà không cần độ thưa như ReLU mang lại. Tránh dùng tanh trong các mạng truyền thẳng rất sâu, nơi tốc độ và khả năng chống mất mát gradient của ReLU khiến nó là lựa chọn tốt hơn.

Ưu điểm chính của tanh so với sigmoid là gì?

Đầu ra lấy tâm tại 0 của Tanh (trong khoảng -1 đến 1) ngăn dịch chuyển độ chệch xảy ra với khoảng 0 đến 1 của sigmoid. Điều này dẫn đến cập nhật trọng số cân bằng hơn và hội tụ nhanh hơn. Tanh cũng có độ dốc lớn hơn gần 0, nghĩa là gradient mạnh hơn trong lan truyền ngược so với sigmoid.

Vì sao tanh gây mất mát gradient?

Tanh bão hòa tại -1 và 1, nghĩa là đạo hàm tiến gần 0 khi đầu vào rời xa 0. Trong mạng sâu, các gradient nhỏ này nhân với nhau khi lan truyền ngược, thu nhỏ theo hàm mũ qua mỗi tầng đến khi gần như biến mất. Điều này khiến các tầng đầu khó học, đó là lý do ReLU được ưa chuộng cho các kiến trúc rất sâu.

Tôi triển khai tanh trong PyTorch như thế nào?

PyTorch cung cấp tanh qua nn.Tanh() như một tầng hoặc torch.tanh() như một hàm. Bạn có thể thêm nó vào mô hình hoặc áp dụng trực tiếp lên tensor. Cả hai cách hoạt động như nhau và hỗ trợ tự động tính gradient cho lan truyền ngược.

Chủ đề

Liên quan