动手学深度学习53 语言模型

news2024/11/15 16:02:43

动手学深度学习53 语言模型

  • 语言模型
  • 代码
  • QA

语言模型

核心:预测文本出现的概率
最常见应用:做预训练模型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当数据序列很长怎么办?常用n-gram 。
一元语法:马尔科夫假设tao=0 基本认为每一个字是独立的,不管前面的东西。
二元语法:马尔科夫假设tao=1 每一个字只与前一个字相关。例如:x3只依赖于x2…………
三元语法:马尔科夫假设tao=2 每一个字只与前两个字相关。例如:x3依赖于x2,x1,…………
最大的好处:可以处理很长的序列。每次看的序列是固定的。
n元语法,数据存储是指数关系 一元语法忽略掉了很多时序信息。n越大,空间复杂度越大。
在这里插入图片描述
n元语法:每次看n个子序列。
在这里插入图片描述

代码

num_steps: 时间t–tao
扫一遍数据,所有数据只用一次。问题:有数据可能访问不到。
每次把前k个数据扔掉,能遍历所有可能的数据?每次切的不一样。
X:两个长为num_steps=5的序列,Y:每个元素是对应X序列的后一个元素。
数据采样做法:
第一种做法:所有 min-batch采样都是独立的。
第二种做法:两个相邻小批量的数据是相邻的。数据是连续的,可以做更长的序列出来。

import random
import torch
from d2l import torch as d2l
import re

d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt', '090b5e7e70c295757f55df93cb0a180b9691891a')

def read_time_machine():
    """将时间机器数据集加载到文本行的列表中"""
    with open(d2l.download('time_machine'), 'r') as f:
        lines = f.readlines()
    return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]

tokens = d2l.tokenize(read_time_machine())
# 因为每个文本行不一定是一个句子或一个段落,因此我们把所有文本行拼接到一起
corpus = [token for line in tokens for token in line]
vocab = d2l.Vocab(corpus)
# print(vocab.token_freqs[:10])

freqs = [freq for token, freq in vocab.token_freqs]
d2l.plot(freqs, xlabel='token: x', ylabel='frequency: n(x)',
         xscale='log', yscale='log')

bigram_tokens = [pair for pair in zip(corpus[:-1], corpus[1:])]
# print(bigram_tokens)
# bigram_vocab = d2l.Vocab(bigram_tokens)
# print(bigram_vocab.token_freqs[:10])
trigram_tokens = [triple for triple in zip(corpus[:-2], corpus[1:-1], corpus[2:])]
trigram_vocab = d2l.Vocab(trigram_tokens)
print(trigram_vocab.token_freqs[:10])

bigram_freqs = [freq for token, freq in bigram_vocab.token_freqs]
trigram_freqs = [freq for token, freq in trigram_vocab.token_freqs]
d2l.plot([freqs, bigram_freqs, trigram_freqs], xlabel='token: x',
         ylabel='frequency: n(x)', xscale='log', yscale='log',
         legend=['unigram', 'bigram', 'trigram'])

def seq_data_iter_random(corpus, batch_size, num_steps):
    """使用随机抽样生成一个小批量子序列"""
    # 从随机偏移量开始对序列进行分区,随机范围包括num_steps-1
    corpus = corpus[random.randint(0, num_steps - 1):]
    # 减去1,是因为我们需要考虑标签
    num_subseqs = (len(corpus) - 1) // num_steps
    # 长度为num_steps的子序列的起始索引
    initial_indices = list(range(0, num_subseqs * num_steps, num_steps))
    # 在随机抽样的迭代过程中,
    # 来自两个相邻的、随机的、小批量中的子序列不一定在原始序列上相邻
    random.shuffle(initial_indices)

    def data(pos):
        # 返回从pos位置开始的长度为num_steps的序列
        return corpus[pos: pos + num_steps]

    num_batches = num_subseqs // batch_size
    for i in range(0, batch_size * num_batches, batch_size):
        # 在这里,initial_indices包含子序列的随机起始索引
        initial_indices_per_batch = initial_indices[i: i + batch_size]
        X = [data(j) for j in initial_indices_per_batch]
        Y = [data(j + 1) for j in initial_indices_per_batch]
        yield torch.tensor(X), torch.tensor(Y)

my_seq = list(range(35))
for X, Y in seq_data_iter_random(my_seq, batch_size=2, num_steps=5):
    print('X: ', X, '\nY:', Y)

