本项目配套讲解博客:[文本分类(LSTM+PyTorch)](https://blog.csdn.net/Bat_Reality/article/details/128509050?spm=1001.2014.3001.5502)
### 一、传统方法的基本步骤
1. 预处理:首先进行分词,然后是除去停用词;
2. 将文本表示成向量,常用的就是文本表示向量空间模型;
3. 进行特征选择,这里的特征就是词语,去掉一些对于分类帮助不大的特征。常用的特征选择的方法是词频过滤,互信息,信息增益,卡方检验等;
4. 接下来就是构造分类器,在文本分类中常用的分类器一般是SVM,朴素贝叶斯等;
5. 训练分类器,后面只要来一个文本,进行文本表示和特征选择后,就可以得到文本的类别。
### 二、深度学习与传统方法的区别
传统做法主要问题的文本表示是高纬度高稀疏的,特征表达能力很弱;此外需要人工进行特征工程,成本很高。
利用深度学习做文本分类,首先还是要进行分词,这是做中文语料必不可少的一步,这里的分词使用的jieba分词。 词语的表示不用one-hot编码,而是使用词向量(word embedding),现在最常用的词向量的分布式表示就是word2vec,这样的分布式表示,既降低了维度,也体现了语义信息。使用深度学习进行文本分类,不需要进行特征选择这一步,因为深度学习具有自动学习特征的能力。
### 三、LSTM文本分类
先将句子进行分词,然后将每个词语表示为词向量,再将词向量按顺序送进LSTM,最后LSTM的输出就是这段话的表示,而且能够包含句子的时序信息。
![LSTM文本分类流程图](https://img-blog.csdnimg.cn/d7618d3cb1ce47459b3250a494c30973.png)
##### 1. 处理数据集
```python
# utils.py
def read_file(path):
"""
读取文本文件进行预处理
:param path: 文件路径
:return: 分词后的数组
"""
if 'training_label' in path:
with open(path, 'r', encoding='utf-8') as file:
lines = file.readlines()
lines = [line.strip('\n').split(' ') for line in lines]
x = [line[2:] for line in lines]
y = [line[0] for line in lines]
return x, y
elif 'training_nolabel' in path:
with open(path, 'r', encoding='utf-8') as file:
lines = file.readlines()
x = [line.strip('\n').split(' ') for line in lines]
return x
else:
with open(path, 'r', encoding='utf-8') as file:
lines = file.readlines()
x = ["".join(line[1:].strip('\n').split(",")) for line in lines[1:]]
x = [item.split(' ') for item in x]
return x
```
### 2. word2vec词向量模型
依据原始数据提取了data与labels之后,还需要依据文本生成词向量,即建立单词与向量的一一对应关系,同时建立词汇之间的语义联系。
```python
# word2vec.py
from gensim.models import word2vec
import os
from utils import read_file
def train_word2vec(x):
"""
LineSentence(inp):格式简单:一句话=一行; 单词已经过预处理并被空格分隔。
size:是每个词的向量维度;
window:是词向量训练时的上下文扫描窗口大小,窗口为5就是考虑前5个词和后5个词;
min-count:设置最低频率,默认是5,如果一个词语在文档中出现的次数小于5,那么就会丢弃;
sg ({0, 1}, optional) – 模型的训练算法: 1: skip-gram; 0: CBOW
iter (int, optional) – 迭代次数,默认为5
:param x: 处理好的数据集
:return: 训练好的模型
"""
return word2vec.Word2Vec(x, size=300, window=5, min_count=5, sg=1, iter=10)
if __name__ == '__main__':
data_dir = './data'
print("loading training data ...")
train_x, y = read_file(os.path.join(data_dir, 'training_label.txt'))
train_no_label = read_file(os.path.join(data_dir, 'training_nolabel.txt'))
print("loading test data...")
test_data = read_file(os.path.join(data_dir, 'testing_data.txt'))
print("training text data and transforming to vectors by skip-gram...")
model = train_word2vec(train_x + train_no_label + test_data)
print("saving model...")
model.save(os.path.join(data_dir, 'word2vec.model'))
```
### 3. 数据预处理
数据预处理就是按照词向量对样本中的数据生成句子的矩阵,因此这里需要统一句子的长度,生成数据集并实现数据集的封装。实现代码由两部分构成,首先生成对应矩阵,然后封装dataset便于使用dataloader加载数据。
```python
# pre_processing.py
import torch
from gensim.models import Word2Vec
class DataProcess:
def __init__(self, sentences, sen_len, w2v_path="./data/word2vec.model"):
self.sentences = sentences # 句子列表
self.sen_len = sen_len # 句子的最大长度
self.w2v_path = w2v_path # word2vec模型路径
self.index2word = [] # 实现index到word转换
self.word2index = {} # 实现word到index转换
self.embedding_matrix = []
# load word2vec.model
self.embedding = Word2Vec.load(self.w2v_path)
self.embedding_dim = self.embedding.vector_size
def make_embedding(self):
# 为model里面的单词构造word2index, index2word 和 embedding
for i, word in enumerate(self.embedding.wv.vocab):
print('get word #{}'.format(i+1), end='\r')
self.word2index[word] = len(self.word2index)
self.index2word.append(word)
self.embedding_matrix.append(self.embedding[word])
self.embedding_matrix = torch.tensor(self.embedding_matrix)
# 將"<PAD>"和"<UNK>"加进embedding里面
self.add_embedding("<PAD>")
self.add_embedding("<UNK>")
print("total words: {}".format(len(self.embedding_matrix)))
return self.embedding_matrix
def add_embedding(self, word):
# 将新词添加进embedding中
vector = torch.empty(1, self.embedding_dim)
torch.nn.init.uniform_(vector)
self.word2index[word] = len(self.word2index)
self.index2word.append(word)
self.embedding_matrix = torch.cat([self.embedding_matrix, vector], 0)
def sentence_word2idx(self):
sentence_list = []
for i, sentence in enumerate(self.sentences):
# 将句子中的单词表示成index
sentence_index = []
for word in sentence:
if word in self.word2index.keys():
# 如果单词在字典中则直接读取index
sentence_index.append(self.word2index[word])
else:
# 否则赋予<UNK>
sentence_index.append(self.word2index["<UNK>"])
# 统一句子长度
sentence_index = self.pad_sequence(sentence_index)
sentence_list.append(sentence_index)
return torch.LongTensor(sentence_list)
def pad_sequence(self, sentence):
# 统一句子长度
if len(sentence) > self.sen_len:
sentence = sentence[:self.sen_len]
else:
pad_len = self.sen_len - len(sentence)
for _ in range(pad_len):
sentence.append(self.word2index["<PAD>"])
assert len(sentence) == self.sen_len
return sentence
def labels2tensor(self, y):
y = [int(label) for label in y]
return torch.LongTensor(y)
```
### 4. 封装数据集
```python
# data_loader.py
from torch.utils import data
class TwitterDataset(data.Dataset):
def __init__(self, x, y):
self.data = x
self.label = y
def __getitem__(self, index):
if self.label is None:
return self.data[index]
return self.data[index], self.label[index]
def __len__(self):
return len(self.data)
```
### 5. 构造模型
模型包括三个部分:embedding层、LSTM
sjx_alo
- 粉丝: 1w+
- 资源: 1235
最新资源
- 基于STM32为电子香味项目,通过蓝牙模块传输数据,嵌入式硬件平台,RFID使用的是RC522.整个项目包括软硬件以及android程序详细文档+全部资料+高分项目+源码.zip
- 基于发布-订阅模型的多线程消息框架,用于嵌入式平台,纯C实现,性能和灵活性极高详细文档+全部资料+高分项目+源码.zip
- 基于嵌入式Linux的一套可视对讲设备代码,比较底层,写的比较好,里面的lib库是一些图像处理库详细文档+全部资料+高分项目+源码.zip
- php 实现各种排序和查找算法源代码.zip
- 基于嵌入式qt的车载系统详细文档+全部资料+高分项目+源码.zip
- 基于嵌入式的基础图形库详细文档+全部资料+高分项目+源码.zip
- 基于嵌入式平台ARM Linux的新冠肺炎疫情监控平台详细文档+全部资料+高分项目+源码.zip
- 基于嵌入式的视觉运动控制详细文档+全部资料+高分项目+源码.zip
- 基于嵌入式综合项目:STM32F407基于ARM Cortex-M4处理器,云服务器Linux操作系统,MySQL数据存储转发详细文档+全部资料+高分项目+源码
- 基于热风控制系统嵌入式项目,基于STM32F1芯片和RT-Thread实时系统开发出温度闭环控制和风速控制详细文档+全部资料+高分项目+源码.zip
- 基于全志V3S的嵌入式开发者打怪升级项目详细文档+全部资料+高分项目+源码.zip
- 基于事件型嵌入式驱动框架。详细文档+全部资料+高分项目+源码.zip
- 基于使用B-Tree作为索引,基于MMap的嵌入式键值数据库详细文档+全部资料+高分项目+源码.zip
- 基于三个嵌入式的小项目:一个是基于科大讯飞的语音识别系统,一个是智能音乐相册,一个是别踩白块小游戏详细文档+全部资料+高分项目+源码.zip
- 基于物联网模式开发的嵌入式程序详细文档+全部资料+高分项目+源码.zip
- 基于以太网通信的电力电子设备运行状态的远程监控嵌入式系统设计详细文档+全部资料+高分项目+源码.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