用TFIDF词袋模型进行新闻分类

词袋 不关注词的先后顺序—词袋模型(bow–一元模型) bag of words
二元模型
n-gram

创建输出目录  保存训练好的模型
import os#对文件和目录进行操作
output_dir = u'output'
if not os.path.exists(output_dir):
    os.mkdir(output_dir)

加载数据

import numpy as np#一个数据分析处理数据的常见的库,它提供的数据结构比 Python 自身的更高效
import pandas as pd

1.Pandas 是基于 NumPy 的一个开源 Python 库,它被广泛用于快速分析数据,以及数据清洗和准备等工作。它的名字来源是由” Panel data”(面板数据,一个计量经济学名词)两个单词拼成的。简单地说,你可以把 Pandas 看作是 Python 版的 Excel。
2. Pandas能很好地处理来自各种不同来源的数据,比如 Excel 表格、CSV 文件、SQL 数据库,甚至还能处理存储在网页上的数据。
3. Pandas基于Numpy,常常与Numpy、matplotlib一起使用。
4. Pandas库的两个主要数据结构:
Series:一维
DataFrame:多维

python list 列表保存的是对象的指针,比如 [0,1,2] 需要保存 3 个指针和 3 个整数的对象,这样就很浪费内存了。

Numpy 是储存在一个连续的内存块中,节约了计算资源。

查看训练数据
train_data = pd.read_csv('sohu_train.txt', sep='\t', header=None, dtype=np.str_, encoding='utf8',error_bad_lines=False, delimiter="\t", names=[u'频道', u'文章'])
train_data.head()

用TFIDF词袋模型进行新闻分类
载入停用词
stopwords = set()
with open('stopwords.txt', 'r',encoding='utf8') as infile:
    for line in infile:
        line = line.rstrip('\n')
        if line:
            stopwords.add(line.lower())

计算每个文章的tfidf特征

import jieba
from sklearn.feature_extraction.text import TfidfVectorizer

min_df去掉df值小的词 这样的词一般是非常专业的名词或者是生僻词 是噪音
max_df 去掉df值很大的词 这样词是常用词 去掉不要

tfidf = TfidfVectorizer(tokenizer=jieba.lcut, stop_words=stopwords, min_df=50, max_df=0.3)#使用TfidfVectorizer实例化
x = tfidf.fit_transform(train_data[u'文章'])

·输出结果

Building prefix dict from the default dictionary ...

Loading model from cache C:\Users\10248\AppData\Local\Temp\jieba.cache
Loading model cost 0.550 seconds.

Prefix dict has been built successfully.

E:\ANACODAN\lib\site-packages\sklearn\feature_extraction\text.py:388: UserWarning: Your stop_words may be inconsistent with your preprocessing. Tokenizing the stop words generated tokens ['&', ',', '.', ';', 'e', 'g', 'nbsp', '—', '\u3000', '傥', '兼', '前', '唷', '啪', '啷', '喔', '始', '漫', '然', '特', '竟', '若果', '莫', '见', '设', '说', '达', '非'] not in stop_words.

  warnings.warn('Your stop_words may be inconsistent with '
print(u'词表大小: {}'.format(len(tfidf.vocabulary_)))
词表大小: 14516

训练分类器

编码目标变量 因为咱们的标签是字符串 sklearn只接受数值

from sklearn.preprocessing import LabelEncoder#LabelEncoder:将类别数据数字化
y_encoder = LabelEncoder()
y = y_encoder.fit_transform(train_data[u'频道'])#将类别转换成0,1,2,3,4,5,6,7,8,9...

y[:10]

·输出结果

array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3])

编码X变量
x = tfidf.transform(train_data[u’文章’])

划分训练测试数据
from sklearn.model_selection import train_test_split#分割数据集
根据y分层抽样,测试数据占20%
#因为现在数据量很大  此时采用对下标进行分割
train_idx, test_idx = train_test_split(range(len(y)), test_size=0.2, stratify=y)
train_x = x[train_idx, :]#训练集
train_y = y[train_idx]
test_x = x[test_idx, :]#测试集
test_y = y[test_idx]

训练逻辑回归模型 我们是12分类 属于多分类

常用参数说明
penalty: 正则项类型,l1还是l2
C: 正则项惩罚系数的倒数,越大则惩罚越小
fit_intercept: 是否拟合常数项
max_iter: 最大迭代次数
multi_class: 以何种方式训练多分类模型
ovr = 对每个标签训练二分类模型
multinomial ovo = 直接训练多分类模型,仅当solver={newton-cg, sag, lbfgs}时支持
solver: 用哪种方法求解,可选有{liblinear, newton-cg, sag, lbfgs}
小数据liblinear比较好,大数据量sag更快
多分类问题,liblinear只支持ovr模式,其他支持ovr和multinomial
liblinear支持l1正则,其他只支持l2正则

