赞
踩
本文主要讲解:使用遗传算法GA-LSTM-优化神经网络神经元个数-dropout-batch_size
主要思路:
需要请私聊,是一个时间序列数据
遗传算法是模拟自然界优胜劣汰法则而出现的一种进化算法,也是一种邻域搜索算法,其核心的思想就是通过不断的在解空间进化,然后通过选择算子选择出适应度高的子代,然后对适应度高的子代进行遗传操作,通过迭代一定的次数或者当个体达到要求的适应度值时即可停止算法。
主要过程
初始化种群 ——自然选择——杂交——遗传、变异——自然选择——再到杂交,循环往复。
主运行程序入口
"""
结合排队模型寻优参数
使得超出时间最小
"""
import copy
import heapq
import math
import random
import matplotlib.pyplot as plt
# 简单实现SGA算法
import numpy as np
import pandas as pd
from keras.layers import Dense, Dropout, LSTM
from keras.layers.core import Activation
from keras.models import Sequential
from scipy.optimize import fsolve
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from tensorflow.keras import Sequential
from tensorflow.python.keras.layers import Dense
from tensorflow.python.keras.layers import Dropout
from tensorflow.python.keras.layers import LSTM
from tensorflow.python.keras.models import Sequential
# 根据解的精度确定染色体(chromosome)的长度
# 需要根据决策变量的上下边界来确定
def getEncodedLength(delta=0.001, boundarylist=[]):
# 每个变量的编码长度
lengths = []
for i in boundarylist:
lower = i[0]
upper = i[1]
# lamnda 代表匿名函数f(x)=0,50代表搜索的初始解
res = fsolve(lambda x: ((upper - lower) * 1 / delta) - 2 ** x + 1, 50)
length = int(np.ceil(res[0]))
lengths.append(length)
return lengths
pass
# 随机生成初始编码种群
def getIntialPopulation(encodelength, populationSize):
# 随机化初始种群为0
chromosomes = np.zeros((populationSize, sum(encodelength)), dtype=np.uint8)
for i in range(populationSize):
chromosomes[i, :] = np.random.randint(0, 2, sum(encodelength))
# print('chromosomes shape:', chromosomes.shape)
return chromosomes
# 染色体解码得到表现型的解
def decodedChromosome(encodelength, chromosomes, boundarylist, delta=0.001):
populations = chromosomes.shape[0]
variables = len(encodelength)
decodedvalues = np.zeros((populations, variables))
for k, chromosome in enumerate(chromosomes):
chromosome = chromosome.tolist()
start = 0
for index, length in enumerate(encodelength):
# 将一个染色体进行拆分,得到染色体片段
power = length - 1
# 解码得到的10进制数字
demical = 0
for i in range(start, length + start):
demical += chromosome[i] * (2 ** power)
power -= 1
lower = boundarylist[index][0]
upper = boundarylist[index][1]
decodedvalue = lower + demical * (upper - lower) / (2 ** length - 1)
decodedvalues[k, index] = decodedvalue
# 开始去下一段染色体的编码
start = length
return decodedvalues
# 得到个体的适应度值及每个个体被选择的累积概率
def getFitnessValue(func, chromosomesdecoded):
# 得到种群规模和决策变量的个数
population, nums = chromosomesdecoded.shape
# 最差的个数及下标
worst = 0
worst_index = np.zeros((worst), dtype=np.uint8)
# 初始化种群的适应度值为0
objvalues = np.zeros((population, 1))
fitnessvalues = np.zeros((population, 1))
# 计算适应度值
low_bound = 3 # 为了扩大范围而减去的天数
for i in range(population):
objvalues[i, 0] = func(chromosomesdecoded[i, :])
if (objvalues[i, 0] < low_bound):
print("\n\n!!!!!!!!!小于%d天了!!!!!!!!!!!\n" % low_bound)
# fitnessvalues[i,0] = 2**(100000/10**(objvalues[i, 0] -low_bound))
fitnessvalues[i, 0] = 1000 / 1.5 ** (objvalues[i, 0])
print('参数{} 适应度{}'.format(chromosomesdecoded[i, :], fitnessvalues[i, 0]))
# 寻找精英
elite_value = np.max(fitnessvalues[:, 0])
elite_index = np.where(fitnessvalues[:, 0] == elite_value)
# 去掉最差的
if worst > 0:
temp = heapq.nsmallest(worst, fitnessvalues)
for i in range(worst):
worst_index = np.where(fitnessvalues == temp[i])
fitnessvalues[worst_index[0][0]] = 0
# 计算每个染色体被选择的概率
probability = fitnessvalues / np.sum(fitnessvalues)
# 得到每个染色体被选中的累积概率
cum_probability = np.cumsum(probability)
return fitnessvalues, cum_probability, elite_index
# 新种群选择
def selectNewPopulation(chromosomes, cum_probability, elite_index):
select_index = []
m, n = chromosomes.shape
newpopulation = np.zeros((m, n), dtype=np.uint8)
# 前elite个染色体是精英
for i in range(1):
newpopulation[i] = chromosomes[elite_index[i][0]]
select_index.append(elite_index[i][0])
count = 1 # 新种群中旧精英的个数
limit = 4 # 新种群中旧精英的最大个数
i = 0
while i < m - 1:
randoma = np.random.rand()
logical = cum_probability >= randoma
index = np.where(logical == 1)
# index是tuple,tuple中元素是ndarray
if count < limit:
newpopulation[i + 1, :] = chromosomes[index[0][0], :]
select_index.append(index[0][0])
i += 1
if index[0][0] in elite_index[0]:
count += 1
elif not (index[0][0] in elite_index[0]):
newpopulation[i + 1, :] = chromosomes[index[0][0], :]
select_index.append(index[0][0])
i += 1
else:
pass
# print('count = ',count)
return newpopulation, select_index
# 新种群交叉
def crossover(population, fitnessvalues):
k1 = 1
k3 = 1
updatepopulation = copy.deepcopy(population)
n_indv, len_indv = population.shape
f_max = np.max(list(fitnessvalues))
f_avg = np.mean(list(fitnessvalues))
cross_index = [x for x in range(n_indv)]
random.shuffle(cross_index)
for i in range(0, n_indv - 1, 2):
f_apo = max([fitnessvalues[cross_index[i]][0], fitnessvalues[cross_index[i + 1]][0]])
if f_apo < f_avg:
Pc = k3
else:
Pc = k1 * (f_max - f_apo) / (f_max - f_avg)
flag = random.random()
# print('Pc=%4f, flag=%4f'%(Pc,flag))
if flag < Pc:
a = cross_index[i]
b = cross_index[i + 1]
# print('%d %d cross'%(a,b))
# 随机产生2个交叉点
crossoverPoint = random.sample(range(1, len_indv), 2)
# 升序排列交叉结点
crossoverPoint = sorted(crossoverPoint)
# 两点交叉
updatepopulation[a, crossoverPoint[0]:crossoverPoint[1]] = population[b,
crossoverPoint[0]:crossoverPoint[1]]
updatepopulation[b, crossoverPoint[0]:crossoverPoint[1]] = population[a,
crossoverPoint[0]:crossoverPoint[1]]
return updatepopulation
# 染色体变异
def mutation(population, fitnessvalues):
"""
:param population: 经交叉后得到的种群
:param Pm: 变异概率默认是0.01
:return: 经变异操作后的新种群
"""
k2 = 0.5
k4 = 0.5
updatepopulation = copy.deepcopy(population)
n_indv, len_indv = population.shape
f_max = np.max(list(fitnessvalues))
f_avg = np.mean(list(fitnessvalues))
f_min = np.min(list(fitnessvalues))
for i in range(n_indv):
if fitnessvalues[i][0] < f_avg:
Pm = k2
else:
Pm = k4 * (f_max - fitnessvalues[i][0]) / (f_max - f_avg)
# 计算需要变异的基因个数
gene_num = int(round(len_indv * (f_max - fitnessvalues[i][0]) / (f_max - f_min) / 3))
flag = random.random()
# print('Pm=%4f, flag=%4f'%(Pm,flag))
if flag < Pm:
# print('%d mutation'%i)
# 随机抽取gene_num个基因进行基本位变异
mutationGeneIndex = random.sample(range(0, len_indv), gene_num)
# 确定每个将要变异的基因在整个染色体中的基因座(即基因的具体位置)
for gene in mutationGeneIndex:
# 确定变异基因位于当前染色体的第几个基因位
# mutation
if updatepopulation[i, gene] == 0:
updatepopulation[i, gene] = 1
else:
updatepopulation[i, gene] = 0
return updatepopulation
# 定义目标函数
def objFunc():
return lambda x: 21.5 + x[0] * np.sin(4 * np.pi * x[0]) + x[1] * np.sin(20 * np.pi * x[1])
batch_size = 128
epochs = 2
steps = 10
scalerx = StandardScaler()
scalery = StandardScaler()
def create_dataset(X, y, seq_len):
features = []
targets = [] # 标签
for i in range(0, len(X) - seq_len, 1): # 此处的1表示步长,每隔一步滑一下
data = X.iloc[i:i + seq_len] # 序列数据;前闭后开
label = y.iloc[i + seq_len] # 标签数据
# 保存到features和labels
features.append(data)
targets.append(label)
trainX = np.array(features).astype('float64')
return trainX, np.array(targets).reshape(-1, 1)
def process_data():
# usecols 代表使用数据的列索引,左闭右开
dataset = pd.read_csv("data5.csv", engine='python', parse_dates=['date'], usecols=range(1, 9), index_col=['date'])
columns = ['Y', 'X1', 'X2', 'X3', 'X4', 'X5', 'X6']
# 对X进行标准化
for col in columns[1:]:
dataset[col] = scalerx.fit_transform(dataset[col].values.reshape(-1, 1))
# 对Y进行标准化
for col in columns[:1]:
dataset[col] = scalery.fit_transform(dataset[col].values.reshape(-1, 1))
X = dataset.drop(columns=['Y'], axis=1)
y = dataset['Y']
# test_size代表划分20%到测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False, random_state=666)
return X_train, y_train, X_test, y_test
X_train, y_train, X_test, y_test = process_data()
X_train, y_train = create_dataset(X_train, y_train, steps)
X_test, y_test = create_dataset(X_test, y_test, steps)
# 建立模型
def build_model(neurons1, neurons2, dropout):
nb_features = X_train.shape[2]
input1 = X_train.shape[1]
model1 = Sequential()
model1.add(LSTM(
input_shape=(input1, nb_features),
units=neurons1,
return_sequences=True))
model1.add(Dropout(dropout))
model1.add(LSTM(
units=neurons2,
return_sequences=False))
model1.add(Dropout(dropout))
model1.add(Dense(units=1))
model1.add(Activation("linear"))
model1.compile(loss='mse', optimizer='Adam', metrics='mae')
return model1, X_train, y_train, X_test, y_test
# def main(max_iter=300):
if __name__ == '__main__':
max_iter = 80
popSize = 10
# 每次迭代得到的最优解
optimalSolutions = []
optimalValues = [] # 最优目标函数值
optimalFitness = [] # 最优适应度值
avgFitness = [] # 平均适应度值
# 决策变量的取值范围
'''
神经网络第一层神经元个数
神经网络第二层神经元个数
dropout比率
batch_size
'''
decisionVariables = [[50, 150], [5, 15], [0.05, 0.5], [8, 16]]
# 得到染色体编码长度
lengthEncode = getEncodedLength(boundarylist=decisionVariables)
# 得到初始种群编码
chromosomesEncoded = getIntialPopulation(lengthEncode, popSize)
fitnessvalues = np.zeros((popSize, 1))
print('初始化\n', chromosomesEncoded)
# print('累计概率\n',cum_proba)
for iteration in range(max_iter):
# 种群解码
decoded = decodedChromosome(lengthEncode, chromosomesEncoded, decisionVariables)
# 得到个体适应度值和个体的累积概率
fitnessvalues_before, cum_proba, elite_index = getFitnessValue(objFunc(), decoded)
print('elite ', elite_index)
# 选择新的种群
newpopulations, select_index = selectNewPopulation(chromosomesEncoded, cum_proba, elite_index)
for i, value in enumerate(select_index):
fitnessvalues[i] = fitnessvalues_before[value]
# 交叉
crossoverpopulation = crossover(newpopulations, fitnessvalues)
# print('交叉')
# 变异
mutationpopulation = mutation(crossoverpopulation, fitnessvalues)
# print('变异')
# 将变异后的种群解码,得到每轮迭代最终的种群
final_decoded = decodedChromosome(lengthEncode, mutationpopulation, decisionVariables)
# 适应度评价
# fitnessvalues, cum_individual_proba,elite_index = getFitnessValue(objFunc(), final_decoded)
# print('适应度')
# 搜索每次迭代的最大适应度值
optimalFitness.append(np.max(list(fitnessvalues)))
# 反求最优(最小)目标函数值
# optimalValues.append(math.log10((100000/math.log2(optimalFitness[-1])))+3)
optimalValues.append(math.log(1000 / optimalFitness[-1], 1.5))
print('%d iter, best value: %4f' % (iteration, optimalValues[-1]))
# 平均适应度值
avgFitness.append(np.mean(list(fitnessvalues)))
# 最优解
index = np.where(fitnessvalues == max(list(fitnessvalues)))
optimalSolutions.append(final_decoded[index[0][0], :])
# update
chromosomesEncoded = mutationpopulation
# cum_proba = cum_individual_proba
# 搜索最优解
optimalValue = np.min(optimalValues)
optimalIndex = np.where(optimalValues == optimalValue)
optimalSolution = optimalSolutions[optimalIndex[0][0]]
plt.figure(1)
plt.xlabel('generation')
plt.ylabel('fitness')
plt.plot(optimalValues)
## 测量运行时间
# elapsedtime = timeit.timeit(stmt=main, number=1)
# print('Searching Time Elapsed:(S)', elapsedtime)
如有问题请私聊,多谢合作
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。