主要步驟:
1.准備數據
- 數據集讀入
- 數據集亂序
- 將數據集分為訓練集和測試集
- 將輸入特征和標簽配對,每次喂入神經網絡一小撮(batch)
2.搭建網絡
- 定義神經網絡中所有可訓練參數
3.參數優化
- 反向傳播,不斷減少loss
4.測試效果
- 計算當前參數前向傳播后的准確率
代碼:
import tensorflow as tf from sklearn import datasets from matplotlib import pyplot as plt import numpy as np # 導入輸入特征和標簽
x_data = datasets.load_iris().data y_data = datasets.load_iris().target # 隨機打亂數據 # 使用相同的隨機種子,保證輸入特征和標簽一一對應
np.random.seed(116) np.random.shuffle(x_data) np.random.seed(116) np.random.shuffle(y_data) tf.random.set_seed(116) # 將打亂后的數據分割為訓練集(前120行)和測試集(后30行)
x_train = x_data[:-30] y_train = y_data[:-30] x_test = x_data[-30:] y_test = y_data[-30:] # 轉換x的數據類型,保證后面矩陣相乘時數據類型一致
x_train = tf.cast(x_train, tf.float32) x_test = tf.cast(x_test, tf.float32) # 將輸入特征和標簽一一配對 # 每32組數據,打包一次,分批次喂入神經網絡
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32) test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32) # 聲明神經網絡的參數 # 4個輸入特征,3個分類,故輸入層為4個輸入節點,輸出層為3個神經元
w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1)) b1 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1)) # 學習率
lr = 0.2
# 記錄每輪訓練后的loss,為后續畫loss曲線提供參數
train_loss_results = [] # 記錄每輪訓練后的正確率
test_acc = [] # 將數據喂入神經網絡500次
epoch = 500
# 因為數據分批次喂入神經網絡,所以需要求和
loss_all = 0 # 數據集級別的循環,每個epoch喂入一次數據集
for epoch in range(epoch): # batch級別的循環,每個step喂入一個batch
for step, (x_train, y_train) in enumerate(train_db): with tf.GradientTape() as tape: # 神經網絡乘加操作
y = tf.matmul(x_train, w1) + b1 # 使y符合概率分布,與獨熱碼同級,相減可求loss
y = tf.nn.softmax(y) # 將標簽轉換為獨熱碼格式,方便計算loss和accuracy
y_ = tf.one_hot(y_train, depth=3) # 使用均方誤差損失函數
loss = tf.reduce_mean(tf.square(y_ - y)) # 將每個step計算出來的loss累加
loss_all += loss.numpy() # 計算loss對各參數的導數
grads = tape.gradient(loss, [w1, b1]) # 參數w1和b1自更新
w1.assign_sub(lr * grads[0]) b1.assign_sub(lr * grads[1]) # 輸出每次訓練的loss
# 因為有4組batch,所以除以4
print("epoch:%d loss:%f" % (epoch, loss_all/4)) # 記錄每次訓練的loss,方便后面繪制loss變化曲線圖
train_loss_results.append(loss_all/4) # 歸零,方便下次統計
loss_all = 0 # 調用測試數據,統計正確率
# total_correct為正確個數, total_number為測試總數
# 注意,此時仍為batch級別的循環,每次循環,喂入一個batch
total_correct, total_number = 0, 0 for x_test, y_test in test_db: # 使用更新后的參數進行預測
y = tf.matmul(x_test, w1) + b1 y = tf.nn.softmax(y) # 返回y中最大值的索引,即預測的分類
pred = tf.argmax(y, axis=1) # 將pred轉換成y_test的類型
pred = tf.cast(pred, dtype=y_test.dtype) # 將bool類型轉換成int類型,若分類正確correct=1,否則為0
correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32) # 計算每個batch中的correct數
correct = tf.reduce_sum(correct) # 將所有batch中的correct數加起來
total_correct += int(correct) # x_test有多少行,每個batch就有多少樣本
total_number += x_test.shape[0] acc = total_correct/total_number test_acc.append(acc) print("test_acc:%f" % acc) print("****************") # 繪制 loss 曲線
plt.title('Loss Function Curve') # 圖片標題
plt.xlabel('Epoch') # x軸變量名稱
plt.ylabel('Loss') # y軸變量名稱
plt.plot(train_loss_results, label="$Loss$") # 逐點畫出trian_loss_results值並連線,連線圖標是Loss
plt.legend() # 畫出曲線圖標
plt.show() # 畫出圖像
# 繪制 Accuracy 曲線
plt.title('Acc Curve') # 圖片標題
plt.xlabel('Epoch') # x軸變量名稱
plt.ylabel('Acc') # y軸變量名稱
plt.plot(test_acc, label="$Accuracy$") # 逐點畫出test_acc值並連線,連線圖標是Accuracy
plt.legend() plt.show()
運行結果: