【机器学习 | 朴素贝叶斯】朴素贝叶斯算法:概率统计方法之王,简单有效的数据分类利器

🤵‍♂️ 个人主页: @AI_magician

📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。

👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!🐱‍🏍

🙋‍♂️声明:本人目前大学就读于大二,研究兴趣方向人工智能&硬件(虽然硬件还没开始玩,但一直很感兴趣!希望大佬带带)

该文章收录专栏

[✨--- 《深入解析机器学习:从原理到应用的全面指南》 ---✨]

朴素贝叶斯

贝叶斯算法是一种常用的概率统计方法,它利用贝叶斯定理来进行分类和预测。其在计算机还没有出现前几十年就存在了,那个时候科学家们都是用手算的,是最早的机器学习形式之一,该算法基于统计学原理,通过已知的先验概率和观测到的数据,更新对事件发生概率的估计。因为有着一个很强的假设,每个数据特征都是独立的,这也是条件独立的前提条件,也叫"朴素的"的假设,故叫朴素贝叶斯算法。

具体公式推导如下:

  1. 贝叶斯定理表达式:
    根据贝叶斯定理,我们可以得到以下表达式:
    P(A|B) = (P(B|A) * P(A)) / P(B) (注意的是 P(B|A) 的分母范围不是整体样本,而是P(A),所以乘上P(A) 就相当于是基于全局的 P(B|A)

其中,

  • P(A|B) 是在给定观测数据 B 的条件下事件 A 发生的概率(后验概率)。
  • P(B|A) 是在事件 A 发生的条件下观测到数据 B 的概率(似然)。
  • P(A) 是事件 A 发生的先验概率。
  • P(B) 是观测到的数据 B 的概率。

贝叶斯定理的核心思想是通过已知的条件概率和边际概率,计算出后验概率。先验概率是在考虑任何观测数据之前,基于先前的知识或经验得出的概率。后验概率是在考虑观测数据之后,根据先验概率和条件概率计算得出的概率。

  1. 朴素贝叶斯分类器:
    在朴素贝叶斯分类器中,我们假设特征之间相互独立,即给定类别的情况下,特征之间是条件独立的 。基于这个假设,我们可以将贝叶斯定理改写为:
    P(C|X) = (P(X|C) * P©) / P(X)

其中,

  • P(C|X) 是在给定观测数据 X 的条件下类别 C 发生的概率(后验概率)。
  • P(X|C) 是在类别 C 发生的条件下观测到数据 X 的概率(似然)。
  • P© 是类别 C 的先验概率。
  • P(X) 是观测到的数据 X 的概率。
  1. 具体公式推导:
    假设观测数据有 n 个特征,我们可以将数据表示为 X = (x₁, x₂, ..., xₙ),其中 xᵢ 表示第 i 个特征的取值。根据朴素贝叶斯分类器的条件独立性假设 ,上述表达式可以进一步简化为:
    P(C|X) = (P(x₁|C) * P(x₂|C) * ... * P(xₙ|C) * P©) / P(X)

为了进行分类,我们需要计算每个类别的后验概率P(C|X) ,并选择具有最高后验概率的类别作为预测结果。具体大白话来说就是,更具已知数据中这个类别的概率是多少再乘上数据中特征属于这个类别的概率的结果就是其后验概率了。而其中的这个 P(X|C) 似然概率就需要进行参数估计,见下一部分。

  1. 参数估计:
    在实际应用中,我们需要利用训练数据来计算各个概率的估计值。常见的参数估计方法有极大似然估计和贝叶斯估计。 (极大似然估计 vs 贝叶斯估计:谁才是朴素贝叶斯的最佳伴侣?)
  • 极大似然估计:假设训练集中包含 m 个样本,属于类别 C 的样本个数为 mᵢ(i ∈ {1, 2, ..., k},k 是类别的个数)。则根据极大似然估计,我们可以得到:
    P© = mᵢ / m
    P(x|C) = m(x, C) / mᵢ

其中,

  • P© 是类别 C 的先验概率。
  • P(x|C) 是在类别 C 发生的条件下特征 x 出现的概率(似然)
  • m(x, C) 是在训练集中属于类别 C 且特征为 x 的样本个数
  1. 假设样本数据是从某个概率分布生成的,该分布属于一个参数化家族。

  2. 在这个参数化家族中,找到一组参数,使得样本数据Based on这组参数生成的概率(即似然函数)最大。

  3. 这组参数就是对总体参数的极大似然估计。

假设有样本数据 X 1 , X 2 , . . . , X n X_1, X_2, ..., X_n X1,X2,...,Xn,它们独立同分布,概率密度函数或概率质量函数为 f ( x ∣ θ ) f(x|\theta) f(x∣θ) ,其中 θ \theta θ 是未知参数。则似然函数为:

L ( θ ∣ X 1 , X 2 , . . . , X n ) = f ( X 1 ∣ θ ) f ( X 2 ∣ θ ) . . . f ( X n ∣ θ ) L(\theta|X_1,X_2,...,X_n) = f(X_1|\theta)f(X_2|\theta)...f(X_n|\theta) L(θ∣X1,X2,...,Xn)=f(X1∣θ)f(X2∣θ)...f(Xn∣θ)

极大似然估计的目标是找到一组 θ \theta θ 的值,使得这个似然函数最大(即概率最大):

θ MLE = arg ⁡ max ⁡ θ L ( θ ∣ X 1 , X 2 , . . . , X n ) \theta_{\text{MLE}} = \arg\max_\theta L(\theta|X_1,X_2,...,X_n) θMLE=argmaxθL(θ∣X1,X2,...,Xn)

即满足:

d L d θ = 0 \frac{dL}{d\theta} = 0 dθdL=0

解这个方程组就可以得到 θ \theta θ 的极大似然估计。

极大似然估计有以下几个主要性质:

  1. 当样本量趋于无穷大时,MLE是渐进最优的,即收敛于真实参数值。

  2. MLE不需要事先指定先验分布

  3. 对给定的数据集,MLE总是存在的。

  4. MLE是充分利用数据信息的。

  5. MLE比较容易计算。

综上,极大似然估计通过最大化似然函数,找到最有可能产生观测数据的模型参数,是一种常用而有效的参数估计方法。它具有渐进最优、无需先验等优点,理论性质良好。

  • 贝叶斯估计:贝叶斯估计是对极大似然估计进行修正,以解决可能出现的概率为零的情况 。常见的贝叶斯估计方法有拉普拉斯平滑Lidstone平滑。
  1. 贝叶斯估计(Bayesian Estimation):
    • 先验概率的估计:贝叶斯估计引入了一个先验分布用于对先验概率进行平滑。常见的先验分布包括拉普拉斯平滑和贝叶斯平滑 。拉普拉斯平滑将每个类别的出现次数加上一个常数 α \alpha α,然后再进行归一化,以平滑先验概率的估计。贝叶斯平滑则使用一个更一般的先验分布,例如狄利克雷分布,通过调整参数来控制平滑的程度。
    • 条件概率的估计:对于条件概率的估计,我们可以使用与先验概率相似的方法进行平滑。例如,对于每个特征 X j X_j Xj,我们可以将每个取值的出现次数加上一个常数 α \alpha α,然后再进行归一化,以平滑条件概率的估计。

贝叶斯估计相对于极大似然估计的优势在于它可以通过引入先验分布来减小估计的偏差,**并在数据较少时提供更稳定的估计结果。**然而,贝叶斯估计也会引入一定的偏差,因为它基于先验分布的假设。

在实际应用中,我们可以根据数据集的大小和特征的分布情况选择适当的参数估计方法。对于较大的数据集,极大似然估计通常可以提供较好的结果。而对于较小的数据集或特征分布较稀疏的情况,贝叶斯估计可以提供更稳定的估计结果。

这些公式和推导提供了贝叶斯算法的基本原理,但具体应用时需要根据实际情况进行相应的调整和优化。

基于朴素贝叶斯算法的生活案例可以是垃圾邮件分类。我们可以使用朴素贝叶斯算法来训练一个模型,该模型可以根据邮件的内容将其分类为垃圾邮件或非垃圾邮件。

具体的推导建模步骤如下:

  1. 数据准备:收集一批已经标记好的垃圾邮件和非垃圾邮件样本数据。每个样本数据包含邮件的内容和标签(垃圾或非垃圾)。

  2. 数据预处理:对邮件内容进行预处理,包括去除停用词、标点符号和数字,将文本转换为小写,并进行词干提取或词形还原等操作。

  3. 特征提取:将每个邮件转换为特征向量表示。常用的方法是使用词袋模型(Bag of Words),将每个单词作为一个特征,统计每个单词在邮件中出现的频率。

    词袋模型是一种常用的文本特征提取方法,它将文本转换为固定长度的向量表示。在词袋模型中,文本被看作是一个袋子,其中包含了所有单词,而忽略了它们的顺序和语法结构。每个词都独立地出现

    以下是词袋模型的基本步骤:

    1. 构建词汇表 :首先,需要构建一个词汇表,其中包含了所有在训练数据中出现的单词。这个词汇表可以根据整个语料库或者特定的文档集合来构建。
    2. 向量化 :对于每个文本样本,将其转换为一个特征向量。特征向量的长度等于词汇表中单词的数量。通常,可以使用稀疏向量表示来表示特征向量,其中大部分元素为零。
    3. 计算词频:对于每个文本样本,计算每个单词在文本中出现的频率。将这些频率作为特征向量的元素值。

    例如,假设我们有两个文档:

    文档1: "我喜欢看电影"

    文档2: "我不喜欢看电影"

    在这个例子中,我们的词汇表是 {我,喜欢,看,电影,不}。那么,文档1和文档2的词袋表示分别是:

    文档1: [1, 1, 1, 1, 0]

    文档2: [1, 1, 1, 1, 1]

    词袋模型的主要优点是简单和高效。然而,它也有一些缺点。首先,它忽略了词的顺序,这在许多情况下是非常重要的 。其次,它假设所有的词都是独立的,不考虑词与词之间的关系 。最后,它只考虑了词频,没有考虑词的重要性,这在信息检索中是非常重要的。(在一些应用中只需要词频很有效)

    为了解决这些问题,有一些改进的词袋模型,如TF-IDF模型,它考虑了词的重要性。还有词嵌入模型,如Word2Vec和GloVe,它们考虑了词与词之间的关系。

  4. 计算概率:根据训练数据计算每个特征在垃圾邮件和非垃圾邮件中出现的概率。具体来说,这些单词对应的特征控制了属于垃圾邮箱还是非垃圾邮箱的概率。

  5. 训练模型:根据计算得到的概率,训练一个朴素贝叶斯分类器模型。

  6. 预测分类:对于一个新的邮件,将其转换为特征向量表示,并使用训练好的模型预测其分类。

下面是一个不使用封装库的Python代码示例:

python 复制代码
import re
import math

# 数据准备
spam_emails = [
    "Get a free laptop now!",
    "Earn money fast with no effort!",
    "Enlarge your assets with our product!",
    "Meet singles in your area tonight!"
]

ham_emails = [
    "Hi, how are you?",
    "Can we meet tomorrow?",
    "Remember to buy groceries on your way home.",
    "I'll be there in 5 minutes."
]

# 数据预处理
def preprocess_email(email):
    email = email.lower() # 全部小写
    email = re.sub(r'\W', ' ', email)  # 去除非字母数字字符
    email = re.sub(r'\s+', ' ', email)  # 合并多个空格为一个空格
    return email.strip() # 去除空格

spam_emails = [preprocess_email(email) for email in spam_emails]
ham_emails = [preprocess_email(email) for email in ham_emails]

# 特征提取(每一封邮件)
def extract_features(email):
    features = {}
    words = email.split()
    for word in words:
        features[word] = features.get(word, 0) + 1  # 字典查询不存在值返回默认值0实现自动添加。
    return features

spam_features = [extract_features(email) for email in spam_emails]
ham_features = [extract_features(email) for email in ham_emails]
print(spam_emails)
print(spam_features)
# 计算概率 (建立词汇表及其对应单词的概率)
spam_word_count = {}
ham_word_count = {}
spam_total_words = 0
ham_total_words = 0

for email in spam_features:
    for word, count in email.items():
        spam_word_count[word] = spam_word_count.get(word, 0) + count
        spam_total_words += count

for email in ham_features:
    for word, count in email.items():
        ham_word_count[word] = ham_word_count.get(word, 0) + count
        ham_total_words += count

print(spam_word_count,spam_total_words)
spam_word_prob = {}
ham_word_prob = {}

for word, count in spam_word_count.items():
    spam_word_prob[word] = count / spam_total_words  # 极大似然估计求概率 ( p(x|c(spam))/m^i )

for word, count in ham_word_count.items():
    ham_word_prob[word] = count / ham_total_words

print("spam_word_prob:\n",spam_word_prob)
# 训练模型
spam_prior = len(spam_emails) / (len(spam_emails) + len(ham_emails)) # 先验概率 P(C(spam)|X)
ham_prior = len(ham_emails) / (len(spam_emails) + len(ham_emails)) # 先验概率  P(C(ham)|X)

# 预测分类
def predict(email):
    email = preprocess_email(email)
    features = extract_features(email)
    
    # 加法求分数 (避免概率相乘时出现下溢问题)
    spam_score = math.log(spam_prior)
    ham_score = math.log(ham_prior)
    print(spam_score,ham_score)
    for word, count in features.items():
#         print(word,spam_word_prob[word])
        if word in spam_word_prob:
            spam_score -= math.log(spam_word_prob[word]) * count # 因为词频一定是在0~1之间的,要递增需要相减 
        if word in ham_word_prob:
            ham_score -= math.log(ham_word_prob[word]) * count
        print(spam_score,ham_score)
    spam_score = math.exp(spam_score)
    ham_score = math.exp(ham_score)
    # 乘法分数  (概率相乘时出现下溢问题)
#     spam_score = (spam_prior)
#     ham_score = (ham_prior)

#     for word, count in features.items():
#         if word in spam_word_prob:
#             spam_score *= spam_word_prob[word] ** count
#         if word in ham_word_prob:
#             ham_score *= ham_word_prob[word] ** count
    print(spam_score,ham_score)
    if spam_score >= ham_score:
        return "spam"
    else:
        return "ham"

# 测试
test_email = "Get a free laptop now!"
prediction = predict(test_email)
print(f"\nPrediction for email '{test_email}': {prediction}")

输出:

['get a free laptop now', 'earn money fast with no effort', 'enlarge your assets with our product', 'meet singles in your area tonight']
[{'get': 1, 'a': 1, 'free': 1, 'laptop': 1, 'now': 1}, {'earn': 1, 'money': 1, 'fast': 1, 'with': 1, 'no': 1, 'effort': 1}, {'enlarge': 1, 'your': 1, 'assets': 1, 'with': 1, 'our': 1, 'product': 1}, {'meet': 1, 'singles': 1, 'in': 1, 'your': 1, 'area': 1, 'tonight': 1}]
{'get': 1, 'a': 1, 'free': 1, 'laptop': 1, 'now': 1, 'earn': 1, 'money': 1, 'fast': 1, 'with': 2, 'no': 1, 'effort': 1, 'enlarge': 1, 'your': 2, 'assets': 1, 'our': 1, 'product': 1, 'meet': 1, 'singles': 1, 'in': 1, 'area': 1, 'tonight': 1} 23
spam_word_prob:
 {'get': 0.043478260869565216, 'a': 0.043478260869565216, 'free': 0.043478260869565216, 'laptop': 0.043478260869565216, 'now': 0.043478260869565216, 'earn': 0.043478260869565216, 'money': 0.043478260869565216, 'fast': 0.043478260869565216, 'with': 0.08695652173913043, 'no': 0.043478260869565216, 'effort': 0.043478260869565216, 'enlarge': 0.043478260869565216, 'your': 0.08695652173913043, 'assets': 0.043478260869565216, 'our': 0.043478260869565216, 'product': 0.043478260869565216, 'meet': 0.043478260869565216, 'singles': 0.043478260869565216, 'in': 0.043478260869565216, 'area': 0.043478260869565216, 'tonight': 0.043478260869565216}
-0.6931471805599453 -0.6931471805599453
2.4423470353692043 -0.6931471805599453
5.577841251298354 -0.6931471805599453
8.713335467227504 -0.6931471805599453
11.848829683156653 -0.6931471805599453
14.984323899085803 -0.6931471805599453
3218171.4999999995 0.5

Prediction for email 'Get a free laptop now!': spam

实践大于理论 ------ 伽利略

对数函数具有一些特殊的性质,使得它在概率计算中非常有用。

在概率计算中,我们通常需要计算多个概率的乘积。当这些概率非常小的时候,连续相乘可能会导致结果变为零或非常接近零。这是由于计算机浮点数的精度限制所导致的。

为了解决这个问题,我们可以使用对数概率进行计算。对数函数具有以下性质:

  1. 对数函数是单调递增的。这意味着概率的对数值的大小顺序与概率本身的大小顺序(都会变小)相同。因此,对数概率的加法可以代替概率的乘法。
  2. 对数函数将乘法转换为加法。对数函数的一个重要性质是,它将乘法操作转换为加法操作。具体来说,对数函数满足以下等式:log(ab) = log(a) + log(b)。这意味着将两个概率的对数相加,等于将这两个概率相乘。

通过将概率转换为对数概率,我们可以将概率的乘法转换为对数概率的加法,从而避免了下溢问题 。这样做的好处是,我们可以在对数空间中进行计算,而不会丢失精度(其实相当于是转换到对数空间了)。

在代码中,使用math.log函数对概率进行取对数操作,将概率的乘法转换为对数概率的加法。然后,在最后比较概率大小时,使用math.exp函数将对数概率转换回原始概率进行比较。

总结起来,使用对数概率进行计算是为了避免概率相乘时出现下溢问题,并且利用对数函数的性质将乘法转换为加法,从而提高计算的准确性和效率。

这段代码用了简单的词频特征提取方法,将每个单词的计数作为特征(词频) ,且在计算概率时没有进行平滑处理。平滑处理是为了避免在训练数据中出现未见过的单词时,概率为零的情况。sklearn中的MultinomialNB分类器**默认使用了拉普拉斯平滑(Laplace smoothing)**来处理这种情况。并默认使用了更复杂的特征提取方法,称为词袋模型(Bag of Words),它将每个单词的出现与否作为特征

下面是一个使用封装库scikit-learn的Python代码示例:

python 复制代码
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB

# 数据准备
spam_emails = [
    "Get a free laptop now!",
    "Earn money fast with no effort!",
    "Enlarge your assets with our product!",
    "Meet singles in your area tonight!"
]

ham_emails = [
    "Hi, how are you?",
    "The cat sat on the mat",
    "Can we meet tomorrow?",
    "Remember to buy groceries on your way home.",
    "I'll be there in 5 minutes."
]

labels = ["spam", "spam", "spam", "spam", "ham", "ham", "ham", "ham", "ham"]

# 特征提取
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(spam_emails + ham_emails)
print(type(X))
print(X)
print(vectorizer.get_feature_names_out())
print(X.toarray())
# 训练模型
model = MultinomialNB() # 多项式朴素贝叶斯
model.fit(X, labels) # 接受数组和稀疏矩阵

# 预测分类
test_email = ["Get a free laptop now!", "how are you?"]
test_email_vector = vectorizer.transform(test_email)
print(test_email_vector)
prediction = model.predict(test_email_vector)[0]
print(f"Prediction for email '{test_email}': {prediction}")

输出:

<class 'scipy.sparse._csr.csr_matrix'>
  (0, 12)	1
  (0, 11)	1
  (0, 18)	1
  (0, 25)	1
  (1, 7)	1
  (1, 23)	1
  (1, 10)	1
  (1, 39)	1
  (1, 24)	1
  (1, 8)	1
  (2, 39)	1
  (2, 9)	1
  (2, 41)	1
  (2, 2)	1
  (2, 27)	1
  (2, 28)	1
  (3, 41)	1
  (3, 21)	1
  (3, 31)	1
  (3, 17)	1
  (3, 1)	1
  (3, 36)	1
  (4, 14)	1
  (4, 16)	1
  (4, 0)	1
  (4, 40)	1
  (5, 32)	2
  (5, 6)	1
  (5, 30)	1
  (5, 26)	1
  (5, 20)	1
  (6, 21)	1
  (6, 5)	1
  (6, 38)	1
  (6, 35)	1
  (7, 41)	1
  (7, 26)	1
  (7, 29)	1
  (7, 34)	1
  (7, 4)	1
  (7, 13)	1
  (7, 37)	1
  (7, 15)	1
  (8, 17)	1
  (8, 19)	1
  (8, 3)	1
  (8, 33)	1
  (8, 22)	1
['are' 'area' 'assets' 'be' 'buy' 'can' 'cat' 'earn' 'effort' 'enlarge'
 'fast' 'free' 'get' 'groceries' 'hi' 'home' 'how' 'in' 'laptop' 'll'
 'mat' 'meet' 'minutes' 'money' 'no' 'now' 'on' 'our' 'product' 'remember'
 'sat' 'singles' 'the' 'there' 'to' 'tomorrow' 'tonight' 'way' 'we' 'with'
 'you' 'your']
[[0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0]
 [0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
  0 0 0 1 0 0]
 [0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
  0 0 0 1 0 1]
 [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
  1 0 0 0 0 1]
 [1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 1 0]
 [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 2 0 0 0
  0 0 0 0 0 0]
 [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
  0 0 1 0 0 0]
 [0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0
  0 1 0 0 0 1]
 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0
  0 0 0 0 0 0]]
  (0, 11)	1
  (0, 12)	1
  (0, 18)	1
  (0, 25)	1
  (1, 0)	1
  (1, 16)	1
  (1, 40)	1
