<jupyter_start><jupyter_text>**Multiple Input and Output Channels** **Multiple Input Channels**<jupyter_code>import torch

def corr2d(X, K):
    h, w = K.shape
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j] = (X[i: i + h, j: j + w] * K).sum()
    return Y
    
def corr2d_multi_in(X, K):
    # First, traverse along the 0th dimension (channel dimension) of X and K.
    # Then, add them together
    return sum([corr2d(x, k) for x, k in zip(X, K)])<jupyter_output><empty_output><jupyter_text>We can construct the input array X and the kernel array K of the above diagram to validate the output of the cross-correlation operation.<jupyter_code>X = torch.tensor([[[0, 1, 2], [3, 4, 5], [6, 7, 8]],
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]])
K = torch.tensor([[[0, 1], [2, 3]], [[1, 2], [3, 4]]])
corr2d_multi_in(X, K)<jupyter_output><empty_output><jupyter_text>**Multiple Output Channels**For multiple output channels we simply generate multiple outputs and then stack themtogether.<jupyter_code>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 torch.stack([corr2d_multi_in(X, k) for k in K], dim=0)<jupyter_output><empty_output><jupyter_text>We construct a convolution kernel with 3 output channels by concatenating the kernelarray $K$ with $K+1$ (plus one for each element in $K$) and $K+2$.<jupyter_code>K = torch.stack([K, K + 1, K + 2], dim=0)
K.shape<jupyter_output><empty_output><jupyter_text>We can have multiple input and output channels.<jupyter_code>print(X.shape)
print(K.shape)
print(corr2d_multi_in_out(X, K))<jupyter_output>torch.Size([2, 3, 3])
torch.Size([3, 2, 2, 2])
tensor([[[ 56.,  72.],
         [104., 120.]],

        [[ 76., 100.],
         [148., 172.]],

        [[ 96., 128.],
         [192., 224.]]])<jupyter_text>**$1\times 1$ Convolutions**<jupyter_code>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 = torch.matmul(K, X) # Matrix multiplication in the fully connected layer.
    return Y.reshape((c_o, h, w))<jupyter_output><empty_output><jupyter_text>This is equivalent to cross-correlation with an appropriately narrow $1\times 1$ kernel.<jupyter_code>X = torch.randn(size=(3, 3, 3))
K = torch.randn(size=(2, 3, 1, 1))
Y1 = corr2d_multi_in_out_1x1(X, K)
Y2 = corr2d_multi_in_out(X, K)
(Y1 - Y2).norm().item() < 1e-6<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15957847196085811, 'fraction_numerical': 0.042152803914188935, 'mean_word_length': 4.072519083969466, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '625257', 'license': 'Apache-2.0', 'n_tokens_mistral': 1114, 'n_tokens_neox': 1030, 'n_words': 291, 'path': 'L11 Convolutional Networks/L11_7_Channels.ipynb', 'repo_name': 'JiahongChen/d2l-pytorch-implementation', 'size': '2657'}