RNN经典案例——构建人名分类器

RNN经典案例——人名分类器

  • 一、数据处理
    • 1.1 去掉语言中的重音标记
    • 1.2 读取数据
    • 1.3 构建人名类别与人名对应关系字典
    • 1.4 将人名转换为对应的onehot张量
  • 二、构建RNN模型
    • 2.1 构建传统RNN模型
    • 2.2 构建LSTM模型
    • 2.3 构建GRU模型
  • 三、构建训练函数并进行训练
    • 3.1 从输出结果中获得指定类别函数
    • 3.2 随机生成训练数据
    • 3.3 构建传统的RNN训练函数
    • 3.4 构建LSTM训练函数
    • 3.5 构建GRU训练函数
    • 3.6 构建时间计算函数
    • 3.7 构建训练过程的日志打印函数
    • 3.8 调用train函数, 进行模型的训练
  • 四、构建评估模型并预测
    • 4.1 构建传统RNN评估函数
    • 4.2 构建LSTM评估函数
    • 4.3 构建GRU评估函数
    • 4.4 构建预测函数

一、数据处理

from io import open
import glob
import os
import string 
import unicodedata
import random
import time
import math
import torch
import torch.nn as nn
import matplotlib.pyplot as plt

1.1 去掉语言中的重音标记

# 获取常用字符数量和常用标点
all_letters = string.ascii_letters + " .,;'"
n_letters = len(all_letters)
print("all_letters:",all_letters)
print("n_letters:",n_letters)

在这里插入图片描述

