【NLP 27、文本分类任务 —— 传统机器学习算法】

不要抓着枯叶哭泣,你要等待初春的新芽

                                                        —— 25.1.23

一、文本分类任务

定义:预先设定好一个文本类别集合,对于一篇文本,预测其所属的类别

例如:

         情感分析:

                这家饭店太难吃了 —> 正类                

                这家菜很好吃        —> 负类

         领域分类:

                今日A股行情大好  —> 经济

                今日湖人击败勇士 —> 体育


二、文本分类 — 使用场景

1.资讯文章打标签

将大的分类再分成二级分类,进行小部分分类

2.电商评论分析

可以进一步分析,当作不同类别,分析具体的好/差评原因

3.违规检测

涉黄、涉暴、涉恐、辱骂等

主要应用在客服、销售对话质检、或网站内容审查等


三、自定义类别任务

类别的定义方式是任意

只要人基于文本能够判断,都可以作为分类类别

如: 垃圾邮件分类、② 对话、文章是否与汽车交易相关、③ 文章风格是否与某作者风格一致、④ 文章是否是机器生成、⑤ 合同文本是否符合规范、⑥ 文章适合阅读人群(未成年、中年、老年、孕妇等)


四、文本分类 — 机器学习

① 定义类别 ——> ② 收集数据 ——> ③ 模型训练 ——> ④ 预测

1.定义类别

首先定义有几个类别

2.收集数据

对于每个类别作数据的收集和标注

3.模型训练

将类别数据送到一个分类器(神经网络 / 机器学习中的其他方法)中去

4.预测

用这个分类器对一些未知文本类别的文本去预测一些类别


五、传统机器学习算法 ① 贝叶斯算法

1.全概率公式

事件A的概率:等于在每种划分之下,划分事件 Bi 的概率 × 在这个划分下事件 A 的概率


2.贝叶斯公式

①  

② 

③ 

P(A|B):后验概率,表示在已知事件B发生的情况下,事件A发生的概率

P(B|A):似然度,在事件A发生的条件下,事件B发生的概率

P(A):先验概率,是在没有任何关于B的信息时,对事件A发生概率的初始估计

P(B):边缘概率,可以通过全概率公式进行计算

B事件发生下,A事件发生的概率 = A事件发生的概率 × A事件发生下,B事件发生的概率 除以 B事件发生的概率


3.贝叶斯公式的应用

求解:如果核酸检测呈阳性,感染新冠的概率是多少?

我们假定新冠在人群中的感染率为0.1%(先验概率:千分之一 0.001)【先验 / 前置概率】

核酸检测有一定误报率,我们假定如下:

P(A) = 感染新冠

P(B) = 核酸检测呈阳性 

P(A | B) = 核酸检测呈阳性,确实感染新冠

P(B | A) = 感染了新冠,且检测结果呈阳性

P(B | ^A) = 未感染新冠,且检测结果呈阳性

计算如下:

        P(A | B) = P(A) * P(B | A) / P (B)

        P(B) = P(B | A) * P(A) + P(B | ^A) * P(^A) # 全概率公式

        P(A | B) = P(A) * P(B | A) /【P(B | A) * P(A) + P(B | ^A) * P(^A)】

                     = 0.001 × 0.99 / (0.99 × 0.001 + 0.05 × 0.999)

                     ≈ 0.019 ≈ 0.02


4.贝叶斯公式在NLP中的应用

用贝叶斯公式处理文本分类任务

一个合理假设:文本属于哪个类别,与文本中包含哪些词相关

任务:知道文本中有哪些词,预测文本属于某类别的概率


5.贝叶斯公式 — 文本分类

假定有3个类别A1, A2, A3

一个文本S有n个词组成,W1, W2, W3....Wn

想要计算文本S属于A1类别的概率:P(A1|S)  = P(A1|W1, W2, W3....Wn)

除以公共分母,得出的所有类别可能性加和为1,近似于做自动归一化

# 贝叶斯公式

# 分母是公共的,可以不进行计算

P(A1 | S) = P(W1, W2…Wn | A1)  * P(A1) / P(W1,W2…Wn)

P(A2 | S) = P(W1, W2…Wn | A2)  * P(A2) / P(W1,W2…Wn)

P(A3 | S) = P(W1, W2…Wn | A3)  * P(A3) / P(W1,W2…Wn)

# 词的独立性假设

P(W1, W2…Wn | A3)  = P(W1 | A3) * P(W2 | A3) *… * P(Wn | A3) 


6.贝叶斯公式 — 代码实现

jieba.initialize():是 ​jieba​ 分词库中的一个函数,用于初始化分词所需的词典和配置。在某些情况下,特别是在多线程或分布式环境中使用 jieba 时,显式调用 initialize() 可以确保分词器正确加载词典并优化性能。

