Python的遗传算法GA优化深度置信网络DBN超参数回归预测

        DBN超参数众多,包括隐含层层数、各层节点数、无监督预训练阶段的训练次数及其学习率、微调阶段的训练次数及其学习率、与Batchsize,如果采用SGD相关优化器,还有动量项这个超参数。总之就是特别多,手动选择的话很难选到最佳超参数组合,为此采用遗传算法对上述超参数进行优化。

        之前写过MATLAB版本的DBN超参数优化,今天这个是python/torch版本的DBN超参数优化。具体运行环境python36、torch1.2。

        话不多说,直接上结果。数据结构是多输入单输出,按照7:3随机划分训练集与测试集。

        1、DBN预测,代码如下

# -*- coding: utf-8 -*-
# DBN建模
import time
import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体)
plt.rcParams['axes.unicode_minus'] = False   # 步骤二(解决坐标轴负数的负号显示问题)
from sklearn.preprocessing import StandardScaler,MinMaxScaler
from sklearn.model_selection import train_test_split
from scipy.io import savemat,loadmat
from sklearn.metrics import r2_score
import warnings
warnings.filterwarnings("ignore")
import torch
from utils.DBN import DBN
device = 'cuda:0' if torch.cuda.is_available() else 'cpu'
seed=0
if device == 'cuda':
    torch.cuda.manual_seed(seed) # 为当前GPU设置随机种子
    torch.cuda.manual_seed_all(seed)  # if you are using multi-GPU,为所有GPU设置随机种子
else:
    torch.manual_seed(seed) # 为CPU设置随机种子
# In[] 加载数据
data=pd.read_csv('data1.csv',header=None)
input_data=data.iloc[:,:-1].values
output_data=data.iloc[:,-1].values.reshape(-1,1)
# 归一化
#ss_X = StandardScaler().fit(input_data)
#ss_y = StandardScaler().fit(output_data)
ss_X=MinMaxScaler(feature_range=(0,1)).fit(input_data)
ss_y=MinMaxScaler(feature_range=(0,1)).fit(output_data)
input_data = ss_X.transform(input_data)
output_data = ss_y.transform(output_data)
# 划分样本
x_train,x_valid, y_train, y_valid = train_test_split(input_data,output_data,test_size=0.3,random_state=0)
# In[] 模型构建与训练
start_time=time.time()
#超参数设置
input_length = x_train.shape[1]
output_length = y_train.shape[1]
# network
# rbm的学习率和迭代次数,无监督逐层预训练
learning_rate=0.1
epoch_pretrain = 10
# 隐含层
hidden_units = [20,15]
# batchsize
batch_size = 64
# 微调阶段dbn采用SGD优化器,学习率,迭代次数,动量,激活函数(4选1),损失函数为均方差
learning_rate_finetune=0.1
epoch_finetune = 100
momentum=0.9
tf='Sigmoid'# Sigmoid ReLU Tanh Softplus
loss_function = torch.nn.MSELoss(reduction='mean')  # 均方差损失
optimizer = torch.optim.SGD
# Build model
dbn = DBN(hidden_units, input_length, output_length,learning_rate=learning_rate,activate=tf, device=device)
# 无监督预训练dbn中各rbm
dbn.pretrain(x_train, epoch=epoch_pretrain, batch_size=batch_size)
# 有监督微调
dbn.finetune(x_train, y_train, epoch_finetune, batch_size, loss_function,
             optimizer(dbn.parameters(), lr=learning_rate_finetune, momentum=momentum),
             validation=[x_valid,y_valid],shuffle=True,types=1)
