#導入所需模塊
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
#隨機打亂數據,因爲原始數據是順序的,順序不打亂會影響準確率
#seed:隨機種子,是一個整數,當設置之後,每次生成的隨機數都一樣
np.random.seed(116)
np.random.shuffle(x_data)
np.random.seed(116)
np.random.shuffle(y_data)
tf.random.set_seed(116)
#將打亂的數據集分爲訓練集和測試集
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)
#from_tensor_slices函數使輸入特徵和標籤一一對應(把數據集分批次,每個批次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)
#生成神經網絡的參數,4個輸入特徵,故輸入層爲4個節點,,因爲分爲3類,故輸出層爲3個神經元
#用tf.Variable()標記參數可訓練
#使用seed使每次生成的隨機數相同
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 #學習率爲0.1
train_loss_results = [] #將每輪的loss記錄在此列表中,爲後續畫loss曲線提供數據
test_acc = [] #將每輪的acc記錄在此列表中,爲後續話acc曲線提供數據
epoch = 500 #循環500次
loss_all = 0 #每輪分爲4個step,loss_all記錄四個step生成的4個loss和
#訓練
for epoch in range(epoch): #數據級別的循環,每個epoch循環一次數據集
for step,(x_train,y_train) in enumerate(train_db): #batch級別的循環,每個step循環一個batch
with tf.GradientTape() as tape: #with結構記錄梯度信息
y = tf.matmul(x_train,w1) + b1 #神經網絡的乘加運算
y = tf.nn.softmax(y) #使輸出y符合概率分佈(此操作後與獨熱編碼同量級)
y_ = tf.one_hot(y_train,depth=3) #將標籤值轉換爲獨熱編碼格式,方便計算loss和accuracy
loss = tf.reduce_mean(tf.square(y_ - y)) #採用均方誤差損失函數mse = mean(sum(y - out)^2)
loss_all += loss.numpy() #將每個step計算出來的loss值累加,爲後續求loss平均值提供數據,這樣計算的loss更準確
grads = tape.gradient(loss,[w1,b1]) #對loss函數進行求梯度
w1.assign_sub(lr * grads[0]) #參數w1自更新
b1.assign_sub(lr * grads[1]) #參數b1自更新
print("Epoch {},loss: {}".format(epoch,loss_all/4)) #每個epoch,打印loss信息
train_loss_results.append(loss_all / 4) #將4個step的loss平均記錄在此變量中
loss_all = 0 #loss_all歸零,爲記錄一個epoch的loss做準備
#測試
#total_correct爲預測對的樣本的個數,total_number爲測試的總樣本數,將這兩個變量都初始化爲0
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)
pred = tf.argmax(y,axis=1) #返回y中最大值的索引,即預測的分類
pred = tf.cast(pred,dtype=y_test.dtype) #將pred轉換爲y_test的數據類型
correct = tf.cast(tf.equal(pred,y_test),dtype=tf.int32) #若分類正確,則correct=1,否則correct=0,將bool型的結果轉換爲int型
correct = tf.reduce_sum(correct) #將每個batch的correct數加起來
total_correct += int(correct) #將所有batch的correct數加起來
total_number += x_test.shape[0] #total_number爲測試的總樣本數,也就是x_test的行數,shape[0]返回變量的行數
acc = total_correct / total_number #總的正確率等於total_correct / total_number
test_acc.append(acc)
print("Test_acc",acc)
print("--------------------")
# 繪製loss曲線
plt.title('loss Function Curve') #圖片標題
plt.xlabel('epoch') #x軸變量名稱
plt.ylabel('loss') #y軸變量名稱
plt.plot(train_loss_results,label="$Loss$") #逐點畫出train_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()
下面的是筆者的微信公衆號,歡迎關注,會持續更新c++、python、tensorflow、機器學習、深度學習等系列文章