def seq_data_iter_sequential(corpus, batch_size, num_steps):
    """使用顺序分区生成一个小批量子序列"""
    # 从随机偏移量开始划分序列
    offset = random.randint(0, num_steps)
    num_tokens = ((len(corpus) - offset - 1) // batch_size) * batch_size
    Xs = torch.tensor(corpus[offset: offset + num_tokens])
    Ys = torch.tensor(corpus[offset + 1: offset + 1 + num_tokens])
    Xs, Ys = Xs.reshape(batch_size, -1), Ys.reshape(batch_size, -1)
    num_batches = Xs.shape[1] // num_steps
    for i in range(0, num_steps * num_batches, num_steps):
        X = Xs[:, i: i + num_steps]
        Y = Ys[:, i: i + num_steps]
        yield X, Y

for X, Y in seq_data_iter_sequential(my_seq, batch_size=2, num_steps=5):
    print('X: ', X, '\nY:', Y)


class SeqDataLoader:
    """加载序列数据的迭代器"""
    def __init__(self, batch_size, num_steps, use_random_iter, max_tokens):
        if use_random_iter:
            self.data_iter_fn = d2l.seq_data_iter_random
        else:
            self.data_iter_fn = d2l.seq_data_iter_sequential
        self.corpus, self.vocab = d2l.load_corpus_time_machine(max_tokens)
        self.batch_size, self.num_steps = batch_size, num_steps

    def __iter__(self):
        return self.data_iter_fn(self.corpus, self.batch_size, self.num_steps)

def load_data_time_machine(batch_size, num_steps, use_random_iter=False, max_tokens=10000):
    """返回时光机器数据集的迭代器和词表"""
    data_iter = SeqDataLoader(
        batch_size, num_steps, use_random_iter, max_tokens)
    return data_iter, data_iter.vocab
Downloading ../data/timemachine.txt from http://d2l-data.s3-accelerate.amazonaws.com/timemachine.txt...
[('the', 2261), ('i', 1267), ('and', 1245), ('of', 1155), ('a', 816), ('to', 695), ('was', 552), ('in', 541), ('that', 443), ('my', 440)]
--------

排序报错待解决。
在这里插入图片描述
不调用d2l的Vocab,按照前面的代码重新写一份。

import random
import torch
from d2l import torch as d2l
import re
import collections

d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt', '090b5e7e70c295757f55df93cb0a180b9691891a')

def read_time_machine():
    """将时间机器数据集加载到文本行的列表中"""
    with open(d2l.download('time_machine'), 'r') as f:
        lines = f.readlines()
    return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]

tokens = d2l.tokenize(read_time_machine())

class Vocab:
    """
    文本词表
    min_freq:  出现少于多少次 就不管他 扔掉
    reserved_tokens: 标记句子开始或者结束的token
    """
    def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):
        if tokens is None:
            tokens = []
        if reserved_tokens is None:
            reserved_tokens = []
        # 按出现频率排序  对token排序
        counter = count_corpus(tokens)
        self._token_freqs = sorted(counter.items(), key=lambda x: x[1], reverse=True)
        # 未知词元的索引为0  unk 未知token <> NLP 常见的 token的一个表示方法
        self.idx_to_token = ['<unk>'] + reserved_tokens
        self.token_to_idx = {token: idx for idx, token in enumerate(self.idx_to_token)}
        # 把词数据全部count一遍,扔掉出现次数比较少的词
        for token, freq in self._token_freqs:
            if freq < min_freq:
                break
            if token not in self.token_to_idx:
                self.idx_to_token.append(token)
                self.token_to_idx[token] = len(self.idx_to_token) - 1

    def __len__(self):
        return len(self.idx_to_token)
     
    # 核心:getitem 根据给的token返回index
    def __getitem__(self, tokens):
        if not isinstance(tokens, (list, tuple)):
            return self.token_to_idx.get(tokens, self.unk)
        return [self.__getitem__(token) for token in tokens]
	# 核心: to_token 给index返回token
    def to_tokens(self, indices):
        if not isinstance(indices, (list, tuple)):
            return self.idx_to_token[indices]
        return [self.idx_to_token[index] for index in indices]

    @property
    def unk(self):  # 未知词元的索引为0
        return 0

    @property
    def token_freqs(self):
        return self._token_freqs

def count_corpus(tokens):
    """统计词元的频率"""
    # 这里的tokens是1D列表或2D列表
    if len(tokens) == 0 or isinstance(tokens[0], list):
        # 将词元列表展平成一个列表
        tokens = [token for line in tokens for token in line]
    return collections.Counter(tokens)

