本章主要利用多層感知機實現圖像分類,具體將構造參數、模型結構、準確率等等。
1、數據集讀取及歸一化
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
x_train, x_test = tf.cast(x_train / 255.0,tf.float32), tf.cast(x_test / 255.0,tf.float32)
print(x_train.shape,y_train.shape)
# 將訓練數據的特徵和標籤組合
batch_size=256
train_dataset = tfdata.Dataset.from_tensor_slices((x_train, y_train)).shuffle(x_train.shape[0])
test_dataset = tfdata.Dataset.from_tensor_slices((x_test, y_test))
train_iter=train_dataset.batch(batch_size)
test_iter=test_dataset.batch(batch_size)
2、定義模型參數
num_inputs=28*28
num_hidden=128
num_outputs=10
W1 = tf.Variable(tf.random.normal(shape=(num_inputs, num_hidden),mean=0, stddev=0.01, dtype=tf.float32))
b1 = tf.Variable(tf.zeros(num_hidden, dtype=tf.float32))
W2 = tf.Variable(tf.random.normal(shape=(num_hidden, num_outputs),mean=0, stddev=0.01, dtype=tf.float32))
b2 = tf.Variable(tf.random.normal([num_outputs], stddev=0.1))
3、定義relu激活函數
def relu(x):
return tf.math.maximum(x, 0)
4、定義模型
根據f(x)=Xw+b進行計算:
def net(x):
x = tf.reshape(x, [-1, num_inputs])
result1 = relu(tf.matmul(x, W1) + b1)
return tf.math.softmax(tf.matmul(result1, W2) + b2)
5、定義損失函數
#爲了有更好的數值穩定性,使用API
def loss(y_hat,y_true):
return tf.losses.sparse_categorical_crossentropy(y_true,y_hat)
6、定義準確率
def accuracy(y_hat, y):
return np.mean((tf.cast(tf.argmax(y_hat, axis=1), tf.int32) == tf.cast(y, tf.int32)))
7、定義驗證集準確率
def evaluate_accuracy(test_iter):
acc_sum, n = 0.0, 0
for X, y in test_iter:
n += 1
y = tf.cast(y, dtype=tf.int32)
output = net(X)
acc_sum += accuracy(output, y)
return acc_sum / n
8、定義SGD優化器
def sgd(params, lr, batch_size, grads):
for i, param in enumerate(params):
param.assign_sub(lr * grads[i] / batch_size)
9、訓練
def train(num_epochs,lr,params):
for epoch in range(num_epochs):
train_l_sum, train_acc_sum, n = 0.0, 0.0, 0
for X, y in train_iter:
n+=1 #一個epoch取多少次
with tf.GradientTape() as t:
t.watch(params)
l = tf.reduce_mean(loss(net(X), y))
grads = t.gradient(l, params) # 通過調用反向函數t.gradients計算小批量隨機梯度,並調用優化算法sgd迭代模型參數
sgd(params, lr, batch_size, grads)
train_acc_sum+=accuracy(net(X),y)
train_l_sum+=l.numpy()
test_acc=evaluate_accuracy(test_iter)
print("epoch %d, train loss:%.6f, train acc:%.5f, test acc:%.5f"%(epoch,train_l_sum/n,train_acc_sum/n,test_acc))
結果:
10、預測
def show_image(image): # 顯示圖像
n=image.shape[0]
_,figs=plt.subplots(1,n,figsize=(15,15))
for i in range(n):
figs[i].imshow(image[i].reshape((28,28)))
plt.show()
def get_fashion_mnist_labels(labels):# 顯示圖像標籤
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[int(i)] for i in labels]
def predict(image_10):
label_10 = y_test[:10] # 拿到前10個數據
show_image(image_10)
print("真實樣本標籤:", label_10)
print("真實數字標籤對應的服飾名:", get_fashion_mnist_labels(label_10))
image_10 = tf.cast(image_10/255.0,tf.float32)
predict_label = tf.argmax(net(image_10),1).numpy()
print("預測樣本標籤:", predict_label.astype("int8"))
print("預測數字標籤對應的服飾名:", get_fashion_mnist_labels(predict_label))
結果:
附上所有源碼:
import tensorflow as tf
from tensorflow.keras.datasets import fashion_mnist
import matplotlib.pyplot as plt
import numpy as np
from tensorflow import data as tfdata
# 1、數據集讀取及歸一化
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
image_10=x_test[:10]
x_train, x_test = tf.cast(x_train / 255.0,tf.float32), tf.cast(x_test / 255.0,tf.float32)
print(x_train.shape, y_train.shape)
# 將訓練數據的特徵和標籤組合
batch_size = 256
train_dataset = tfdata.Dataset.from_tensor_slices((x_train, y_train)).shuffle(x_train.shape[0])
test_dataset = tfdata.Dataset.from_tensor_slices((x_test, y_test))
train_iter = train_dataset.batch(batch_size)
test_iter = test_dataset.batch(batch_size)
# 2、定義模型參數
num_inputs = 28 * 28 # 輸入神經元個數
num_hidden = 128 # 隱藏層個數
num_outputs = 10 # 分類數
W1 = tf.Variable(tf.random.normal(shape=(num_inputs, num_hidden), mean=0, stddev=0.01, dtype=tf.float32))
b1 = tf.Variable(tf.zeros(num_hidden, dtype=tf.float32))
W2 = tf.Variable(tf.random.normal(shape=(num_hidden, num_outputs), mean=0, stddev=0.01, dtype=tf.float32))
b2 = tf.Variable(tf.random.normal([num_outputs], stddev=0.1))
# 3、定義relu激活函數
def relu(x):
return tf.math.maximum(x,0)
# 4、定義模型
def net(X):
x = tf.reshape(X, shape=[-1, num_inputs])
h = relu(tf.matmul(x, W1) + b1)
return tf.math.softmax(tf.matmul(h, W2) + b2)
# 5、定義損失函數
# 爲了有更好的數值穩定性,使用API
def loss(y_hat, y_true):
return tf.losses.sparse_categorical_crossentropy(y_true, y_hat)
# 6、計算準確率
def accuracy(y_hat, y):
return np.mean((tf.cast(tf.argmax(y_hat, axis=1), tf.int32) == tf.cast(y, tf.int32)))
# 7、計算測試集準確率
def evaluate_accuracy(test_iter):
acc_sum, n = 0.0, 0
for X, y in test_iter:
n += 1
y = tf.cast(y, dtype=tf.int32)
output = net(X)
acc_sum += accuracy(output, y)
return acc_sum / n
# 8、SGD優化器
def sgd(params, lr, batch_size, grads):
for i, param in enumerate(params):
param.assign_sub(lr * grads[i] / batch_size)
#9、訓練
def train(num_epochs,lr,params):
for epoch in range(num_epochs):
train_l_sum, train_acc_sum, n = 0.0, 0.0, 0
for X, y in train_iter:
n+=1 #一個epoch取多少次
with tf.GradientTape() as t:
t.watch(params)
l = tf.reduce_mean(loss(net(X), y))
grads = t.gradient(l, params) # 通過調用反向函數t.gradients計算小批量隨機梯度,並調用優化算法sgd迭代模型參數
sgd(params, lr, batch_size, grads)
train_acc_sum+=accuracy(net(X),y)
train_l_sum+=l.numpy()
test_acc=evaluate_accuracy(test_iter)
print("epoch %d, train loss:%.6f, train acc:%.5f, test acc:%.5f"%(epoch,train_l_sum/n,train_acc_sum/n,test_acc))
# 10、預測
def show_image(image): # 顯示圖像
n=image.shape[0]
_,figs=plt.subplots(1,n,figsize=(15,15))
for i in range(n):
figs[i].imshow(image[i].reshape((28,28)))
plt.show()
def get_fashion_mnist_labels(labels):# 顯示圖像標籤
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[int(i)] for i in labels]
def predict(image_10):
label_10 = y_test[:10] # 拿到前10個數據
show_image(image_10)
print("真實樣本標籤:", label_10)
print("真實數字標籤對應的服飾名:", get_fashion_mnist_labels(label_10))
image_10 = tf.cast(image_10/255.0,tf.float32)
predict_label = tf.argmax(net(image_10),1).numpy()
print("預測樣本標籤:", predict_label.astype("int8"))
print("預測數字標籤對應的服飾名:", get_fashion_mnist_labels(predict_label))
if __name__=="__main__":
train(50,0.3,params=[W1,b1,W2,b2])
predict(image_10)# 預測