参数类型说明
enable_parallelint 或 False是否启用并行分词。如果设置为 True,则启用并行分词;如果设置为具体的整数,表示并行分词的线程数;默认为 False,即不启用并行分词。
use_paddlebool是否启用 PaddlePaddle 模式。如果设置为 True,则启用 PaddlePaddle 模式进行分词;默认为 False,即不启用该模式。使用此模式需要安装 PaddlePaddle 库。
user_dictstr用户自定义词典的路径。通过设置此参数,可以让 jieba 加载指定的自定义词典,以便在分词时识别特定的词汇。
cut_allbool是否使用全模式分词。如果设置为 True,则使用全模式分词,即把句子中所有的可以成词的词语都扫描出来;如果设置为 False,则使用精确模式分词,即试图将句子最精确地切开;默认为 False
HMMbool是否使用 HMM 模型来识别新词。如果设置为 True,则使用 HMM 模型;如果设置为 False,则不使用 HMM 模型;默认为 True
use_parallelbool 或 int是否启用并行分词及并行分词的线程数。如果设置为 True,则启用并行分词,默认使用CPU核心数;如果设置为整数,则指定并行分词的线程数;默认为 False

Ⅰ、初始化

defaultdict():Python 标准库 collections 模块中的一个类,用于创建具有默认值的字典。当访问一个不存在的键时,defaultdict 会自动创建该键并赋予一个默认值,而不会抛出 KeyError 异常。这在处理数据聚合、计数等场景中非常有用。

参数类型说明
default_factory可调用对象(如函数、类等)用于生成默认值的工厂函数。当访问一个不存在的键时,defaultdict 会调用此工厂函数来生成默认值。常见的用法包括 int(默认值为 0)、list(默认值为 [])、set(默认值为 set())等。如果未提供此参数,defaultdict 的行为类似于普通字典,访问不存在的键时会抛出 KeyError
**kwargs任意关键字参数传递给字典的其他关键字参数,通常用于初始化字典。例如,可以传递一个可迭代对象来初始化字典的键值对。
    def __init__(self, data_path):self.p_class = defaultdict(int)self.word_class_prob = defaultdict(dict)self.load(data_path)

Ⅱ、加载语料文件

defaultdict():Python 标准库 collections 模块中的一个类,用于创建具有默认值的字典。当访问一个不存在的键时,defaultdict 会自动创建该键并赋予一个默认值,而不会抛出 KeyError 异常。这在处理数据聚合、计数等场景中非常有用。

参数类型说明
default_factory可调用对象(如函数、类等)用于生成默认值的工厂函数。当访问一个不存在的键时,defaultdict 会调用此工厂函数来生成默认值。常见的用法包括 int(默认值为 0)、list(默认值为 [])、set(默认值为 set())等。如果未提供此参数,defaultdict 的行为类似于普通字典,访问不存在的键时会抛出 KeyError
**kwargs任意关键字参数传递给字典的其他关键字参数,通常用于初始化字典。例如,可以传递一个可迭代对象来初始化字典的键值对。

set(): Python 内置函数,用于创建一个无序且不重复的集合(set)。集合中的元素必须是可哈希的(即不可变类型),如数字、字符串、元组等。集合常用于去重、集合运算(如并集、交集、差集)等操作。

参数类型说明
iterable可迭代对象(可选)用于初始化集合的可迭代对象,如列表、元组、字符串等。如果未提供,则创建一个空集合。

json.loads(): Python json 模块中的函数,用于将 JSON 格式的字符串解析为 Python 对象(如字典、列表、字符串、数字等)。常用于处理来自网络请求、文件读取等的 JSON 数据。

参数类型说明
sstr要解析的 JSON 格式字符串。
cls可选,json.JSONDecoder 的子类用于解码的自定义解码器类,默认为 json.JSONDecoder
object_hook可选,函数用于自定义解码特定类型的对象。
parse_float可选,函数用于解析浮点数的函数,默认为 float
parse_int可选,函数用于解析整数的函数,默认为 int
parse_constant可选,函数用于解析 JSON 常量(如 nulltruefalse)的函数。
object_pairs_hook可选,函数用于自定义解码对象对的函数,优先级高于 object_hook
strict可选,bool如果为 True,则在遇到非法字符时抛出异常,默认为 True
buffering可选,bool已弃用,忽略此参数。

jieba.lcut():jieba 分词库中的函数,用于将输入的字符串进行分词,并返回一个列表。与 jieba.cut() 不同,lcut() 直接返回列表,而 cut() 返回一个生成器。

参数类型说明
sentencestr需要分词的字符串。
cut_allbool是否使用全模式分词。True 表示全模式,False 表示精确模式(默认)。
HMMbool是否使用 HMM 模型识别新词。True 表示使用,False 表示不使用(默认)。
use_paddlebool是否启用 PaddlePaddle 模式进行分词。需要安装 PaddlePaddle 库。True 或 False
user_dictstr用户自定义词典的路径,用于增强分词效果。

union():集合(set)对象的方法,用于返回两个或多个集合的并集。并集包含所有出现在任一集合中的元素,且不重复。

参数类型说明
*othersset 或可迭代对象一个或多个要合并到当前集合的其他集合或可迭代对象。
    def load(self, path):self.class_name_to_word_freq = defaultdict(dict)self.all_words = set()  #汇总一个词表with open(path, encoding="utf8") as f:for line in f:line = json.loads(line)class_name = line["tag"]title = line["title"]words = jieba.lcut(title)self.all_words = self.all_words.union(set(words))self.p_class[class_name] += 1  #记录每个类别样本数量word_freq = self.class_name_to_word_freq[class_name]#记录每个类别下的词频for word in words:if word not in word_freq:word_freq[word] = 1else:word_freq[word] += 1self.freq_to_prob()return

