赞
踩
深度学习小白,若有错误希望各位大佬多多包涵。
数据集可以直接从网上下载,这里把数据集分为了训练集和测试集,但是更多的时候我们会分成训练集,交叉验证集和测试集,这样的训练效果会更好。
(x, y), (x_test, y_test) = datasets.fashion_mnist.load_data()
这里得到的x, y, x_test , y_test都是Numpy类型,要转化为张量类型
def preprocess(x, y):
# 并做归一化处理
x = tf.cast(x, dtype=tf.float32) / 255.
y = tf.cast(y, dtype=tf.int32)
return x, y
这个函数与map()组合使用,传入preprocess,即可完成映射,类型转换
然后,为了加快计算的速度将整个样本切片为batch大小的小样本
为了方便操作,先生成Dataset类的对象,然后再dataset成员方法batch
db = tf.data.Dataset.from_tensor_slices((x, y))
db = db.map(preprocess).shuffle(10000).batch(batches)
测试集做相同的处理即可
循环处理每一个batch数据样本
sample = next(iter(db))
使用Sequential容器,生成Sequential类的一个实例
model = Sequential([
# [b,784] @ [784,256]--> [b,256]
layers.Dense(256, activation=tf.nn.relu),
# [b,256]--> [b,128]
layers.Dense(128, activation=tf.nn.relu),
# [b, 128] --> [b,64]
layers.Dense(64, activation=tf.nn.relu),
# [b,64] --> [b,32]
layers.Dense(32, activation=tf.nn.relu),
# [b,32] --> [b,10] 输出层
layers.Dense(10)
])
并用成员函数build, summary完成网络权值,偏置和输入维度的初始化与网络模型参数状况的输出
model.build(input_shape=[None, 28 * 28])
model.summary()
构造优化器
优化器主要使用apply_gradients方法传入变量和对应梯度从而来对给定变量进行迭代,或者直接使用minimize方法对目标函数进行迭代优化。
optimizers = optimizers.Adam(learning_rate=1e-3)
在使用自动求导功能计算梯度,需要将向前计算过程放置在tf.GradientTape()环境中, 利用GradientTape对象的gradient()方法自动求解参数的梯度, 并利用optimizers对象更新参数
with tf.GradientTape() as tape:
logits = model(x)
y_onehot = tf.one_hot(y, depth=10)
loss_ce = tf.losses.categorical_crossentropy(y_onehot, logits, from_logits=True)
loss_ce = tf.reduce_mean(loss_ce)
grads = tape.gradient(loss_ce, model.trainable_variables)
optimizers.apply_gradients(zip(grads, model.trainable_variables))
# -*- codeing = utf-8 -*- # @Time : 10:02 # @Author:Paranipd # @File : mnist_test.py # @Software:PyCharm import os import tensorflow as tf from tensorflow import keras from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics # 数据集, 网络层, 分类器, 容器 os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 去掉不必要的报错 # 预处理,参数类型转换 ,加载的数据集是Nunpy类型 def preprocess(x, y): # 并做归一化处理 x = tf.cast(x, dtype=tf.float32) / 255. y = tf.cast(y, dtype=tf.int32) return x, y # 加载数据集 = 训练集 + 测试集 x,y : 普通数据类型(Numpy) # x.sahpe : (60000, 28 , 28) y.shape:(60000,) # x.min-max:(0,255) y :[0,9] (x, y), (x_test, y_test) = datasets.fashion_mnist.load_data() print(x.shape, x.dtype, y.shape, y.dtype) # 批处理样本数 batches = 128 # 创建一个数据集,其元素是给定张量的切片 # 通过使用tf.data.Dataset提供的接口from_tensor_slices将(x,y)-->Dataset类的对象 db = tf.data.Dataset.from_tensor_slices((x, y)) # map数据类型的转换 # shuffle 将数据集随机打散 # batch 将多个样本组成一个batch ,加速计算 # 注意不同的顺序,会有不同的结果 db = db.map(preprocess).shuffle(10000).batch(batches) # 为了使每次取数据样本的数量为batches # print('db:', db) db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test)) db_test = db_test.map(preprocess).batch(batches) # 通过Dataset的对象db进行迭代,获取下一批batch ==>sample = next(iter(db)) db_iter = iter(db) sample = next(db_iter) print('batch:', sample[0].shape, sample[1].shape) # 通过Sequential容器封装一个网络大类对象 model = Sequential([ # [b,784] @ [784,256]--> [b,256] layers.Dense(256, activation=tf.nn.relu), # [b,256]--> [b,128] layers.Dense(128, activation=tf.nn.relu), # [b, 128] --> [b,64] layers.Dense(64, activation=tf.nn.relu), # [b,64] --> [b,32] layers.Dense(32, activation=tf.nn.relu), # [b,32] --> [b,10] 输出层 layers.Dense(10) ]) # 初始化网络的权值和维度 model.build(input_shape=[None, 28 * 28]) # Sequential类的类方法 # 输出网络模式各层的参数状况,查看网络模型的结构 model.summary() # w = w - lr * grad # 学习率的设置,更新参数 optimizers = optimizers.Adam(learning_rate=1e-3) def main(): # 将整个数据集迭代30次 for epoch in range(30): # 迭代数据集对象,待step参数 ,完成一次batch的数据训练叫做一个step # 批次处理部分数据集,一次处理128个样本 for step, (x, y) in enumerate(db): # x: [b,28,28] ==> [b,784] 一维 # y: [b] x = tf.reshape(x, [-1, 28 * 28]) # 在使用自动求导功能计算梯度,需要将向前计算过程放置在tf.GradientTape()环境中 # 利用GradientTape对象的gradient()方法自动求解参数的梯度 # 并利用optimizers对象更新参数 with tf.GradientTape() as tape: # 梯度记录器 # [b,784] ==> [b,10] # model(x) 实际是调用类中__call__方法 # 输出网络模型(向前计算)结果 logits = model(x) # onehot编码 y_onehot = tf.one_hot(y, depth=10) # 均方差代价函数 loss_mse = tf.reduce_mean(tf.losses.MSE(y_onehot, logits)) # 交叉熵损失计算函数 loss_ce = tf.losses.categorical_crossentropy(y_onehot, logits, from_logits=True) loss_ce = tf.reduce_mean(loss_ce) # 对所有的可优化变量求导 grads = tape.gradient(loss_ce, model.trainable_variables) # 更新可以优化张量 # zip将对应元素打包为元组,这些元组组成一个列表 optimizers.apply_gradients(zip(grads, model.trainable_variables)) if step % 100 == 0: print(epoch, step, 'loss:', float(loss_ce), float(loss_mse)) # test 计算一个精确度 total_correct = 0 total_num = 0 for x, y in db_test: # x: [b,28,28] ==> [b,784] # y: [b] x = tf.reshape(x, [-1, 28 * 28]) # [b,10] logits = model(x) # logits --> prob: [b,10] int64 # 将输出结果归一化处理,得到和为1的概率 prob = tf.nn.softmax(logits, axis=1) # [0,1] # 找到对应维度最大值的索引位置 pred = tf.argmax(prob, axis=1) pred = tf.cast(pred, dtype=tf.int32) # pred:[b] # y: [b] # correct: [b], True(1): equal; False(0): not equal correct = tf.equal(pred, y) correct = tf.reduce_sum(tf.cast(correct, dtype=tf.int32)) # 预测对的数量 total_correct += int(correct) # 总的数量 total_num += x.shape[0] # 精确度 acc = total_correct / total_num print(epoch, 'text acc:', acc) if __name__ == "__main__": main()
模型结果
最终的预测精确度有0.87左右,要是再做一些优化处理和误差处理准确度还可以更高。
提示:这里对文章进行总结:
epoch: 使用训练集的全部数据对模型进行一次完整训练,称"一代训练"
batch: 使用训练集中的一小部分样本对模型权值进行一次反向传播的参数更新,这一个小部分样本被称为“一批数据"
iteration:使用一个batch数据对模型进行一次参数更新的过程,被称为"一次训练"
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。