import tensorflow as tf
import os
# 一、多輸入通道,單輸出通道
# 輸入形狀爲 h * w * channel
def corr2d(X, K):
c,h,w = K.shape
Y = tf.Variable(tf.zeros((X.shape[0] - h + 1, X.shape[1] - w +1, X.shape[2])))
Y_out = tf.Variable(tf.zeros((X.shape[0] - h + 1, X.shape[1] - w +1)))
for i in range(Y.shape[2]):
for j in range(Y.shape[1]):
for k in range(Y.shape[0]):
print(X[:,:,i])
# 注意這裏切片方式,以 channel 通道方向切片,這裏輸出的 Y 也是 h * w * channel形式
Y[j, k,i].assign(tf.cast(tf.reduce_sum(X[j:j+h, k:k+w, i] * K[i,: ,:]), dtype=tf.float32))
# 得到的Y仍然是三個通道,然後求和合併成一個通道
Y_out = tf.reduce_sum(Y,axis=2)
return Y_out
X = tf.random.uniform(shape=(4,4,2),maxval=10, minval=1, dtype='int32')
print('X',X)
K = tf.constant([[[1, 0],[0,1]],[[1, 1],[1,0]]])
print('K',K)
Y = corr2d(X, K)
Y
多通道輸出即:
# K.shape = c0 * c1 * h * w
def corr2d_multi_in_out(X, K):
return tf.stack([corr2d(X, k) for k in K],axis=0)
def corr2d_multi_in_out_1x1(X, K):
h, w, c_i = X.shape
c_o = K.shape[0]
# X展開
X = tf.reshape(X,(h * w, c_i))
# K 展開
K = tf.reshape(K,(c_o, c_i))
Y = tf.matmul(K, tf.transpose(X))
return tf.reshape(Y, (c_o, h, w))
經驗證,做 1×1 卷積時,以上函數與之前實現的互相關運算函數corr2d_multi_in_out等價。在之後的模型裏我們將會看到1×11×1卷積層被當作保持高和寬維度形狀不變的全連接層使用。於是,我們可以通過調整網絡層之間的通道數來控制模型複雜度。
X = tf.random.uniform((3,3,3))
K = tf.random.uniform((2,3,1,1))
Y1 = corr2d_multi_in_out_1x1(X, K)
Y2 = corr2d_multi_in_out(X, K)
print('Y1',Y1)
print('Y2',Y2)
tf.norm(Y1-Y2) < 1e-6