MNIST数据集介绍并基于Tensorflow实现逻辑回归

  • MNIST数据集介绍

MNIST数据集是一个手写体数据集,它来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST)。训练集 (training set) 由来自 250 个不同人手写的数字构成,其中 50% 是高中学生, 50% 来自人口普查局 (the Census Bureau) 的工作人员。 测试集(test set) 也是同样比例的手写数字数据。该数据集包含60,000个用于训练的示例和10,000个用于测试的示例。这些数字已经过尺寸标准化并位于图像中心,图像是固定大小(28x28像素),其值为0到1。为简单起见,每个图像都被平展并转换为784(28 * 28)个特征的一维numpy数组。

MNIST数据集官网为:Link,官网提供下面4个文件的下载链接,分别为训练集图片、训练集图片对应标签(数字0-9)、测试集图片、测试集图片对应便签;我们发现文件的后缀名.gz,说明它们都是压缩文件。

  • 训练集图片格式解析: 

将上述文件下载到本机磁盘, 解压缩train-images-idx3-ubyte.gz文件并打开,拿到train-images.idx3-ubyte文件,下面来看以.idx3-ubyte结尾的文件是个什么东东,简单来说:idx3的数字表示数据维度,也就是图片为3维,这3个维度分别为:训练集每张图片长28个像素点,宽28个像素点,共60000张图片,故(28*28*60000);ubyte表示每张图片以字节文件保存,我们知道MNIST数据集中每张图片中一个像素点为一通道,像素值为0到255。0表示背景(白色),255表示数字(黑色)。打开文件,格式如下:

官网数据描述如下: 

这里我们取第一行:0000 0803 0000 ea60 0000 001c 0000 001c

其中 0000 0803 为该文件的前4个字节,表示文件的magic number(魔数),大概就是确定数据类型的一个标志,是随便设定的,知乎有个回答关于魔数,讲的比较好Link;随后4个字节 0000 ea60 ,对应10进制为60000,表示含有60000张数字图片;再随后4个字节 0000 001c ,对应10进制为28;再随后4个字节 0000 001c 同理对应10进制为28,表示每张图片共有28*28个像素点。再随后1个字节 0000 表示第一张图片第1个像素点值为0 ,001c 表示第一张图片第2个像素点值为24,如此下去,知道最后一张图片的最后一个像素点。

  • 训练集图片对应便签格式解析: 

解压缩train-labels-idx1-ubyte.gz文件并打开,拿到train-labels.idx1-ubyte文件,idx1的表示该便签数据集的数据维度为1,打开文件格式如下:

官网类别数据集描述如下: 

拿第一行来说:0000 0801 0000 ea60 0500 0401 0902 0103

简单来说,该文件前4个字节 0000 0801 表示魔数,而随后4个字节 0000 ea60 表示含有的标签数量,对应10进制为60000,即含有60000个标签,随后每1个字节表示标签,05->数字5、00->数字0、04->数字4......,如此下去直到最后一个标签。

测试集图片与测试集图片对应便签数据格式同理。

  • 读取mnist数据集并保存成图片

import os
import cv2
import numpy as np
"""
参数rb表示“以只读+二进制形式打开文件"
"""
image_dataset = open("D:/download/MNIST/t10k-images-idx3-ubyte/t10k-images.idx3-ubyte", "rb")
bytes = image_dataset.read(4)
"""
int.from_bytes()方法表示将字节数组转换成int数字
byteorder='big表示最有效的字节在字节数组的开头
"""
image_magic_number = int.from_bytes(bytes, byteorder='big', signed=False)
#image_num:文件中包含数字图片的数量
image_num = int.from_bytes(image_dataset.read(4), byteorder='big', signed=False)
#image_row:单张图片包含像素点的行数
image_row = int.from_bytes(image_dataset.read(4), byteorder='big', signed=False)
#image_col:单张图片包含像素点的列数
image_col = int.from_bytes(image_dataset.read(4), byteorder='big', signed=False)
if not os.path.exists("D:/download/MNIST/t10k-images-idx3-ubyte/images_dir"):
    os.makedirs("D:/download/MNIST/t10k-images-idx3-ubyte/images_dir")    
images_dir = "D:/download/MNIST/t10k-images-idx3-ubyte/images_dir"
for i in range(image_num):
    #用来保存一张图片的所有的像素点
    image = []
    for j in range(image_row * image_col):
        #一个字节表示一个像素点
        image.append(int.from_bytes(image_dataset.read(1), byteorder='big', signed=False))
    
    #将一张图片的像素点转换成28*28的形式
    image = np.array(image, dtype=np.uint8).reshape((image_row, image_col)) 
    image_path = images_dir + "/" + str(i)+ ".jpg"
    """
    千万注意路径中不能含有中文
    """
    cv2.imwrite(image_path, image)   

生成的图片如下:

基于Tensorflow实现逻辑回归

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

if __name__ == "__main__":
    # one_hot=True是将28*28的图片展开成张量的形式
    mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

    # 设置每个批次的大小
    batch_size = 100
    # 计算一个有多少个批次
    num_batch = mnist.train.num_examples // batch_size

    # 定义1个placehold
    x = tf.placeholder(tf.float32, [None, None])
    y = tf.placeholder(tf.float32, [None, None])

    # 创建一个简单的神经网络
    w = tf.Variable(tf.truncated_normal([784,100],stddev=0.1))
    b = tf.Variable(tf.zeros([1, 100]))
    # now_result--->1*10
    now_result = tf.nn.relu(tf.matmul(x,w)+b)
    now_result_droup = tf.nn.dropout(now_result,keep_prob=0.9)
    # now_result = tf.nn.tanh(tf.matmul(x,w)+b)

    '''
    为了改进识别准确率,这里再添加一个隐含层
    '''
    h_w = tf.Variable(tf.truncated_normal([100,10],stddev=0.1))
    h_b = tf.Variable(tf.zeros([1,10]))
    prediction = tf.matmul(now_result_droup, h_w) + h_b

    # 二次代价损失函数tf.square---->相当于对向量做2范数操作
    """
    这里使用交叉熵损失函数,二次代价损失函数会出现离得距离比较远但是梯度却很小的问题
    """
    # lossf = tf.reduce_mean(tf.square(y - prediction))
    loss_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=prediction,labels=y))
    # 使用梯度下降算法
    trai_step = tf.train.GradientDescentOptimizer(0.2).minimize(loss_entropy)

    # 结果存放在一个布尔型列表中
    correct_prediction = tf.equal(tf.argmax(input=y, axis=1), tf.argmax(input=prediction, axis=1))
    # print(correct_prediction)
    # 求准确率--->tf.cast()函数的作用是执行 tensorflow 中张量数据类型转换
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    # 初始化变量
    init = tf.global_variables_initializer()

    # 开始创建会话执行代码
    with tf.Session() as sess:
        # 初始化变量
        sess.run(init)
        # 迭代21次
        for epoch in range(21):
            # 遍历每个批次
            for batch in range(num_batch):
                # 取出没一个批次的数据,分开取 batch_x->[100,768] batch_y->[100,10]
                batch_x, batch_y = mnist.train.next_batch(batch_size)          
                sess.run(trai_step, feed_dict={x: batch_x, y: batch_y})
            # 模型已经训练好了,用test集进行测试
            acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})
            print("迭代次数:" + str(epoch) + "   测试集准确率:" + str(acc * 100) + "%")

结果如下:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值