自适应差分进化极限学习机模型
自适应差分进化学习机( Adaptive Differential Evolution Extreme Learning Machine,ADE-ELM)是一种结合了差分进化算法(Differential Evolution,DE)和极限学习机(Extreme Learning Machine,ELM)的混合模型,旨在提高极限学习机的性能。
一、介绍
- 极限学习机(ELM)
极限学习机是一种单隐层前馈神经网络(ELFN),其特点是随机生成输入层到隐层的权重和偏置,并通过最小二乘法直接计算隐层到输出层的权重。
优势在于训练速度快,更适用于大规模数据库。
- 差分进化算法(DE)
差分进化是一种基于种群的全局优化算法,通过变异,交叉和选择操作来搜索最优解。
DE拥有较强的全局搜索能力,适用于复杂的非线性优化问题。
- 自适应差分进化极限学习机(ADE-ELM)
结合了ELM和DE的优点,通过自适应差分进化算法优化ELM的输入层到隐层的权重和偏置,以提高模型的泛化能力和预测精度
主要步骤:
(1)初始化:随机生成初始种群,每个个体代表一组ELM的输入层到隐层的权重和偏置
(2)变异:根据差分进化的变异策略生成新的个体
(3)交叉:将变异个体与当前个体进行交叉操作,生成试验个体
(4)选择:根据适应度函数选择较优的个体进入下一代
(5)自适应调整:根据种群的进化状态自适应调整DE的控制参数(如变异因子和交叉概率)
(6)训练ELM:使用优化后的权重和偏置训练ELM模型,并计算输出层的权重
(7)评估:在测试集上评估模型的性能
- 优点:
全局搜索能力
自适应调整
训练速度快
二、模型构建
import numpy as np
from sklearn.base import BaseEstimator, RegressorMixin
from sklearn.metrics import mean_squared_error
import time
import sys
import matplotlib.pyplot as plt
class ADE_ELM(BaseEstimator, RegressorMixin):
def __init__(self, hidden_units=20, max_iter=100, F=0.5, CR=0.9, adaptive=True):
"""
初始化 ADE-ELM 模型
参数:
- hidden_units: 隐层神经元数量
- max_iter: 差分进化的最大迭代次数
- F: 差分进化的变异因子
- CR: 差分进化的交叉概率
- adaptive: 是否使用自适应机制
"""
self.hidden_units = hidden_units
self.max_iter = max_iter
self.F = F
self.CR = CR
self.adaptive = adaptive
self.weights = None
self.bias = None
self.beta = None
def _sigmoid(self, x):
"""Sigmoid 激活函数"""
return 1 / (1 + np.exp(-x))
def _initialize_population(self, n_features):
"""初始化差分进化的种群"""
#生成形状为(self.hidden_units, n_features + 1)
#隐藏层层数即代表了生成的种群的个体数目?(20,9)
return np.random.uniform(-1, 1, (self.hidden_units,n_features + 1,))
def _evaluate_fitness(self, population, X, y):
"""计算种群中每个个体的适应度(MSE)"""
fitness = []
population = population.T
W = population[:-1].reshape(-1, self.hidden_units)
b = population[-1]
#隐藏层输出
H = self._sigmoid(np.dot(X, W) + b)
#输出层权重,#伪逆
beta = np.dot(np.linalg.pinv(H), y)
#预测值
y_pred = np.dot(H, beta)
rmse = np.sqrt(mean_squared_error(y, y_pred))
fitness = rmse
return np.array(fitness)
def _mutate(self, population, F):
"""差分进化的变异操作"""
mutant_population = np.zeros_like(population)
for i in range(len(population)):
indices = [idx for idx in range(len(population)) if idx != i]
a, b, c = population[np.random.choice(indices, 3, replace=False)]
mutant_population[i] = a + F * (b - c)
return mutant_population
def _crossover(self, population, mutant_population, CR):
"""差分进化的交叉操作"""
# 有疑虑
trial_population = np.zeros_like(population)
for i in range(len(population)):
crossover_mask = np.random.rand(population.shape[1]) < CR
trial_population[i] = np.where(crossover_mask, mutant_population[i], population[i])
return trial_population
def _select(self, population, trial_population, X, y):
"""差分进化的选择操作"""
fitness = self._evaluate_fitness(population, X, y)
trial_fitness = self._evaluate_fitness(trial_population, X, y)
new_population = np.where(trial_fitness < fitness, trial_population, population)
return new_population
def fit(self, X, y):
n_samples, n_features = X.shape
population = self._initialize_population(n_features)
fit_list = []
for iteration in range(self.max_iter):
if self.adaptive:
self.F = 0.5 + 0.5 * np.random.rand()
self.CR = 0.9 + 0.1 * np.random.rand()
mutant_population = self._mutate(population, self.F)
trial_population = self._crossover(population, mutant_population, self.CR)
population = self._select(population, trial_population, X, y)
#进度条
print("\r", end="")
i = int((iteration+1)*100/self.max_iter)
print("进度: {}%: ".format(i), "▓" * (i // 2), end="")
sys.stdout.flush()
time.sleep(0.05)
#监测适应度
fitness = self._evaluate_fitness(population,X, y)
fit_list.append(fitness)
#绘制曲线
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
plt.plot(range(self.max_iter), fit_list, marker='o')
plt.xlabel('迭代次数')
plt.ylabel('RMSE')
plt.title('学习曲线')
plt.grid()
plt.show()
# 选择最优个体
best_individual = population.T
self.weights = best_individual[:-1] # 形状为 (8,20)
self.bias = best_individual[-1] # 形状为 (1,20)
# 计算隐藏层输出
H = self._sigmoid(
np.dot(X, self.weights) + self.bias) #(1000,20) X: (n_samples, n_features), weights: (n_features, hidden_units)
self.beta = np.dot(np.linalg.pinv(H), y) # (20,1)H: (n_samples, hidden_units), y: (n_samples,)
def predict(self, X):
"""
使用训练好的模型进行预测
参数:
- X: 输入特征 (n_samples, n_features)
返回:
- y_pred: 预测值 (n_samples,)
"""
H = self._sigmoid(np.dot(X, self.weights) + self.bias)
y_pred = np.dot(H, self.beta)
return y_pred