10 KiB
根据 Python 中的名称预测国籍
原文:https://www.askpython.com/python/examples/predict-nationality-using-names
嘿伙计们!在本教程中,我们将建立一个 RNN 和 LSTM 模型,帮助我们根据每个角色的名字来预测国籍。
让我们从了解我们拥有的数据集开始。
了解数据集
Dataset 是一个文本文件,包含每个行中用逗号分隔的人名和姓名的国籍。该数据集包含超过 2 万个名字和 18 个独特的国籍,如葡萄牙语、爱尔兰语、西班牙语等等。
数据的快照如下所示。你可以在这里下载数据集。
Dataset Snapshot Nationality Predictor
用 Python 中的人名预测国籍
让我们直接进入代码实现。我们将从导入模块开始,然后导入我们为本次演示选择的名称和国籍数据集。
第一步:导入模块
在开始构建任何模型之前,我们需要将所有需要的库导入到我们的程序中。
from io import open
import os, string, random, time, math
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from sklearn.model_selection import train_test_split
import torch
import torch.nn as nn
import torch.optim as optim
from IPython.display import clear_output
第二步:加载数据集
为了加载数据集,我们遍历数据中的每一行,并创建一个包含姓名和国籍的元组列表。这将使模型更容易理解后面部分中的数据。
languages = []
data = []
X = []
y = []
with open("name2lang.txt", 'r') as f:
#read the dataset
for line in f:
line = line.split(",")
name = line[0].strip()
lang = line[1].strip()
if not lang in languages:
languages.append(lang)
X.append(name)
y.append(lang)
data.append((name, lang))
n_languages = len(languages)
print("Number of Names: ", len(X))
print("Number of Languages: ",n_languages)
print("All Names: ", X)
print("All languages: ",languages)
print("Final Data: ", data)
Load Dataset Nationality Predictor
第三步:列车测试分割
我们将将数据按 80:20 的比例分成培训和测试,其中 80%的数据用于培训,其余 20%用于测试。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 123, stratify = y)
print("Training Data: ", len(X_train))
print("Testing Data: ", len(X_test))
Training Data: 16040
Testing Data: 4010
步骤 4:编码数据
字符编码将被用作序列模型的输入,而不是原始文本数据。因此,我们必须对输入进行加密,并在字符级别对其进行识别。
一旦我们在字符级创建了编码,我们需要连接所有的字符级编码来获得整个单词的编码。这一过程适用于所有姓名和国籍。
all_letters = string.ascii_letters + ".,;"
print(string.ascii_letters)
n_letters = len(all_letters)
def name_rep(name):
rep = torch.zeros(len(name), 1, n_letters)
for index, letter in enumerate(name):
pos = all_letters.find(letter)
rep[index][0][pos] = 1
return rep
上面的函数 name_rep 为名称生成一次性编码。首先,我们声明一个零张量,输入大小等于名字的长度,外部大小等于列表中的全部字符数。
接下来,我们循环遍历每个字符以标识字母的索引,并将该索引位置值设置为 1,其余值为 0。
def nat_rep(lang):
return torch.tensor([languages.index(lang)], dtype = torch.long)
对国籍进行编码遵循的逻辑比对姓名进行编码简单得多。我们只需确定特定国籍在我们的国籍列表中出现的索引,以对国籍进行编码。然后,索引被指定为编码。
第五步:建立神经网络模型
我们将使用 Pytorch 建立一个 RNN 模型,我们创建一个类来实现这个目标。
init 函数(构造函数)帮助我们初始化网络特征,例如与隐藏层相关的权重和偏差。
class RNN_net(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(RNN_net, self).__init__()
self.hidden_size = hidden_size
self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
self.i2o = nn.Linear(input_size + hidden_size, output_size)
self.softmax = nn.LogSoftmax(dim = 1)
def forward(self, input_, hidden):
combined = torch.cat((input_, hidden), 1)
hidden = self.i2h(combined)
output = self.i2o(combined)
output = self.softmax(output)
return output, hidden
def init_hidden(self):
return torch.zeros(1, self.hidden_size)
forward 函数首先连接角色的输入和隐藏表示,然后使用 i2h、i2o 和 softmax 层将其作为输入来计算输出标签。
def infer(net, name):
net.eval()
name_ohe = name_rep(name)
hidden = net.init_hidden()
for i in range(name_ohe.size()[0]):
output, hidden = net(name_ohe[i], hidden)
return output
n_hidden = 128
net = RNN_net(n_letters, n_hidden, n_languages)
output = infer(net, "Adam")
index = torch.argmax(output)
print(output, index)
网络实例和人名作为输入参数传递给 infer 函数。我们将网络设置为评估模式,并在此函数中计算输入人名的一键表示。
接下来,我们将根据隐藏大小计算隐藏表示,并在将计算的隐藏表示返回到网络之前循环所有字符。
最后,我们将计算输出,即这个人的国籍。
第六步:计算 RNN 模型的精度
在继续训练模型之前,让我们创建一个函数来计算模型的准确性。
为了达到同样的目的,我们将创建一个评估函数,将以下内容作为输入:
- 网络实例
- 数据点的数量
- k 的值
- x 和 Y 测试数据
def dataloader(npoints, X_, y_):
to_ret = []
for i in range(npoints):
index_ = np.random.randint(len(X_))
name, lang = X_[index_], y_[index_]
to_ret.append((name, lang, name_rep(name), nat_rep(lang)))
return to_ret
def eval(net, n_points, k, X_, y_):
data_ = dataloader(n_points, X_, y_)
correct = 0
for name, language, name_ohe, lang_rep in data_:
output = infer(net, name)
val, indices = output.topk(k)
if lang_rep in indices:
correct += 1
accuracy = correct/n_points
return accuracy
在函数内部,我们将执行以下操作:
- 使用
data loader加载数据。 - 迭代数据加载器中出现的所有人名。
- 对输入调用模型并获得输出。
- 计算预测类。
- 计算正确预测的类别总数
- 返回最终百分比。
第七步:训练 RNN 模型
为了训练模型,我们将编写一个简单的函数来训练我们的网络。
def train(net, opt, criterion, n_points):
opt.zero_grad()
total_loss = 0
data_ = dataloader(n_points, X_train, y_train)
for name, language, name_ohe, lang_rep in data_:
hidden = net.init_hidden()
for i in range(name_ohe.size()[0]):
output, hidden = net(name_ohe[i], hidden)
loss = criterion(output, lang_rep)
loss.backward(retain_graph=True)
total_loss += loss
opt.step()
return total_loss/n_points
def train_setup(net, lr = 0.01, n_batches = 100, batch_size = 10, momentum = 0.9, display_freq = 5):
criterion = nn.NLLLoss()
opt = optim.SGD(net.parameters(), lr = lr, momentum = momentum)
loss_arr = np.zeros(n_batches + 1)
for i in range(n_batches):
loss_arr[i + 1] = (loss_arr[i]*i + train(net, opt, criterion, batch_size))/(i + 1)
if i%display_freq == display_freq - 1:
clear_output(wait = True)
print("Iteration number ", i + 1, "Top - 1 Accuracy:", round(eval(net, len(X_test), 1, X_test, y_test),4), 'Top-2 Accuracy:', round(eval(net, len(X_test), 2, X_test, y_test),4), 'Loss:', round(loss_arr[i]),4)
plt.figure()
plt.plot(loss_arr[1:i], "-*")
plt.xlabel("Iteration")
plt.ylabel("Loss")
plt.show()
print("\n\n")
n_hidden = 128
net = RNN_net(n_letters, n_hidden, n_languages)
train_setup(net, lr = 0.0005, n_batches = 100, batch_size = 256)
在对 100 个批次的模型进行训练之后,我们能够利用 RNN 模型实现 66.5%的前 1 名准确度和 79%的前 2 名准确度。
Loss Plot Nationality Predictor
第八步:LSTM 模式培训
我们还将讨论如何实现 LSTM 模型来对人名的国籍进行分类。为了达到同样的目的,我们将使用 Pytorch 并创建一个自定义的 LSTM 类。
class LSTM_net(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(LSTM_net, self).__init__()
self.hidden_size = hidden_size
self.lstm_cell = nn.LSTM(input_size, hidden_size) #LSTM cell
self.h2o = nn.Linear(hidden_size, output_size)
self.softmax = nn.LogSoftmax(dim = 2)
def forward(self, input_, hidden):
out, hidden = self.lstm_cell(input_.view(1, 1, -1), hidden)
output = self.h2o(hidden[0])
output = self.softmax(output)
return output.view(1, -1), hidden
def init_hidden(self):
return (torch.zeros(1, 1, self.hidden_size), torch.zeros(1, 1, self.hidden_size))
n_hidden = 128
net = LSTM_net(n_letters, n_hidden, n_languages)
train_setup(net, lr = 0.0005, n_batches = 100, batch_size = 256)
在对 100 个批次的模型进行训练之后,我们能够利用 LSTM 模型实现 52.6%的前 1 名准确度和 66.9%的前 2 名准确度。
Loss Plot Nationality Predictor LSTM
结论
恭喜你!您刚刚学习了如何使用 Pytorch 构建国籍分类模型。希望你喜欢它!😇
喜欢这个教程吗?无论如何,我建议你看一下下面提到的教程:
感谢您抽出时间!希望你学到了新的东西!!😄



