人工智慧實踐:Tensorflow筆記:程式碼總結(2)

cs-凌晨技術工作室發表於2020-09-30

1.where(a,b,c):

關係式a成立,取b,關係式a不成立,取c。

a = tf.constant([1, 2, 3, 4, 5], dtype=tf.int32)
b = tf.constant([5, 4, 3, 2, 1], dtype=tf.int32)
c = tf.where(tf.greater(a, b), a, b)
d = tf.where(tf.less(a, b), a, b)
print(c)
print(d)

在這裡插入圖片描述

2。numpy的隨機數:

rdm = np.random.RandomState(seed=1)
a = rdm.rand() # 返回一個隨機標量
b = rdm.rand(2, 3) # 返回一個大小為23列的隨機矩陣
print("a:", a)
print("b:", b)

1.形狀描述不是使用元組
2.括號內是形狀而不是範圍。

3。vstack:矩陣每行的元素的個數相同時,在垂直方向上進行疊加。

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.vstack((a, b))
print("c:\n", c)

在這裡插入圖片描述

4。mgrid:生成等間隔數值點 格式為 起始值-結束值-步長。

x, y = np.mgrid[1:3:1, 2:4:0.5]

在這裡插入圖片描述

5。ravel:將多維陣列變成一維的。

在這裡插入圖片描述

6。np.c_:兩個一維張量進行配對。

在這裡插入圖片描述
上述三個的程式碼:np的。

x, y = np.mgrid[1:3:1, 2:4:0.5]
# ravel:多維陣列變成了一維陣列。
# np。c—_  兩個進行配對。
grid = np.c_[x.ravel(), y.ravel()]
print("x:\n", x)
print("y:\n", y)
print("x.ravel():\n", x.ravel())
print("y.ravel():\n", y.ravel())
print('grid:\n', grid)

7,學習率的指數衰減公式:原始學習率X(學習率衰減率)^(epoch/指定的數)

這樣就可以控制每多少次epoch更新一次學習率。

import tensorflow as tf

w = tf.Variable(tf.constant(5, dtype=tf.float32))

# 使用了指數衰減學習率。

epoch = 40
LR_BASE = 0.2  # 最初學習率
LR_DECAY = 0.99  # 學習率衰減率
LR_STEP = 1  # 喂入多少輪BATCH_SIZE後,更新一次學習率

for epoch in range(epoch):  # for epoch 定義頂層迴圈,表示對資料集迴圈epoch次,此例資料集資料僅有1個w,初始化時候constant賦值為5,迴圈100次迭代。
    lr = LR_BASE * LR_DECAY ** (epoch / LR_STEP)     # 利用了指數衰減的那個公式動態的更新學習率。
    with tf.GradientTape() as tape:  # with結構到grads框起了梯度的計算過程。
        loss = tf.square(w + 1)
    grads = tape.gradient(loss, w)  # .gradient函式告知誰對誰求導

    w.assign_sub(lr * grads)  # .assign_sub 對變數做自減 即:w -= lr*grads 即 w = w - lr*grads
    print("After %s epoch,w is %f,loss is %f,lr is %f" % (epoch, w.numpy(), loss, lr))

8。sigmoid啟用函式:

在這裡插入圖片描述

9,tanh啟用函式:

在這裡插入圖片描述

10,relu啟用函式:

在這裡插入圖片描述

11,leaky relu啟用函式:

在這裡插入圖片描述

12,均方誤差作為啟用函式:

loss_mse = tf.reduce_mean(tf.square(y_ - y))

import tensorflow as tf
import numpy as np

SEED = 23455

rdm = np.random.RandomState(seed=SEED)  # 生成[0,1)之間的隨機數
# rand後是維度,表示的是生成 32行 2列的資料。
x = rdm.rand(32, 2)
y_ = [[x1 + x2 + (rdm.rand() / 10.0 - 0.05)] for (x1, x2) in x]  # 生成噪聲[0,1)/10=[0,0.1); [0,0.1)-0.05=[-0.05,0.05)
x = tf.cast(x, dtype=tf.float32)
w1 = tf.Variable(tf.random.normal([2, 1], stddev=1, seed=1))

epoch = 15000
lr = 0.002

