我很想了解这个问题的一些见解 – 我尝试在文献中寻找解释,但毫无头绪。所以我正在构建一个神经网络(使用Keras)来解决一个回归问题。我有大约50万个样本,每个样本有2万个特征,并且试图预测一个数值输出。可以想象这是根据房屋、庭院等的一系列数值测量来预测房价。特征是按字母顺序排列的,因此它们的相邻特征几乎没有意义。
当我第一次尝试创建神经网络时,如果我提供了所有2万个特征,它会严重过拟合 – 手动将其减少到1000个特征大大提高了性能。
我读到1×1卷积神经网络被用于特征降维,但这些都是用于图像和2D输入的。
所以我构建了一个基本的神经网络,包含三层:
model = Sequential()model.add(Conv1D(128, kernel_size=1, activation="relu", input_shape=(n_features,1)))model.add(Flatten())model.add(Dense(100, activation='relu', kernel_initializer='he_uniform'))model.add(Dense(1, activation='linear'))
我还将训练集的输入从n_samples, n_features
重塑为:reshaped= X_train.reshape(n_samples, n_features, 1)
,以符合Conv1D的预期输入格式。
与普通的密集神经网络相反,这就像我手动选择了表现最佳的特征一样。我的问题是 – 为什么这有效?用密集层替换卷积层完全破坏了性能。这与特征降维有关,还是完全是其他原因?
我以为2D图像使用1×1卷积来减少图像的通道维度 – 但我只有一个通道使用1×1卷积,那么到底减少了什么?将我的1D卷积层过滤器设置为128,是否意味着我选择了128个特征,然后这些特征被 feeding到下一层?这些特征是基于损失反向传播选择的吗?
我很难想象我的特征信息发生了什么变化。
最后,如果我以后再添加另一层卷积层会怎样?如果我添加另一层1×1卷积层,有没有办法概念化会发生什么?这是进一步的特征子采样吗?
谢谢!
回答:
让我们用一个包含128个单元的Dense层来增强你的模型,并观察两个模型的摘要。
卷积模型
from tensorflow.keras.layers import *from tensorflow.keras.models import Model, Sequentialn_features = 1000 # 你的序列长度model = Sequential()model.add(Conv1D(128, kernel_size=1, activation="relu", input_shape=(n_features,1)))model.add(Flatten())model.add(Dense(100, activation='relu', kernel_initializer='he_uniform'))model.add(Dense(1, activation='linear'))model.summary()
Model: "sequential_1"_________________________________________________________________Layer (type) Output Shape Param # =================================================================conv1d_1 (Conv1D) (None, 1000, 128) 256 _________________________________________________________________flatten_1 (Flatten) (None, 128000) 0 _________________________________________________________________dense_8 (Dense) (None, 100) 12800100 _________________________________________________________________dense_9 (Dense) (None, 1) 101 =================================================================Total params: 12,800,457Trainable params: 12,800,457Non-trainable params: 0
全连接模型
from tensorflow.keras.layers import *from tensorflow.keras.models import Model, Sequentialn_features = 1000 # 你的序列长度model = Sequential()model.add(Dense(128, activation="relu", input_shape=(n_features,1)))model.add(Flatten())model.add(Dense(100, activation='relu', kernel_initializer='he_uniform'))model.add(Dense(1, activation='linear'))model.summary()
Model: "sequential_2"_________________________________________________________________Layer (type) Output Shape Param # =================================================================dense_10 (Dense) (None, 1000, 128) 256 _________________________________________________________________flatten_2 (Flatten) (None, 128000) 0 _________________________________________________________________dense_11 (Dense) (None, 100) 12800100 _________________________________________________________________dense_12 (Dense) (None, 1) 101 =================================================================Total params: 12,800,457Trainable params: 12,800,457Non-trainable params: 0_____________________________
如你所见,两个模型在每层的参数数量上是相同的。但它们本质上是完全不同的。
假设我们只有长度为4的输入。一个1×1卷积使用3个滤波器将在这4个输入上使用3个独立的核,每个核将一次操作一个输入元素,因为我们选择了kernel_size = 1。所以,每个核只是一个单一的标量值,它将与输入数组一个元素一个元素地相乘(将添加偏置)。这里的关键是1×1卷积只关注当前的输入,这意味着它没有任何空间自由度,它一次只关注当前的输入点。(这将对后面的解释有用)
现在,对于密集/全连接层,每个神经元都连接到每个输入,这意味着全连接层有完全的空间自由度,它可以查看所有地方。等效的卷积层将是kernel_size = 1000(实际的输入长度)。
那么,为什么1×1卷积可能表现得更好呢?
- 嗯,没有实际查看数据属性之前很难说。但一个猜测可能是你在使用没有空间依赖性的特征。
你随机选择了特征,并且可能混合了它们(一次查看许多输入特征并不会帮助,反而会学习到一些额外的噪声)。这可能是你使用卷积层(它一次只查看一个特征)而不是全连接层(它查看所有特征并混合它们)获得更好性能的原因。