Ⅲ、将词频和样本频率转化为概率

sum():Python 的内置函数,用于计算可迭代对象(如列表、元组等)中所有元素的总和。它也可以用于将一个可迭代对象中的元素累加到一个初始值上。

参数类型说明
iterable可迭代对象(如列表、元组、集合等)要计算总和的可迭代对象。
startint 或 float(可选)累加的初始值,默认为 0

.values(): Python 字典(dict)的方法,用于返回字典中所有值的视图对象。这个视图对象显示的是字典中所有值的动态视图,当字典的值发生变化时,视图也会反映这些变化。 

dict(): Python 的内置函数,用于创建一个新的字典(dict)。它可以通过多种方式初始化字典,包括从另一个字典、键值对的可迭代对象、关键字参数等。

参数类型说明
object映射对象或可迭代对象(可选)如果提供,object 应该是一个映射(如另一个字典)或包含键值对的可迭代对象。
**kwargs关键字参数(可选)任意数量的关键字参数,用于初始化字典。每个关键字参数的键和值将成为字典中的键值对。

defaultdict():Python 标准库 collections 模块中的一个类,用于创建具有默认值的字典。当访问一个不存在的键时,defaultdict 会自动创建该键并赋予一个默认值,而不会抛出 KeyError 异常。这在处理数据聚合、计数等场景中非常有用。

参数类型说明
default_factory可调用对象(如函数、类等)用于生成默认值的工厂函数。当访问一个不存在的键时,defaultdict 会调用此工厂函数来生成默认值。常见的用法包括 int(默认值为 0)、list(默认值为 [])、set(默认值为 set())等。如果未提供此参数,defaultdict 的行为类似于普通字典,访问不存在的键时会抛出 KeyError
**kwargs任意关键字参数传递给字典的其他关键字参数,通常用于初始化字典。例如,可以传递一个可迭代对象来初始化字典的键值对。

items():Python 字典(dict)的方法,用于返回字典中所有键值对的视图对象。这个视图对象显示的是字典条目的动态视图,意味着当字典发生变化时,视图也会反映这些变化。

len():Python 的内置函数,用于返回对象(如字符串、列表、字典、集合等)的长度或项目数量。

参数类型说明
object任何可迭代或可计数的对象(如字符串、列表、字典、集合、元组等)要计算长度的对象。
    #将记录的词频和样本频率都转化为概率def freq_to_prob(self):#样本概率计算total_sample_count = sum(self.p_class.values())self.p_class = dict([c, self.p_class[c] / total_sample_count] for c in self.p_class)#词概率计算self.word_class_prob = defaultdict(dict)for class_name, word_freq in self.class_name_to_word_freq.items():total_word_count = sum(count for count in word_freq.values()) #每个类别总词数for word in word_freq:#加1平滑,避免出现概率为0,计算P(wn|x1)prob = (word_freq[word] + 1) / (total_word_count + len(self.all_words))self.word_class_prob[class_name][word] = probself.word_class_prob[class_name]["<unk>"] = 1/(total_word_count + len(self.all_words))return

Ⅳ、计算给定单词序列的联合概率

.get():Python 字典(dict)对象的一个方法,用于获取指定键对应的值。如果键不存在于字典中,.get() 方法可以返回一个默认值,而不是引发 KeyError 异常。这使得 .get() 方法在处理字典时更加安全和便捷。

    #P(w1|x1) * P(w2|x1)...P(wn|x1)def get_words_class_prob(self, words, class_name):result = 1for word in words:unk_prob = self.word_class_prob[class_name]["<unk>"]result *= self.word_class_prob[class_name].get(word, unk_prob)return result

Ⅴ、计算特定事件类别x下的联合概率

    #计算P(w1, w2..wn|x1) * P(x1)def get_class_prob(self, words, class_name):#P(x1)p_x = self.p_class[class_name]# P(w1, w2..wn|x1) = P(w1|x1) * P(w2|x1)...P(wn|x1)p_w_x = self.get_words_class_prob(words, class_name)return p_x * p_w_x

Ⅵ、文本分类

jieba.lcut():jieba 分词库中的函数,用于将输入的字符串进行分词,并返回一个列表。与 jieba.cut() 不同,lcut() 直接返回列表,而 cut() 返回一个生成器。

参数类型说明
sentencestr需要分词的字符串。
cut_allbool是否使用全模式分词。True 表示全模式,False 表示精确模式(默认)。
HMMbool是否使用 HMM 模型识别新词。True 表示使用,False 表示不使用(默认)。
use_paddlebool是否启用 PaddlePaddle 模式进行分词。需要安装 PaddlePaddle 库。True 或 False
user_dictstr用户自定义词典的路径,用于增强分词效果。

append():Python 列表(list)的方法,用于在列表的末尾添加一个新的元素。

