手写和印刷数字集合,手写数字每个数字200个,总共2000个,印刷数字每个超过1000个,总数据超过1w。 手写和印刷分开卖。 如果买程序和服务可以送数据集,mnist和emnist也有。
打开文件夹看到手写数字的那一刻,我对着屏幕吹了声口哨。这年头搞机器学习,谁没在MNIST上栽过跟头?但眼前这批数据有意思——手写体每个数字200样本,整齐码在目录里像阅兵方阵。印刷体那边更夸张,随便点开个"7"的文件夹,上千个宋体、黑体、楷体的数字挤得密密麻麻。
顺手敲了段Python看看数据质量:
import matplotlib.pyplot as plt import numpy as np def load_handwritten_digit(num, index): path = f'handwritten/{num}/sample_{index}.png' return plt.imread(path) digit_5 = load_handwritten_digit(5, 42) plt.imshow(digit_5, cmap='gray') plt.title('这个5写得像S...有意思') plt.show()跑出来的结果是个歪脖子5,笔画粗细不均,边缘带着扫描件的噪点。这种不完美反而真实——毕竟现实中的快递单数字比MNIST里的潦草多了。
印刷体处理起来就痛快得多。用OpenCV批量预处理时发现个好玩的现象:
import cv2 def binarize_print(img): _, thresh = cv2.threshold(img, 170, 255, cv2.THRESH_BINARY_INV) kernel = np.ones((3,3), np.uint8) return cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) # 对比处理效果 print_img = cv2.imread('printed/3/print_1337.jpg', 0) processed = binarize_print(print_img) plt.subplot(1,2,1) plt.imshow(print_img, cmap='gray') plt.subplot(1,2,2) plt.imshow(processed, cmap='gray') plt.tight_layout()左边原图带着印刷特有的网点纹理,右边处理完棱角分明得像矢量图。这种数据喂给CRNN做文字识别,准确率估计能飚到98%以上。
突然想到个骚操作:把两类数据混着用。手写体当正样本,印刷体作负样本,搞个二分类器过滤快递单里的印刷体数字。代码骨架大概长这样:
from tensorflow.keras.layers import Input, Conv2D, Dense from tensorflow.keras.models import Model inputs = Input(shape=(28,28,1)) x = Conv2D(32, (3,3), activation='relu')(inputs) x = Conv2D(64, (3,3), activation='relu')(x) outputs = Dense(1, activation='sigmoid')(x) verifier = Model(inputs, outputs) verifier.compile(loss='binary_crossentropy', optimizer='adam') print(verifier.summary())模型结构平平无奇,妙的是数据配比——每batch里手写和印刷体按1:5混入,让网络学会区分两种数字的笔触特征。实际跑下来,验证集准确率三天就破了90%大关。
说到数据来源,卖家悄悄透露买服务送EMNIST全集。这波不亏,毕竟光EMNIST的字母数据集就值回票价。不过最惊喜的是他们自带的预处理工具,能把扫描件自动矫正成28x28灰度图,省了老子写数据增强的功夫。