深度学习实践(一)基于Transformer英译汉模型

2024-04-10 04:52

本文主要是介绍深度学习实践(一)基于Transformer英译汉模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文目录

  • 前述
  • 一、环境依赖
  • 二、数据准备
    • 1. 数据加载
    • 2. 构建单词表
      • 程序解析
        • (1)将列表里每个子列表的所有单词合并到一个新列表(没有子列表)中。
        • (2)Counter()-- 统计迭代对象各元素出现次数,并按次数从多到少排序
        • (3)获取出现频率最高的前 50000 个元素及其个数。
        • (4) 建立字典word_dict{ }:存放元素及其索引号
        • (5) 建立字典index_dict{ }---{ 索引号:元素 }
    • 3. 将英文、中文单词列表转为单词索引列表
    • 4. 划分batch
  • 三、模型搭建

前述

基础请查看:Transformer基础查看地址!

一、环境依赖

nltk==3.5
numpy==1.18.5
seaborn==0.11.1
matplotlib==3.3.2
psyco==1.6
zhtools==0.0.5#torch==1.12.1 安装torch时使用下面的命令
pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 torchaudio==0.12.1 --extra-index-url https://download.pytorch.org/whl/cu113 -i https://pypi.tuna.tsinghua.edu.cn/simple

代码导入包 :

import copy
import math
import matplotlib.pyplot as plt
import numpy as np
import os
import seaborn as sns
import time
import torch
import torch.nn as nn
import torch.nn.functional as Ffrom collections import Counter
from langconv import Converter
from nltk import word_tokenize
from torch.autograd import Variable

二、数据准备

  数据集可以去网络上下载,下面的是train.txt文件部分内容,前面为英文,后面为繁体中文,中间以'\t'隔开。其他数据文件也相同。
这里数据集是英文和繁体中文,所以第一步我们需要将繁体中文变为简体中文。
在这里插入图片描述

转换代码如下:

def cht_to_chs(sent):
"""" zh-hans" 是一个语言代码,用于指代中文(汉语)的简体字形式。在国际化和本地化领域,语言代码用于标识特定语言或语言变体。在这里,"zh" 表示汉语(中文),"hans" 表示简体字形式。因此,"zh-hans" 表示简体中文。"""sent = Converter("zh-hans").convert(sent) sent = sent.encode("utf-8")return sent

1. 数据加载

作用:读取数据路径下的完整句子,将每个句子分割为一个一个的单词,并存到子列表中。返回含有子列表的列表,

