Python 基于keras的Mnist识别

Python 基于keras的Mnist识别,python,machine-learning,deep-learning,keras,mnist,Python,Machine Learning,Deep Learning,Keras,Mnist,如何训练模型识别一张图片中的五个数字。 代码如下: from keras.layers import Conv2D from keras.layers import MaxPooling2D from keras.layers import Flatten from keras.layers import Dropout, Dense, Input from keras.models import Model, Sequential model = Sequential() model.add

如何训练模型识别一张图片中的五个数字。 代码如下:

from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dropout, Dense, Input
from keras.models import Model, Sequential

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
             activation='relu',
             input_shape=(28, 140, 1)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dropout(0.5))
这里应该有一个识别图片中每个数字的循环,但我不知道如何实现它

model.add(Dense(11, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
          optimizer=keras.optimizers.Adadelta(),
          metrics=['accuracy'])

model.fit(X_train, y_train,
      batch_size=1000,
      epochs=8,
      verbose=1,
      validation_data=(X_valid, y_valid))
组合mnist编号的图片如下:

from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dropout, Dense, Input
from keras.models import Model, Sequential

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
             activation='relu',
             input_shape=(28, 140, 1)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dropout(0.5))

既然您已经有了一个性能非常好的映像,那么您所要做的就是扩展模型中的类的数量

您可以使用5乘以11的类,而不是仅使用11个类

前11个类标识第一个数字,后11个类标识第二个数字,依此类推。总共55个等级,图像中每个位置11个等级

因此,简言之:

  • X_training将是整个图像,如您在链接中所示,形状为
    (28140)
    ,或
    (140,28)
    ,具体取决于加载图像的方法
  • Y_训练将是一个55元素向量,形状
    (55,)
    ,告诉每个象限中有哪些数字
示例:对于第一幅图像,使用9,7,5,4,10,您将创建
Y_training
,其中以下位置包含值1:

  • Y_培训[9]=1
  • Y\u培训[18]=1(18=7+11)
  • Y#u培训[27]=1#(27=5+22)
  • Y\u培训[37]=1(37=4+33)
  • Y\u培训[54]=1(54=10+44)
按照您想要的方式创建模型层,与常规MNIST模型几乎相同,这意味着:无需尝试循环或类似的操作

但它可能需要比以前大一点

你将不能再使用分类的交叉熵,因为你将有5个正确的类而不是1个。如果您最后使用的是“sigmoid”激活,
binary\u crossentropy
应该是一个很好的替代品


确保最后一层适合55元素向量,例如
densite(55)

我建议两种可能的方法:

案例1-图像结构良好。

在您提供的示例中,情况确实如此,因此如果您的数据与您提供的链接中的数据相似,我将建议使用这种方法

在您提供的链接中,每个图像基本上由5个28×28像素图像叠加在一起组成。在这种情况下,我建议剪切图像(也就是说,将每个图像剪切成5块),并使用通常的MNIST数据(例如,使用您提供的代码)训练您的模型。然后,当您想应用模型对新数据进行分类时,只需将每个新图像切割成5块。使用您的模型对这5个部件中的每一个进行分类,然后将这5个数字作为输出写在另一个旁边

关于这句话:

这里应该有一个识别图片中每个数字的循环,但是 我不知道如何去实现它

对于循环,不需要
。把你的数字剪下来

案例2-图像结构不好。

在这种情况下,每个图像都标有5个数字。因此,
y_列
y_有效
)中的每一行将是一个0,1向量,包含55个条目。 前11个条目是第一个数字的一个热编码,第二11个条目是第二个数字的一个热编码,依此类推。因此,
y_train
中的每一行将有5个条目等于1,其余条目等于0

此外,使用sigmoid激活函数和“二进制交叉熵”损失,而不是在输出层使用softmax激活和
分类交叉熵

总而言之,请替换以下内容:

model.add(Dense(11, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
          optimizer=keras.optimizers.Adadelta(),
          metrics=['accuracy'])
为此:

model.add(Dense(55, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
          optimizer=keras.optimizers.Adadelta())

这个问题在90年代由Yann LeCun解决。你可以在他的网站上找到演示和文件

一个不太通用的解决方案是在单个数字MNIST上训练CNN,并使用此CNN对您提供的图像进行推断。预测是通过在多数字图像上滑动经过训练的CNN并应用后处理来聚合结果,并可能估计边界框来完成的

一个非常通用的解决方案是建立一个模型,该模型能够预测数字的边界框并对其进行分类,该解决方案可以处理数量可变、比例和位置不同的数字。最近,R-CNN、Fast RCNN和


您可以在

上找到更快RCNN的python实现,这方面的经典工作是

Keras模型(功能性,非顺序性):

PS
您可以使用11个类来表示10位数字和空格。

总结一下,基本上有两种解决此问题的方法。使用类似opencv的东西对图像进行预处理,以提取出您想要识别的数字,然后运行标准的单位数CNN,或者使用如下所述的某种类型的CNN执行整个操作:蛮力CNN(对多个数字进行训练)、RNN等。如果图像的格式是可预测的,则opencv是一个不错的选择,现在,这是我选择的路线,现在!所有的答案都很有帮助,这似乎是最接近原始问题的答案,也是我为什么在这里奖励奖金的原因。