朴素贝叶斯法
用于MNIST分类任务
准确率可达到84.15%
数学原理参考:《统计学习方法》by 李航
Load MNIST Database
通过Keras框架能够比较方便的获得已经打乱顺序的MNIST训练集和测试集。
1 | from keras.datasets import mnist |
获取的数据集构成:
Training set | Test set |
---|---|
60000 examples | 10000 examples |
Visualize the First Six Training Images
看看MNIST数据集的图片是什么样的,查看前6张图片。
1 | import matplotlib.pyplot as plt |
显示如下,可以看出,是灰度值图片:

Binarization
为了方便处理,将灰度图图片二值化。这里先将非0的像素值全置1。
1 | X_train = (X_train>0).astype('uint8') |
对比一下二值化前后的图片:


产生上面两幅图的代码:
1 | def visualize_input(img, ax): |
Train
老办法,先对训练集数据进行reshape
操作,将一幅图展开为行向量。整个训练集(60000张图片)就变成了一个大小为60000×784
的数组,之后尽量进行矩阵操作。
1 | X_train = np.reshape(X_train, (X_train.shape[0], -1)) |
带拉普拉斯平滑的训练函数:
1 | def train(train_data,train_label): #with Laplace smoothing |
注意:函数输出的conditional_prob
是将对应位置像素值判断为1的概率矩阵,若想判断0概率,用1和它做差就可以。
Test
单张图片的预测:
1 | def test_one_image(test_image, prior_prob_log, |
预测所有测试集图片:
1 | def test_all_images(test_data, prior_prob_log, |
计算准确率:1
2
3
4def print_accuracy(predict_label, real_label):
accuracy = (predict_label == real_label).sum() / len(real_label)
print("test accuracy is %.2f%%" % (accuracy*100))
return accuracy
这里将乘法用log转为加法(这个例子中均为单调函数,不影响结果),提高运算速度
1 | import time |
测试的输出:
1 | prior_prob shape: (10,) |
Conclusion
- 本次实验将图像展开、对单个像素独立判断,损失了图像的空间信息,而这种空间信息正是我们人眼识别图像的关键。所以最终的准确率不会太高。
- 测试数据的准确率为84.15%,比我想象中的要好很多(共有10个分类,随机猜测的准确率只有10%)。我认为,能使准确率达到84.15%的原因主要是:(1) MNIST数据集被预先处理过。通过上面的6张示例图片可以看出,MNIST中的图片较为纯净,没有噪声干扰,非常清晰。所以实验中可以直接进行二值化。(2) MNIST数据集中,图片中的数字总是在中心位置,大小合适,比较饱满。这一点保留了部分的空间信息。
- 本例中的二值化过程是直接将非0值置1,如果采用更合理的阈值(比如取当前图片最大像素值的一半)进行二值化操作,进行训练、测试过程,最终的准确率可能会提升。