1、导入数据
from tensorflow import keras
fashion_mnist = keras.datasets.fashion_mnist
(x_train,y_train),(x_test,y_test) = fashion_mnist.load_data()
print(y_train)
print(x_test.shape)
print(x_train.shape)
-----------------------------------------------
[9 0 0 ... 3 0 5]
(10000, 28, 28)
(60000, 28, 28)
2、求导
import tensorflow as tf
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])
print([L.numpy(), w_grad.numpy(), b_grad.numpy()])
----------------------------------------------------
[62.5, array([[35.],
[50.]], dtype=float32), 15.0]
3、参数更新——以线性回归为例
import tensorflow as tf
import numpy as np
X_raw = np.array([2013, 2014, 2015, 2016, 2017], dtype=np.float32)
y_raw = np.array([12000, 14000, 15000, 16500, 17500], dtype=np.float32)
#数据处理至(0,1)
X = (X_raw - X_raw.min()) / (X_raw.max() - X_raw.min())
y = (y_raw - y_raw.min()) / (y_raw.max() - y_raw.min())
# 1、定义Tensor类型
X = tf.constant(X)
y = tf.constant(y)
# 2、参数变量初始化
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=1e-3) #迭代更新器(学习率0.001)
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))
# TensorFlow自动计算损失函数关于自变量(模型参数)的梯度
grads = tape.gradient(loss, variables)
# TensorFlow自动根据梯度更新参数
optimizer.apply_gradients(grads_and_vars=zip(grads, variables))
print(a.numpy(), b.numpy())
--------------------------------------------
0.97637 0.057565063
4、使用模型——以线性回归为例
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]])
# 1、构建线性模型
class Linear(tf.keras.Model):
def __init__(self):
super().__init__()
self.dense = tf.keras.layers.Dense(
units=1,
activation=None,
kernel_initializer=tf.zeros_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.GradientTape() as tape:
y_pred = model(X)
loss = 0.5 * tf.reduce_mean(tf.square(y_pred - y))
# 使用 model.variables 这一属性直接获得模型中的所有变量
grads = tape.gradient(loss, model.variables)
optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))
print(model.variables)
---------------------------------------
[<tf.Variable 'linear/dense/kernel:0' shape=(3, 1) dtype=float32, numpy=
array([[0.6348866],
[1.2355742],
[1.8362627]], dtype=float32)>, <tf.Variable 'linear/dense/bias:0' shape=(1,) dtype=float32, numpy=array([0.60068834], dtype=float32)>]
5、评估模型
预测手写数字,使用BP神经网络
import tensorflow as tf
import numpy as np
#定义网络模型
class MLP(tf.keras.Model):
def __init__(self):
super().__init__()
# 定义两层神经网络,第一层100个神经元,激活函数relu,第二层10个神经元输出给softmax
self.flatten = tf.keras.layers.Flatten()
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) #通过指数运算,转换成概率
return output
#获取并处理数据
class MNISTLoader(object):
def __init__(self):
# 1、获取数据
(self.train_data, self.train_label), (self.test_data, self.test_label) = tf.keras.datasets.mnist.load_data()
# 2、处理数据,归一化,维度以及类型转换
# 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]
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):
# 从数据集中随机取出batch_size个元素并返回
index = np.random.randint(0, np.shape(self.train_data)[0], batch_size)
return self.train_data[index, :], self.train_label[index]
if __name__ == '__main__':
num_epochs = 5
batch_size = 64
learning_rate = 0.001
# 实例化模型和数据读取类,并实例化一个优化器,这里使用 Adam 优化器
model = MLP()
data_loader = MNISTLoader()
optimizer = tf.keras.optimizers.Adam(learning_rate=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.GradientTape() as tape:
y_pred = model(X)
# 使用tf.keras.losses计算损失,交叉熵损失
loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred)
# 求出平均损失
loss = tf.reduce_mean(loss)
if batch_index %500 == 0:
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))
#模型评估
y_pred = model.predict(data_loader.test_data)
# 定义评估函数,SparseCategoricalAccuracy()用来评估分类模型
sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy()
# 定义测试数据集一共批次的大小
sparse_categorical_accuracy.update_state(y_true=data_loader.test_label, y_pred=y_pred)
print("测试准确率: %f" % sparse_categorical_accuracy.result())
---------------------------------------------------
batch 0: loss 2.415590
batch 500: loss 0.152828
batch 1000: loss 0.091031
batch 1500: loss 0.085214
batch 2000: loss 0.151987
batch 2500: loss 0.256697
batch 3000: loss 0.018460
batch 3500: loss 0.042614
batch 4000: loss 0.079014
batch 4500: loss 0.021934
测试准确率: 0.972200
2)构建CNN模型,替换上述代码中的BP模型
class CNN(tf.keras.Model): #CNN神经网络
def __init__(self):
super().__init__()
self.conv1 = tf.keras.layers.Conv2D(
filters=32, # 卷积层神经元(卷积核)数目
kernel_size=[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],
padding='same',
activation=tf.nn.relu
)
self.pool2 = tf.keras.layers.MaxPool2D(pool_size=[2, 2], strides=2)
self.flatten = tf.keras.layers.Reshape(target_shape=(7 * 7 * 64,))
self.dense1 = tf.keras.layers.Dense(units=1024, activation=tf.nn.relu)
self.dense2 = tf.keras.layers.Dense(units=10)
def call(self, inputs):
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
-----------------------------------------
batch 0: loss 2.297870
batch 500: loss 0.034485
batch 1000: loss 0.026096
batch 1500: loss 0.009321
batch 2000: loss 0.004407
batch 2500: loss 0.009589
batch 3000: loss 0.000847
batch 3500: loss 0.024362
batch 4000: loss 0.000482
batch 4500: loss