赞
踩
数据集:
数据集里有人名和对应的国家,我们需要训练一个模型,输入一个新的名字,模型能预测出这个名字是基于哪种语言的(18种不同的语言,18分类)。
在自然语言处理中,通常的方式:
只需要输出最终的隐藏状态,然后最终的隐藏状态接一个线性层,然后分成18个类别。这样可以实现名字分类的任务。本节主要学习的就是处理自然语言过程的方法和流程。
整体的使用模型结构:
*
比如,Maclean这个名字,我们其实得到的是一个序列M a c l e a n,每一个字符其实就是x1,x2,x3,x4。依次类推,所以看上去我们只是名字一个字段,实际上它是一个序列,而且还有问题就是序列的长短是不一样的,所以我们还要思考序列长度不一致的问题。
模型处理过程:
主体代码:
if __name__ == '__main__':
# N_CHARS:序列的字符数 HIDDEN_SIZE:隐藏层尺寸 N_COUNTRY:国家的类别数 N_LAYES:GRU的层数
classifier = RNNClassication(N_CHARS,HIDDEN_SIZE,N_COUNTRY,N_LAYES)
# 使用GPU
if USE_GPU:
device = torch.device("cuda:0")
model.to(device)
# 优化器和损失函数
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr = 0.001)
# 计时
start = time.time()
print("Trainginng for {} epochs...".format(N_EPOCHS))
acc_list = []
for epoch in range(1,N_EPOCHS):
# 训练
trainModel()
# 测试
acc = testModel()
acc_list.append(acc)
# 计时模块
def time_since(since):
s = time.time() - since
m = math.floor(s/60)
s -= m*60
return "{} {}".format(m,s)
# 绘图模块
epoch = np.arange(1,len(acc_list)+1,1)
acc_list = np.array(acc_list)
plt.plot(epoch,acc_list)
plt.xlabel("Epoch")
plt.ylabel("Accuracy")
plt.grid()
plt.show()
- 字符串先转变成序列,转成字符列表,列表里面的每一个数就是名字里面的每一个字符。
- 再做词典,用ASCII表,ASCII表是128个字符,我们把字典长度设置成128,求每一个字符对应的ASCII值,拼成我们想要的序列。上图中的最右表中每一个数并不是一个数字,而是一个one-hot向量。例如77,就是一个128维的向量,第77个数的值为1,其他的值都是0。对于Embedding(嵌入层)来说,只要告诉嵌入层第几个维度是1就行了,所以只需要把ASCII值放在这就行了。
数据对齐,使得数据的长度一致,找出最长的,然后其余的补0。做完填充之后,可以保证构成一个张量。
# 准备数据集
class NameDataset(Dataset):
def __init__(self,is_train_set=True):
filename = 'names_train.csv.gz' if is_train_set else 'names_test.csv.gz'
with gzip.open(filename,'rt') as f: # 使用gzip读取gz文件
reader = csv.reader(f) # 使用csv读取里面内容
rows = list(reader) # 存到列表中,每一个都是元组(名字,国家)
self.names = [row[0] for row in rows] # 将名字存到列表中
self.len = len(self.name) # 记录长度
self.countries = [row[1] for row in rows] # 将国家存到列表中
self.countries_list = list(sorted(set(self.countries))) # 去重 排序 再存到列表
self.countries_dict = self.getCountryDict() # 设置一个字典进行查找国家
self.countries_num = len(self.countries_list) # 国家的类别数
def __getitem__(self, item):
return self.names[item],self.countries_dict[self.countries[item]] # 字典,key是国家名,value是index
def __len__(self):
return self.len
def getCountryDict(self): # 构造国家的查询字典
country_dict = dict()
for idx,country_name in enumerate(self.countries_list,0):
country_dict[country_name] = idx
return country_dict
def idx2country(self,index): # 根据索引返回国家的字符串
return self.countries_list[index]
def getCountriesNum(self): # 返回国家的数量
return self.countries_num
注意:上述代码读取数据集为什么不用Numpy?因为读取数据集有很多种方式,如果是pickle/HDFS/HD5类型的数据,要用相应的包。
trainset = NameDataset(is_train_set=True)
trainloader = DataLoader(dataset=trainset,batch_size=BATCH_SIZE,shuffle=True)
testset = NameDataset(is_train_set=False)
testloader = DataLoader(dataset=testset,batch_size=BATCH_SIZE,shuffle=False)
N_COUNTRY = trainset.getCountriesNum() # 决定模型最终输出的维度大小
GRU相关的参数:hidden_size和n_layers:
Embedding层的输入、输出维度:
GRU的输入、输出维度:
其中,bidrectional是双向循环神经网络
# 模型
class RNNClassication(nn.Module):
def __init__(self,input_size,hidden_size,output_size,n_layers=1,bidirectional = True):
super(RNNClassication, self).__init__()
self.hidden_size = hidden_size # GRU layer
self.n_layers = n_layers # GRU layer
self.n_directions = 2 if bidirectional else 1 #What is the Bi-Direction RNN/LSTM/GRU?
# The input of Embedding Layer with shape:声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/235417
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。