美文网首页AI人工智能与数学之美
使用Tensorflow进行Mnist数据集实战

使用Tensorflow进行Mnist数据集实战

作者: climb66的夏天 | 来源:发表于2020-10-10 16:37 被阅读0次

    MNIST数据集简介

    在进行MNIST数据集实战之前,我们先简单了解一下MNIST数据集。
    MNIST数据集的全称叫手写数字图片数据集,它包含了0~9共10种数字的手写图片,每种数字一共有7000张图片,采集自不同风格的真实手写图片,整个数据集有70000张图片。

    其中60000张图片用作训练集,剩下的10000张图片用作测试集。

    而其中每张图片的大小是28x28大小,并且只保留了灰度信息。

    我们学写程序,都会从一个“hello world”开始,那么,我的深度学习之旅就从这个MNIST数据集开始吧。

    下面具体说一下怎么使用这个数据集来训练模型。

    第一步: 首先加载MINST数据集,现在这个过程在Tensorflow 2.0中很简单了,一行代码就可搞定。

    每二步: 使用训练集来训练模型,每训练100次,打印看一下模型的损失值。以及用测试集来测试一下模型的性能。

    第三步: 在训练完成后,把模型训练过程中的损失值和准确率使用Matplotlib画出来,使我们能够更直观地看到模型的训练曲线。

    下面看一下具体代码实现流程:

    首先我们要导入一些库,如下:

    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import datasets,layers,optimizers
    import matplotlib
    from matplotlib import pyplot as plt
    

    接下来,我们把MNIST数据集加载进来:

    (x_train,y_train),(x_test,y_test) = datasets.mnist.load_data()
    print('x_train:',x_train.shape,'y_train:',y_train.shape,'x_test:',x_test.shape,'y_test:',y_test.shape)
    x_train: (60000, 28, 28) y_train: (60000,) x_test: (10000, 28, 28) y_test: (10000,)
    

    可以看到,加载这个数据集只需使用一行代码,另外,我打印了这个数据集中训练集和测试集的一些信息。

    下面,把训练集和测试集做成一个Tensorflow易于批量处理的Dataset:

    batchsz = 512#批量处理大小,表示一次性可以处理512张图片
    
    train_db = tf.data.Dataset.from_tensor_slices((x_train,y_train))
    train_db = train_db.shuffle(1000)##把训练集中的数据打散,防止神经网络记忆住训练数据
    train_db = train_db.batch(batchsz)#批量化处理
    train_db = train_db.map(preprocess)#对训练数据集中的数据做预处理
    train_db = train_db.repeat(20)#对整个训练数据集遍历20次进行训练
    

    注意,其中有一个预处理函数preprocess,它的实现如下:

    def preprocess(x,y):
        print(x.shape,y.shape)
        x = tf.cast(x,dtype=tf.float32)/255.#把图片中的灰度值归一化到0~1区间
        x = tf.reshape(x,[-1,28*28])#把每一张图片都打平成28*28的一维向量,方便神经网络模型处理
        y = tf.cast(y,dtype=tf.int32)#把训练集中的标签值类型转化为tf.int32类型
        y = tf.one_hot(y,depth=10)#然后把标签值处理为one_hot编码格式的数据
        
        return x,y
    

    训练集处理好后,我们按着同样的流程处理一下测试集:

    test_db = tf.data.Dataset.from_tensor_slices((x_test,y_test))
    test_db = test_db.batch(batchsz)
    test_db = test_db.map(preprocess)
    
    #查看批量处理后,训练集中的数据
    sample_x,sample_y = next(iter(train_db))
    print(sample_x.shape,sample_y.shape)
    (512, 784) (512, 10)
    

    通过打印信息,可以看到,批量处理后,训练集中的一批数据中有512张图片,每张图片被打平成784(28x28)和一维向量。同时标签数据中有512个标签,每个标签都是长度为10的向量。

    准备工作都好了,开始训练模型吧。我这里使用张量的方式来实现这个模型。

    def main():
        lr = 1e-2#学习率
        losses,accs = [],[]#用来保存损失值和准确率的数组
        
        #初始化模型需要用到的超参数
        w1,b1 = tf.Variable(tf.random.normal([784,256],stddev=0.1)), tf.Variable(tf.zeros([256]))
        w2,b2 = tf.Variable(tf.random.normal([256,128],stddev=0.1)), tf.Variable(tf.zeros([128]))
        w3,b3 = tf.Variable(tf.random.normal([128,10],stddev=0.1)),tf.Variable(tf.zeros([10]))
    
        #使用一个for循环进行迭代20次
        for step, (x,y) in enumerate(train_db):
            with tf.GradientTape() as tape:
                #下面这个是用张量实现的一个简单的全连接层
                h1 = x@w1+b1
                h1 = tf.nn.relu(h1)#激活函数采用relu函数
    
                h2 = h1@w2+b2
                h2 = tf.nn.relu(h2)
    
                out = h2@w3+b3
        
                loss = tf.square(y-out)#这里是每一张图片的损失值
                loss = tf.reduce_mean(loss)#计算这批样本的损失值的均值
                
            grads = tape.gradient(loss,[w1,b1,w2,b2,w3,b3])#根据损失值计算出各个超参数的梯度
            for p,g in zip([w1,b1,w2,b2,w3,b3],grads):
                p.assign_sub(g*lr)#对超参数进行梯度下降
        
            #训练100步后打印损失值
            if step%100 ==0:
                print(step,'loss:',float(loss))
                losses.append(float(loss))
                
            if step%100 ==0:
                #每训练100次后,测试模型
                total,total_correct = 0.,0.
                for x_test,y_test in test_db:
                    h1 = x_test@w1+b1
                    h1 = tf.nn.relu(h1)
                    
                    h2 = h1@w2+b2
                    h2 = tf.nn.relu(h2)
                    
                    out = h2@w3+b3
                    
                    pred = tf.argmax(out,axis=1)#测试集的预测值
                    y_test = tf.argmax(y_test,axis=1)#测试集的真实标签
                    
                    correct = tf.equal(y_test,pred)#计算预测正确的数据
                    total_correct += tf.reduce_sum(tf.cast(correct,dtype=tf.int32)).numpy()
                    total += y_test.shape[0]
                    
                print(step, 'Evaluate acc:', total_correct/total)
                accs.append(total_correct/total)
        
        #画模型的训练误差曲线
        plt.figure()
        x = [i*80 for i in range(len(losses))]
        plt.plot(x,losses,color='C0',marker='s',label='训练')
        plt.xlabel('Step')
        plt.ylabel('MSE')
        plt.legend()
        plt.savefig('train.svg')
        
        #画模型的测试准确率曲线
        plt.figure()
        plt.plot(x,accs,color='C1',marker='s',label='测试')
        plt.xlabel('Step')
        plt.ylabel('准确率')
        plt.legend()
        plt.savefig('test.svg')
    

    最后,在这个函数调用main():

    if __name__ == '__main__':
        main()
    

    下面是运行截图:


    模型的训练误差曲线 模型的测试准确率曲线

    相关文章

      网友评论

        本文标题:使用Tensorflow进行Mnist数据集实战

        本文链接:https://www.haomeiwen.com/subject/nsarpktx.html