for epoch in range(epoch):
    with tf.GradientTape() as tape:
        y = tf.matmul(x, w1)
        # 均方函式誤差。
        loss_mse = tf.reduce_mean(tf.square(y_ - y))

    grads = tape.gradient(loss_mse, w1)
    w1.assign_sub(lr * grads)

    if epoch % 500 == 0:
        print('------')
        print("After %d training steps,w1 is " % (epoch))
        print(w1.numpy(), "\n")
print("Final w1 is: ", w1.numpy())

13,自定義損失函式:

import tensorflow as tf
import numpy as np

SEED = 23455
COST = 1
PROFIT = 99

rdm = np.random.RandomState(SEED)
x = rdm.rand(32, 2)
y_ = [[x1 + x2 + (rdm.rand() / 10.0 - 0.05)] for (x1, x2) in x]  # 生成噪聲[0,1)/10=[0,0.1); [0,0.1)-0.05=[-0.05,0.05)
x = tf.cast(x, dtype=tf.float32)

w1 = tf.Variable(tf.random.normal([2, 1], stddev=1, seed=1))

epoch = 10000
lr = 0.002

for epoch in range(epoch):
    with tf.GradientTape() as tape:
        y = tf.matmul(x, w1)
        # tf。where的語句,如果y大於y——   執行第一個,否則執行第二個。
        loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_) * COST, (y_ - y) * PROFIT))

    grads = tape.gradient(loss, w1)
    w1.assign_sub(lr * grads)

    if epoch % 500 == 0:
        print("After %d training steps,w1 is " % (epoch))
        print(w1.numpy(), "\n")
print("Final w1 is: ", w1.numpy())

# 自定義損失函式
# 酸奶成本1元, 酸奶利潤99元
# 成本很低,利潤很高,人們希望多預測些,生成模型係數大於1,往多了預測

14,交叉熵損失函式:評判 標準值 和 預測值 之間差距。多個預測值,熵越小的說明越接近標準值。

loss_ce1 = tf.losses.categorical_crossentropy([1, 0], [0.6, 0.4]) 第一個引數是標準的,第二個引數是預測的。

15,softmax對二維的進行求解時。

y = np.array([[12, 3, 2], [3, 10, 1], [1, 2, 5], [4, 6.5, 1.2], [3, 6, 1]])
y_pro = tf.nn.softmax(y)
print(tf.reduce_sum(y_pro, axis=0))
print(tf.reduce_sum(y_pro, axis=1))
print(y_pro)

結果:
在這裡插入圖片描述
軸為1時的計算是正確的說明按照行求和的值才為1。因此softmax對二維的求解時,相當於對每一行進行求解

16,tf.nn.softmax_cross_entropy_with_logits(y_, y):一般來說,在一些問題都會先把解轉化為概率和為1 的(用sotfmax),然後用交叉熵進行比較。可以直接呼叫這一個函式實現這兩步。

17,非線性的啟用函式寫在哪裡呢?

嗯,非常合理:
在這裡插入圖片描述

18,緩解過擬合的正則化,

# 匯入所需模組
import tensorflow as tf
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd

# 讀入資料/標籤 生成x_train y_train
df = pd.read_csv('dot.csv')
x_data = np.array(df[['x1', 'x2']])     # 3002列
y_data = np.array(df['y_c'])    # 1維向量  大小300
# 不明白這段程式碼的意義?
x_train = np.vstack(x_data).reshape(-1, 2)
y_train = np.vstack(y_data).reshape(-1, 1)
Y_c = [['red' if y else 'blue'] for y in y_train]
# 轉換x的資料型別,否則後面矩陣相乘時會因資料型別問題報錯
x_train = tf.cast(x_train, tf.float32)
y_train = tf.cast(y_train, tf.float32)

# from_tensor_slices函式切分傳入的張量的第一個維度,生成相應的資料集,使輸入特徵和標籤值一一對應
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)

# 生成神經網路的引數,輸入層為2個神經元,隱藏層為11個神經元,1層隱藏層,輸出層為1個神經元
# 用tf.Variable()保證引數可訓練
w1 = tf.Variable(tf.random.normal([2, 11]), dtype=tf.float32)
b1 = tf.Variable(tf.constant(0.01, shape=[11]))

