人工智能数学基础实验(四):最大似然估计的-AI 模型训练与参数优化

[复制链接]
发表于 2025-5-26 16:18:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一、实验目标


  • 理解最大似然估计(MLE)原理:掌握通过最大化数据出现概率估计模型参数的焦点头脑。
  • 实现 MLE 与 AI 模型结合:使用 MLE 手动估计朴素贝叶斯模型参数,并与 Scikit-learn 内置模型对比,深入理解参数优化对分类性能的影响。
  • 分析模型性能影响因素:探究训练集 / 测试集比例、特性数目对模型准确率、运行时间的影响,提升数据建模与调优本领。
二、实验要求

(一)数据预备



  • 天生或加载二分类数据集,使用 Scikit-learn 的make_classification创建含 20 维特性的 1000 样本数据。
  • 划分训练集与测试集,初始比例为 7:3。
(二)MLE 参数估计



  • 假设特性服从高斯分布,手动计算各分类的均值、方差及先验概率。
  • 推导后验概率公式,实现基于 MLE 的朴素贝叶斯分类器。
(三)模型构建与对比



  • 手动实现:基于 MLE 参数的朴素贝叶斯分类器,对新样本举行分类猜测。
  • Scikit-learn 对比:使用GaussianNB内置模型,比力两者的准确率、准确率、召回率及运行时间。
(四)性能分析



  • 调整测试集比例(0.2~0.5),观察模型稳定性。
  • 改变特性数目(10~50),分析特性维度对模型性能的影响。
三、实验原理



四、实验步骤

(一)数据天生与预处理

  1. import numpy as np  
  2. from sklearn.datasets import make_classification  
  3. # 生成二分类数据集  
  4. X, y = make_classification(  
  5.     n_samples=1000, n_features=20, n_classes=2, random_state=42  
  6. )  
  7. # 划分训练集与测试集(初始比例7:3)  
  8. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)  
复制代码
(二)手动实现 MLE 与朴素贝叶斯

  1. class ManualNaiveBayes:  
  2.     def fit(self, X, y):  
  3.         self.classes = np.unique(y)  
  4.         self.params = {}  
  5.         for c in self.classes:  
  6.             X_c = X[y == c]  
  7.             self.params[c] = {  
  8.                 'mean': np.mean(X_c, axis=0),  # 均值  
  9.                 'var': np.var(X_c, axis=0),    # 方差  
  10.                 'prior': len(X_c) / len(X)     # 先验概率  
  11.             }  
  12.     def predict(self, X):  
  13.         posteriors = []  
  14.         for c in self.classes:  
  15.             prior = np.log(self.params[c]['prior'])  
  16.             mean = self.params[c]['mean']  
  17.             var = self.params[c]['var']  
  18.             # 计算对数似然  
  19.             likelihood = -0.5 * np.sum(np.log(2 * np.pi * var)) - 0.5 * np.sum(((X - mean)**2)/var, axis=1)  
  20.             posterior = prior + likelihood  
  21.             posteriors.append(posterior)  
  22.         return self.classes[np.argmax(posteriors, axis=0)]  # 选择后验概率最大的类别  
复制代码
(三)模型训练与对比

  1. from sklearn.naive_bayes import GaussianNB  
  2. from sklearn.metrics import accuracy_score  
  3. # 手动模型训练与预测  
  4. manual_nb = ManualNaiveBayes()  
  5. manual_nb.fit(X_train, y_train)  
  6. y_pred_manual = manual_nb.predict(X_test)  
  7. # Scikit-learn模型训练与预测  
  8. sklearn_nb = GaussianNB()  
  9. sklearn_nb.fit(X_train, y_train)  
  10. y_pred_sklearn = sklearn_nb.predict(X_test)  
  11. # 性能指标计算  
  12. print(f"手动实现准确率:{accuracy_score(y_test, y_pred_manual):.4f}")  
  13. print(f"Sklearn实现准确率:{accuracy_score(y_test, y_pred_sklearn):.4f}")  
复制代码
(四)参数调优与分析



  • 测试集比例影响:循环测试test_size=[0.2, 0.3, 0.4, 0.5],发现两者准确率波动较小(手动实现约 0.69~0.71,Scikit-learn 约 0.70~0.72),但 Scikit-learn 在测试集比例较大时稳定性略优。
  • 特性数目影响:特性数从 10 增至 30 时,准确率上升(峰值约 0.73);超过 30 后因过拟合降落。手动实现运行时间随特性数呈平方级增长,Scikit-learn 因底层优化增长迟钝。
