手把手教你自制编程AI:训练2小时,RNN就能写自己的代码

栏目: 编程工具 · 发布时间: 6年前

内容简介:手把手教你自制编程AI:训练2小时,RNN就能写自己的代码

手把手教你自制编程AI:训练2小时,RNN就能写自己的代码

我们都知道,神经网络下围棋能赢柯洁、读X光照片好过医生、就连文本翻译上也快超过人类了……其实在写代码方面,神经网络也丝毫不落下风……用 Linux 源代码训练2小时, 一个递归神经网络就能重写好它自己的代码,这是不是比 程序员 学得还快?

接下来的文章,AI开发者Thibault Neveu就要手把手教你做一个这样的神经网络。

作者 |  Thibault Neveu

编译 | AI100

认这很疯狂。 开发者让神经网络学会了自己编程来重写它自己代码!好吧,咱们也试。

预备条件

  1. Tensorflow + 基 本的深度学习 技能

  2. 该项目的github代码 库 –  https://github.com/thibo73800/deep_generation/tree/master/c_code

  3. 我会在本文中快速回顾一下递归神经网络。但是,如果你对这个课题不甚了解,我相信以下两个资源能让你弄懂递归神经网络:

视频 –  https://www.youtube.com/watch?v=iX5V1WpxxkY&t=2652s

文章 –  http://colah.github.io/posts/2015-08-Understanding-LSTMs/

我不会在本文中详解本项目的所有环节。但我会仔细阐述其中的基本要点来让你理解整个项目。花点时间,亲手运行下文中给出的每一段代码,理解其中的逻辑。这很重要,毕竟,实践出真知。

接下来是正题,让我们开始吧!

数据库

跟其他监督训练一样,我们需要为神经网络提供一个数据集。这里我们使用C语言(如果用太简单的语言,就不好玩了)。我们直接用Linux github代码库中的 c语言 脚本作为训练数据。我已经把我们会用到的.c代码提取到本 项目中

代码地址- https://github .com/thibo73800/deep_generation/tree/master/c_code/dataset

首要问题:如何表示数据?

神经网络只能用于处理数字。对于其他形式的数据,它就无能为力了。因此,数据集中的每个字符都需要被翻译成这种形式(每个数字对应一个字符)。

手把手教你自制编程AI:训练2小时,RNN就能写自己的代码

示例:把字符转换为整数(int)

举例来说,这里用数字7表示字符“=”。为了在反向传播期间获得更好的收敛性,我们稍后会在独热编码(One-Hot Encoding)编码中表示每个数字。

# List all file in the dataset directory

all_file = os.listdir(“dataset”)

# Filter : Select only c file

all_file_name = np.array([f for f in all_file if f.find(“.c”) != -1])

content = “”

for name in all_file_name:

with open(os.path.join(“dataset”, name), “r”) as f:

content += f.read() + “n”

# Convert the string into a list of interger

vocab = set(content)

vocab_to_int = {c: i for i, c in enumerate(vocab)}

int_to_vocab = dict(enumerate(vocab))

encoded = np.array([vocab_to_int[c] for c in content], dtype=np.int32)

这里,需要记住的三个重要变量是:vocab_to_int、int_to_vocab和encoded。前两个变量是让我们能够字符和整数间随意转换。最后的变量是用编码器的形式来表示所有数据。(均已转换为数字)

第一个批函数

首先创建一个简单的批处理:由两个输入序列构成,每个序列10个数字。这一批处理将作为下文字符处理的一个示例。

batch = {

“x” : [

encoded[:10],

encoded[20:30]

],

“y” : [

encoded[1:11],

encoded[21:31]

]

}

Batch Inputs : 

[20  6 58 27  6 27 97 86 56 49]

[ 36  32  32  37  27  12  94  60  89 101]

Batch Targets : 

[ 6 58 27  6 27 97 86 56 49 57]

[ 32  32  37  27  12  94  60  89 101  77]

这就是批函数所处理的内容,翻译成字符如下:

['/', '*', 'n', ' ', '*', ' ', 'C', 'o', 'p', 'y']

['2', '0', '0', '4', ' ', 'E', 'v', 'g', 'e', 'n']

