基于MNIST数据集通过朴素贝叶斯学习生成随机手写体数字图像

        好久没写博客了,话不多说,进入主题。

1、贝叶斯方法

        关于贝叶斯方法,刘未鹏的文章一出,感觉不再需要其他文章了。读者可以阅读以下http://mindhacks.cn/2008/09/21/the-magical-bayesian-method/

2、训练数据集

        经典的手写数字图像训练和测试集来自http://yann.lecun.com/exdb/mnist/。读者可以下载。

3、具体实现过程

        3.1 导入数据集

        上面提到的数据由于编码问题,需要自己写导入方法,如果你也是用python的话,有现成的模板可以使用。推荐一个GitHub的下载地址

        3.2 学习并生成图片

        对于一张图像,例如数据集中28*28的图像,每个像素点像素值为0~255。这样一来,经过抽象,一张图像可以分为图像本身数据信息images和它所表示的意义label。其中,images是一个28*28=784维的特征集,且每个维度的特征有256个取值(0~255的像素值)label表示这个特征集的分类,为0~9分为10类。

        根据贝叶斯方法,我们需要得到类别label的先验概率P(c) = {P(c_i)} (i=0~9)。这个过程可以通过简单的统计计算即可。然后在特定类别c的情况下,我们需要去统计计算出每个维度的特征值的后验概率P(x_j | c) = {P(x_j = k | c)} (j = 0~784, k = 0~255)。学习过程即可结束。

        根据学习到的类别label的先验概率和特征向量的后验概率,在生成图像时,我们只需要根据相应的概率随机生成图像信息矩阵即可。首先是生成随机生成0~9的随机数,作为类别label的取值;然后在特定label的情况下,根据P(x_j | c)生成每个维度的随机概率取值,组成图像矩阵。

       根据生成的图像矩阵,生成图像。

4、注意

        关于根据分布概率生成随机数的方法,我采用的是将概率映射到0~1000的范围。比如概率分布是0.2,0.5, 0.3,那么生成0~1000范围的随机数,如果随机数是在在0~199范围的话,就映射为P=0.2的值,以此类推。

5、生成图片效果

基于MNIST数据集通过朴素贝叶斯学习生成随机手写体数字图像_第1张图片

基于MNIST数据集通过朴素贝叶斯学习生成随机手写体数字图像_第2张图片

基于MNIST数据集通过朴素贝叶斯学习生成随机手写体数字图像_第3张图片

6、Python实现代码

# -*- coding: utf-8 -*-
print(__doc__)

import math
import pylab as pl
import numpy as np
from mnist import MNIST
import random
from collections import Counter

# 按照分布概率采样,生成class随机数
def prob_choice_class(probs):
    rnd = random.random() * sum(probs)
    for i, w in enumerate(probs):
        rnd -= w
        if rnd < 0:
            return i

# 按照分布概率采样,生成feature随机数
# 按照概率分布进行映射到0~1000区间
def prob_choice_feature(probs):
    rnd = random.random() * 1000
    prob_section = []
    for i in range(0, len(probs)):
        if rnd >= sum(prob_section):
            prob_section.append(int(probs[i]*1000))
            if rnd < sum(prob_section) or i == len(probs)-1:
                return i
    

# 开源数据集
mndata = MNIST('data')
mndata.load_training()

# 平滑数据,转化为(samples, feature)的矩阵
n_samples = len(mndata.train_images)
data = np.array(mndata.train_images).reshape(n_samples, -1)

# 统计数据
count_class = Counter()
count_feature = {}
# 构建3维数组
for x in range(0, 10):
    ycount = {}
    for y in range(0, 784):
        zcount = {}
        for z in range(0, 256):
            zcount[z] = 0
        ycount[y] = zcount
    count_feature[x] = ycount
# 分别统计class和feature
for i in range(0, len(data)):
    count_class[mndata.train_labels[i]] += 1
    for j in range(0, len(data[i])):
        count_feature[mndata.train_labels[i]][j][int(data[i][j])] += 1

# 计算class的概率分布
count_class_prob = []
count_class_sum = sum(count_class.values())
for key, value in count_class.iteritems():
    count_class_prob.append(float(value)/count_class_sum)

# 计算每个像素维度的分布概率
count_feature_prob = {}
# 构建3维数组
for x in range(0, 10):
    ycount = {}
    for y in range(0, 784):
        zcount = {}
        for z in range(0, 256):
            zcount[z] = 0
        ycount[y] = zcount
    count_feature_prob[x] = ycount
# 具体计算
for i in range(0, 10):
    for j in range(0, 784):
        count_feature_sum = sum(count_feature[i][j].values())
        for k in range(0, 256):
            count_feature_prob[i][j][k] = float(count_feature[i][j][k])/count_feature_sum
##file_class = open('model/classprob', 'w')
##file_feature = open('model/featureprob', 'w')
##file_class.write(str(count_class_prob))
##file_feature.write(str(count_feature_prob))
##file_class.close()
##file_feature.close()
# 根据模型构建图片
# 指定构建图片数量
nr_target = 10
# 图片的像素维度(28*28=784)
nr_feature = 784
# 开始生成图片像素矩阵
class_ = []
feature = []
for x in xrange(nr_target):
    target = prob_choice_class(count_class_prob)
    class_.append(target)
    for y in xrange(nr_feature):
        feature.append(float(prob_choice_feature(count_feature_prob[target][y])))
features = np.array(feature).reshape((nr_target, 28, 28))

# 根据矩阵保存为相应图片
# 图片命名规则:编号_类别(num_class)
num = 0
for index, (image, prediction) in enumerate(zip(features, class_)):
    pl.subplot(1, 1, 1)
    pl.axis('off')
    pl.imshow(image, cmap=pl.cm.gray_r, interpolation='nearest')
    pl.savefig('pic/'+repr(num)+'_%i' % prediction)
##    pl.title('Create: %i' % prediction)
    num += 1

##pl.show()


#END ICTwangbiao


你可能感兴趣的:(Python,ML)