1. 程式人生 > >深度學習筆記——感知機

深度學習筆記——感知機

程式碼參考了零基礎入門深度學習(1) - 感知器這篇文章,我只對程式碼裡可能存在的一些小錯誤進行了更改。至於感知機的原理以及程式碼裡不清楚的地方可以結合該文章理解。

from functools import reduce


class Perceptron:

    def __init__(self,input_num,activator):
        '''
        param input_num: 初始化感知機,設定輸入引數的個數
        param activator: 初始化感知機,設定啟用函式
        '''
        self.activator = activator
        # 權重向量初始化為0
        self.weights = [0.0 for i in range(input_num)]
        # 偏置項初始化為0
        self.bias = 0.0

    def __str__(self):
        '''
        列印學習到的權重,偏置項
        '''
        return 'weights\t:{}\nbias\t:{}\n'.format(str(self.weights),str(self.bias))

    def predict(self,input_vec):
        '''
        輸入向量,輸出感知機的計算結果
        '''
        # 把input_vec[x1,x2,x3...]和weights[w1,w2,w3,...]打包在一起
        # 變成[(x1,w1),(x2,w2),(x3,w3),...]
        # 然後利用map函式計算[x1*w1,x2*w2,x3*w3,...]
        # 最後利用reduce求和
        zipped = zip(input_vec,self.weights)
        map_result = map(lambda ele:ele[0]*ele[1],list(zipped))
        sum_result = reduce(lambda a,b:a+b,map_result,0.0)
        return self.activator(sum_result+self.bias)
    
    def train(self,input_vecs,labels,iteration,rate):
        '''
        :param input_vec: 一組向量
        :param labels: 與每個向量對應的label
        :param iteration: 訓練輪數
        :param rate: 學習率
        :return: 
        '''
        for i in range(iteration):
            self._one_iteration(input_vecs,labels,rate)

    def _one_iteration(self, input_vecs, labels, rate):
        '''
        一次迭代,把所有的訓練資料過一遍
        '''
        # 把輸入和輸出打包在一起,成為樣本的列表[(input_vec,label),...]
        # 而每個訓練樣本是(input_vec,labels)
        samples = zip(input_vecs,labels)
        # 對每個樣本,按照感知機規則更新權重
        for ele in list(samples):
            # 計算感知機在當前權重下的輸出
            output = self.predict(ele[0])
            # 更新權重
            self._update_weights(ele[0],output,ele[1],rate)

    def _update_weights(self, input_vec, output, label, rate):
        '''
        按照感知機規則更新權重
        隨機梯度下降法。
        '''
        # 把input_vec[x1,x2,x3,...]和weights[w1,w2,w3,...]打包在一起
        # 變成[(x1,w1),(x2,w2),(x3,w3),...]
        # 然後利用感知機規則更新權重
        delta = label - output
        self.weights = list(map(lambda ele:ele[1]+rate*delta*ele[0],zip(input_vec,self.weights)))
        # 更新bias
        self.bias += rate*delta




def f(x):
    '''
    定義啟用函式f
    '''
    return 1 if x > 0 else 0

def get_training_dataset():
    '''
    基於and真值表構建訓練資料
    '''
    # 構建訓練資料
    # 輸入向量列表
    input_vecs = [[1,1],[0,0],[1,0],[0,1]]
    # 期望的輸出列表,注意要與輸入一一對應
    # [1,1] -> 1, [0,0] -> 0, [1,0] -> 0, [0,1] -> 0
    labels = [1,0,0,0]
    return input_vecs,labels

def train_and_perception():
    '''
    使用and真值表訓練感知機
    '''
    # 建立感知機,輸入引數個數為2(因為and是二元函式),啟用函式為f
    p = Perceptron(2,f)
    # 訓練,迭代10輪,學習速率為0.1
    input_vecs,labels= get_training_dataset()
    p.train(input_vecs,labels,10,0.1)
    # 返回訓練好的感知機
    return p
'''
if __name__ == '__main__':
    # 訓練感知機
    and_perception = train_and_perception()
    # 列印訓練獲得的權重
    print(and_perception)
    # 測試
    print('1 and 1 = %d' %and_perception.predict([1,1]))
    print('0 and 0 = %d' %and_perception.predict([0,0]))
    print('1 and 0 = %d' %and_perception.predict([1,0]))
    print('0 and 1 = %d' %and_perception.predict([0,1]))
'''