我尝试构建3D-Unet,以从卫星图像中学习空间和光谱特征,以进行多类分类。输入形状为(样本,图像高度,图像宽度,带,通道),而输出仅为2D图像和特定类别的概率的维数(“ categoical_crossentropy”)。
输入和输出形状:
x_train.shape
# (samples = 200, image_height= 512, image_width = 512, bands= 64, channels = 1)
y_train.shape
# (samples= 200, image_height = 512, image_width 512, classes = 12)
到目前为止,我使用Keras构建了一个简单的3D-Unet,它为我提供了4D特征向量,其中前3个维度包含3d特征,第四个维度包含12类的概率。
def conv_block3D(tensor, nfilters, size=3, padding='same', initializer="he_normal"):
x = Conv3D(filters=nfilters, kernel_size=(size, size,size), padding=padding)(tensor)
x = BatchNormalization()(x)
x = Activation("relu")(x)
x = Conv3D(filters=nfilters, kernel_size=(size, size,size), padding=padding)(x)
x = BatchNormalization()(x)
x = Activation("relu")(x)
return x
def deconv_block3D(tensor, residual, nfilters, size=3, padding='same', strides=(2, 2, 2)):
y = Conv3DTranspose(nfilters, kernel_size=(size, size,size), strides=strides, padding=padding)(tensor)
y = concatenate([y, residual], axis=4)
y = conv_block3D(y, nfilters)
return y
def Unet3D(img_height, img_width,bands, nclasses=12, filters=64):
input_layer = Input(shape=(img_height, img_width,bands,1), name='image_input')
conv1 = conv_block3D(input_layer, nfilters=filters)
conv1_out = MaxPooling3D(pool_size=(2, 2, 2))(conv1)
conv2 = conv_block3D(conv1_out, nfilters=filters*2)
conv2_out = MaxPooling3D(pool_size=(2, 2, 2))(conv2)
conv3 = conv_block3D(conv2_out, nfilters=filters*4)
conv3_out = MaxPooling3D(pool_size=(2, 2, 2))(conv3)
conv4 = conv_block3D(conv3_out, nfilters=filters*8)
conv4_out = MaxPooling3D(pool_size=(2, 2, 2))(conv4)
conv4_out = Dropout(0.5)(conv4_out)
conv5 = conv_block3D(conv4_out, nfilters=filters*16)
conv5 = Dropout(0.5)(conv5)
deconv6 = deconv_block3D(conv5, residual=conv4, nfilters=filters*8)
deconv6 = Dropout(0.5)(deconv6)
deconv7 = deconv_block3D(deconv6, residual=conv3, nfilters=filters*4)
deconv7 = Dropout(0.5)(deconv7)
deconv8 = deconv_block3D(deconv7, residual=conv2, nfilters=filters*2)
deconv8 = Dropout(0.5)(deconv8)
deconv9 = deconv_block3D(deconv8, residual=conv1, nfilters=filters)
conv10 = Conv3D(filters=nclasses, kernel_size=(1, 1, 1), padding='same')(deconv9)
conv10 = BatchNormalization()(conv10)
output = Activation("relu")(conv10)
model = Model(inputs=input_layer, outputs=output, name='Unet')
model.compile(optimizer = optimizers.Adam(lr = 1e-5), loss = 'categorical_crossentropy', metrics = ['accuracy'])
return model
现在输出为(512,512,64,12)。我想要的形状为(512,512,12)。
我已经尝试在第三维上使用“平均池”并重塑数据,但是Unet没有学到任何东西:
average = AveragePooling3D(pool_size=(1, 1, 64), padding='same')(conv10)
output = Reshape((img_height, img_width, nclasses), input_shape=(average.shape))(average)
output = Conv2D(filters=nclasses, kernel_size=(1, 1))(output)
output = BatchNormalization()(output)
output = Activation('softmax')(output)
model = Model(inputs=input_layer, outputs=output, name='Unet')
model.compile(optimizer = optimizers.Adam(lr = 1e-5), loss = 'categorical_crossentropy', metrics = ['accuracy'])
return model
有什么想法吗?