我之前大致写了一篇在pytorch中如何自己定义数据集合,在这里如何自定义数据集

不过这个例子使用的是image,也就是图像。如果我们用到的是文本呢,处理的是NLP问题呢?

在解决这个问题的时候,我在网上无意间搜索到这样一篇文章PyTorch 入门实战(三)——Dataset和DataLoader

在这篇博文中,作者从dataset和dataloader一步步讲解,让我有了很大的感悟。然后我根据自己之前那篇文章,总结了一下如何在nlp问题中自定义数据集。

首先上一个简单的例子,

import torch
from torch.utils.data import Dataset, DataLoader
import numpy as np Data = np.array([[1, 2], [3, 4],[5, 6], [7, 8]])
Label = np.array([[0], [1], [0], [2]])
#创建子类
class subDataset(Dataset):
#初始化,定义数据内容和标签
def __init__(self, Data, Label):
self.Data = Data
self.Label = Label
#返回数据集大小
def __len__(self):
return len(self.Data)
#得到数据内容和标签
def __getitem__(self, index):
data = torch.Tensor(self.Data[index])
label = torch.IntTensor(self.Label[index])
return data, label dataset = subDataset(Data, Label)
print(dataset)
print('dataset大小为:', dataset.__len__())
print(dataset.__getitem__(0))
print(dataset[0]) #创建DataLoader迭代器
dataloader =DataLoader(dataset,batch_size= 2, shuffle = False, num_workers= 4)
for i, item in enumerate(dataloader):
print('i:', i)
data, label = item
print('data:', data)
print('label:', label) result: <__main__.subDataset object at 0x10b697198>
dataset大小为: 4
(tensor([1., 2.]), tensor([0], dtype=torch.int32))
(tensor([1., 2.]), tensor([0], dtype=torch.int32))
i: 0
data: tensor([[1., 2.],
[3., 4.]])
label: tensor([[0],
[1]], dtype=torch.int32)
i: 1
data: tensor([[5., 6.],
[7., 8.]])
label: tensor([[0],
[2]], dtype=torch.int32)

在上面这个例子中,需要特别注意的是我们定义的数据,使用的是数组形式。当我看到这一点的时候,我就很自然的联想到了这不不就是文本的数据形式吗?

每个句子通过一个向量代表,每个向量是一个数组的元素。

而且区别于图像,我们需要得到图像的路径,然后得到图像的数据,在文本这里,我们对句子向量化之后,这个数据可以直接被使用进来。

这就是为啥在子类中的__init__函数和__getitem__函数比较简单的原因。

所以我们只需要类别,把我们的句子向量转化为类似上面例子中Data的格式,Label转化为上面例子中的格式就好了。

接下来我们进入实践环节。