# 因为每个文本行不一定是一个句子或一个段落,因此我们把所有文本行拼接到一起
corpus = [token for line in tokens for token in line]
vocab = d2l.Vocab(corpus)
# print(vocab.token_freqs[:10])

freqs = [freq for token, freq in vocab.token_freqs]
d2l.plot(freqs, xlabel='token: x', ylabel='frequency: n(x)',
         xscale='log', yscale='log')

bigram_tokens = [pair for pair in zip(corpus[:-1], corpus[1:])]
# print(bigram_tokens)
bigram_vocab = Vocab(bigram_tokens)
# print(bigram_vocab.token_freqs[:10])
trigram_tokens = [triple for triple in zip(corpus[:-2], corpus[1:-1], corpus[2:])]
trigram_vocab = Vocab(trigram_tokens)
print(trigram_vocab.token_freqs[:10])

bigram_freqs = [freq for token, freq in bigram_vocab.token_freqs]
trigram_freqs = [freq for token, freq in trigram_vocab.token_freqs]
d2l.plot([freqs, bigram_freqs, trigram_freqs], xlabel='token: x',
         ylabel='frequency: n(x)', xscale='log', yscale='log',
         legend=['unigram', 'bigram', 'trigram'])

def seq_data_iter_random(corpus, batch_size, num_steps):
    """使用随机抽样生成一个小批量子序列"""
    # 从随机偏移量开始对序列进行分区,随机范围包括num_steps-1
    corpus = corpus[random.randint(0, num_steps - 1):]
    # 减去1,是因为我们需要考虑标签
    num_subseqs = (len(corpus) - 1) // num_steps
    # 长度为num_steps的子序列的起始索引
    initial_indices = list(range(0, num_subseqs * num_steps, num_steps))
    # 在随机抽样的迭代过程中,
    # 来自两个相邻的、随机的、小批量中的子序列不一定在原始序列上相邻
    random.shuffle(initial_indices)

    def data(pos):
        # 返回从pos位置开始的长度为num_steps的序列
        return corpus[pos: pos + num_steps]

    num_batches = num_subseqs // batch_size
    for i in range(0, batch_size * num_batches, batch_size):
        # 在这里,initial_indices包含子序列的随机起始索引
        initial_indices_per_batch = initial_indices[i: i + batch_size]
        X = [data(j) for j in initial_indices_per_batch]
        Y = [data(j + 1) for j in initial_indices_per_batch]
        yield torch.tensor(X), torch.tensor(Y)

my_seq = list(range(35))
for X, Y in seq_data_iter_random(my_seq, batch_size=2, num_steps=5):
    print('X: ', X, '\nY:', Y)