现在,我们需要来处理一些数值。我们希望神经网络能够在上一个字符”n”已知的条件下预测出下一个字符。而且,不只是上一个字符。如果我告诉神经网络上一个字符是“e” ,下一个字符的可能性空间会非常大。但如果我能告诉神经网络前几个字符分别是 “w” 、“h”、 “i” 、“l” 和 “e” ,下一个要输入的字符很显然就是“(“。

因此,我们必须构建一个能够考虑字符时间间隔的神经网络。这就是递归神经网络。

递归神经网络?

手把手教你自制编程AI:训练2小时,RNN就能写自己的代码

为说明上述实例,我们用一个典型的分类器(上图左侧)来处理上一个字符;它被传递出蓝色的隐含层后,分类器就能推断出结果。递归神经网络在结构上则不同。每个红色的隐含层“细胞”不仅与输入相连,还与前一个“ 细胞 ”(instant t-1)相连。为了解决这里的问题,我们的“ 细胞 ”内部使用长短期记忆(LSTM)网络。

请花点时间来理解递归神经网络的原理,这样才能充分理解接下来的代码。

构建模型!

手把手教你自制编程AI:训练2小时,RNN就能写自己的代码

Tensorboard图

接下来的内容,我们将详述这一神经网络的5大部分。占位符在这里用作模型的一个入口。LSTM 神经元 初始化后用于生成递归神经网络。

输出层各自相连,用于估量模型的误差。最后,我们会定义训练内容。

1)图形输入

with tf.name_scope(“graph_inputs”):

inputs = tf.placeholder(tf.int32, [2, 10], name='placeholder_inputs')

targets = tf.placeholder(tf.int32, [2, 10], name='placeholder_targets')

keep_prob = tf.placeholder(tf.float32, name='placeholder_keep_prob')

这个批处理由两个大小为10的输入序列构成,因此输入的预期特征是[2, 10],批处理的每个入口都与单一输出相关联,目标的特征定义与此相同。最后,我们定义了一个用作概率值的占位符,用以表示后面的退出率(dropout)。

2)LSTM

with tf.name_scope(“LSTM”):

def create_cell():

lstm = tf.contrib.rnn.BasicLSTMCell(4)

drop = tf.contrib.rnn.DropoutWrapper(lstm, output_keep_prob=keep_prob)

return drop

cell = tf.contrib.rnn.MultiRNNCell([create_cell() for _ in range(3)])

initial_state = cell.zero_state(2, tf.float32)

io_size = len(vocab)

x_one_hot = tf.one_hot(inputs, io_size)

cell_outputs, final_state = tf.nn.dynamic_rnn(cell, x_one_hot, initial_state=initial_state)

让我们来学习这份代码的每一部分:

  • create_cell() 用于生成由4个隐神经元所构成的LSTM 神经元 。在返回结果前,该函数还在cell输出中添加了一个退出项(dropout)。

  • tf.contrib.rnn.MultiRNNCell用于实例化递归神经网络。我们把给出的create_cell()数组作为参数,是因为我们希望得到由多层网络构成的递归神经网络。本例为三层。

  • initial_state:已知递归神经网络的每个 神经元 都依赖于先前的状态,因此我们必须实例化一个全是零的初始状态,它将作为批处理首批入口的输入。

  • x_one_hot将batch转化为独热编码。

  • cell_outputs给出递归神经网络每个细胞的输出。在本例中,每个输出由4个数值(隐神经元个数)构成。

  • final_state返回最后一个细胞的状态,在训练期间可用作下一批处理的最新初始状态(假设下一个批处理是上一个批处理的逻辑延续)。

3)图形输出

with tf.name_scope(“graph_outputs”):

seq_output_reshape = tf.reshape(cell_outputs, [-1, 4], name=”reshape_x”)

with tf.name_scope('output_layer'):

w = tf.Variable(tf.truncated_normal((4, io_size), stddev=0.1), name=”weights”)

b = tf.Variable(tf.zeros(io_size), name=”bias”)

logits = tf.add(tf.matmul(seq_output_reshape , w), b, name= “logits”)

softmax = tf.nn.softmax(logits, name='predictions')

细胞的输出值被储存在一个三维特征表内[序列数,序列大小,神经元数],或为 [2, 10, 4]。我们无需按序列来分离输出。然后,改变输出值的维度以储存在seq_out_reshape的数组[20, 4]内。

