簡單說分四步
01準備數(shù)據(jù) 02搭建網(wǎng)絡 03優(yōu)化訓練參數(shù)————(訓練部分 + 測試部分)循環(huán) 04作圖——loss,,acc
import tensorflow as tf
import numpy as np
from sklearn import datasets
from matplotlib import pyplot as plt
#01準備數(shù)據(jù)
x_data=datasets.load_iris().data
y_data=datasets.load_iris().target
#數(shù)據(jù)集亂序
np.random.seed(116)
np.random.shuffle(x_data)
np.random.seed(116)
np.random.shuffle(y_data)
tf.random.set_seed(116)
#劃分訓練集(前120個數(shù)據(jù))和測試集(后30個數(shù)據(jù))
x_train=x_data[:-30]
y_train=y_data[:-30]
x_test=x_data[-30:]
y_test=y_data[-30:]
#統(tǒng)一數(shù)據(jù)類型為float32,以免后面矩陣相乘時因為數(shù)據(jù)類型不一致而報錯
x_train=tf.cast(x_train,tf.float32)
x_test=tf.cast(x_test,tf.float32)
#數(shù)據(jù)配對,,使用tensorflow數(shù)據(jù)切片
#使得輸入數(shù)據(jù)(特征)和標簽一一配對,,訓練集120對數(shù)據(jù),測試集30對數(shù)據(jù)
#并分組打包,,每32對數(shù)據(jù)打包為一個batch,,方便后面模型訓練
#所以訓練集包含4個batch,,測試集包含1個batch
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)
#02 搭建網(wǎng)絡
#定義網(wǎng)絡的初始參數(shù)
#隨機生成符合[截斷式正太分布]的初始參數(shù) w1[4*3] 和 b1[3]
#參數(shù)標要記為可訓練Variable,而不是常量constant
#標準差0.1,,隨機數(shù)種子seed=1
#(truncated——截斷式,,意思就是生成的參數(shù),在均值的上下兩個標準差范圍內,,是為了讓生成的隨機數(shù)不要相差太多)
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.1 #學習率
epoch=500
#迭代次數(shù)500輪,,每輪都在更新參數(shù),看能不能吧損失函數(shù)降到最低,,不能的話可以再增加迭代次數(shù)
#可以看到結果,,大概185次迭代后,acc就達到1了,,但是loss還在降低,。注意過擬合問題
#新建兩個空列表
#一個記錄每一輪訓練后得到的損失函數(shù)值loss,一個記錄每一輪測試后得到的精度acc
#兩個列表后期用于作圖
train_loss_results=[]
test_acc=[]
#上面說到120個訓練樣本組成的訓練集,,我們劃分為4個batch來喂給模型
#所以每輪都會產(chǎn)生四個loss
#每輪記錄的loss應該是四個loss的平均值
#設置一個變量來累加這四個loss
loss_all=0
#03 優(yōu)化訓練參數(shù)————(訓練部分 + 測試部分)循環(huán)500次
#一:訓練部分
#兩層for循環(huán),,外層執(zhí)行500次,內層是4個訓練集的batch和1個測試集的batch
for epoch in range (epoch):
for step , (x_train,y_train) in enumerate(train_db):
#在with結構中記錄梯度信息,,計算每一輪batch的損失函數(shù)值
with tf.GradientTape() as tape:
y=tf.matmul(x_train,w1)+ b1 #計算訓練集的預測值
y=tf.nn.softmax(y) #使y值符合概率分布——softmax激活函數(shù)就是歸一化
y_=tf.one_hot(y_train,depth=3)#使訓練集的標簽轉變?yōu)楠殶岽a
#定義損失函數(shù)為——均方誤差損失函數(shù)
loss=tf.reduce_mean(tf.square(y_-y))
#累計四個batch的loss值,,方便后面求每次迭代里,loss的平均值
loss_all=loss_all+loss.numpy()
tf.reduce_mean 函數(shù) 用于計算張量tensor沿著指定的數(shù)軸(tensor的某一維度)上的的平均值,,主要用作降維或者計算tensor(圖像)的平均值,。
tf.reduce_mean(input_tensor, axis=None, keep_dims=False, name=None )
第一個參數(shù)input_tensor: 輸入的待降維的tensor; 第二個參數(shù)axis: 指定的軸,如果不指定,,則計算所有元素的均值; 第三個參數(shù)keep_dims:是否降維度,, 設置為True,輸出的結果保持輸入tensor的形狀,,設置為False,,輸出結果會降低維度;
#進行完一次batch后更新參數(shù)
#01求導(損失函數(shù)對各個參數(shù)),02更新
grads =tape.gradient(loss,[w1,b1])
w1.assign_sub(lr*grads[0])
b1.assign_sub(lr*grads[1])
# ---------- 至此,,一個batch的訓練結束,,獲得了一個損失函數(shù)值,兩個參數(shù)各更新了1次
#每結束一次epoch,,打印一次loss信息(也就是四個batch,,獲得了四次loss累計值loss_all)
print("Epoch{}\nloss:{}".format(epoch,loss_all/4))
#記錄下這輪epoch的loss值 到 之前新建的空列表中,方便后面作圖,,同時清空loss_all
train_loss_results.append(loss_all/4)
loss_all=0
#二:測試部分
#注意是包含在外層循環(huán)里的 也就是訓練500輪,,每一輪都在更新參數(shù)獲得loss,每一輪最后都會測試獲得acc
#預測正確的樣本個數(shù),,測試的總樣本個數(shù)
total_correct,total_number=0,0
#遍歷測試集中的所有數(shù)據(jù),,計算前想傳播的預測結果
for x_test,y_test in test_db:
#使用更新后的參數(shù)進行預測,,并計算分類準確度acc
y=tf.matmul(x_test,w1)+ b1
y=tf.nn.softmax(y)
#返回y中最大值的索引,即預測的類別號
pred=tf.argmax(y,axis=1) #axis=1,橫向比較
#將pred轉換為和y_test一致的數(shù)據(jù)類型,,方便比較
pred=tf.cast(pred,dtype=y_test.dtype)
#將pred 與 y_test 相比較 ,,若分類正確,則令correct=1,,否則為0
#這里需要把equal的結果(bool類型)轉換為int類型
correct=tf.cast(tf.equal(pred,y_test),dtype=tf.int32)
#將每個batch的correct值加起來
correct=tf.reduce_sum(correct)
#將所有batch的correct值加起來
total_correct=total_correct+int(correct)
#total_number為測試的總樣本數(shù),,也就是x_test的行數(shù),.shape[0]返回變量行數(shù)
total_number=total_number+x_test.shape[0] #————————說實話不是很懂這里啥意思,,為什么要累加
#計算準確率acc,,每一輪epoch計算一次
acc=total_correct/total_number
#將每一輪的acc丟到之前的空列表,方便后面作圖
test_acc.append(acc)
print("Test_acc:",acc)
print("----------------------------------")
輸出結果:
Epoch0
loss:0.282131090760231
Test_acc 0.16666666666666666
----------------------------------
Epoch1
loss:0.25459615513682365
Test_acc 0.16666666666666666
----------------------------------
Epoch2
loss:0.22570250555872917
Test_acc 0.16666666666666666
----------------------------------
Epoch3
loss:0.21028400212526321
Test_acc 0.16666666666666666
----------------------------------
Epoch4
loss:0.19942264258861542
Test_acc 0.16666666666666666
----------------------------------
Epoch5
loss:0.18873638287186623
Test_acc 0.5
----------------------------------
Epoch6
loss:0.17851299792528152
Test_acc 0.5333333333333333
----------------------------------
Epoch7
loss:0.16922874748706818
Test_acc 0.5333333333333333
----------------------------------
Epoch8
loss:0.16107673197984695
Test_acc 0.5333333333333333
----------------------------------
Epoch9
loss:0.15404684096574783
Test_acc 0.5333333333333333
----------------------------------
·
·
·
·
·
·
Epoch500
#04 作圖————loss,,acc
#loss曲線
plt.title("Loss Function Curve")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.plot(train_loss_results,label="$loss$") #這里的label是指圖片上的圖例名稱
plt.legend() #圖片上的圖例
plt.show()
#accuracy曲線
plt.title("Acc Curve")
plt.xlabel("epoch")
plt.ylabel("acc")
plt.plot(test_acc,label="$acc$") #這里的label是指圖片上的圖例名稱
plt.legend() #圖片上的圖例
plt.show()
|