基于词向量word2vec模型的文本分类实现(算例有代码)

词向量

词向量大白话解释:就是一个神经网络。针对一段文本,输入前面几个单词和后面几个单词。输出当前这个单词。然后用神经网络中间层的权重系数来表示输出的这个Y单词。
词向量是表示文本的一种方式,词汇表中的每个单词由高维空间的实值向量表示。具有相似含义的单词在向量空间中具有相似的表达能力(在向量空间中接近)。
有很多封装好的模块可以帮我们词向量。我们只需将得到的词向量作为我们分类器的输入,来完成文本分类。

算例

数据集
电力95598工单 两行,第一行为类别标签。第二行为工单文本。

本文主要基于95598工单完成文本分类,选取浙江省95598工单数据集3171条。其中的工单可以分类为反映、建议、表扬、举报、投诉、以往业务、查询、报修8个类别。

导入包
采用keras完成模型训练,我比较喜欢keras,TensorFlow不怎么用生疏啦。

import pandas as pd
import numpy as np
import jieba as jb
import re
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import  pad_sequences
from keras .models import  Sequential
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers import Embedding
from keras.layers.convolutional import  Conv1D
from keras.layers.convolutional import  MaxPooling1D
import keras
from keras .models import load_model

读取数据

csv='95598.csv'
file_txt=pd.read_csv(csv, header=0,encoding='gbk')#[1169656 rows x 3 columns]

file_txt=file_txt.dropna()#删除空值[1005981 rows x 2 columns]

#添加文字标签
file_txt['biaoqian']=''
file_txt.loc[file_txt['BUSI_TYPE_CODE']==7,'biaoqian']='反映'
file_txt.loc[file_txt['BUSI_TYPE_CODE']==6,'biaoqian']='建议'
file_txt.loc[file_txt['BUSI_TYPE_CODE']==5,'biaoqian']='表扬'
file_txt.loc[file_txt['BUSI_TYPE_CODE']==4,'biaoqian']='举报'
file_txt.loc[file_txt['BUSI_TYPE_CODE']==3,'biaoqian']='投诉'
file_txt.loc[file_txt['BUSI_TYPE_CODE']==2,'biaoqian']='以往业务'
file_txt.loc[file_txt['BUSI_TYPE_CODE']==1,'biaoqian']='查询'
file_txt.loc[file_txt['BUSI_TYPE_CODE']==0,'biaoqian']='报修'
print(file_txt)

去除标点符号和停用词

# 定义删除除字母,数字,汉字以外的所有符号的函数
def remove_punctuation(line):
    line = str(line)
    if line.strip() == '':
        return ''
    rule = re.compile(u"[^a-zA-Z0-9\u4E00-\u9FA5]")
    line = rule.sub('', line)
    return line

#停用词
def stopwordslist(filepath):
    stopwords = [line.strip() for line in open(filepath, 'r', encoding='gbk').readlines()]
    return stopwords

# 加载停用词
stopwords = stopwordslist("停用词.txt")

#去除标点符号
file_txt['clean_review']=file_txt['ACCEPT_CONTENT'].apply(remove_punctuation)
#去除停用词
file_txt['cut_review']=file_txt['clean_review'].apply(lambda x:" ".join([w for w in list(jb.cut(x)) if w not in stopwords]))

词向量 预处理来啦
keras 中的词向量层Embedding需要整数输入。
首先我们得将单词映射到整数。
from keras.preprocessing.text import Tokenizer
读取的是所有文本

#将单词编成整数系列
#单词-整数的映射
def create_tokenizer(lines):
	tokenizer=Tokenizer()
	tokenizer.fit_on_texts(lines)
	return  tokenizer
tokenizer=create_tokenizer(file_txt['cut_review'])

填充句子长度
由于每个文本长短不一。我们需要将短文本用0填充,使所有文本长读一致。
找到最大长度的文本单词数 即最大长度

#找到最长句子长度
max_length=max([len(s.split()) for s in file_txt['cut_review']])
print('最长词语 句子:',max_length)#126

填充长度,使长度一致
from keras.preprocessing.sequence import pad_sequences

docs为所有文本
padding='post’为向后填充,即在后面填充0.也有在前面填充0的

