如何在Keras中处理CNN的可变大小输入?

我正在尝试对MNIST数据库进行常规分类,但使用的是随机裁剪的数字。图像的裁剪方式如下:随机移除首行/末行和/或首列/末列。

我想使用Keras(以及Tensorflow后端)来构建卷积神经网络进行卷积操作,然后进行常规分类。

输入的大小是可变的,我无法使其正常工作。

以下是我裁剪数字的方式

import numpy as npfrom keras.utils import to_categoricalfrom sklearn.datasets import load_digitsdigits = load_digits()X = digits.imagesX = np.expand_dims(X, axis=3)X_crop = list()for index in range(len(X)):    X_crop.append(X[index, np.random.randint(0,2):np.random.randint(7,9), np.random.randint(0,2):np.random.randint(7,9), :])X_crop = np.array(X_crop)y = to_categorical(digits.target)from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X_crop, y, train_size=0.8, test_size=0.2)

以下是我想要使用的模型架构

from keras.layers import Dense, Dropoutfrom keras.layers.convolutional import Conv2Dfrom keras.models import Sequentialmodel = Sequential()model.add(Conv2D(filters=10,                  kernel_size=(3,3),                  input_shape=(None, None, 1),                  data_format='channels_last'))model.add(Dense(128, activation='relu'))model.add(Dropout(0.2))model.add(Dense(10, activation='softmax'))model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])model.summary()model.fit(X_train, y_train, epochs=100, batch_size=16, validation_data=(X_test, y_test))
  1. 有人知道如何在我的神经网络中处理可变大小输入吗?

  2. 以及如何进行分类?


回答:

TL/DR – 请直接跳到第4点

在我们进入正题之前,先让我们解决你网络中的一些问题:

  1. 你的网络因为激活函数而无法工作:使用categorical_crossentropy时,你需要使用softmax激活函数:

    model.add(Dense(10, activation='softmax'))
  2. 空间张量向量化:正如Daniel所说,你需要在某个阶段将你的向量从空间(图像)转换为向量化(向量)。当前,直接将Dense应用到Conv2D的输出上,相当于(1, 1)卷积。也就是说,你的网络输出是空间的,而不是向量化的,这会导致维度不匹配(你可以通过运行你的网络或检查model.summary()来验证这一点)。为了改变这一点,你需要使用GlobalMaxPooling2DGlobalAveragePooling2D。例如:

    model.add(Conv2D(filters=10,              kernel_size=(3, 3),              input_shape=(None, None, 1),             padding="same",             data_format='channels_last'))model.add(GlobalMaxPooling2D())model.add(Dense(128, activation='relu'))model.add(Dropout(0.2))model.add(Dense(10, activation='softmax'))
  3. 拼接的numpy数组需要具有相同的形状:如果你检查X_crop的形状,你会发现它不是一个空间矩阵。这是因为你拼接了形状不同的矩阵。不幸的是,无法克服这个问题,因为numpy.array需要具有固定的形状。

  4. 如何使你的网络训练不同形状的示例:要做到这一点,最重要的是要理解两件事。第一,在单个批次中,每张图像应具有相同的大小。第二,调用fit多次是个坏主意,因为这样会重置内部模型状态。所以需要做的是:

    a. 编写一个函数,用于裁剪单个批次 – 例如,一个get_cropped_batches_generator函数,该函数给定一个矩阵,从中裁剪出一个批次并随机裁剪它。

    b. 使用train_on_batch方法。以下是一个示例代码:

    from six import nextbatches_generator = get_cropped_batches_generator(X, batch_size=16)losses = list()for epoch_nb in range(nb_of_epochs):    epoch_losses = list()    for batch_nb in range(nb_of_batches):        # cropped_x在不同的批次中可能具有不同的形状(一般情况下)        cropped_x, cropped_y = next(batches_generator)         current_loss = model.train_on_batch(cropped_x, cropped_y)        epoch_losses.append(current_loss)    losses.append(epoch_losses.sum() / (1.0 * len(epoch_losses)))final_loss = losses.sum() / (1.0 * len(losses))

关于上述代码的一些评论:首先,train_on_batch不使用keras的进度条。它返回单个损失值(对于给定批次) – 这就是为什么我添加了计算损失的逻辑。你也可以使用Progbar回调来实现这一点。其次,你需要实现get_cropped_batches_generator – 我没有写代码以保持答案的清晰度。你可以提出另一个问题,询问如何实现它。最后,我使用six来保持Python 2Python 3之间的兼容性。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注