自动机器学习:利用遗传算法优化递归神经网络

最近,在自动机器学习方面有很多工作,从选择合适的算法到特征选择和超参数调优。有几种可用的工具(例如:AutoML和TPOT),可以帮助用户高效地执行数百个实验。同样,深层神经网络结构通常由专家设计;通过试验和错误的方法。通过这种方法,在几个领域研发出了最先进的模型,但是这种方法非常耗时。最近,由于可用计算能力的增加,研究人员正在使用强化学习和进化算法来自动化搜索最优的神经结构。

在本文中,我们将学习如何应用遗传算法(GA)来寻找一个最优的窗口大小和一些基于递归神经网络(RNN)的长短期记忆(LSTM)单元。为此,我们将使用Keras来训练和评估时间序列预测问题的模型。对于遗传算法,将使用名为DEAP的python包。本文的主要目的是让读者熟悉遗传算法,以找到最优设置;因此,本文只研究两个参数。此外,本文假定读者对RNN有所认识(理论和应用)。

  • DEAP地址:https://github.com/DEAP/deap

具有完整代码的ipython netbook可以在以下链接中找到。

  • 代码地址:https://github.com/aqibsaeed/Genetic-Algorithm-RNN

遗传算法

遗传算法是一种启发式搜索,是一种基于自然选择过程的优化方法。它们被广泛应用于在较大的参数空间寻找近似最优解的优化问题。物种进化的过程(例子中的解决方法)是模仿的,依赖于生物启发的部分,例如交叉。此外,由于它不考虑辅助信息(例如导数),它可以用于离散和连续优化。

对于遗传算法,必须满足两个先决条件,a)解决方案表示或定义一个染色体,b)适应度函数来评估产生的解决方案。在我们的例子中,二进制数组是解决方案的遗传表示(参见图1),模型在验证集上的均方根误差(RMSE)将成为一个适应度值。此外,构成遗传算法的三种基本操作如下:

1. 选择:它定义了为进一步的复制而保留的解决方案。例如赌轮选择。

2. 交叉:它描述了如何从现有的解决方案创建新的解决方案。例如n点交叉。

3. 突变:它的目的是通过随机交换或关闭解决方案,将多样性和新奇性引入到解决方案池(solution pool)中。例如二进制突变。

图1

有时,一种被称为“Elitism”的技术也被使用,它只保留少数最好的解决方案,并传递给下一代。图2描述了一个完整的遗传算法,其中,初始解(种群)是随机生成的。接下来,根据适应度函数和选择进行评估,然后进行交叉和变异。这个过程重复定义迭代的次数中重复。最后,选择一个具有最高适应度分数的解决方案作为最佳解决方案。

图2

实现

现在,我们对遗传算法是什么以及它如何工作有一个很好的理解。接下来,让我们开始编码。

我们将使用风力发电预测数据。它由7个风力发电场的标准(0-1)风能度量组成。为了简单起见,我们将使用第一个风力发电场(名为wp1),但我鼓励读者尝试并扩展代码,以预测所有7个风力发电场的能源。

  • 风能预测数据地址:https://www.kaggle.com/c/GEF2012-wind-forecasting/data

导入所需的包,加载数据集并定义两个辅助函数。第一个方法prepare_dataset将数据分割成块,为模型训练创建XY对。X是过去(例1到t-1)的风电价值(wind power value),Y将在t时刻为未来值(future value)。第二种方法train_evaluate执行三件事,1)解码遗传算法解决方案以获得窗口大小和单元数。2)使用GA找到的窗口大小来准备数据集,并将其划分为训练和验证集,3)训练LSTM模型,在验证集上计算RMSE,并返回该值将其作为当前遗传算法解决方案的适应度值。

import numpy as np
import pandas as pd
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split as split

from keras.layers import LSTM, Input, Dense
from keras.models import Model

from deap import base, creator, tools, algorithms
from scipy.stats import bernoulli
from bitstring import BitArray

