MINST数字识别

 

这个过程有点类似Flink、Spark的算子计算过程,通过各种算子,将RDD转化成目标数据。这里本质也是通过各种算子将图片转化为目标数据。

import os
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, optimizers, datasets

class MNISTLoader():
   
def __init__(self):
        mnist = tf.keras.datasets.mnist
        (
self.train_data, self.train_label), (self.test_data, self.test_label) = mnist.load_data()
       
#MNIST中的图像默认为uint8(0-255的数字)。以下代码将其归一化到0-1之间的浮点数,并在最后增加一维作为颜色通道
       
self.train_data = np.expand_dims(self.train_data.astype(np.float32)/255.0, axis=-1) # [60000, 28, 28, 1]#在最后位置,增加一维度,与reshape类似
       
self.test_data = np.expand_dims(self.test_data.astype(np.float32) / 255.0, axis=-1) # [10000, 28, 28, 1]
       
self.train_label = self.train_label.astype(np.int32)  # [60000]
       
self.test_label = self.test_label.astype(np.int32)  # [10000]
       
self.num_train_data, self.num_test_data = self.train_data.shape[0], self.test_data.shape[0]

   
def get_batch(self, batch_size):
       
#生产随机索引
       
index = np.random.randint(0, self.num_train_data, batch_size)
       
#根据随机索引返回对应内容
       
return self.train_data[index, :], self.train_label[index] #随机获取50条数据

#多层感知机模型

class MLP(tf.keras.Model):
   
# 初始化
   
def __init__(self):
       
super().__init__()
       
#定义网络机构,以及对应的函数
       
self.flatten = tf.keras.layers.Flatten() #Flatten层将除第一维(batch_size)以外的维度展平
       
self.dense1 = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)
       
self.dense2 = tf.keras.layers.Dense(units=10)

   
def call(self, inputs):
       
# print(inputs.shape)  #(50, 28, 28, 1)
        #
调用
       
x = self.flatten(inputs) #压平层,用于将多维张量压成一维
       
x = self.dense1(x)
        x =
self.dense2(x)
        output = tf.nn.softmax(x)
       
return output

#卷积神经网络模型
class CNN(tf.keras.Model):
   
# 初始化
   
def __init__(self):
       
super().__init__()
       
#第一层卷积
       
self.conv1 = tf.keras.layers.Conv2D(
           
filters=32#卷积层神经元(卷积核)数目,设置神经元(卷积核)数目32,则输出(batchsize,28,28,32),32个神经元输出数据整合到一起
           
kernel_size=[5,5], #感受野大小,卷积核大小,就是那个小方块的大小,通常为奇数正方形,比如3*3,5*5
           
padding='same', # padding策略(vaild 或 same)
           
activation=tf.nn.relu #激活函数
       
)
       
#加一个池化层,用区域最大值池化,本质也是降维
       
self.pool1 = tf.keras.layers.MaxPool2D(pool_size=[2,2],strides=2)
       
#第二层卷积
       
self.conv2 = tf.keras.layers.Conv2D(
           
filters=64# 卷积层神经元(卷积核)数目,这个数据是啥?
           
kernel_size=[5, 5],  # 感受野大小,卷积核大小,就是那个小方块的大小,通常为奇数正方形,比如3*3,5*5
           
padding='same'# padding策略(vaild 或 same)
           
activation=tf.nn.relu  # 激活函数
       
)
       
#再池化一次
       
self.pool2 = tf.keras.layers.MaxPool2D(pool_size=[2, 2], strides=2)
       
#压平,就是resharp
       
self.flatten = tf.keras.layers.Reshape(target_shape=(7 * 7 * 64,))
       
#全连接层,输出1024
       
self.dense1 = tf.keras.layers.Dense(units=1024, activation=tf.nn.relu)
       
#全连接层,输出10,10就是最终输出各分类的概率
       
self.dense2 = tf.keras.layers.Dense(units=10)

   
def call(self, inputs): #输入数据[batch_size,28,28,1]
       
x = self.conv1(inputs)  # [batch_size, 28, 28, 32]
       
x = self.pool1(x)  # [batch_size, 14, 14, 32]
       
x = self.conv2(x)  # [batch_size, 14, 14, 64]
       
x = self.pool2(x)  # [batch_size, 7, 7, 64]
       
x = self.flatten(x)  # [batch_size, 7 * 7 * 64]
       
x = self.dense1(x)  # [batch_size, 1024]
       
x = self.dense2(x)  # [batch_size, 10]
       
output = tf.nn.softmax(x) #取出最大概率的那个分类
        
return output


#超参数
num_epochs = 5 #循环5次
batch_size = 50 #每次读取的数据量
learning_rate = 0.001 #学习率

#模型

model = MLP() #准确率97%
# model = CNN() #准确率99%
#载入数据

data_loader = MNISTLoader()

#优化,Adam代替了GD梯度算法
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
#一共循环的次数 1200 * 5
num_batches = int(data_loader.num_train_data // batch_size * num_epochs)

for batch_index in range(num_batches):
    X, y = data_loader.get_batch(batch_size)
   
with tf.GradientTape() as tape:
        y_pred = model(X)
       
#损失函数,交叉熵作为损失函数,代替了MSE,在分类问题中被广泛应用。其离散形式为 H(y, \hat{y}) = -\sum_{i=1}^{n}y_i \log(\hat{y_i}) ,其中 y 为真实概率分布, \hat{y} 为预测概率分布, n 为分类任务的类别个数。预测概率分布与真实分布越接近,则交叉熵的值越小,反之则越大。
       
loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred)
        loss = tf.reduce_mean(loss)
       
print("batch %d: loss %f" %(batch_index, loss.numpy()))
       
#计算模型的梯度,然后进行训练优化,相当于迭代过程中的自动优化
       
grads = tape.gradient(loss, model.variables) #对这些参数求导
       
optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables)) #应用优化

print("final variables", model.variables)

#模型的评估
sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy()
num_batches =
int(data_loader.num_test_data / batch_size)
for batch_index in range(num_batches):
    start_index, end_index = batch_index * batch_size , (batch_index +
1) * batch_size
    y_pred = model.predict(data_loader.test_data[start_index:end_index])
    sparse_categorical_accuracy.update_state(
y_true=data_loader.test_label[start_index:end_index], y_pred=y_pred)
   
print("test accuracy: %f" %(sparse_categorical_accuracy.result()))

效果非常好:

Model: "cnn"

_________________________________________________________________

Layer (type)                 Output Shape              Param #  

=================================================================

conv2d (Conv2D)              multiple                  832      

_________________________________________________________________

max_pooling2d (MaxPooling2D) multiple                  0        

_________________________________________________________________

conv2d_1 (Conv2D)            multiple                  51264    

_________________________________________________________________

max_pooling2d_1 (MaxPooling2 multiple                  0        

_________________________________________________________________

reshape (Reshape)            multiple                  0        

_________________________________________________________________

dense (Dense)                multiple                  3212288  

_________________________________________________________________

dense_1 (Dense)              multiple                  10250    

=================================================================

Total params: 3,274,634

Trainable params: 3,274,634

Non-trainable params: 0

_________________________________________________________________

test accuracy: 0.992183

test accuracy: 0.992222

test accuracy: 0.992261

test accuracy: 0.992300

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yesunx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值