从零开始构建简单分类器
在机器学习领域,分类器是一个非常重要的工具。它可以将输入的数据进行分类,从而帮助我们更好地理解和处理数据。接下来,我们将详细探讨如何从零开始构建一个简单的分类器。
1. 构建还是购买分类器
在开始构建分类器之前,我们需要考虑是自己构建还是使用现有的分类器。以下是一些决策因素:
| 情况 | 建议选择 |
| — | — |
| 构建对话式AI | 现有分类器 |
| 构建分类和路由助手 | 构建分类器 |
| 不擅长数据科学 | 现有分类器 |
| 擅长数据科学 | 构建分类器 |
| 需要控制所有组件的源代码 | 构建分类器 |
| 空闲时间少 | 现有分类器 |
| 为了学习而学习 | 构建分类器 |
2. 从零开始构建简单分类器
假设我们要为一个零售对话式助手构建一个新的分类器。该助手需要处理超过十几个意图,因此分类器必须能够将话语分类到十几个以上的类别中。我们将从学习如何将话语分为两个类别开始:
#reset_password
和 “not #reset_password”,然后扩展到三个类别:
#reset_password
、
#store_hours
和
#store_location
,最后讨论如何扩展到任意数量的类别。
2.1 最简单的文本分类器
将文本转换为数字的最简单方法是使用词袋(Bag of Words)技术。词袋分类器将输入的文本字符串视为单词的集合,不考虑单词的顺序和含义,只对单词进行计数。
以下是一个使用两个文本语句训练词袋分类器的示例:“Reset my password” 和 “When does the store open”。
| 文本语句 | 词袋 | 类别标签 |
| — | — | — |
| Reset my password | my:1, password:1, reset:1 | 正例 |
| When does the store open | does:1, open:1, store:1, when:1 | 负例 |
词袋算法将单词按字母顺序索引,如下表所示:
| 单词 | 索引 |
| — | — |
| does | 0 |
| my | 1 |
| open | 2 |
| password | 3 |
| reset | 4 |
| store | 5 |
| when | 6 |
通过这种方式,我们可以将文本语句转换为数值数组。例如,“Reset my password” 可以表示为
[0, 1, 0, 1, 1, 0, 0]
。
以下是几个示例话语的数值表示和分类输出:
| 文本输入 | 词袋的数值数组 | 分类输出 |
| — | — | — |
| Reset my password | [0, 1, 0, 1, 1, 0, 0] | 正例 |
| Password reset | [0, 0, 0, 1, 1, 0, 0] | 正例 |
| When does the store open | [1, 0, 1, 0, 0, 1, 1] | 负例 |
| When does my password reset | [1, 1, 0, 1, 1, 0, 1] | 负例 |
2.2 简单分类器背后的数学原理
在前面的部分,我们已经看到了如何将输入的文本短语转换为数值表达式。接下来,我们需要找到一个函数
f
,使得
f(input) = prediction
。
我们可以使用逻辑回归算法来找到这个函数。逻辑回归是一种类似于线性回归的技术,不同之处在于目标是离散的分类。在我们的例子中,分类是二进制的(0 或 1)。
逻辑回归的中心方程是一个线性函数,每个参数都乘以一个权重,然后求和,再加上一个常数(偏置)。对于具有两个参数的逻辑回归,函数如下:
[f = weight_0 + weight_1 \times parameter_1 + weight_2 \times parameter_2]
机器学习的神奇之处在于,给定足够的示例,它可以推断(学习)参数的权重。
我们的训练数据有两个输出值:1 和 0,分别表示正例和负例。0 到 1 之间的值表示输入属于正类的概率。因此,机器学习算法应该被限制在返回 [0,1] 范围内的值。逻辑函数如下:
[Probability\ of\ positive\ example = \frac{e^f}{1 + e^f}]
我们通过训练两个示例语句(“reset my password” 和 “when does the store open”)来找到回归函数的具体参数值。以下是训练代码:
training_data = read_data_from_csv_file("training_2class_small.csv")
vec, clf, pipe = train_binary_classifier_pipeline("reset_password", training_data)
display(eli5.show_weights(clf, vec=vec, top=20, target_names=pipe.classes_))
训练后,我们可以使用逻辑方程对任何示例进行分类。例如,对于 “reset my password”:
[f = 0.189 + 0.378\times1 + 0.378\times1 + 0.378\times1 = 1.323]
[e^f = e^{1.323} = 3.755]
[probability = \frac{e^f}{1 + e^f} = \frac{3.755}{4.755} = 0.790]
系统有 79% 的置信度将该话语分类为
#reset_password
。
对于 “when does the store open”:
[f = 0.189 +0 - 0.378\times1 - 0.378\times1 - 0.378\times1- 0.378\times1 = -1.323]
[e^f = e^{-1.323} = 0.266]
[probability = \frac{e^f}{1 + e^f} = \frac{0.266}{1.266} = 0.210]
系统有 21% 的置信度将该话语分类为
#reset_password
。
对于 “where are you located”,由于该短语中的单词都不在训练集中,因此方程只包含偏置参数:
[f = 0.189]
[e^f = e^{0.189} = 1.201]
[probability = \frac{e^f}{1 + e^f} = \frac{1.201}{2.201} = 0.547]
系统有 54.7% 的置信度将该话语分类为
#reset_password
。这表明该分类器训练不足,需要更多的训练数据才能做出更好的预测。
我们可以通过以下 mermaid 流程图来展示分类过程:
graph LR
A[文本输入] --> B[词袋转换]
B --> C[数值数组]
C --> D[逻辑回归方程]
D --> E[预测概率]
E --> F[分类输出]
3. 扩展简单分类器
在前面的部分,我们的分类器只能预测一个类(一个意图)。现在,我们将扩展分类器以预测多个类。
3.1 预测多个类
我们可以通过使用多个分类器来扩展简单分类器。每个分类器专注于检测一个单一的类,然后我们可以使用聚合结果来确定最可能的类。
以下是一个包含三个意图的最小训练集:
| 输入(话语) | 输出(意图) |
| — | — |
| Reset my password | #reset_password |
| When does the store open | #store_hours |
| Where is my nearest store | #store_location |
每个分类器对训练数据有二进制的视图,如下表所示:
| 输入(话语) | 分类器 1 | 分类器 2 | 分类器 3 |
| — | — | — | — |
| Reset my password | #reset_password | #not_store_hours | #not_store_location |
| When does the store open | #not_reset_password | #store_hours | #not_store_location |
| Where is my nearest store | #not_reset_password | #not_store_hours | #store_location |
以下是训练三个分类器的代码:
training_data = read_data_from_csv_file("training_3class_small.csv")
# 训练三个分类器
reset_password_vec, reset_password_clf, reset_password_pipe = train_binary_classifier_pipeline("reset_password", training_data)
store_hours_vec, store_hours_clf, store_hours_pipe = train_binary_classifier_pipeline("store_hours", training_data)
store_location_vec, store_location_clf, store_location_pipe = train_binary_classifier_pipeline("store_location", training_data)
# 检查每个分类器的权重
display(eli5.show_weights(reset_password_clf, vec=reset_password_vec, top=20, target_names=reset_password_pipe.classes_))
display(eli5.show_weights(store_hours_clf, vec=store_hours_vec, top=20, target_names=store_hours_pipe.classes_))
display(eli5.show_weights(store_location_clf, vec=store_location_vec, top=20, target_names=store_location_pipe.classes_))
训练后,我们可以对单个话语进行测试。例如,对于 “reset my password”:
[f_{reset_password} = -0.430 + 0.531 + 0.234 + 0.531 = 0.866]
[e^{f_{reset_password}} = e^{0.866} = 2.377]
[probability = \frac{e^{f_{reset_password}}}{1 + e^{f_{reset_password}}} = \frac{2.377}{3.377} = 0.704]
[f_{store_hours} = -1 – 0.230 – 0.460 – 0.230 = -1.920]
[e^{f_{store_hours}} = e^{-1.920} = 0.147]
[probability = \frac{e^{f_{store_hours}}}{1 + e^{f_{store_hours}}} = \frac{0.147}{1.147} = 0.128]
[f_{store_location} = -1.258 – 0.297 + 0.234 - 0.297 = -1.618]
[e^{f_{store_location}} = e^{-1.618} = 0.198]
[probability = \frac{e^{f_{store_location}}}{1 + e^{f_{store_location}}} = \frac{0.198}{1.198} = 0.165]
预测结果可以总结在以下概率表中:
| 分类器 | 正预测概率 | 负预测概率 |
| — | — | — |
| #reset_password | 0.704 | 0.296 |
| #store_hours | 0.128 | 0.872 |
| #store_location | 0.165 | 0.834 |
由于
#reset_password
的正预测置信度最高,因此该话语被分类为
#reset_password
。
对于 “tell me a joke”,由于该短语中的单词都不在训练集中,因此每个分类器的预测概率都较低,表明该话语不属于任何一个意图。
我们可以通过以下 mermaid 流程图来展示多分类过程:
graph LR
A[输入话语] --> B[分类器 1]
A --> C[分类器 2]
A --> D[分类器 3]
B --> E[预测概率 1]
C --> F[预测概率 2]
D --> G[预测概率 3]
E --> H[聚合结果]
F --> H
G --> H
H --> I[最终分类输出]
通过以上步骤,我们可以从零开始构建一个简单的分类器,并将其扩展到预测多个类。在实际应用中,我们需要使用更多的训练数据来提高分类器的准确性。
从零开始构建简单分类器
4. 多分类器的深入分析
在前面我们已经成功扩展分类器以预测多个类,接下来深入分析多分类器的一些特性和需要注意的地方。
4.1 权重分析
从训练好的三个分类器的权重中,我们可以得到一些有价值的信息:
-
词的关联
:对于
#reset_password
分类器,“my” 的权重低于 “reset” 和 “password”,因为 “my” 也出现在
#store_location
的示例中,这表明分类器会根据词与不同意图的关联程度来分配权重。同理,“store” 在
#store_hours
分类器中的权重也有所降低。
-
负权重信号
:
#reset_password
分类器对 “store” 有很强的负权重,因为 “store” 出现在所有非
#reset_password
的话语中,这是分类器识别不同意图的一种方式。
-
负偏置情况
:每个分类器都有负偏置,这是因为每个分类器看到的负例比正例多,暗示每个类相对来说是比较罕见的。
-
权重变化趋势
:与之前只有两个训练示例的情况相比,现在每个分类器有三个示例,权重的绝对值更大,这意味着更多的示例允许分类器做出更强的推断。
4.2 概率分析
在多分类的情况下,我们需要明确概率的含义和计算方式。
-
单个分类器内概率和为 1
:在每个分类器中,正预测概率和负预测概率之和为 1,即每个输入要么是该类的正例,要么是负例。
-
分类器间概率独立性
:三个分类器是完全独立的,它们的正预测概率之间没有必然的联系。如果 AI 提供商返回的概率之和为 1,可能有两种情况:
- 他们对概率进行了缩放,使得它们的和为 1。
- 他们使用了不同的算法,如一体化分类器。
5. 分类器的实际应用与优化
在实际应用中,我们需要考虑如何使用和优化分类器,以提高其性能和实用性。
5.1 应用场景
分类器可以应用于各种自然语言处理任务,如对话式 AI、分类和路由助手等。在对话式 AI 中,分类器可以帮助识别用户的意图,从而提供相应的回复或操作。
5.2 优化建议
- 增加训练数据 :从前面的分析可以看出,训练数据的数量和多样性对分类器的性能有很大影响。更多的训练数据可以让分类器学习到更丰富的模式,从而做出更准确的预测。
- 调整阈值 :在实际应用中,我们可以设置一个置信度阈值,当分类器的预测置信度低于该阈值时,不选择该意图,避免低置信度的预测影响系统的准确性。
- 特征工程 :除了词袋模型,我们还可以考虑使用其他特征工程方法,如词嵌入、TF - IDF 等,以提高文本表示的质量。
6. 总结与展望
通过本文,我们详细介绍了如何从零开始构建一个简单的分类器,并将其扩展到预测多个类。主要步骤如下:
1. 选择构建或使用现有的分类器,根据自身情况综合考虑技能、时间、需求等因素。
2. 使用词袋模型将文本转换为数值数组,为后续的数学处理做准备。
3. 运用逻辑回归算法找到合适的函数,实现从输入到预测的转换。
4. 通过多个分类器的组合,实现多分类的预测。
然而,我们构建的分类器还存在一些局限性,如训练数据不足导致的预测不准确等问题。在未来的研究和应用中,我们可以进一步探索以下方向:
-
更复杂的算法
:尝试使用深度学习算法,如神经网络、循环神经网络等,以提高分类器的性能。
-
多模态数据融合
:结合文本、图像、语音等多模态数据,使分类器能够处理更复杂的场景。
-
自适应学习
:让分类器能够根据新的数据自动调整和优化,提高其适应性和泛化能力。
总之,构建一个高效准确的分类器是一个不断探索和优化的过程,需要我们结合实际需求和技术发展,不断改进和创新。
以下是一个总结多分类器构建流程的 mermaid 流程图:
graph LR
A[确定构建或购买决策] --> B[准备训练数据]
B --> C[使用词袋模型转换文本]
C --> D[训练单分类器(逻辑回归)]
D --> E[扩展到多分类器]
E --> F[测试和优化分类器]
F --> G[应用到实际场景]
通过以上的分析和总结,希望能帮助大家更好地理解和应用分类器,为自然语言处理任务提供有力的支持。
超级会员免费看
1720

被折叠的 条评论
为什么被折叠?



