当前位置:   article > 正文

用朴素贝叶斯分类方法解决MNIST手写数字分类问题_mnist 处理好的

mnist 处理好的

在上一次做了最小二乘法解决分类问题,最近复习了贝叶斯后验概率,顺便写了个程序,在上一次的基础上做出少许改进,总体上正确率没有上次高。上次的代码见这篇文章https://blog.csdn.net/qwe900/article/details/109774223

朴素贝叶斯的分类算法主要分一下步骤:
1.计算先验概率以及条件概率
2.对于给定的例子,计算目标概率和目标条件时,该例子所有情况概率的积
3.比较正类计算2和负类计算2中的大小,从而决定预测的结果。
在这里插入图片描述
在这里插入图片描述
例子通俗易懂,那么就编程实现一下吧。
先放个结果,好像没有想象中那么好…(上次写的一些函数还能接着用)
在这里插入图片描述
因为比较懒,写了比较多for循环,并且只做了二分类以及只做了训练集上的指标分析,有时间将代码再完善一下。

import numpy as np
import struct
import prettytable as pt
import time
# 训练集文件
train_images_idx3_ubyte_file = r'D:\2pic\train-images.idx3-ubyte'
# 训练集标签文件
train_labels_idx1_ubyte_file = r'D:\2pic\train-labels.idx1-ubyte'

# 测试集文件
test_images_idx3_ubyte_file = r'D:\2pic\t10k-images.idx3-ubyte'
# 测试集标签文件
test_labels_idx1_ubyte_file = r'D:\2pic\t10k-labels.idx1-ubyte'


def decode_idx3_ubyte(idx3_ubyte_file):
    """
    解析idx3文件的通用函数
    :param idx3_ubyte_file: idx3文件路径
    :return: 数据集
    """
    # 读取二进制数据
    bin_data = open(idx3_ubyte_file, 'rb').read()

    # 解析文件头信息,依次为魔数、图片数量、每张图片高、每张图片宽
    offset = 0
    fmt_header = '>iiii' #因为数据结构中前4行的数据类型都是32位整型,所以采用i格式,但我们需要读取前4行数据,所以需要4个i。我们后面会看到标签集中,只使用2个ii。
    magic_number, num_images, num_rows, num_cols = struct.unpack_from(fmt_header, bin_data, offset)
    print('魔数:%d, 图片数量: %d张, 图片大小: %d*%d' % (magic_number, num_images, num_rows, num_cols))

    # 解析数据集
    image_size = num_rows * num_cols
    offset += struct.calcsize(fmt_header)  #获得数据在缓存中的指针位置,从前面介绍的数据结构可以看出,读取了前4行之后,指针位置(即偏移位置offset)指向0016。
    print(offset)
    fmt_image = '>' + str(image_size) + 'B'  #图像数据像素值的类型为unsigned char型,对应的format格式为B。这里还有加上图像大小784,是为了读取784个B格式数据,如果没有则只会读取一个值(即一副图像中的一个像素值)
    print(fmt_image,offset,struct.calcsize(fmt_image))
    images = np.empty((num_images, num_rows, num_cols))
    #plt.figure()
    for i in range(num_images):
        if (i + 1) % 10000 == 0:
            print('已解析 %d' % (i + 1) + '张')
            print(offset)
        images[i] = np.array(struct.unpack_from(fmt_image, bin_data, offset)).reshape((num_rows, num_cols))
        #print(images[i])
        offset += struct.calcsize(fmt_image)
#        plt.imshow(images[i],'gray')
#        plt.pause(0.00001)
#        plt.show()
    #plt.show()

    return images


def decode_idx1_ubyte(idx1_ubyte_file):
    """
    解析idx1文件的通用函数
    :param idx1_ubyte_file: idx1文件路径
    :return: 数据集
    """
    # 读取二进制数据
    bin_data = open(idx1_ubyte_file, 'rb').read()

    # 解析文件头信息,依次为魔数和标签数
    offset = 0
    fmt_header = '>ii'
    magic_number, num_images = struct.unpack_from(fmt_header, bin_data, offset)
    print('魔数:%d, 图片数量: %d张' % (magic_number, num_images))

    # 解析数据集
    offset += struct.calcsize(fmt_header)
    fmt_image = '>B'
    labels = np.empty(num_images)
    for i in range(num_images):
        if (i + 1) % 10000 == 0:
            print ('已解析 %d' % (i + 1) + '张')
        labels[i] = struct.unpack_from(fmt_image, bin_data, offset)[0]
        offset += struct.calcsize(fmt_image)
    return labels