plt.figure()
plt.plot(dbn.finetune_train_loss,label='train_loss')
plt.plot(dbn.finetune_valid_loss,label='valid_loss')
plt.legend()
plt.title('Loss Curve')
plt.show()
# In[] Make prediction and plot
y_predict = dbn.predict(x_valid, batch_size,types=1)
y_predict=y_predict.cpu().numpy()
end_time=time.time()
print('Time cost: %f s'%(end_time-start_time))
# 对测试结果进行反归一化
test_pred = ss_y.inverse_transform(y_predict)
test_label = ss_y.inverse_transform(y_valid)
# In[] 
# 画出测试集的值
plt.figure()
plt.plot(test_label,c='r', label='true')
plt.plot(test_pred,c='b',label='pred')
plt.legend()
plt.show()
# In[]计算各种指标
# mape
test_mape=np.mean(np.abs((test_pred-test_label)/test_label))
# rmse
test_rmse=np.sqrt(np.mean(np.square(test_pred-test_label)))
# mae
test_mae=np.mean(np.abs(test_pred-test_label))
# R2
test_r2=r2_score(test_label,test_pred)
print('测试集的mape:',test_mape,' rmse:',test_rmse,' mae:',test_mae,' R2:',test_r2)

结果如下:

图 1 DBN损失曲线
图2 DBN预测结果

        指标如下:

        mape: 0.02131540499483512  

        rmse: 0.06900334093296646  

        mae: 0.04012139316438816  

        R2: 0.9663487401772392

2、遗传优化DBN超参数

本文利用GA对DBN的超参数进行寻优,以最小化DBN预测值与实际值的MSE为适应度函数,目的就是通过GA找到一组超参数,用这组超参数训练的DBN,具有最小的网络误差。寻优参数及其范围设置如下:

lb=[0.01,0.01,0.1,1 ,1,  1,  1,10]
ub=[0.1,  0.5,  1,21,201,257,4,101]
#预训练学习率的范围是0.01到0.1
#微调训练学习率的范围是0.01到0.5
#动量0.1到1
#rbm迭代次数是1到20,
#dbn微调的迭代次数是1到200
#batchsize是1到256
#隐含层数量是1到3
#隐含层节点数是10-100

操作要点:

1)前3个超参数是浮点型、后面的都是整型

2)遗传算法每条DNA的长度是10,就是前7个参数是两个学习率、动量项、两个训练迭代次数、batchsize与层数,因为我们程序设置的最大隐含层是3(ub中是4,是因为random.int这个函数是左闭右开),所以一共10维,即使某DNA中层数是2,也是10维,只不过最后1层为0,例如:

[0.1,0.5,0.9,10,25,64,1,10,0,0],则代表两个学习率分别为0.1 0.5;动量为0.9; 两个迭代次数分别是10,25,batchsize是64,隐含层层数是1,神经元为[10]

[0.1,0.5,0.9,10,25,64,2,10,15,0],则代表两个学习率分别为0.1 0.5;动量为0.9; 两个迭代次数分别是10,25,batchsize是64,隐含层层数是2,各层神经元分别为[10,15]

[0.1,0.5,0.9,10,25,64,5,10,15,20],则代表两个学习率分别为0.1 0.5;动量为0.9; 两个迭代次数分别是10,25,batchsize是64,隐含层层数是3,各层神经元分别为[10,15,30]

当然哈,ub中这个参数是可调的,随便设都行,只要大于1。

3)交叉操作的时候,隐含层层数这个参数不交叉,因为两个DNA如果层数不一致,交叉了的话,后面的节点数就不对了。如果要交叉这个参数的话,就把后面各层的节点数一起进行交叉。

4)变异的时候,隐含层层数发生改变之后,先把该条DNA的各层节点数全部置0 ,然后重新根据层数进行赋值。

寻优结果适应度曲线如图所示。

图3 适应度曲线

 对应GA每代优化后的最优超参数组合如下表所示。可见最优DBN的隐含层层数为3层,各层的节点数是92、35、54。

 取最后一代优化得到的最优超参数组合(就是第9行那个)用来训练DBN,得到的结果如下:

