神經網絡-感知器

目錄

前言

這是一篇神經網絡最最最基礎的博文!
講解的是感知器和自適應性聖經元,爲以後的深度學習打下基礎。
本文章是閱覽技術文檔加以實現和理解。
原文地址:http://www.ranling.com/category/it/689240.html

感知器

感知器的最初概念來源於生物神經元類逼成帶有二值輸出的簡單邏輯門。從生物學的角度來看,神經元相當於大腦中的神經網絡的一個節點。當刺激抵達樹突,輸入信號就會在神經細胞體內進行聚集(因爲樹突有很多),當刺激超過一定的閾值的時候就會產生一個輸出信號,然後繼續傳遞下去。根據這個原理有人就提出了感知器這個概念。
enter image description here

Frank Rosenblatt感知器

這是以這個人的名字命名的感知器。這個感知器的思路特別簡單,也是我們在書本上見到最多的。
用權重W(可以理解爲每個樹突的重要性不一樣)向量點積特徵向量x會得到一個值y,看看這個值y與閾值進行對比,如果超過閾值就說明產生了刺激。
這就是一個最簡單的 二值分類器

Heaviside階躍函數

也稱爲單位階躍函數,就是一個激活函數。
函數表達式爲:

這裏寫圖片描述
其中θ 是閾值

z就是上文中的x 點積 權重向量w
這裏寫圖片描述
注意這裏的權重是一個向量的,應該跟x向量擁有一樣的列數。
這裏寫圖片描述

明白了上面的概念,感知機就很簡單了。畫出它的函數圖像。
這裏寫圖片描述

反過頭去看公式,我麼可以做一下變換。
就是把θ 搬到左邊來。還可以在w權重向量中,把第0個元素當作θ !
這裏寫圖片描述

算法步驟

1、權重初始化
2、計算預測值
3、更新權重
4、更新閾值
算法模型爲:

這裏寫圖片描述
(因爲公式的轉換我們把閾值放進了w向量中,w0就是閾值(負的),所以模型圖中的weight update 可以看作算法步驟3、4的結合)

下面就針對算法的步驟來看

權重初始化

初始化爲0或者比較小的隨機數。

計算預測值

z=dot(W,X) W爲權重向量,X爲輸入向量。

z>0 ? 1 : -1;

更新權重