def load_train_images(idx_ubyte_file=train_images_idx3_ubyte_file):
    """
    TRAINING SET IMAGE FILE (train-images-idx3-ubyte):
    [offset] [type]          [value]          [description]
    0000     32 bit integer  0x00000803(2051) magic number
    0004     32 bit integer  60000            number of images
    0008     32 bit integer  28               number of rows
    0012     32 bit integer  28               number of columns
    0016     unsigned byte   ??               pixel
    0017     unsigned byte   ??               pixel
    ........
    xxxx     unsigned byte   ??               pixel
    Pixels are organized row-wise. Pixel values are 0 to 255. 0 means background (white), 255 means foreground (black).

    :param idx_ubyte_file: idx文件路径
    :return: n*row*col维np.array对象,n为图片数量
    """
    return decode_idx3_ubyte(idx_ubyte_file)


def load_train_labels(idx_ubyte_file=train_labels_idx1_ubyte_file):
    """
    TRAINING SET LABEL FILE (train-labels-idx1-ubyte):
    [offset] [type]          [value]          [description]
    0000     32 bit integer  0x00000801(2049) magic number (MSB first)
    0004     32 bit integer  60000            number of items
    0008     unsigned byte   ??               label
    0009     unsigned byte   ??               label
    ........
    xxxx     unsigned byte   ??               label
    The labels values are 0 to 9.

    :param idx_ubyte_file: idx文件路径
    :return: n*1维np.array对象,n为图片数量
    """
    return decode_idx1_ubyte(idx_ubyte_file)


def load_test_images(idx_ubyte_file=test_images_idx3_ubyte_file):
    """
    TEST SET IMAGE FILE (t10k-images-idx3-ubyte):
    [offset] [type]          [value]          [description]
    0000     32 bit integer  0x00000803(2051) magic number
    0004     32 bit integer  10000            number of images
    0008     32 bit integer  28               number of rows
    0012     32 bit integer  28               number of columns
    0016     unsigned byte   ??               pixel
    0017     unsigned byte   ??               pixel
    ........
    xxxx     unsigned byte   ??               pixel
    Pixels are organized row-wise. Pixel values are 0 to 255. 0 means background (white), 255 means foreground (black).

    :param idx_ubyte_file: idx文件路径
    :return: n*row*col维np.array对象,n为图片数量
    """
    return decode_idx3_ubyte(idx_ubyte_file)


def load_test_labels(idx_ubyte_file=test_labels_idx1_ubyte_file):
    """
    TEST SET LABEL FILE (t10k-labels-idx1-ubyte):
    [offset] [type]          [value]          [description]
    0000     32 bit integer  0x00000801(2049) magic number (MSB first)
    0004     32 bit integer  10000            number of items
    0008     unsigned byte   ??               label
    0009     unsigned byte   ??               label
    ........
    xxxx     unsigned byte   ??               label
    The labels values are 0 to 9.

    :param idx_ubyte_file: idx文件路径
    :return: n*1维np.array对象,n为图片数量
    """
    return decode_idx1_ubyte(idx_ubyte_file)

def pretreat(train_labels,test_labels,train_images,test_images):
    
    train_images_column=train_images.reshape(60000,784,1)
    test_images_column=test_images.reshape(10000,784,1)
    train_labels=train_labels.reshape(60000,1)
    test_labels=test_labels.reshape(10000,1)
    
    for i in range(len(train_labels)):
        if train_labels[i] == 0:
            train_labels[i] =1
        elif train_labels[i] != 0:
            train_labels[i] = -1 ## 5923个0 /60000 约1/10 正确
        
    for i in range(len(test_labels)):
        if test_labels[i] == 0:
            test_labels[i] =1
        elif test_labels[i] != 0:
            test_labels[i] = -1 ## 980个0 /10000 约1/10  正确
            
    train_images_2D=train_images_column.reshape(60000,784)
    test_images_2D=test_images_column.reshape(10000,784)
    train_images_2DT=train_images_2D.T
    test_images_2DT=test_images_2D.T   
    
    return train_labels,test_labels,train_images_2DT,test_images_2DT

