Logo
Section 1 / 3

项目创建:第一部分

在本节课中,我们将基于字符级RNN开展另一个项目。在这个项目中,我们将构建一个模型,用于破解加密的文本。

检查点

项目创建:第一部分

在本节课中,我们将基于字符级RNN开展另一个项目。在这个项目中,我们将构建一个模型,用于破解加密的文本。

项目简介

现在你已经了解了循环神经网络(RNN)的工作原理,并且在上一章中也完成了一个项目。在本章中,我们将构建一个模型,用于破解使用特定密码算法加密的字符串。

什么是密码(cipher)?

密码是一种用于加密和解密数据的加密算法。在本项目中,我们将使用凯撒密码(Caesar cipher)。它是一种单字母替换密码,即明文中的每个字母都被另一个字母替代,从而形成密文。这是最简单的替换密码形式,通常也被称为移位密码。其基本思想是将每一个字母替换成在字母表中向后(或向前)移动固定位数(0 到 25 之间)的另一个字母。

例如,如果我们对字符串 hello 使用右移 1 位的方式进行加密,得到的密文(即加密后的数据)将是 ifmmp。

请完成下面的小测验来检验你的理解。

现在你已经清楚我们要做什么了,接下来就开始吧。

下载数据集

该数据集包含 10,000 条加密短语及其对应的明文版本。请下载以下两个数据文件并查看内容。

plaintext.txt

cipher.txt

加载数据集

下载完数据集并查看文本文件后,我们接下来加载数据并开始处理。

1import os 2 3def load_data(path): 4 input_file = os.path.join(path) 5 with open(input_file, "r") as f: 6 data = f.read() 7 return data.split('\n') 8 9codes = load_data('cipher.txt') 10plaintext = load_data('plaintext.txt') 11print('数据加载成功!')

运行上述代码后,我们就完成了数据的加载。我们将加密文本存储在变量 codes 中,将原始明文存储在变量 plaintext 中。

你可以使用以下代码查看数据内容:

1print(codes[:3]) 2print(plaintext[:3])

上述语句将打印出数据集中的前三个句子。第一行输出的是密文,第二行输出的是对应的明文。

现在,在继续之前,我们需要明确将要构建的模型类型。

模型概述——字符级 RNN

我们将使用的模型是一个字符级的循环神经网络(RNN),因为凯撒密码是在字符级别上操作的。

字符级 RNN 接收一个整数作为输入,代表某个特定字符,并输出另一个整数。换句话说,我们的模型将以编码(转换为整数形式)作为输入,并输出对应的明文(整数再转换回文本)。为了让模型正常工作,我们需要对数据集进行如下预处理步骤:

  • 将每个字符单独分离为数组元素(而不是以整个短语或单词作为数组元素)。
  • 对字符进行标记化(tokenization),以便将字母转换为整数,反之亦然。
  • 对字符串进行填充(padding),使所有输入和输出都能以矩阵形式表示。

为了更直观地理解这一过程,假设我们的源序列(此处为 codes)或目标序列(此处为 plaintext)如下所示(一个字符串列表):

(图示:原始字符串列表)

由于模型将在字符级别上运行,我们需要将每个字符串拆分为字符列表(这一步由分词器隐式完成):

(图示:拆分为字符)

然后,通过标记化过程将每个字符转换为整数。注意,在之前的课程中我们使用的是词级 RNN,它将每个单词转换为整数;而这里的字符级 RNN 中,分词器会为每个字母分配一个整数,每个单元格代表一个字符而非一个单词。

(图示:字符转为整数)

在之前的课程中我们讨论过填充(padding)操作,这里我们也需要进行填充以构成矩阵。为了将输入转换为矩阵形式,我们需要找到列表中最长的序列,并用 0 填充所有较短的序列。假设本例中“and two”是最长序列,则最终的矩阵如下所示:

(图示:填充后的矩阵)

数据预处理

为了让神经网络能够预测文本数据,首先必须将其转换为模型可理解的形式。像 "dog" 这样的文本数据本质上是一系列 ASCII 字符编码。由于神经网络是由一系列乘法和加法运算组成的,因此输入数据必须是数值形式。

我们将沿用上一章中的方法,将文本数据转换为数字。

1from tensorflow.python.keras.preprocessing.text import Tokenizer 2 3def tokenize(x): 4 x_tk = Tokenizer(char_level=True) 5 x_tk.fit_on_texts(x) 6 return x_tk.texts_to_sequences(x), x_tk 7 8text_sentences = [ 9 'The quick brown fox jumps over the lazy dog .', 10 'By Jove , my quick study of lexicography won a prize .', 11 'This is a short sentence .'] 12 13text_tokenized, text_tokenizer = tokenize(text_sentences) 14 15print(text_tokenizer.word_index) 16 17for sample_i, (sent, token_sent) in enumerate(zip(text_sentences, text_tokenized)): 18 print('x 中的第 {} 个序列'.format(sample_i + 1)) 19 print(' 输入: {}'.format(sent)) 20 print(' 输出: {}'.format(token_sent))

解释:

  • 第 1 行:从 Keras 库中导入 Tokenizer。
  • 第 3 到第 7 行:定义了一个函数用于对输入文本进行标记化(即将文本转换为数字)。该函数返回两个结果:一是给定文本的整数表示,二是 Tokenizer 对象,后者可用于后续将文本转换为整数。之所以需要返回这个对象,是因为我们希望在其他句子上使用相同的分词器,以确保相同字符始终对应相同的整数表示。
  • 第 8 行:定义了一些测试句子,用于验证函数是否正常工作。
  • 第 14 行输出如下:
    1{' ': 1, 'e': 2, 'o': 3, 't': 4, 'i': 5, 's': 6, 'h': 7, 'r': 8, 'y': 9, 'u': 10, 'c': 11, 'n': 12, 'a': 13, 'p': 14, '.': 15, 'q': 16, 'k': 17, 'b': 18, 'w': 19, 'f': 20, 'x': 21, 'j': 22, 'm': 23, 'v': 24, 'l': 25, 'z': 26, 'd': 27, 'g': 28, ',': 29}
    可以看到,每个字符都被映射到了一个唯一的整数。
  • 第 16 行:使用循环打印出标记化后的数据,也就是转换为整数形式的结果。注意,一组句子中的每个整数代表一个字符,而不是一个单词。

Quiz

单选题

如果右移10位,输入文本 "Go kbo vokbxsxq klyed mszrobc" 的解密文本是什么?

1 / 1

项目:IMDB影评情感分析

项目创建:第二部分