参数类型说明
object任意类型要添加到列表末尾的对象。可以是任何数据类型,如整数、字符串、列表等。

sorted():Python 的内置函数,用于对可迭代对象进行排序,并返回一个新的排序后的列表。原对象不会被修改。

参数类型说明
iterable可迭代对象需要排序的对象,如列表、元组、字符串等。
key可选,函数用于提取比较键的函数。默认为 None,即直接比较元素。
reverse可选,布尔值如果设置为 True,则列表元素将被倒序(从大到小)排列。默认为 False

sum():Python 的内置函数,用于计算可迭代对象(如列表、元组等)中所有元素的总和。它也可以用于将一个可迭代对象中的元素累加到一个初始值上。

参数类型说明
iterable可迭代对象(如列表、元组、集合等)要计算总和的可迭代对象。
startint 或 float(可选)累加的初始值,默认为 0
    #做文本分类def classify(self, sentence):words = jieba.lcut(sentence) #切词results = []for class_name in self.p_class:prob = self.get_class_prob(words, class_name)  #计算class_name类概率results.append([class_name, prob])results = sorted(results, key=lambda x:x[1], reverse=True) #排序#计算公共分母:P(w1, w2, w3...wn) = P(w1,w2..Wn|x1)*P(x1) + P(w1,w2..Wn|x2)*P(x2) ... P(w1,w2..Wn|xn)*P(xn)#不做这一步也可以,对顺序没影响,只不过得到的不是0-1之间的概率值pw = sum([x[1] for x in results]) #P(w1, w2, w3...wn)results = [[c, prob/pw] for c, prob in results]#打印结果for class_name, prob in results:print("属于类别[%s]的概率为%f" % (class_name, prob))return results

Ⅶ、贝叶斯文本分类实践 

import math
import jieba
import re
import os
import json
from collections import defaultdictjieba.initialize()"""
贝叶斯分类实践P(A|B) = (P(A) * P(B|A)) / P(B)
事件A:文本属于类别x1。文本属于类别x的概率,记做P(x1)
事件B:文本为s (s=w1w2w3..wn)
P(x1|s) = 文本为s,属于x1类的概率.   #求解目标#
P(x1|s) = P(x1|w1, w2, w3...wn) = P(w1, w2..wn|x1) * P(x1) / P(w1, w2, w3...wn)P(x1) 任意样本属于x1的概率。x1样本数/总样本数
P(w1, w2..wn|x1) = P(w1|x1) * P(w2|x1)...P(wn|x1)  词的独立性假设
P(w1|x1) x1类样本中,w1出现的频率公共分母的计算,使用全概率公式:
P(w1, w2, w3...wn) = P(w1,w2..Wn|x1)*P(x1) + P(w1,w2..Wn|x2)*P(x2) ... P(w1,w2..Wn|xn)*P(xn)
"""class BayesApproach:def __init__(self, data_path):self.p_class = defaultdict(int)self.word_class_prob = defaultdict(dict)self.load(data_path)def load(self, path):self.class_name_to_word_freq = defaultdict(dict)self.all_words = set()  #汇总一个词表with open(path, encoding="utf8") as f:for line in f:line = json.loads(line)class_name = line["tag"]title = line["title"]words = jieba.lcut(title)self.all_words = self.all_words.union(set(words))self.p_class[class_name] += 1  #记录每个类别样本数量word_freq = self.class_name_to_word_freq[class_name]#记录每个类别下的词频for word in words:if word not in word_freq:word_freq[word] = 1else:word_freq[word] += 1self.freq_to_prob()return#将记录的词频和样本频率都转化为概率def freq_to_prob(self):#样本概率计算total_sample_count = sum(self.p_class.values())self.p_class = dict([c, self.p_class[c] / total_sample_count] for c in self.p_class)#词概率计算self.word_class_prob = defaultdict(dict)for class_name, word_freq in self.class_name_to_word_freq.items():total_word_count = sum(count for count in word_freq.values()) #每个类别总词数for word in word_freq:#加1平滑,避免出现概率为0,计算P(wn|x1)prob = (word_freq[word] + 1) / (total_word_count + len(self.all_words))self.word_class_prob[class_name][word] = probself.word_class_prob[class_name]["<unk>"] = 1/(total_word_count + len(self.all_words))return#P(w1|x1) * P(w2|x1)...P(wn|x1)def get_words_class_prob(self, words, class_name):result = 1for word in words:unk_prob = self.word_class_prob[class_name]["<unk>"]result *= self.word_class_prob[class_name].get(word, unk_prob)return result#计算P(w1, w2..wn|x1) * P(x1)def get_class_prob(self, words, class_name):#P(x1)p_x = self.p_class[class_name]# P(w1, w2..wn|x1) = P(w1|x1) * P(w2|x1)...P(wn|x1)p_w_x = self.get_words_class_prob(words, class_name)return p_x * p_w_x#做文本分类def classify(self, sentence):words = jieba.lcut(sentence) #切词results = []for class_name in self.p_class:prob = self.get_class_prob(words, class_name)  #计算class_name类概率results.append([class_name, prob])results = sorted(results, key=lambda x:x[1], reverse=True) #排序#计算公共分母:P(w1, w2, w3...wn) = P(w1,w2..Wn|x1)*P(x1) + P(w1,w2..Wn|x2)*P(x2) ... P(w1,w2..Wn|xn)*P(xn)#不做这一步也可以,对顺序没影响,只不过得到的不是0-1之间的概率值pw = sum([x[1] for x in results]) #P(w1, w2, w3...wn)results = [[c, prob/pw] for c, prob in results]#打印结果for class_name, prob in results:print("属于类别[%s]的概率为%f" % (class_name, prob))return resultsif __name__ == "__main__":path = "F:\人工智能NLP/NLP\Day7_文本分类问题\data/train_tag_news.json"ba = BayesApproach(path)query = "中国三款导弹可发射多弹头 美无法防御很急躁"ba.classify(query)


