🏷️sec_channels
Mặc dù chúng ta đã mô tả mỗi tấm ảnh được tạo nên bởi nhiều kênh (channel) (cụ thể, ảnh màu sử dụng hệ màu RGB tiêu chuẩn với các kênh riêng biệt thể hiện lượng màu đỏ, xanh lá và xanh dương), nhưng cho đến lúc này, ta vẫn đơn giản hóa tất cả các ví dụ tính toán với chỉ một kênh đầu vào và một kênh đầu ra. Điều đó đã cho phép chúng ta coi các đầu vào, các bộ lọc tích chập và các đầu ra như các mảng hai chiều.
Khi chúng ta thêm các kênh vào hỗn hợp ấy, đầu vào cùng với các lớp biểu diễn ẩn của ta trở thành các mảng ba chiều.
Chẳng hạn, mỗi ảnh RGB đầu vào có dạng
Khi dữ liệu đầu vào có nhiều kênh, ta cần xây dựng một bộ lọc tích chập với cùng số kênh đầu vào như dữ liệu nhập, để nó có thể thực hiện tính tương quan chéo với dữ liệu này.
Giả sử số kênh dữ liệu đầu vào là
Tuy nhiên, khi
Trong :numref:fig_conv_multi_in
minh hoạ một ví dụ về phép tương quan chéo hai chiều với hai kênh đầu vào.
Phần tô đậm là phần tử đầu ra đầu tiên cùng các phần tử của mảng đầu vào và bộ lọc được sử dụng trong phép tính đó:
Để thực sự hiểu được những gì đang xảy ra ở đây, chúng ta có thể tự lập trình phép toán tương quan chéo với nhiều kênh đầu vào.
Chú ý rằng tất cả những gì chúng ta đang làm là thực hiện một phép tương quan chéo trên mỗi kênh rồi cộng các kết quả lại bằng hàm add_n
.
from d2l import mxnet as d2l
from mxnet import np, npx
npx.set_np()
def corr2d_multi_in(X, K):
# First, traverse along the 0th dimension (channel dimension) of X and K.
# Then, add them together by using * to turn the result list into a
# positional argument of the add_n function
return sum(d2l.corr2d(x, k) for x, k in zip(X, K))
Ta có thể tạo mảng đầu vào X
và mảng bộ lọc K
tương ứng với các giá trị trong hình trên để kiểm chứng kết quả đầu ra.
X = np.array([[[0, 1, 2], [3, 4, 5], [6, 7, 8]],
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]])
K = np.array([[[0, 1], [2, 3]], [[1, 2], [3, 4]]])
corr2d_multi_in(X, K)
Cho đến nay, bất kể số lượng kênh đầu vào là bao nhiêu thì ta vẫn luôn kết thúc với chỉ một kênh đầu ra. Tuy nhiên, như đã thảo luận trước đây, hóa ra việc có nhiều kênh ở mỗi tầng là rất cần thiết. Trong các kiến trúc mạng nơ-ron phổ biến nhất, ta thường tăng kích thước chiều kênh khi tiến sâu hơn trong mạng, đồng thời giảm độ phân giải không gian để đánh đổi với chiều kênh sâu hơn này. Theo trực giác, ta có thể xem mỗi kênh tương ứng với một tập các đặc trưng khác nhau. Nhưng thực tế phức tạp hơn một chút so với cách diễn giải theo trực giác này vì các biểu diễn không được học độc lập mà được tối ưu hóa để có ích khi kết hợp với nhau. Vì vậy, có thể việc phát hiện biên sẽ được học bởi một vài kênh thay vì chỉ một kênh duy nhất.
Đặt
Ta lập trình một hàm tương quan chéo để tính đầu ra của nhiều kênh như dưới đây.
def corr2d_multi_in_out(X, K):
# Traverse along the 0th dimension of K, and each time, perform
# cross-correlation operations with input X. All of the results are merged
# together using the stack function
return np.stack([corr2d_multi_in(X, k) for k in K])
Ta tạo một bộ lọc tích chập với 3 kênh đầu ra bằng cách nối mảng bộ lọc K
với K+1
(cộng một cho mỗi phần tử trong K
) và K+2
.
K = np.stack((K, K + 1, K + 2))
K.shape
Dưới đây, ta thực hiện các phép tính tương quan chéo trên mảng đầu vào X
với mảng bộ lọc K
.
Đầu ra sẽ gồm có 3 kênh.
Kết quả của kênh đầu tiên khớp với kết quả trước đây khi áp dụng bộ lọc đa kênh đầu vào và một kênh đầu ra lên mảng đầu vào X
.
corr2d_multi_in_out(X, K)
Thoạt nhìn, một phép tích chập
Do cửa sổ có kích thước tối thiểu nên so với các tầng tích chập lớn hơn, phép tích chập
:numref:fig_conv_1x1
biểu diễn phép tính tương quan chéo sử dụng bộ lọc tích chập
Do đó, tầng tích chập
Hãy kiểm tra xem liệu nó có hoạt động trong thực tế: Ta sẽ lập trình một phép tích chập
def corr2d_multi_in_out_1x1(X, K):
c_i, h, w = X.shape
c_o = K.shape[0]
X = X.reshape(c_i, h * w)
K = K.reshape(c_o, c_i)
Y = np.dot(K, X) # Matrix multiplication in the fully connected layer
return Y.reshape(c_o, h, w)
Khi thực hiện phép tích chập corr2d_multi_in_out
.
X = np.random.uniform(size=(3, 3, 3))
K = np.random.uniform(size=(2, 3, 1, 1))
Y1 = corr2d_multi_in_out_1x1(X, K)
Y2 = corr2d_multi_in_out(X, K)
np.abs(Y1 - Y2).sum() < 1e-6
- Ta có thể sử dụng nhiều kênh để mở rộng các tham số mô hình của tầng tích chập.
- Tầng tích chập
$1\times 1$ khi được áp dụng lên từng điểm ảnh tương đương với tầng kết nối đầy đủ giữa các kênh. - Tầng tích chập
$1\times 1$ thường được sử dụng để điều chỉnh số lượng kênh giữa các tầng của mạng và để kiểm soát độ phức tạp của mô hình.
- Giả sử rằng ta có hai bộ lọc tích chập có kích thước tương ứng là
$k_1$ và$k_2$ (không có tính phi tuyến ở giữa).- Chứng minh rằng kết quả của phép tính có thể được biểu diễn bằng chỉ một phép tích chập.
- Phép tích chập tương đương này có kích thước là bao nhiêu?
- Điều ngược lại có đúng không?
- Giả sử kích thước của đầu vào là
$c_i\times h\times w$ và một bộ lọc tích chập có kích thước$c_o\times c_i\times k_h\times k_w$ , đồng thời sử dụng đệm$(p_h, p_w)$ và sải bước$(s_h, s_w)$ .- Chi phí tính toán (phép nhân và phép cộng) cho lượt truyền xuôi là bao nhiêu?
- Dung lượng bộ nhớ cho tính toán truyền xuôi là bao nhiêu?
- Dung lượng bộ nhớ cho tính toán truyền ngược là bao nhiêu?
- Chi phí tính toán cho lượt lan truyền ngược là bao nhiêu?
- Số lượng tính toán sẽ tăng lên bao nhiêu lần nếu ta nhân đôi số lượng kênh đầu vào
$c_i$ và số lượng kênh đầu ra$c_o$ ? Điều gì xảy ra nếu ta gấp đôi phần đệm? - Nếu chiều cao và chiều rộng của bộ lọc tích chập là
$k_h=k_w=1$ , thì độ phức tạp của tính toán truyền xuôi là bao nhiêu? - Các biến
Y1
vàY2
trong ví dụ cuối cùng của mục này có giống nhau không? Tại sao? - Khi cửa sổ tích chập không phải là
$1\times 1$ , bạn sẽ lập trình các phép tích chập sử dụng phép nhân ma trận như thế nào?
Bản dịch trong trang này được thực hiện bởi:
- Đoàn Võ Duy Thanh
- Nguyễn Mai Hoàng Long
- Nguyễn Lê Quang Nhật
- Lê Khắc Hồng Phúc
- Nguyễn Văn Cường
- Phạm Minh Đức
- Nguyễn Duy Du
- Phạm Hồng Vinh