研发LLM模型,如何用数值表示人类自然语言?

上一篇:《人工智能——自然语言处理简介》
序言:人工智能大语言模型(LLM)如何理解人类的自然语言?这个过程的核心在于将文本转化为计算机能处理的数值形式,经过计算,最终达到对语言的理解。起初,我们只是简单的随便用一个数字来表示一个单词或一个词根,但随着研究深入,我们发现,不同的数值表达方式能显著提高模型对语言的理解效果。因此,在构建大语言模型(LLM)时,关键的一步是将人类语言转化成合适的数值表示,以便模型能够接收、处理并生成有效的输出。好了,让我们进入正题。
与真实数据源协同工作
现在你已经了解了获取句子、用词索引进行编码以及对结果进行序列化的基本知识,你可以通过使用一些著名的公共数据集,将其通过工具转换为易于序列化的格式来进一步提升技能。我们将从TensorFlow Datasets中的IMDb数据集开始,它的大部分处理工作已经为你完成了。之后,我们将亲自动手处理一个基于JSON的数据集以及几个包含情感数据的逗号分隔值(CSV)数据集!
从TensorFlow Datasets获取文本
我们在第4章探索过TFDS,因此如果你对本节中的某些概念不熟悉,可以回顾一下。TFDS的目标是尽可能简单地以标准化方式访问数据。它提供了多个基于文本的数据集,我们将探索imdb_reviews,这是一个包含5万条电影评论的IMDb数据集,每条评论的情感被标注为正面或负面。
下面的代码将加载IMDb数据集的训练集并逐项迭代,将包含评论的文本字段添加到名为imdb_sentences的列表中。每条评论由文本和表示情感的标签组成。注意,将tfds.load调用包裹在tfds.as_numpy中,确保数据以字符串而不是张量的形式加载:
imdb_sentences = []
train_data = tfds.as_numpy(tfds.load('imdb_reviews', split="train"))
for item in train_data:
imdb_sentences.append(str(item['text']))
获得句子后,可以像之前一样创建一个分词器并对它们进行拟合,还可以创建一组序列:
tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=5000)
tokenizer.fit_on_texts(imdb_sentences)
sequences = tokenizer.texts_to_sequences(imdb_sentences)
你还可以打印出你的词索引以查看:
print(tokenizer.word_index)
词索引过大无法全部显示,但以下是前20个词。注意,分词器按数据集中词的频率排列,因此“the”、“and”和“a”等常用词被索引:
{'the': 1, 'and': 2, 'a': 3, 'of': 4, 'to': 5, 'is': 6, 'br': 7, 'in': 8, 'it': 9, 'i': 10, 'this': 11, 'that': 12, 'was': 13, 'as': 14, 'for': 15, 'with': 16, 'movie': 17, 'but': 18, 'film': 19, "'s": 20, ...}
这些是停用词,如上一节所述。由于这些词出现频率最高且缺乏独特性,它们的存在会影响训练准确性。
此外,注意“br”也在列表中,因为它在该语料库中常用作HTML标签
。
你可以更新代码,使用BeautifulSoup移除HTML标签,添加字符串转换以移除标点符号,并从给定列表中删除停用词,如下所示:
from bs4 import BeautifulSoup
import string
stopwords = ["a", ..., "yourselves"]
table = str.maketrans('', '', string.punctuation)
imdb_sentences = []
train_data = tfds.as_numpy(tfds.load('imdb_reviews', split="train"))
for item in train_data:
sentence = str(item['text'].decode('UTF-8').lower())
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 + " "
imdb_sentences.append(filtered_sentence)
tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=25000)
tokenizer.fit_on_texts(imdb_sentences)
sequences = tokenizer.texts_to_sequences(imdb_sentences)
print(tokenizer.word_index)
注意,在处理之前将句子转换为小写,因为所有的停用词都存储为小写。现在打印出的词索引如下所示
{'movie': 1, 'film': 2, 'not': 3, 'one': 4, 'like': 5, 'just': 6, 'good': 7, 'even': 8, 'no': 9, 'time': 10, 'really': 11, 'story': 12, 'see': 13, 'can': 14, 'much': 15, ...}
可以看到现在比之前干净了许多。不过,仍有改进空间,我注意到在查看完整索引时,一些不常见的词在末尾显得无意义。评论者经常将词组合在一起,比如用连字符(“annoying-conclusion”)或斜杠(“him/her”),移除标点会错误地将这些词合并为一个词。
你可以添加代码,在句子创建后立即在这些字符周围添加空格
sentence = sentence.replace(",", " , ")
sentence = sentence.replace(".", " . ")
sentence = sentence.replace("-", " - ")
sentence = sentence.replace("/", " / ")
这样,类似“him/her”这样的组合词会被转换为“him / her”,然后/被去掉,分词后会成为两个词。这样可能会带来更好的训练效果。
现在你已经有了语料库的分词器,可以对句子进行编码。例如,前面章节的简单句子会变成这样
sentences = [
'Today is a sunny day',
'Today is a rainy day',
'Is it sunny today?'
]
sequences = tokenizer.texts_to_sequences(sentences)
print(sequences)
结果为:
[[516, 5229, 147], [516, 6489, 147], [5229, 516]]
如果解码,可以看到停用词已被删除,句子被编码为“today sunny day”、“today rainy day”和“sunny today”。
如果想在代码中解码,可以创建一个新字典,将键和值反转(即词索引中的键值对互换)并进行查找。代码如下:
reverse_word_index = dict(
[(value, key) for (key, value) in tokenizer.word_index.items()])
decoded_review = ' '.join([reverse_word_index.get(i, '?') for i in sequences[0]])
print(decoded_review)
这将输出:
today sunny day
使用IMDb子词数据集
TFDS还包含几个使用子词预处理的IMDb数据集。在这里,你不需要按词分割句子,它们已经按子词进行分割。使用子词是一种在按字母(少量低语义令牌)和按词(大量高语义令牌)之间的折中方法,通常可以非常有效地训练语言分类器。这些数据集还包含用于分割和编码语料库的编码器和解码器。
要访问它们,可以调用tfds.load并传入imdb_reviews/subwords8k或imdb_reviews/subwords32k,例如
(train_data, test_data), info = tfds.load(
'imdb_reviews/subwords8k',
split=(tfds.Split.TRAIN, tfds.Split.TEST),
as_supervised=True,
with_info=True
)
可以通过info对象访问编码器,这将帮助查看词汇量大小
encoder = info.features['text'].encoder
print('Vocabulary size: {}'.format(encoder.vocab_size))
输出8185,因为在此实例中词汇量由8,185个令牌组成。若想查看子词列表,可以使用encoder.subwords属性获取:
print(encoder.subwords)
输出类似以下内容
['the_', ', ', '. ', 'a_', 'and_', 'of_', 'to_', 's_', 'is_', 'br', 'in_', 'I_', 'that_', ...]
这里可以注意到,停用词、标点和语法在语料库中都有,还有像
这样的HTML标签。空格用下划线表示,因此第一个令牌是“the”。
若想编码字符串,可以使用编码器
sample_string = 'Today is a sunny day'
encoded_string = encoder.encode(sample_string)
print('Encoded string is {}'.format(encoded_string))
输出将是令牌列表
Encoded string is [6427, 4869, 9, 4, 2365, 1361, 606]
你的五个词被编码为七个令牌。查看令牌,可以用编码器的subwords属性返回一个数组。它是从零开始的,例如“Today”中的“Tod”编码为6427,是数组中的第6426项:
print(encoder.subwords[6426])
输出:
Tod
若要解码,可以使用编码器的decode方法:
encoded_string = encoder.encode(sample_string)
original_string = encoder.decode(encoded_string)
test_string = encoder.decode([6427, 4869, 9, 4, 2365, 1361, 606])
后面的代码行将产生相同的结果,因为encoded_string尽管名字如此,其实是一个和下一行硬编码的列表相同的令牌列表。
本节总结:本节主要介绍了如何将文本表达转化为计算机可理解的数字表达形式。 具体来说,就是通过TensorFlow Datasets对文本进行预处理,包括分词、去停用词等步骤,最终将文本转换为数字序列,为后续的自然语言处理任务做好准备;下一篇是这一篇的补充,主要讲述如何从CSV和JSON文件中提取文本用于训练模型。
研发LLM模型,如何用数值表示人类自然语言?的更多相关文章
- Generative Pre-trained Transformer(GPT)模型技术初探
一.Transformer模型 2017年,Google在论文 Attention is All you need 中提出了 Transformer 模型,其使用 Self-Attention 结构取 ...
- 千亿参数开源大模型 BLOOM 背后的技术
假设你现在有了数据,也搞到了预算,一切就绪,准备开始训练一个大模型,一显身手了,"一朝看尽长安花"似乎近在眼前 -- 且慢!训练可不仅仅像这两个字的发音那么简单,看看 BLOOM ...
- 【NLP】揭秘马尔可夫模型神秘面纱系列文章(三)
向前算法解决隐马尔可夫模型似然度问题 作者:白宁超 2016年7月11日22:54:57 摘要:最早接触马尔可夫模型的定义源于吴军先生<数学之美>一书,起初觉得深奥难懂且无什么用场.直到学 ...
- 模型的元数据Meta -- Django从入门到精通系列教程
该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...
- 三 Django模型层之Meta
模型的Meta选项 本文阐述所有可用的元数据选项,你可以在模型的Meta类中设置他们 Meta选项 abstract 如果为True,就表示抽象基类 app_label 如果模型在INSTALLED_ ...
- 自然语言处理中的N-Gram模型
N-Gram(有时也称为N元模型)是自然语言处理中一个非常重要的概念,通常在NLP中,人们基于一定的语料库,可以利用N-Gram来预计或者评估一个句子是否合理.另外一方面,N-Gram的另外一个作用是 ...
- django模型的元数据Meta
模型的元数据,指的是“除了字段外的所有内容”,例如排序方式.数据库表名.人类可读的单数或者复数名等等.所有的这些都是非必须的,甚至元数据本身对模型也是非必须的.但是,我要说但是,有些元数据选项能给予你 ...
- WPF在3D Cad模型中利用TextureCoordinates实现颜色渐变显示偏差值的变化
原文:WPF在3D Cad模型中利用TextureCoordinates实现颜色渐变显示偏差值的变化 注:最近在做3D机械模型重建方面的软件,需要根据光栅传感器采集的数据绘制3D图形,并显示出色差以及 ...
- 谷歌大脑提出:基于NAS的目标检测模型NAS-FPN,超越Mask R-CNN
谷歌大脑提出:基于NAS的目标检测模型NAS-FPN,超越Mask R-CNN 朱晓霞发表于目标检测和深度学习订阅 235 广告关闭 11.11 智慧上云 云服务器企业新用户优先购,享双11同等价格 ...
- python自定义小工具:密码匿名化、毫秒时间显示、人类易读字节
import base64 import time def timestamp2datems(timestamp): ''' 时间戳转为日期字串,精确到ms.单位s :param timestamp: ...
随机推荐
- WPF 模仿前端大佬写一个Hover效果
先看一下效果吧: 原博主的地址:[动画进阶]神奇的卡片 Hover 效果与 Blur 的特性探究 - ChokCoco - 博客园 (cnblogs.com) 原效果是一个css效果,我们采用WPF的 ...
- 远程连接 Ubuntu Desktop 桌面
在 Ubuntu 的 设置 > 系统 > 远程桌面 上打开 桌面共享 和 远程控制 选项. sudo apt install gnome-remote-desktop 未完待续 参考: S ...
- mysql 存储结构介绍及执行过程分析
MySQL体系结构介绍 1 mysql 的体系结构 MySQL整体的逻辑结构可以分为4层,客户层.服务层.存储引擎层.数据层 客户层 客户层:进行相关的连接处理.权限控制.安全处理等操作 服务层 服务 ...
- 详解JVM 内存结构与实战调优总结
详解JVM 内存结构与实战调优总结 GC优化案例做个总结: 1在进行GC优化之前,需要确认项目的架构和代码等已经没有优化空间.我们不能指望一个系统架构有缺陷或者代码层次优化没有穷尽的应用,通过GC优化 ...
- Vue3 比 Vue2 快的体现-第一部分
Vue3 比 Vue2 快的原因 首先体现在 Diff算法的优化上, Vue2 中的 虚拟DOM对比采用全量对比策略,这样的话每次渲染也就把静态dom节点做对比了.在Vue3 中 Diff算法 优化了 ...
- 小tips:CSS3中的background-clip属性(背景的裁剪区域)
CSS3中的background-clip属性,其主要是用来确定背景的裁剪区域,换句话说,就是如何控制元素背景显示区域. 语法如下: background-clip : border-box || p ...
- Angular 学习笔记 (Typescript 高级篇)
由于 typescript 越来越复杂. 所以特意开多一个篇幅来记入一些比较难的, 和一些到了一定程度需要知道的基础. 主要参考 https://basarat.gitbook.io/typescri ...
- Java Web 拾遗
许是年纪大了,老是回忆起以前的点点滴滴.翻看当初的代码,如同偶遇多年未见的前女友,曾经一起深入交流的情谊在颔首之间消散,令人烦躁. 今天就来聊聊老生常谈的 Java Web 开发.缘于一个简单的Spr ...
- [Tkey] 黑兔子,白兔子
CL-21 一般拿到这个题第一眼都应该能看出并查集,subtask1 是给并查集暴力修改的. 后面 subtask2 没有联通操作,是给纯线段树的,也算是启发正解了 再往下可以考虑操作 \(1\) 采 ...
- 2022年7月中国数据库排行榜:墨天轮榜单榜眼易主,PolarDB得分涨幅最大
信创元年,后起之秀,大有可为.2022年7月的 墨天轮中国数据库流行度排行榜 风起云涌,本月排行榜共有232个数据库参与排名,相比上月,新增 ShuangzhaoDB 数据库.榜单前十名的唯一变化是达 ...