w2 = tf.Variable(tf.random.normal([11, 1]), dtype=tf.float32)
b2 = tf.Variable(tf.constant(0.01, shape=[1]))

lr = 0.01  # 學習率
epoch = 400  # 迴圈輪數

# 訓練部分
for epoch in range(epoch):
    for step, (x_train, y_train) in enumerate(train_db):
        with tf.GradientTape() as tape:  # 記錄梯度資訊

            h1 = tf.matmul(x_train, w1) + b1  # 記錄神經網路乘加運算
            h1 = tf.nn.relu(h1)
            y = tf.matmul(h1, w2) + b2

            # 採用均方誤差損失函式mse = mean(sum(y-out)^2)
            loss = tf.reduce_mean(tf.square(y_train - y))

        # 計算loss對各個引數的梯度
        variables = [w1, b1, w2, b2]
        grads = tape.gradient(loss, variables)

        # 實現梯度更新
        # w1 = w1 - lr * w1_grad tape.gradient是自動求導結果與[w1, b1, w2, b2] 索引為0,1,2,3 
        w1.assign_sub(lr * grads[0])
        b1.assign_sub(lr * grads[1])
        w2.assign_sub(lr * grads[2])
        b2.assign_sub(lr * grads[3])

    # 每20個epoch,列印loss資訊
    if epoch % 20 == 0:
        print('epoch:', epoch, 'loss:', float(loss))

# 預測部分
print("*******predict*******")
# xx在-3到3之間以步長為0.01,yy在-3到3之間以步長0.01,生成間隔數值點
xx, yy = np.mgrid[-3:3:.1, -3:3:.1]
# 將xx , yy拉直,併合並配對為二維張量,生成二維座標點
grid = np.c_[xx.ravel(), yy.ravel()]
grid = tf.cast(grid, tf.float32)
# 將網格座標點喂入神經網路,進行預測,probs為輸出
probs = []
for x_test in grid:
    # 使用訓練好的引數進行預測
    h1 = tf.matmul([x_test], w1) + b1
    h1 = tf.nn.relu(h1)
    y = tf.matmul(h1, w2) + b2  # y為預測結果
    probs.append(y)

# 取第0列給x1,取第1列給x2
x1 = x_data[:, 0]
x2 = x_data[:, 1]
# probs的shape調整成xx的樣子
probs = np.array(probs).reshape(xx.shape)
plt.scatter(x1, x2, color=np.squeeze(Y_c)) #squeeze去掉緯度是1的緯度,相當於去掉[['red'],[''blue]],內層括號變為['red','blue']
# 把座標xx yy和對應的值probs放入contour<[‘kɑntʊr]>函式,給probs值為0.5的所有點上色  plt點show後 顯示的是紅藍點的分界線
plt.contour(xx, yy, probs, levels=[.5])
plt.show()
# 讀入紅藍點,畫出分割線,不包含正則化
# 不清楚的資料,建議print出來檢視 

正則化程式碼:

# 匯入所需模組
import tensorflow as tf
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd

# 讀入資料/標籤 生成x_train y_train
df = pd.read_csv('dot.csv')
x_data = np.array(df[['x1', 'x2']])
y_data = np.array(df['y_c'])
print('y_data', y_data.shape)
x_train = x_data
y_train = y_data.reshape(-1, 1)
print('y_train', y_train)

Y_c = [['red' if y else 'blue'] for y in y_train]

# 轉換x的資料型別,否則後面矩陣相乘時會因資料型別問題報錯
x_train = tf.cast(x_train, tf.float32)
y_train = tf.cast(y_train, tf.float32)

# from_tensor_slices函式切分傳入的張量的第一個維度,生成相應的資料集,使輸入特徵和標籤值一一對應
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)

# 生成神經網路的引數,輸入層為4個神經元,隱藏層為32個神經元,2層隱藏層,輸出層為3個神經元
# 用tf.Variable()保證引數可訓練
w1 = tf.Variable(tf.random.normal([2, 11]), dtype=tf.float32)
b1 = tf.Variable(tf.constant(0.01, shape=[11]))

w2 = tf.Variable(tf.random.normal([11, 1]), dtype=tf.float32)
b2 = tf.Variable(tf.constant(0.01, shape=[1]))