直接看公式
這裏寫圖片描述
其中
η表示學習速率(0.0和1.0間的常數)
y’表示實際的標籤值取值只有(-1,1)
y‘表示預測值 取值也只有(-1,1)
那麼y-y` 的值域爲{-2,0,2}

先看取0的時候
如果是0說明我們猜對了,那麼權重應該保持不變。

取-2的時候
說明真實結果是-1,預測值爲1。
我們的公式是z(i)=w(i)*x(i)。
出現這種情況只有一種原因:z(i) 就不應該超過閾值,那麼我們設置的權重就太大了。我們可以變小一點。正好當前權值加上一個負數就會變小。

取2的時候
說明真實結果是1,預測值爲-1。
根據上面的公式。
出現這種情況的只有一種原因:z(i)應該超過閾值,那麼我們權重就太小了。正好當前權重加上一個正數2就會變大。

這種調整很明顯可以正確的推向目標方向。

更新閾值

閾值也不是一次性寫死的,需要學習的到。這裏閾值的更新跟權重的更新幾乎一模一樣。直接上公式。
這裏寫圖片描述

這裏寫圖片描述

與權重跟新類似,閾值也會向目標方向推進!(無法理解的小夥伴一定要注意,w(0)存放的是-θ 是閾值的負數,上一節講過的。不理解可以在紙上畫一下)

代碼部分

# -*- coding: utf-8 -*-
# @Time    : 2017/11/17 上午10:10
# @Author  : SkullFang
# @Email   : [email protected]
# @File    : main.py
# @Software: PyCharm
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
class Preceptron(object):
    """
    內部變量 eta 學習率,
    n_iter: 權重向量訓練次數,
    w_權重向量,
    errors_錯誤隊列
    """

    def __init__(self,eta=0.01,n_iter=10):
        """
        :param eta:學習率 
        :param n_iter: 權重向量
        """
        self.eta=eta
        self.n_iter=n_iter
        pass

    def fit(self,x,y):
        """
        :param x:輸入樣本向量 
        :param y: 對應樣本分類
        :return: 
        """

        #初始化權重向量爲0
        #加一是因爲還有個閾值把它設置成0
        #x.shape[1]是列
        self.w_=np.zeros(1+x.shape[1])
        self.errors_=[]

        for _ in range(self.n_iter):
            errors=0
            for xi,target in zip(x,y):
                """
                zip會強行把兩個列表變成一個元祖形式的例如
                for x in zip([[1,2,3],[4,5,6]],[1,-5]):
                    print(x)

                ([1, 2, 3], 1)
                ([4, 5, 6], -5)
                """
                #update=eta*(y-y')
                update=self.eta * (target-
                self.predict(xi))
                #w(i)=w(i)+eta*(y-y')*x(i)
                self.w_[1:]+=update*xi
                #更新閾值
                self.w_[0] += update
                #錯誤次數
                errors+=int(update!=0.0)
                #把錯誤次數加到隊列中
                self.errors_.append(errors)
                pass
            pass
        pass

    def net_input(self,x):
        """
        這個是爲了輸入向量和權重向量做一下點積
        :param x: 輸入向量
        :return: 
        """
        return np.dot(x,self.w_[1:]+self.w_[0])
        pass

    def predict(self,x):
        """
        算出分類結果
        :param x: 
        :return: 
        """
        return np.where(self.net_input(x)>=0.0,1,-1)
        pass
    pass

這裏有都註釋,可以按照算法步驟一步一步的看。

調用代碼

if __name__ == '__main__':
    file = "data/irisdata.csv"
    df=pd.read_csv(file,header=None)
    #前10行
    # print(df.head(10))
    #加載0到100行第4列
    y=df.loc[0:100,4].values
    y=np.where(y=='Iris-setosa',-1,1)
    #x要第0列和2列
    x=df.loc[0:100,[0,2]].values

    plt.scatter(x[:50, 0], x[:50, 1], color='red', marker='o', label='setosa')
    plt.scatter(x[50:100, 0], x[50:100, 1], color='blue', marker='x', label='versicolor')
    plt.legend(loc='upper left')

    #作出感知器
    pnn = Preceptron(eta=0.1, n_iter=10)
    #訓練
    pnn.fit(x,y)
    #畫出結果
    plot_decision_regions(x,y,pnn,resolution=0.02)

其中csv數據爲最經典的鶯尾花數據。
這是地址:
https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data
打開復制在本地創建csv數據即可。

這裏使用了一個輔助畫圖的函數

def plot_decision_regions(x,y,classifier,resolution=0.02):
    """
    用於結果展示
    :param x: 
    :param y: 
    :param classifier: 
    :param resolution: 
    :return: 
    """
    makers=('s','x','o','v')
    colors=('red','blue','lightgreen','gray','cyan')
    cmap=ListedColormap(colors[:len(np.unique(y))])

    x1_min,x1_max=x[:,0].min()-1,x[:,0].max()
    x2_min,x2_max=x[:,1].min()-1,x[:,1].max()

    print(x1_min,x1_max)
    print(x2_min,x2_max)

    xx1,xx2=np.meshgrid(np.arange(x1_min,x1_max,resolution),np.arange(x2_min,x2_max,resolution))

    #預測結果
    z=classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)

    #畫分界線
    z=z.reshape(xx1.shape)
    plt.contourf(xx1, xx2, z, alpha=0.4, cmap=cmap)
    plt.xlim(x1_min, x1_max)
    plt.ylim(xx2.min(), xx2.max())
    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=x[y==cl,0],y=x[y==cl,1],alpha=0.0,c=cmap(idx),marker=makers[idx],label=cl)


    plt.show()

如果有哪裏看不懂歡迎留言。大家一起學習一起進步。

發佈了47 篇原創文章 · 獲贊 80 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章