"""参数参数path 为数据的路径,如下train_file= 'nmt/en-cn/train.txt'  # 训练集dev_file= "nmt/en-cn/dev.txt"      # 验证集load_data(train_file)
"""def load_data(self, path):"""读取英文、中文数据对每条样本分词并构建包含起始符和终止符的单词列表"""en = []    #定义英文列表cn = []    #定义中文列表with open(path, mode="r", encoding="utf-8") as f:     #只读的形式打开文件路径,文件描述符为f。for line in f.readlines():          #按行读取sent_en, sent_cn = line.strip().split("\t")  #以‘\t’进行分割,前面的赋给sent_en,后面的赋给sent_cn 。sent_en = sent_en.lower()    #将英文转换为小写。sent_cn = cht_to_chs(sent_cn)  #将繁体中文转为简体中文。"""	word_tokenize() 是 NLTK库中的一个函数,用于将文本分词成单词(token)。它可以将一个句子或文本分解成一个个单词或标点符号,用于处理英文句子"""sent_en = ["BOS"] + word_tokenize(sent_en) + ["EOS"]# 中文按字符切分sent_cn = ["BOS"] + [char for char in sent_cn] + ["EOS"]en.append(sent_en)  #将切割好的英文 存入英文列表。包含['BOS', 'i', 'love', 'you', 'EOS']cn.append(sent_cn)  #将切割好的中文 存入中文列表。return en, cn    #返回两个单词列表"""
输出列表格式如下:en = [['BOS','I', 'love', 'natural', 'language', 'processing', '.', 'EOS'] ,['BOS', 'Natural', 'language', 'processing', 'is', 'fascinating', '.', 'EOS']]
"""	            

2. 构建单词表

"""输入参数train_en, train_cn = load_data(train_file)build_dict(train_en)  这里的输入为单词列表。输入列表如下:train_en= [['BOS','I', 'love', 'natural', 'language', 'processing', '.', 'EOS'] ,['BOS', 'Natural', 'language', 'processing', 'is', 'fascinating', '.', 'EOS']]
"""
PAD = 0                             # padding占位符的索引
UNK = 1                             # 未登录词标识符的索引
def build_dict(self, sentences, max_words=5e4):"""构造分词后的列表数据构建单词-索引映射(key为单词,value为id值)"""# 统计数据集中单词词频word_count = Counter([word for sent in sentences for word in sent])# 按词频保留前max_words个单词构建词典# 添加UNK和PAD两个单词ls = word_count.most_common(int(max_words))total_words = len(ls) + 2word_dict = {word [0]: index + 2 for index, word in enumerate(ls)}word_dict['UNK'] = UNKword_dict['PAD'] = PAD# 构建id2word映射index_dict = {v: k for k, v in word_dict.items()}return word_dict, total_words, index_dict

程序解析

(1)将列表里每个子列表的所有单词合并到一个新列表(没有子列表)中。

将sentences里面每句话的每个单词组合形成一个新的列表。

sentences = [['BOS''I', 'love', 'natural', 'language', 'processing', '.', 'EOS'] ,['BOS', 'Natural', 'language', 'processing', 'is', 'fascinating', '.', 'EOS']]word_list = [word for sent in sentences for word in sent]
"""
另一种写法:word_list = []for sent in sentences:for word in sent:word_list.append(word)
"""
print(word_list )
"""输出: ['BOS', 'I', 'love', 'natural', 'language', 'processing', '.', 'EOS', 'BOS', 'Natural', 'language', 'processing', 'is', 'fascinating', '.', 'EOS']
"""
(2)Counter()-- 统计迭代对象各元素出现次数,并按次数从多到少排序
from collections import Counter
#Python 中的一个内置数据结构
# 定义一个列表
word_list = ['BOS', 'I', 'love', 'natural', 'language', 'processing', '.', 'EOS', 'BOS', 'Natural', 'language', 'processing', 'is', 'fascinating', '.', 'EOS']
# 使用 Counter 统计列表中各元素的出现次数
word_count = Counter(word_list)
print(word_count )"""输出: Counter({'BOS': 2, 'language': 2, 'processing': 2, '.': 2, 'EOS': 2, 'I': 1, 'love': 1, 'natural': 1, 'Natural': 1, 'is': 1, 'fascinating': 1})
"""
(3)获取出现频率最高的前 50000 个元素及其个数。
from collections import Counterword_count = Counter({'BOS': 2, 'language': 2, 'processing': 2, '.': 2, 'EOS': 2, 'I': 1, 'love': 1, 'natural': 1, 'Natural': 1, 'is': 1, 'fascinating': 1})ls = word_count.most_common(int(5e4))#返回列表中频率最高的元素和它们的计数,按照计数从高到低排序。频率最高的前 50000 个元素。
print(ls)
"""
输出:[('BOS', 2), ('language', 2), ('processing', 2), ('.', 2), ('EOS', 2), ('I', 1), ('love', 1), ('natural', 1), ('Natural', 1), ('is', 1), ('fascinating', 1)]"""
(4) 建立字典word_dict{ }:存放元素及其索引号

enumerate(可迭代元素),返回的第一个值为索引,第二个值为元素。

ls = [('BOS', 2), ('language', 2), ('processing', 2), ('.', 2), ('EOS', 2), ('I', 1), ('love', 1), ('natural', 1), ('Natural', 1), ('is', 1), ('fascinating', 1)]word_dict = {word [0]: index + 2 for index, word in enumerate(ls)}"""另一种写法:word_dict = {}for index, word  in enumerate(ls):word_dict[ word[0] ] = index + 2print(word_dict)
"""
print(word_dict)  #存放元素及其索引号
"""输出: {'BOS': 2, 'language': 3, 'processing': 4, '.': 5, 'EOS': 6, 'I': 7, 'love': 8, 'natural': 9, 'Natural': 10, 'is': 11, 'fascinating': 12}
"""word_dict['UNK'] = 1
word_dict['PAD'] = 0
print(word_dict)
"""输出:{'BOS': 2, 'language': 3, 'processing': 4, '.': 5, 'EOS': 6, 'I': 7, 'love': 8, 'natural': 9, 'Natural': 10, 'is': 11, 'fascinating': 12, 'UNK': 1, 'PAD': 0}
"""
(5) 建立字典index_dict{ }—{ 索引号:元素 }
word_dict= {'BOS': 2, 'language': 3, 'processing': 4, '.': 5, 'EOS': 6, 'I': 7, 'love': 8, 'natural': 9, 'Natural': 10, 'is': 11, 'fascinating': 12, 'UNK': 1, 'PAD': 0}index_dict = {v: k for k, v in word_dict.items()}
print(index_dict)"""输出:{2: 'BOS', 3: 'language', 4: 'processing', 5: '.', 6: 'EOS', 7: 'I', 8: 'love', 9: 'natural', 10: 'Natural', 11: 'is', 12: 'fascinating', 1: 'UNK', 0: 'PAD'}
"""

3. 将英文、中文单词列表转为单词索引列表

  def word2id(self, en, cn, en_dict, cn_dict, sort=True):"""将英文、中文单词列表转为单词索引列表`sort=True`表示以英文语句长度排序,以便按批次填充时,同批次语句填充尽量少"""length = len(en)# 单词映射为索引out_en_ids = [[en_dict.get(word, UNK) for word in sent] for sent in en]out_cn_ids = [[cn_dict.get(word, UNK) for word in sent] for sent in cn]# 按照语句长度排序def len_argsort(seq):"""传入一系列语句数据(分好词的列表形式),按照语句长度排序后,返回排序后原来各语句在数据中的索引下标"""return sorted(range(len(seq)), key=lambda x: len(seq[x]))# 按相同顺序对中文、英文样本排序if sort:# 以英文语句长度排序sorted_index = len_argsort(out_en_ids)out_en_ids = [out_en_ids[idx] for idx in sorted_index]out_cn_ids = [out_cn_ids[idx] for idx in sorted_index]return out_en_ids, out_cn_ids

4. 划分batch

    def split_batch(self, en, cn, batch_size, shuffle=True):"""划分批次`shuffle=True`表示对各批次顺序随机打乱"""# 每隔batch_size取一个索引作为后续batch的起始索引idx_list = np.arange(0, len(en), batch_size)# 起始索引随机打乱if shuffle:np.random.shuffle(idx_list)# 存放所有批次的语句索引batch_indexs = []for idx in idx_list:"""形如[array([4, 5, 6, 7]), array([0, 1, 2, 3]), array([8, 9, 10, 11]),...]"""# 起始索引最大的批次可能发生越界,要限定其索引batch_indexs.append(np.arange(idx, min(idx + batch_size, len(en))))# 构建批次列表batches = []for batch_index in batch_indexs:# 按当前批次的样本索引采样batch_en = [en[index] for index in batch_index]batch_cn = [cn[index] for index in batch_index]# 对当前批次中所有语句填充、对齐长度# 维度为:batch_size * 当前批次中语句的最大长度batch_cn = seq_padding(batch_cn)batch_en = seq_padding(batch_en)# 将当前批次添加到批次列表# Batch类用于实现注意力掩码batches.append(Batch(batch_en, batch_cn))return batches

三、模型搭建

这篇关于深度学习实践(一)基于Transformer英译汉模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/890109

相关文章

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

Spring AI Alibaba接入大模型时的依赖问题小结

《SpringAIAlibaba接入大模型时的依赖问题小结》文章介绍了如何在pom.xml文件中配置SpringAIAlibaba依赖,并提供了一个示例pom.xml文件,同时,建议将Maven仓... 目录(一)pom.XML文件:(二)application.yml配置文件(一)pom.xml文件:首

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

python实现简易SSL的项目实践

《python实现简易SSL的项目实践》本文主要介绍了python实现简易SSL的项目实践,包括CA.py、server.py和client.py三个模块,文中通过示例代码介绍的非常详细,对大家的学习... 目录运行环境运行前准备程序实现与流程说明运行截图代码CA.pyclient.pyserver.py参

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、