在TensorFlow 1.X版本中,调用tf.enable_eager_execution()函数启动Eager Execution模式。则需要调用tf.compat.v1.disable_eager_execution()函数)张量流使用张量(张量)作为数据的基本单元。
自动求导机制
对y = x*x的导数
import tensorflow as tf
x = tf.Variable(initial_value=3.)
with tf.GradientTape() as tape: # 在 tf.GradientTape() 的上下文内,所有计算步骤都会被记录以用于求导
y = tf.square(x)
y_grad = tape.gradient(y, x) # 计算y关于x的导数
print([y, y_grad])
x 是一个初始化为3的 变量 (Variable),使用 tf.Variable() 声明。与普通张量一样,变量同样具有形状、类型和值三种属性。使用变量需要有一个初始化过程,可以通过在tf.Variable() 中指定initial_value 参数来指定初始值。变量与普通张量的一个重要区别是其默认能够被TensorFlow的自动求导机制所求导,因此往往被用于定义机器学习模型的参数。tf.GradientTape() 是一个自动求导的记录器,在其中的变量和计算步骤都会被自动记录。在上面的示例中,变量 x 和计算步骤 y = tf.square(x) 被自动记录,因此可以通过 y_grad =tape.gradient(y, x) 求张量 y 对变量 x 的导数。在机器学习中,更加常见的是对多元函数求偏导数,以及对向量或矩阵的求导。以下代码是如何使用 tf.GradientTape() 计算函数的偏导数。
x = tf.constant([[1., 2.], [3., 4.]])
y = tf.constant([[1.], [2.]])
w = tf.Variable(initial_value=[[1.], [2.]])
b = tf.Variable(initial_value=1.)
with tf.GradientTape() as tape:
L = 0.5 * tf.reduce_sum(tf.square(tf.matmul(x, w) + b - y))
w_grad, b_grad = tape.gradient(L, [w, b]) # 计算L(w, b)关于w, b的偏导数
print([L.numpy(),w_grad.numpy(),b_grad.numpy])
numpy下线性回归:
a, b = 0, 0
num_epoch = 10000
learning_rate = 1e-3
for e in range(num_epoch):
# 手动计算损失函数关于自变量(模型参数)的梯度
y_pred = a * X + b
grad_a, grad_b = (y_pred - y).dot(X), (y_pred - y).sum()
# 更新参数
a, b = a - learning_rate * grad_a, b - learning_rate * grad_b
print(a, b)
tensorflow下的线性回归
import tensorflow as tf
x = tf.constant(x)
y = tf.constant(y)
a = tf.Variable(initial_value=0.)
b = tf.Variable(initial_value=0.)
variables = [a,b]
num_epoch = 10000
optimizer = tf.keras.optimizers.SGD(learning_rate = 0.0003)
for e in range(num_epoch):
# 使用tf.GradientTape()记录损失函数的梯度
with tf.GradientTape() as tape:
y_pred = a * x + b
loss = 0.5 * tf.reduce_sum(tf.square(y_pred - y)) # 损失函数
grads = tape.gradient(loss, variables) # 求偏导
optimizer.apply_gradients(grads_and_vars = zip(grads, variables)) # 优化器
print(a, b)
使用tf.keras.optimizers.SGD(learning_rate=1e-3) 声明了一个梯度下降 优化器 (Optimizer)。优化器可以帮助我们根据计算出的求导结果更新模型参数,从而最小化某个特定的损失函数,具体使用方式是调用其 apply_gradients() 方法。 optimizer.apply_gradients() 需要提供参数 grads_and_vars ,即待更新的变量(如上述代码中的 variables )及损失函数关于这些变量的偏导数(如上述代码中的grads )。这里需要传入一个Python列表(List),列表中的每个元素是一个 (变量的偏导数,变量)对。比如这里是 [(grad_a, a), (grad_b, b)] 。我们通过 grads = tape.gradient(loss,variables) 求出tape中记录的 loss 关于 variables = [a, b] 中每个变量的偏导数,也就是grads = [grad_a, grad_b] ,再使用Python的 zip() 函数将 grads = [grad_a, grad_b] 和variables = [a, b] 拼装在一起,就可以组合出所需的参数了。
自定义模型类
在实际中使用实例化的模型类model = Modle 代替y = a * x +b ,然后使用y_pred = model(x)调用模型,并使用model.variables获取模型参数
tensorflow模型建立和训练,模型(model)和层(layer)
'''
模型类
'''
class MyModel(tf.keras.Model):
def __init__(self):
super().__init__() # python2中 super(MyModel,self).__init__()
# 此处添加初始代码(包含call方法中会用到的层),例如
# layer1 = tf.keras.layers.BuiltInLayer(...)
# layer2 = MyCustomLayer()
def call(self,input):
# 此处添加模型调用的代码(处理输入并返回输出),例如
# x = layer1(input)
# output = layer2(x)
# 还可以添加自定义的函数
将上面线性模型y_pred = a * x + b ,以模型类的方式编写:
import tensorflow as tf
x = tf.constant([[1.0,2.0,3.0],[4.0,5.0,6.0]])
y = tf.constant([[10.0],[20.0]])
class Linear(tf.keras.Model):
def __init__(self):
super().__init__()
self.dense = tf.keras.layer.Dence(
units = 1,
activation=None,
kernel_initializer=tf.zeors_initializer(),
bias_initializer=tf.zeros_initializer(),
)
def call(self,input):
output = self.dense(input)
return output =
model = Linear()
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
for i in range(100):
with tf.GradieneTape() as tape:
y_pred = model(x) # 全连接层(不激活时)相当于线性变换
loss = tf.reduce_mean(tf.square(y_pred - y))
grads = tape.gradient(loss,model.variables) # model.variables获取模型中的所有变量
optimizer.apply_gradients(grads_and_vars=zip(grads,model.variables))
print(model.variables)
多层感知机(MLP),进行一下步骤:
1、使用 tf.keras,datasets 获取数据集并预处理
2、使用 tf.keras.Model 和 tf.keras.layers 构建模型
3、构建模型训练流程,使用 tf.keras.losses 进行损失函数的计算,并使用 tf.keras.optimizer 优化模型
4、构建模型评估流程,使用 tf.keras.metrics计算评估指标
import tensorflow as tf
'''
加载数据
'''
class MNISTLoader():
def __init__(self):
mnist = tf.keras.datasets.mnist # 自动从网上加载数据
(self.train_data,self.train_label),(self.test_train,self.test_label) = mnist.load_data()
# MNIST中的图像默认为unit8(0-255)。下面将其归一化,并在最后加一维作为颜色通道
self.train_data = np.expand_dims(self.train_data.astype(np.float32) / 255.0,axis = -1)
# [60000,28,28,1],np.expand_dims()添加一维通道
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)
self.test_label = self.test_label.astype(np.int32)
self.num_train_data,self_num_test_data = self.train_data.shape[0],self.test_data.shape[0]
def get_batch(self,batch_size):
# 从数据中随机取出batch_size个元素并返回
index = np.random.randint(0,np.shape(self.train_data)[0],batch_size)
return self.train_data[index,:],self.train_label[index]
'''
模型构建:tf.keras.Model 和 tf.keras.Layer
'''
class MLP(tf.keras.Model):
def __init__(self):
super().__init__:
self.flatten = tf.keras.layers.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): # [batch_size,28,28,1]
x = self.flatten(inputs) # [batch_size,784]
x = self.dense1(x) # [batch_size,100]
x = self.dense2(x) # [batch_size,10]
output = tf.nn.softmax(x)
'''
模型训练:tf.keras.losses 和 tf.keras.optimizer
'''
num_epochs = 5
batch_size = 50
learning_rate = 0.001
model = MLP()
data_loader = MNISTLoader()
optimizer = tf.keras.optimizers.Adam(learning_rate)
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.GradieneTape() as tape:
y_pred = model(x)
loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y,y_pred=y_pred)
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))
'''
模型评估:tf.keras.metrics
'''
sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy()
num_batches = int(data_losder.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_ture = data_loader.test_label[start_index:
end_index],y_pred=y_pred)
print("test accuracy: %f" % sparse_categorical_accuracy.result())