7.贝叶斯算法的优点和缺点

缺点:

① 如果样本不均衡会极大影响先验概率

② 对于未见过的特征或样本,条件概率为零,失去预测的意义(可以引入平滑)

③ 特征独立假设只是个假设

④ 没有考虑语序,也没有词义

优点:

① 简单高效

② 一定的可解释性

③ 如果样本覆盖的好,效果是不错的

④ 训练数据可以很好的分批处理


六、传统机器学习算法 ② 支持向量机 SVM

SVM:support vector machine,1964年提出

属于有监督学习 supervised learning

通过数据样本,学习最大边距超平面

引例:尝试用一条线将蓝色球与红色三角分开

SVM分类器:类别不同的样本进行切分,并且要尽可能的让两类数据中最近的支持向量 距离这条分割函数最远(目标是最大化marginmargin:分类线到两边最近的支持向量的距离)【寻找一个最优的决策边界距离两个类别的最近的样本(称为支持向量)最远】

线性(直线)可分问题下的决策函数:

线性(直线)不可分问题:SVM算法中,将空间映射到更高的维度来分类非线性数据

神经网络中:添加激活函数来拟合非线性数据分布】


1.支持向量机 — 核函数

为了解决线性不可分问题,我们需要把输入映射到高维,即寻找函数,使其输出维度高于x  

例如: x = [X1, X2, X3]  

=  [X1*X1,  X1*X2,  X1*X3,  X2*X1,  X2*X2,  X2*X3,  X3*X1,  X3*X2,  X3*X3]   (对自己做笛卡尔积)

这样x就从3维上升到9维

向高维映射如何解决线性不可分问题?

示例:

考虑一组一维数据,[-1, 0, 1] 为正样本,[-3, -2, 2, 3]为负样本

将x映射为【x,  x^2】后 ,可以用直线划分,更高维度也是同理

但是这样出现一个问题,维度过高的向量计算在进行内积运算非常耗时,而svm的求解中内积运算很频繁

所以我们希望内有一种方法快速计算内积运算【

核函数的意义:

两个向量x1、x2过一个核函数之后的结果,恰好等于这两个向量x1、x2分别通过一个高维映射然后再做内积得到的结果,基于核函数可以简化支持向量机中的内积运算

绕过向高维空间映射的向量内积运算,直接代入计算核函数的公式,使得经过核函数运算后的向量恰好等于原向量经过向量内积运算映射到高维空间

所谓的【核函数即为满足条件:【】的函数,这些函数统称为核函数


2.常见核函数

线性核函数:

多项式核函数:

高斯核函数:

双曲正切核函数:


3.支持向量机 — 解决多分类问题

假设要解决一个K分类问题,即有K个目标类别

方式一:one vs one方式

建立 K(K - 1) / 2 个svm分类器,每个分类器负责K个类别中的两个类别,判断输入样本属于哪个类别

对于一个待预测的样本,使用所有分类器进行分类,最后保留被预测词数最多的类别

例:假设类别有[A,B,C]

        X —> SVM(A,B) —> A

        X —> SVM(A,C) —> A

        X —> SVM(B,C) —> B

最终判断   X —> A


方式二:one vs rest方式

建立K个svm分类器,每个分类器负责划分输入样本属于K个类别中的某一个类别的概率,最后保留预测分值最高的类别

例:假设类别有[A,B,C]

        X —> SVM(A,rest) —> 0.1

        X —> SVM(B,rest) —> 0.2

        X —> SVM(C,rest) —> 0.5

最终判断: X —> C 


4.支持向量机的优缺点

优点:

        ① 少数支持向量决定了最终结果,对异常值不敏感

        ② 对于样本数量需求较低

        ③ 可以处理高维度数据

缺点:

        ① 样本数量过多的时候,计算负担很大

        ② 多分类任务处理起来比较麻烦

        ③ 核函数的选取以及参数的选取较为困难


5.代码实现

Ⅰ、加载训练好的模型

Word2Vec.load():加载之前保存的 Word2Vec 模型

参数类型说明
filepath_or_bufferstr 或 file-like object模型文件的路径或文件对象。
*args任意其他参数传递给底层加载机制的其他参数(通常不需要)。
**kwargs任意关键字参数传递给底层加载机制的其他关键字参数(通常不需要)。
#输入模型文件路径
#加载训练好的模型
def load_word2vec_model(path):model = Word2Vec.load(path)return model

