赞
踩
jieba分词
繁体、简体都可以
#精确模式分词
import jieba
content='我来工作爱生活爱拉芳爱学习喜欢跳舞'
jieba.lcut(content,cut_all=False)
#全模式分词
jieba.lcut(content,cut_all=True)
#搜索引擎模式
jieba.lcut_for_search(content)
#自定义字典dict
jieba.load_userdict("./dict.txt")
jieba.lcut(content)
hanlp分词
基于tensorflow2.0
import hanlp #zhongwen tokenizer=hanlp.load('CTB6_CONVSEG') tokenizer('我来工作爱生活,爱拉芳爱学习喜欢跳舞') #英文 tokenizer=hanlp.utils.rules.tokenize_english tokenizer('i love work and dog and wo') #命名实体NER 也就是专有名词的划分 #中文 recognizer=hanlp.load(hanlp.pretrained.ner.MSRA_NER_BERT_BASE_ZH) list('我来工作爱生活,爱拉芳爱学习喜欢跳舞') recognizer(list('我来工作爱生活,爱拉芳爱学习喜欢跳舞')) #英文 recognizer=hanlp.load(hanlp.pretrained.ner.COLL03_NER_BERT_BASE_UNCASED_EN)
词性标注
#中文的
#词性标注 动词、名词划分
import jieba.posseg as pseg
pseg.lcut("我爱工作爱生活爱学校")
#英文
tagger=hanlp.load(hanlp.pretrained.pos.PTB_POS_RNN_FASTTEXT_EN)
其实就是把文字变成数字,计算机才认识!!
one-hot编码
优缺点:操作简单,便于理解但是割裂了词与词的联系,占用内存大
假如4个词 ’我和小王‘
就可以表示为
我(1,0,0,0)
和(0,1,0,0)
以此类推的4*4的0-1矩阵
from sklearn.externals import joblib
#导入词汇映射器
from keras.preprocessing.text import Tokenizer
#初始化词汇表
vacal={"鹿晗","张翰","林更新"}
t=Tokenizer(num_words=None,char_level=False)
t.fit_on_text(vacal)
for token in vocal:
zero_list=[0]*len(vocal)
token_index=t.texts_to_sequences([token])[0][0]-1
zero_list[token_index]=1
tokenizer_path='./e' #保存的位置
jolib.dump(t,tokenizer_path)
word2vec
无监督训练方法,将网络参数作为词汇的向量表示包括了cbow和skipgram。
CBOW步骤就是:如果i love nice day like ,假设窗口大小为3,则是i love nice 三个词,然后 i 和nice 作为输入,采用one-hot编码,(1,0,0,0,0)和(0,1,0,0,0)然后预测 love,以此内推,love nice day用love和day预测nice
skipgram的步骤和CBOW类似,输入和输出交换
#lr表示学习率
# 训练模型
import fasttest
model=fasttext.train_unsupervised(data,'cbow',dim=300,epoch=1,lr=0.05)
#训练完后检验,找到nice相关的词汇
model.get_nearest_neighbors('nice')
#保存模型
model.save_model('fil9.bin')
#用的时候直接调用
modelnew=fasttext.load_model('fil9.bin')
word embedding 词嵌入
# 导入torch和tensorboard导入进来 import torch import json import fileinput from torch.utils.tensorboard import SummaryWriter # 实例化一个写入对象 writer = SummaryWriter() # 随机初始化一个100*50的矩阵, 将其视作已经得到的词嵌入矩阵 embedded = torch.randn(100, 50) # 导入事先准备好的100个中文词汇文件, 形成meta列表原始词汇 meta = list(map(lambda x: x.strip(), fileinput.FileInput("./vocab100.csv"))) writer.add_embedding(embedded, metadata=meta) writer.close()
也就是帮忙理解语调,标签正常不、特征丰富不、标签分类
下面以酒店评语的数据来进行文本分析
标签数量分布
酒店的评论有两列,第一列包括各种评论,第二列是评论的好坏 好的为1,不好的0
# 导入必备的工具包 import seaborn as sns import pandas as pd import matplotlib.pyplot as plt import jieba # 设置显示风格 plt.style.use('fivethirtyeight') # 利用pandas读取训练数据和验证数据 train_data = pd.read_csv("./cn_data/train.tsv", sep="\t") valid_data = pd.read_csv("./cn_data/dev.tsv", sep="\t") # 获得训练数据标签的数量分布 sns.countplot("label", data=train_data) plt.title("train_data") plt.show() # 获得验证数据标签的数量分布 sns.countplot("label", data=valid_data) plt.title("valid_data") plt.show()
## 获得训练集和验证集长度分布
# 在训练数据中添加新的句子长度列, 每个元素的值都是对应句子的长度 train_data["sentence_length"] = list(map(lambda x: len(x), train_data["sentence"])) # 绘制句子长度列的数量分布 # sns.countplot("sentence_length", data=train_data) # plt.xticks([]) # plt.show() # 绘制dist长度分布图 # sns.distplot(train_data["sentence_length"]) # plt.yticks([]) # plt.show() #---------------------------------=----------------------- # 在验证数据中添加新的句子长度列, 每个元素的值对应句子的长度 valid_data["sentence_length"] = list(map(lambda x: len(x), valid_data["sentence"])) # 绘制句子长度列的数量分布图 # sns.countplot("sentence_length", data=valid_data) # plt.xticks([]) # plt.show() # 绘制dist长度分布图 # sns.distplot(valid_data["sentence_length"]) # plt.yticks([]) # plt.show() # 绘制训练数据语句长度的散点图 # sns.stripplot(y="sentence_length", x="label", data=train_data) # plt.show() # 绘制验证数据语句长度的散点图 # sns.stripplot(y="sentence_length", x="label", data=valid_data) # plt.show()
统计不同词汇的数量
# 进行训练集的句子进行分词, 并统计出不同词汇的总数
# train_vocab = set(chain(*map(lambda x: jieba.lcut(x), train_data["sentence"])))
# print("训练集共包含不同词汇总数为:", len(train_vocab))
# 进行验证集的句子进行分词, 并统计出不同词汇的总数
# valid_vocab = set(chain(*map(lambda x: jieba.lcut(x), valid_data["sentence"])))
# print("验证集共包含不同词汇总数为:", len(valid_vocab))
训练集词云
# 导入jieba 中的词性标注工具包 import jieba.posseg as pseg # 定义获取形容词的列表函数 def get_a_list(text): # 使用jieba的词性标注方法来切分文本, 获得两个属性word,flag # 利用flag属性去判断一个词汇是否是形容词 r = [] for g in pseg.lcut(text): if g.flag == 'a': r.append(g.word) return r # 导入绘制词云的工具包 from wordcloud import WordCloud # 定义获取词云的函数并绘图 def get_word_cloud(keywords_list): # 首先实例化词云类对象, 里面三个参数 # font_path: 字体路径,为了能够更好的显示中文 # max_words: 指定词云图像最多可以显示的词汇数量 # backgroud_color: 代表图片的北京颜色 wordcloud = WordCloud(max_words=100, background_color='white') # 将传入的列表参数转化为字符串形式, 因为词云对象的参数要求是字符串类型 keywords_string = " ".join(keywords_list) # 生成词云 wordcloud.generate(keywords_string) # 绘图 plt.figure() plt.imshow(wordcloud, interpolation="bilinear") plt.axis("off") plt.show() # 获取训练集上的正样本 p_train_data = train_data[train_data["label"]==1]["sentence"] # 对正样本的每个句子提取形容词 train_p_a_vocab = chain(*map(lambda x: get_a_list(x), p_train_data)) # 获取训练集上的负样本 n_train_data = train_data[train_data["label"]==0]["sentence"] # 对负样本的每个句子提取形容词 train_n_a_vocab = chain(*map(lambda x: get_a_list(x), n_train_data)) # 调用获取词云的函数 get_word_cloud(train_p_a_vocab) get_word_cloud(train_n_a_vocab) #------------------------------------------------------------- # 获取验证集的数据正样本 p_valid_data = valid_data[valid_data["label"]==1]["sentence"] # 获取正样本的每个句子的形容词 valid_p_a_vocab = chain(*map(lambda x: get_a_list(x), p_valid_data)) # 获取验证集的数据负样本 n_valid_data = valid_data[valid_data["label"]==0]["sentence"] # 获取负样本的每个句子的形容词 valid_n_a_vocab = chain(*map(lambda x: get_a_list(x), n_valid_data)) # 调用获取词云的函数 get_word_cloud(valid_p_a_vocab) get_word_cloud(valid_n_a_vocab)
文本特征处理
包括语料、长度的处理
‘我 喜欢 工作’假设是【2,43,56】
1.n-gram特征:就是特征中假如到相邻的特征 而我和喜欢相邻假设是89 加到里面 喜欢和工作相邻假设是5 加入其中【2,43,56,89,5】
#n-gram
def creat_ngram_set(input_list):
return set(zip(*[input_list[i:] for i in range(ngram_range)]))
input_list=[4,2,89,56,7]
#长度规范 能够覆盖90%以上的语料长度
假设是20,不足加0,长度大于20保留后面20个舍去前面的
cutlen=20
def padding(x_train):
return sequence.pad_sequences(x_train,cutlen)
文本增强
回译数据增强,基于google翻译接口,将原始的中文句子翻译成另外一种语言如英语,然后又翻译回来
优势劣势:获得预料质量高,但是对于短文本可能重复率高,那么也可以中文变成英语,英语变韩文然后再变回中文
word1='我爱狗狗'
word2='她和他的家的东西'
from gooletrain import Translator
translator=Translator()
#ko是韩语
translations=translator.translate([word1,word2],dest='ko')
ko_result=list(map(lambda x:x.text,translations))
#翻译回来
translations=translator.translate(ko_result,dest='zh-cn')
cn_result=list(map(lambda x:x.text,translations))
看这一段新闻是哪一类的体育?财经?
首先导入我们需要的数据
# 导入相关的工具包 import torch import torchtext # 导入数据集中的文本分类任务 from torchtext.datasets import text_classification import os # 定义数据下载路径, 当前文件夹下的data文件夹 load_data_path = "./data" if not os.path.isdir(load_data_path): os.mkdir(load_data_path) # 选取torchtext包中的文本分类数据集'AG_NEWS', 即新闻主题分类数据 # 顺便将数据加载到内存中 train_dataset, test_dataset = text_classification.DATASETS['AG_NEWS'](root=load_data_path)
构建带有embedding的文本分类模型
对数据batch处理
构建训练和验证函数
训练模型和验证
查看嵌入的词向量
注意troch.nn里面有很多神经网络的
# 导入相关工具包 import torch import torch.nn as nn import torch.nn.functional as F # 指定BATCH_SIZE的大小 BATCH_SIZE = 1 import torchtext # 导入数据集中的文本分类任务 from torchtext.datasets import text_classification import os # 定义数据下载路径, 当前文件夹下的data文件夹 load_data_path = "./data" if not os.path.isdir(load_data_path): os.mkdir(load_data_path) # 选取torchtext包中的文本分类数据集'AG_NEWS', 即新闻主题分类数据 # 顺便将数据加载到内存中 train_dataset, test_dataset = text_classification.DATASETS['AG_NEWS'](root=load_data_path) # 进行设备检测, 如果有GPU的话有限使用GPU进行模型训练, 否则在CPU上进行训练 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 构建文本分类的类 class TextSentiment(nn.Module): def __init__(self, vocab_size, embed_dim, num_class): # vocab_size: 代表整个语料包含的单词总数 # embed_dim: 代表词嵌入的维度 # num_class: 代表是文本分类的类别数 这里是4 super().__init__() # 实例化EMbedding层的对象, 传入3个参数, 分别代表单词总数, 词嵌入的维度, spqrse进行梯度求解时只更新部分权重 self.embedding = nn.Embedding(vocab_size, embed_dim, sparse=True) # 实例化全连接线性层的对象, 两个参数分别代表输入的维度和输出的维度 self.fc = nn.Linear(embed_dim, num_class) # 对定义的所有层权重进行初始化 self.init_weights() def init_weights(self): # 首先给定初始化权重的值域范围 initrange = 0.5 # 各层的权重使用均匀分布进行初始化 self.embedding.weight.data.uniform_(-initrange, initrange) self.fc.weight.data.uniform_(-initrange, initrange) self.fc.bias.data.zero_() def forward(self, text): # text: 代表文本进过数字化映射后的张量 # 对文本进行词嵌入的操作 embedded = self.embedding(text) c = embedded.size(0) // BATCH_SIZE embedded = embedded[:BATCH_SIZE * c] # 明确一点, 平均池化的张量需要传入三维张量, 而且在行上进行操作 embedded = embedded.transpose(1, 0).unsqueeze(0) # 进行平均池化的操作 embedded = F.avg_pool1d(embedded, kernel_size=c) # 首先将三维张量恢复成二维张量, 再将行列进行转置 return self.fc(embedded[0].transpose(1, 0)) # 获取整个语料中词汇的总数 VOCAB_SIZE = len(train_dataset.get_vocab()) # 指定词嵌入的维度 EMBED_DIM = 32 # 获取真个文本分类的总数 NUM_CLASS = len(train_dataset.get_labels()) # 实例化模型对象 model = TextSentiment(VOCAB_SIZE, EMBED_DIM, NUM_CLASS).to(device) #---------------------------------------------------------------------------------------------------------- # 构建产生批次数据的函数 def generate_batch(batch): # batch: 由样本张量和标签的元组所组成的batch_size大小的列表 # 首先提取标签的列表 label = torch.tensor([entry[1] for entry in batch]) # 然后提取样本张量 text = [entry[0] for entry in batch] text = torch.cat(text) return text, label batch = [(torch.tensor([3,23,2,8]), 1), (torch.tensor([3,45,21,6]), 0)] res = generate_batch(batch) print(res) #--------------- # 导入数据加载器的工具包,处理数据的 from torch.utils.data import DataLoader #-------------------------------------------------------------- # 编写训练函数的代码 def train(train_data): # train_data: 代表传入的训练数据 # 初始化训练损失值和准确率 train_loss = 0 train_acc = 0 # 使用数据加载器构建批次数据,shuffle随机打乱,返回的是text和lable的张量 data = DataLoader(train_data, batch_size=BATCH_SIZE, shuffle=True, collate_fn=generate_batch) # 对data进行循环遍历, 使用每个batch数据先进行训练 for i, (text, cls) in enumerate(data): # 训练模型的第一步: 将优化器的梯度清零 optimizer.zero_grad() # 将一个批次的数据输入模型中, 进行预测 output = model(text) # 计算预测值和真实标签之间的损失 loss = criterion(output, cls) # 将该批次的损失值累加到总损失中 train_loss += loss.item() # 进行反向传播的计算 loss.backward() # 参数更新 optimizer.step() # 计算该批次的准确率并加到总准确率上, 注意一点这里加的是准确的数字 train_acc += (output.argmax(1) == cls).sum().item() # 进行整个轮次的优化器学习率的调整 scheduler.step() # 返回本轮次训练的平均损失值和平均准确率 return train_loss / len(train_data), train_acc / len(train_data) # 编写验证函数的代码 def valid(valid_data): # valid_data: 代表验证集的数据 # 初始化验证的损失值和准确率 valid_loss = 0 valid_acc = 0 # 利用数据加载器构造每一个批次的验证数据 data = DataLoader(valid_data, batch_size=BATCH_SIZE, collate_fn=generate_batch) # 循环遍历验证数据 for text, cls in data: # 注意: 在验证阶段, 一定要保证模型的参数不发生改变, 也就是不求梯度,直接用训练的参数 with torch.no_grad(): # 将验证数据输入模型进行预测 output = model(text) # 计算损失值 loss = criterion(output, cls) # 将该批次的损失值累加到总损失值中 valid_loss += loss.item() # 将该批次的准确数据累加到总准确数字中 valid_acc += (output.argmax(1) == cls).sum().item() # 返回本轮次验证的平均损失值和平均准确率 return valid_loss / len(valid_data), valid_acc / len(valid_data) #--------------------------------------- # 导入时间工具包 import time # 导入数据的随机划分方法工具包 from torch.utils.data.dataset import random_split # 指定训练的轮次 N_EPOCHS = 10 # 定义初始的验证损失值 min_valid_loss = float('inf') # 定义损失函数, 定义交叉熵损失函数 criterion = torch.nn.CrossEntropyLoss().to(device) # 定义优化器, 定义随机梯度下降优化器 optimizer = torch.optim.SGD(model.parameters(), lr=4.0) # 定义优化器步长的一个优化器, 专门用于学习率的衰减 scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 1, gamma=0.9) # 选择全部训练数据的95%作为训练集数据, 剩下的5%作为验证数据 train_len = int(len(train_dataset) * 0.95) sub_train_, sub_valid_ = random_split(train_dataset, [train_len, len(train_dataset) - train_len]) # 开始每一次的训练模型 for epoch in range(N_EPOCHS): # 记录训练开始的时间 start_time = time.time() # 将训练数据和验证数据分别传入训练函数和验证函数中, 得到训练损失和准确率, 以及验证损失和准确率 train_loss, train_acc = train(sub_train_) valid_loss, valid_acc = valid(sub_valid_) # 计算当前轮次的总时间 secs = int(time.time() - start_time) # 将耗时的秒数转换成分钟+秒 mins = secs / 60 secs = secs % 60 # 打印训练和验证的耗时, 损失值, 准确率值 print('Epoch: %d' % (epoch + 1), " | time in %d minites, %d seconds" % (mins, secs)) print(f'\tLoss: {train_loss:.4f}(train)\t|\tAcc: {train_acc * 100:.1f}%(train)') print(f'\tLoss: {valid_loss:.4f}(valid)\t|\tAcc: {valid_acc * 100:.1f}%(valid)') print('********************') print(model.state_dict()['embedding.weight']) #-------------看emdedding的词向量 print(model.state_dict()['embedding.weight'])
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。