np.random.seed(1120)
data = pd.read_csv('train.csv')
data = np.reshape(np.array(data['wp1']),(len(data['wp1']),1))

# Use first 17,257 points as training/validation and rest of the 1500 points 
as test set.
train_data = data[0:17257]
test_data = data[17257:]
def prepare_dataset(data, window_size):
    X, Y = np.empty((0,window_size)), np.empty((0))
    for i in range(len(data)-window_size-1):
        X = np.vstack([X,data[i:(i + window_size),0]])
        Y = np.append(Y,data[i + window_size,0])   
    X = np.reshape(X,(len(X),window_size,1))
    Y = np.reshape(Y,(len(Y),1))
    return X, Y

def train_evaluate(ga_individual_solution):   
    # Decode GA solution to integer for window_size and num_units
    window_size_bits = BitArray(ga_individual_solution[0:6])
    num_units_bits = BitArray(ga_individual_solution[6:]) 
    window_size = window_size_bits.uint
    num_units = num_units_bits.uint
    print('\nWindow Size: ', window_size, ', Num of Units: ', num_units)
    
    # Return fitness score of 100 if window_size or num_unit is zero
    if window_size == 0 or num_units == 0:
        return 100, 
    
    # Segment the train_data based on new window_size; split into train and 
validation (80/20)
    X,Y = prepare_dataset(train_data,window_size)
    X_train, X_val, y_train, y_val = split(X, Y, test_size = 0.20, 
random_state = 1120)
    
    # Train LSTM model and predict on validation set
    inputs = Input(shape=(window_size,1))
    x = LSTM(num_units, input_shape=(window_size,1))(inputs)
    predictions = Dense(1, activation='linear')(x)
    model = Model(inputs=inputs, outputs=predictions)
    model.compile(optimizer='adam',loss='mean_squared_error')
    model.fit(X_train, y_train, epochs=5, batch_size=10,shuffle=True)
    y_pred = model.predict(X_val)
    
    # Calculate the RMSE score as fitness score for GA
    rmse = np.sqrt(mean_squared_error(y_val, y_pred))
    print('Validation RMSE: ', rmse,'\n')
    
    return rmse,

接下来,使用DEAP包来定义运行遗传算法的东西。对于长度为10的解,我们将使用二进制表示。它将使用伯努利分布随机初始化。同样,使用了有序交叉、随机突变和赌轮选择。遗传算法参数值被任意初始化;我建议你在不同的设置下尝试。

population_size = 4
num_generations = 4
gene_length = 10

# As we are trying to minimize the RMSE score, that's why using -1.0. 
# In case, when you want to maximize accuracy for instance, use 1.0
creator.create('FitnessMax', base.Fitness, weights = (-1.0,))
creator.create('Individual', list , fitness = creator.FitnessMax)

toolbox = base.Toolbox()
toolbox.register('binary', bernoulli.rvs, 0.5)
toolbox.register('individual', tools.initRepeat, creator.Individual, toolbox.
binary, 
n = gene_length)
toolbox.register('population', tools.initRepeat, list , toolbox.individual)

toolbox.register('mate', tools.cxOrdered)
toolbox.register('mutate', tools.mutShuffleIndexes, indpb = 0.6)
toolbox.register('select', tools.selRoulette)
toolbox.register('evaluate', train_evaluate)

population = toolbox.population(n = population_size)
r = algorithms.eaSimple(population, toolbox, cxpb = 0.4, mutpb = 0.1, 
ngen = num_generations, verbose = False)

通过使用 tools.selBest(population,k = 1),可以很容易地通过遗传算法找到的K最佳解决方案。之后,最优配置可以用来训练完整的训练集,并在holdout测试集上进行测试。

# Print top N solutions - (1st only, for now)
best_individuals = tools.selBest(population,k = 1)
best_window_size = None
best_num_units = None