Ⅱ、加载数据集

 open():打开一个文件,并返回一个文件对象,用于读取、写入或其他操作。

参数类型说明
filestr 或 path-like object要打开的文件路径。
modestr文件打开模式,如 'r'(读取)、'w'(写入)、'a'(追加)等。
bufferingint缓冲策略。
encodingstr文件编码方式,如 'utf-8'
errorsstr错误处理方式,如 'strict''ignore' 等。
其他参数根据模式不同,可能有其他参数。

json.loads():将 JSON 格式的字符串解析为 Python 对象(如字典、列表等)。

参数类型说明
sstr要解析的 JSON 字符串。
cls可选,json.JSONDecoder 的子类自定义解码器类,默认为 json.JSONDecoder
object_hook可选,函数用于自定义解码特定类型的对象。
其他参数其他可选参数,如 parse_floatparse_int 等。

append():将一个元素添加到列表的末尾。

参数类型说明
object任意类型要添加到列表末尾的对象。

join():将序列中的元素连接成一个字符串,元素之间使用指定的分隔符。

参数类型说明
iterable可迭代对象要连接的元素序列,如列表、元组等。
sepstr元素之间的分隔符,默认为空字符串。

jieba.lcut():使用 jieba 分词库将输入的字符串切分成词语列表。

参数类型说明
sentencestr需要分词的字符串。
cut_allbool是否使用全模式分词。True 表示全模式,False 表示精确模式(默认)。
HMMbool是否使用 HMM 模型识别新词。True 表示使用,False 表示不使用(默认)。
use_paddlebool是否启用 PaddlePaddle 模式进行分词。需要安装 PaddlePaddle 库。True 或 False
user_dictstr用户自定义词典的路径,用于增强分词效果。
#加载数据集
def load_sentence(path, model):sentences = []labels = []with open(path, encoding="utf8") as f:for line in f:line = json.loads(line)title, content = line["title"], line["content"]sentences.append(" ".join(jieba.lcut(title)))labels.append(line["tag"])train_x = sentences_to_vectors(sentences, model)train_y = label_to_label_index(labels)return train_x, train_y

Ⅲ、 将tag标签转换为类别编号

#tag标签转化为类别标号
def label_to_label_index(labels):return [LABELS[y] for y in labels]

Ⅳ、 文本向量化

split():将字符串按照指定的分隔符切分成子字符串列表。

参数类型说明
sepstr 或 None分隔符,默认为任意空白字符。
maxsplitint最大分割次数,默认为 -1,表示不限制。

np.zeros():创建一个指定形状和数据类型的全零数组。

参数类型说明
shapeint 或 tuple数组的形状。
dtypedata-type数组元素的数据类型,默认为 float64
order'C' 或 'F'内存布局方式,'C' 行优先,'F' 列优先,默认为 'C'

append():将一个元素添加到列表的末尾。

参数类型说明
object任意类型要添加到列表末尾的对象。

np.array():创建一个 NumPy 数组。

参数类型说明
objectarray_like输入数据,可以是列表、元组、嵌套列表等。
dtypedata-type数组元素的数据类型,默认由输入数据推断。
copybool是否复制输入数据,默认为 True
ndminint返回数组的最小维度。
其他参数根据具体需求,可能有其他参数。

model.wv():访问 Word2Vec 模型的词向量(word vectors)。

参数类型说明
wordstr要获取词向量的单词。
vectorbool是否返回词向量,默认为 True
其他参数根据具体需求,可能有其他参数。
#文本向量化,使用了基于这些文本训练的词向量
def sentences_to_vectors(sentences, model):vectors = []for sentence in sentences:words = sentence.split()vector = np.zeros(model.vector_size)for word in words:try:vector += model.wv[word]# vector = np.max([vector, model.wv[word]], axis=0)except KeyError:vector += np.zeros(model.vector_size)vectors.append(vector / len(words))return np.array(vectors)

Ⅴ、SVM分类器训练

SVC():支持向量分类器(Support Vector Classifier),用于分类任务

参数类型说明
Cfloat正则化参数,控制误分类的惩罚力度。
kernelstr 或 callable核函数类型,如 'linear''poly''rbf''sigmoid' 等。
degreeint多项式核函数的度数,默认为 3。
gammastr 或 float核函数的系数,'scale' 或 'auto',或具体数值。
coef0float核函数中的独立项。
其他参数根据具体需求,可能有其他参数。

SVC对象.fit():训练支持向量分类器模型。

参数类型说明
Xarray-like训练数据的特征矩阵。
yarray-like训练数据的目标标签。
sample_weightarray-like每个样本的权重。
其他参数根据具体需求,可能有其他参数。

SVC对象.predict():使用训练好的支持向量分类器进行预测。

参数类型说明
Xarray-like需要预测的数据特征矩阵。
返回值array预测的标签。

classification_report():生成一个文本报告,展示主要的分类指标,如精确率(precision)、召回率(recall)、F1 分数等。

