网格的小节作为cnn

时间:2018-08-02 11:49:36

标签: tensorflow machine-learning keras conv-neural-network

我有两个巨大的网格(输入和输出),它们代表相同区域的一些空间数据。我希望能够通过在感兴趣的像素周围为神经网络提供一小部分输入网格,从而逐像素生成输出。

在CNN上进行训练和评估的天真的方法是分别提取节,并将其赋予fit()函数。但是如果CNN运行在子网格上,例如输入的256×256区域,那么我将每个时期复制每个数据点65536(!!!)次。

那么有什么办法让karas仅仅使用更大数据结构的子部分作为训练?

对我来说,这听起来像是在数据序列的序列部分上训练RNN,而不是分别复制每个部分。

性能考虑主要是在评估模型的情况下。我想使用此模型来生成具有12.5 cm分辨率的巨大地理区域(丹麦)的输出网格

2 个答案:

答案 0 :(得分:2)

在我看来,您正在寻找fully convolutional network(FCN)。

通过仅使用尺寸随输入缩放的图层(特别是禁止使用密集的图层),FCN能够生成空间范围与输入范围成比例增长的输出-通常,输出具有与您的情况相同的分辨率。

如果输入很大,您仍然可以在子图像上训练FCN。然后进行推断,您可以

  • 在整个图像上运行网络:的确,有时输入太大而无法在训练过程中一起添加,但是可以单独输入以进行推断。
  • 或将输入分成子图像,然后将结果平铺。在那种情况下,我可能会使用重叠的图块来避免潜在的边框效果。

答案 1 :(得分:0)

您可能可以使用Sequence生成器。

您仍然必须为每个批次创建切片,但是与CNN操作相比,获取切片一点也不慢。

通过使用keras.utils.Sequence,批次的生成与模型的执行是并行的,因此不会受到任何惩罚:

class GridGenerator(keras.utils.Sequence):
    def __init__(self, originalGrid_maybeFileName, outputGrid, subGridSize):
        self.originalGrid = originalGrid_maybeFileName 
        self.outputGrid = outputGrid

        self.subgridSize = subgridSize

    def __len__(self):

        #naive implementation, if grids are squares and the sizes are multiples of each other
        self.divs = self.originalGrid.shape[:,:,1] // self.subgridSize

        return self.divs * self.divs

    def __getitem__(self,i):

        row, column = divmod(i, self.divs)

        #using channels_last
        x= self.originalGrid[:,row:row+self.subgridSize, column:column+self.subgridSize]
        y= self.outputGrid[:,row:row+self.subgridSize, column:column+self.subgridSize]

        return x,y

如果整个网格都不适合您PC的内存,则应该找到一次加载部分网格的方法。 (使用发电机加载这些零件)

创建生成器并使用fit_generator进行训练:

generator = GridGenerator(xGrid, yGrid, subSize)

#you can create additional generators to take a part of that as training and another part as validation

model.fit_generator(generator, len(generator), ...., workers = 4)

workers参数确定在发送到模型之前将并行加载多少个批次。