以Python撰寫 AI模型框架

以Python撰寫 AI模型框架框架

by 高煥堂機器學習

  1. 前言:ide

    在AI(人工智慧)方面,因爲當今的機器學習本質是一種<大數據相關性支撐的>概括性推理。軟體框架的複用(Reuse)性愈高,對於應用開發的幫助愈大。所以,在AI領域裏,軟體框架魅力將會大放異彩。在本文裏,是基於最簡單的Perceptron模型來闡述如何分析、設計及實做一個框架和API。在本節裏,將優化這個AI模型,讓它從線性分類,提高到非線性分類,能夠展示更高的智慧,也適用於更廣的範圍。並且將把最典型的Sigmoid激勵函數,添加到上一節所撰寫的Percentron基類裏。因爲這Sigmoid激勵函數適合於二元分類(Binary classification)的情境,包括線性和非線性二元分類問題。因此將這框架取名爲:BCModelFarmework。期待充分發揮框架威力、支援您的商業模式,邁向輝煌騰達之道。函數

  2. Python框架設計:從需求到實做學習

    你們都知道,人們的需求都是善變的,因此API的內涵也是隨時會改變的。在上一篇文章裏,其API裏只定義了一個getLR()函數。在本節裏,就來替API增添多函數。大數據

2.1 親自演練:需求分析 優化

一旦客人的需求有所改變了,可能會不斷擴充API。例如,當客人來了以後,纔會告知下述5項資料:學習率(Learning Rate)、要訓練幾次合(Epoch)、訓練資料集X[] ,以及指望值T[]等。就能依據框架的需求時間軸概念,來繪出下圖:設計

以Python撰寫 AI模型框架
圖一、框架需求分析code

從這圖能夠看出來,這5項資料都是寫在子類裏,而框架必須透過API來向子類索取這5項資料值。一旦框架取得了這些資料,就能展開AI模型的訓練工做了。如今,就依據上圖的思惟而繪製出類別圖,以下所示:
以Python撰寫 AI模型框架
圖二、此範例的類別圖blog

在這PerFramewor02框架裏,含有一個Perceptron基類,讓myNN子類來繼承之。也就是由子類來實做Perceptron裏的抽象函數。

2.2 親自演練:實現框架

如今,就以Python來實現這個框架,以下:

PerFramework02.py

import numpy as np
from abc import ABC, abstractmethod

class Perceptron(ABC):
def init(self):
self.learningRate = self.getLR()
self.epoches = self.getEpoch()
self.B = 0;
self.W = 0;
self.correctRate = np.zeros([30])

def train(self):
    X = self.getX()
    T = self.getT()
    len = X.size

   for i in range(self.epoches):
        errorCount = 0;

        for j in range(len):
            error = T[j] - self.predict(X[j])
            update = self.learningRate * error
            # 修正W和B
            self.W += update * X[j]
            self.B += update
            # 累積錯誤次數
            if (error != 0):
                     errorCount = errorCount + 1
     # 算出正確率
     self.correctRate[i] = 1 - errorCount * 1.0 / len

def predict(self, x):
    y = x * self.W + self.B
    z = self.getZ(y)
    return z

def printCR(self, idx):
    print("#:", idx, " ", self.correctRate[idx])

@abstractmethod
def getLR(): pass

@abstractmethod
def getEpoch(): pass

@abstractmethod
def getZ(y): pass

@abstractmethod
def getX(): pass

@abstractmethod
def getT(): pass

這個時候,API已經擴大了,總共包含了5個抽象函數:getLR()、getEpoch()、getZ()、getX()和getT()。在程式執行時,基類就會透過抽象函數的機制,來呼叫子類的函數,來取得上述的5項資料。接着,就來撰寫App以下:

Ex1-01.py

import numpy as np
from abc import ABC, abstractmethod
from PerFramework02 import Perceptron

class myNN(Perceptron):
def init(self):
super().init()

def getLR(self):
    return 0.1

def getEpoch(self):
    return 30

def getZ(self, y):
    if (y >= 0):
        return 1
    else:
        return 0

def getX(self):
    dx = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])
    return dx

