自分で簡単なセンサーアルゴリズムを書く


感知器を自分で書く
  • 自分でセンサーを書く
  • 1感知機とは何ですか?
  • 2センシングマシンモデル
  • 3センシングマシン学習アルゴリズム
  • 4まとめ

  • 1感知機とは何ですか.
    センサ(perceptron)は、入力されたすべてのインスタンスをTrueまたはFalseの2つに分類できる2つの分類の線形分類モデルである.センシングマシンモデルの入力ベクトルはインスタンスの特徴ベクトルであり、N次元空間で平面を探して、この平面がインスタンスを正負の2種類に分けることができるようにすることが任務であり、この平面を超平面と呼ぶ.感知機はニューラルネットワークとベクトルマシンをサポートする基礎である.
    2センサモデル
    入力スペース:χ⊆Rn χ ⊆ R n
    出力空間:y={+1,−1}y={+1,−1}
    入力スペースから出力への関数:
    f(x)=sign(w⋅x+b) f ( x ) = s i g n ( w ⋅ x + b )
    次のようになります.
    sign(x)={+1−1x≥0x<0 s i g n ( x ) = { + 1 x ≥ 0 − 1 x < 0
    幾何学的説明:
    関数の中のw wは超平面の法ベクトルと理解することができて、b bは超平面の断面積で、超平面は全体の空間を2つの部分に分けて、分類した正、負の2種類です.
    3センサ学習アルゴリズム
    感知機学習アルゴリズムの具体的な戦略は,誤分類点から超平面までの距離と損失関数を用い,勾配降下法を用いて損失関数を最小化することで超平面を解くことができる.
  • 元の形式は、まずすべてのパラメータを0に初期化し、その後、勾配降下法に従って、各誤分類点でパラメータを更新し、クラス:
    class PreceptronClassifier:
      def __init__(self,learning_rate):
          self.b = 0
          self.w = []
          self.rate = learning_rate
    
      def func(self, x):
          #     
          res = 0.0
          for i in range(len(x)):
              res += self.w[i]*x[i]
          res += self.b
          return res
    
      def update(self,error_x,error_y):
          #     
          for i in range(len(error_x)):
              self.w[i] += self.rate*error_x[i]*error_y
          self.b += self.rate*error_y
    
      def error_label(self,temp_res:list,trainY):
          #       
          for i in range(len(self.w)):
              if temp_res[i] == trainY[i]:
                  temp_res[i] = 0
              else:
    
                  temp_res[i] = 1
          return temp_res
    
      def fit(self, trainX,trainY):
          #      
          self.w = [0]*len(trainX[0])
          self.b = 0
          temp_res = self.prediction(trainX)
          temp_res = self.error_label(temp_res, trainY)
          train_iter = 0
          while(1 in temp_res):
              #       
              print(' '+str(train_iter)+'   ','w:',self.w,'b:',self.b)
              error_index = temp_res.index(1)
              self.update(trainX[error_index],trainY[error_index])
              temp_res = self.prediction(trainX)
              temp_res = self.error_label(temp_res, trainY)
    
      def prediction(self, testX):
          #     
          res  = []
          for x in testX:
              res.append(1 if self.func(x) > 0 else -1 )
          return res
    
    
    if __name__ == '__main__':
      #            
      trainX = [[3,3],[4,3],[1,1]]
      trainY = [1,1,-1]
      testX  = [[1,2],[3,4]]
      #     ,     
      pc = PreceptronClassifier(0.5)
      pc.fit(trainX,trainY)       #   
      print(pc.prediction(testX)) #   
  • にカプセル化する.
  • 対偶形式は前述したように、w wパラメータを更新するたびにw=w+を使用するηyixi w = w + η y i x iという式はモデル対求のバイアスであり,η η 学習率を表す.したがって、各インスタンスに対してyixi y i x iは変化しないので、最終的なモデルパラメータは以下のように表すことができる.
    w=∑i−1Nαiyixib=∑i−1Nαiyi w = ∑ i − 1 N α i y i x i b = ∑ i − 1 N α i y i
    αi α iは、i番目のi点がモデルを更新するために誤分類された回数を示す.これが対偶形式であり、以下にコードを置く:
    class PreceptronClassifier:
      def __init__(self,learning_rate):
          self.b = 0
          self.w = []
          self.rate = learning_rate
    
      def func(self, x):
          #     
          res = 0.0
          for i in range(len(x)):
              res += self.w[i]*x[i]
          res += self.b
          return res
    
      def update(self,error_index, trainY):
          #     
          self.a[error_index] += 1
          for i in range(len(self.w)):
              self.w[i] += self.rate*self.matrix[error_index][i]
          self.b += self.rate*trainY[error_index]
    
      def error_label(self,temp_res:list,trainY):
          #       
          for i in range(len(self.w)):
              if temp_res[i] == trainY[i]:
                  temp_res[i] = 0
              else:
    
                  temp_res[i] = 1
          return temp_res
    
      def fit(self, trainX,trainY):
          #      
          self.w = [0]*len(trainX[0])
          self.a = [0]*len(trainX)
          self.b = 0
          self.matrix = []
          for i in range(len(trainX)):
              self.matrix.append([xi*trainY[i] for xi in trainX[i]])
          temp_res = self.prediction(trainX)
          temp_res = self.error_label(temp_res, trainY)
          train_iter = 0
          while(1 in temp_res):
              train_iter += 1
              error_index = temp_res.index(1)
              self.update(error_index,trainY)
              temp_res = self.prediction(trainX)
              temp_res = self.error_label(temp_res, trainY)
              print(' '+str(train_iter)+'   ','w:',self.w,'b:',self.b)
    
      def prediction(self, testX):
          #     
          res  = []
          for x in testX:
              res.append(1 if self.func(x) > 0 else -1 )
          return res
    
    
    if __name__ == '__main__':
      #            
      trainX = [[3,3],[4,3],[1,2]]
      trainY = [1,1,-1]
      testX  = [[1,2],[3,4]]
      #     ,     
      pc = PreceptronClassifier(0.5)
      pc.fit(trainX,trainY)       #   
      print(pc.prediction(testX)) #   
  • 4まとめ
    センサモデルは簡単で実現しやすく,入門レベルのアルゴリズムであり,ニューラルネットワークとベクトルマシンをサポートする基礎でもある.例えばニューラルネットワークの全接続層は感知機に似ているので,このアルゴリズムは理解に値する.
    初めて勉強したばかりなので,どうぞご指摘ください.