我们能用keras + numpy + opencv做什么?
在本文中,我将向您展示使用out-of-the-box的python库构建深度学习项目的可能性。
数据
MNIST是一个广为人知且使用的数据集:手写数字的图像。这个数据集,以及CIFAR等其他数据集,经常被用作测试深度学习中各种基准。
from keras.datasets import mnist (x_train, y_train), (x_test, y_test) = mnist.load_data()
只要有一点创造力和适当的库,我们可以从MNIST中创建完全不同的数据集。让我们从训练数据中抽取9个随机观察结果并将它们连接起来。
seq_length = 9 random_chars = np.random.randint(0, len(x_train)-1, seq_length) image_seq = np.concatenate([x_train[j] for j in random_chars], axis=1) seq_label = np.array([y_train[j] for j in random_chars])
您可能已经猜到我们对之前的代码做了什么,但只是为了确保这里的可视化。
plt.imshow(image_seq)
使用MNIST随机生成序列
现在我们知道如何生成随机MNIST观测序列的图像。
建造模型
当然我们应该用适当的结构处理这两种类型的数据。
def build_Model(num_classes, seq_lenght, input_shape=(28, 252, 1)): inputs = Input(name='x', shape=input_shape, dtype='float32') conv1 = Conv2D(seq_lenght, (3, 3), padding='same', name='conv1', kernel_initializer='he_normal')(inputs) conv1 = Activation('relu')(conv1) conv1 = MaxPooling2D(pool_size=(2, 2), name='max1')(conv1) dims = conv1.get_shape() reshape = Reshape(target_shape=(seq_lenght, int(dims[1]*dims[2])), name='reshape')(conv1) reshape = Dense(128, activation='relu', kernel_initializer='he_normal', name='dense2')(reshape) lstm_1 = LSTM(32, return_sequences=True, kernel_initializer='he_normal', name='lstm1')(reshape) lstm_2 = LSTM(32, return_sequences=True, kernel_initializer='he_normal', name='lstm2')(lstm_1) y_pred = Dense(num_classes, activation='softmax', kernel_initializer='he_normal',name='output')(lstm_2) model = Model(inputs=inputs, outputs=y_pred) model.compile(Adam(lr=0.001), 'categorical_crossentropy', metrics=['accuracy']) return model
Conv + LSTM模型
在使用适当的训练和验证集进行一些训练后,我们可以得到了一个能对图像中数字进行高准确率描述的模型。这是模型在一张看不见的图片上的说明。
完全准确预测序列
预测序列中的一个错误
该模型具有两种核心类型的层:2D-Convolutions和LSTM。这两个是当前深度学习架构最重要的层,可解决大多数计算机视觉和NLP问题。
关于如何合并卷积层和LSTM层的技巧。
关于这个模型需要注意的一些重要细节包括得到正确的张量维度、如何对其进行整形以及如何使用LSTMs处理序列。
1、正确地重新形成卷积的张量是至关重要的,以便LSTM可以使用它。请注意我们如何设置最后一个卷积中的过滤器数量以匹配序列长度。一旦我们完成了这个,我们需要将我们产生的张量重塑为一个表示序列的张量,以便LSTM层可以正确使用它。
conv1 = Conv2D(seq_lenght, (3, 3), padding='same', name='conv1', kernel_initializer='he_normal')(inputs) … dims = conv1.get_shape() reshape = Reshape(target_shape=(seq_lenght, int(dims[1]*dims[2])), name='reshape')(conv1)
2、还要注意我们设置参数`return_sequence = True`。在第一个LSTM层中,我们这样做是因为我们想要堆叠处理序列的另一个层,而在第二个层中也是如此,因为我们希望将完整序列作为预测。
lstm_1 = LSTM(32, return_sequences=True, kernel_initializer='he_normal', name='lstm1')(reshape) lstm_2 = LSTM(32, return_sequences=True, kernel_initializer='he_normal', name='lstm2')(lstm_1)
3、最后,我们使用标准方法来获得类预测:Softmax层。因为Keras的Softmax实现只允许2D和3D张量,忽略批量维度,所以沿着模型处理张量形状是至关重要的。
y_pred = Dense(num_classes, activation='softmax', kernel_initializer='he_normal',name='output')(lstm_2)
我们可以看到,该模型仍有改进的空间,通过继续训练并监控验证损失以避免过度拟合,这样做很容易。
(试图)得到真实的
实际上,这个数据集很容易建模,并且可能通过更大的模型和更多的训练可以达到100%的准确度。然而,现实世界中的数据很可能更乱,更复杂。如果您将照片作为数据处理,则可能会发现数据模糊或其他复杂情况。我们可以模仿使用OpenCV。考虑一种新的,随机的生成数据的方法来训练模型。
seq_length = 9 random_chars = np.random.randint(0, len(x_train)-1, seq_length) image_seq = [] for j in random_chars: if np.random.random(1) >= 0.5: image_seq.append(cv2.medianBlur(x_train[j], 5)) else: image_seq.append(x_train[j]) image_seq = np.concatenate(image_seq, axis=1)
模糊生成序列的示例
OpenCV有几种模糊数据的方法,我们在这个例子中只考虑一种。
通过这种生成序列的新方法,我们使用“更真实”的数据训练另一个模型。经过13个周期的训练之后,我们获得了一个模型,该模型在非模糊验证数据集上具有约94%的准确度,在模糊验证数据集上具有约91%的准确度。尽管数据非常复杂,该模型仍然可以产生高性能指标。
模糊生成序列的预测
为什么这有用?
这显然是一个有趣的项目。尽管如此,这是一个非常好的练习,可以磨练你的编程,计算机视觉和深度学习技能,特别是考虑到它使用的数据集和工具是开源的,但实际上还有更多。
通过前面的例子,我们可以训练一个复杂的神经网络来检测序列的边缘和形状。通过更多的数据和训练周期,就可以使用此模型作为基础,使用转移学习来构建一个标注自定义数据的模型。
================================================================= Total params: 78,519 Trainable params: 78,069 Non-trainable params: 450
关于实验的最后想法
有许多方法可以利用开源数据集和工具。这只是几行代码和创造力可以做到的一个例子。