我正在尝试理解神经网络架构的工作原理。我读了一些文档,但对输入/输出形状感到困惑。
在我的例子中,我试图做以下事情。假设我的输入始终是(20, 15, 15)的形状。其中包含一个深度为20的矩阵,每个输入有15行x 15列。基本上,每个批次中的每个输入都是一个3D输入。我希望输出的深度为6的矩阵,每个矩阵有15行x 15列,这也是一个3D输出。
链接中的问题/答案对他想要的来说是有意义的,但我似乎无法让它对我想要的起作用。当然,神经网络可以比下面的例子更深,但我现在只是试图理解逻辑。
from keras.models import Sequentialfrom keras.layers import Dense, LSTM, Conv1D, Conv2D, Conv3Dfrom keras.optimizers import Adamclass Model2(): def __init__(self): self.learning_rate = 0.001 self.build_model() def build_model(self): self.model = Sequential() self.model.add(Conv2D(12, kernel_size=3, activation='relu', padding='same', input_shape=(15, 15, 20))) self.model.add(Conv2D(10, kernel_size=3, activation='relu', padding='same')) self.model.add(Dense((6), activation='softmax')) self.model.compile(loss='mse', optimizer=Adam(lr=self.learning_rate))a = Model2()a.model.summary()
输出:
Model: "sequential_1"_________________________________________________________________Layer (type) Output Shape Param # =================================================================conv2d_1 (Conv2D) (None, 15, 15, 12) 2172 _________________________________________________________________conv2d_2 (Conv2D) (None, 15, 15, 10) 1090 _________________________________________________________________dense_1 (Dense) (None, 15, 15, 6) 66 =================================================================Total params: 3,328Trainable params: 3,328Non-trainable params: 0_________________________________________________________________
看起来是合理的。我假设输出的形状是(批次大小, x(列), y(行), z(深度)) 分别对应四个数字。这样就能得到我想要的结果。
但从上面链接的问题来看,由于输出形状的顺序让我感到困惑。
从上面的链接来看,他的conv1d解决方案是:
class Model1(): def __init__(self): self.learning_rate = 0.001 self.build_model() def build_model(self): self.model = Sequential() self.model.add(Conv1D(64, kernel_size=3, activation='relu', padding='same', input_shape=(1287, 69))) self.model.add(Conv1D(32, kernel_size=3, activation='relu', padding='same')) self.model.add(Dense((8), activation='softmax')) self.model.compile(loss='mse', optimizer=Adam(lr=self.learning_rate))a = Model1()a.model.summary()
输出:
Model: "sequential_1"_________________________________________________________________Layer (type) Output Shape Param # =================================================================conv1d_1 (Conv1D) (None, 1287, 64) 13312 _________________________________________________________________conv1d_2 (Conv1D) (None, 1287, 32) 6176 _________________________________________________________________dense_1 (Dense) (None, 1287, 8) 264 =================================================================Total params: 19,752Trainable params: 19,752Non-trainable params: 0_________________________________________________________________
在他的例子中,他最初的输入是1287行,69列。他的预期输出是1287行和8列。
简而言之,如果四个数字的输出形状是(批次,x,y,z),那么三个数字的输出形状是(批次,y,x)吗?假设x是列,y是行,z是深度。这是准确的吗?看起来很 confusing…
当我将input_shape改为(20,15,15)而不是(15,15,20)时,我的输出会非常不同:
Model: "sequential_1"_________________________________________________________________Layer (type) Output Shape Param # =================================================================conv2d_1 (Conv2D) (None, 20, 15, 12) 1632 _________________________________________________________________conv2d_2 (Conv2D) (None, 20, 15, 10) 1090 _________________________________________________________________dense_1 (Dense) (None, 20, 15, 6) 66 =================================================================Total params: 2,788Trainable params: 2,788Non-trainable params: 0
输入形状的顺序是x, y, z的什么?是input_shape(x, y, z)吗?还是(z, y, x),就像numpy数组的顺序一样。还有,当输出形状是3维/4维时,顺序是什么?(Batch, z, y, x)?
回答:
在卷积层的输出形状中,第一个维度是批次,最后一个维度总是深度。因此,对于2D卷积,输出形状将是(batch,y,x,z),对于1D卷积,输出形状将是(batch,x,z)。
输出的深度总是等于该层的卷积核数量。对于全连接层,输出的深度也等于层单元的数量。
卷积核在空间维度(x,y)上“移动”,不同卷积核的结果被放置在输出的不同z层上。
换句话说,如果你有一个卷积层Conv2D(kernels,padding='same')
,并且你将(batch,y,x,z)作为输入数据传递给它,输出形状将是(batch,y,x,kernels)。