使用 RNN 求解基本数学方程 [附编码示例]

已发表: 2020-12-07

如果生活给了你RNN,做一个计算器

循环神经网络是经典的人工神经网络之一,其中节点之间的连接形成顺序有向图。 RNN 因其用于处理可变长度序列的内部状态存储器而以语音识别、手写识别等应用而闻名。

RNN 进一步分为两种类型。 第一个是有限脉冲,其神经网络采用有向无环图的形式,其中一个节点可以与一个或多个在网络中没有可见循环的领先节点连接。 另一种是无限脉冲,其神经网络采用有向循环图的形式,不能展开为前馈神经网络。

目录

我们该怎么办?

让我们建立一个模型来预测算术表达式的输出。 例如,如果我输入“11+88”,那么模型应该将序列中的下一个单词预测为“99”。 输入和输出是一个字符序列,因为 RNN 处理的是顺序数据。

与数据集收集相比,现在设计模型的架构看起来像是一项简单的任务。 生成数据或收集数据集是一项艰巨的任务,因为数据饥饿 AI 模型需要大量数据才能达到可接受的准确性。

所以这个模型可以通过6个基本步骤来实现:

  1. 生成数据
  2. 建立模型
  3. 向量化和去向量化数据
  4. 制作数据集
  5. 训练模型
  6. 测试模型

在我们深入实施模型之前,让我们导入所有必需的库。

numpy导入np

将张量导入tf

tensorflow.keras.models导入顺序

tensorflow.keras.layers导入Dense、Dropout、SimpleRNN、RepeatVector、TimeDistributed

tensorflow.keras.callbacks导入EarlyStopping,LambdaCallback

termcolor导入有色

1. 生成数据

让我们定义一个 char 字符串,其中包含编写基本算术方程所需的所有字符。 因此,字符串由 0-9 的所有字符和所有算术运算符组成,例如 /、*、+、-、.(十进制)。

我们不能直接将数值数据输入到我们的模型中,我们需要以张量的形式传递数据。 将数据中的字符串转换为 one-hot 编码向量将为我们提供优化的模型性能。 one-hot 编码向量是一个长度与我们的 char 字符串长度相同的数组,每个 one-hot 向量仅在每个字符串中存在的相应字符索引处具有一个。

例如,假设我们的字符串是 '0123456789',如果我们想编码一个像 '12' 这样的字符串,那么 one-hot 向量将是 [ [0,1,0,0,0,0,0,0 ,0,0],[0,0,1,0,0,0,0,0,0,0] ]。 为此,我们需要创建两个字典,其中一个索引作为键,字符作为值,另一个作为反之亦然。

char_string = ' 0123456789/*+-. '

num_chars = len (char_string)

character_to_index = dict ((c, i) for i, c in enumerate (char_string))

index_to_character = dict ((i, c) for i, c in enumerate (char_string))

现在让我们编写一个函数,该函数返回一个随机算术方程以及该方程的结果。

def除法(n,d):

如果d != 0返回n / d否则0

定义数据生成():

