粒子群算法PSO优化BP神经网络(PSO-BP)回归预测——Python和MATLAB实现

下面是一个使用Python实现的粒子群算法(PSO)优化反向传播神经网络(BP)的示例代码。

以下是具体的代码实现:

```python
import numpy as np
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 激活函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    return x * (1 - x)

# Feedforward Neural Network
class BP_Network:
    def __init__(self, input_size, hidden_size, output_size):
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.output_size = output_size

        # 权重和偏置初始化
        self.W1 = np.random.randn(input_size, hidden_size)
        self.b1 = np.random.randn(hidden_size)
        self.W2 = np.random.randn(hidden_size, output_size)
        self.b2 = np.random.randn(output_size)

    def predict(self, X):
        self.hidden_activation = sigmoid(np.dot(X, self.W1) + self.b1)
        self.output = np.dot(self.hidden_activation, self.W2) + self.b2
        return self.output

    def train(self, X, y, epochs, learning_rate):
        for _ in range(epochs):
            # Forward pass
            self.hidden_activation = sigmoid(np.dot(X, self.W1) + self.b1)
            output = np.dot(self.hidden_activation, self.W2) + self.b2
            
            # 计算误差
            error = y - output
            
            # Backward pass
            d_output = error  # 对输出层的误差
            d_hidden = d_output.dot(self.W2.T) * sigmoid_derivative(self.hidden_activation)

            # 更新权重和偏置
            self.W2 += self.hidden_activation.T.dot(d_output) * learning_rate
            self.b2 += np.sum(d_output, axis=0) * learning_rate
            self.W1 += X.T.dot(d_hidden) * learning_rate
            self.b1 += np.sum(d_hidden, axis=0) * learning_rate

# 粒子类
class Particle:
    def __init__(self, input_size, hidden_size, output_size):
        self.network = BP_Network(input_size, hidden_size, output_size)
        self.position = np.concatenate([self.network.W1.flatten(), self.network.b1, self.network.W2.flatten(), self.network.b2])
        self.velocity = np.random.rand(len(self.position)) * 0.1
        self.best_position = np.copy(self.position)
        self.best_score = float('inf')

    def evaluate(self, X, y):
        self.network.W1 = self.position[:self.network.input_size * self.network.hidden_size].reshape(self.network.input_size, self.network.hidden_size)
        self.network.b1 = self.position[self.network.input_size * self.network.hidden_size:self.network.input_size * self.network.hidden_size + self.network.hidden_size]
        self.network.W2 = self.position[self.network.input_size * self.network.hidden_size + self.network.hidden_size:-self.network.output_size].reshape(self.network.hidden_size, self.network.output_size)
        self.network.b2 = self.position[-self.network.output_size:]

        predictions = self.network.predict(X)
        error = np.mean((y - predictions) ** 2)
        return error

# 粒子群算法
def pso(X_train, y_train, num_particles=30, epochs=100, hidden_size=10):
    input_size = X_train.shape[1]
    output_size = y_train.shape[1]
    
    particles = [Particle(input_size, hidden_size, output_size) for _ in range(num_particles)]
    global_best_position = np.zeros(len(particles[0].position))
    global_best_score = float('inf')

    for iteration in range(epochs):
        for particle in particles:
            score = particle.evaluate(X_train, y_train)

            # 更新个人最佳
            if score < particle.best_score:
                particle.best_score = score
                particle.best_position = np.copy(particle.position)

            # 更新全局最佳
            if score < global_best_score:
                global_best_score = score
                global_best_position = np.copy(particle.position)

        # 更新速度和位置
        w = 0.5
        c1 = 1.0
        c2 = 1.0

        for particle in particles:
            r1 = np.random.rand(len(particle.position))
            r2 = np.random.rand(len(particle.position))
            particle.velocity = (w * particle.velocity +
                                 c1 * r1 * (particle.best_position - particle.position) +
                                 c2 * r2 * (global_best_position - particle.position))
            particle.position += particle.velocity

        print(f'Iteration {iteration + 1}, Global Best Score: {global_best_score}')

    return global_best_position

# 生成数据
X, y = make_regression(n_samples=1000, n_features=10, noise=0.1)
y = y.reshape(-1, 1)  # 确保输出为二维数组

# 数据归一化
scaler = StandardScaler()
X = scaler.fit_transform(X)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# PSO 优化 BP 神经网络
best_params = pso(X_train, y_train, num_particles=30, epochs=100, hidden_size=10)

# 从最佳参数中构建最终模型
best_network = BP_Network(input_size=X_train.shape[1], hidden_size=10, output_size=1)
best_network.W1 = best_params[:best_network.input_size * best_network.hidden_size].reshape(best_network.input_size, best_network.hidden_size)
best_network.b1 = best_params[best_network.input_size * best_network.hidden_size:best_network.input_size * best_network.hidden_size + best_network.hidden_size]
best_network.W2 = best_params[best_network.input_size * best_network.hidden_size + best_network.hidden_size:-1].reshape(best_network.hidden_size, 1)
best_network.b2 = best_params[-1:]

# 在测试集上预测
y_test_pred = best_network.predict(X_test)

# 计算均方误差
test_mse = np.mean((y_test - y_test_pred) ** 2)
print(f'Test MSE: {test_mse}')
```

