发 帖  
原厂入驻New

高焕堂AI概论:以Python撰写 AI模型框架

2020-12-22 10:01:11  824 高焕堂 人工智能
分享
1. 前言:
  在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[]等。就能依据框架的需求时间轴概念,来绘出下图:
5.png
1、框架需求分析

      从这图可以看出来,这5项资料都是写在子类里,而框架必须透过API来向子类索取这5项资料值。一旦框架取得了这些资料,就能展开AI模型的训练工作了。现在,就依据上图的思维而绘制出类别图,如下所示:
6.png
2、此范例的类别图
   在这PeRFramewor02框架里,含有一个Perceptron基类,让myNN子类来继承之。也就是由子类来实作Perceptron里的抽象函数。
2.2  亲自演练:实現框架

  现在,就以Python来实現这个框架,如下:




  1. # PerFramework02.py

  2. import numpy as np
  3. from abc import ABC, abstractmethod

  4. class Perceptron(ABC):
  5.     def __init__(self):
  6.         self.learningRate = self.getLR()
  7.         self.epoches = self.getEpoch()
  8.         self.B = 0;
  9.         self.W = 0;
  10.         self.correctRate = np.zeros([30])

  11.     def train(self):
  12.         X = self.getX()
  13.         T = self.getT()
  14.         len = X.size

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

  17.             for j in range(len):
  18.                 error = T[j] - self.predict(X[j])
  19.                 update = self.learningRate * error
  20.                 # 修正W和B
  21.                 self.W += update * X[j]
  22.                 self.B += update
  23.                 # 累积错误次数
  24.                 if (error != 0):
  25.                          errorCount = errorCount + 1
  26.          # 算出正确率
  27.          self.correctRate[i] = 1 - errorCount * 1.0 / len

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

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

  34.    @abstractmethod
  35.    def getLR():    pass

  36.   @abstractmethod
  37.    def getEpoch():  pass

  38.   @abstractmethod
  39.    def getZ(y):  pass

  40.   @abstractmethod
  41.    def getX():  pass

  42.    @abstractmethod
  43.    def getT(): pass


复制代码


这个时候,API已经扩大了,总共包含了5个抽象函数:getLR()、getEpoch()、getZ()、getX()和getT()。在程式执行时,基类就会透过抽象函数的机制,来呼叫子类的函数,来取得上述的5项资料。接着,就来撰写App如下:



  1. # Ex1-01.py

  2. import numpy as np
  3. from abc import ABC, abstractmethod
  4. from PerFramework02 import Perceptron

  5. class myNN(Perceptron):
  6.     def __init__(self):
  7.         super().__init__()

  8.     def getLR(self):
  9.         return 0.1

  10.     def getEpoch(self):
  11.         return 30

  12.     def getZ(self, y):
  13.         if (y >= 0):
  14.             return 1
  15.         else:
  16.             return 0

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

  20.     def getT(self):
  21.         dt = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0])
  22.         return dt
  23. # ----主程式部分---------------------------------------
  24. p = myNN()
  25. p.train()
  26. p.printCR(0)
  27. p.printCR(1)
  28. p.printCR(2)
  29. p.printCR(21)
  30. p.printCR(22)
  31. p.printCR(23)
  32. p.printCR(24)
  33. p.printCR(25)
  34. p.printCR(26)

复制代码

这是一支能在Python环境里执行的App,内含两个类别,其中的myNN继承框架里的Perceptron基类。其中的主程式(部分)里有个指令
  p = myN
   诞生一个myNN的物件,并且呼叫到Perceptron基类的建构式(Constructor):




  1. class Perceptron(ABC):

  2.          def __init__(self):
  3.             self.learningRate = self.getLR()
  4.             self.epoches = self.getEpoch()
  5.       # …………..

  6.        # ………….

复制代码

然后,开始执行这建构式里的指令,首先呼叫到getLR()函数,转而呼叫子类myNN里的getLR()函数,要求它传回来<学习率>的值。接着,就呼叫到getEpoch()函数,转而呼叫子类myNN里的getEpoch()函数,要求它传回来训练的回合数。然后返回主程式部分,执行下一个指令:
    p.train()
  于是,这指令就呼叫Perceptron基类的train()函数,并开始执行train()函数里的指令:




  1. def train(self):
  2.         X = self.getX()
  3.         T = self.getT()

复制代码

