人工智能模型训练:从不同格式文件中读取训练数据集

上一篇:《研发LLM模型,如何用数值表示人类自然语言?》

序言:人工智能数据工程师在采集数据时往往会使用不同的工具,因此最终得到的原始数据结构各不相同。市场上已知的数据采集和分析工具所输出的文件格式大致有几种。前面我们介绍了如何从谷歌的TFDS中提取支持的格式数据,今天将为大家讲解两类更常用的数据集文件格式:CSV和JSON结构化数据集。这些数据集的质量和组织方式在很大程度上决定了模型的质量和成功与否。

从CSV文件中读取文本

虽然TFDS有很多优秀的数据集,但它并不是包罗万象的,很多时候你需要自己管理数据的加载。NLP数据最常见的格式之一就是CSV文件。在接下来的几章中,你将使用一个我从开源的文本情感分析数据集改编的Twitter数据CSV文件。你将使用两个不同的数据集,一个用于二元分类,将情感简化为“positive”或“negative”,另一个则使用全范围的情感标签。每个数据集的结构是相同的,所以我只展示二元版本。

Python的csv库使得处理CSV文件变得简单。在这种情况下,数据存储在每行两个值的形式中。第一个值是一个数字(0或1),表示情感是消极还是积极。第二个值是一个包含文本的字符串。

以下代码将读取CSV文件并进行与我们在前一部分中相似的预处理。它会在复合词的标点符号周围添加空格,使用BeautifulSoup去除HTML内容,然后删除所有标点符号字符:

import csv

sentences = []

labels = []

with open('/tmp/binary-emotion.csv', encoding='UTF-8') as csvfile:

reader = csv.reader(csvfile, delimiter=",")

for row in reader:

labels.append(int(row[0]))

sentence = row[1].lower()

sentence = sentence.replace(",", " , ")

sentence = sentence.replace(".", " . ")

sentence = sentence.replace("-", " - ")

sentence = sentence.replace("/", " / ")

soup = BeautifulSoup(sentence)

sentence = soup.get_text()

words = sentence.split()

filtered_sentence = ""

for word in words:

word = word.translate(table)

if word not in stopwords:

filtered_sentence = filtered_sentence + word + " "

sentences.append(filtered_sentence)

这将为你提供一个包含35,327个句子的列表。

创建训练和测试子集

现在文本语料库已经读入到句子的列表中,你需要将其拆分为训练和测试子集以便训练模型。例如,如果你想使用28,000个句子进行训练,将其余的保留用于测试,可以使用以下代码:

training_size = 28000

training_sentences = sentences[0:training_size]

testing_sentences = sentences[training_size:]

training_labels = labels[0:training_size]

testing_labels = labels[training_size:]

现在你有了一个训练集,你需要从中创建词索引。以下是使用tokenizer创建最多包含20,000个单词的词汇表的代码。我们将句子的最大长度设为10个单词,将较长的句子从结尾截断,较短的句子在结尾填充,并使用“”来表示未出现在词汇表中的词:

vocab_size = 20000

max_length = 10

trunc_type = 'post'

padding_type = 'post'

oov_tok = ""

tokenizer = Tokenizer(num_words=vocab_size, oov_token=oov_tok)

tokenizer.fit_on_texts(training_sentences)

word_index = tokenizer.word_index

training_sequences = tokenizer.texts_to_sequences(training_sentences)

training_padded = pad_sequences(training_sequences, maxlen=max_length, padding=padding_type, truncating=trunc_type)

你可以通过查看training_sequences和training_padded来检查结果。例如,以下代码打印训练序列中的第一个项目,你可以看到它被填充到最大长度为10:

print(training_sequences[0])

print(training_padded[0])

输出示例:

[18, 3257, 47, 4770, 613, 508, 951, 423]

[18 3257 47 4770 613 508 951 423 0 0]

你还可以通过打印词索引来检查它:

print(word_index)

输出示例:

{'': 1, 'just': 2, 'not': 3, 'now': 4, 'day': 5, 'get': 6, 'no': 7, 'good': 8, 'like': 9, 'go': 10, 'dont': 11, ...}

在这些词中,你可能会考虑删除一些停用词,比如“like”和“dont”。检查词索引总是很有帮助。

从JSON文件中读取训练文本

另一种非常常见的文本文件格式是JavaScript对象表示法(JSON)。这是一种开放标准文件格式,经常用于数据交换,特别是与网络应用程序一起使用。它可读性强,设计为使用键/值对。因此,它特别适合带标签的文本。快速搜索Kaggle上的JSON数据集,会得到超过2500个结果。比如,著名的数据集斯坦福问答数据集(SQuAD)就是以JSON格式存储的。

JSON的语法非常简单,对象包含在花括号中,作为由逗号分隔的键/值对。例如,一个表示我名字的JSON对象是:

