Tensorflow 2.0 初学者的自学笔记(1)
简介
其实之前我学习过tf1.1的一些知识,当时被tf.session和tf.graph搞得死去活来,各种看不懂,但是前段时间被教授强迫再次捡起自己垃圾的tensorflow的时候, 决定好好升级一下自己的大脑,顺便写下来方便自己复习 本文学习子tensorflow2.0的官方中文文档。主要作用是方便我复习。 原文地址
基本的设计逻辑
我们在设计一个深度学习模型的时候,通常分为以下几步。
们会对我们的数据进行预处理,但是因为不同的任务预处理的方法存在差别,因此就不在这里详细展开来说这个事情。设计一个类,用来表示我们设计好的模型在类的外面,定义我们的损失函数(loss function)和选择优化器(optimizer).其中损失函数就是我们用来梯度下降的原函数,而选择优化器则是我们选择的在梯度曲面上的更新参数的方法。选择衡量指标来度量模型的损失值(loss)和准确率(accuracy)。这些指标在 epoch 上累积值,然后打印出整体结果。使用修饰器@tf.function 和tf.GradientTape 来设计训练模型的函数。在python当中,修饰器的主要作用是在我们想给一个函数扩展功能但是又不想破坏其本身的时候,调用一个可以将函数作为对象传入的函数,将其作为修饰器,从而实现上述功能的。在这里修饰器的作用是取代原来的回话所存在的。参考内容地址训练并测试我们的模型。
示例代码详解
将 Tensorflow 导入您的程序:
from __future__
import absolute_import
, division
, print_function
, unicode_literals
import tensorflow
as tf
from tensorflow
.keras
.layers
import Dense
, Flatten
, Conv2D
from tensorflow
.keras
import Model
加载并准备 MNIST 数据集,并使用 tf.data 来将数据集切分为 batch 以及混淆数据集
mnist
= tf
.keras
.datasets
.mnist
(x_train
, y_train
), (x_test
, y_test
) = mnist
.load_data
()
x_train
, x_test
= x_train
/ 255.0, x_test
/ 255.0
x_train
= x_train
[..., tf
.newaxis
]
x_test
= x_test
[..., tf
.newaxis
]
train_ds
= tf
.data
.Dataset
.from_tensor_slices
(
(x_train
, y_train
)).shuffle
(10000).batch
(32)
test_ds
= tf
.data
.Dataset
.from_tensor_slices
((x_test
, y_test
)).batch
(32)
创建你的模型类 在构建我们模型的时候,我们定义了自己的模型类Mymodel,这个类继承自tf.keras.Model这个类。之后我们使用super函数。super 是用来解决多重继承问题的。而这里我们直接在mymodel类中调用父类的初始化函数并将这个实例转换为子类的实例,这是我们为子类添加了几个新的属性,也就是我们那这里的一个过滤层,一个卷基层和两个全联接层的对象。
class MyModel(Model
):
def __init__(self
):
super(MyModel
, self
).__init__
()
self
.conv1
= Conv2D
(32, 3, activation
='relu')
self
.flatten
= Flatten
()
self
.d1
= Dense
(128, activation
='relu')
self
.d2
= Dense
(10, activation
='softmax')
def call(self
, x
):
x
= self
.conv1
(x
)
x
= self
.flatten
(x
)
x
= self
.d1
(x
)
return self
.d2
(x
)
model
= MyModel
()
定义你的损失函数(在这里这个函数是一个对象也是一个函数。)选择优化器也是同理。同时你的训练损失,测试损失,训练精度,测试精度也是以对象的形式存在。
loss_object
= tf
.keras
.losses
.SparseCategoricalCrossentropy
()
optimizer
= tf
.keras
.optimizers
.Adam
()
train_loss
= tf
.keras
.metrics
.Mean
(name
='train_loss')
train_accuracy
= tf
.keras
.metrics
.SparseCategoricalAccuracy
(name
='train_accuracy')
test_loss
= tf
.keras
.metrics
.Mean
(name
='test_loss')
test_accuracy
= tf
.keras
.metrics
.SparseCategoricalAccuracy
(name
='test_accuracy')
设计你的训练函数和测试函数。其中在训练函数当中,@tf.function取代了tf.session的作用。其他内容都是显而易见的,这里就不赘述了。
@tf
.function
def train_step(images
, labels
):
with tf
.GradientTape
() as tape
:
predictions
= model
(images
)
loss
= loss_object
(labels
, predictions
)
gradients
= tape
.gradient
(loss
, model
.trainable_variables
)
optimizer
.apply_gradients
(zip(gradients
, model
.trainable_variables
))
train_loss
(loss
)
train_accuracy
(labels
, predictions
)
@tf
.function
def test_step(images
, labels
):
predictions
= model
(images
)
t_loss
= loss_object
(labels
, predictions
)
test_loss
(t_loss
)
test_accuracy
(labels
, predictions
)
进行训练,并显示
EPOCHS
= 5
for epoch
in range(EPOCHS
):
for images
, labels
in train_ds
:
train_step
(images
, labels
)
for test_images
, test_labels
in test_ds
:
test_step
(test_images
, test_labels
)
template
= 'Epoch {}, Loss: {}, Accuracy: {}, Test Loss: {}, Test Accuracy: {}'
print (template
.format(epoch
+1,
train_loss
.result
(),
train_accuracy
.result
()*100,
test_loss
.result
(),
test_accuracy
.result
()*100))
总结
与之前繁琐的回话中进行训练以及形形色色的调用层的方法,我个人认为在2.0当中,tf.function大大简化了tensorflow的操作逻辑,变得更加易于上手,这个文档简单介绍了训练一个神经网络的基本流程。 但是我依然存在一些疑问,希望在接下来的学习当中进行解答。事实上,很多时候损失函数我们并不能直接轻松的就从tf当中调用出来,更多的时候,损失函数需要我们亲手进行设计,学习完这个文档之后,我还没有掌握如何自行设计损失函数。同时,我还发现在这个例子当中,并没有出现我们在1.x的类设计当中最为关键的placeholder的设计,不知道是不是已经不需要这样做了(因为他直接调取的数据是来自tf.data的数据)。