def show_result(labels,result,dataset):
    TP=0 #正类预测为正类
    FN=0 #正类预测为负类   
    FP=0 #负类预测为正类
    TN=0 #负类预测为负类
    for i in range(len(labels)):
        if labels[i]==1 and result[i]==1:
            TP=TP+1
        elif labels[i]==1 and result[i]==-1:
            FN=FN+1
        elif labels[i]==-1 and result[i]==1:
            FP=FP+1
        elif labels[i]==-1 and result[i]==-1:
            TN=TN+1   
    tb = pt.PrettyTable()
    tb.field_names = [dataset,"Predicted y=1","Prediected y=-1","Total"]
    tb.add_row(["y=+1",TP,FN,TP+FN])
    tb.add_row(["y=-1",FP,TN,FP+TN])
    tb.add_row(["All",TP+FP,FN+TN,TP+FP+FN+TN])
    print(tb)   
    error = (FN+FP)/(TP+FP+FN+TN) * 100
    print('错误率为',"%.3f" % error,'%')
    print('\n')
    


def CalculateP(train_image_feature,train_labels):
    print("计算XY交事件的概率...")
    PP=0
    NP=0
    PN=0
    NN=0
    for i in range(493):
        PP=0
        NP=0
        PN=0
        NN=0
        for j in range(60000):
            if train_image_feature[i,j] == 1 and train_labels[j]== 1:
                PP=PP+1
            elif train_image_feature[i,j] == 0 and train_labels[j]== 1:
                NP=NP+1
            elif train_image_feature[i,j] == 1 and train_labels[j]== -1:
                PN=PN+1
            elif train_image_feature[i,j] == 0 and train_labels[j]== -1:
                NN=NN+1                
        P[i,0] = PP/5923
        P[i,1] = NP/5923        
        P[i,2] = PN/54077
        P[i,3] = NN/54077 
    print("已完成XY交事件的概率的计算")
    return P

def CDF(P,train_image_feature):
    print("计算XY条件概率...")    
    PY_P=5923/60000
    PY_N=54077/60000
    b_predict = np.zeros([60000,1])
    for j in range(60000):
        temp_PP = 1
        temp_PN = 1        
        for i in range(493):
            index = int(1-(train_image_feature[i,j]))
            multi_P = P[i,index]
            temp_PP = multi_P * temp_PP

        for i in range(493):
            index = int(3-(train_image_feature[i,j]))
            multi_P = P[i,index]
            temp_PN = multi_P * temp_PN
        
    
        if PY_P*temp_PP > PY_N*temp_PN:
            b_predict[j] = 1
            print("标签号为",j,"样本预测为y=1") 
        elif PY_P*temp_PP < PY_N*temp_PN:
            b_predict[j] = -1
            print("标签号为",j,"样本预测为y=-1") 
    print("已计算完毕XY的条件概率...")    
    return b_predict
if __name__ == '__main__':
   
    train_images = load_train_images()
    train_labels = load_train_labels()
    test_images = load_test_images()
    test_labels = load_test_labels()  
    [train_labels,test_labels,train_images_2DT,test_images_2DT]=pretreat(train_labels,test_labels,train_images,test_images)
    tt=0
    index=[]
    train_image_feature=np.zeros([493,60000])
    for i in range (784):
        non_zero = np.linalg.norm(train_images_2DT[i,:], ord=0) 
        if non_zero >= 600:
            train_image_feature[tt,:]=train_images_2DT[i,:]
            tt=tt+1
            index.append(i)
    P = np.zeros([493,4])
    train_image_feature[train_image_feature<128.0] = 0  ##一定要先取小的后取大的
    train_image_feature[train_image_feature>=128.0] = 1
    
    P = CalculateP(train_image_feature,train_labels)

            
    ## 下一步骤对结果进行预测计算条件概率 
    b_predict = CDF(P,train_image_feature)
    show_result(train_labels,b_predict,'Bayes')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287

主要思路是

  • X的原始特征为28*28=784维,运用上一篇博客(引言处)的办法,提取出比较有用的区域为493维。
  • 计算条件概率时候如 P ( X ( 1 ) ∣ Y = 1 ) = P ( X ( 1 ) = 1 , Y = 1 ) P ( Y = 1 ) P(X^{(1)}|Y=1)=\frac {P(X^{(1)}=1,Y=1)}{P(Y=1)} P(X(1)Y=1)=P(Y=1)P(X(1)=1,Y=1),分母部分为统计所有标签中,正类的个数,正类这里指的是0,负类指的是非0,0的概率大概在1/10左右,这里提前运行出来结果是5932个。
  • 在计算完概率,存储到P矩阵中,该矩阵的维度是493*4,每一列分别表示X=1,Y=1;X=0,Y=1;X=1,Y=-1;X=0,Y=-1四种情况的条件概率结果。
  • P在这里插入图片描述
    等修改好了再更一波。
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号