感知機模型

归去_来兮發表於2024-09-06

一、概述

  感知機模型(Perceptron Model)也叫做神經元模型,設計靈感即來自於生物神經元的執行機制,依次完成資訊接收、處理、輸出的過程。當前大放異彩的各種人工神經網路模型即由一個個人工神經元構成,因此,本文介紹的感知機模型(神經元模型)就是各種神經網路模型的基本單元。

二、模型原理

模型原理

  模型的核心概況起來即是線性迴歸+符號函式對映。對未知資料,先做線性擬合,輸出值再經符號函式對映,完成類別判定。因此,感知機模型也是直接用於二分類任務的模型。模型示意圖可表示為

模型原理直接地表示也就是

\[y=\left\{ \begin{aligned} &-1, \ w\cdot x+b<0\\ &1, \ w\cdot x+b\geq 0 \end{aligned} \right. \]

對任意待測樣本,將其特徵向量直接代入計算即可。

模型的訓練

  模型的引數就是指線性迴歸中的權重和偏置,確定了它們也就確定了整個模型。對引數的確定往往透過訓練資料集實施,也就是由訓練集和標籤之間的對應構造一個關於待求引數的損失函式,透過不斷迭代最佳化,在過程中確定出最佳的引數值。損失函式的構造通常採用這樣一種方式,就是計算所有誤分類樣本到決策函式的距離和。表示式為

\[d=\frac{1}{\left| \left| w \right| \right|}\sum_{x_i\in M}{\left| w\cdot x_i+b \right|} \]

其中,\(\left| \left| w \right| \right|=\sqrt{w_{1}^{2}+w_{2}^{2}+...+w_{n}^{2}}\),M為誤分類樣本集。
  為進一步簡化,可以將絕對值計算以‘-y’等價替換。y是樣本的標籤,取值要麼為1,要麼為-1,若y為1,表明樣本為正,錯誤判定時計算得到的迴歸值為負,此時‘-y負值’為正;若y為-1,表明樣本為負,錯誤判定時計算得到的迴歸值為正,此時‘-y正值’仍為正,與絕對值運算等價,此時損失函式表示式為

\[d=-\frac{1}{\left| \left| w \right| \right|}\sum_{x_i\in M}{y_i(w\cdot x_i+b)} \]

  式中的\(\frac{1}{\left| \left| w \right| \right|}\)實質地表徵了決策函式的方向性,而模型關注的是對兩類樣本的類別結果判定,並不實際關注決策函式的具體方向以及樣本到函式距離的具體差異,因而該部分可以省去,損失函式也就簡化為

\[d=-\sum_{x_i\in M}{y_i(w\cdot x_i+b)} \]

三、Python實現

手工實現:

import numpy as np
from sklearn import datasets

def model(X, theta):
    return X @ theta

def predict(x, theta):
    flags = model(x, theta)
    y = np.ones_like(flags)
    y[np.where(flags < 0)[0]] = -1
    return y

def computerCost(X, y, theta):
    y_pred = predict(X, theta)
    error_index = np.where(y_pred != y)[0]
    return np.squeeze(-y_pred[error_index].T @ y[error_index])

def gradientDescent(X, y, alpha, num_iters=1000):
    n = X.shape[1]
    theta = np.zeros((n, 1))
    J_history = []
    for i in range(num_iters):
        y_pred = predict(X, theta)
        error_index = np.where(y_pred != y)[0]
        theta = theta + alpha * X[error_index, :].T @ y[error_index]
        cur_cost = computerCost(X, y, theta)
        J_history.append(cur_cost)
        print('.', end='')
        if cur_cost == 0:
            print(f'Finished in advance in iteration {i + 1}!')
            break

    return theta, J_history

iris = datasets.load_iris()
X = iris.data
m = X.shape[0]
X = np.hstack((np.ones((m, 1)), X))
y = iris.target
y[np.where(y != 0)[0]] = -1
y[np.where(y == 0)[0]] = 1
y = y.reshape((len(y), 1))
theta, J_history = gradientDescent(X, y, 0.01, 1000)
y_pred = predict(X, theta)
acc = np.sum(y_pred == y) / len(y)

print('acc:\n', acc)


基於PyTorch實現:

import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import numpy as np

# 生成一些隨機的線性可分資料
np.random.seed(42)
num_samples = 100
features = 2
x = 10 * np.random.rand(num_samples, features)  # 生成隨機輸入特徵
w_true = np.array([2, -3.4])  # 真實的權重
b_true = 4.2  # 真實的偏置
y_true = np.dot(x, w_true) + b_true + 0.1 * np.random.randn(num_samples)  # 新增噪聲
y_true = np.where(y_true > 0, 1, -1)  # 將輸出標籤轉換為二分類問題

# 將資料轉換為 PyTorch 的 Tensor
x = torch.tensor(x, dtype=torch.float32)
y_true = torch.tensor(y_true, dtype=torch.float32)

# 定義感知機模型
class Perceptron(nn.Module):
    def __init__(self, input_size):
        super(Perceptron, self).__init__()
        self.linear = nn.Linear(input_size, 1)

    def forward(self, x):
        return torch.sign(self.linear(x))

# 初始化感知機模型
perceptron = Perceptron(input_size=features)

# 定義損失函式和最佳化器
criterion = nn.MSELoss()
optimizer = optim.SGD(perceptron.parameters(), lr=0.01)

# 訓練感知機模型
num_epochs = 100
for epoch in range(num_epochs):
    # 前向傳播
    y_pred = perceptron(x)

    # 計算損失
    loss = criterion(y_pred.view(-1), y_true)

    # 反向傳播和最佳化
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    # 列印損失
    if (epoch + 1) % 10 == 0:
        print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')

# 在訓練資料上進行預測
with torch.no_grad():
    predictions = perceptron(x).numpy()

# 視覺化結果
plt.scatter(x[:, 0], x[:, 1], c=predictions.flatten(), cmap='coolwarm', marker='o')
plt.title('Perceptron Model')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.show()


End.


pdf下載

相關文章