当前位置:   article > 正文

机器学习之文本分类预测,包含jieba分词和模型优化_文本预测模型

文本预测模型

本文的应用场景是对文本类字段进行预处理(包括分词、词语频次计算)、常用分类模型建模以及模型参数调优,对刚接触文本分类建模的同学能够有一个完整的操作路径呈现。

目录

1.导入模块

2.数据预处理

TF-IDF和Word Counts对比

3.建模预测

4.模型优化

关于cv

三种参数优化方法对比


1.导入模块

  1. import pandas as pd
  2. import numpy as np
  3. import jieba
  4. import re
  5. from opencc import OpenCC #繁体转简体
  6. from sklearn import preprocessing
  7. from sklearn.linear_model import LogisticRegression
  8. from bayes_opt import BayesianOptimization
  9. from sklearn.svm import SVC
  10. from sklearn.tree import DecisionTreeClassifier
  11. from sklearn.ensemble import RandomForestClassifier
  12. from sklearn.model_selection import train_test_split
  13. import xgboost as xgb
  14. import time

2.数据预处理

  1. '''假设已经有一个待处理的数据集data,
  2. 已转换为dataframe形式,
  3. 包含一个特征列name和一个预测列category'''
  4. # 由于后续划分训练集和测试集时,若训练集分类数量小于2则会报错,
  5. # 因此这里筛选分类数量大于50的数据,避免出现某分类数量小于2的情况
  6. filtered_values = value_counts[value_counts < 50].index.tolist()
  7. print(filtered_values) #输出被删除的分类
  8. data=data[~data['category'].isin(filtered_values)]
  9. print(data.shape)
  10. cc = OpenCC('D:/python/python3.9.13/Lib/site-packages/opencc/config/t2s') #繁体转简体文件
  11. #清洗name字段,可根据字段的特点做特殊化处理,
  12. #这里作了去掉除中文数字英文外的字符、英文统一小写、中文繁体转简体的操作
  13. data['name_clean'] = data['name'].apply(lambda x: cc.convert(re.sub(r'[\u4e00-\u9fa5a-zA-Z0-9]','',x).lower()
  14. #jieba分词
  15. data['jieba_cut'] = data['name_clean'].apply(lambda i:jieba.cut(i))
  16. data['jieba_cut'] =[' '.join(i) for i in data['jieba_cut']]
  17. # 将文本标签转化为数字
  18. lbl_enc = preprocessing.LabelEncoder()
  19. y = lbl_enc.fit_transform(data.category.values.reshape(-1, 1))
  20. X= data.jieba_cut.values
  21. # 将数据分成训练和验证集
  22. xtrain, xtest, ytrain, ytest = train_test_split(X, y, stratify=y, random_state=42, test_size=0.3, shuffle=True)
  23. print (xtrain.shape)
  24. print (xtest.shape)
  25. # 使用TF-IDF来fit训练集和测试集(半监督学习)
  26. def number_normalizer(tokens):
  27. """ 将所有数字标记映射为一个占位符(Placeholder)。
  28. 对于许多实际应用场景来说,以数字开头的tokens不是很有用,
  29. 但这样tokens的存在也有一定相关性。 通过将所有数字都表示成同一个符号,可以达到降维的目的。
  30. """
  31. return ("#NUMBER" if token[0].isdigit() else token for token in tokens)
  32. class NumberNormalizingVectorizer(TfidfVectorizer):
  33. def build_tokenizer(self):
  34. tokenize = super(NumberNormalizingVectorizer, self).build_tokenizer()
  35. return lambda doc: list(number_normalizer(tokenize(doc)))
  36. stwlist=[] #停用词,可自定义
  37. tfv = NumberNormalizingVectorizer(min_df=3,
  38. max_df=0.5,
  39. max_features=None,
  40. ngram_range=(1, 2),
  41. use_idf=True,
  42. smooth_idf=True,
  43. stop_words = stwlist
  44. )
  45. tfv.fit(list(xtrain) + list(xtest))
  46. xtrain_tfv = tfv.transform(xtrain)
  47. xtest_tfv = tfv.transform(xtest)

TF-IDF和Word Counts对比

TF-IDF(Term Frequency-Inverse Document Frequency)和Word Counts(词频统计)都是文本处理中常用的技术,但它们有一些不同点。

定义

  • Word Counts:简单地计算每个单词在文档中出现的次数。
  • TF-IDF:除了计算每个单词在文档中出现的次数,还考虑到了该单词在整个语料库中的出现频率以及单词对文档的重要性。

特点

  • Word Counts:简单易实现,对于短文本效果较好,但对于长文本或者大量文档,会出现很多重复的常见词汇,从而降低了区分度。
  • TF-IDF:可以减少常见单词的出现频率对区分度的影响,更能够准确地找到关键词,因此在长文本和大量文档的情况下表现更好。同时,TF-IDF 也能够反映单词对于文档的重要性,因此可以用于文本分类、信息检索等任务。

计算公式

  • Word Counts:词频 = 某个单词在文档中出现的次数 / 文档中总的单词数
  • TF-IDF:tf - idf = tf * idf

其中,tf 表示单词在文档中的出现频率,idf 表示某个单词在整个语料库中的出现频率,公式如下:

应用场景

  • Word Counts:适用于短文本或者对文本的整体特征不太关注的情况(如文本分类中的朴素贝叶斯算法)。
  • TF-IDF:适用于长文本或者需要重点关注文本中关键词的情况,如搜索引擎排名、信息检索等。

综上,如果你需要提取文本中的关键信息并进行分类或搜索,应该使用 TF-IDF;如果你只是统计文本中的出现次数,并不需要考虑文本中关键词的重要性,则可以使用 Word Counts。

附上Word Counts的使用代码

  1. from sklearn.feature_extraction.text import CountVectorizer
  2. # 词汇计数(Word Counts)
  3. ctv = CountVectorizer(min_df=3,
  4. max_df=0.5,
  5. ngram_range=(1,2))
  6. ctv.fit(list(xtrain) + list(xtest))
  7. xtrain_ctv = ctv.transform(xtrain)
  8. xtest_ctv = ctv.transform(xtest)

3.建模预测

  1. #为了初步筛选适合的模型,以字典容纳常用的分类模型,并以各个模型的默认参数形式进行训练
  2. start_time=time.time()
  3. clf_dict={"逻辑回归":LogisticRegression(),"SVM":SVC(),"朴素贝叶斯":MultinomialNB(),"决策树":DecisionTreeClassifier(),"随机森林":RandomForestClassifier(),"XGBOOST":xgb.XGBClassifier()}
  4. for clf_name in clf_dict:
  5. clf=clf_dict[clf_name]
  6. clf.fit(xtrain_tfv,ytrain)
  7. print("模型得分:",clf_name,":",clf.score(xtest_tfv,ytest))
  8. print("模型对象:",clf.get_params())
  9. end_time = time.time()
  10. print("模型运行时间:",round((end_time-start_time)/60,2),'分钟')

4.模型优化

模型参数调优常用的方法有三种:随机搜索法、贝叶斯优化法以及网格搜索法,一般所耗时间从小到大。由于前两种方法都带有一定的随机性,而本次优化的目的是希望找到全局最优解,因此选择网格搜索法作为此次模型优化的方法。

  1. #网格搜索法调参,以逻辑回归模型为例
  2. clf=LogisticRegression()
  3. #模型的参数集合
  4. params={'penalty': ['l1', 'l2'],
  5. 'C': [0.01, 0.1, 1, 10, 100],
  6. 'max_iter': [10, 100, 1000],
  7. 'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag']}
  8. grid_search = GridSearchCV(estimator=clf, param_grid=params, cv=5)
  9. grid_search.fit(xtrain_tfv , ytrain)
  10. # 网格搜索训练后的副产品
  11. print("模型的最优参数:",grid_search.best_params_)
  12. print("最优模型分数:",grid_search.best_score_)
  13. print("最优模型对象:",grid_search.best_estimator_)

关于cv

在使用 GridSearchCV 进行网格搜索时,参数 cv 是用来指定交叉验证的折数(folds)或者交叉验证生成器。它决定了将数据集划分为多少个部分来进行交叉验证。

通常情况下,较小的 cv 值会导致训练时间更快,但估计的性能可能会有较大的方差。较大的 cv 值会导致训练时间更长,但估计的性能通常会更稳定。

选择合适的 cv 值需要考虑以下几个因素:

  1. 数据集的大小:如果数据集较小,使用较小的 cv 值可能更合适,以避免过度拆分数据。而对于较大的数据集,可以选择较大的 cv 值以更好地利用数据。

  2. 计算资源:较大的 cv 值需要更长的训练时间和更多的计算资源。如果你的计算资源有限,可能需要选择较小的 cv 值。

  3. 模型复杂度:如果你的模型非常复杂,较小的 cv 值可能不足以准确评估模型的性能。在这种情况下,可以考虑使用较大的 cv 值。

一般来说,cv 值可以在 3 到 10 之间选择。常见的选择有 5 折交叉验证 (cv=5) 和 10 折交叉验证 (cv=10)。

三种参数优化方法对比

  • 网格搜索(Grid Search):

    • 优点:简单易懂,适用于小规模参数空间;能够找到给定参数范围内的最佳组合。
    • 缺点:计算开销大,在参数空间较大时效率低;无法考虑参数之间的依赖关系;可能会导致过拟合。
  • 随机搜索(Random Search):

    • 优点:相对于网格搜索,计算开销较小;可以在较大的参数空间中搜索,不受参数间依赖关系的限制。
    • 缺点:搜索过程是随机的,无法保证找到全局最优解;可能需要更多的迭代次数才能找到好的结果。
  • 贝叶斯优化(Bayesian Optimization):

    • 优点:通过建立参数的先验模型,可以根据过去的观察结果进行参数搜索,更加高效地找到最佳参数组合;能够处理高维参数空间和非凸优化问题。
    • 缺点:实现相对复杂,需要选择适当的先验模型和采样策略;可能对初始观察结果敏感。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/243323
推荐阅读
相关标签
  

闽ICP备14008679号