首先,我们从[这里(https://github.com/DA-southampton/cnn-lstm-bilstm-deepcnn-clstm-in-pytorch/tree/master/Data)中的训练数据中截取了2000条保存下来,作为我们的训练数据,命名为train.txt。

数据形式大概是这样的:A lovely film for the holiday season . ||| 3

接下来上代码:

#首先读取数据集合,并且构建词汇表格
file = open('train.txt','r') i = 0
data,tag,sentence_lst = [],[],[]
word_to_idx,idx_to_word = {},{} for line in file:
lst=line.strip().split('|||')
if len(lst)!=2: #确保上一步拆分成句子和类别的元素才进行下面的操作,保证成功
continue
sentence,label= lst[0],lst[1] #提取出句子和类别
words=sentence.split(' ')#在中文中,这一步可以使用结巴分词操作
for word in words:
if word not in word_to_idx:
word_to_idx[word] = i
idx_to_word[i] = word
i=i+1
sentence_lst.append(word_to_idx[word])
if (len(sentence_lst)>=50):
break
for j in range(50-len(sentence_lst)):
sentence_lst.append(0) #这之上的操作完成了两件事情,一个是构建词汇表,二就是将句子向量化
data.append(sentence_lst)
tag.append([int(label)])
sentence_lst = [] #将list转化为数组
data=np.array(data)
tag=np.array(tag) #这个步骤很重要,就是把我们生成的list转化为数组的形式 import torch
from torch.utils.data import Dataset, DataLoader
import numpy as np Data =data
Label = tag
#创建子类
class subDataset(Dataset):
#初始化,定义数据内容和标签
def __init__(self, Data, Label):
self.Data = Data
self.Label = Label
#返回数据集大小
def __len__(self):
return len(self.Data)
#得到数据内容和标签
def __getitem__(self, index):
data = torch.Tensor(self.Data[index])
label = torch.IntTensor(self.Label[index])
return data, label dataset = subDataset(Data, Label)
print(dataset)
print('dataset大小为:', dataset.__len__())
print(dataset.__getitem__(0))
print(dataset[0]) #创建DataLoader迭代器
dataloader =DataLoader(dataset,batch_size= 100, shuffle = False, num_workers= 4)
for i, item in enumerate(dataloader):
print('i:', i)
data, label = item
print('data:', data)
print('label:', label)

这样,我们就自己定义了一个数据集合并且使用dataloader将其切分。

data.size()
torch.Size([99, 50])#为啥是99呢,因为切分到最后不够100个了。这里不用纠结,大小就是batch_size * seq_length label.size()
torch.Size([99, 1]) #

我们知道这里data就是我们在训练模型的时候的输入,对于这个输入我们的维度是这样的batch_size * seq_length,这一点时参考的How to correctly give inputs to Embedding, LSTM and Linear layers in PyTorch?

这里我们得到的data正合适是符合这个size的,所以我可以把这个数据带入到模型中去。

textcnn 模型

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable class Textcnn(nn.Module):
def __init__(self,vocabulary_size,embedding_dim,kernel_num,batch_size,class_size,dropout):
super(Textcnn,self).__init__()
self.embedding = nn.Embedding(vocabulary_size,embedding_dim)
self.conv1 = nn.Conv2d(1,kernel_num,(3,embedding_dim))
self.conv2 = nn.Conv2d(1,kernel_num,(4,embedding_dim))
self.conv3 = nn.Conv2d(1,kernel_num,(5,embedding_dim))
self.dropout = nn.Dropout(dropout)
self.fc = nn.Linear(3*kernel_num,class_size) def conv_maxplooing1(self,x):
x = F.relu(self.conv1(x)) #(batch_size*kernel_num*(vocabulary_len-3+1)*1)
x = x.squeeze(3) #(batch_size*kernel_num*(vocabulary_len-3+1))
x = F.max_pool1d(x,x.size(2)).squeeze(2) #(batch_size*kernel_num)
return x
def conv_maxplooing2(self,x):
x = F.relu(self.conv2(x)) #(batch_size*kernel_num*(vocabulary_len-3+1)*1)
x = x.squeeze(3) #(batch_size*kernel_num*(vocabulary_len-3+1))
x = F.max_pool1d(x,x.size(2)).squeeze(2) #(batch_size*kernel_num)
return x
def conv_maxplooing3(self,x):
x = F.relu(self.conv3(x)) #(batch_size*kernel_num*(vocabulary_len-3+1)*1)
x = x.squeeze(3) #(batch_size*kernel_num*(vocabulary_len-3+1))
x = F.max_pool1d(x,x.size(2)).squeeze(2) #(batch_size*kernel_num)
return x def forward(self,x):
emb = self.embedding(x) #(batch_size*vocabulary_len*embedding_dim)
emb = emb.unsqueeze(1) #(batch_size*1*vocabulary_len*embedding_dim)
out1 = self.conv_maxplooing1(emb) #(batch_size*kernel_num)
out2 = self.conv_maxplooing2(emb)
out3 = self.conv_maxplooing3(emb)
out = torch.cat((out1,out2,out3),1) #(batch_size*(kernel_num*3))
out = self.dropout(out)
result = self.fc(out) #(batch_size*class_size)
return result

但是令人惊讶的是,在带入data的时候,出现了错误,错误代码大致是这样的:Expected tensor for argument #1 'indices' to have scalar type Long; but got CPUFloatTensor instead (while checking arguments for embedding)

就是讲,你这个输入tesor格式不对,应该long,而不是float

于是我要进行一个操作

data=data.long()
label=label.squeeze(1).long() ##注意这里我们把label去除了一个维度,通过上面我们知道,label维度本来是99*1,也就是这样的[[1],[2],[3]...],我们需要把它转化为这种[1,2,3...]才能在模型中使用
for i, item in enumerate(dataloader):
data, label = item
data=data.long()
label=label.squeeze(1).long()
outputs = model(sentence.long())
loss = criterion(outputs, label.squeeze(1).long())

具体详细的展示我会弄一个ipynb

如何在nlp问题中定义自己的数据集的更多相关文章

  1. [ROR] 如何在mixin模块中定义类方法(Howto define class methods in a mixin module)

    方法一: 修改模块的include方法 module Bbq def self.included(base) base.send :include, InstanceMethods base.exte ...

  2. 如何在ALV_Grid的函数中定义下拉列表

    转自 http://www.cnblogs.com/VerySky/articles/2392262.htmlABAP--如何在ALV_Grid的函数中定义下拉列表 REPORT. ********* ...

  3. 如何在WPF中定义窗体模板

    参考网址:https://www.cnblogs.com/chenxizhang/archive/2010/01/10/1643676.html可以在app.xaml中定义一个ControlTempl ...

  4. 如何在NLP领域第一次做成一件事

    作者简介 周明,微软亚洲研究院首席研究员.ACL候任主席(president).中国计算机学会中文信息技术专委会主任.中国中文信息学会常务理事.哈工大.天津大学.南开大学.山东大学等多所学校博士导师. ...

  5. [Laravel-Swagger]如何在 Laravel 项目中使用 Swagger

    如何在 Laravel 项目中使用 Swagger http://swagger.io/getting-started/ 安装依赖 swagger-php composer require zirco ...

  6. 如何在 ETL 项目中统一管理上百个 SSIS 包的日志和包配置框架

    一直准备写这么一篇有关 SSIS 日志系统的文章,但是发现很难一次写的很完整.因为这篇文章的内容可扩展的性太强,每多扩展一部分就意味着需要更多代码,示例和理论支撑.因此,我选择我觉得比较通用的 LOG ...

  7. 如何在JDK1.8中愉快地处理日期和时间

    如何在JDK1.8中愉快地处理日期和时间 JDK1.8新增了LocalDate和LocalTime接口,为什么要搞一套全新的处理日期和时间的API?因为旧的java.util.Date实在是太难用了. ...

  8. 如何在C语言中调用Swift函数

    在Apple官方的<Using Swift with Cocoa and Objectgive-C>一书中详细地介绍了如何在Objective-C中使用Swift的类以及如何在Swift中 ...

  9. PHP字符串中的变量解析(+教你如何在PHP字符串中加入变量)

    定义字符串的时候,用单引号或者双引号都是可以的.我个人习惯是用双引号.在输出字符串的时候,若字符串中含有字符串变量,使用单引号和双引号则是有区别的.如下面程序: 1 2 3 4 5 6 7 8 < ...

随机推荐

  1. Ajax异步封装

    //自己封装了一个异步方法. //第一个参数:GET或者是POST,二个参数:请求的url地址, //第三个:是否异步第四个:往后台发送的Post的数据,最后一个后台返回数据之后,处理数据的回调函数. ...

  2. 关于hibernate save方法未能存储数据入库的处理过程

    关于hibernate save方法未能存储数据入库的处理过程2018年04月18日 10:57:49 守望dfdfdf 阅读数:230更多个人分类: 工作 问题编辑版权声明:本文为博主原创文章,转载 ...

  3. Version Control&Git

    首先了解一下什么是版本控制: Version control (版本控制)是指对软件开发过程中各种程序代码.配置文件及说明文档等文件变更的管理,是软件配置管理的核心思想之一. 其次版本控制最主要的功能 ...

  4. 从零开始的全栈工程师——js篇2.19(BOM)

    一.BOM 浏览器对象模型 1.window.open(url,ways) url 是打开的网页地址ways 打开的方式 _self 2.window.close() 关闭当前页面 3.window. ...

  5. JS的函数参数传递为值传递

    function setAge(i) { alert(i);//24 i = 18; alert(i);//18,i的改变不会影响外面的age }; var age = 24; setAge(age) ...

  6. Java I/O 工作机制(二) —— Java 的 I/O 的交互方式分析

    简介: BIO:同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善.  ...

  7. java 网络流 TCP/UDP

    一.ServerSocket java.lang.Object |-java.net.ServerSocket 有子类SSLServerSocket. 此类实现服务器套接字.服务器套接字等待请求通过网 ...

  8. 前端高质量知识(一)-JS内存空间详细图解

    变量对象与堆内存   var a = 20;   var b = 'abc';   var c = true;   var d = { m: 20 } 因为JavaScript具有自动垃圾回收机制,所 ...

  9. 剑指offer28 字符串的排列

    1.全局变量可以在最后去定义并初始化,不一定非要在开头 2.此题有一种特殊情况需要考虑,比如字符串是“aa”,那输出应该是“aa”,而不是“aa,aa”,即相同的不输出.实现这个处理用了c++中的容器 ...

  10. Python IDE PyCharm的快捷键大全

    Python IDE PyCharm的快捷键大全 1.编辑(Editing) Ctrl + Space 基本的代码完成(类.方法.属性) Ctrl + Alt + Space 快速导入任意类 Ctrl ...