### 代码解释

1. **数据生成与预处理**:使用`make_regression`生成模拟回归数据,归一化输入数据。
2. **BP网络实现**:定义了一个简单的前馈神经网络类,并实现了训练和预测功能。
3. **粒子类实现**:定义了粒子类,该类的每个实例都有自己的神经网络,位置(参数)、速度、最佳位置和最佳评分。
4. **PSO算法**:实现了PSO算法,通过评估每个粒子的表现来更新其位置和速度,并根据最佳表现更新全局最佳位置。
5. **模型训练与测试**:使用PSO优化BP神经网络后,预测测试集并计算均方误差。

### 注意事项

- 本示例中的神经网络和PSO实现是基本的,可以根据需求调整超参数和模型结构。
- 若处理更复杂的问题,建议考虑使用深度学习库如`TensorFlow`或`PyTorch`,并结合现有的优化算法库。
 

在MATLAB中,可以使用内置的神经网络工具箱来实现BP神经网络进行预测。以下是一个使用MATLAB创建和训练BP神经网络的示例代码。

### 1. 准备数据

首先,我们需要准备一些示例数据。这里我们将生成一些随机数据作为示例。

### 2. 创建和训练模型

以下是完整的MATLAB代码示例:

```matlab
% 生成示例数据
X = rand(1000, 20);  % 1000个样本,20个特征
y = rand(1000, 1);    % 1000个样本,1个目标

% 将数据分为训练集和测试集
trainRatio = 70/100;  % 70%用于训练
valRatio = 15/100;    % 15%用于验证
testRatio = 15/100;   % 15%用于测试

% 划分数据
[trainX, valX, testX, trainY, valY, testY] = ...
    dividerand(X, y, trainRatio, valRatio, testRatio);

% 创建一个前馈神经网络
hiddenLayerSize = 10;  % 隐藏层神经元数量
net = fitnet(hiddenLayerSize);

% 设置训练参数
net.performParam.regularization = 0.01;  % 正则化参数
net.trainParam.epochs = 1000;             % 最大训练周期
net.trainParam.goal = 1e-5;                % 停止条件

% 训练网络
[net, tr] = train(net, trainX', trainY');

% 使用验证集和测试集评估模型性能
valPredictions = net(valX');
testPredictions = net(testX');

% 计算均方误差
valMSE = perform(net, valY', valPredictions);
testMSE = perform(net, testY', testPredictions);

fprintf('Validation MSE: %.4f\n', valMSE);
fprintf('Test MSE: %.4f\n', testMSE);

% 绘制训练过程
figure;
plotperform(tr);
```

### 代码解释

1. **数据生成**:使用`rand`函数生成随机的特征和目标数据。
2. **数据划分**:使用`dividerand`函数将数据划分为训练集、验证集和测试集。
3. **网络创建**:使用`fitnet`创建一个前馈神经网络,指定隐藏层中神经元的数量。
4. **训练参数设置**:可以设置正则化参数、最大训练周期和停止条件等。
5. **模型训练**:使用`train`函数来训练网络。
6. **预测与评估**:对验证集和测试集进行预测,并计算均方误差MSE。
7. **结果可视化**:使用`plotperform`函数绘制训练过程中的性能曲线。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值