Python机器学习数字识别

我正在按照这个网站上的代码进行学习:

https://blog.luisfred.com.br/reconhecimento-de-escrita-manual-com-redes-neurais-convolucionais/

以下是网站上逐步讲解的代码:

from keras. datasets import mnistfrom keras. models import Sequentialfrom keras. layers import Densefrom keras. layers import Dropoutfrom keras. layers import Flattenimport numpy as npfrom matplotlib import pyplot as pltfrom keras. layers . convolutional import Conv2Dfrom keras. layers . convolutional import MaxPooling2Dfrom keras. utils import np_utilsfrom keras import backend as KK . set_image_dim_ordering ( 'th' )import cv2import matplotlib. pyplot as plt#% inline matplotlib # 如果你在使用Jupyter,这对在单元格内绘制图形或图表会很有用#将数据分为训练和测试子集( X_train , y_train ) , ( X_test , y_test ) = mnist. load_data ( )# 因为我们在处理灰度图,所以可以# 将深度设置为值1X_train = X_train . reshape ( X_train . shape [ 0 ] , 1 , 28 , 28 ) . astype ( 'float32' )X_test = X_test . reshape ( X_test . shape [ 0 ] , 1 , 28 , 28 ) . astype ( 'float32' )# 我们根据# 灰度图对数据进行归一化。浮点值在范围[0,1]内,而不是[.255]X_train = X_train / 255X_test = X_test / 255# 将y_train和y_test转换为二进制类别数组(one-hot向量),它们是类别向量y_train = np_utils. to_categorical ( y_train )y_test = np_utils. to_categorical ( y_test )# MNIST中发现的数字类型数量。在这种情况下,值为10,对应于(0,1,2,3,4,5,6,7,8,9)。num_classes = y_test. shape [ 1 ]def deeper_cnn_model ( ) :    model = Sequential ( )    # Convolution2D将是我们的输入层。我们可以观察到它具有    # 30个特征图,大小为5×5,激活函数类型为ReLU。    model.add ( Conv2D ( 30 , ( 5 , 5 ) , input_shape = ( 1 , 28 , 28 ) , activation = 'relu' ) )    # MaxPooling2D层将是我们的第二层,我们将有一个2x2大小的采样窗口    model.add ( MaxPooling2D ( pool_size = ( 2 , 2 ) ) )    # 一个新的卷积层,具有15个大小为3×3的特征图,激活函数为ReLU    model.add ( Conv2D ( 15 , ( 3 , 3 ) , activation = 'relu' ) )    # 一个新的2x2维度的子采样    model.add ( MaxPooling2D ( pool_size = ( 2 , 2 ) ) )    # 我们包含一个20%的概率的dropout(你可以尝试其他值)    model.add ( Dropout ( 0.2 ) )    # 我们需要转换卷积层的输出,以便它可以作为下一个密集连接层的输入。    # 这做的就是“展平/flatten”卷积层的输出的结构,创建一个单一的长特征向量    # 供Fully Connected层使用。    model.add ( Flatten ( ) )    # 具有128个神经元的全连接层。    model.add ( Dense ( 128 , activation = 'relu' ) )    # 接着是一个新的具有64个神经元的全连接层    model.add ( Dense ( 64 , activation = 'relu' ) )    # 接着是一个新的具有32个神经元的全连接层    model.add ( Dense ( 32 , activation = 'relu' ) )    # 输出层具有与    # 要获得的类别数量兼容的神经元数量。请注意我们使用的是softmax激活函数,    model.add ( Dense ( num_classes, activation = 'softmax' , name = 'preds' ) )    # 配置神经网络的整个训练过程    model.compile ( loss = 'categorical_crossentropy' , optimizer = 'adam' , metrics = [ 'accuracy' ] )    return modelmodel = deeper_cnn_model ( )model.summary ( )model.fit ( X_train , y_train, validation_data = ( X_test , y_test ) , epochs = 10 , batch_size = 200 )scores = model. evaluate ( X_test , y_test, verbose = 0 )print ( "\ nacc:% .2f %%" % (scores [1] * 100))###在训练完成后增强以检查多个数字img_pred = cv2. imread ( 'five.JPG' ,   0 )plt.imshow(img_pred, cmap='gray')# 强制图像具有与训练数据相同的输入尺寸(28x28)if img_pred. shape != [ 28 , 28 ] :    img2 = cv2. resize ( img_pred, ( 28 , 28 ) )    img_pred = img2. reshape ( 28 , 28 , - 1 ) ;else :    img_pred = img_pred. reshape ( 28 , 28 , - 1 ) ;# 这里我们也告知深度的值为1,行数和列数,对应于图像的28x28。img_pred = img_pred. reshape ( 1 , 1 , 28 , 28 )pred = model. predict_classes ( img_pred )pred_proba = model. predict_proba ( img_pred )pred_proba = "% .2f %%" % (pred_proba [0] [pred] * 100)print ( pred [ 0 ] , "的概率为" , pred_proba )