lr = 0.01  # 學習率為
epoch = 400  # 迴圈輪數

# 訓練部分
for epoch in range(epoch):
    for step, (x_train, y_train) in enumerate(train_db):
        with tf.GradientTape() as tape:  # 記錄梯度資訊

            h1 = tf.matmul(x_train, w1) + b1  # 記錄神經網路乘加運算
            h1 = tf.nn.relu(h1)
            y = tf.matmul(h1, w2) + b2

            # 採用均方誤差損失函式mse = mean(sum(y-out)^2)
            loss_mse = tf.reduce_mean(tf.square(y_train - y))
            # 新增l2正則化
            loss_regularization = []
            # tf.nn.l2_loss(w)=sum(w ** 2) / 2
            loss_regularization.append(tf.nn.l2_loss(w1))
            loss_regularization.append(tf.nn.l2_loss(w2))
            # 求和
            # 例:x=tf.constant(([1,1,1],[1,1,1]))
            #   tf.reduce_sum(x)
            # >>>6
            # loss_regularization = tf.reduce_sum(tf.stack(loss_regularization))
            loss_regularization = tf.reduce_sum(loss_regularization)
            loss = loss_mse + 0.03 * loss_regularization
            # REGULARIZER = 0.03

        # 計算loss對各個引數的梯度
        variables = [w1, b1, w2, b2]
        grads = tape.gradient(loss, variables)

        # 實現梯度更新
        # w1 = w1 - lr * w1_grad
        w1.assign_sub(lr * grads[0])
        b1.assign_sub(lr * grads[1])
        w2.assign_sub(lr * grads[2])
        b2.assign_sub(lr * grads[3])

    # 每200個epoch,列印loss資訊
    if epoch % 20 == 0:
        print('epoch:', epoch, 'loss:', float(loss))

# 預測部分
print("*******predict*******")
# xx在-3到3之間以步長為0.01,yy在-3到3之間以步長0.01,生成間隔數值點
xx, yy = np.mgrid[-3:3:.1, -3:3:.1]
# 將xx, yy拉直,併合並配對為二維張量,生成二維座標點
grid = np.c_[xx.ravel(), yy.ravel()]
grid = tf.cast(grid, tf.float32)
# 將網格座標點喂入神經網路,進行預測,probs為輸出
probs = []
for x_predict in grid:
    # 使用訓練好的引數進行預測
    h1 = tf.matmul([x_predict], w1) + b1
    h1 = tf.nn.relu(h1)
    y = tf.matmul(h1, w2) + b2  # y為預測結果
    probs.append(y)

# 取第0列給x1,取第1列給x2
x1 = x_data[:, 0]
x2 = x_data[:, 1]
# probs的shape調整成xx的樣子
probs = np.array(probs).reshape(xx.shape)
plt.scatter(x1, x2, color=np.squeeze(Y_c))
# 把座標xx yy和對應的值probs放入contour<[‘kɑntʊr]>函式,給probs值為0.5的所有點上色  plt點show後 顯示的是紅藍點的分界線
plt.contour(xx, yy, probs, levels=[.5])
plt.show()

# 讀入紅藍點,畫出分割線,包含正則化
# 不清楚的資料,建議print出來檢視 

19,優化器,不同的優化器實質上只是定義了不同的一階動量和二階動量的公式。

在這裡插入圖片描述

20,sgd優化器:

在這裡插入圖片描述

# 利用鳶尾花資料集,實現前向傳播、反向傳播,視覺化loss曲線

# 匯入所需模組
import tensorflow as tf
from sklearn import datasets
from matplotlib import pyplot as plt
import numpy as np
import time  ##1##

# 匯入資料,分別為輸入特徵和標籤
x_data = datasets.load_iris().data
y_data = datasets.load_iris().target

# 隨機打亂資料(因為原始資料是順序的,順序不打亂會影響準確率)
# seed: 隨機數種子,是一個整數,當設定之後,每次生成的隨機數都一樣(為方便教學,以保每位同學結果一致)
np.random.seed(116)  # 使用相同的seed,保證輸入特徵和標籤一一對應
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)

