ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

朴素贝叶斯回归分类:从概率计算到连续特征处理实战

朴素贝叶斯回归分类:从概率计算到连续特征处理实战 1. 从“分类”与“回归”的混淆说起为什么需要朴素贝叶斯回归如果你在数据科学或机器学习的入门路上摸索过一阵子大概率会对“分类”和“回归”这两个词既熟悉又困惑。熟悉是因为它们是监督学习的两大基石任务困惑则在于当看到“朴素贝叶斯回归”这样的组合时第一反应往往是这名字是不是写错了朴素贝叶斯不是经典的分类算法吗怎么和回归扯上关系了这正是这个标题最有趣的地方它精准地戳中了一个常见的认知模糊地带。在绝大多数教材和入门教程里朴素贝叶斯Naive Bayes总是以“文本分类”、“垃圾邮件过滤”的明星身份出现它的输出是离散的类别标签比如“是垃圾邮件”或“不是垃圾邮件”。而“回归”任务无论是线性回归还是逻辑回归注意逻辑回归虽然名字带回归但本质是分类其目标通常是预测一个连续的数值。所以“朴素贝叶斯回归”听起来像是个“缝合怪”。但事实并非如此。这里的“回归分类”并非笔误它指向的是朴素贝叶斯算法在处理连续型特征时其核心概率估计过程所蕴含的“回归”思想。更准确地说当我们假设特征服从某种连续概率分布如高斯分布时训练朴素贝叶斯模型的过程实质上是在为每个类别下的每个特征拟合一个概率分布模型。对于高斯朴素贝叶斯这就是在估计每个类别的均值和方差。当你用这个训练好的模型去预测一个新样本时算法计算的是该样本属于各个类别的“后验概率”这个概率值本身是一个连续的、介于0到1之间的数值。虽然我们最终通过比较概率大小来做出“分类”决策选择概率最大的类别但模型内部产出的、作为决策依据的“概率分数”其计算过程与回归模型预测连续值的思路有异曲同工之妙——都是基于输入特征通过一个参数化的模型线性组合之于回归概率密度函数之于朴素贝叶斯计算出一个连续的输出。因此“朴素贝叶斯回归分类”这个说法可以理解为一种强调我们不仅要关注朴素贝叶斯最终“分对了哪一类”这个分类结果更要深入理解它如何计算出属于每一类的“可能性”这个连续的概率值。掌握这一点对于模型评估、阈值调整、以及理解模型在置信度不高时的表现至关重要。这就像医生不仅告诉你诊断结果分类还会告诉你得这个病的概率有多大回归式的概率输出后者往往包含了更丰富的信息。2. 朴素贝叶斯的核心从“条件独立”假设到概率计算引擎要真正掌握朴素贝叶斯无论是用于分类还是理解其回归式的概率输出都必须吃透它的核心原理。这个原理可以用一个简洁而强大的公式概括贝叶斯定理加上一个“朴素”的假设。2.1 贝叶斯定理逆概率问题的钥匙一切始于贝叶斯定理。我们最终想知道的是在观察到样本的特征数据X (x1, x2, ..., xn)之后它属于某个类别C_k的概率是多少即求P(C_k | X)这被称为后验概率。贝叶斯定理给出了计算方法P(C_k | X) [P(X | C_k) * P(C_k)] / P(X)其中P(C_k)是先验概率即在看到任何数据之前我们基于经验认为类别C_k出现的概率。比如在垃圾邮件过滤中垃圾邮件的先验概率可能设为0.5如果我们假设一半是垃圾邮件。P(X | C_k)是似然概率即在类别C_k的条件下观察到特征组合X的概率。这是模型需要从数据中学习的关键部分。P(X)是证据因子即观察到特征X的总概率。在实际分类中由于对于同一个XP(X)是常数我们只需要比较分子大小即可做出决策argmax_{C_k} [P(X | C_k) * P(C_k)]。2.2 “朴素”假设化不可能为可能的关键简化现在问题来了特征X是一个向量包含多个特征(x1, x2, ..., xn)。直接估计P(x1, x2, ..., xn | C_k)这个联合概率分布是极其困难的尤其当特征维度n很高时需要的数据量是指数级增长的这就是所谓的“维度灾难”。朴素贝叶斯的“朴素”之处就在于它做了一个非常强的、但往往在实践中行之有效的假设所有特征在给定类别的条件下是相互独立的。也就是说假设我们知道了一封邮件是垃圾邮件类别给定那么这封邮件里出现“免费”这个词和出现“赢取”这个词的概率是互不影响的。基于这个“条件独立性”假设复杂的联合概率就可以分解为单个特征概率的乘积P(X | C_k) P(x1 | C_k) * P(x2 | C_k) * ... * P(xn | C_k)这样一来问题就大大简化了。我们不需要去估计高维的联合分布只需要为每个类别C_k下的每个特征x_i估计一个一维的概率分布P(x_i | C_k)即可。这个假设虽然很少在现实中完全成立“免费”和“赢取”在垃圾邮件中很可能同时出现但它极大地降低了模型复杂度使计算变得可行并且在很多实际问题中尤其是文本分类表现得出奇地好。2.3 概率估计处理连续与离散特征如何估计P(x_i | C_k)呢这取决于特征x_i的类型离散特征如文本中的词是否出现、分类标签通常使用多项式分布或伯努利分布。例如在文本分类中P(单词“会议” | 类别“工作邮件”)可以用“工作邮件”类别中所有文档里“会议”这个词出现的频率来估计可能加上平滑避免零概率。连续特征如身高、温度、像素强度这就是“回归”思想体现的地方。我们假设连续特征在给定类别下服从某个参数分布最常用的就是高斯正态分布。这就是高斯朴素贝叶斯。我们需要为每个类别C_k下的每个连续特征x_i估计两个参数均值μ_{ik}和标准差σ_{ik}。然后对于一个具体的特征值x_i其似然概率P(x_i | C_k)可以通过高斯分布的概率密度函数PDF计算P(x_i | C_k) (1 / sqrt(2πσ_{ik}^2)) * exp(-(x_i - μ_{ik})^2 / (2σ_{ik}^2))这个过程本质上就是一种“回归”我们用数据某个类别下的所有样本的某个特征值去拟合一个连续的概率分布模型高斯分布。预测时对于一个新的特征值我们通过这个拟合好的模型计算其概率密度这个密度值是一个连续的量。注意这里有一个非常重要的实操细节。概率密度函数PDF的值可以大于1只要曲线下总面积为1即可它代表的是“可能性密度”而非概率。但在朴素贝叶斯的乘法公式中我们直接使用这个密度值作为P(x_i | C_k)的替代。这是因为我们最终比较的是不同类别下这个连乘积的相对大小只要所有类别都使用同样的密度函数计算比例关系就是正确的。这是理解连续特征处理的关键。3. 实战演练手把手实现高斯朴素贝叶斯分类器理解了原理我们通过一个完整的例子从数据准备到模型评估亲手实现并理解一个高斯朴素贝叶斯分类器。我们使用经典的鸢尾花Iris数据集它包含3种鸢尾花Setosa, Versicolor, Virginica每种有50个样本每个样本有4个连续特征萼片长度、萼片宽度、花瓣长度、花瓣宽度。3.1 环境准备与数据概览首先我们需要一个基础的Python科学计算环境。如果你使用Anaconda这些库通常已经安装好了。# 导入必要的库 import numpy as np import pandas as pd from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, classification_report, confusion_matrix import matplotlib.pyplot as plt import seaborn as sns # 加载数据 iris load_iris() X iris.data # 特征矩阵形状 (150, 4) y iris.target # 目标标签0, 1, 2 分别对应三种花 feature_names iris.feature_names target_names iris.target_names # 查看数据基本信息 print(f特征数据形状: {X.shape}) # (150, 4) print(f目标标签形状: {y.shape}) # (150,) print(f特征名称: {feature_names}) print(f类别名称: {target_names}) # 将数据转换为DataFrame便于查看 df pd.DataFrame(X, columnsfeature_names) df[species] pd.Categorical.from_codes(y, target_names) print(df.head()) print(df.groupby(species).size())运行这段代码你会看到数据是平衡的每类50个样本特征都是连续值。接下来我们按惯例划分训练集和测试集。# 划分训练集和测试集保持类别分布 X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.3, random_state42, stratifyy) print(f训练集大小: {X_train.shape}, 测试集大小: {X_test.shape})3.2 核心算法实现从零开始编写高斯朴素贝叶斯我们不直接调用sklearn的GaussianNB而是自己实现一遍以加深对原理的理解。我们的类需要完成以下功能拟合fit计算每个类别的先验概率P(C_k)以及每个类别下每个特征的均值μ_{ik}和方差σ_{ik}^2。预测predict对于新样本计算其属于每个类别的后验概率的对数并返回概率最大的类别标签。可选预测概率predict_proba返回属于每个类别的概率。为什么用对数概率因为多个概率通常是小于1的小数连乘会导致数值下溢结果无限接近于0。取对数后连乘变为连加不仅避免了数值问题计算也更快。class GaussianNaiveBayes: def __init__(self): self.classes_ None self.priors_ None # 先验概率的对数 self.means_ None # 每个类别下每个特征的均值 self.vars_ None # 每个类别下每个特征的方差 self.epsilon 1e-9 # 一个小常数防止方差为0导致除零错误 def fit(self, X, y): 训练模型。 参数: X: 训练特征形状 (n_samples, n_features) y: 训练标签形状 (n_samples,) n_samples, n_features X.shape self.classes_ np.unique(y) n_classes len(self.classes_) # 初始化存储数组 self.means_ np.zeros((n_classes, n_features)) self.vars_ np.zeros((n_classes, n_features)) self.priors_ np.zeros(n_classes) for idx, c in enumerate(self.classes_): # 获取属于当前类别的所有样本 X_c X[y c] # 计算先验概率该类样本数 / 总样本数 self.priors_[idx] np.log(X_c.shape[0] / n_samples) # 存储对数先验 # 计算每个特征的均值和方差 self.means_[idx, :] X_c.mean(axis0) self.vars_[idx, :] X_c.var(axis0) self.epsilon # 添加平滑项 def _calculate_log_likelihood(self, x, mean, var): 计算单个特征值在高斯分布下的对数似然。 # 高斯分布的对数概率密度函数公式 return -0.5 * (np.log(2 * np.pi * var) (x - mean) ** 2 / var) def predict_log_proba(self, X): 计算样本属于每个类别的对数后验概率。 返回: 形状 (n_samples, n_classes) n_samples, n_features X.shape n_classes len(self.classes_) log_proba np.zeros((n_samples, n_classes)) for idx in range(n_classes): # 对数先验 prior self.priors_[idx] # 对数似然对每个特征的对数似然求和条件独立假设 log_likelihood np.sum(self._calculate_log_likelihood(X, self.means_[idx], self.vars_[idx]), axis1) # 对数后验 对数先验 对数似然 (证据因子P(X)是常数在比较时忽略) log_proba[:, idx] prior log_likelihood return log_proba def predict_proba(self, X): 将对数概率转换回概率需归一化。 log_proba self.predict_log_proba(X) # 减去每行的最大值避免指数运算溢出这是一个常见的数值稳定技巧 log_proba_max log_proba.max(axis1, keepdimsTrue) log_proba_adj log_proba - log_proba_max proba np.exp(log_proba_adj) proba_sum proba.sum(axis1, keepdimsTrue) return proba / proba_sum def predict(self, X): 预测类别标签。 log_proba self.predict_log_proba(X) # 选择对数概率最大的类别 return self.classes_[np.argmax(log_proba, axis1)]3.3 模型训练、预测与评估现在我们用自己实现的模型和sklearn的官方实现同时进行训练和预测并对比结果。# 使用我们自己的实现 my_gnb GaussianNaiveBayes() my_gnb.fit(X_train, y_train) y_pred_my my_gnb.predict(X_test) y_proba_my my_gnb.predict_proba(X_test) # 获取概率输出 # 使用sklearn的实现进行对比 from sklearn.naive_bayes import GaussianNB sk_gnb GaussianNB() sk_gnb.fit(X_train, y_train) y_pred_sk sk_gnb.predict(X_test) y_proba_sk sk_gnb.predict_proba(X_test) print( 自定义模型性能 ) print(f准确率: {accuracy_score(y_test, y_pred_my):.4f}) print(分类报告:) print(classification_report(y_test, y_pred_my, target_namestarget_names)) print(\n Scikit-learn模型性能 ) print(f准确率: {accuracy_score(y_test, y_pred_sk):.4f}) print(分类报告:) print(classification_report(y_test, y_pred_sk, target_namestarget_names)) # 检查概率输出是否接近由于数值计算细节可能略有差异 print(f\n概率预测的均方误差自定义 vs sklearn: {np.mean((y_proba_my - y_proba_sk)**2):.10f})运行后你会发现两个模型的准确率几乎一样通常在0.95以上概率预测也高度一致。这验证了我们自己实现的正确性。更重要的是我们通过predict_proba方法获得了每个测试样本属于三个类别的概率这是一个连续的、向量形式的输出。例如对于一个样本输出可能是[0.01, 0.85, 0.14]这明确告诉我们模型认为它属于第二类Versicolor的“信心”非常足。这种概率输出就是朴素贝叶斯“回归”能力的体现。3.4 可视化决策边界与概率输出为了更直观地理解模型如何工作我们可以可视化其在两个主要特征上的决策边界和概率等高线。# 为了可视化我们只取两个特征花瓣长度和花瓣宽度 X_train_2d X_train[:, [2, 3]] # 索引2和3对应花瓣长度和宽度 X_test_2d X_test[:, [2, 3]] # 在2D特征上重新训练模型 my_gnb_2d GaussianNaiveBayes() my_gnb_2d.fit(X_train_2d, y_train) # 创建网格来绘制决策区域 x_min, x_max X_train_2d[:, 0].min() - 0.5, X_train_2d[:, 0].max() 0.5 y_min, y_max X_train_2d[:, 1].min() - 0.5, X_train_2d[:, 1].max() 0.5 xx, yy np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02)) # 预测网格上每个点的类别和属于第一类Setosa的概率 Z my_gnb_2d.predict(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) # 计算属于类别0的概率 proba_setosa my_gnb_2d.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 0] proba_setosa proba_setosa.reshape(xx.shape) # 开始绘图 plt.figure(figsize(15, 5)) # 子图1决策边界 plt.subplot(1, 2, 1) # 绘制决策区域 from matplotlib.colors import ListedColormap cmap_light ListedColormap([#FFAAAA, #AAFFAA, #AAAAFF]) plt.contourf(xx, yy, Z, cmapcmap_light, alpha0.8) # 绘制训练数据点 for i, color, target_name in zip([0,1,2], [red, green, blue], target_names): idx np.where(y_train i) plt.scatter(X_train_2d[idx, 0], X_train_2d[idx, 1], ccolor, labeltarget_name, edgecolork, s50) plt.xlabel(花瓣长度 (cm)) plt.ylabel(花瓣宽度 (cm)) plt.title(高斯朴素贝叶斯决策区域 (2D特征)) plt.legend() plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) # 子图2类别0Setosa的概率等高线 plt.subplot(1, 2, 2) # 绘制概率等高线 contour plt.contourf(xx, yy, proba_setosa, levels20, cmapRdYlBu) plt.colorbar(contour, labelP(Setosa)) # 绘制训练数据点 for i, color, target_name in zip([0,1,2], [red, green, blue], target_names): idx np.where(y_train i) plt.scatter(X_train_2d[idx, 0], X_train_2d[idx, 1], ccolor, labeltarget_name, edgecolork, s50) plt.xlabel(花瓣长度 (cm)) plt.ylabel(花瓣宽度 (cm)) plt.title(属于Setosa类别的概率等高线) plt.legend() plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) plt.tight_layout() plt.show()这张图非常具有启发性。左图显示了清晰的线性决策边界这是因为在高斯假设下同类样本的决策边界是二次的但在某些情况下如方差相等会退化为线性。右图的概率等高线则完美展示了“回归”的一面颜色从深蓝概率接近0平滑过渡到深红概率接近1在决策边界附近概率值在0.5附近变化。模型不仅做出了分类还给出了一个连续、平滑的“置信度”地图。你可以清晰地看到离Setosa类别的中心红色点簇越远属于它的概率就越低。4. 超越基础朴素贝叶斯的优势、局限与调优实战通过上面的实战我们看到了朴素贝叶斯简单有效的一面。但它绝非万能。在实际项目中深刻理解其优势和局限并掌握相应的调优技巧是将其价值最大化的关键。4.1 核心优势为什么它至今仍被广泛应用极高的训练和预测效率由于“朴素”的独立性假设模型只需要计算每个特征在每个类别下的统计量如均值和方差。训练过程就是简单的计数或计算均值/方差时间复杂度是O(n_samples * n_features)对于大规模数据集非常友好。预测时也只是进行几次概率密度计算和乘法或对数加法速度极快。对小规模数据和不完整数据相对稳健即使训练数据量不大它也能给出不错的概率估计。对于缺失值在离散特征情况下可以通过平滑技术处理在连续特征情况下如果某个特征缺失在计算联合概率时可以直接忽略该特征因为独立假设下是连乘乘以1不影响结果这比其他模型如决策树需要插补更简单。天然的多分类支持与概率输出不像SVM等需要改造才能处理多分类朴素贝叶斯直接可以处理任意多分类问题。其输出的概率具有较好的解释性可以用于构建更复杂的决策系统如结合成本矩阵。对无关特征有一定鲁棒性如果一个特征与类别完全无关那么它在所有类别下的分布会趋于一致在计算后验概率时这个特征项P(x_i|C_k)对所有类别C_k都差不多在比较时影响力就会减弱。当然这并不意味着你可以随意加入无关特征。4.2 固有局限与常见陷阱“朴素”假设的强约束这是它最大的弱点。现实中特征之间往往存在相关性例如在文本分类中“苹果”和“公司”这两个词在“科技”类别下是高度相关的。独立性假设会高估或低估某些特征组合出现的概率可能导致模型性能下降尤其是在特征间存在强依赖关系时。连续特征分布假设可能不成立高斯朴素贝叶斯假设特征服从正态分布。如果真实分布严重偏离正态如极度偏斜、多峰分布模型的性能会大打折扣。例如预测房价时房价的分布通常不是对称的正态分布。“零概率”问题在离散特征如文本中如果某个特征值在训练集的某个类别中从未出现那么P(x_i | C_k) 0这会导致整个联合概率为0无论其他特征多么有说服力。这在高维稀疏数据中很常见。对输入数据的尺度敏感虽然高斯朴素贝叶斯本身不受特征尺度影响因为它是基于分布形状但如果数据预处理不当如存在异常值会严重影响均值和方差的估计从而影响模型。4.3 实战调优技巧与问题诊断针对上述局限在实际项目中我们可以采取以下策略1. 处理连续特征分布检验与变换在应用高斯朴素贝叶斯前务必检查连续特征的分布。可以使用直方图、Q-Q图或统计检验如Shapiro-Wilk检验。import scipy.stats as stats # 以鸢尾花花瓣长度为例 feature_data X_train[:, 2] # 花瓣长度 plt.figure(figsize(12,4)) plt.subplot(1,2,1) plt.hist(feature_data, bins20, edgecolorblack) plt.title(花瓣长度分布直方图) plt.subplot(1,2,2) stats.probplot(feature_data, distnorm, plotplt) plt.title(Q-Q图) plt.show() # Shapiro-Wilk检验 stat, p stats.shapiro(feature_data) print(fShapiro-Wilk检验统计量{stat:.3f}, p值{p:.3f}) if p 0.05: print(样本可能服从正态分布) else: print(样本可能不服从正态分布)如果分布严重非正态可以考虑进行数据变换对数变换适用于右偏分布如收入、房价。np.log1p(X)。Box-Cox变换一种更通用的幂变换可以自动寻找最佳变换参数。from scipy.stats import boxcox。分箱离散化将连续特征转换为有序的离散区间然后使用多项式朴素贝叶斯。这牺牲了一些信息但完全避开了分布假设。pd.cut。2. 处理离散特征与零概率问题平滑技术对于文本分类等场景必须使用平滑。最常见的是拉普拉斯平滑Laplace Smoothing或加一平滑。假设一个特征有V个可能的取值在计算P(x_iv | C_k)时公式变为P(x_iv | C_k) (count(v, C_k) α) / (count(C_k) α * V)其中α是平滑参数通常设为1。在sklearn的MultinomialNB和BernoulliNB中通过参数alpha来控制。3. 特征选择与相关性处理虽然朴素贝叶斯对无关特征有一定容忍度但冗余或高度相关的特征会放大独立性假设的误差。进行特征选择是有益的。方差过滤移除方差极低的特征几乎为常数。互信息法选择与目标类别互信息最高的特征。主成分分析PCA在极端情况下可以通过PCA提取不相关的主成分然后再用朴素贝叶斯。但要注意PCA后的特征失去了原始语义且独立性假设在理论上可能仍然不成立这是一种工程上的折中。4. 处理类别不平衡朴素贝叶斯的先验概率P(C_k)直接由训练集各类别样本数计算。如果数据严重不平衡模型会倾向于预测多数类。解决方法在fit时设置class_prior参数手动指定先验概率。使用class_weight参数如果算法支持或在训练时对少数类样本进行过采样。5. 模型诊断当准确率不高时如果你的朴素贝叶斯模型表现不佳可以按以下步骤排查检查特征分布如上所述用可视化工具看特征是否严重偏离正态。检查特征独立性计算特征间的相关系数矩阵。如果存在高度相关的特征对如相关系数 0.8考虑移除其中一个或使用PCA。检查“零概率”问题对于离散特征查看训练后每个类别的特征概率矩阵是否有大量零值。与更复杂的模型对比训练一个逻辑回归或随机森林作为基准。如果朴素贝叶斯显著差于它们很可能是因为独立性假设过于违背现实。进行交叉验证确保性能评估是稳定的避免因数据划分导致的偶然性。5. 进阶应用从概率输出到现实世界决策朴素贝叶斯输出的概率不仅仅是用来选最大值的。在许多实际场景中这个连续的、可解释的概率分数本身就是宝贵的输出。5.1 设置分类阈值与代价敏感学习在垃圾邮件过滤中把正常邮件误判为垃圾邮件False Positive的代价可能比漏掉垃圾邮件False Negative更高。我们不能简单地以0.5为阈值。 假设我们有一个二分类问题1垃圾邮件0正常邮件模型给出了P(垃圾邮件|邮件)的概率。我们可以定义一个代价矩阵C_FP: 将正常邮件判为垃圾邮件的代价。C_FN: 将垃圾邮件判为正常邮件的代价。最优决策不再是概率大于0.5就判为垃圾邮件而是当P(垃圾邮件|邮件) * C_FN (1 - P(垃圾邮件|邮件)) * C_FP时才判为垃圾邮件。 化简后得到阈值T C_FP / (C_FP C_FN)。 如果C_FP是C_FN的4倍误杀正常邮件代价更高那么阈值T 4/(41) 0.8。只有当模型有80%以上的把握时我们才将其标记为垃圾邮件。朴素贝叶斯直接输出的概率使得这种基于代价的决策变得非常直接。5.2 构建排序系统与推荐在一些场景中我们不需要硬分类而是需要根据“属于某个类别的可能性”进行排序。例如异常检测计算每个样本属于“正常”类别的概率将概率最低的N个样本作为异常候选进行人工审核。内容推荐在新闻分类中计算一篇文章属于“体育”、“科技”、“财经”等各类别的概率。即使最终将其归入概率最高的“科技”类我们也可以将“财经”概率第二高的文章推荐给对财经也感兴趣的用户。sklearn的predict_proba输出正好是一个完美的“兴趣强度”向量。5.3 作为更复杂模型的组件朴素贝叶斯融合朴素贝叶斯的高效和概率输出特性使其可以作为大型系统中的一个可靠组件。集成学习可以将多个在不同特征子集上训练的朴素贝叶斯模型进行平均软投票提升稳定性和性能。层级分类在海量类别的分类问题中如商品分类可以先用一个朴素的贝叶斯进行粗分类如“电子产品” vs “服装”然后在粗分类内部使用更复杂的模型如BERT进行细分类以平衡精度和效率。半监督学习利用朴素贝叶斯对未标记数据预测概率将高置信度的预测作为伪标签加入训练集迭代训练这是一种经典的自我训练Self-training策略。5.4 一个综合案例客户流失预测假设我们有一个电信客户数据集要预测客户是否会流失。特征包括月费用连续、合约期限连续、客服呼叫次数连续、是否开通国际漫游二元、支付方式分类电子支票、邮寄支票、银行转账、信用卡。数据预处理对连续特征月费用、合约期限、呼叫次数检查分布并做必要的变换如对数变换。对分类特征支付方式进行独热编码或直接使用CategoricalNBsklearn0.24版本支持。模型训练使用高斯朴素贝叶斯处理连续特征结合处理分类特征的方法。注意sklearn的GaussianNB只处理连续特征你需要将处理后的分类特征与其他连续特征拼接或者使用Pipeline和ColumnTransformer。概率校准朴素贝叶斯输出的概率往往不是“校准良好”的即预测为0.9的事件实际发生的频率可能不是90%。对于需要精确概率的场景如计算客户终身价值可以使用CalibratedClassifierCV对概率输出进行校准。决策制定根据predict_proba输出的流失概率结合客户的价值ARPU平均用户收入计算每个客户的“风险价值”。对高风险高价值的客户优先进行挽留干预。在整个过程中朴素贝叶斯模型提供的不仅仅是一个“会/不会流失”的标签而是一个可用于资源优化配置的连续风险评分这正是其“回归分类”双重价值的完美体现。从我个人的多次项目经验来看朴素贝叶斯是一个“被低估的基准模型”。它简单到常常被初学者跳过又被追求复杂度的从业者忽视。但它的高效、稳定和可解释的概率输出使其在数据探索、快速原型构建、以及作为复杂系统的基础组件方面具有不可替代的价值。下次当你面对一个分类问题时不妨先从训练一个朴素贝叶斯模型开始看看它的概率输出能告诉你关于数据的哪些故事这往往是一个非常有价值的起点。
返回列表