NLP基础
基本概念
NLP,自然语言处理,目标是让计算机能够理解、解释、生成人类语言的数据。包括语言理解,语言生成,机器翻译,情感分享,语音识别,语音合成等
应用方向
-
自然语言理解
- 情感分析: 给定选项范围内分析文本的情绪是正面还是负面
- 文本分类:对文本进行分类
- 信息检索:和搜索引擎相关
- 抽取式阅读理解:给定文本输入,用文本中的内容回答问题
- 语义匹配:给定两个文本,判断是否相似
- 自然语言推理:给定两个文本,判读是蕴涵,矛盾还是无关
- 命名实体识别:给定文本输入,返回还有命名实体及其对应标签的映射 把实体分为特定的类别
- 文本摘要:对文本进行摘要
-
自然语言转换
- 机器翻译:自然语言转换 seq2seq
- 非抽取式阅读理解:给定文本,理解文本,回答问题
- 文本风格转换:转换风格,换一种方式表达
- 语音识别:语音转文本
- 意图改写:给定文本,把文本中的意图和核心信息进行重新表达
-
自然语言生成
- 文本生成:根据上下文,自动生成文本
- 语音合成:文本转语音
- 文本到知识:文本提取知识
- 语义解析:自然语言转化为逻辑表示,命令解析,查询理解
-
应用方向
- 数据集
可以再github等网站找到一些公开的文本数据集
NLP基础概念
- 词表 词库:文本数据集中出现的单词集合
- 语料库:文本数据集合,原始的语料,书籍文章等
- 词嵌入:把单词热编码映射到低维空间,可以捕捉语义
- 停用词:忽略的常见词
- 分词:把文本分隔为一个个单词
- 词袋模型:把文本表示为单词的集合,忽略单词的顺序和语法结构
- N-gram:连续的n个单词组成一个序列,这样的序列可以表示语法,一定的上下文信息
NLP基本流程
- 语料获取
- 第三方数据集语料库
- 网络数据
- 购买
- 语料预处理
- 去除非文本内容
- 中文分词 如jieba分词
- 词性标注
- 去除停用词
- 文本向量化 把文本转化为特征向量
- 模型构建 TextCNN RNN LSTM GRM
- 模型训练
- 模型评价 roc曲线 AUC线等
NLP中的特征工程
在NLP中,特征工程是将文本数据转化为适合机器学习模型使用的数值表示的过程
- 词向量
- 独热编码one-hot 类似机器学习中的字典特征提取,只有一个元素是1,其他为0
- 词频-逆文档频率
- n-grams 把连续的n个词组合起来,形成一个短语捕捉上下文信息
- 常见做法是把n-grams和TF-IDF相结合,先形成n-grams再计算TF-IDF权重
- 稠密编码 特征嵌入 将热编码这样的离散高维数据转化为低维数据
- 词嵌入算法
- Embedding Layer 热编码使用矩阵映射
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from tqdm import tqdm
from sklearn.model_selection import train_test_split
sentences = '''
人闲桂花落
夜静春山空
月出惊山鸟
时鸣春涧中
空山不见人
但闻人语响
返景入深林
复照青苔上
移舟泊烟渚
日暮客愁新
野旷天低树
江清月近人
床前明月光
疑是地上霜
举头望明月
低头思故乡
白日依山尽
黄河入海流
欲穷千里目
更上一层楼
千山鸟飞绝
万径人踪灭
孤舟蓑笠翁
独钓寒江雪
江旷春潮白
山长晓岫青
他乡临睨极
花柳映边亭
'''
sentences = sentences.strip().split('\n')
# 创建词表和对应的映射关系
word_list = [word for word in ''.join(sentences)]
# print(word_list)
word_dict = {w: i for i, w in enumerate(list(set(word_list)))}
number_dict = {i: w for i, w in enumerate(list(set(word_list)))}
n_class = len(word_dict) #词表大小
# 设置模型超参数
m_dim =10 # 嵌入向量的维度
n_hidden = 5 # 神经元数量
n_step = 4 # 输入步长数
# 划分数据集
train_data,test_data = train_test_split(sentences,test_size=0.3,random_state=1,shuffle=True)
# 创建输入的样本和目标值
def make_batch(sentences):
input_batch = []
target_batch = []
for sen in sentences:
word = [word for word in sen]
# print(word)
input = [word_dict[n] for n in word[:-1]]
target = word_dict[word[-1]]
input_batch.append(input)
target_batch.append(target)
return input_batch, target_batch
# 创建模型
class NNLM(nn.Module):
def __init__(self, n_step, n_class, m_dim,n_hidden):
super(NNLM, self).__init__()
# 定义嵌入层,单词索引映射为嵌入向量
self.embed = nn.Embedding(n_class, m_dim)
# 第一层隐藏层
self.linear1 = nn.Linear(m_dim*n_step, n_hidden)
# 分类类别数就是词表大小
self.linear2 = nn.Linear(n_hidden, n_class)
def forward(self, x):
x = self.embed(x) # 通过嵌入曾得到的形状是(batch_size, n_step,m_dim)-> (batch_size, n_step*m_dim)
x = x.view(-1, x.size(1) * x.size(2)) # 拉平为二维数据
h = torch.tanh(self.linear1(x))
output = self.linear2(h)
return output
# 初始化模型
model = NNLM(n_step, n_class, m_dim, n_hidden)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss() # 损失函数 交叉熵
optimizer = optim.Adam(model.parameters(), lr=0.001) # 优化器 学习率
# 准备输入和目标数据
input_batch, target_batch = make_batch(train_data)
input_batch = torch.LongTensor(input_batch)
target_batch = torch.LongTensor(target_batch)
# 开始训练
for epoch in tqdm(range(5000)):
optimizer.zero_grad() # 梯度清零
output = model(input_batch)
loss = criterion(output, target_batch)
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward() # 反向传播
optimizer.step() # 参数更新
# 训练数据 使用训练好的模型进行预测
input_batch, target_batch = make_batch(test_data)
input_batch = torch.LongTensor(input_batch)
target_batch = torch.LongTensor(target_batch)
predict = model(input_batch).max(1, keepdim=True)[1]
print(predict.squeeze())
print(target_batch)
print(predict.squeeze()==target_batch)
print('acc: ',(predict.squeeze()==target_batch).sum()/len(target_batch))
# 输出预测结果
# print([sen[:-1] for sen in sentences], '->', [number_dict[n.item()] for n in predict.squeeze()])