def getT(self):
    dt = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0])
    return dt

----主程式部分---------------------------------------

p = myNN()
p.train()
p.printCR(0)
p.printCR(1)
p.printCR(2)
p.printCR(21)
p.printCR(22)
p.printCR(23)
p.printCR(24)
p.printCR(25)
p.printCR(26)
這是一支能在Python環境裏執行的App,內含兩個類別,其中的myNN繼承框架裏的Perceptron基類。其中的主程式(部分)裏有個指令:

p = myNN()

誕生一個myNN的物件,而且呼叫到Perceptron基類的建構式(Constructor):

class Perceptron(ABC):

     def __init__(self):
        self.learningRate = self.getLR()
        self.epoches = self.getEpoch()

    # …………..

# ………….

而後,開始執行這建構式裏的指令,首先呼叫到getLR()函數,轉而呼叫子類myNN裏的getLR()函數,要求它傳回來<學習率>的值。接着,就呼叫到getEpoch()函數,轉而呼叫子類myNN裏的getEpoch()函數,要求它傳回來訓練的回合數。而後返回主程式部分,執行下一個指令:

    p.train()

因而,這指令就呼叫Perceptron基類的train()函數,並開始執行train()函數裏的指令:

   def train(self):

X = self.getX()

    T = self.getT()

就呼叫到getX()函數了,並轉而呼叫myNN裏的getX()函數,要求它傳回來訓練資料X[]的內容。接着呼叫getT()函數了,然而這getT()是抽象函數,其指令是實做於myNN子類裏,因而就轉而呼叫myNN裏的getT()函數,要求它傳回來指望資料T[]的內容。而後展開訓練的動做,並輸出結果以下:

以Python撰寫 AI模型框架

一開始,在第#0~#22回合,其預測的正確率比較低。然而愈多回合的訓練,其正確率就逐漸上升了。到了第#23回合以後,其預測的正確率就接近於1.0(即達到100%)了。以上展示了框架API的不斷成長過程,而框架與App之間的互動也更頻繁了。
  1. 優化模型:使用Sigmoid激勵函數

    3.1 寫出一支App:使用Sigmoid函數

    在上一節裏,是基於最簡單的Perceptron模型來闡述如何分析、設計及實做一個框架和API。在本節裏,將優化這個AI模型,讓它從線性分類,提高到非線性分類,能夠展示更高的智慧,也適用於更廣的範圍。本節的範例裏,將把最典型的Sigmoid激勵函數,添加到上一節所撰寫的Percentron基類裏。因爲這Sigmoid激勵函數適合於二元分類(Binary classification)的情境,包括線性和非線性二元分類問題。因此將這框架取名爲:BCModelFarmework。以下述Python程式碼:

    #BCModelFramework.py

    from abc import ABC, abstractmethod

import numpy as np
class Perceptron(ABC):

def __init__(self):
    self.learningRate = self.onLearningRate()
    self.epoches = self.onEpoch()
    dw = self.onW()
    self.W = dw[0]
    self.B = dw[1]
    self.correctRate = np.zeros(self.epoches)

def train(self):
    X = self.onX()
    T = self.onT()
    epoches = self.correctRate.size
    len = np.size(X, 0)
    for i in range(epoches):
        errorCount = 0
        for j in range(len):
            z = self.predict(X[j])
            loss = T[j] - z
            delta = 2 * self.deriv(z) * loss
            update = self.learningRate * delta
            # 修正W和B
            self.W += update * X[j]
            self.B += update
            # 累計錯誤次數
            if (z >= 0.5):
                v = 1
            else:
                v = 0
            if ((T[j] - v) != 0):

                errorCount = errorCount + 1
        # 算出正確率
        self.correctRate[i] = 1 - errorCount * 1.0 / len
def predict(self, X):
    y = np.dot(X, self.W) + self.B
    z = self.sigmoid(y)
    return z
def sigmoid(self, y):
    z = float(1 / (1 + np.exp(-y)))
    return z
def deriv(self, z):
    d = z * (1 - z)
    return d

@abstractmethod
def onLearningRate():   pass

