【发布时间】:2019-01-22 00:30:23
【问题描述】:
我的直接问题是,我尝试过的所有各种 CNN 回归模型总是返回相同(或非常相似)的值,我正试图找出原因。但我愿意接受广泛的建议。
我的数据集如下所示:
-
x: 64x64 灰度图像排列成 64 x 64 x n ndarray -
y: 0 到 1 之间的值,每个对应一个图像(可以将其视为某种比例) -
weather:每张照片拍摄时的 4 个天气读数(环境温度、湿度、露点、气压)
目标是使用图像和天气数据来预测y。由于我正在处理图像,因此我认为 CNN 是合适的(如果这里有其他策略,请告诉我)。
据我了解,CNN 最常用于分类任务——将它们用于回归是相当不寻常的。但从理论上讲,它应该不会有太大的不同——我只需要将损失函数更改为 MSE/RMSE 并将最后一个激活函数更改为线性(尽管这里可能使用 sigmoid 更合适,因为y 介于 0 和 1 之间)。
我遇到的第一个障碍是试图弄清楚如何合并天气数据,自然的选择是将它们合并到第一个全连接层中。我在这里找到了一个例子:How to train mix of image and data in CNN using ImageAugmentation in TFlearn
我遇到的第二个障碍是确定架构。通常我会选择一篇论文并复制它的架构,但我在 CNN 图像回归上找不到任何东西。所以我尝试了一个(相当简单的)具有 3 个卷积层和 2 个全连接层的网络,然后我尝试了 https://github.com/tflearn/tflearn/tree/master/examples 的 VGGNet 和 AlexNet 架构
现在我遇到的问题是我尝试的所有模型都输出相同的值,即训练集的平均值 y。看看张量板,损失函数很快就变平了(大约 25 个 epoch 之后)。你知道这里发生了什么吗?虽然我确实了解每一层的基本功能,但对于特定数据集或任务的良好架构,我没有直觉。
这是一个例子。我正在使用 tflearn 示例页面中的 VGGNet:
tf.reset_default_graph()
img_aug = ImageAugmentation()
img_aug.add_random_flip_leftright()
img_aug.add_random_flip_updown()
img_aug.add_random_90degrees_rotation(rotations=[0, 1, 2, 3])
convnet = input_data(shape=[None, size, size, 1],
data_augmentation=img_aug,
name='hive')
weathernet = input_data(shape=[None, 4], name='weather')
convnet = conv_2d(convnet, 64, 3, activation='relu', scope='conv1_1')
convnet = conv_2d(convnet, 64, 3, activation='relu', scope='conv1_2')
convnet = max_pool_2d(convnet, 2, strides=2, name='maxpool1')
convnet = conv_2d(convnet, 128, 3, activation='relu', scope='conv2_1')
convnet = conv_2d(convnet, 128, 3, activation='relu', scope='conv2_2')
convnet = max_pool_2d(convnet, 2, strides=2, name='maxpool2')
convnet = conv_2d(convnet, 256, 3, activation='relu', scope='conv3_1')
convnet = conv_2d(convnet, 256, 3, activation='relu', scope='conv3_2')
convnet = conv_2d(convnet, 256, 3, activation='relu', scope='conv3_3')
convnet = max_pool_2d(convnet, 2, strides=2, name='maxpool3')
convnet = conv_2d(convnet, 512, 3, activation='relu', scope='conv4_1')
convnet = conv_2d(convnet, 512, 3, activation='relu', scope='conv4_2')
convnet = conv_2d(convnet, 512, 3, activation='relu', scope='conv4_3')
convnet = max_pool_2d(convnet, 2, strides=2, name='maxpool4')
convnet = conv_2d(convnet, 512, 3, activation='relu', scope='conv5_1')
convnet = conv_2d(convnet, 512, 3, activation='relu', scope='conv5_2')
convnet = conv_2d(convnet, 512, 3, activation='relu', scope='conv5_3')
convnet = max_pool_2d(convnet, 2, strides=2, name='maxpool5')
convnet = fully_connected(convnet, 4096, activation='relu', scope='fc6')
convnet = merge([convnet, weathernet], 'concat')
convnet = dropout(convnet, .75, name='dropout1')
convnet = fully_connected(convnet, 4096, activation='relu', scope='fc7')
convnet = dropout(convnet, .75, name='dropout2')
convnet = fully_connected(convnet, 1, activation='sigmoid', scope='fc8')
convnet = regression(convnet,
optimizer='adam',
learning_rate=learning_rate,
loss='mean_square',
name='targets')
model = tflearn.DNN(convnet,
tensorboard_dir='log',
tensorboard_verbose=0)
model.fit({
'hive': x_train,
'weather': weather_train
},
{'targets': y_train},
n_epoch=1000,
batch_size=batch_size,
validation_set=({
'hive': x_val,
'weather': weather_val
},
{'targets': y_val}),
show_metric=False,
shuffle=True,
run_id='poop')
要了解我的对象是什么:
-
x_train是形状为(n, 64, 64, 1)的 ndarray -
weather_train是形状为(n, 4)的 ndarray -
y_train是形状为(n, 1)的 ndarray
过度拟合是另一个问题,但鉴于模型在训练集上的表现不佳,我想我以后可以担心。
【问题讨论】:
-
你最后一个全连接层设置
sigmoid作为它的激活函数。这通常仅在您想要执行分类时使用。我会尝试其他激活功能,例如relu。 -
是的,我正在尝试
sigmoid、linear和relu作为最后一个全连接层。我知道linear最常见于回归任务,但由于响应永远不会是负面的,我认为relu也可以工作,并且由于响应始终在 0 和 1 之间,sigmoid似乎也有点合适。 -
您找到解决问题的方法了吗?我对答案很感兴趣
标签: tensorflow regression conv-neural-network tflearn