# 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使每次生成的隨機數相同(方便教學,使大家結果都一致,在現實使用時不寫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的和

# 訓練部分
now_time = time.time()  ##2##
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符合概率分佈(此操作後與獨熱碼同量級,可相減求loss)
            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更準確
        # 計算loss對各個引數的梯度
        grads = tape.gradient(loss, [w1, b1])

        # 實現梯度更新 w1 = w1 - lr * w1_grad    b = b - lr * b_grad
        w1.assign_sub(lr * grads[0])  # 引數w1自更新
        b1.assign_sub(lr * grads[1])  # 引數b自更新

    # 每個epoch,列印loss資訊
    print("Epoch {}, loss: {}".format(epoch, loss_all / 4))
    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轉換為y_test的資料型別
        pred = tf.cast(pred, dtype=y_test.dtype)
        # 若分類正確,則correct=1,否則為0,將bool型的結果轉換為int型
        correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32)
        # 將每個batch的correct數加起來
        correct = tf.reduce_sum(correct)
        # 將所有batch中的correct數加起來
        total_correct += int(correct)
        # total_number為測試的總樣本數,也就是x_test的行數,shape[0]返回變數的行數
        total_number += x_test.shape[0]
    # 總的準確率等於total_correct/total_number
    acc = total_correct / total_number
    test_acc.append(acc)
    print("Test_acc:", acc)
    print("--------------------------")
total_time = time.time() - now_time  ##3##
print("total_time", total_time)  ##4##

# 繪製 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()

# 本檔案較 class1\p45_iris.py 僅新增四處時間記錄  用 ##n## 標識
# 請將loss曲線、ACC曲線、total_time記錄到 class2\優化器對比.docx  對比各優化器收斂情況

21,SGDM優化器:

# 利用鳶尾花資料集,實現前向傳播、反向傳播,視覺化loss曲線

# 匯入所需模組
import tensorflow as tf
from sklearn import datasets
from matplotlib import pyplot as plt
import numpy as np
import time  ##1##

# 匯入資料,分別為輸入特徵和標籤
x_data = datasets.load_iris().data
y_data = datasets.load_iris().target

# 隨機打亂資料(因為原始資料是順序的,順序不打亂會影響準確率)
# seed: 隨機數種子,是一個整數,當設定之後,每次生成的隨機數都一樣(為方便教學,以保每位同學結果一致)
np.random.seed(116)  # 使用相同的seed,保證輸入特徵和標籤一一對應
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)

# 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使每次生成的隨機數相同(方便教學,使大家結果都一致,在現實使用時不寫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的和

# 訓練部分
now_time = time.time()  ##2##
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符合概率分佈(此操作後與獨熱碼同量級,可相減求loss)
            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更準確
        # 計算loss對各個引數的梯度
        grads = tape.gradient(loss, [w1, b1])

        # 實現梯度更新 w1 = w1 - lr * w1_grad    b = b - lr * b_grad
        w1.assign_sub(lr * grads[0])  # 引數w1自更新
        b1.assign_sub(lr * grads[1])  # 引數b自更新

    # 每個epoch,列印loss資訊
    print("Epoch {}, loss: {}".format(epoch, loss_all / 4))
    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轉換為y_test的資料型別
        pred = tf.cast(pred, dtype=y_test.dtype)
        # 若分類正確,則correct=1,否則為0,將bool型的結果轉換為int型
        correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32)
        # 將每個batch的correct數加起來
        correct = tf.reduce_sum(correct)
        # 將所有batch中的correct數加起來
        total_correct += int(correct)
        # total_number為測試的總樣本數,也就是x_test的行數,shape[0]返回變數的行數
        total_number += x_test.shape[0]
    # 總的準確率等於total_correct/total_number
    acc = total_correct / total_number
    test_acc.append(acc)
    print("Test_acc:", acc)
    print("--------------------------")
total_time = time.time() - now_time  ##3##
print("total_time", total_time)  ##4##

# 繪製 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()

# 本檔案較 class1\p45_iris.py 僅新增四處時間記錄  用 ##n## 標識
# 請將loss曲線、ACC曲線、total_time記錄到 class2\優化器對比.docx  對比各優化器收斂情況

在這裡插入圖片描述

相關文章