参数类型说明
y_truearray-like真实的目标标签。
y_predarray-like预测的目标标签。
labelsarray-like报告中包含的标签列表。
target_nameslist 或 None标签的可读名称。
sample_weightarray-like每个样本的权重。
其他参数根据具体需求,可能有其他参数。
def main():model = load_word2vec_model("model.w2v")train_x, train_y = load_sentence("F:\人工智能NLP\\NLP\Day7_文本分类问题\data\\train_tag_news.json", model)test_x, test_y = load_sentence("F:\人工智能NLP\\NLP\Day7_文本分类问题\data\\valid_tag_news.json", model)classifier = SVC()classifier.fit(train_x, train_y)y_pred = classifier.predict(test_x)print(classification_report(test_y, y_pred))

Ⅵ、使用基于词向量的SVM分类器

#!/usr/bin/env python3  
#coding: utf-8#使用基于词向量的分类器
#对比几种模型的指标import json
import jieba
import numpy as np
from gensim.models import Word2Vec
from sklearn.metrics import classification_report
from sklearn.svm import SVC
from collections import defaultdictLABELS = {'健康': 0, '军事': 1, '房产': 2, '社会': 3, '国际': 4, '旅游': 5, '彩票': 6, '时尚': 7, '文化': 8, '汽车': 9, '体育': 10, '家居': 11, '教育': 12, '娱乐': 13, '科技': 14, '股票': 15, '游戏': 16, '财经': 17}#输入模型文件路径
#加载训练好的模型
def load_word2vec_model(path):model = Word2Vec.load(path)return model#加载数据集
def load_sentence(path, model):sentences = []labels = []with open(path, encoding="utf8") as f:for line in f:line = json.loads(line)title, content = line["title"], line["content"]sentences.append(" ".join(jieba.lcut(title)))labels.append(line["tag"])train_x = sentences_to_vectors(sentences, model)train_y = label_to_label_index(labels)return train_x, train_y#tag标签转化为类别标号
def label_to_label_index(labels):return [LABELS[y] for y in labels]#文本向量化,使用了基于这些文本训练的词向量
def sentences_to_vectors(sentences, model):vectors = []for sentence in sentences:words = sentence.split()vector = np.zeros(model.vector_size)for word in words:try:vector += model.wv[word]# vector = np.max([vector, model.wv[word]], axis=0)except KeyError:vector += np.zeros(model.vector_size)vectors.append(vector / len(words))return np.array(vectors)def main():model = load_word2vec_model("model.w2v")train_x, train_y = load_sentence("F:\人工智能NLP\\NLP\Day7_文本分类问题\data\\train_tag_news.json", model)test_x, test_y = load_sentence("F:\人工智能NLP\\NLP\Day7_文本分类问题\data\\valid_tag_news.json", model)classifier = SVC()classifier.fit(train_x, train_y)y_pred = classifier.predict(test_x)print(classification_report(test_y, y_pred))if __name__ == "__main__":main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/24794.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于YOLO11深度学习的医学X光骨折检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

FastAPI系列:Ubuntu部署FastAPI项目实战

这篇文章提供了在Ubuntu上部署FastAPI应用程序的详细指南。首先&#xff0c;读者将学习如何创建项目目录并设置Python虚拟环境&#xff0c;接着安装FastAPI、Uvicorn和Gunicorn等必要依赖。随后&#xff0c;文章指导用户编写基本的FastAPI应用程序代码&#xff0c;并使用Gunico…

Redis缓存淘汰算法——LRU

文章目录 一、LRU 算法概述1.1 LRU 算法的工作原理1.2 手写LRU 二、Redis 中的 LRU 算法2.1 近似 LRU 算法2.2 如何判断“最近最少使用”的键&#xff1f;2.3 Redis 中的 LRU 配置 在 Redis 中&#xff0c; LRU&#xff08;Latest Recently Used&#xff0c;最近最少使用&…

【原创工具】同文件夹PDF文件合并 By怜渠客

【原创工具】同文件夹PDF文件合并 By怜渠客 原贴&#xff1a;可批量合并多个文件夹内的pdf工具 - 吾爱破解 - 52pojie.cn 他这个存在一些问题&#xff0c;并非是软件内自主实现的PDF合并&#xff0c;而是调用的pdftk这一工具&#xff0c;但楼主并没有提供pdftk&#xff0c;而…

C# Combox 绑定数据

