用于执行加法的序列对序列学习的实现
输入:“535 + 61”
输出:“596”
填充通过使用重复的前哨字符(空格)来处理。
在“学习执行”http://arxiv.org/abs/1410.4615和“用神经网络进行序列对序列的学习”http://papers.nips.cc/paper/5346-sequence-to-sequence-learning-with-neural-networks.pdf中,可以选择反向输入,从而提高许多任务的性能。从理论上讲,它引入了源和目标之间的短期依赖关系。
两位数反转:一层LSTM (128 HN), 5k训练示例= 55课时99%的训练/测试准确率
三位数反转:一层LSTM (128 HN), 50k训练示例= 100课时99%的训练/测试准确率
四位数反转:一层LSTM (128 HN), 400k训练示例= 20课时99%的训练/测试准确率
五位数反转:一层LSTM (128 HN), 550k训练示例= 30课时99%的训练/测试准确率
图书馆(keras)图书馆(stringi)#函数定义 ----------------------------------------------------#创建char表并对其排序。learn_encoding<-函数(字符){排序(字符)}#从字符序列编码为一个热整数表示。# > encode("22+22", char_table)# [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12]# 2 0 0 0 0 1 0 0 0 0 0 0 0 0# 2 0 0 0 0 1 0 0 0 0 0 0 0 0# + 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0# 2 0 0 0 0 1 0 0 0 0 0 0 0 0# 2 0 0 0 0 1 0 0 0 0 0 0 0 0编码<-函数(char char_table) {strsplit(字符,"")% > %unlist()% > %酸式焦磷酸钠(函数(x) {as.numeric(x= =char_table)})% > %t()}#解码一个热表示/概率表示#到他们的字符输出。解码<-函数(x, char_table) {应用(x,1,函数(y) {char_table [which.max(y)]})% > %paste0(崩溃="")}返回问题和期望答案的列表。generate_data<-函数(大小、数字反转=真正的) {max_num<-as.integer(paste0(代表(9数字),崩溃=""))#为问题的两边生成整数x<-样本(1:max_num,大小=的大小,取代=真正的)y<-样本(1:max_num,大小=的大小,取代=真正的)#使左边总是比右边小left_side<-ifelse(x< =y, x, y)right_side<-ifelse(x> =y, x, y)结果<-left_side+right_side# pad,右边有空格问题<-paste0(left_side“+”right_side)问题<-stri_pad(问题,宽度=2*数字+1,一边=“正确”,垫=”“)如果(反){问题<-stri_reverse(问题)}# pad,左侧空格结果<-stri_pad(结果,宽度=数字+1,一边=“左”,垫=”“)列表(问题=问题,结果=结果)}#参数 --------------------------------------------------------------#模型和数据集的参数TRAINING_SIZE<-50000数字<-2输入的最大长度是'int + int'(例如,'345+678')。最大长度的# int是数字MAXLEN<-数字+1+数字#所有的数字,加号和空格字符集<-c(0:9,“+”,”“)char_table<-learn_encoding(字符集)#数据准备 --------------------------------------------------------#生成数据例子<-generate_data(大小=TRAINING_SIZE,数字=位数)#向量化x<-数组(0,昏暗的=c(长度(例子$MAXLEN问题),长度(char_table)))y<-数组(0,昏暗的=c(长度(例子$问题),数字+1,长度(char_table)))为(我在1:TRAINING_SIZE) {x (,,)<-编码(例子$问题[我],char_table)y (,,)<-编码(例子$结果[我],char_table)}#洗牌指数<-样本(1:TRAINING_SIZE,大小=TRAINING_SIZE)x<-x(指数、)y<-y(指数、)#显式地将10%留给我们从未进行过训练的验证数据split_at<-trunc(TRAINING_SIZE/10)x_val<-x (1:split_at,)y_val<-y (1:split_at,)x_train<-x [(split_at+1):TRAINING_SIZE,)y_train<-y [(split_at+1):TRAINING_SIZE,)打印(的训练数据:)
#培训 ----------------------------------------------------------------HIDDEN_SIZE<-128BATCH_SIZE<-128层<-1#初始化顺序模型模型<-keras_model_sequential()
模型% > %使用RNN对输入序列进行编码,产生一个HIDDEN_SIZE的输出。#注意:在输入序列长度可变的情况下,#使用input_shape=(None, num_feature)。layer_lstm(HIDDEN_SIZEinput_shape =c(MAXLEN长度(char_table)))% > %#作为解码器RNN的输入,反复提供最后一个隐藏状态# RNN为每个时间步。重复“DIGITS + 1”次数,因为这是最大值#输出长度,例如,当DIGITS=3时,最大输出为999+999=1998。layer_repeat_vector(数字+1)#解码器RNN可以是多层叠加,也可以是单层。#通过将return_sequences设置为True,不仅返回最后的输出,而且返回#到目前为止所有的输出形式为(num_samples, timesteps,# output_dim)。这是必要的,正如timedie分发在以下预期#第一个维度是时间步长。为(我在1:层)模型% > %layer_lstm(HIDDEN_SIZEreturn_sequences =真正的)模型% > %#在输入的每个时间切片上应用致密层。对于每一步#,决定应该选择哪个字符。time_distributed(layer_dense(单位=长度(char_table)))% > %layer_activation(“softmax”)#编译模型模型% > %编译(损失=“categorical_crossentropy”,优化器=“亚当”,指标=“准确性”)#获取模型摘要总结(模型)
模型:“顺序 " ____________________________________________________________________________ 输出层(类型)的形状参数 # ============================================================================ lstm (lstm) (72192, 128) repeat_vector (RepeatVector)(没有,128)0 lstm_1 (lstm)(没有,128)131584 time_distributed (TimeDistribute(没有3 12)1548 d)激活(激活)(没有3 12)0 ============================================================================ 总参数:205324可训练的参数:205324 Non-trainable params: 0 ____________________________________________________________________________
#装置循环模型% > %适合(x =x_train,y =y_train,batch_size =BATCH_SIZE,时代=70,validation_data =列表(x_val y_val))#预测一个新的观察结果new_obs<-编码(“55 + 22”char_table)% > %数组(昏暗的=c(1,5,12))结果<-预测(new_obs模型)结果<-结果(1,,)解码(因此,char_table)