<jupyter_start><jupyter_text>Multiple Input and Output Channels**Multiple Input Channels**![Cross-correlation with 2 input channels](http://www.d2l.ai/_images/conv_multi_in.svg)<jupyter_code>import d2l
from mxnet import nd

def corr2d_multi_in(X, K):
    # First, traverse along the 0th dimension (channel dimension) of X and K. 
    # Then, add them together by using * 
    return nd.add_n(*[d2l.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 = nd.array([[[0, 1, 2], [3, 4, 5], [6, 7, 8]],
              [[1, 2, 3], [4, 5, 6], [7, 8, 9]]])
K = nd.array([[[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 them together.<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 nd.stack(*[corr2d_multi_in(X, k) for k in K])<jupyter_output><empty_output><jupyter_text>We construct a convolution kernel with 3 output channels by concatenating the kernel array `K` with `K+1` (plus one for each element in `K`) and `K+2`.<jupyter_code>K = nd.stack(K, K + 1, K + 2)
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>(2, 3, 3)
(3, 2, 2, 2)

[[[ 56.  72.]
  [104. 120.]]

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

 [[ 96. 128.]
  [192. 224.]]]
<NDArray 3x2x2 @cpu(0)><jupyter_text>$1\times 1$ Convolutions![1x1 convolutions](http://www.d2l.ai/_images/conv_1x1.svg)<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 = nd.dot(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 = nd.random.uniform(shape=(3, 3, 3))
K = nd.random.uniform(shape=(2, 3, 1, 1))

Y1 = corr2d_multi_in_out_1x1(X, K)
Y2 = corr2d_multi_in_out(X, K)

(Y1 - Y2).norm().asscalar() < 1e-6<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14948859166011014, 'fraction_numerical': 0.045633359559402044, 'mean_word_length': 4.74040632054176, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '344067', 'license': 'Apache-2.0', 'n_tokens_mistral': 1077, 'n_tokens_neox': 991, 'n_words': 271, 'path': 'slides/2_26/channels.ipynb', 'repo_name': 'yang-chenyu104/berkeley-stat-157', 'size': '2542'}