def seq_data_iter_sequential(corpus, batch_size, num_steps):
    """使用顺序分区生成一个小批量子序列"""
    # 从随机偏移量开始划分序列
    offset = random.randint(0, num_steps)
    num_tokens = ((len(corpus) - offset - 1) // batch_size) * batch_size
    Xs = torch.tensor(corpus[offset: offset + num_tokens])
    Ys = torch.tensor(corpus[offset + 1: offset + 1 + num_tokens])
    Xs, Ys = Xs.reshape(batch_size, -1), Ys.reshape(batch_size, -1)
    num_batches = Xs.shape[1] // num_steps
    for i in range(0, num_steps * num_batches, num_steps):
        X = Xs[:, i: i + num_steps]
        Y = Ys[:, i: i + num_steps]
        yield X, Y

for X, Y in seq_data_iter_sequential(my_seq, batch_size=2, num_steps=5):
    print('X: ', X, '\nY:', Y)


class SeqDataLoader:
    """加载序列数据的迭代器"""
    def __init__(self, batch_size, num_steps, use_random_iter, max_tokens):
        if use_random_iter:
            self.data_iter_fn = d2l.seq_data_iter_random
        else:
            self.data_iter_fn = d2l.seq_data_iter_sequential
        self.corpus, self.vocab = d2l.load_corpus_time_machine(max_tokens)
        self.batch_size, self.num_steps = batch_size, num_steps

    def __iter__(self):
        return self.data_iter_fn(self.corpus, self.batch_size, self.num_steps)

def load_data_time_machine(batch_size, num_steps, use_random_iter=False, max_tokens=10000):
    """返回时光机器数据集的迭代器和词表"""
    data_iter = SeqDataLoader(
        batch_size, num_steps, use_random_iter, max_tokens)
    return data_iter, data_iter.vocab
[(('the', 'time', 'traveller'), 59), (('the', 'time', 'machine'), 30), (('the', 'medical', 'man'), 24), (('it', 'seemed', 'to'), 16), (('it', 'was', 'a'), 15), (('here', 'and', 'there'), 15), (('seemed', 'to', 'me'), 14), (('i', 'did', 'not'), 14), (('i', 'saw', 'the'), 13), (('i', 'began', 'to'), 13)]
X:  tensor([[17, 18, 19, 20, 21],
        [27, 28, 29, 30, 31]]) 
Y: tensor([[18, 19, 20, 21, 22],
        [28, 29, 30, 31, 32]])
X:  tensor([[ 2,  3,  4,  5,  6],
        [22, 23, 24, 25, 26]]) 
Y: tensor([[ 3,  4,  5,  6,  7],
        [23, 24, 25, 26, 27]])
X:  tensor([[12, 13, 14, 15, 16],
        [ 7,  8,  9, 10, 11]]) 
Y: tensor([[13, 14, 15, 16, 17],
        [ 8,  9, 10, 11, 12]])
X:  tensor([[ 1,  2,  3,  4,  5],
        [17, 18, 19, 20, 21]]) 
Y: tensor([[ 2,  3,  4,  5,  6],
        [18, 19, 20, 21, 22]])
X:  tensor([[ 6,  7,  8,  9, 10],
        [22, 23, 24, 25, 26]]) 
Y: tensor([[ 7,  8,  9, 10, 11],
        [23, 24, 25, 26, 27]])
X:  tensor([[11, 12, 13, 14, 15],
        [27, 28, 29, 30, 31]]) 
Y: tensor([[12, 13, 14, 15, 16],
        [28, 29, 30, 31, 32]])

在这里插入图片描述

QA

在这里插入图片描述

1 数字会做embedding。
2 连续单词是有时序的,有先后顺序,不能打乱。
3 不存count为0的词,空间复杂度还是n–文本长度。
4 过滤掉长尾,不是长尾效应–电商名词。
在这里插入图片描述
5 n-gram 中文gram-字,n个字。也可用词。
6 T 序列的长度,每次看多长的序列。
7 把一对词做成一个token。广告中可以把特定产品映射成特定token。
8 T 16 32 不错选择,可以先试试。256 512长度都有。T根据模型复杂度考虑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1910204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

zabbix“专家坐诊”第245期问答

问题一 Q&#xff1a;vfs.dev.discovery拿的是哪里的文件&#xff0c;我看源码里面获取的是/proc/parttions里面的信息&#xff0c;但是我没有这个device&#xff0c;是怎么获取出来的&#xff1f; 在这里插入图片描述 A&#xff1a;检查下系统内核版本或者agent程序版本&…

收银系统源码

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 私有化独立部署/全开源源码&#xff0c;系统开发语言&#xff1a; 核心开发语言: PHP、HTML…

数据结构(初阶1)

文章目录 一、复杂度概念 二、时间复杂度 2.1 大O的渐进表示法 2.2 时间复杂度计算示例 2.2.1. // 计算Func2的时间复杂度&#xff1f; 2.2.2.// 计算Func3的时间复杂度&#xff1f; 2.2.3.// 计算Func4的时间复杂度&#xff1f; 2.2.4.// 计算strchr的时间复杂度&#xff1f; …

区间贪心

目录 1.贪心算法的思想 2.区间贪心算法常用的一些题目类型 1.选择最多不相交区间问题 P2970 [USACO09DEC] Selfish Grazing S 1.思路分析 2.上代码 2.区间选点问题 P1250 种树 1.题目 2.方法一 1.代码解释 3.方法二 3.区间合并问题 P2434 [SDOI2005] 区间 1. 思路…

容器docker

文章目录 前言一、docker1.1 为什么有docker1.2 docker架构1.3 docker 安装1.4 docker中央仓库1.5 docker 基本指令1.6 docker数据卷&#xff0c;挂载例&#xff1a;nginx 数据卷挂载例&#xff1a;mysql 本地持久化 1.7 镜像制作镜像结构dockerfile基础指令容器生成镜像 1.8 d…

JFlash读取和烧录加密stm32程序

JFlash读取和烧录加密stm32程序 安装后JFlash所在的目录&#xff1a;C:\Program Files\SEGGER\JLink 一、烧写加密程序 1、打开C:\Program Files\SEGGER\JLink目录&#xff0c;找到JFlash.exe,双击它&#xff0c;就可以打开该执行程序。见下图&#xff1a; 2、选择“Create …

Vue基础知识:Vue3.3出现的defineOptions,如何使用,解决了什么问题?

1.那么为什么会出现defineOptions? 原因说明&#xff1a; 有<script setup></script>语法糖应用之前&#xff0c;如果要定义 props&#xff0c;emits 可以轻而易举地添加一个与 setup 平级的属性。但是用了<script setup>后&#xff0c;就没法这么干了整个…

地理服务零成本:免费地图API合辑

在全球化和数字化不断推进的今天&#xff0c;地图已成为我们日常生活和工作中不可或缺的工具。无论是规划日常通勤、探索未知地域&#xff0c;还是进行地理数据分析&#xff0c;地图都发挥着至关重要的作用。它们不仅提供了地理信息的直观表示&#xff0c;还支持复杂的空间查询…

【U8+】登录U8时,选择账套登录窗口闪退。

【问题描述】 打开用友U8企业应用平台登录窗口&#xff0c; 输入账号和密码后&#xff0c;选择账套的时候闪退。 【解决方法】 方法一&#xff1a; 重装微软的silverlight&#xff0c;在U8soft\3rdprogram中有安装包。 注&#xff1a;不要自动更新此程序版本。关闭杀毒软件防火…

【线程安全】线程互斥的原理

文章目录 Linux线程互斥线程互斥相关概念互斥量mutex引出线程并发问题引出互斥锁、互斥量 互斥量的接口初始化互斥量销毁互斥量互斥量加锁和解锁使用互斥锁抢票 可重入和线程安全概念&#xff1a;常见线程不安全的情况常见线程安全的情况常见不可重入的情况常见可重入情况可重入…

jvm 05JVM - 对象的创建 ,oop模型,字符串常量池

01.JVM - 对象的创建 1、对象的创建的方式 Java语言中&#xff0c;对象创建的方式有六种&#xff1a; new关键字&#xff1a;最常见的形式、Xxx的静态方法、XxxBuilder、XxxFactory的静态方法。 Class类的newInstance()方法&#xff1a;通过反射的方式创建对象&#xff0c;调…

92. 反转链表 II (Swift 版本)

题目描述 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 分析 这是一个经典的链表问题&#xff0c;要求反转链表的部分节点。我们可以通过以下步骤实…

Codesys 连接 EtherCAT 总线伺服

本文内容是根据参考视频做的笔记&#xff1a; EtherCAT Master 控制&#xff1a;https://www.bilibili.com/video/BV1L14y1t7ks/EtherCAT Master Motion 控制&#xff1a;https://www.bilibili.com/video/BV16P411j71E/ EtherCAT 总线简单介绍 从站站号&#xff1a;如果使用扫…

【pytorch22】激活函数与GPU加速

激活函数 ReLu还是还是可能出现梯度弥散&#xff0c;因为x<0的时候&#xff0c;梯度还是可能小于0 leaky relu&#xff0c;在x<0的时候&#xff0c;梯度就不会为0&#xff0c;梯度不会不动 Relu函数在x0处是不连续的 一种更加光滑的曲线是SELU&#xff0c;是两个函数的…

ESXI6.7升级补丁报错VIB QLC_bootbank_qedrntv

1、报错如下图 2、原因 VMware在下方链接说的很清楚&#xff0c;报错原因为OEM提供的镜像与新版本补丁某些驱动不兼容&#xff1b; https://knowledge.broadcom.com/external/article?legacyId78487https://knowledge.broadcom.com/external/article?legacyId78487 3、解决 …

自动化立体仓库设计步骤:7步

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 完整版文件和更多学习资料&#xff0c;请球友到知识星球【智能仓储物流技术研习社】自行下载 这份文件是关于自动化立体仓库设计步骤的详细指南&#xff0c;其核心内容包括以下几个阶…

Git常用技能速成

文章目录 一.版本控制二.提交并推送代码三.提交推送代码 一.版本控制 接下来&#xff0c;我们就需要对我们的功能进行优化&#xff0c;但是需要说明的是&#xff0c;我们不仅仅要对上述提到的缓存进行优化&#xff0c;还需要对我们程序的各个方面进行优化。我们本章节主要是针…

mirthConnect 常用示例和语法整理

mirthConnect 常用示例和语法整理 1、jolt json常用语法 https://please.blog.csdn.net/article/details/140137463 2、常用方法 2.1 WinningDateUtils 所有的时间工具在WinningDateUtils里面 获取当前时间&#xff1a;var nowStrWinningDateUtils.getStandardNowStr()获取…

【C++】开源:格式化库fmt配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍格式化库fmt配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下…