用Python代码实战5大经典神经网络算法:从感知机到Hopfield网络

神经网络作为人工智能的核心技术之一,其发展历程中涌现了许多经典算法。本文将带您用Python代码实现5个具有里程碑意义的神经网络模型,通过动手实践深入理解其工作原理。我们将使用NumPy等基础库,避免过度依赖深度学习框架,让您真正掌握算法本质。

1. 单层感知机:二分类的起点

感知机是神经网络的最简单形式,由Frank Rosenblatt在1957年提出。它能够学习线性可分的二分类问题,是理解更复杂神经网络的基础。

import numpy as np

class Perceptron:
    def __init__(self, input_size, lr=0.01):
        self.weights = np.random.rand(input_size)
        self.bias = np.random.rand()
        self.lr = lr
    
    def predict(self, x):
        z = np.dot(x, self.weights) + self.bias
        return 1 if z > 0 else 0
    
    def train(self, X, y, epochs=100):
        for _ in range(epochs):
            for x, y_true in zip(X, y):
                y_pred = self.predict(x)
                error = y_true - y_pred
                self.weights += self.lr * error * x
                self.bias += self.lr * error

关键点解析:

  • 权重初始化:使用随机小数值初始化权重和偏置
  • 激活函数:采用阶跃函数(step function)作为激活函数
  • 学习规则:经典的感知机学习规则,仅当分类错误时调整权重

注意:感知机只能解决线性可分问题。对于非线性问题,需要更复杂的网络结构。

2. 多层感知机与反向传播:突破线性限制

多层感知机(MLP)通过引入隐藏层和非线性激活函数,能够解决非线性分类问题。反向传播算法是其训练的核心。

class MLP:
    def __init__(self, input_size, hidden_size, output_size):
        self.W1 = np.random.randn(input_size, hidden_size)
        self.b1 = np.zeros(hidden_size)
        self.W2 = np.random.randn(hidden_size, output_size)
        self.b2 = np.zeros(output_size)
    
    def sigmoid(self, x):
        return 1 / (1 + np.exp(-x))
    
    def forward(self, X):
        self.z1 = np.dot(X, self.W1) + self.b1
        self.a1 = self.sigmoid(self.z1)
        self.z2 = np.dot(self.a1, self.W2) + self.b2
        return self.sigmoid(self.z2)
    
    def backward(self, X, y, output, lr=0.01):
        error = output - y
        delta2 = error * output * (1 - output)
        dW2 = np.dot(self.a1.T, delta2)
        db2 = np.sum(delta2, axis=0)
        
        delta1 = np.dot(delta2, self.W2.T) * self.a1 * (1 - self.a1)
        dW1 = np.dot(X.T, delta1)
        db1 = np.sum(delta1, axis=0)
        
        self.W2 -= lr * dW2
        self.b2 -= lr * db2
        self.W1 -= lr * dW1
        self.b1 -= lr * db1
    
    def train(self, X, y, epochs=1000, lr=0.01):
        for _ in range(epochs):
            output = self.forward(X)
            self.backward(X, y, output, lr)

反向传播的四个关键步骤:

  1. 前向传播计算输出
  2. 计算输出层误差
  3. 反向传播误差到隐藏层
  4. 更新权重和偏置

3. K-means聚类:无监督学习的代表

K-means是最经典的聚类算法之一,通过迭代寻找聚类中心来实现数据分组。

class KMeans:
    def __init__(self, k=3, max_iter=100):
        self.k = k
        self.max_iter = max_iter
    
    def fit(self, X):
        self.centroids = X[np.random.choice(X.shape[0], self.k, replace=False)]
        
        for _ in range(self.max_iter):
            # 分配步骤
            distances = np.sqrt(((X - self.centroids[:, np.newaxis])**2).sum(axis=2))
            self.labels = np.argmin(distances, axis=0)
            
            # 更新步骤
            new_centroids = np.array([X[self.labels == i].mean(axis=0) 
                                     for i in range(self.k)])
            
            if np.allclose(self.centroids, new_centroids):
                break
                
            self.centroids = new_centroids
    
    def predict(self, X):
        distances = np.sqrt(((X - self.centroids[:, np.newaxis])**2).sum(axis=2))
        return np.argmin(distances, axis=0)

K-means的优缺点对比:

优点 缺点
简单易懂,实现容易 需要预先指定K值
计算效率高 对初始中心点敏感
适用于大数据集 只能发现球形簇
可解释性强 对噪声和异常值敏感

4. 竞争学习:生物启发的无监督方法

竞争学习模拟了生物神经元的侧向抑制机制,只有"获胜"的神经元会更新其权重。

class CompetitiveLearning:
    def __init__(self, input_size, output_size, lr=0.01):
        self.weights = np.random.rand(output_size, input_size)
        self.lr = lr
    
    def find_winner(self, x):
        similarities = np.dot(self.weights, x)
        return np.argmax(similarities)
    
    def train(self, X, epochs=100):
        for _ in range(epochs):
            for x in X:
                winner = self.find_winner(x)
                self.weights[winner] += self.lr * (x - self.weights[winner])
    
    def predict(self, X):
        return [self.find_winner(x) for x in X]

竞争学习的生物学基础:

  • 侧向抑制:活跃神经元抑制邻近神经元
  • Hebbian学习:"一起激活的神经元会连接在一起"
  • 神经可塑性:突触强度随经验变化

5. Hopfield网络:联想记忆的典范

Hopfield网络是一种全连接递归网络,能够存储和回忆模式,在联想记忆中有重要应用。

class HopfieldNetwork:
    def __init__(self, size):
        self.size = size
        self.weights = np.zeros((size, size))
    
    def train(self, patterns):
        for p in patterns:
            p = np.reshape(p, (self.size, 1))
            self.weights += np.dot(p, p.T)
        np.fill_diagonal(self.weights, 0)
    
    def recall(self, pattern, max_iter=10):
        pattern = np.copy(pattern)
        for _ in range(max_iter):
            for i in range(self.size):
                activation = np.dot(self.weights[i], pattern)
                pattern[i] = 1 if activation >= 0 else -1
        return pattern

Hopfield网络的能量函数:

E = -1/2 * ΣΣ w_ij * s_i * s_j

网络会收敛到能量局部最小点,这些点对应存储的记忆模式。

可视化与实战技巧

为了更直观地理解这些算法的行为,我们可以使用Matplotlib进行可视化。以下是感知机决策边界的可视化示例:

import matplotlib.pyplot as plt

def plot_decision_boundary(model, X, y):
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01),
                         np.arange(y_min, y_max, 0.01))
    
    Z = np.array([model.predict(np.array([x, y])) 
                 for x, y in zip(xx.ravel(), yy.ravel())])
    Z = Z.reshape(xx.shape)
    
    plt.contourf(xx, yy, Z, alpha=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=20, edgecolor='k')
    plt.title('Perceptron Decision Boundary')
    plt.xlabel('Feature 1')
    plt.ylabel('Feature 2')
    plt.show()

神经网络训练的实用技巧:

  • 数据标准化:将输入特征缩放到相似范围
  • 学习率调整:开始使用较大学习率,后期逐渐减小
  • 批量训练:小批量训练比全批量更高效
  • 早停策略:验证集性能不再提升时停止训练
  • 权重初始化:Xavier或He初始化优于纯随机初始化

通过这5个经典算法的实现,我们不仅理解了神经网络的发展脉络,也掌握了从简单到复杂的多种学习范式。这些基础算法仍然是现代深度学习的核心思想来源,深入理解它们将为学习更先进的模型打下坚实基础。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