1.在界面中添加一个combox 2.将数据绑定到combox List<GrindingType> type new List<GrindingType>();type.Add(new GrindingType { Id 1, Name "Product A", Type new List<string> { "1", "2" } });type.Add(new Grin…

怎样能写出完美的Prompt

怎样能写出完美的Prompt 大模型发展Prompt 实测最后感受 大模型发展 随着语言大模型的智能化演进&#xff0c;其作为内容生产引擎的核心竞争力日益凸显。如何通过Prompt工程深度释放其潜能&#xff0c;实现工作效率的指数级提升与文本质量的突破性飞跃&#xff0c;本质上是对&…

【含开题报告+文档+PPT+源码】基于SpringBoot+Vue的农村合作社招聘系统

开题报告 本文以服务新农村建设为背景&#xff0c;针对农村劳动力就业信息获取不充分、求职效率低下的问题&#xff0c;设计并实现了农村合作社招聘系统。该平台具备注册登录、个人信息管理、就业资讯发布与互动、岗位搜索、详细信息查看、岗位申请以及申请状态跟踪等功能。系…

数据结构与算法-图论-最短路-拓展运用

选择最佳路线 分析&#xff1a; 这是一道图论中的最短路径问题&#xff0c;目标是在给定的公交网络中&#xff0c;找到从琪琪家附近的车站出发&#xff0c;到她朋友家附近车站&#xff08;编号为 s &#xff09;的最短时间。以下是对该问题的详细分析&#xff1a; 问题关键信息…

鸿道Intewell操作系统的Linux实时拓展方案

在工业控制、智能制造、自动驾驶等领域&#xff0c;实时性一直是操作系统的核心挑战。Linux作为开源系统的代表&#xff0c;虽然具备生态丰富&#xff0c;功能强大的优势&#xff0c;但其内核调度机制与中断处理能力难以满足微秒级硬实时要求。针对这一痛点&#xff0c;鸿道Int…

搭建Nexus前端npm私服,上传发布npm包和下载依赖

1、创建repository 登录Nexus的管理页面&#xff0c;创建npm&#xff08;proxy&#xff09;和npm&#xff08;hosted&#xff09;&#xff0c;然后创建npm&#xff08;group&#xff09;将这两个repository包含进来。 1.1 创建npm&#xff08;proxy&#xff09; 选择npm&…

数组总结【代码随想录】

一.数组 1.lc 27移除数组中的重复元素 且必须仅使用 O(1) 额外空间并 原地 修改输入数组。 输入&#xff1a;nums [3,2,2,3], val 3 输出&#xff1a;2, nums [2,2] 解释&#xff1a;函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长…

大模型训练——pycharm连接实验室服务器

一、引言 我们在运行或者复现大佬论文代码的时候&#xff0c;笔记本的算力不够&#xff0c;需要使用实验室的服务器进行运行。可以直接在服务器的终端上执行&#xff0c;但是这样的话代码调试就不方便。而我们可以使用 pycharm 连接到服务器&#xff0c;既方便了代码调试&…

STM32的C语言软件延时函数

STM32的延时方法很多&#xff0c;其中采用定时器延时&#xff0c;可以得到较为精确的延时&#xff0c;但是有时对延时精度要求不高的场合&#xff0c;采用软件延时&#xff0c;也是必须的。特别是在RTOS系统中&#xff0c;使用SysTick的普通计数模式对延迟进行管理&#xff0c;…

前端网页或者pwa如何实现只横屏显示,设备竖着的时候依然保持横屏

开发的时候&#xff0c;就是以横屏的样式开发的&#xff0c;所以横屏的展示效果就是&#xff1a; 当设备竖着的时候&#xff0c;会进行缩放&#xff0c;展示效果不友好&#xff0c;所以需要设备竖着的时候&#xff0c;也横屏显示&#xff1a; 实现原理就是&#xff1a;使用css监…

计算机毕业设计SpringBoot+Vue.js电影评论网站系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Locale+Jackson导致Controller接口StackOverflowError异常解决

问题 由于参与的项目有出海需求&#xff0c;即需要给外国人使用&#xff0c;即&#xff1a;需要支持i18n&#xff08;Internationalization的缩写&#xff0c;共20个字母&#xff0c;除去首尾两个字母&#xff0c;中间有18个&#xff0c;故简称i18n&#xff09;。 本来是好的…

Graph and GNN——图的表示与图神经网络的介绍与应用

Hi&#xff0c;大家好&#xff0c;我是半亩花海。细数日子已然有很长一段时间没有更新博客了&#xff0c;不是在忙东忙西&#xff0c;就是在玩这玩那&#xff0c;在家摆&#xff0c;在学校gap&#xff0c;无敌了。言归正传&#xff0c;今天暂且先进一步探索并整理一部分图神经网…

京准电钟:NTP精密时钟服务器在自动化系统中的作用

京准电钟&#xff1a;NTP精密时钟服务器在自动化系统中的作用 京准电钟&#xff1a;NTP精密时钟服务器在自动化系统中的作用 NTP精密时钟服务器在自动化系统中的作用非常重要&#xff0c;特别是在需要高精度时间同步的场景中。NTP能够提供毫秒级的时间同步精度&#xff0c;这…

Https解决了Http的哪些问题

部分内容来源&#xff1a;小林coding 详细解析 Http的风险 HTTP 由于是明文传输&#xff0c;所以安全上存在以下三个风险&#xff1a; 1.窃听风险 比如通信链路上可以获取通信内容&#xff0c;用户号容易没。 2.篡改风险 比如强制植入垃圾广告&#xff0c;视觉污染&#…

GO 进行编译时插桩,实现零码注入

Go 编译时插桩 Go 语言的编译时插桩是一种在编译阶段自动注入监控代码的技术&#xff0c;目的是在不修改业务代码的情况下&#xff0c;实现对应用程序的监控和追踪。 基本原理 Go 编译时插桩的核心思想是通过在编译过程中对源代码进行分析和修改&#xff0c;将监控代码注入到…