for bi in best_individuals:
    window_size_bits = BitArray(bi[0:6])
    num_units_bits = BitArray(bi[6:]) 
    best_window_size = window_size_bits.uint
    best_num_units = num_units_bits.uint
    print('\nWindow Size: ', best_window_size, ', Num of Units: ', 
best_num_units)
# Train the model using best configuration on complete training set 
#and make predictions on the test set
X_train,y_train = prepare_dataset(train_data,best_window_size)
X_test, y_test = prepare_dataset(test_data,best_window_size)

inputs = Input(shape=(best_window_size,1))
x = LSTM(best_num_units, input_shape=(best_window_size,1))(inputs)
predictions = Dense(1, activation='linear')(x)
model = Model(inputs = inputs, outputs = predictions)
model.compile(optimizer='adam',loss='mean_squared_error')
model.fit(X_train, y_train, epochs=5, batch_size=10,shuffle=True)
y_pred = model.predict(X_test)

rmse = np.sqrt(mean_squared_error(y_test, y_pred))
print('Test RMSE: ', rmse)

在本文中,我们了解了如何使用遗传算法自动找到最佳窗口大小以及在RNN中使用的一些单元。为了进一步学习,我建议尝试使用不同的遗传算法参数配置,扩展遗传表达式,以包含更多的参数。

本文分享自微信公众号 - ATYUN订阅号(atyun_com)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-01-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏CSDN技术头条

一文读懂数据科学、机器学习和AI的区别

当我跟别人介绍自己是一名数据科学家时,别人总会问我“数据科学与机器学习之间有什么区别?”或者“那你从事的工作一定是跟人工智能有关吧?”关于这些问题我已经回答过了...

23880
来自专栏CSDN技术头条

看机器学习如何还原图像色彩

k-means是机器学习中最著名、最广泛使用的算法之一。在这篇文章中,将使用k-means算法来减少图像上的颜色(但不减少像素),从而也减少了图像的大小。在这个...

25390
来自专栏CSDN技术头条

用最通俗易懂的方式打开机器学习!

在一个风和日丽的周末...... ? ? ? ? ? ? ? 故事一:瑞雪兆丰年 我们中国有一句关于农业生产的古老谚语:瑞雪兆丰年。就是说,如果前一年冬天下雪...

23460
来自专栏web前端教室

我理解与实施的学习前端的路径

随着微信小程序的出现,前端的知识愈加的碎片化。没有哪个知识能够搞定一切。 在很久以前我可以说,你会做静态页面html就可以啦,那年月都用table表格做页面。后...

19080
来自专栏向治洪

深度神经网络中的对抗样本与学习

概述 最近 大半年,人工智能领域成为科技领域提到的最多的名词之一。在kdnuggets此前发布的文章(Deep Learning’s Deep Flaws)’s...

37870
来自专栏CSDN技术头条

8个深度学习方面的最佳实践

【摘要】本文介绍了作者在深度学习的课程中学到的八个非常有用的技巧。以下是译文。 我很开心自己在过去的2017年中在人工智能领域获得的成就。我也学了不少数学方面的...

27580
来自专栏小灰灰

JDK容器学习之Queue: PriorityQueue

优先级队列 PriorityQueue 单端队列,队列中的元素有优先级的顺序 ? 1. 底层数据结构 // 存储队列元素的数组 transient Object...

24850
来自专栏小灰灰

Java学习之深拷贝浅拷贝及对象拷贝的两种方式

I. Java之Clone 0. 背景 对象拷贝,是一个非常基础的内容了,为什么会单独的把这个领出来讲解,主要是先前遇到了一个非常有意思的场景 有一个任务,需要...

50390
来自专栏web前端教室

农历2016年最后一次先行者群视频

今天是周日,也是农历2016年最后一次先行者群视频课程,然后就是春节了,提前祝大家春节快乐。下次课程就要在2月才开始。 ? 如上图,从2016年二三月吧,开始到...

20470
来自专栏web前端教室

知识碎片化对前端学习体系化的损害

你我都身处信息大爆炸的时代,这是一个伟大的时代。 自秦一统天下以来,2000余年从未有普通人能像我们这代人一样,能够这样随心所欲的接触我们想要接触的任何知识。 ...

23070

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励