# 去掉一些语言中的重音标记
# 如: Ślusàrski ---> Slusarski
def unicodeToAscii(s):ascii = ''.join(# NFD会将每个字符分解为其基本字符和组合标记,Ś会拆分为音掉和S#'Mn'这类字符通常用于表示重音符号、音调符号等c for c in unicodedata.normalize('NFD',s) if unicodedata.category(c) != 'Mn' and c in all_letters)return ascii

1.2 读取数据

# 读取数据
data_path = "./data/names/"def readLines(filename):lines = open(filename,encoding='utf-8').read().strip().split('\n')return [unicodeToAscii(line) for line in lines]
# 调试
filename = data_path + "Chinese.txt"
lines = readLines(filename)
print(lines)

在这里插入图片描述

1.3 构建人名类别与人名对应关系字典

# 类别名字列表
category_lines = {}
# 类别名称
all_category = []for filename in glob.glob(data_path + '*.txt'):category = os.path.splitext(os.path.basename(filename))[0]all_category.append(category)lines = readLines(filename)category_lines[category] = lines# 查看类别总数
n_categories = len(all_category)
print("n_categories:",n_categories)

在这里插入图片描述

1.4 将人名转换为对应的onehot张量

def lineToTensor(line):tensor = torch.zeros(len(line),1,n_letters)for i,letter in enumerate(line):tensor[i][0][all_letters.find(letter)] = 1return tensor  
# 调试
line = 'cui'
line_tensor = lineToTensor(line)
line_tensor

在这里插入图片描述

二、构建RNN模型

2.1 构建传统RNN模型

class RNN(nn.Module):def __init__(self,input_size,hidden_size,output_size,num_layers=1):super(RNN,self).__init__()self.hidden_size = hidden_sizeself.num_layers = num_layers# 实例化RNNself.rnn = nn.RNN(input_size,hidden_size,num_layers)# RNN 层的输出转换为最终的输出特征self.linear = nn.Linear(hidden_size,output_size)# 将全连接层的输出特征转换为概率分布self.softmax = nn.LogSoftmax(dim=-1)def forward(self,input,hidden):# input 形状为1*n_letters需要变换为三维张量input = input.unsqueeze(0)rr,hn = self.rnn(input,hidden)return self.softmax(self.linear(rr)),hn# 定义初始化隐藏状态def initHidden(self):return torch.zeros(self.num_layers,1,self.hidden_size)

2.2 构建LSTM模型

class LSTM(nn.Module):def __init__(self,input_size,hidden_size,output_size,num_layers=1):super(LSTM,self).__init__()self.hidden_size = hidden_sizeself.num_layers = num_layersself.lstm = nn.LSTM(input_size,hidden_size,num_layers)self.linear = nn.Linear(hidden_size,output_size)self.softmax = nn.LogSoftmax(dim=-1)def forward(self,input,hidden,c):input = input.unsqueeze(0)rr,(hn,c) = self.lstm(input,(hidden,c))return self.softmax(self.linear(rr)),hn,cdef initHidden(self):hidden = c = torch.zeros(self.num_layers,1,self.hidden_size)return hidden,c

2.3 构建GRU模型

class GRU(nn.Module):def __init__(self,input_size,hidden_size,output_size,num_layers=1):super(GRU,self).__init__()self.hidden_size = hidden_sizeself.num_layers = num_layersself.gru = nn.GRU(input_size,hidden_size,num_layers)self.linear = nn.Linear(hidden_size,output_size)self.softmax = nn.LogSoftmax(dim=-1)def forward(self,input,hidden):input = input.unsqueeze(0)rr,hn = self.gru(input,hidden)return self.softmax(self.linear(rr)),hndef initHidden(self):return torch.zeros(self.num_layers,1,self.hidden_size)
# 调用
# 实例化参数
input_size = n_letters
n_hidden = 128
output_size = n_categoriesinput = lineToTensor('B').squeeze(0)
hidden = c = torch.zeros(1,1,n_hidden)rnn = RNN(n_letters,n_hidden,n_categories)
lstm = LSTM(n_letters,n_hidden,n_categories)
gru = GRU(n_letters,n_hidden,n_categories)rnn_output, next_hidden = rnn(input, hidden)
print("rnn:", rnn_output)
lstm_output, next_hidden, c = lstm(input, hidden, c)
print("lstm:", lstm_output)
gru_output, next_hidden = gru(input, hidden)
print("gru:", gru_output) 

在这里插入图片描述

三、构建训练函数并进行训练

3.1 从输出结果中获得指定类别函数

def categoryFromOutput(output):# 从输出张量中返回最大的值和索引top_n,top_i = output.topk(1)category_i = top_i[0].item()# 获取对应语言类别, 返回语⾔类别和索引值return all_category[category_i],category_i
# 调试
category, category_i = categoryFromOutput(gru_output)
print("category:", category)
print("category_i:", category_i)

在这里插入图片描述

3.2 随机生成训练数据

def randomTrainingExample():# 随机获取一个类别category = random.choice(all_category)# 随机获取该类别中的名字line = random.choice(category_lines[category])# 将类别索引转换为tensor张量category_tensor = torch.tensor([all_category.index(category)],dtype=torch.long)# 对名字进行onehot编码line_tensor = lineToTensor(line)return category,line,category_tensor,line_tensor
# 调试
for i in range(10):category,line,category_tensor,line_tensor = randomTrainingExample()print('category =',category,'/ line =',line,'/ category_tensor =',category_tensor,'/ line_tensor =',line_tensor)

在这里插入图片描述

3.3 构建传统的RNN训练函数

# 定义损失函数
criterion = nn.NLLLoss()
# 设置学习率为0.005
learning_rate = 0.005
import torch.optim as optim
def trainRNN(category_tensor,line_tensor):# 实例化对象rnn初始化隐层张量hidden = rnn.initHidden()# 梯度清零optimizer = optim.SGD(rnn.parameters(),lr=0.01,momentum=0.9)optimizer.zero_grad()# 前向传播for i in range(line_tensor.size()[0]):# output 是 RNN 在每个时间步的输出。每个时间步的输出是一个隐藏状态,这些隐藏状态可以用于后续的处理,例如分类、回归等任务。# hidden是 RNN 在最后一个时间步的隐藏状态。这些隐藏状态可以用于捕获整个序列的信息,通常用于后续的处理,例如作为下一个层的输入。output,hidden = rnn(line_tensor[i],hidden)# 计算损失loss = criterion(output.squeeze(0),category_tensor)# 反向传播loss.backward()optimizer.step()# 更新模型中的参数#for p in rnn.parameters():#p.data.add_(-learning_rate,p.grad.data)return output,loss.item()

3.4 构建LSTM训练函数

def trainLSTM(category_tensor,line_tensor):hidden,c = lstm.initHidden()lstm.zero_grad()for i in range(line_tensor.size()[0]):output,hidden,c = lstm(line_tensor[i],hidden,c)loss = criterion(output.squeeze(0),category_tensor)loss.backward()for p in lstm.parameters():p.data.add_(-learning_rate,p.grad.data)return output,loss.item()

3.5 构建GRU训练函数

def trainGRU(category_tensor,line_tensor):hidden = gru.initHidden()gru.zero_grad()for i in range(line_tensor.size()[0]):output,hidden = gru(line_tensor[i],hidden)loss = criterion(output.squeeze(0),category_tensor)loss.backward()for p in gru.parameters():p.data.add_(-learning_rate,p.grad.data)return output,loss.item()

3.6 构建时间计算函数

# 获取每次打印的训练耗时
def timeSince(since):# 获得当前时间now = time.time()# 获取时间差s = now - since# 将秒转换为分m = s // 60# 计算不够1分钟的秒数s -= m * 60return '%dm %ds' % (m,s)

3.7 构建训练过程的日志打印函数

# 设置训练迭代次数
n_iters= 1000
# 设置结果的打印间隔
print_every = 50
# 设置绘制损失曲线上的打印间隔
plot_every = 10
def train(train_typr_fn):# 保存每个间隔的损失函数all_losses = []# 获得训练开始的时间戳start = time.time()# 设置当前间隔损失为0current_loss = 0# 循环训练for iter in range(1,n_iters+1):category,line,category_tensor,line_tensor = randomTrainingExample()output,loss = train_typr_fn(category_tensor,line_tensor)# 计算打印间隔的总损失current_loss += lossif iter % print_every == 0:# 获得预测的类别和索引guess,guess_i = categoryFromOutput(output)if guess == category:correct = '✓'else:correct = '✗(%s)' % categoryprint('%d %d%% (%s) %.4f %s / %s %s' % (iter, iter / n_iters *100, timeSince(start), loss, line, guess, correct))if iter % plot_every == 0:all_losses.append(current_loss / plot_every)current_loss = 0 return all_losses,int(time.time()-start)       

3.8 调用train函数, 进行模型的训练

# 调⽤train函数, 分别进⾏RNN, LSTM, GRU模型的训练
all_losses1, period1 = train(trainRNN)
all_losses2, period2 = train(trainLSTM)
all_losses3, period3 = train(trainGRU)

在这里插入图片描述

# 创建画布0
plt.figure(0)
# 绘制损失对⽐曲线
plt.plot(all_losses1, label="RNN")
plt.plot(all_losses2, color="red", label="LSTM")
plt.plot(all_losses3, color="orange", label="GRU")
plt.legend(loc='upper left')# 创建画布1
plt.figure(1)
x_data=["RNN", "LSTM", "GRU"]
y_data = [period1, period2, period3]
# 绘制训练耗时对⽐柱状图
plt.bar(range(len(x_data)), y_data, tick_label=x_data)

在这里插入图片描述
在这里插入图片描述

四、构建评估模型并预测

4.1 构建传统RNN评估函数

# 构建传统RNN评估函数
def evaluateRNN(line_tensor):hidden = rnn.initHidden()for i in range(line_tensor.size()[0]):output,hidden = rnn(line_tensor[i],hidden)return output.squeeze(0)

4.2 构建LSTM评估函数

# 构建LSTM评估函数
def evaluateLSTM(line_tensor):hidden,c = lstm.initHidden()for i in range(line_tensor.size()[0]):output,hidden,c = lstm(line_tensor[i],hidden,c)return output.squeeze(0)

4.3 构建GRU评估函数

# 构建GRU评估函数
def evaluateGRU(line_tensor):hidden = gru.initHidden()for i in range(line_tensor.size()[0]):output,hidden = gru(line_tensor[i],hidden)return output.squeeze(0)
# 调试
line = "Bai"
line_tensor = lineToTensor(line)rnn_output = evaluateRNN(line_tensor)
lstm_output = evaluateLSTM(line_tensor)
gru_output = evaluateGRU(line_tensor)
print("rnn_output:", rnn_output)
print("gru_output:", lstm_output)
print("gru_output:", gru_output)

在这里插入图片描述

4.4 构建预测函数

def predict(input_line,evaluate,n_predictions=3):print('\n> %s' % input_line)with torch.no_grad():output = evaluate(lineToTensor(input_line))topv,topi = output.topk(n_predictions,1,True)predictions = []for i in range(n_predictions):# 从topv中取出的output值value = topv[0][i].item()# 取出索引并找到对应的类别category_index = topi[0][i].item()# 打印ouput的值, 和对应的类别print('(%.2f) %s' % (value, all_category[category_index]))# 将结果装进predictions中predictions.append([value, all_category[category_index]])
for evaluate_fn in [evaluateRNN, evaluateLSTM, evaluateGRU]:print("-"*18)predict('Dovesky', evaluate_fn)predict('Jackson', evaluate_fn)predict('Satoshi', evaluate_fn)

在这里插入图片描述

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

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

相关文章

【可答疑】基于51单片机的智能台灯(含仿真、代码、报告、演示视频等)

✨哈喽大家好,这里是每天一杯冰美式oh,985电子本硕,大厂嵌入式在职0.3年,业余时间做做单片机小项目,有需要也可以提供就业指导(免费)~ 🐱‍🐉这是51单片机毕业设计100篇…

数据分析-28-交互式数据分析EDA工具和低代码数据科学工具

文章目录 1 数据分析的七步指南1.1 第一步:问题定义和数据采集1.2 第二步:数据清洗和预处理1.3 第三步:数据探索和分析1.4 第四步:模型建立和分析1.5 第五步:数据可视化1.6 第六步:结果解释和报告1.7 第七步:部署和维护1.8 基础的数据分析库1.9 低代码数据科学工具2 EDA…

STM32 通用定时器

一、概述 STM32内部集成了多个定时/计数器,根据型号不同,STM32系列芯片最多包含8个定时/计数器。其中,TIM6、TIM7为基本定时器,TIM2~TIM5为通用定时器,TIM1、TIM8为高级控制定时器。 1.定时器的类型 基本定时器通用定…

实战案例:结合大模型与爬虫技术实现12306智能查票系统

大语言模型,例如 GPT-4,拥有强大的知识储备和语言理解能力,能够进行流畅的对话、创作精彩的故事,甚至编写代码。然而,它们也面临着一些难以克服的困境,就像一个空有知识却无法行动的巨人 信息滞后&#xf…

Linux 之 安装软件、GCC编译器、Linux 操作系统基础

安装软件、GCC编译器、Linux 操作系统基础 学习任务: 安装 Vmware虚拟机、掌握Ubuntu 系统的使用认识 Ubuntu 操作系统的终端和 Shell掌握软件安装、文件系统、掌握磁盘管理与解压缩掌握 VIM 编辑器、Makefile 基本语法熟悉 Linux 常见指令操作 安装好开发软件&…

[Go语言快速上手]初识Go语言

目录 一、什么是Go语言 二、第一段Go程序 1、Go语言结构 注意 2、Go基础语法 关键字 运算符优先级 三、Go语言数据类型 示例 小结 一、什么是Go语言 Go语言,通常被称为Golang,是一种静态类型、编译型的计算机编程语言。它由Google的Robert Gr…

用HTML5+CSS+JavaScript庆祝国庆

用HTML5CSSJavaScript庆祝国庆 中华人民共和国的国庆日是每年的10月1日。 1949年10月1日,中华人民共和国中央人民政府成立,在首都北京天安门广场举行了开国大典,中央人民政府主席毛泽东庄严宣告中华人民共和国成立,并亲手升起了…

Vue3 中Ref的最佳实践

在vue3中如果我们需要获取一个响应式的变量,可以使用ref来定义一个变量。 const name ref( "" );name.value "test" 定义好后,就可以实现修改状态,更新UI的效果了。 在这个基础上,本文主要讨论跨组件时如何…

Discord:报错:A fatal Javascript error occured(解决办法)

按 Windows 键 R 并输入 %appdata% 选择 discord 文件夹并将其删除。 再次按 Windows 键 R 并输入 %LocalAppData% 选择 discord 文件夹并再次将其删除。 附加: 如果还不行,就通过官网下载吧,这个问题通过epic下载可能会有

Python并发编程挑战与解决方案

Python并发编程挑战与解决方案 并发编程是现代软件开发中的一项核心能力,它允许多个任务同时运行,提高程序的性能和响应速度。Python因其易用性和灵活性而广受欢迎,但其全局解释器锁(GIL)以及其他特性给并发编程带来了…

Docker面试-24年

1、Docker 是什么? Docker一个开源的应用容器引擎,是实现容器技术的一种工具,让开发者可以打包他们的应用以及环境到一个镜像中,可以快速的发布到任何流行的操作系统上。 2、Docker的三大核心是什么? 镜像:Docker的…

网络威胁情报技术的进步

网络威胁形势不断演变,必然导致防御者和攻击者之间持续展开军备竞赛。幸运的是,网络威胁情报 (CTI) 技术的进步为安全专业人员提供了强大的工具,使他们能够保持领先地位。 本指南深入探讨了 CTI 的最新进展,让您了解这些技术如何…

【学习笔记】手写一个简单的 Spring MVC

目录 一、什么是Spring MVC ? Spring 和 Spring MVC 的区别? Spring MVC 的运行流程? 二、实现步骤 1. DispatcherServlet 1. 创建一个中央分发器 拦截所有请求 测试 2. 接管 IOC 容器 1. 创建配置文件 2. 修改 web.xml 配置文件 …

1分钟搞懂K8S中的NodeSelector

文章目录 NodeSelector是什么?为什么使用NodeSelector?怎么用NodeSelector?POD配置示例yaml配置示例 如何知道K8S上面有哪些节点,每个节点都有什么信息呢?1. 使用kubectl命令行工具查看所有节点及其标签2. 使用kubectl…

算法【Java】—— 二叉树的深搜

深搜 深搜简单来说就是一直递归到底,然后返回,以二叉树为例,就是从根节点出发一直搜索到叶子节点,然后想上返回。 这里简单说明一下:深搜的英文缩写是 dfs,下面定义深搜函数名我直接命名为 dfs 实战演练 …

内存占用估算方法

优质博文:IT-BLOG-CN 通过掌握每种数据类型的大小,就可以更准确地预测对象和数据的内存消耗。 一、基础数据类型 Java基础数据类型结构,在64位系统开启指针压缩情况下的内存占用字节数: booleanbytecharshortintlongfloatdoub…

PYTHON实现HTTP request的一些有用的函数

前言 我们知道,当需要设计一个程序和服务器进行交互时,往往会用到HTTP的request,即服务器有一个对外接口REST API,因此当向服务器发送符合格式要求的HTTP request时,服务器会给出响应,甚至执行一些任务。如…

码随想录算法训练营第62天|卡码网:97. 小明逛公园、127. 骑士的攻击

1. 卡码网 97. 小明逛公园 题目链接:https://kamacoder.com/problempage.php?pid1155 文章链接:https://www.programmercarl.com/kamacoder/0097.小明逛公园.html 思路: 使用Floyd 算法,目的是解决多源最短路问题,即 …

如何编写一个优雅的commit message

在Git中,git commit 命令扮演着至关重要的角色。它的主要作用是将暂存区(staging area)里的改动内容提交到本地仓库(repository)中,形成一个新的版本或提交(commit)。这个过程是 Git…

基于Node2Vec的图嵌入实现过程

目录 一、引言二、Node2Vec(原理)2.1 随机游走(Random Walk)2.2 嵌入学习2.3 Node2Vec 的优势 三、使用 Node2Vec 进行图嵌入(实践)3.1 读取和转换 JSON 文件为 Graph 对象3.2 训练 Node2Vec 模型3.3 二维嵌…