3、结果对比

  • 10
    点赞
  • 127
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论
遗传算法GA)是一种优化算法,可以用于优化深度置信网络DBN)的超参数,并用于回归预测。 以下是用Python实现遗传算法GA优化DBN超参数回归预测的步骤: 1. 定义适应度函数:适应度函数用于评估每个个体的适应度程度。在回归预测中,可以使用均方根误差(RMSE)作为适应度函数。 2. 初始化种群:初始化一组随机的超参数组合作为种群。 3. 选择操作:选择操作用于选择适应度最好的个体。可以使用轮盘赌选择,即根据每个个体的适应度计算选择概率,然后随机选择个体。 4. 交叉操作:交叉操作用于将两个个体的超参数组合进行交叉,生成新的个体。可以使用单点交叉或多点交叉。 5. 变异操作:变异操作用于随机改变个体的某些超参数值,以增加种群的多样性。 6. 重复以上步骤,直到达到预定的迭代次数或满足收敛条件。 7. 输出最优解:输出适应度最好的个体的超参数组合作为最优解,用于DBN超参数调优。 8. 使用最优解进行回归预测:使用最优解的超参数组合训练DBN模型,并用于回归预测。 下面是一个简单的Python代码示例,用于实现遗传算法GA优化DBN超参数回归预测: ```python import numpy as np from sklearn.neural_network import BernoulliRBM from sklearn.pipeline import Pipeline from sklearn.linear_model import LinearRegression from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error # 定义适应度函数 def fitness_function(params, X_train, y_train, X_test, y_test): dbn = Pipeline(steps=[('rbm', BernoulliRBM(n_components=params['n_components'], learning_rate=params['learning_rate'], n_iter=params['n_iter'], verbose=1)), ('regression', LinearRegression())]) dbn.fit(X_train, y_train) y_pred = dbn.predict(X_test) rmse = np.sqrt(mean_squared_error(y_test, y_pred)) return rmse # 初始化种群 def create_population(pop_size, params_range): population = [] for i in range(pop_size): params = {} for key in params_range: params[key] = np.random.uniform(params_range[key][0], params_range[key][1]) population.append(params) return population # 选择操作 def selection(population, fitness_func): fitness_scores = [fitness_func(individual) for individual in population] total_fitness = sum(fitness_scores) selection_probs = [fitness/total_fitness for fitness in fitness_scores] selected_indices = np.random.choice(len(population), size=len(population), p=selection_probs, replace=True) selected_population = [population[i] for i in selected_indices] return selected_population # 交叉操作 def crossover(parent1, parent2): child = {} for key in parent1: if np.random.random() < 0.5: child[key] = parent1[key] else: child[key] = parent2[key] return child # 变异操作 def mutation(individual, params_range, mutation_rate): for key in params_range: if np.random.random() < mutation_rate: individual[key] = np.random.uniform(params_range[key][0], params_range[key][1]) return individual # GA优化函数 def optimize(params_range, X_train, y_train, X_test, y_test, pop_size=50, n_generations=50, mutation_rate=0.1): population = create_population(pop_size, params_range) for i in range(n_generations): population = selection(population, lambda params: fitness_function(params, X_train, y_train, X_test, y_test)) new_population = [] for j in range(pop_size//2): parent1, parent2 = np.random.choice(population, size=2, replace=False) child1 = crossover(parent1, parent2) child2 = crossover(parent2, parent1) child1 = mutation(child1, params_range, mutation_rate) child2 = mutation(child2, params_range, mutation_rate) new_population.extend([child1, child2]) population = new_population best_individual = min(population, key=lambda params: fitness_function(params, X_train, y_train, X_test, y_test)) return best_individual # 使用最优解进行回归预测 def predict(params, X_train, y_train, X_test): dbn = Pipeline(steps=[('rbm', BernoulliRBM(n_components=params['n_components'], learning_rate=params['learning_rate'], n_iter=params['n_iter'], verbose=1)), ('regression', LinearRegression())]) dbn.fit(X_train, y_train) y_pred = dbn.predict(X_test) return y_pred # 示例 if __name__ == '__main__': # 生成随机数据 X = np.random.rand(1000, 10) y = np.random.rand(1000) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # 定义超参数搜索范围 params_range = {'n_components': [10, 100], 'learning_rate': [0.01, 0.1], 'n_iter': [10, 100]} # 使用遗传算法优化DBN超参数 best_params = optimize(params_range, X_train, y_train, X_test, y_test) # 使用最优解进行预测 y_pred = predict(best_params, X_train, y_train, X_test) rmse = np.sqrt(mean_squared_error(y_test, y_pred)) print('RMSE:', rmse) print('Best params:', best_params) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值