@abstractmethod
def onEpoch(): pass

@abstractmethod
def onX(): pass

@abstractmethod
def onT(): pass

@abstractmethod
def onW(): pass

def getW(self):
return self.W
def getCR(self):
return self.correctRate
這個BCModelFramework框架裏,含由一個Perceptron基類,它提供的API總共包含5個抽象函數:onLearningRate()、onEpoch()、onX()、onT()和onW()。接着,就可基於這個框架來快速開發App了,以下述的程式碼:

Ex12-07.py

import numpy as np
from abc import ABC, abstractmethod
from BCModelFramework import Perceptron

class myNN(Perceptron):
def init(self):
super().init()
def onLearningRate(self):
return 0.1
def onEpoch(self):
return 80
def onX(self):
dx = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])
return dx
def onT(self):
dt = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0])
return dt
def onW(self):
self.dw = np.array([[0.0], 0.0])
return self.dw
def printWeight(self):
print(self.getW())
def printCR(self, idx):
cr = self.correctRate
print(" 第", idx, "回合: ", str(int(cr[idx] * 100)), "%")

-----------------主程式部分-------------------------------------------

p = myNN()
p.train()
print(" 正確率:")
p.printCR(0)
p.printCR(1)
p.printCR(10)
p.printCR(20)
p.printCR(30)
p.printCR(40)
p.printCR(50)
p.printCR(60)
p.printCR(70)
這是一支能在Python環境裏執行的App,內含兩個類別。其中的myNN繼承框架裏的Perceptron基類,以下:

以Python撰寫 AI模型框架

圖三、框架支援App的快速開發

這個簡單範例裏,輸出層神經元的主要計算公式是:y= X*W+B。表現於指令:

  def predict(self, X):

y = np.dot(X, self.W) + self.B
   z = self.sigmoid(y)
   return z

計算出y值以後,再經由Sigmoid()激勵函數,轉換出z值,才成爲這神經元的輸出值(即z值)。有了z值以後,就能進行「反向傳播(Backpropagation)」來更新權重(Weight)值。表現於指令:

loss = T[j] - z

   delta = 2 * self.deriv(z) * loss
   update = self.learningRate * delta

其中的loss值,還要乘以Sigmoid的導數(Derivation)值,來決定修正的幅度。這樣子,讓模型的適用範圍更廣了。除了能夠應用於線性分類(Linear classification)問題上,也適用於非線性分類(Nonlinear classification)的情境。

至於主程式(部分)裏有個指令:

p = myNN()

誕生一個myNN的物件,而且呼叫到基類Perceptron的建構式:

class Perceptron(ABC):

  def __init__(self):
     self.learningRate = self.onLearningRate()
     self.epoches = self.onEpoch()
     dw = self.onW()
        # …………

        # …………

而後,開始執行建構式裏的指令,呼叫到了onLearningRate()函數,轉而呼叫子類myNN裏的onLearningRate()函數,要求它傳回來<學習率>的值。接着,就呼叫到onEpoch()函數,轉而呼叫子類myNN裏的onEpoch()函數,要求它傳回來訓練的回合數。接着,就呼叫到onW()函數,轉而呼叫子類myNN裏的onW()函數,要求它傳回來權重的初期值。而後返回主程式部分,執行下一個指令:

   p.train()

因而,這指令就呼叫基類Perceptron裏的train()函數,執行到train()函數裏的指令:

    def train(self):

X = self.onX()
       T = self.onT()

就呼叫到onX()函數了。然而這onX()是抽象函數,其指令是實做於myNN子類裏。因而就轉而呼叫myNN裏的onX()函數,要求它傳回來訓練資料X[]的內容。接着呼叫onT()函數了,就轉而呼叫myNN裏的onT()函數,要求它傳回來指望資料T[]的內容。而後展開訓練的動做,並輸出結果以下:
以Python撰寫 AI模型框架

其結果與上一個範例是一致的,一開始的預測正確率比較低。然而愈多回合的訓練,其正確率就逐漸上升了。到了第#50回合以後,其預測的正確率就接近於1.0(即達到100%)了。◆

相關文章
相關標籤/搜索