random1 = np.random.randint(低= 0 ,高= 100

random2 = np.random.randint(low = 0 ,high = 100 )

op = np.random.randint(低= 0 ,高= 4

如果op == 1

arith = str (random1) + ' + ' + str (random2)

res = str (random1 + random2)

elif op == 1

arith = str (random1) + ' ' + str (random2)

res = str (random1 random2)

elif op == 2

arith = str (random1) + ' * ' + str (random2)

res = str (random1 * random2)

否则

arith = str (random1) + ' / ' + str (random2)

res = str ( round (division(random1, random2), 2 ))

返回arith, res

另请阅读:有趣的神经网络项目想法

2. 建立模型

该模型将有一个编码器和一个解码器。 编码器是一个简单的 RNN 模型,输入形状为 (None,num_chars) 和 128 个隐藏单元,我们选择隐藏单元为 32、64、128 等的原因是因为 CPU 或 GPU 以隐藏单元为幂的性能更好2.

我们的编码器将是一个完全连接的网络,这些网络的输出将反馈到网络中,这就是 RNN 的工作方式。 RNN 层默认使用“tanh”激活,我们不会更改,因为它最适合编码器。 该层的输出将是单个向量,为了获得整个输出的单个向量,我们将使用带有所需次数的 RepeatVector() 层作为参数。

现在输出向量将具有给定输入的本质,并且该向量将被馈送到解码器。

解码器由一个简单的 RNN 层组成,这将生成输出序列,因为我们需要 RNN 层返回预测的序列,我们将把“return_sequences”标记为 True。 通过将“return_sequences”指定为 True,RNN 层将返回每个时间步的预测序列(多对多 RNN)。

该 RNN 层的输出被馈送到具有“num_chars”个隐藏单元的 Dense 层,我们将使用 softmax 激活,因为我们需要每个字符的概率。 在我们部署一个 Dense 层之前,我们需要将该层缩减为一个 TimeDistributed 层,因为我们需要部署 Dense 层用于每个时间步的输出。

hidden_​​units = 128

max_time_steps = 5 #我们将输出硬编码为 5 个字符

定义模型():

模型=顺序()

model.add(SimpleRNN(hidden_​​units, input_shape = ( None , num_chars)))

model.add(RepeatVector(max_time_steps))

model.add(SimpleRNN(hidden_​​units, return_sequences = True ))

model.add(TimeDistributed(Dense(num_chars,activation = ' softmax ' )))

返回模型

模型=模型()

模型.summary()

model.compile(损失= '分类交叉熵' ,优化器= '亚当' ,指标= [ '准确性' ])

模型的架构将如上图所示

必读:神经网络教程

3. 向量化和去向量化数据

让我们定义用于向量化和去向量化数据的函数。

这是将算术表达式和结果一起向量化的函数。

def向量化(arith, res):

x = np.zeros((max_time_steps, num_chars))

y = np.zeros((max_time_steps, num_chars))

x_remaining = max_time_steps len (arith)

y_remaining = max_time_steps len (res)

对于i, c in enumerate (arith):

x[x_remaining + i, character_to_index[c]] = 1

对于范围内i (x_remaining):

x[i, character_to_index[ ' 0 ' ]] = 1

对于i, c in enumerate (res):

y[y_remaining + i, character_to_index[c]] = 1

对于范围内(y_remaining):

y[i, character_to_index[ ' 0 ' ]] = 1

返回x, y

同样,这里是对字符串进行去矢量化的函数。 由于我们收到的输出是一个概率向量,我们将使用 np.argmax() 来选择概率最高的字符。 现在 index_to_character 字典用于追溯该索引处的字符。

def去矢量化(输入):

res = [index_to_character[np.argmax(vec)] for i, vec in enumerate ( input )]

返回'​​ ' .join(res)

现在我们对“去向量化”函数的约束是,它将用零填充尾随字符。 例如,如果输入向量是 ('1-20', '-19'),那么去向量化的输出将是 ('01-20', '00-19')。 我们需要处理这些额外的填充零。 让我们编写一个用于剥离字符串的函数。

def剥离(输入):

标志=

输出= ' '

对于c输入 _

如果不是标志c == ' 0 '

继续

如果c == ' + 'c == ' 'c == ' * 'c == ' / 'c == ' ' :

标志=

否则

标志=

输出+= c

返回输出

4. 制作数据集

现在我们已经完成了定义一个生成数据的函数,让我们使用该函数并创建一个包含许多这样的(算术表达式,结果)对的数据集。

def create_dataset (num_equations):

x_train = np.zeros((num_equations, max_time_steps, num_chars))

y_train = np.zeros((num_equations, max_time_steps, num_chars))

对于范围内i (num_equations):

e, l =数据生成()

x, y =矢量化(e, l)

x_train[i] = x

y_train[i] = y

返回x_train, y_train

5. 训练模型

让我们创建一个包含 50,000 个样本的数据集,这是训练我们的数据饥饿模型的一个公平数字,我们将使用 25% 的数据进行验证。 另外,如果准确率在 8 个 epoch 内保持不变,我们为智能训练中断创建回调。 这可以通过将耐心参数设置为 8 来实现。

x_train, y_train = create_dataset( 50000 )

simple_logger = LambdaCallback(

on_epoch_end = lambda e, l: print ( ' {:.2f} ' .format(l[ ' val_accuracy ' ]), end = ' _ ' )

)

early_stopping = EarlyStopping(monitor = ' val_loss ' , 耐心= 8 )

model.fit(x_train,y_train,epochs = 100 ,validation_split = 0.25 ,verbose = 0

回调= [simple_logger, early_stopping])

6. 测试模型

现在让我们通过创建一个大小为 30 的数据集来测试我们的模型。

x_test, y_test = create_dataset(num_equations = 20 )

preds = model.predict(x_test)

full_seq_acc = 0

对于i, pred in enumerate (preds):

pred_str =剥离(去矢量化(pred))

y_test_str =剥离(去向量化(y_test[i]))

x_test_str =剥离(去向量化(x_test[i]))

col = ' green ' if pred_str == y_test_str else ' red '

full_seq_acc += 1 / len (preds) * int (pred_str == y_test_str)

outstring = '输入:{},输出:{},预测:{} ' .format(x_test_str, y_test_str, pred_str)

打印(彩色(outstring,col))

print ( ' \n全序列精度:{:.3f} % ' .format( 100 * full_seq_acc))

输出将如下所示

我们可以看到这里的准确性有点差,无论如何我们可以通过调整一些超参数来优化它,比如隐藏单元的数量、验证拆分、epoch 的数量等。

结论

我们了解了 RNN 的基本工作流程,了解 RNN 最适合序列数据,生成随机算术方程的数据集,开发了用于预测基本算术表达式输出的序列模型,使用数据集训练了该模型我们已经创建并最终使用模型从未见过的小数据集测试了该模型。

如果您有兴趣了解有关 RNN、机器学习的更多信息,请查看 IIIT-B 和 upGrad 的机器学习和人工智能 PG 文凭,该文凭专为在职专业人士设计,提供 450 多个小时的严格培训、30 多个案例研究和作业, IIIT-B 校友身份、5 个以上实用的实践顶点项目和顶级公司的工作协助。

机器学习中有哪些不同类型的神经网络?

在机器学习中,人工神经网络基本上是被设计成类似于人脑的计算模型。 机器学习根据需要实现的数学计算采用不同类型的人工神经网络。 这些神经网络是不同机器学习技术的子集,它们以不同的方式从数据中学习。 一些最广泛使用的神经网络类型是 - 循环神经网络 - 长期短期记忆,前馈神经网络 - 人工神经元,径向基函数神经网络,Kohonen 自组织神经网络,卷积神经网络和模块化神经网络,其中。

递归神经网络有什么优势?

循环神经网络是深度学习和机器学习中最常用的人工神经网络之一。 在这种类型的神经网络模型中,从上一步获得的结果作为输入馈送到后续步骤。 递归神经网络具有几个优点,例如 - 它可以随着时间的推移保留所有信息,包括其先前的输入,这使其成为时间序列预测的理想选择。 这种类型是长短记忆的最佳实例。 此外,循环神经网络通过使用卷积层提供建设性的像素邻域。

神经网络在实际应用中是如何使用的?

人工神经网络是深度学习的一个组成部分,深度学习又是机器学习和人工智能的一个超级专业分支。 神经网络用于不同行业以实现各种关键目标。 人工神经网络的一些最有趣的实际应用包括股票市场预测、面部识别、航空航天工业中的高性能自动驾驶和故障诊断、国防领域的武装攻击和目标定位分析、图像处理、医疗保健领域的药物发现和疾病检测、签名验证、笔迹分析、天气预报和社交媒体趋势预测等。