{

"firstName": "Laurence",

"lastName": "Moroney"

}

JSON还支持数组,类似于Python列表,使用方括号表示。如下所示:

[

{"firstName": "Laurence", "lastName": "Moroney"},

{"firstName": "Sharon", "lastName": "Agathon"}

]

对象也可以包含数组,因此这是完全有效的JSON:

[

{

"firstName": "Laurence",

"lastName": "Moroney",

"emails": ["lmoroney@gmail.com", "lmoroney@galactica.net"]

},

{

"firstName": "Sharon",

"lastName": "Agathon",

"emails": ["sharon@galactica.net", "boomer@cylon.org"]

}

]

一个较小的数据集是Rishabh Misra发布的用于讽刺检测的新闻标题数据集,存储在JSON中,非常有趣,可以在Kaggle上找到。该数据集收集了来自The Onion的讽刺新闻标题和来自HuffPost的正常新闻标题。

讽刺数据集的文件结构非常简单:

{

"is_sarcastic": 1或0,

"headline": 包含标题的字符串,

"article_link": 包含链接的字符串

}

数据集包含约26,000项,每行一个。为了使其在Python中更具可读性,我创建了一个版本,将这些项目包含在一个数组中,以便作为一个列表读取,用于本章的源代码。

读取JSON文件

Python的json库使读取JSON文件变得简单。由于JSON使用键/值对,你可以基于键索引内容。例如,对于讽刺数据集,你可以创建一个文件句柄指向JSON文件,使用json库打开它,进行可迭代操作,逐行读取每个字段,并使用字段名获取数据项。

代码如下:

import json

with open("/tmp/sarcasm.json", 'r') as f:

datastore = json.load(f)

for item in datastore:

sentence = item['headline'].lower()

label = item['is_sarcastic']

link = item['article_link']

这样就很容易像在本章中所做的那样创建句子和标签列表,然后对句子进行分词。你还可以在读取句子的同时进行预处理,删除停用词、HTML标签、标点符号等。以下是生成句子、标签和URL列表的完整代码,同时对句子进行清理,去除不需要的单词和字符:

with open("/tmp/sarcasm.json", 'r') as f:

datastore = json.load(f)

sentences = []

labels = []

urls = []

for item in datastore:

sentence = item['headline'].lower()

sentence = sentence.replace(",", " , ")

sentence = sentence.replace(".", " . ")

sentence = sentence.replace("-", " - ")

sentence = sentence.replace("/", " / ")

soup = BeautifulSoup(sentence)

sentence = soup.get_text()

words = sentence.split()

filtered_sentence = ""

for word in words:

word = word.translate(table)

if word not in stopwords:

filtered_sentence = filtered_sentence + word + " "

sentences.append(filtered_sentence)

labels.append(item['is_sarcastic'])

urls.append(item['article_link'])

与之前一样,可以将这些数据分为训练集和测试集。如果你希望使用数据集中的26,000项中的23,000项进行训练,可以这样操作:

training_size = 23000

training_sentences = sentences[0:training_size]

testing_sentences = sentences[training_size:]

training_labels = labels[0:training_size]

testing_labels = labels[training_size:]

要对数据进行分词并准备训练,可以遵循之前的步骤。在这里,我们再次指定词汇大小为20,000个单词,最大序列长度为10,在末尾进行截断和填充,并使用“OOV”标记表示未在词汇表中的词:

vocab_size = 20000

max_length = 10

trunc_type = 'post'

padding_type = 'post'

oov_tok = ""

tokenizer = Tokenizer(num_words=vocab_size, oov_token=oov_tok)

tokenizer.fit_on_texts(training_sentences)

word_index = tokenizer.word_index

training_sequences = tokenizer.texts_to_sequences(training_sentences)

padded = pad_sequences(training_sequences, padding='post')

print(word_index)

输出将是按词频排序的整个索引:

{'': 1, 'new': 2, 'trump': 3, 'man': 4, 'not': 5, 'just': 6, 'will': 7, 'one': 8, 'year': 9, 'report': 10, 'area': 11, 'donald': 12, ...}

希望这些相似的代码可以帮助你看到在为神经网络准备文本时可以遵循的模式。在下一章中,你将看到如何使用嵌入来构建文本分类器,而在第7章中,你将进一步探索循环神经网络。然后在第8章中,你将看到如何进一步增强序列数据,以创建一个可以生成新文本的神经网络!

总结,在这三节中,我们介绍了人工智能大语言模型生成自然语言的关键技术。其实,这并非神秘,只是当你不曾接触时不知如何下手,而当掌握方法后会发现并不复杂。现在,掌握了这些技能后,我们已准备好迈出下一步,学习如何从单词中推导出意义以及如何识别和处理语言中的情绪——这是理解自然语言的关键起点。

posted @ 2024-11-11 09:51  果冻人工智能  阅读(89)  评论(0编辑  收藏  举报