单词-整数映射 包含在这个encode_docs函数里啦

#使用tokenizer.text_to_sequences()函数来获取单词-整数编码
#使用pad_sequences 函数来为长度不够的文本进行填0操作,使所有文本长度一致
def encode_docs(tokenizer,max_length,docs):
	encoded=tokenizer.texts_to_sequences(docs)#单词-整数映射
	padded=pad_sequences(encoded,maxlen=max_length,padding='post')
	return padded

输入,输出 处理

X_train=encode_docs(tokenizer,max_length,file_txt['cut_review'])
y_train=file_txt['BUSI_TYPE_CODE']
y_train=np.array(y_train)#(130583, 1)
Y_train=keras.utils.to_categorical(y_train,8)#8分类

查看下X_train

查看下Y_train

定义神经网络模型
用下简单的卷积神经网络。只是演示下词向量文本分类流程,没必要用高级模型

#使用Embedding层作为第一层,需要指定词汇表大小,
实值向量空间的大小以及输入文档的最大长度。词汇表大小是我们词汇表中的单词总数,加上一个未知单词 vocad_size=len(tokenizer.word_index)+1

Embedding(vocad_size,100,input_length=max_length)
vocad_size:为词汇表大小
实值向量空间的大小:取100,即一个单词用100维的“权重”表示。
input_length:输入文本的最大长度。

#定义神经网络模型
"""
#使用Embedding层作为第一层,需要指定词汇表大小,
实值向量空间的额大小以及输入文档的最大长度。词汇表大小是我们词汇表中的单词总数,加上一个未知单词
"""
vocad_size=len(tokenizer.word_index)+1
print('词汇表大小:',vocad_size)#7896

#定义神经网络模型
def define_model(vocad_size,max_length):
	model=Sequential()
	model.add(Embedding(vocad_size,100,input_length=max_length))
	model.add(Conv1D(filters=32,kernel_size=5,activation='relu'))
	model.add(MaxPooling1D(pool_size=2))
	model.add(Flatten())
	model.add(Dense(16,activation='relu'))
	model.add(Dense(8,activation='softmax'))
	model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
	model.summary()
	return model

训练模型

#模型训练
def model_train():
    model = define_model(vocad_size, max_length)
    model.fit(X_train, Y_train, epochs=10, verbose=2)
    model.save('词向量模型分类.h5')
    model_train()
model_train()

模型评估

from sklearn.metrics import accuracy_score#分类器评估
model=load_model('词向量模型分类.h5')
predict_y=model.predict(X_train)
pred_y=np.argmax(predict_y,axis=1)
test_y=np.array(file_txt['BUSI_TYPE_CODE'])
f1=accuracy_score(pred_y,test_y)
print(f1)

结果完美

对新的文本进行预测
代码就不写啦,简单写下流程。
1首先准备好一个字典(标签数字:标签文字)方便预测时直接输出文字
2.对输入的文本进行分词,去除停用词,标点符号等操作
3.处理后文本line加上中括号。对文本进行 单词整数映射,填充长度。整个操作包括在了encode_docs()函数里(如果文本比训练集文本最长还长,Keras中pad_sequences会截断,取前面的)
4 模型预测,得到最大数字索引,即类别数字标签
5.查找字典,得到 类别文字。打印

yd_names1 = {'0':'报修','1':'查询','2':'以往业务','3':'投诉','4':'举报','5':'表扬','6':'建议','7':'反映'}

def predict_text(文本,停用词,tokenizer,max_length,model):
    line='对文本进行分词并去除停用词,标点符号后的文本'
    #填充长度,注意line要加[]号括起来。
    padded=encode_docs(tokenizer,max_length,[line])
    y_predict=model.predict(padded,verbose=0)
    pred_y = np.argmax(y_predict, axis=1) #得到的是最大数值索引
    print(yd_names1[pred_y])#获取类型文字信息

基于tf-idf的文本分类见链接
短文本分类:电力95598工单分类实现

电气专业的计算机小白,写博文不容易。如果你觉得本文对你有用,请点个赞支持下。谢谢。

猜你喜欢

转载自blog.csdn.net/kobeyu652453/article/details/107228172