from sklearn.linear_model import LogisticRegression#引入逻辑回归
model = LogisticRegression(multi_class='multinomial', solver='lbfgs')#solver='lbfgs':求解方式
model.fit(train_x, train_y)

·输出结果

E:\ANACODAN\lib\site-packages\sklearn\linear_model\_logistic.py:763: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.

Increase the number of iterations (max_iter) or scale the data as shown in:
    https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
    https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
  n_iter_i = _check_optimize_result(
LogisticRegression(multi_class='multinomial')

模型效果评估

from sklearn.metrics import confusion_matrix, precision_recall_fscore_support
在测试集上计算模型的表现
test_y_pred = model.predict(test_x)
计算混淆矩阵
pd.DataFrame(confusion_matrix(test_y, test_y_pred), columns=y_encoder.classes_, index=y_encoder.classes_)

·输出结果

    体育    健康    女人    娱乐    房地产    教育    文化    新闻    旅游    汽车    科技    财经
体育    193 1   0   1   0   0   3   2   0   0   0   0
健康    0   165 9   0   0   4   0   7   3   0   4   8
女人    1   5   167 4   0   0   13  5   3   0   1   1
娱乐    0   1   9   164 0   5   17  2   0   0   1   1
房地产    0   1   4   0   180 0   0   3   0   0   1   11
教育    0   0   3   2   0   185 2   6   1   0   1   0
文化    0   3   13  17  0   1   153 8   2   1   2   0
新闻    1   4   6   5   1   12  4   124 5   2   11  25
旅游    0   2   8   0   6   1   8   8   163 0   1   3
汽车    1   1   3   0   0   0   0   4   2   182 1   6
科技    0   1   0   0   0   2   2   12  5   1   164 13
财经    1   4   3   0   12  0   4   19  2   4   11  140
计算各项评价指标
def eval_model(y_true, y_pred, labels):
    # 计算每个分类的Precision, Recall, f1, support
    p, r, f1, s = precision_recall_fscore_support(y_true, y_pred)
    # 计算总体的平均Precision, Recall, f1, support
    tot_p = np.average(p, weights=s)
    tot_r = np.average(r, weights=s)
    tot_f1 = np.average(f1, weights=s)
    tot_s = np.sum(s)
    res1 = pd.DataFrame({
        u'Label': labels,
        u'Precision': p,
        u'Recall': r,
        u'F1': f1,
        u'Support': s
    })
    res2 = pd.DataFrame({
        u'Label': [u'总体'],
        u'Precision': [tot_p],
        u'Recall': [tot_r],
        u'F1': [tot_f1],
        u'Support': [tot_s]
    })
    res2.index = [999]
    res = pd.concat([res1, res2])
    return res[[u'Label', u'Precision', u'Recall', u'F1', u'Support']]

·输出结果

eval_model(test_y, test_y_pred, y_encoder.classes_)

Label   Precision   Recall  F1  Support
0   体育    0.979695    0.965   0.972292    200
1   健康    0.877660    0.825   0.850515    200
2   女人    0.742222    0.835   0.785882    200
3   娱乐    0.849741    0.820   0.834606    200
4   房地产    0.904523    0.900   0.902256    200
5   教育    0.880952    0.925   0.902439    200
6   文化    0.742718    0.765   0.753695    200
7   新闻    0.620000    0.620   0.620000    200
8   旅游    0.876344    0.815   0.844560    200
9   汽车    0.957895    0.910   0.933333    200
10  科技    0.828283    0.820   0.824121    200
11  财经    0.673077    0.700   0.686275    200
999 总体    0.827759    0.825   0.825831    2400

模型保存

保存模型到文件  pip install dill
#注意  我们要把tfidf特征提取模型保存  标签转换模型   预测模型
!pip install dill
import dill
import pickle
model_file = os.path.join(output_dir, u'model.pkl')
with open(model_file, 'wb') as outfile:
    dill.dump({
        'y_encoder': y_encoder,
        'tfidf': tfidf,
        'lr': model
    }, outfile)

·输出结果

Requirement already satisfied: dill in e:\anacodan\lib\site-packages (0.3.4)

测试模型,对新文档预测

加载新文档数据
new_data = pd.read_csv('sohu_test.txt', sep='\t', header=None, dtype=np.str_, encoding='utf8',error_bad_lines=False, delimiter="\t", names=[u'频道', u'文章'])
new_data.head()

用TFIDF词袋模型进行新闻分类
加载模型
import pickle
model_file = os.path.join(output_dir, u'model.pkl')
with open(model_file, 'rb') as infile:
    model = pickle.load(infile)
对新文档预测(这里只对前10篇预测)
1. 转化为词袋表示
new_x = model['tfidf'].transform(new_data[u'文章'][:50])

·输出结果


E:\ANACODAN\lib\site-packages\sklearn\feature_extraction\text.py:388: UserWarning: Your stop_words may be inconsistent with your preprocessing. Tokenizing the stop words generated tokens ['&', ',', '.', ';', 'e', 'g', 'nbsp', '—', '\u3000', '傥', '兼', '前', '唷', '啪', '啷', '喔', '始', '漫', '然', '特', '竟', '若果', '莫', '见', '设', '说', '达', '非'] not in stop_words.

  warnings.warn('Your stop_words may be inconsistent with '
2. 预测类别
new_y_pred = model['lr'].predict(new_x)
new_y_pred

·输出结果

array([3, 0, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
       3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
       3, 3, 3, 3, 3, 3])
3. 解释类别
pd.DataFrame({u'预测频道': model['y_encoder'].inverse_transform(new_y_pred), u'实际频道': new_data[u'频道'][:50]})

·输出结果

    预测频道    实际频道
0   娱乐    娱乐
1   体育    娱乐
2   娱乐    娱乐
3   娱乐    娱乐
4   教育    娱乐
5   娱乐    娱乐
6   娱乐    娱乐
7   娱乐    娱乐
8   娱乐    娱乐
9   娱乐    娱乐
10  娱乐    娱乐
11  娱乐    娱乐
12  娱乐    娱乐
13  娱乐    娱乐
14  娱乐    娱乐
15  娱乐    娱乐
16  娱乐    娱乐
17  娱乐    娱乐
18  娱乐    娱乐
19  娱乐    娱乐
20  娱乐    娱乐
21  娱乐    娱乐
22  娱乐    娱乐
23  娱乐    娱乐
24  娱乐    娱乐
25  娱乐    娱乐
26  娱乐    娱乐
27  娱乐    娱乐
28  娱乐    娱乐
29  娱乐    娱乐
30  娱乐    娱乐
31  娱乐    娱乐
32  娱乐    娱乐
33  娱乐    娱乐
34  娱乐    娱乐
35  娱乐    娱乐
36  娱乐    娱乐
37  娱乐    娱乐
38  娱乐    娱乐
39  娱乐    娱乐
40  娱乐    娱乐
41  娱乐    娱乐
42  娱乐    娱乐
43  娱乐    娱乐
44  娱乐    娱乐
45  娱乐    娱乐
46  娱乐    娱乐
47  娱乐    娱乐
48  娱乐    娱乐
49  娱乐    娱乐

主函数,调用模型对新闻进行预测

加载模型
import pickle
import os
import numpy as np
import pandas as pd

output_dir = u'output'
if not os.path.exists(output_dir):
    os.mkdir(output_dir)

model_file = os.path.join(output_dir, u'model.pkl')
with open(model_file, 'rb') as infile:
    model = pickle.load(infile)

oo = 1
while oo == 1:
    f = open('yuce.txt', 'w', encoding='utf8')
    f.write(input())
    f.close()
    new1_data = pd.read_csv('yuce.txt', sep='\t', header=None, dtype=np.str_, encoding='utf8', names=[u'文章'])
    new1_data.head()
    # 加载模型
    import pickle

    model_file = os.path.join(output_dir, u'model.pkl')
    with open(model_file, 'rb') as infile:
        model = pickle.load(infile)
    new1_x = model['tfidf'].transform(new1_data[u'文章'])
    # 2. 预测类别
    new1_y_pred = model['lr'].predict(new1_x)
    pd.DataFrame({u'预测频道': model['y_encoder'].inverse_transform(new1_y_pred)})
    print(pd.DataFrame({u'预测频道': model['y_encoder'].inverse_transform(new1_y_pred)}))
    with open(r'yuce.txt', 'a+', encoding='utf-8') as test:
        test.truncate(0)

Original: https://blog.csdn.net/weixin_57231611/article/details/120915342
Author: 赵有才er
Title: 用TFIDF词袋模型进行新闻分类

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/699793/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球