📜  Python的手写方程求解器

📅  最后修改于: 2021-10-23 08:02:29             🧑  作者: Mango

获取训练数据

  • 下载数据集
      从此链接下载数据集。解压缩 zip 文件。将有不同的文件夹包含不同数学符号的图像。为简单起见,在我们的方程求解器中使用 0-9 位数字、+、?-? 和时间图像。在观察数据集时,我们可以看到它对某些数字/符号有偏见,因为它包含 12000 张图像用于某些符号,而其他图像包含 3000 张图像。要消除这种偏差,请将每个文件夹中的图像数量减少到大约。 4000。
  • 提取特征
      我们可以使用轮廓提取来获取特征。
    1. 反转图像,然后将其转换为二值图像,因为当对象为白色,周围为黑色时,轮廓提取的效果最佳。
    2. 要查找轮廓,请使用“findContour”函数。对于特征,使用’boundingRect’函数获取轮廓的边界矩形(边界矩形是包围整个轮廓的最小水平矩形)。
    3. 由于我们数据集中的每个图像只包含一个符号/数字,我们只需要最大尺寸的边界矩形。为此,我们计算每个轮廓的边界矩形的面积并选择面积最大的矩形。
    4. 现在,将最大区域边界矩形的大小调整为 28 x 28。将其重新整形为 784 x 1。因此现在将有 784 像素值或特征。现在,给它相应的标签(例如,对于 0-9 个图像,为其数字分配相同的标签,对于 – 分配标签 10,对于 + 分配标签 11,对于时间分配标签 12)。所以现在我们的数据集包含 784 个特征列和一个标签列。提取特征后,将数据保存为 CSV 文件。

    使用卷积神经网络训练数据

      由于卷积神经网络适用于二维数据,而我们的数据集是 785 × 1 的形式。因此,我们需要对其进行整形。首先,将我们数据集中的标签列分配给变量 y_train。然后从数据集中删除标签列,然后将数据集重塑为 28 x 28。现在,我们的数据集已准备好用于 CNN。
  • 构建卷积神经网络
      为了制作 CNN,导入所有必要的库。
    import pandas as pd
    import numpy as np
    import pickle
    np.random.seed(1212)
    import keras
    from keras.models import Model
    from keras.layers import * from keras import optimizers
    from keras.layers import Input, Dense
    from keras.models import Sequential
    from keras.layers import Dense
    from keras.layers import Dropout
    from keras.layers import Flatten
    from keras.layers.convolutional import Conv2D
    from keras.layers.convolutional import MaxPooling2D
    from keras.utils import np_utils
    from keras import backend as K
    K.set_image_dim_ordering('th')
    from keras.utils.np_utils import to_categorical
    from keras.models import model_from_json
    
      使用 ‘to_categorical’函数将 y_train 数据转换为分类数据。要制作模型,请使用以下代码行。
    model = Sequential()
    model.add(Conv2D(30, (5, 5), input_shape =(1, 28, 28), activation ='relu'))
    model.add(MaxPooling2D(pool_size =(2, 2)))
    model.add(Conv2D(15, (3, 3), activation ='relu'))
    model.add(MaxPooling2D(pool_size =(2, 2)))
    model.add(Dropout(0.2))
    model.add(Flatten())
    model.add(Dense(128, activation ='relu'))
    model.add(Dense(50, activation ='relu'))
    model.add(Dense(13, activation ='softmax'))
    # Compile model
    model.compile(loss ='categorical_crossentropy', 
                  optimizer ='adam', metrics =['accuracy'])
    
  • 将模型拟合到数据
      为了使 CNN 拟合数据,请使用以下代码行。
    model.fit(np.array(l), cat, epochs = 10, batch_size = 200, 
              shuffle = True, verbose = 1)
    
      以 98.46% 的准确率训练我们的模型大约需要三个小时。训练完成后,我们可以将我们的模型保存为 json 文件以备将来使用,这样我们就不必每次训练我们的模型等待三个小时。为了保存我们的模型,我们可以使用以下代码行。
    model_json = model.to_json()
    with open("model_final.json", "w") as json_file:
        json_file.write(model_json)
    # serialize weights to HDF5
    model.save_weights("model_final.h5")
    

    使用它测试我们的模型或求解方程

      首先,使用以下代码行导入我们保存的模型。
    json_file = open('model_final.json', 'r')
    loaded_model_json = json_file.read()
    json_file.close()
    loaded_model = model_from_json(loaded_model_json)
    # load weights into new model
    loaded_model.load_weights("model_final.h5")
    
  • 现在,输入包含手写方程的图像。将图像转换为二进制图像,然后反转图像(如果数字/符号为黑色)。
  • 现在获取图像的轮廓,默认情况下,它会从左到右获取轮廓。
  • 获取每个轮廓的边界矩形。
  • 有时,它会导致相同数字/符号的两个或多个轮廓。为避免这种情况,请检查这两个轮廓的边界矩形是否重叠。如果它们重叠,则丢弃较小的矩形。
  • 现在,将所有剩余的边界矩形调整为 28 x 28。
  • 使用该模型,预测每个边界矩形的相应数字/符号并将其存储在字符串。
  • 之后,在字符串上使用 ‘eval’函数来求解方程。


      从这里下载手写方程求解器的完整代码。