本文首发在微信公众号‘java学习每天一个知识点’,更多资源请关注公众号获取。
一、将收集到的语料进行文本预处理
1)train.txt预处理为train.csv,格式为id,内容,标签
使用excel打开train.txt然后选择分隔符为英文逗号,这样内容在一列,然后再为他们添加id,从1-900,接着添加标签,0,1,2分别表示财经,体育,军事。最后另存为csv文件。
2)对内容进行分词和停用词过滤,这里使用结巴和LTP分词,然后存入新的csv文件
import pandas as pd
import jieba
from pyltp import Segmentor
import os
LTP_DATA_DIR = 'ltp_model\\ltp_data_v3.4.0\\' # ltp模型目录的路径
cws_model_path = os.path.join(LTP_DATA_DIR, 'cws.model') # 分词模型路径,模型名称为`cws.model`
# 去除停用词,然后用LTP分词,返回去除停用词和分词后的文本列表
def clean_stopwords(contents):
contents_list = []
stopwords_list = set(stopwords)
for row in contents: # 循环去除停用词
words_list = jieba.lcut(row)
words = [w for w in words_list if w not in stopwords_list]
sentence_0 = ' '.join(words) # 把是列表的words中的连接符用’’,成了字符串
sentence=segmentor(sentence_0)
contents_list.append(sentence)
return contents_list
def segmentor(sentence):
segmentor = Segmentor() # 初始化实例
segmentor.load(cws_model_path) # 加载模型
words = segmentor.segment(sentence) # 分词,words是str类型
#输出测试,可不写
print(' '.join(words))
words_1 = ' '.join(words) # 返回的words_1是str
segmentor.release() # 释放模型
return words1
# 将清洗后的文本和标签写入.csv文件中
def after_clean2csv(contents, labels): # 输入为文本列表和标签列表
columns = ['contents', 'labels']
save_file = pd.DataFrame(columns=columns, data=list(zip(contents, labels)))
save_file.to_csv('xgboost/train_test3.csv', index=False, encoding="utf-8")
def stopwordslist(filepath):
stopwords = [line.strip() for line in open(filepath, 'r', encoding='utf-8').readlines()] # 读取每一行并去除每行的首尾空格
return stopwords
if __name__ == '__main__':
stopwords = stopwordslist('xgboost/stopWords.txt')
train_data = pd.read_csv('xgboost/train.csv', sep=',',
names=['ID','review', 'label']).astype(str)
labels = []
for i in range(len(train_data['label'])):
labels.append(train_data['label'][i])
print(train_data["label"][i])
contents = clean_stopwords(train_data['review'])
after_clean2csv(contents, labels)
解析代码
pd.read_csv()将csv文件读入并转化为数据框形式
pd.read_csv(filepath_or_buffer, sep=',', names=None)
filepath_or_buffer 必填参数,文件所在处的路径
sep: 指定分隔符,默认为逗号','
names: 指定列的名称,用列表表示。一般我们没有表头,即header=None时,这个用来添加列名.
'\t'.join(words) 将序列中的元素以指定的字符连接生成一个新的字符串,words是list测试:使
list1 = ['hh','bbbb','wo']
print(type(list1))
str1 = ' '.join(list1)
print(type(str1))
print(list1)
print(str1)
结果:
['hh', 'bbbb', 'wo']
hh bbbb wo
可以看到list变为了str
可能出现的bug
解析bug:
因为可能已经打开了这个文件,关闭这个文件即可
转换成功之后的test3.csv文件截图如下:
二、文本特征提取
使用sklearn计算训练集的TF-IDF,并将训练集和测试集分别转换为TF-IDF权重矩阵,作为模型的输入。
train_data = pd.read_csv('E:/hebin/xgboost/train_test3.csv', sep=',', names=['contents', 'labels']).astype(str)
cw = lambda x: int(x)
train_data['labels'] = train_data['labels'].apply(cw) # 把labels列的纯数字字符串转换为int型
x_train, x_test, y_train, y_test = train_test_split(train_data['contents'], train_data['labels'], test_size=0.3) # 分割数据集为train和test
# 将语料转化为词袋向量,根据词袋向量统计TF-IDF
vectorizer = CountVectorizer(max_features=5000)
tf_idf_transformer = TfidfTransformer()
tf_idf = tf_idf_transformer.fit_transform(vectorizer.fit_transform(x_train))
x_train_weight = tf_idf.toarray() # 训练集TF-IDF权重矩阵
tf_idf = tf_idf_transformer.transform(vectorizer.transform(x_test))
x_test_weight = tf_idf.toarray() # 测试集TF-IDF权重矩阵
解析代码
1)cw = lambda x: int(x)
使用lambda表达式,输入x,返回int(x)。跟定义一个函数c1,传入x,返回int(x)一样。
结果
10
10
2)sklearn的train_test_split
train_test_split函数用于将矩阵随机划分为训练子集和测试子集,并返回划分好的训练集测试集样本和训练集测试集标签。
X_train,X_test, y_train, y_test =cross_validation.train_test_split(train_data,train_target,test_size=0.3)
train_data:被划分的样本特征集
train_target:被划分的样本标签
test_size:如果是浮点数,在0-1之间,表示测试样本占比;如果是整数的话就是样本的数量
3) TF-IDF(term frequency–inverse document frequency,词频-逆向文件频率)是一种用于信息检索(information retrieval)与文本挖掘(text mining)的常用加权技术。
TF-IDF是一种统计方法,用以评估字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。
TF是词频(Term Frequency)
词频(TF)表示词条(关键字)在文本中出现的频率。
IDF是逆向文件频率(Inverse Document Frequency)
逆向文件频率 (IDF) :某一特定词语的IDF,可以由总文件数目除以包含该词语的文件的数目,再将得到的商取对数得到。
vectorizer = CountVectorizer(5000)
CountVectorizer会将文本中的词语转换为词频矩阵,它通过fit_transform函数计算各个词语出现的次数,通过get_feature_names()可获得所有文本的关键词,通过toarray()可看到词频矩阵的结果。
TfidfTransformer
TfidfTransformer用于统计vectorizer中每个词语的TF-IDF值
vectorizer.fit_transform(x_train)计算每个词出现的次数 tf_idf_transformer.fit_transform将词频矩阵统计成TF-IDF值
DMatrix是XGBoost的二进制的缓存文件,加载的数据存储在对象DMatrix中。
dtrain = xgb.DMatrix(x_train_weight, label=y_train)
dtest = xgb.DMatrix(x_test_weight, label=y_test)
解析:
参考:https://xgboost.readthedocs.io/en/latest/python/python_api.html
可能出现的bug2
解析bug
ValueError是因为int型不能将非纯数字的字符串转换为整数,说明获取到的字符串有非纯数字的,所以才会出现错误,结合给出的错误提示labels。发现train_test3在标签列的第一行有labels
改正方法:
方法一、删去train_test3在标签列的第一行之后重新训练,成功。
方法二、在文本预处理时候,to_csv方法中使用header=0,让csv文件不保存列名。
# xgboost模型构建
param = {'silent': 0, 'eta': 0.3, 'max_depth': 6, 'objective': 'multi:softmax', 'num_class': 3,
'eval_metric': 'merror'} # 参数
evallist = [(dtrain, 'train'), (dtest, 'test')]
num_round = 100 # 循环次数
xgb_model = xgb.train(param, dtrain, num_round, evallist)
# 保存训练模型
# xgb_model.save_model('data/xgb_model')
y_predict = xgb_model.predict(dtest) # 模型预测
label_all = ['财经', '体育', '军事']
confusion_mat = metrics.confusion_matrix(y_test, y_predict)
df = pd.DataFrame(confusion_mat, columns=label_all)
df.index = label_all
print('准确率:', metrics.accuracy_score(y_test, y_predict))
print('confusion_matrix:', df)
print('分类报告:', metrics.classification_report(y_test, y_predict))
解析:
参考https://xgboost.readthedocs.io/en/latest/python/python_api.html
1、
xgboost.train(params,dtrain,num_round,evallist)
params:booster的参数
dtrain:要训练的数据
num_round:迭代次数
evallist:(对列表(DMatix,string))在培训期间评估度量标准的验证集列表。验证指标将帮助我们跟踪模型的性能。
2、
metrics.confusion_matrix(y_test, y_predict)
计算混淆矩阵用来评估分类的准确度.
3、
metrics.accuracy_score(y_test, y_predict)
分类准确率分数是指所有分类正确的百分比
4、
metrics.classification_report(y_test, y_predict)
用于显示主要分类指标的文本报告.在报告中显示每个类的精确度,召回率,F1值等信息。
F1值是精确度和召回率的调和平均值,精确度和召回率都高时, F1值也会高. F1值在1时达到最佳值(完美的精确度和召回率),最差为0.
最终结果为
eee,准确率有点低,主要由于tf-idf比较依赖数据,而本次实验数据只有900条,影响了准确率。