Prediction for email '['Get a free laptop now!', 'how are you?']': spam

CountVectorizersklearn.feature_extraction.text模块中的一个类,它用于将文本数据转换为向量形式,这种形式对于机器学习算法的输入非常有用。下面是CountVectorizer的基本原理:

  1. Tokenization(分词)CountVectorizer首先将文本分解为单独的单词(在英文中通常是通过空格来分隔),这个过程被称为分词。例如,句子 "The cat sat on the mat" 可能会被分解为 "The", "cat", "sat", "on", "the", "mat"。

  2. Vocabulary Building(构建词汇表) :然后,CountVectorizer会创建一个词汇表,其中包含所有出现在所有文档中的唯一单词。例如,如果我们有两个文档,一个是 "The cat sat on the mat",另一个是 "The dog sat on the log",那么词汇表就会是 "The", "cat", "sat", "on", "the", "mat", "dog", "log"。

  3. Encoding(编码) :最后,CountVectorizer会将每个文档转换为一个向量。向量的长度等于词汇表中的单词数量,每个元素代表词汇表中对应单词在文档中出现的次数。例如,对于文档 "The cat sat on the mat" 和词汇表 "The", "cat", "sat", "on", "the", "mat", "dog", "log",其对应的向量可能是 [2, 1, 1, 1, 1, 1, 0, 0](这里假设我们不区分大小写,"The" 和 "the" 被视为同一个单词,则表示出现了两次)。

