您无法直接从原始文本转到拟合机器学习或深度学习模型。
您必须先清理您的文本,这意味着将其拆分成单词并处理标点符号和大小写。
事实上,有一整套文本准备方法您可能需要使用,而方法的选择真正取决于您的自然语言处理任务。
在本教程中,您将了解如何清理和准备文本,以便使用机器学习进行建模。
完成本教程后,您将了解:
- 如何通过开发自己非常简单的文本清理工具来启动您的项目。
- 如何更进一步,使用 NLTK 库中更复杂的方法。
- 使用像词嵌入这样的现代文本表示方法时如何准备文本。
通过我的新书 《深度学习在自然语言处理中的应用》 开启您的项目,书中包含分步教程以及所有示例的Python 源代码文件。
让我们开始吧。
- 更新于 2017 年 11 月:修复了“拆分单词”部分的代码拼写错误,感谢 David Comfort。

如何开发用于时间序列预测的多层感知器模型
照片由 Bureau of Land Management 提供,部分权利保留。
教程概述
本教程分为6个部分;它们是
- 弗兰茨·卡夫卡著《变形记》
- 文本清理是特定于任务的
- 手动分词
- 使用 NLTK 进行分词和清理
- 其他文本清理注意事项
- 清理文本以用于词嵌入的技巧
需要深度学习处理文本数据的帮助吗?
立即参加我的免费7天电子邮件速成课程(附代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
弗兰茨·卡夫卡著《变形记》
让我们开始选择一个数据集。
在本教程中,我们将使用弗兰茨·卡夫卡(Franz Kafka)创作的《变形记》(Metamorphosis)一书中的文本。没有特别的原因,只是因为它很短,我喜欢它,您也可能喜欢。我猜这是大多数学生在学校里必须阅读的经典作品之一。
《变形记》的完整文本可从 Project Gutenberg 免费获取。
您可以下载文本的 ASCII 版本,网址是:
- 弗兰茨·卡夫卡《变形记》纯文本 UTF-8(可能需要加载两次页面)。
下载文件并将其放入当前工作目录,文件名为“metamorphosis.txt”。
文件中包含我们不感兴趣的头部和尾部信息,特别是版权和许可信息。打开文件,删除头部和尾部信息,然后将文件另存为“metamorphosis_clean.txt”。
清理后的文件开头应如下所示:
一天早晨,格里高尔·萨姆沙从不安的睡梦中醒来,发现自己在床上变成了一只可怕的甲虫。
文件应以以下内容结尾:
仿佛是为了印证他们新的梦想和良好的意愿,他们一到达目的地,格蕾特就第一个站起来伸展了年轻的身体。
可怜的格里高尔……
文本清理是特定于任务的
在实际获取文本数据后,清理文本数据的第一个步骤是明确您想要实现的目标,并在此背景下审查您的文本,看看具体哪些内容可能有所帮助。
花点时间看看文本。您发现了什么?
这是我看到的:
- 它是纯文本,所以没有标记需要解析(太棒了!)。
- 原始德语的翻译使用了英式英语(例如,“travelling”)。
- 这些行是人为地以大约 70 个字符换行的(唉)。
- 没有明显的拼写错误。
- 有标点符号,如逗号、撇号、引号、问号等。
- 有连字符的描述,如“armour-like”。
- 大量使用破折号(“-”)来连接句子(也许可以替换成逗号?)。
- 有名字(例如,“Mr. Samsa”)。
- 似乎没有需要处理的数字(例如,1999)。
- 有章节标记(例如,“II”和“III”),我们已经移除了第一个“I”。
我相信对于训练有素的眼睛来说,还有很多其他的细节。
在本教程中,我们将介绍通用的文本清理步骤。
尽管如此,请考虑我们处理此文本文件时可能的一些可能目标。
例如
- 如果我们对开发一种“Kafkaesque”语言模型感兴趣,我们可能希望保留所有的大小写、引号和其他标点符号。
- 如果我们对将文档分类为“Kafka”和“Not Kafka”感兴趣,也许我们应该去除大小写、标点符号,甚至将单词缩减到词干。
使用您的任务作为选择如何准备文本数据的视角。
手动分词
文本清理很难,但我们选择处理的文本已经非常干净了。
我们可以编写一些 Python 代码手动清理它,这对于您遇到的简单问题来说是一个很好的练习。像正则表达式和字符串分割这样的工具可以帮助您走很长的路。
1. 加载数据
让我们加载文本数据以便我们可以处理它。
文本很小,可以快速轻松地加载到内存中。情况并非总是如此,您可能需要编写代码来内存映射文件。像 NLTK(在下一节介绍)这样的工具将使处理大文件更加容易。
我们可以将整个“metamorphosis_clean.txt”加载到内存中,如下所示:
1 2 3 4 5 |
# 加载文本 filename = 'metamorphosis_clean.txt' file = open(filename, 'rt') text = file.read() 文件.close() |
运行示例将整个文件加载到内存中,准备好进行处理。
2. 按空格分割
清理文本通常意味着得到一个我们可以用于机器学习模型的单词或标记列表。
这意味着将原始文本转换为单词列表,然后再次保存。
一个非常简单的方法是按空格分割文档,包括“ ”、换行符、制表符等。我们可以使用 Python 中加载字符串的 split() 函数来完成。
1 2 3 4 5 6 7 8 |
# 加载文本 filename = 'metamorphosis_clean.txt' file = open(filename, 'rt') text = file.read() 文件.close() # 按空格分割成单词 words = text.split() print(words[:100]) |
运行示例,文档被分割成一个长单词列表,并打印出前 100 个供我们查看。
我们可以看到标点符号被保留(例如,“wasn’t”和“armour-like”),这很好。我们还可以看到句末标点符号与最后一个单词一起保留(例如,“thought.”),这不太理想。
1 |
['One', 'morning,', 'when', 'Gregor', 'Samsa', 'woke', 'from', 'troubled', 'dreams,', 'he', 'found', 'himself', 'transformed', 'in', 'his', 'bed', 'into', 'a', 'horrible', 'vermin.', 'He', 'lay', 'on', 'his', 'armour-like', 'back,', 'and', 'if', 'he', 'lifted', 'his', 'head', 'a', 'little', 'he', 'could', 'see', 'his', 'brown', 'belly,', 'slightly', 'domed', 'and', 'divided', 'by', 'arches', 'into', 'stiff', 'sections.', 'The', 'bedding', 'was', 'hardly', 'able', 'to', 'cover', 'it', 'and', 'seemed', 'ready', 'to', 'slide', 'off', 'any', 'moment.', 'His', 'many', 'legs,', 'pitifully', 'thin', 'compared', 'with', 'the', 'size', 'of', 'the', 'rest', 'of', 'him,', 'waved', 'about', 'helplessly', 'as', 'he', 'looked.', '"What\'s', 'happened', 'to', 'me?"', 'he', 'thought.', 'It', "wasn't", 'a', 'dream.', 'His', 'room,', 'a', 'proper', 'human'] |
3. 选择单词
另一种方法可能是使用正则表达式模型(re),通过选择字母数字字符(a-z、A-Z、0-9 和 ‘_’)的字符串来分割文档。
例如
1 2 3 4 5 6 7 8 9 |
# 加载文本 filename = 'metamorphosis_clean.txt' file = open(filename, 'rt') text = file.read() 文件.close() # 按单词分割 import re words = re.split(r'\W+', text) print(words[:100]) |
同样,运行示例我们可以看到我们得到了单词列表。这次,我们可以看到“armour-like”变成了两个词“armour”和“like”(没问题),但像“What’s”这样的缩写词也变成了两个词“What”和“s”(不太理想)。
1 |
['One', 'morning', 'when', 'Gregor', 'Samsa', 'woke', 'from', 'troubled', 'dreams', 'he', 'found', 'himself', 'transformed', 'in', 'his', 'bed', 'into', 'a', 'horrible', 'vermin', 'He', 'lay', 'on', 'his', 'armour', 'like', 'back', 'and', 'if', 'he', 'lifted', 'his', 'head', 'a', 'little', 'he', 'could', 'see', 'his', 'brown', 'belly', 'slightly', 'domed', 'and', 'divided', 'by', 'arches', 'into', 'stiff', 'sections', 'The', 'bedding', 'was', 'hardly', 'able', 'to', 'cover', 'it', 'and', 'seemed', 'ready', 'to', 'slide', 'off', 'any', 'moment', 'His', 'many', 'legs', 'pitifully', 'thin', 'compared', 'with', 'the', 'size', 'of', 'the', 'rest', 'of', 'him', 'waved', 'about', 'helplessly', 'as', 'he', 'looked', 'What', 's', 'happened', 'to', 'me', 'he', 'thought', 'It', 'wasn', 't', 'a', 'dream', 'His', 'room'] |
3. 按空格分割并移除标点符号
注意:此示例是为 Python 3 编写的。
我们可能需要单词,但不需要逗号和引号这样的标点符号。我们也想将缩写词保留在一起。
一种方法是将文档按空格分割成单词(如“2. 按空格分割”),然后使用字符串翻译将所有标点符号替换为空(例如,移除它们)。
Python 提供了一个名为 *string.punctuation* 的常量,它提供了一个很好的标点符号列表。例如:
1 |
print(string.punctuation) |
结果如下:
1 |
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ |
Python 提供了一个名为 translate() 的函数,它可以将一组字符映射到另一组字符。
我们可以使用 maketrans() 函数创建一个映射表。我们可以创建一个空的映射表,但该函数的第三个参数允许我们列出在翻译过程中要删除的所有字符。例如:
1 |
table = str.maketrans('', '', string.punctuation) |
我们可以将所有这些放在一起,加载文本文件,按空格将其分割成单词,然后翻译每个单词以移除标点符号。
1 2 3 4 5 6 7 8 9 10 11 12 |
# 加载文本 filename = 'metamorphosis_clean.txt' file = open(filename, 'rt') text = file.read() 文件.close() # 按空格分割成单词 words = text.split() # 从每个单词中移除标点符号 import string table = str.maketrans('', '', string.punctuation) stripped = [w.translate(table) for w in words] print(stripped[:100]) |
我们可以看到这已经达到了预期的效果,大部分是。
像“What’s”这样的缩写词变成了“Whats”,而“armour-like”变成了“armourlike”。
1 |
['One', 'morning', 'when', 'Gregor', 'Samsa', 'woke', 'from', 'troubled', 'dreams', 'he', 'found', 'himself', 'transformed', 'in', 'his', 'bed', 'into', 'a', 'horrible', 'vermin', 'He', 'lay', 'on', 'his', 'armourlike', 'back', 'and', 'if', 'he', 'lifted', 'his', 'head', 'a', 'little', 'he', 'could', 'see', 'his', 'brown', 'belly', 'slightly', 'domed', 'and', 'divided', 'by', 'arches', 'into', 'stiff', 'sections', 'The', 'bedding', 'was', 'hardly', 'able', 'to', 'cover', 'it', 'and', 'seemed', 'ready', 'to', 'slide', 'off', 'any', 'moment', 'His', 'many', 'legs', 'pitifully', 'thin', 'compared', 'with', 'the', 'size', 'of', 'the', 'rest', 'of', 'him', 'waved', 'about', 'helplessly', 'as', 'he', 'looked', 'Whats', 'happened', 'to', 'me', 'he', 'thought', 'It', 'wasnt', 'a', 'dream', 'His', 'room', 'a', 'proper', 'human'] |
如果您了解正则表达式,那么您就知道事情可能会变得很复杂。
4. 规范化大小写
通常需要将所有单词转换为一种大小写。
这意味着词汇量会缩小,但会丢失一些区别(例如,“Apple”公司与“apple”水果是一个常用的例子)。
我们可以通过对每个单词调用 lower() 函数将所有单词转换为小写。
例如
1 2 3 4 5 6 7 8 9 |
filename = 'metamorphosis_clean.txt' file = open(filename, 'rt') text = file.read() 文件.close() # 按空格分割成单词 words = text.split() # 转换为小写 words = [word.lower() for word in words] print(words[:100]) |
运行示例,我们可以看到所有单词现在都是小写了。
1 |
['one', 'morning,', 'when', 'gregor', 'samsa', 'woke', 'from', 'troubled', 'dreams,', 'he', 'found', 'himself', 'transformed', 'in', 'his', 'bed', 'into', 'a', 'horrible', 'vermin.', 'he', 'lay', 'on', 'his', 'armour-like', 'back,', 'and', 'if', 'he', 'lifted', 'his', 'head', 'a', 'little', 'he', 'could', 'see', 'his', 'brown', 'belly,', 'slightly', 'domed', 'and', 'divided', 'by', 'arches', 'into', 'stiff', 'sections.', 'the', 'bedding', 'was', 'hardly', 'able', 'to', 'cover', 'it', 'and', 'seemed', 'ready', 'to', 'slide', 'off', 'any', 'moment.', 'his', 'many', 'legs,', 'pitifully', 'thin', 'compared', 'with', 'the', 'size', 'of', 'the', 'rest', 'of', 'him,', 'waved', 'about', 'helplessly', 'as', 'he', 'looked.', '"what\'s', 'happened', 'to', 'me?"', 'he', 'thought.', 'it', "wasn't", 'a', 'dream.', 'his', 'room,', 'a', 'proper', 'human'] |
注意
清理文本确实很难,特定于问题,并且充满了权衡。
记住,简单就是最好。
更简单的文本数据、更简单的模型、更小的词汇量。您总是可以以后让事情变得更复杂,看看是否能提高模型的技能。
接下来,我们将看看 NLTK 库中的一些工具,它们提供的功能超出了简单的字符串分割。
使用 NLTK 进行分词和清理
自然语言工具包(Natural Language Toolkit),简称 NLTK,是一个用于处理和建模文本的 Python 库。
它提供了用于加载和清理文本的优秀工具,我们可以用这些工具来准备数据,以便与机器学习和深度学习算法一起使用。
1. 安装 NLTK
您可以使用您喜欢的包管理器(如 pip)来安装 NLTK。
1 |
sudo pip install -U nltk |
安装后,您需要安装该库使用的数据,包括一套非常棒的文档,您以后可以用它来测试 NLTK 中的其他工具。
有几种方法可以做到这一点,例如从脚本中操作:
1 2 |
import nltk nltk.download() |
或者从命令行操作:
1 |
python -m nltk.downloader all |
有关安装和设置 NLTK 的更多帮助,请参阅:
2. 分割成句子
一个好的有用第一步是将文本分割成句子。
某些建模任务偏好以段落或句子的形式输入,例如 word2vec。您可以先将文本分割成句子,将每个句子分割成单词,然后将每个句子保存到文件中,每行一个。
NLTK 提供了 sent_tokenize() 函数来将文本分割成句子。
下面的示例将“metamorphosis_clean.txt”文件加载到内存中,将其分割成句子,并打印第一个句子。
1 2 3 4 5 6 7 8 9 |
# 加载数据 filename = 'metamorphosis_clean.txt' file = open(filename, 'rt') text = file.read() 文件.close() # 分割成句子 from nltk import sent_tokenize sentences = sent_tokenize(text) print(sentences[0]) |
运行示例,我们可以看到,尽管文档被分割成了句子,但每个句子仍然保留了原始文档中行的人工换行。
一天早晨,格里高尔·萨姆沙从不安的睡梦中醒来,发现
自己在床上变成了一只可怕的甲虫。
3. 分割成单词
NLTK 提供了一个名为 word_tokenize() 的函数,用于将字符串分割成标记(名义上是单词)。
它根据空格和标点符号分割标记。例如,逗号和句点被视为单独的标记。缩写词被分开(例如,“What’s”变成“What” “‘s”)。引号被保留,等等。
例如
1 2 3 4 5 6 7 8 9 |
# 加载数据 filename = 'metamorphosis_clean.txt' file = open(filename, 'rt') text = file.read() 文件.close() # 分割成单词 从 nltk.分词 导入 word_tokenize tokens = word_tokenize(text) print(tokens[:100]) |
运行代码,我们可以看到标点符号现在是标记,我们可以稍后选择专门过滤掉它们。
1 |
['One', 'morning', ',', 'when', 'Gregor', 'Samsa', 'woke', 'from', 'troubled', 'dreams', ',', 'he', 'found', 'himself', 'transformed', 'in', 'his', 'bed', 'into', 'a', 'horrible', 'vermin', '.', 'He', 'lay', 'on', 'his', 'armour-like', 'back', ',', 'and', 'if', 'he', 'lifted', 'his', 'head', 'a', 'little', 'he', 'could', 'see', 'his', 'brown', 'belly', ',', 'slightly', 'domed', 'and', 'divided', 'by', 'arches', 'into', 'stiff', 'sections', '.', 'The', 'bedding', 'was', 'hardly', 'able', 'to', 'cover', 'it', 'and', 'seemed', 'ready', 'to', 'slide', 'off', 'any', 'moment', '.', 'His', 'many', 'legs', ',', 'pitifully', 'thin', 'compared', 'with', 'the', 'size', 'of', 'the', 'rest', 'of', 'him', ',', 'waved', 'about', 'helplessly', 'as', 'he', 'looked', '.', '``', 'What', "'s", 'happened', 'to'] |
4. 过滤掉标点符号
我们可以过滤掉所有我们不感兴趣的标记,例如所有独立的标点符号。
这可以通过迭代所有标记并仅保留所有是字母的标记来完成。Python 有一个 isalpha() 函数可以使用。例如:
1 2 3 4 5 6 7 8 9 10 11 |
# 加载数据 filename = 'metamorphosis_clean.txt' file = open(filename, 'rt') text = file.read() 文件.close() # 分割成单词 从 nltk.分词 导入 word_tokenize tokens = word_tokenize(text) # 移除所有非字母标记 words = [word for word in tokens if word.isalpha()] print(words[:100]) |
运行示例,您可以看到不仅标点符号标记被移除了,像“armour-like”和“‘s”这样的例子也被过滤掉了。
1 |
['One', 'morning', 'when', 'Gregor', 'Samsa', 'woke', 'from', 'troubled', 'dreams', 'he', 'found', 'himself', 'transformed', 'in', 'his', 'bed', 'into', 'a', 'horrible', 'vermin', 'He', 'lay', 'on', 'his', 'back', 'and', 'if', 'he', 'lifted', 'his', 'head', 'a', 'little', 'he', 'could', 'see', 'his', 'brown', 'belly', 'slightly', 'domed', 'and', 'divided', 'by', 'arches', 'into', 'stiff', 'sections', 'The', 'bedding', 'was', 'hardly', 'able', 'to', 'cover', 'it', 'and', 'seemed', 'ready', 'to', 'slide', 'off', 'any', 'moment', 'His', 'many', 'legs', 'pitifully', 'thin', 'compared', 'with', 'the', 'size', 'of', 'the', 'rest', 'of', 'him', 'waved', 'about', 'helplessly', 'as', 'he', 'looked', 'What', 'happened', 'to', 'me', 'he', 'thought', 'It', 'was', 'a', 'dream', 'His', 'room', 'a', 'proper', 'human', 'room'] |
5. 过滤掉停用词(和管道)
停用词是那些对短语的深层含义没有贡献的词。
它们是最常见的词,例如:“the”、“a”和“is”。
对于文档分类等一些应用,移除停用词可能是有意义的。
NLTK 提供了多种语言(如英语)的常用停用词列表。它们可以如下加载:
1 2 3 |
from nltk.corpus import stopwords stop_words = stopwords.words('english') print(stop_words) |
您可以通过以下方式查看完整列表:
1 |
['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', 'her', 'hers', 'herself', 'it', 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', 'should', 'now', 'd', 'll', 'm', 'o', 're', 've', 'y', 'ain', 'aren', 'couldn', 'didn', 'doesn', 'hadn', 'hasn', 'haven', 'isn', 'ma', 'mightn', 'mustn', 'needn', 'shan', 'shouldn', 'wasn', 'weren', 'won', 'wouldn'] |
您可以看到它们都是小写并且已经移除了标点符号。
您可以将您的标记与停用词进行比较并过滤掉它们,但您必须确保您的文本经过了相同的预处理。
让我们通过一个简单的文本预处理管道来演示这一点,包括:
- 加载原始文本。
- 分割成标记。
- 转换为小写。
- 从每个标记中移除标点符号。
- 过滤掉剩余的非字母标记。
- 过滤掉停用词标记。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# 加载数据 filename = 'metamorphosis_clean.txt' file = open(filename, 'rt') text = file.read() 文件.close() # 分割成单词 从 nltk.分词 导入 word_tokenize tokens = word_tokenize(text) # 转换为小写 tokens = [w.lower() for w in tokens] # 从每个单词中移除标点符号 import string table = str.maketrans('', '', string.punctuation) stripped = [w.translate(table) for w in tokens] # 移除所有非字母的剩余标记 words = [word for word in stripped if word.isalpha()] # 过滤掉停用词 from nltk.corpus import stopwords stop_words = set(stopwords.words('english')) words = [w for w in words if not w in stop_words] print(words[:100]) |
运行此示例,我们可以看到除了所有其他转换之外,像“a”和“to”这样的停用词也被移除了。
我注意到我们仍然剩下像“nt”这样的标记。这个兔子洞很深;总有更多的事情可以做。
1 |
['一天早上,格里高尔·萨姆沙从不安的梦中醒来,发现自己在床上变成了一只可怕的甲虫。他躺在坚硬的、像盔甲一样的背上,抬起头,看到自己棕色的肚子,微微隆起,由几道拱门分成,肚子紧绷,身体勉强能盖住被子,似乎随时都会滑落。他的许多细腿与他身体的其余部分相比,显得可怜地细小,无助地挥舞着。他想:“这到底是怎么回事?”,但这是一个梦。他的房间,一个真正的、人的房间,虽然有点小,但仍然平静地坐落在四面熟悉的墙壁之间。格里高尔是一个旅行推销员,他收集了一套纺织品样本。他挂在墙上的一幅画最近从一本插图杂志上剪了下来,装在一个漂亮的镀金相框里。这幅画描绘了一位女士,她戴着一顶皮毛帽和皮毛披肩,直立着,举起一只沉重的皮毛手套,笼罩着她整个前臂,朝向观众。] |
6. 词干提取
词干提取是指将每个单词还原为其词根或基本形式的过程。
例如,“fishing”、“fished”、“fisher”都还原为词干“fish”。
某些应用,例如文档分类,可以通过词干提取来减小词汇量,并侧重于文档的意义或情感,而不是深层含义。
有许多词干提取算法,其中一种流行且历史悠久的算法是 Porter 词干提取算法。这种方法可以通过 NLTK 中的 PorterStemmer 类来使用。
例如
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 加载数据 filename = 'metamorphosis_clean.txt' file = open(filename, 'rt') text = file.read() 文件.close() # 分割成单词 从 nltk.分词 导入 word_tokenize tokens = word_tokenize(text) # 词干提取 from nltk.stem.porter import PorterStemmer porter = PorterStemmer() stemmed = [porter.stem(word) for word in tokens] print(stemmed[:100]) |
运行示例,您可以看到单词已被简化为其词干,例如“trouble”变成了“troubl”。您还可以看到,词干提取实现还将标记转换为小写,这可能是为了在单词表中进行内部查找。
您还可以看到,词干提取实现还将标记转换为小写,这可能是为了在单词表中进行内部查找。
1 |
['one', 'morn', ',', 'when', 'gregor', 'samsa', 'woke', 'from', 'troubl', 'dream', ',', 'he', 'found', 'himself', 'transform', 'in', 'hi', 'bed', 'into', 'a', 'horribl', 'vermin', '.', 'He', 'lay', 'on', 'hi', 'armour-lik', 'back', ',', 'and', 'if', 'he', 'lift', 'hi', 'head', 'a', 'littl', 'he', 'could', 'see', 'hi', 'brown', 'belli', ',', 'slightli', 'dome', 'and', 'divid', 'by', 'arch', 'into', 'stiff', 'section', '.', 'the', 'bed', 'wa', 'hardli', 'abl', 'to', 'cover', 'it', 'and', 'seem', 'readi', 'to', 'slide', 'off', 'ani', 'moment', '.', 'hi', 'mani', 'leg', ',', 'piti', 'thin', 'compar', 'with', 'the', 'size', 'of', 'the', 'rest', 'of', 'him', ',', 'wave', 'about', 'helplessli', 'as', 'he', 'look', '.', '``', 'what', "'s", 'happen', 'to' |
如果您需要将单词还原为其词根,NLTK 中有许多不错的词干提取和词形还原算法可供选择。
其他文本清理注意事项
我们才刚刚开始。
由于本教程的源文本一开始就相对干净,我们跳过了文本清理中您可能需要在自己的项目中处理的许多问题。
以下是清理文本时需要考虑的其他事项的简短列表
- 处理不适合放入内存的大文档和大量文本文档。
- 从 HTML、PDF 或其他结构化文档格式的标记中提取文本。
- 将其他语言的字符音译成英语。
- 将 Unicode 字符解码为规范化形式,例如 UTF8。
- 处理特定领域的词语、短语和首字母缩略词。
- 处理或删除数字,例如日期和金额。
- 定位并更正常见的拼写错误和拼写错误。
- …
这个列表还可以继续。
希望您能看到,要获得真正干净的文本是不可能的,我们只是根据时间和资源,尽我们所能。
“干净”这个概念实际上取决于您项目的特定任务或关注点。
一个窍门是,在每次转换后不断审查您的标记。我在这本教程中试图展示这一点,希望您能牢记在心。
理想情况下,您应该在每次转换后保存一个新文件,这样您就可以花时间处理新形式的所有数据。当您花时间审查数据时,总会有一些问题会浮现出来。
您以前做过文本清理吗?您首选的转换流程是什么?
在下面的评论中告诉我。
清理文本以用于词嵌入的技巧
最近,自然语言处理领域已从词袋模型和词嵌入转向词嵌入。
词嵌入的好处在于,它们将每个词编码为一个密集向量,该向量捕获了其在训练文本中相对含义的某些信息。
这意味着诸如大小写、拼写、标点符号等单词的变体将在嵌入空间中自动被学习为相似的。反过来,这可能意味着您的文本所需的清理量可能更少,甚至与传统的文本清理完全不同。
例如,对缩略语进行词干提取或删除标点符号可能不再有意义。
Tomas Mikolov 是 word2vec(一种流行的词嵌入方法)的开发者之一。他建议在学习词嵌入模型时只需进行极少的文本清理。
以下是他被问及如何最好地为 word2vec 准备文本数据时的回答。
没有通用的答案。这取决于您打算如何使用这些向量。根据我的经验,通常最好断开(或删除)单词中的标点符号,有时也将其所有字符转换为小写。还可以将所有数字(可能大于某个常数)替换为单个标记,例如“.”。
所有这些预处理步骤都旨在减小词汇量,同时不删除任何重要内容(在某些情况下,例如小写某些单词时,这可能不正确,例如“Bush”与“bush”不同,而“Another”通常与“another”具有相同的含义)。词汇量越小,内存复杂度就越低,单词的参数估计也就越稳健。您还必须以相同的方式预处理测试数据。
…
总之,如果您进行实验,您将更好地理解这一切。
进一步阅读
如果您想深入了解此主题,本节提供了更多资源。
总结
在本教程中,您学习了如何使用 Python 清理文本以用于机器学习。
具体来说,你学到了:
- 如何通过开发自己非常简单的文本清理工具来启动您的项目。
- 如何更进一步,使用 NLTK 库中更复杂的方法。
- 使用像词嵌入这样的现代文本表示方法时如何准备文本。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
您有清理文本的经验吗?
请在下面的评论中分享您的经验。
谢谢你,Jason。非常有趣的工作。
我很高兴它有帮助。
runfile(‘C:/Users/barnabas/.spyder-py3/temp.py’, wdir=’C:/Users/barnabas/.spyder-py3′)
theano: 1.0.3
tensorflow: 2.0.0-alpha0
keras: 2.2.4
使用 TensorFlow 后端。
很有帮助
干得好!
谢谢你
您好 Jason,如果您能帮我解开疑惑,那就太好了
如果分类数据或数值数据缺失,我们可以用均值或众数创建虚拟变量
如何清理文本数据列,假设有少量数据缺失或 NaN?
嗨 Karthik…您可能会发现以下资源有益
https://machinelearning.org.cn/handle-missing-data-python/
https://machinelearning.org.cn/knn-imputation-for-missing-values-in-machine-learning/
词形还原也是 NLTK 中有用的功能。我推荐 Coursera 的“Python 应用文本挖掘”课程。无论如何,这是一个很好的入门介绍,谢谢 Jason
谢谢您的提醒,Marc。
太棒了 Jason,非常感谢。
谢谢。
完整的列表。我有时也会遇到清理 unicode 等的问题。
有时问题在于从句子中提取关键词。有时则在于将关键词替换为文本中的标准化名称。我为此编写了一个非常快的库,名为 FlashText。它比编译的正则表达式快得多。这是文章链接:https://medium.com/@vi3k6i5/search-millions-of-documents-for-thousands-of-keywords-in-a-flash-b39e5d1e126a
再次感谢。
谢谢您的链接。
非常感谢。从视觉上看,清理也非常有用。
谢谢
谢谢!
非常清晰和全面!
对于某些应用,例如词元化标点符号的槽标签,但将标点符号保留为词元也可能很有用。
另一个常见的做法是通过仅取前 K 个单词或删除文档频率低的单词来修剪生成的词汇量。最后处理数字!您可以将所有数字转换为同一个标记,为每个数字设置一个数字标记,或者完全删除它们。
正如您所说,这都非常具体于应用,因此需要大量的实验。再次感谢!
Carlos,很棒的建议,谢谢!
对我帮助很大,尤其是像您这样写得如此好的老师不多。
我有一个问题,如果我想制作一个词袋模型,从许多网站上抓取文本
我做了数据预处理,现在我可以在一个文件中获取所有我需要的单词,但如何制作向量并将数字分配给每个网站?
好问题,这篇文章可以教您如何编码文本。
https://machinelearning.org.cn/prepare-text-data-machine-learning-scikit-learn/
这真的太棒了,谢谢。
谢谢,我很高兴这能有所帮助。
Jason Brownlee,您是否有关于如何将向量保存到磁盘的教程?每次我解析文档时都必须进行处理。
好问题,您可以使用 pickle 或直接保存 numpy 数组。
Jason,您在以下几行中似乎有一个拼写错误:
# 移除所有非字母标记
words = [word for word in tokens if word.isalpha()]
print(tokens[:100])
应该是
# 移除所有非字母标记
words = [word for word in tokens if word.isalpha()]
print(words[:100])
谢谢 David,已修正!
感谢 Jason 的这篇精彩文章。
我很想知道如何从样本中删除引用的文本,因为这些引用的文本不是我的学生写的。
您对删除表格和其他图形表示法有任何建议吗?
我很感激,
也许是一些针对这些示例的自定义正则表达式?
嗨,Jason,
确实是非常有趣的工作。我想知道是否有任何您(或任何读者)可以推荐给我的关于在未标点文本中添加标点符号的工作。
您可以通过深度 LSTM 学到这一点。
嗨,Jason,
我一直在研究深度 LSTM 和 Matlab,但没有找到太多关于标点符号插入的有用论文/文章。您是否推荐一些关于构建标点系统(punctuation system)的论文/练习?
不,我建议直接开始构建一个。首先定义一个小数据集来训练模型。
您能详细说明一下吗?
我现在拥有的是:
- 电子书,很多。这些是测试和训练数据(数据集)。
- Python 脚本,用于删除所有标点符号和大写字母。标点符号及其对应的索引号
存储在一个表中。此表将用于评估未标点文本的标点符号。我将创建一个新表,当
未标点文本已被标点化,并比较这两个表。您说我必须构建自己的深度 LSTM。我该如何开始?
您说我必须构建自己的深度 LSTM。我该如何开始?
我很乐意帮忙,但我没有能力为您开发或指定此模型。
我找到了一些可能有效的代码。我会尝试让它正常工作。
告诉我进展如何。
谢谢。非常有用。
不客气。
还有,如何在句子中进行词嵌入?有代码示例吗?比如我尝试了 BERT……
这将有助于词嵌入。
https://machinelearning.org.cn/develop-word-embeddings-python-gensim/
您的网站为提供各种 ML 技能提供了极好的起点。谢谢 Jason,我有一个问题:在使用 NLTK 时,它会使用自己的语料库消除停用词。如果我们手动执行相同操作,我们会如何构建停用词集,将其保存在 pickle 文件中,然后消除它们?
NLTK 提供了它们的 pickle 版本。
Jason,帮助很大!
我想开发图像字幕生成,使用我的母语,但我的语言资源稀缺,您能如何帮助我?
也许可以先找到您语言中的图像及其字幕作为训练数据集?
很棒的文章。您能给我一个如何从语料库中删除名称的示例代码吗?谢谢!
抱歉,我没有示例。也许您可以列出名称并从文本中删除它们。
非常感谢这篇精彩的文章。
我现在可以应用算法了吗?
不客气。
请看这里
https://machinelearning.org.cn/start-here/#nlp
如何在文本挖掘中处理缩写词,例如 bcz、u、thr 等?
这很难。
两种粗暴的方法是:
如果您有大量数据,可以对它们进行建模。如果您没有,就删除它们。
谢谢你,Jason。
我开始理解如何清理文本数据了。
干得好。
感谢 Jason 提供的好信息……
但我有一个问题……我能否从文件中(例如 CSV)进行预处理(分词、停用词、词干提取)?……因为我有成千上万份文档,它们保存在 Excel(CSV)中。
谢谢你
当然可以。
您说“停用词是那些对短语的深层含义没有贡献的词。”那么(1)和(2)意思相同吗?
(1) 我点了披萨给 John
(2) 我点了披萨和 John 一起吃
这些也意味着相同
(1) 除非在纽约,玛丽不会接受这份工作
(2) 因为在纽约,玛丽不会接受这份工作
您知道,太多的“数据驱动”和“机器学习” NLP 对您不利!!!!
阅读一些逻辑语义学——那些经过几个世纪研究的知识是缺乏的,这是我的诊断(或者,“一知半解很危险”)。
谢谢。
嗨 Jason,
您是否知道如何从分词后的单词创建有意义的句子?
请尽快告知我。
提前感谢。
你具体指的是什么?
感谢 Jason 提供的好信息。
很高兴它有帮助。
本教程非常有帮助。是否有任何在线免费的 word2vec 参考 pdf?请告知我。感谢发布。
您可以在这里了解更多关于 word2vec 的信息。
https://machinelearning.org.cn/develop-word-embeddings-python-gensim/
嗨,Jason,
链接非常有帮助。感谢分享。我有一个问题,什么算法最适合查找句子中是否存在某些关键词?我的意思是,我知道我正在寻找的关键词,问题在于知道它是否存在。
谢谢,
Sunil
也许可以使用 for 循环并检查每个单词?
嗨 Jason
非常好的教程。我此外还使用了一些模式库的拼写模块以及自动更正。此外,根据问题陈述,还可以应用命名实体识别(NER)过滤(使用spacy或其他现有软件包)……
我有一个关于主题建模的问题,想听听您关于是否需要更多清理步骤的建议。
我有一个请求,希望您能提供一个关于无监督文本主题建模的教程(无论是用于降维还是用于聚类,使用LDA等技术)🙂
不错的技巧!
感谢您的建议。
词干提取部分我遇到了问题
我找不到一种方法能够将 usa 和 u.s.a 识别为同一个词
您可能需要先去除标点符号。
先生,为什么我们在文本清理中去除标点符号?如果我们使用标点符号会怎样?
好问题。
这使得文本更易于建模。例如,我们可以只关注有意义的词。
像 word2vec 和 gloVe 这样的词嵌入模型是否能处理从 Twitter 和其他消息平台抓取的文本中常见的俚语?如果不能,是否有简单的方法制作这些俚语的查找表,或者有其他方法来处理这些词?
如果它们存在于源文本中并且以相同的方式使用。
嗨,杰森博士,
感谢您的发帖,非常有帮助。
我有一个问题,我正在通过 Machine Learning Mastery 的帖子学习 NLP,并尝试练习二分类,我有 116 个负类文件和 4,396 个正类文件。我的疑问是,我是否应该将 4,396 个正类文件减少到 116 个,以匹配 116 个负类文件,以平衡负类文件和正类文件的数量?还是说不需要匹配负类和正类文件的数量?
我希望 Jason 博士能帮助我解答,如果您可以的话。
此致
我在这里有一些建议
https://machinelearning.org.cn/tactics-to-combat-imbalanced-classes-in-your-machine-learning-dataset/
谢谢 Jason 博士,我会学习的。
此致。
嗨,Jason,
感谢这篇文章。我觉得,如果我们预处理大量文本输入,将批次中的每个字符串都经过整个过程可能会很耗时,尤其是在生产环境中。有没有更快的计算速度方法来完成所有这些步骤?
感谢您的考虑。
是的,一旦您定义了词汇表和转换,您就可以并行处理新文本。例如,按句子、段落、文档等。
Jason,
感谢这篇文章!它非常有帮助。
我正在构建一个 NLP 网络,用于根据内容相似性对我的图书馆中的科学论文进行分组/连接。我已经通过相对简单的单词解析器和 Jaccard 相似度度量实现了这一点。但是,我认为借助 WordNet(VerbNet)可以使我的输出更准确。也就是说,如果这些包可以处理“非单词”(即行业特定术语)——其中一些论文包含这些术语(例如,optogenetics、nanoparticle 等)。
这些包能否以一种方式处理“非单词”,从而继续赋予这些单词在原始文本中反映的权重/上下文?
谢谢!
是的。
我需要从 Twitter 数据集中删除相似的文本..该怎么办?
也许可以选择一个文本相似度指标,然后用它来查找相似的文本对并删除一些。
或者查阅文献,看看其他人是如何解决相同问题的。
请删除那张淫秽的阴部图片。它令人不安
谢谢
抱歉。已完成。
嗨,Jason,
您能提供文本文件“metamorphosis_clean.txt”吗?
您可以从原始文本数据创建它。
你到底遇到了什么问题?
非常感谢……
不客气。
嘿 Jason,好文章!
你能告诉我如何在 Python 中处理缩写词(如 bcz、u、thr)吗?应该使用什么代码?
也许可以尝试使用包含它们的预训练词嵌入?
也许可以去除它们?
如果你有足够的数据,也许可以开发你自己的嵌入?
你太棒了!!我给你的解释打 5 分(满分 5 分)。
谢谢。
您好,这是一个很好的教程,我有一个问题,我的文本数据是一行大的,包含这些模式数据:1个产品,60个值或70个值和100个值。在值之后有 8 个空格,然后是 10 行的整数和文本数据。如何将这些行转换为列?
也许先加载到内存中,转换它,然后以新格式保存?
Numpy 可以使用数组上的 .T 属性进行转置。
嗨,Jason
这很有帮助,请问我有一个问题。我有法语文本,在编辑时,文本显示正确,带有“您知道的重音字符,例如‘é’和‘ô’),但是当我导入文本并按空格进行第一次分割时,我得到了奇怪的字符而不是这些法语字母,您知道是什么问题吗?
诚挚地
walid
您可能需要更新帖子中的文本清理过程,以正确支持 unicode 字符。
在文本挖掘中,您将如何处理带有缩写词(如 bcz、u、thr 等)的文本?
如何在 R 和 Python 中处理上述问题?
如果您有足够的数据,您可以学习它们在分布式表示中是如何相互关联的。
如果没有,也许可以手动映射,或者删除它们。
使用 contractions 库来修复俚语。或者定义您自己的词典
情感分析是否需要数据清洗??我有一个包含不同评论的数据集
我该如何清理我的数据?
首先考虑可能对您的数据集有用的数据清理类型。然后应用它们。
如果您不确定,可以尝试几种方法,审查输出,甚至对输出进行建模并比较结果。
这门课程太棒了。我报名参加了 7 天课程,并且要购买这本书。我喜欢这个。
谢谢!
+1
谢谢。
在每页打印的 ML 课程开始的那个大广告是糟糕的广告!我已经在我的 Twitter feed 上多次引用了您的帖子,但除非纠正了,否则不再引用了!🙁
您具体指的是哪个大广告?
对于打印页面,也许这会有所帮助
https://machinelearning.org.cn/faq/single-faq/how-can-i-print-a-tutorial-page-without-the-sign-up-form
如何从给定段落中提取重要的关键词?
我认为这是一个非常难的问题。
您如何定义重要?
感谢您的发帖。
谢谢,很高兴对您有帮助。
大家好,
我有一个问题
我正在用 Python 编写脚本
with codecs.open(path_inc, ‘r’, ‘utf-8′, errors=’ignore’) as file_handle
for lineinc in file_handle
if flag1 == 0
flag1 = 1
continue
#print (lineinc)
word1 = lineinc.split()
if first == 0: #to store the current date we are doing first == 0
#print(word1[0])
current_date = word1[0]
#print(current_date)
first = 1
if current_date == word1[0]
#print(word1[:0])
#print(lineinc)
for item in Incidentnumberlist
if word1[5] == item
f1.write(“\nIncident ” + item + ” present in .inc file”)
else
break
我上面写了我的代码
它会打印输出
Incident 11-5171 present in .inc file
Incident 11-5171 present in .inc file
Incident 10-0210 present in .inc file
Incident 10-0210 present in .inc file
Incident 10-0210 present in .inc file
Incident 10-0210 present in .inc file
Incident 10-0210 present in .inc file
它正在打印重复的行
我不想要重复的行,如何删除它们?
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/can-you-read-review-or-debug-my-code
一次性使用 translate 处理整个文本,而不是逐字处理,这样会快得多,不是吗?
也许可以。
这很有帮助,感谢分享!
我对 Python 还很陌生,但这个教程让我很容易理解。在清理后导出新文件还有其他步骤吗?提前感谢。
谢谢,很高兴它能帮到你!
您可以直接将数组保存到文件,例如 savetext。
https://docs.scipy.org.cn/doc/numpy/reference/generated/numpy.savetxt.html
‘\ufeffOne morning, when Gregor Samsa woke from troubled dreams, he found\r\nhimself transformed in his bed into a horrible vermin.’
如何从文本中删除 feff,即使是 replace 也无效,编码也无效。请帮忙。
也许可以过滤掉非 ASCII 字符。
这是一个超级简单易懂且有用的教程——非常感谢。
谢谢!
我如何使用 ML 查找唯一的短信模板?
抱歉,我不明白。什么是短信模板?机器学习如何提供帮助?
您建议如何处理大型文本文档?
例如,太大了无法放入内存?您现在可以在 ec2 上使用大型机器……
我会使用渐进式加载,逐行处理文档,然后输出处理后的数据。
Jason,感谢您,这篇帖子非常棒!我有一个小问题:从分词开始文本预处理总是好的做法吗?我猜是肯定的,但需要验证,因为我阅读的关于挖掘社交媒体文本的文章中,许多似乎都从文本规范化开始(例如,转换为小写、删除俚语、用户 ID、空白符、将 URL 替换为“url”一词、创建自定义词典替换医学术语),然后继续分词。如果我要从在线论坛收集数据,是先分词再进行上述文本规范化技术更好吗?提前感谢!
从选择词汇表/清理开始,然后分词。
你好 Jason,我叫 Isak,来自印度尼西亚。所以,很抱歉我的英语不好。
我目前正在进行一项关于在投诉管理系统应用程序中使用文本挖掘的论文。我使用的方法是 SVM 和 One vs Rest(One vs All)方法,因为输出类别数为 6。
目的是对学生的愿望文本进行分类。分类结果用于确定校园内可以跟进愿望或投诉的单位或部门。
我想问的是关于预处理过程中的文本规范化阶段。
例如,对于关于互联网连接的愿望文本中的“slow”这个词。
在印度尼西亚语中,“slow”这个词在关于互联网的评论中可以翻译为“lamban”、“lambat”。印度尼西亚人也使用诸如“lag”之类的词。
是否需要更改/统一具有相同含义的词的形式?
例如:将“lamban”、“lambat”、“lag”等词更改为 1 个词(仅“lambat”)
上述案例是我数据集中的真实案例。使用词语:“lamban”、“lambat”和“lag”使我在预处理时感到困惑。
提前感谢!
不,有足够多的例子,模型就能有足够的上下文来区分不同的词语用法。
一般来说,像这样的手工修复非常脆弱。
你好,Jason!
感谢您的辛勤工作!您认为用更简单的对应词(例如 fi、‘、*)替换稀有的特定符号(例如 fi ’ ○)在普遍意义上有意义吗?对此有什么建议吗?
此致。
也许尝试一下,而不是完全删除它们,分别对模型进行拟合,看看哪个表现更好。
下载文本文件的链接已失效(我猜是因为我无法访问),卡夫卡的《变形记》纯文本 UTF-8。您能提供另一种获取文本文件的方法吗?谢谢!
这是帖子的直接链接,它工作正常
http://www.gutenberg.org/cache/epub/5200/pg5200.txt
Jason,感谢您的分享。
我需要您的建议
从 PDF 中提取文本时,如何最好地删除页眉和/或页脚?
注意:首先,我使用 XpdfReader 将所有 PDF 文件转换为文本,然后将它们导入 Python。
祝好。
不知道,也许可以尝试几种方法。
嗨,Jason,
感谢您提供的这个信息丰富的页面。我已经完成了这个练习,但是如何将输出保存到 CSV 文件中呢?假设我使用 pandas 在 Python 中加载了一个 CSV 文件,并对其中一个列应用了这些技术——现在如何保存这些更改并导出到 CSV?谢谢
这将帮助您将数组保存到文件
https://machinelearning.org.cn/how-to-save-a-numpy-array-to-file-for-machine-learning/
是否有关于将其他语言的字符音译成英语的帖子?我已经尝试使用 googletrans 进行翻译,但它并不可靠,因为它有时根本不翻译,有时会给出错误。还有 transdetect,我用它来检测语言并删除不等于“en”的内容。这两种方法都不奏效。请告知是否有任何可靠的方法。
也许从这里开始
https://machinelearning.org.cn/introduction-neural-machine-translation/
还有这里
https://machinelearning.org.cn/develop-neural-machine-translation-system-keras/
嗨 Jason
我正在尝试执行以下代码,但收到错误:“no display name and no $DISPLAY environment variable”。您能告诉我我缺少什么吗?错误出现在最后一行“named_entity.draw()”。
代码如下:
text= “the taj mahal was built by emperor shah jahan”
words=nltk.word_tokenize(text)
tagged_word_name=nltk.pos_tag(words)
named_entity=nltk.ne_chunk(tagged_word_name)
named_entity.draw()
很抱歉听到这个消息,也许可以尝试将您的代码和错误发布到 stackoverflow.com。
我只尝试使用 Regex 从文本文件中提取 Unicode 字符,并将它们单独存储在一个列表中以用于某些特定任务。对于像我一样刚开始 NLP 之旅的人来说,我会说,这太棒了。
谢谢 Jason!
干得好!
非常欢迎。
嗨,Jason,
我想问一个问题:词干提取有助于降低维度吗?我问这个问题是因为不同的来源提供了不同的答案。有些人说是,而另一些人说不是。我也问了 ChatGPT,它也说是。然而,当我尝试时,结果是否定的。所以,我仍然很困惑。
嗨 Nitesh……我们建议利用产生最高准确率的技术。
非常非常有趣,非常感谢亲爱的!
感谢您的支持和反馈 Muse!我们非常感激!