最后,使用一个简单的线性运算:tf.matmul (..) + b。最后以softmax结尾,为的是用概率形式来表示输出。

4)损失

with tf.name_scope(“Loss”):

y_one_hot = tf.one_hot(targets, io_size, name=”y_to_one_hot”)

y_reshaped = tf.reshape(y_one_hot, logits.get_shape(), name=”reshape_one_hot”)

loss = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_reshaped)

loss = tf.reduce_mean(loss)

为进行误差运算,我们的批处理目标必须要表示成跟模型输出值相同的方法和维度。使用与输入相同的编码方式,我们用tf.one_hot来表示输出值。然后将数组tf.reshape ()的维度重写为与tf.matmul (..) + b的线性输出一样。而后,我们就可以用该函数来计算模型的误差。

5)训练

with tf.name_scope(“train”):

adam = tf.train.AdamOptimizer(0.0001)

optimizer = adam.minimize(loss)

我们简单用AdamOptimize来最小化误差。

结果!

这是最值得庆祝的环节:训练结果。我所用到的参数如下:

  • 序列大小:100 

  • 批处理大小:200 

  • 每个细胞的神经元数: 512 

  • 递归神经网络深度:2 

  • 学习速度:0.0005 

  • Dropout:0.5

在我的GPU(GeForce GTX 1060)上训练大约两小时后,所得结果如下图所示:

我们先来观察误差的变化:

手把手教你自制编程AI:训练2小时,RNN就能写自己的代码

最后,我们来阅读模型所生成的代码:

static int super_fold(struct mddev *mddev, void __user * *rd)

{

struct md_rdev *rdev;

if (!tryet &  gcov_ntreef(*stint)) {

if (gc_th->max_sectors)

if (task)

goto next_start;

if (!list_empty(&mddev->disks) {

if (mddev->dev_sectors == 0 ||

mddev->chunk_sectors == 0 && mddev->minor_version !=

mddev->max_disks && mddev->dev_sectors

rdev2->rescan_recovnr != 0)

rdev->recovery_offset = mddev->curr_resync_completed;

}

从结果上看,模型清楚地理解了该程序的一般结构,非常酷:一个函数、参数、变量初始化……条件,等等。

我们注意到,所用数据集中绝对没有那个名为“super_fold”的函数。因此,我很难理解这个函数的具体作用,一个较为合理的解释,是该模型要比我聪明……天哪!!

原文地址:

https://becominghuman.ai/how-to-train-a-neural-network-to-code-by-itself-a432e8a120df

XGBboost已火热开课,已经参加过课程的同学反馈良好, 不过 还可以继续报名哦 ~~

手把手教你自制编程AI:训练2小时,RNN就能写自己的代码

AI100学院特请在机器学习领域深耕10余年的中科院副教授冒老师带来干货课程——《XGBoost从基础到实战》,从XGBoost的 原理 讲解到 代码实战 ,一步步带领大家从XGBoost的安装到一行行 Python 代码实现各类算法任务, 不需要有很强的数学基础,直接从实战入手 。通过4节XGBoost的专题课程,大家可以零基础理解XGBoost原理,掌握XGBoost调参,并能融会贯通地学习其他机器学习算法,学习如何用机器学习算法解决实际问题。如果你足够优秀,还能进击Kaggle竞赛哦。

手把手教你自制编程AI:训练2小时,RNN就能写自己的代码

手把手教你自制编程AI:训练2小时,RNN就能写自己的代码    点击下方“阅读原文”查看更多内容。

[广告]赞助链接: 舆情监测,互联网舆情首选查舆情:http://www.chayuqing.com/ 四季很好,只要有你,文娱排行榜:http://www.yaopaiming.com/

关注公众号:Mcbang_com 了解更多精彩,关注:chayuqing_com 娱乐资讯早知道!


以上所述就是小编给大家介绍的《手把手教你自制编程AI:训练2小时,RNN就能写自己的代码》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Open Data Structures

Open Data Structures

Pat Morin / AU Press / 2013-6 / USD 29.66

Offered as an introduction to the field of data structures and algorithms, Open Data Structures covers the implementation and analysis of data structures for sequences (lists), queues, priority queues......一起来看看 《Open Data Structures》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

MD5 加密
MD5 加密

MD5 加密工具