就呼叫到getX()函数了,并转而呼叫myNN里的getX()函数,要求它传回来训练资料X[]的内容。接着呼叫getT()函数了,然而这getT()是抽象函数,其指令是实作于myNN子类里,于是就转而呼叫myNN里的getT()函数,要求它传回来期望资料T[]的内容。然后展开训练的动作,并输出结果如下: 7.png 一开始,在第#0~#22回合,其预测的正确率比较低。然而愈多回合的训练,其正确率就逐渐上升了。到了第#23回合之后,其预测的正确率就接近于1.0(即达到100%)了。以上展现了框架API的不断成长过程,而框架与App之间的互动也更频繁了。
3.  优化模型:使用Sigmoid激励函数
3.1  写出一支App:使用Sigmoid函数
   在上一节里,是基于最简单的Perceptron模型来阐述如何分析、设计及实作一个框架和API。在本节里,将优化这个AI模型,让它从线性分类,提升到非线性分类,可以展现更高的智慧,也适用于更广的范围。本节的范例里,将把最典型的Sigmoid激励函数,添加到上一节所撰写的Percentron基类里。由于这Sigmoid激励函数适合于二元分类(Binaryclassification)的情境,包括线性和非线性二元分类问题。所以将这框架取名为:BCModelFarmework。如下述Python程式码:




  1. #BCModelFramework.py

  2.   from abc import ABC, abstractmethod

  3. import numpy as np
  4. class Perceptron(ABC):

  5.     def __init__(self):
  6.         self.learningRate = self.onLearningRate()
  7.         self.epoches = self.onEpoch()
  8.         dw = self.onW()
  9.         self.W = dw[0]
  10.         self.B = dw[1]
  11.         self.correctRate = np.zeros(self.epoches)

  12.     def train(self):
  13.         X = self.onX()
  14.         T = self.onT()
  15.         epoches = self.correctRate.size
  16.         len = np.size(X, 0)
  17.         for i in range(epoches):
  18.             errorCount = 0
  19.             for j in range(len):
  20.                 z = self.predict(X[j])
  21.                 loss = T[j] - z
  22.                 delta = 2 * self.deriv(z) * loss
  23.                 update = self.learningRate * delta
  24.                 # 修正W和B
  25.                 self.W += update * X[j]
  26.                 self.B += update
  27.                 # 累计错误次数
  28.                 if (z >= 0.5):
  29.                     v = 1
  30.                 else:
  31.                     v = 0
  32.                 if ((T[j] - v) != 0):

  33.                     errorCount = errorCount + 1
  34.             # 算出正确率
  35.             self.correctRate[i] = 1 - errorCount * 1.0 / len
  36.     def predict(self, X):
  37.         y = np.dot(X, self.W) + self.B
  38.         z = self.sigmoid(y)
  39.         return z
  40.     def sigmoid(self, y):
  41.         z = float(1 / (1 + np.exp(-y)))
  42.         return z
  43.     def deriv(self, z):
  44.         d = z * (1 - z)
  45.         return d

  46.     @abstractmethod
  47.     def onLearningRate():   pass

  48.    @abstractmethod
  49.      def onEpoch():    pass

  50.    @abstractmethod
  51.      def onX():    pass

  52.    @abstractmethod
  53.      def onT():     pass

  54.    @abstractmethod
  55.      def onW():     pass

  56.    def getW(self):
  57.            return self.W
  58.      def getCR(self):
  59.            return self.correctRate

复制代码

这个BCModelFramework框架里,含由一个Perceptron基类,它提供的API总共包含5个抽象函数:onLearningRate()、onEpoch()、onX()、onT()和onW()。接着,就可基于这个框架来快速开发App了,如下述的程式码:



  1. # Ex12-07.py

  2. import numpy as np
  3. from abc import ABC, abstractmethod
  4. from BCModelFramework import Perceptron

  5. class myNN(Perceptron):
  6.     def __init__(self):
  7.         super().__init__()
  8.     def onLearningRate(self):
  9.         return 0.1
  10.     def onEpoch(self):
  11.         return 80
  12.     def onX(self):
  13.         dx = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])
  14.         return dx
  15.     def onT(self):
  16.         dt = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0])
  17.         return dt
  18.     def onW(self):
  19.         self.dw = np.array([[0.0], 0.0])
  20.         return self.dw
  21.     def printWeight(self):
  22.         print(self.getW())
  23.     def printCR(self, idx):
  24.         cr = self.correctRate
  25.         print("  第", idx, "回合:  ", str(int(cr[idx] * 100)), "%")
  26. # -----------------主程式部分-------------------------------------------
  27. p = myNN()
  28. p.train()
  29. print("  正确率:")
  30. p.printCR(0)
  31. p.printCR(1)
  32. p.printCR(10)
  33. p.printCR(20)
  34. p.printCR(30)
  35. p.printCR(40)
  36. p.printCR(50)
  37. p.printCR(60)
  38. p.printCR(70)

复制代码

这是一支能在Python环境里执行的App,内含两个类别。其中的myNN继承框架里的Perceptron基类,如下: 8.png 图3、框架支援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[]的内容。然后展开训练的动作,并输出结果如下:
9.png 其结果与上一个范例是一致的,一开始的预测正确率比较低。然而愈多回合的训练,其正确率就逐渐上升了。到了第#50回合之后,其预测的正确率就接近于1.0(即达到100%)了。
0
2020-12-22 10:01:11   评论 分享淘帖

只有小组成员才能发言,加入小组>>

13个成员聚集在这个小组

加入小组

创建小组步骤

关闭

站长推荐 上一条 /8 下一条

快速回复 返回顶部 返回列表