(五)完整源代码

  1. import numpy as np
  2. from sklearn.model_selection import train_test_split
  3. from sklearn.naive_bayes import GaussianNB
  4. from sklearn.metrics import accuracy_score, precision_score, recall_score
  5. import matplotlib.pyplot as plt
  6. from sklearn.datasets import make_classification
  7. import time
  8. plt.rcParams['font.sans-serif'] = ['SimHei']
  9. plt.rcParams['axes.unicode_minus'] = False
  10. # 1. 数据加载与预处理
  11. # 生成随机二分类数据集
  12. X, y = make_classification(
  13.     n_samples=1000,  # 样本数量
  14.     n_features=20,  # 特征数量
  15.     n_classes=2,  # 类别数量
  16.     n_informative=15,  # 有信息量的特征数量
  17.     n_redundant=3,  # 冗余特征数量
  18.     n_repeated=2,  # 重复特征数量
  19.     class_sep=0.5,  # 类别之间的分离程度
  20.     random_state=42
  21. )
  22. # 划分训练集和测试集
  23. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
  24. # 2. 手动实现MLE估计(朴素贝叶斯)
  25. class ManualNaiveBayes:
  26.     def fit(self, X, y):
  27.         self.classes = np.unique(y)
  28.         self.params = {}
  29.         for c in self.classes:
  30.             X_c = X[y == c]
  31.             self.params[c] = {
  32.                 'mean': np.mean(X_c, axis=0),
  33.                 'var': np.var(X_c, axis=0),
  34.                 'prior': len(X_c) / len(X)
  35.             }
  36.     def predict(self, X):
  37.         X = np.array(X)  # 确保输入是numpy数组
  38.         posteriors = []
  39.         for c in self.classes:
  40.             prior = np.log(self.params[c]['prior'])
  41.             mean = self.params[c]['mean']
  42.             var = self.params[c]['var']
  43.             likelihood = -0.5 * np.sum(np.log(2 * np.pi * var)) - 0.5 * np.sum(((X - mean) ** 2) / var, axis=1)
  44.             posterior = prior + likelihood
  45.             posteriors.append(posterior)
  46.         return self.classes[np.argmax(posteriors, axis=0)]
  47. # 3. 使用sklearn的朴素贝叶斯对比
  48. # 手动实现模型
  49. manual_nb = ManualNaiveBayes()
  50. start_time = time.time()
  51. manual_nb.fit(X_train, y_train)
  52. y_pred_manual = manual_nb.predict(X_test)
  53. manual_time = time.time() - start_time
  54. # sklearn模型
  55. sklearn_nb = GaussianNB()
  56. start_time = time.time()
  57. sklearn_nb.fit(X_train, y_train)
  58. y_pred_sklearn = sklearn_nb.predict(X_test)
  59. sklearn_time = time.time() - start_time
  60. # 4. 结果可视化输出
  61. # 绘制原始数据分布
  62. plt.figure(figsize=(12, 6))
  63. plt.subplot(1, 3, 1)
  64. plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', marker='o')
  65. plt.title('原始数据分布')
  66. plt.xlabel('特征1')
  67. plt.ylabel('特征2')
  68. # 绘制手动实现模型的分类结果
  69. plt.subplot(1, 3, 2)
  70. plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred_manual, edgecolors='k', marker='o')
  71. plt.title('手动实现分类结果')
  72. plt.xlabel('特征1')
  73. plt.ylabel('特征2')
  74. # 绘制sklearn模型的分类结果
  75. plt.subplot(1, 3, 3)
  76. plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred_sklearn, edgecolors='k', marker='o')
  77. plt.title('sklearn分类结果')
  78. plt.xlabel('特征1')
  79. plt.ylabel('特征2')
  80. plt.tight_layout()
  81. plt.show()
  82. # 5. 终端输出性能指标
  83. # 计算手动实现的模型性能指标
  84. manual_acc = accuracy_score(y_test, y_pred_manual)
  85. manual_pre = precision_score(y_test, y_pred_manual)
  86. manual_rec = recall_score(y_test, y_pred_manual)
  87. # 计算sklearn模型性能指标
  88. sklearn_acc = accuracy_score(y_test, y_pred_sklearn)
  89. sklearn_pre = precision_score(y_test, y_pred_sklearn)
  90. sklearn_rec = recall_score(y_test, y_pred_sklearn)
  91. print("手动实现的朴素贝叶斯分类器:")
  92. print(f"准确率:{manual_acc:.4f}")
  93. print(f"精确率:{manual_pre:.4f}")
  94. print(f"召回率:{manual_rec:.4f}")
  95. print(f"运行时间:{manual_time:.4f}秒")
  96. print("\n使用sklearn的高斯朴素贝叶斯分类器:")
  97. print(f"准确率:{sklearn_acc:.4f}")
  98. print(f"精确率:{sklearn_pre:.4f}")
  99. print(f"召回率:{sklearn_rec:.4f}")
  100. print(f"运行时间:{sklearn_time:.4f}秒")
  101. # 6. 不同训练集/测试集比例下的性能指标变化分析
  102. test_sizes = [0.2, 0.3, 0.4, 0.5]
  103. manual_accs = []
  104. sklearn_accs = []
  105. manual_times = []
  106. sklearn_times = []
  107. for test_size in test_sizes:
  108.     X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=42)
  109.     # 手动实现模型
  110.     manual_nb = ManualNaiveBayes()
  111.     start_time = time.time()
  112.     manual_nb.fit(X_train, y_train)
  113.     y_pred_manual = manual_nb.predict(X_test)
  114.     manual_acc = accuracy_score(y_test, y_pred_manual)
  115.     manual_time = time.time() - start_time
  116.     manual_accs.append(manual_acc)
  117.     manual_times.append(manual_time)
  118.     # sklearn模型
  119.     sklearn_nb = GaussianNB()
  120.     start_time = time.time()
  121.     sklearn_nb.fit(X_train, y_train)
  122.     y_pred_sklearn = sklearn_nb.predict(X_test)
  123.     sklearn_acc = accuracy_score(y_test, y_pred_sklearn)
  124.     sklearn_time = time.time() - start_time
  125.     sklearn_accs.append(sklearn_acc)
  126.     sklearn_times.append(sklearn_time)
  127. # 绘制不同测试集比例下的准确率变化
  128. plt.figure(figsize=(12, 6))
  129. plt.subplot(1, 2, 1)
  130. plt.plot(test_sizes, manual_accs,color='red',marker='o',label='手动实现')
  131. plt.plot(test_sizes, sklearn_accs,color='green', label='sklearn实现')
  132. plt.xlabel('测试集比例')
  133. plt.ylabel('准确率')
  134. plt.title('不同测试集比例下的准确率变化')
  135. plt.legend()
  136. plt.grid(True)
  137. # 绘制不同测试集比例下的运行时间变化
  138. plt.subplot(1, 2, 2)
  139. plt.plot(test_sizes, manual_times, marker='o', label='手动实现')
  140. plt.plot(test_sizes, sklearn_times, marker='o', label='sklearn实现')
  141. plt.xlabel('测试集比例')
  142. plt.ylabel('运行时间(秒)')
  143. plt.title('不同测试集比例下的运行时间变化')
  144. plt.legend()
  145. plt.grid(True)
  146. plt.tight_layout()
  147. plt.show()
复制代码
五、实验结果

(一)基础性能对比

模型类型准确率准确率召回率运行时间(秒)手动实现(MLE)0.69670.72790.64710.0009Scikit-learn0.69670.72790.64710.0020




(二)关键结论


  • MLE 的有用性:手动实现成功通过 MLE 估计参数,验证了朴素贝叶斯的分类逻辑,但细节优化不敷(如未处理数值稳定性)。
  • 库函数上风:Scikit-learn 的GaussianNB在雷同准确率下更高效稳定,得当现实应用;手动实现得当学习算法原理。
  • 特性与数据划分:特性数适中(20~30 维)时模型最佳,过多需降维;测试集比例对结果影响较小,建议使用交叉验证提升可靠性。




六、总结

   本次实验通过手动实现 MLE 与朴素贝叶斯分类器,深入理解了参数估计的数学原理,并对比了 Scikit-learn 库函数的性能。结果表明,MLE 是毗连统计理论与呆板学习的重要桥梁,而成熟库函数在工程实践中更具上风。未来可进一步优化手动代码(如向量化计算、正则化),或探索 MLE 在其他模型(如逻辑回归)中的应用。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表