模型建立與訓練

      在〈模型建立與訓練〉中尚無留言

模型與層

人工智慧總是會提到模型與層這些名詞。所以先說明一下什麼是模型,什麼是層。

AI說穿了,就是利用多個演算法,產出一組數值。將已知結果的資料演算一下,產生A值,再將要預測結果的資料演算一下,產生B值。然後由A, B這二個數值去比對大小或範圍,判斷出結果。

要完成一個AI的演算,可能簡單到可能只要一種演算法,也可能複雜到上百種演算法。每一種演算法就是一個層。

將多個層統合起來,並在前頭加入輸入資料的功能,中間還加入 fix, predict等功能,最後再加入輸出功能。然後將全部封裝起來,最終形成~~模型。

TensorFlow建議使用Keras(凱拉斯)建立模型。Keras是目前最為流行的神經網路API。裏面的Layer有卷積層(Convolution Layer)、池化層(Pooling Layer)、全連接層(Fully Connected Layer)…等等。將這些Layer連接、組織並進行封裝,成為一個Model. 

自訂模型類別

自訂模型類別需繼承 keras.Model,並覆寫建構子 __init__ 及 call 方法,如下所示

import tensorflow as tf
import keras
class FirstModel(keras.Model):
def __init__(self):
super().__init__()
#初始化程式碼
#增加 call 方法會用到的層(演算法),記得加self(物件變數),如
# self.layer1 = tf.keras.layers.Dense(...)
def call(self, input):
# 此處接收調用此模型的輸入值,並回傳輸出值,如
#output = self.layer1(input)
#return output

全連接層

在如下的自訂模型中,使用keras.layers.Dense建立全連接層物件 self.dense。全連接層是Keras最基礎且常用的層,其實就是 ax+b的線性計算,也就是先前的迴歸線計算啦。其中的units為輸出的張量維度 1,kernal_initializer為權重矩陣,bias_initializer 則為偏移量。當調用 model(X)時,就是調用call()方法,並將X傳入。然後傳回ax+b線性計算後的結果。keras.optimizers.SGD則負責學習函數的值。如下的完整代碼,輸出的結果,跟先前所提的迴歸線範例一樣。

所以全連接層其實就是在計算迴歸線嘛!!

import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
import threading
import time
import pylab as plt
import numpy as np
import tensorflow as tf
import keras class RegressionModel(keras.Model): def __init__(self): super().__init__() self.dense=keras.layers.Dense( #全連接層 : y=ax+b units=1, #輸出的維度 activation=None, kernel_initializer=tf.zeros_initializer(),#核心初始值 bias_initializer=tf.zeros_initializer#偏移量初始值 ) def call(self, input): output=self.dense(input) print(self.variables[0].numpy(), self.variables[1].numpy()) return output def run():
model=RegressionModel()
optimizer=keras.optimizers.SGD(learning_rate=5e-4)
epoch = 1000 for i in range(epoch):
with tf.GradientTape() as f:
#底下會調用系統級 __call__(),然後再調用 call(), 所以要覆寫 call()方法
y_pred=model(x)
loss=tf.reduce_sum(tf.square(y_pred-y))
y_grad=f.gradient(loss, model.variables)
optimizer.apply_gradients(grads_and_vars=zip(y_grad, model.variables)) ax.clear() ax.plot([0, 0], [yt, yb], color="blue", linewidth=0.5) ax.plot([xl, xr], [0, 0], color="blue", linewidth=0.5) ax.set_xlim(xl, xr) ax.set_ylim(yb, yt) ax.scatter(x, y) ax.plot(x, f(x), color="green", linewidth=5)
# 更新參數 a = model.variables[0] b = model.variables[1] ax.plot(x, a*x+b, color="red", linewidth=1) ax.text(-8,-6,f"y={a.numpy()[0][0]}X+{b.numpy()[0]}") plt.draw() time.sleep(0.1) fig=plt.figure(figsize=(9,6)) rng=np.random.RandomState(1) xl=-15;xr=15;yb=-8;yt=12;n=20 x = np.linspace(-10, 10, n) y = 0.5 * x + 3 - rng.randint(-5, 5, n) ax=fig.add_subplot() reg=np.poly1d(np.polyfit(x, y, 1)) x=x.reshape(n, 1) y=y.reshape(n, 1) t=threading.Thread(target=run) t.start() plt.show() 結果 [[0.45857468]] [3.6142414]
[[0.45857465]] [3.6142414]
[[0.45857465]] [3.6142416]

上述y_pred=model(X),其實就是調用class Model的 __call__()方法。那麼我們不就應該覆寫 __call__()嗎,怎麼覆寫 call()?? 因為 __call__()會先作一些事情,然後再調用 call()。所以我們只需覆寫 call() 即可。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *