天天看點

【MachineLearning】之 感覺機

文章目錄

  • ​​一、前言​​
  • ​​二、感覺機​​
  • ​​(1)那,什麼是感覺機呢?​​
  • ​​(2)感覺機的損失函數​​
  • ​​點到直線的距離​​
  • ​​(3)随機梯度下降(Stochastic gradient descent,簡稱:SGD)​​
  • ​​三、實戰​​

一、前言

邏輯回歸起源于線性回歸
【MachineLearning】之 感覺機

當資料點處于線性可分時,我們可以使用一條直線将其分開,而分割線的函數為:

那麼,怎樣判定這個資料點屬于哪一個類别呢?

可以通過函數進行劃分,比如:​

​sign​

​函數

【MachineLearning】之 感覺機

那麼,當 ​

​(1)​

​​ 和 ​

​(2)​

​ 組合起來,就成了感覺機,如:

二、感覺機

(1)那,什麼是感覺機呢?

線上性回歸的基礎上,将資料點進行劃分,并判定這個資料點屬于哪一個類别。

so,感覺機計算流程圖如下:

【MachineLearning】之 感覺機

(2)感覺機的損失函數

如何減少誤分類情況呢?

【MachineLearning】之 感覺機

通常會使用誤分類點到分割線(面)的距離去定義損失函數

點到直線的距離

對于 維實數向量空間中任意一點 到直線 的距離為:

其中 表示

然後,對于誤分類點

那麼,誤分類點 到分割線(面)的距離就為:

于是,假設所有誤分類點的集合為 ,全部誤分類點到分割線(面)的距離就為:

最後得到感覺機的損失函數為:

從公式(8)可以看出,損失函數 是非負的。也就是說,當沒有誤分類點時,損失函數的值為 ​​

​0​

​​。同時,誤分類點越少,誤分類點距離分割線(面)就越近,損失函數值就越小。同時,損失函數

(3)随機梯度下降(Stochastic gradient descent,簡稱:SGD)

影響因素:學習率太大或者疊代次數太少。

【MachineLearning】之 感覺機

目的:為了快速極小化損失函數,增大“步長”,實作快速收斂。

  1. 一般梯度下降(Gradient descent):針對每個誤分類點執行梯度下降
  2. 随機梯度下降:每次随機選取一個誤分類點執行梯度下降

實驗 SGD 計算公式(8)的極小值時,首先任選一個分割面 和 ,然後使用梯度下降法不斷地極小化損失函數:

計算損失函數的偏導數:

如果 更新 和

實作代碼:

"""感覺機随機梯度下降算法實作
"""
def perceptron_sgd(X, Y, alpha, epochs):
    """
    參數:
    X -- 自變量資料矩陣
    Y -- 因變量資料矩陣
    alpha -- lamda 參數
    epochs -- 疊代次數

    傳回:
    w -- 權重系數
    b -- 截距項
    """
    w = np.zeros(len(X[0])) # 初始化參數為 0
    b = np.zeros(1)
    
    for t in range(epochs): # 疊代
        for i, x in enumerate(X):
            if ((np.dot(X[i], w)+b)*Y[i]) <= 0: # 判斷條件
                w = w + alpha*X[i]*Y[i] # 更新參數
                b = b + alpha*Y[i]

    return w,      

三、實戰

// !wget -nc http://labfile.oss.aliyuncs.com/courses/1081/course-12-data.csv



"""加載資料集
"""
import pandas as pd

df = pd.read_csv("course-12-data.csv", header=0) # 加載資料集
df.head() # 預覽前 5 行資料


"""繪制資料集
"""
from matplotlib import pyplot as plt
%matplotlib inline

plt.figure(figsize=(10, 6))
plt.scatter(df['X0'],df['X1'], c=df['Y'])



// 求最佳分割線
import numpy as np

X = df[['X0','X1']].values
Y = df['Y'].values

alpha = 0.1
epochs = 150

perceptron_sgd(X, Y, alpha, epochs)      
// 求解正确率
L = perceptron_sgd(X, Y, alpha, epochs)
w1 = L[0][0]
w2 = L[0][1]
b = L[1]

z = np.dot(X, np.array([w1, w2]).T) + b
np.sign(z)

// 也可使用sklearn 直接求得
from sklearn.metrics import accuracy_score

accuracy_score(Y, np.sign(z))      

繪制決策邊界線

# 繪制輪廓線圖,不需要掌握
plt.figure(figsize=(10, 6))
plt.scatter(df['X0'],df['X1'], c=df['Y'])

x1_min, x1_max = df['X0'].min(), df['X0'].max(),
x2_min, x2_max = df['X1'].min(), df['X1'].max(),

xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max), np.linspace(x2_min, x2_max))
grid = np.c_[xx1.ravel(), xx2.ravel()]

probs = (np.dot(grid, np.array([L[0][0], L[0][1]]).T) + L[1]).reshape(xx1.shape)
plt.contour(xx1, xx2, probs, [0], linewidths=1, colors='red');      

繪制損失函數變換曲線

"""計算每次疊代後的損失函數值
"""
def perceptron_loss(X, Y, alpha, epochs):
    
    """
    參數:
    X -- 自變量資料矩陣
    Y -- 因變量資料矩陣
    alpha -- lamda 參數
    epochs -- 疊代次數

    傳回:
    loss_list -- 每次疊代損失函數值清單
    """
    
    w = np.zeros(len(X[0])) # 初始化參數為 0
    b = np.zeros(1)
    loss_list = []
    
    for t in range(epochs): # 疊代
        loss_init = 0
        for i, x in enumerate(X):
            if ((np.dot(X[i], w)+b)*Y[i]) <= 0: # 判斷條件
                loss_init += (((np.dot(X[i], w)+b)*Y[i]))
                w = w + alpha*X[i]*Y[i] # 更新參數
                b = b + alpha*Y[i]
        loss_list.append(loss_init * -1)
    
    return loss_list

loss_list = perceptron_loss(X, Y, alpha, epochs)

plt.figure(figsize=(10, 6))
plt.plot([i for i in range(len(loss_list))], loss_list)
plt.xlabel("Learning rate {}, Epochs {}".format(alpha, epochs))
plt.ylabel("Loss function")      

采取減國小習率 + 增加疊代次數的方法找到損失函數極小值點。

alpha = 0.05 # 減國小習率
epochs = 1000 # 增加疊代次數

loss_list = perceptron_loss(X, Y, alpha, epochs)

plt.figure(figsize=(10, 6))
plt.plot([i for i in range(len(loss_list))], loss_list)
plt.xlabel("Learning rate {}, Epochs {}".format(alpha, epochs))
plt.ylabel("Loss function")


L = perceptron_sgd(X, Y, alpha, epochs)
z = np.dot(X, L[0].T) + L[1]
accuracy_score(Y, np.sign(z))      

繼續閱讀