这就是CountVectorizer的基本原理。需要注意的是,CountVectorizer还有许多参数可以调整,例如你可以选择是否将所有单词转换为小写,是否删除停用词,是否包含n-gram特征等等。其中输出是稀疏矩阵的表示形式。

(0, 11) 1 表示在第0个样本(也就是第一个邮件"Get a free laptop now!")中,词汇表中的第11个词出现了1次。

(1, 6) 1 表示在第1个样本(第二个邮件"Earn money fast with no effort!")中,词汇表中的第6个词出现了1次。

以此类推。这里的词汇表是根据所有邮件内容提取出来的,包含了所有唯一的词。数字11、6等就是每个词在这个词汇表中的位置。

而输出的是稀疏矩阵(sparse matrix)的形式,只显示了非零元素,比如一个词在一个邮件中出现过,那么就显示其行号、列号和计数,没有出现的位置就不显示了。

这样的稀疏矩阵表示可以节省空间,因为大多数位置都是0,不需要存储和显示。

总结一下,这个输出表示了每个邮件中包含的单词及其出现次数,这些特征已经转换为了向量化的表示,作为后续机器学习算法的输入。

						  🤞到这里,如果还有什么疑问🤞
					🎩欢迎私信博主问题哦,博主会尽自己能力为你解答疑惑的!🎩
					 	 🥳如果对你有帮助,你的赞是对博主最大的支持!!🥳