在最后,我尝试对自己绘制并导入的数字五进行预测(我也尝试了其他手绘数字,结果同样不理想):

img_pred = cv2. imread ( 'five.JPG' ,   0 )plt.imshow(img_pred, cmap='gray')# 强制图像具有与训练数据相同的输入尺寸(28x28)if img_pred. shape != [ 28 , 28 ] :    img2 = cv2. resize ( img_pred, ( 28 , 28 ) )    img_pred = img2. reshape ( 28 , 28 , - 1 ) ;else :    img_pred = img_pred. reshape ( 28 , 28 , - 1 ) ;# 这里我们也告知深度的值为1,行数和列数,对应于图像的28x28。img_pred = img_pred. reshape ( 1 , 1 , 28 , 28 )pred = model. predict_classes ( img_pred )pred_proba = model. predict_proba ( img_pred )pred_proba = "% .2f %%" % (pred_proba [0] [pred] * 100)print ( pred [ 0 ] , "的概率为" , pred_proba )

这是five.jpg的外观:

手绘数字五的图像

但是当我输入自己的数字时,模型预测错误。你认为这可能是什么原因?我承认我对机器学习是新手,刚刚开始尝试。我的想法是可能是图像的居中或图像的归一化有问题?任何帮助都非常感激!

编辑1:

MNIST测试数字看起来像这样:

白色的数字黑色背景


回答:

看起来你有两个问题,正如你所怀疑的,这些问题与数据的预处理有关。

第一个问题是你的图像相对于训练数据是颠倒的:

  • 在用img_pred = cv2. imread ( 'five.JPG' , 0 )读取你的.jpg的一个通道后,背景像素接近白色,值在215-238附近。
  • 如果你查看X_train中的训练数据,背景像素全部为零,数字为白色或接近白色(上限210-255)。

尝试将你的图像与X_train中的一些选择并排绘制,你会发现它们是颠倒的。

另一个问题是cv2.resize()中的默认插值不保留数据的缩放。在你调整数据大小后,最小值跳到60,而不是0。比较调整尺寸前后的img.pred.min()img.pred.max()的值。

你可以使用以下函数来颠倒并缩放你的数据,使其看起来更像MNIST输入数据:

 def mnist_bytescale(image):    # 使用float进行重新缩放    img_temp = image.astype(np.float32)    # 重新归零数据    img_temp -= img_temp.min()    # 重新缩放并颠倒    img_temp /= (img_temp.max()-img_temp.min())    img_temp *= 255    return 255 - img_temp.astype('uint')

这将翻转你的数据,并线性缩放到0到255之间,就像网络训练的数据一样。然而,如果你绘制mnist_bytescale(img_pred),你会注意到大多数像素的背景水平仍然不是完全0,因为你原始图像的背景水平不是恒定的(可能是由于JPEG压缩)。如果你的网络仍然对这些翻转和缩放的数据有问题,你可以尝试使用np.clip将背景水平置零,看看是否有帮助。

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中创建了一个多类分类项目。该项目可以对…

发表回复

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