相关推荐
_.Switch22 分钟前
Python 自动化运维持续优化与性能调优
运维·开发语言·python·缓存·自动化·运维开发
1 9 J24 分钟前
Java 上机实践4(类与对象)
java·开发语言·算法
J不A秃V头A28 分钟前
Python爬虫:获取国家货币编码、货币名称
开发语言·爬虫·python
阿斯卡码2 小时前
jupyter添加、删除、查看内核
ide·python·jupyter
passer__jw7672 小时前
【LeetCode】【算法】3. 无重复字符的最长子串
算法·leetcode
passer__jw7672 小时前
【LeetCode】【算法】21. 合并两个有序链表
算法·leetcode·链表
sweetheart7-72 小时前
LeetCode22. 括号生成(2024冬季每日一题 2)
算法·深度优先·力扣·dfs·左右括号匹配
小于小于大橙子3 小时前
视觉SLAM数学基础
人工智能·数码相机·自动化·自动驾驶·几何学
埃菲尔铁塔_CV算法4 小时前
图像算法之 OCR 识别算法:原理与应用场景
图像处理·python·计算机视觉
封步宇AIGC5 小时前
量化交易系统开发-实时行情自动化交易-3.4.2.Okex行情交易数据
人工智能·python·机器学习·数据挖掘