当前位置: 首页 > news >正文

构建AI智能体:六十四、模型拟合的平衡艺术:深入理解欠拟合与过拟合

一、模型训练通病

        不知道大家有没有过类似的经历,在很多针对数据类处理的项目中,我们常常遇到这样的困境,模型在训练数据上表现不佳,或者相反,在训练数据上表现完美却在真实场景中一败涂地。这些问题的根源往往在于模型拟合的两种极端状态—欠拟合和过拟合。

        首先了解,什么是拟合,拟合是指将一个模型或函数与实际数据相匹配,以得到一个能够描述或预测这些数据的最佳模型或函数。通俗的讲,想象一下你正在学习一门新课程:

  • 欠拟合就像只看了目录,对知识点一知半解
  • 过拟合就像死记硬背所有例题,但无法解决变型题目
  • 良好拟合则是真正理解了知识原理,能够举一反三

二、MSE(均方误差)简介

1. 基本概念

        MSE(均方误差) 是机器学习中最常用的回归问题评估指标,用于衡量模型预测值与真实值之间的差异程度。

2. 计算公式

MSE = (1/n) × Σ(预测值 - 真实值)²

其中:

  • n:样本数量
  • Σ:求和符号
  • (预测值 - 真实值):单个样本的预测误差

3. 核心特点

3.1 优点:

  • 数学性质优秀:处处可导,便于优化算法(如梯度下降)
  • 惩罚大误差:平方项使较大误差获得更大权重
  • 直观易懂:数值越小代表模型越好

3.2 缺点:

  • 对异常值敏感:离群点会显著增大MSE
  • 量纲问题:单位是原始数据的平方,解释性稍差

4. 实际意义

  • MSE = 0:完美预测,所有预测值与真实值完全一致
  • MSE 较小:模型预测准确度高
  • MSE 较大:模型预测误差大,需要改进

5. 在拟合问题中的应用

  • 欠拟合:训练集和测试集MSE都较高
  • 过拟合:训练集MSE很低,测试集MSE较高
  • 良好拟合:训练集和测试集MSE都适中且接近

MSE就像模型的"成绩单",数值直接反映了预测的精准程度,是模型优化过程中最重要的指导指标之一。

三、什么是欠拟合

定义:模型过于简单,无法捕捉数据中的基本模式和规律,导致在训练数据和测试数据上都表现不佳。

直观理解:就像用直尺去测量弯曲的线条,总是存在很大的误差。

1. 欠拟合的典型表现

1.1 训练集表现差

  • 模型在训练数据上的预测准确率低
  • 损失函数值高且下降缓慢

1.2 测试集同样糟糕

  • 泛化能力差,在新数据上表现同样不好
  • 训练误差和测试误差都很高

1.3 学习曲线特征

  • 训练误差: 高且平坦
  • 测试误差: 高且平坦  
  • 泛化差距: 很小

2. 欠拟合的常见原因

2.1 模型复杂度不足

  • 使用线性模型处理非线性问题
  • 模型参数过少,表达能力有限

2.2 特征工程不充分

  • 缺少重要特征
  • 特征变换不足(如未添加多项式特征)

2.3 训练不充分

  • 训练迭代次数不够
  • 学习率设置不当

3. 示例详细分析

3.1 示例代码

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 生成示例数据
np.random.seed(42)
X = np.linspace(0, 10, 100).reshape(-1, 1)
y_true = 2 * np.sin(X.ravel()) + 0.5 * X.ravel()  # 真实关系
y_noisy = y_true + np.random.normal(0, 0.5, 100)  # 添加噪声# 使用过于简单的模型(线性回归)拟合非线性数据
linear_model = LinearRegression()
linear_model.fit(X, y_noisy)
y_pred_linear = linear_model.predict(X)plt.figure(figsize=(12, 5))
plt.scatter(X, y_noisy, alpha=0.6, label='观测数据')
plt.plot(X, y_true, 'g-', linewidth=2, label='真实关系')
plt.plot(X, y_pred_linear, 'r-', linewidth=2, label='线性模型预测')
plt.title('欠拟合示例:线性模型无法捕捉非线性关系')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"线性模型训练MSE: {mean_squared_error(y_noisy, y_pred_linear):.4f}")

3.2 输出结果

线性模型训练MSE: 1.9636

这张图展示了欠拟合的典型特征:

  • 核心问题:使用过于简单的模型(线性回归)来解决复杂问题(非线性关系)
  • 具体表现:
    • 预测直线无法跟随数据波动
    • 系统性高估和低估交替出现
    • 完全忽略数据的周期性模式
  • 根本原因:模型假设(线性)与数据本质(非线性)不匹配
  • 解决方向:使用更复杂的模型或进行特征工程,使模型能够表达数据的真实模式。
3.2.1 可视化元素解析

3.2.1.1 散点图(观测数据)

  • 蓝色散点代表带有噪声的观测数据
  • 数据点围绕一条波浪形曲线分布,同时有向上的趋势
  • 点的分布显示了一定的随机性,这是添加的噪声造成的

3.2.1.2 绿色曲线(真实关系)

  • 平滑的波浪形曲线:y = 2*sin(x) + 0.5*x
  • 包含两个组成部分:
    • 正弦波动:2*sin(x) 产生周期性起伏
    • 线性趋势:0.5*x 产生整体向上的斜率
  • 这是数据生成的真相,我们希望通过模型学习到的关系

3.2.1.3 红色直线(线性模型预测)

  • 一条简单的斜直线
  • 试图用线性关系来近似整个数据分布
  • 完全忽略了数据的波浪形特征
3.2.2 视觉对比特征

3.2.2.1 形态差异

  • 真实关系:曲线波动 + 线性上升
  • 模型预测:简单直线
  • 两者在多个区域存在明显偏差

3.2.2.2 拟合质量

  • 在x=2.5、x=8等波峰处,红线远低于真实值
  • 在x=5、x=10等波谷处,红线远高于真实值
  • 只有在少数交叉点附近拟合较好
3.2.3 偏差原因分析

3.2.3.1 模型假设与数据本质的冲突

  • 线性模型的基本假设:y = β₀ + β₁x₁,只能表达线性关系
  • 但真实数据生成过程:y = 2*sin(x) + 0.5*x,表达的是复杂的非线性关系
  • 根本冲突:
    • 线性回归假设特征与目标之间存在线性关系
    • 但真实数据包含非线性(正弦)成分
    • 这种假设冲突导致模型无法正确学习数据模式

3.2.3.2 模型复杂度不足

  • 参数空间限制:
    • 线性模型参数:只有2个(截距β₀和斜率β₁)
    • 需要的参数:无限多个(才能准确表达正弦函数)
  • 表达能力对比:
    • 线性模型:只能表达直线
    • 需要模型:能够表达曲线、波动的复杂函数
    • 复杂度差距导致系统性偏差

3.2.3.3 偏差-方差分解角度

  • 总误差 = 偏差² + 方差 + 不可减少误差
  • 在这个例子中:
    • 高偏差:由于模型过于简单,无法捕捉数据真实模式
    • 低方差:模型稳定,对数据变化不敏感
    • 结果:偏差主导了总误差

3.2.3.4 线性模型的局限性

  • 只能学习一阶多项式关系
  • 无法逼近周期函数、指数函数等复杂模式
  • 在函数空间中的表达能力有限

3.3 解决方案

3.3.1 方法纠正

错误方法(当前使用)

# 欠拟合的线性模型
model = LinearRegression()  # 过于简单

正确方法示例

# 方法1:多项式回归
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipelinepoly_model = Pipeline([('poly', PolynomialFeatures(degree=4)),  # 增加复杂度('linear', LinearRegression())
])# 方法2:使用非线性模型
from sklearn.tree import DecisionTreeRegressor
tree_model = DecisionTreeRegressor(max_depth=5)# 方法3:添加正弦特征
X_enhanced = np.column_stack([X, np.sin(X), np.cos(X)])
enhanced_model = LinearRegression()
3.3.2 改进方案

3.3.2.1 改进代码

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.metrics import mean_squared_error, r2_score
import warnings
warnings.filterwarnings('ignore')# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 生成示例数据
np.random.seed(42)
X = np.linspace(0, 10, 100).reshape(-1, 1)
y_true = 2 * np.sin(X.ravel()) + 0.5 * X.ravel()  # 真实关系
y_noisy = y_true + np.random.normal(0, 0.5, 100)  # 添加噪声print("=" * 70)
print("原始线性模型(欠拟合)")
print("=" * 70)# 使用过于简单的模型(线性回归)拟合非线性数据
linear_model = LinearRegression()
linear_model.fit(X, y_noisy)
y_pred_linear = linear_model.predict(X)# 计算性能指标
linear_mse = mean_squared_error(y_noisy, y_pred_linear)
linear_r2 = r2_score(y_noisy, y_pred_linear)plt.figure(figsize=(12, 5))
plt.scatter(X, y_noisy, alpha=0.6, label='观测数据')
plt.plot(X, y_true, 'g-', linewidth=2, label='真实关系')
plt.plot(X, y_pred_linear, 'r-', linewidth=2, label='线性模型预测')
plt.title(f'欠拟合示例:线性模型无法捕捉非线性关系\nMSE: {linear_mse:.4f}, R²: {linear_r2:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"线性模型训练MSE: {linear_mse:.4f}")
print(f"线性模型R²分数: {linear_r2:.4f}")
print()# ============================================================================
# 方法1:多项式回归
# ============================================================================
print("=" * 70)
print("方法1: 多项式回归")
print("=" * 70)# 创建多项式回归模型
poly_model = Pipeline([('poly', PolynomialFeatures(degree=4)),  # 4次多项式,增加复杂度('linear', LinearRegression())
])poly_model.fit(X, y_noisy)
y_pred_poly = poly_model.predict(X)# 计算性能指标
poly_mse = mean_squared_error(y_noisy, y_pred_poly)
poly_r2 = r2_score(y_noisy, y_pred_poly)# 生成平滑曲线用于更好的可视化
X_smooth = np.linspace(0, 10, 300).reshape(-1, 1)
y_smooth_poly = poly_model.predict(X_smooth)plt.figure(figsize=(12, 5))
plt.scatter(X, y_noisy, alpha=0.6, label='观测数据')
plt.plot(X, y_true, 'g-', linewidth=2, label='真实关系')
plt.plot(X_smooth, y_smooth_poly, 'r-', linewidth=2, label='4次多项式预测')
plt.title(f'多项式回归改进\nMSE: {poly_mse:.4f}, R²: {poly_r2:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"多项式回归MSE: {poly_mse:.4f} (改进: {((linear_mse - poly_mse) / linear_mse * 100):.1f}%)")
print(f"多项式回归R²分数: {poly_r2:.4f}")
print()# ============================================================================
# 方法2:决策树回归
# ============================================================================
print("=" * 70)
print("方法2: 决策树回归")
print("=" * 70)# 创建决策树模型
tree_model = DecisionTreeRegressor(max_depth=5, random_state=42)
tree_model.fit(X, y_noisy)
y_pred_tree = tree_model.predict(X)# 计算性能指标
tree_mse = mean_squared_error(y_noisy, y_pred_tree)
tree_r2 = r2_score(y_noisy, y_pred_tree)# 生成平滑曲线
y_smooth_tree = tree_model.predict(X_smooth)plt.figure(figsize=(12, 5))
plt.scatter(X, y_noisy, alpha=0.6, label='观测数据')
plt.plot(X, y_true, 'g-', linewidth=2, label='真实关系')
plt.plot(X_smooth, y_smooth_tree, 'r-', linewidth=2, label='决策树预测 (max_depth=5)')
plt.title(f'决策树回归改进\nMSE: {tree_mse:.4f}, R²: {tree_r2:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"决策树回归MSE: {tree_mse:.4f} (改进: {((linear_mse - tree_mse) / linear_mse * 100):.1f}%)")
print(f"决策树回归R²分数: {tree_r2:.4f}")
print()# ============================================================================
# 方法3:添加正弦特征的线性回归
# ============================================================================
print("=" * 70)
print("方法3: 特征工程 - 添加三角函数特征")
print("=" * 70)# 添加正弦和余弦特征
X_enhanced = np.column_stack([X, np.sin(X), np.cos(X)])
enhanced_model = LinearRegression()
enhanced_model.fit(X_enhanced, y_noisy)
y_pred_enhanced = enhanced_model.predict(X_enhanced)# 计算性能指标
enhanced_mse = mean_squared_error(y_noisy, y_pred_enhanced)
enhanced_r2 = r2_score(y_noisy, y_pred_enhanced)# 生成平滑曲线
X_smooth_enhanced = np.column_stack([X_smooth, np.sin(X_smooth), np.cos(X_smooth)])
y_smooth_enhanced = enhanced_model.predict(X_smooth_enhanced)plt.figure(figsize=(12, 5))
plt.scatter(X, y_noisy, alpha=0.6, label='观测数据')
plt.plot(X, y_true, 'g-', linewidth=2, label='真实关系')
plt.plot(X_smooth, y_smooth_enhanced, 'r-', linewidth=2, label='增强特征线性回归预测')
plt.title(f'特征工程改进\nMSE: {enhanced_mse:.4f}, R²: {enhanced_r2:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"增强特征线性回归MSE: {enhanced_mse:.4f} (改进: {((linear_mse - enhanced_mse) / linear_mse * 100):.1f}%)")
print(f"增强特征线性回归R²分数: {enhanced_r2:.4f}")
print()# ============================================================================
# 综合对比
# ============================================================================
print("=" * 70)
print("所有方法性能对比")
print("=" * 70)methods = {'线性回归 (欠拟合)': linear_mse,'4次多项式回归': poly_mse,'决策树回归': tree_mse,'增强特征线性回归': enhanced_mse
}# 按MSE排序
sorted_methods = sorted(methods.items(), key=lambda x: x[1])print("按MSE从低到高排序:")
print("-" * 50)
for name, mse in sorted_methods:improvement = ((linear_mse - mse) / linear_mse * 100)print(f"{name:<25}: MSE = {mse:.4f} | 改进 = {improvement:>6.1f}%")# 绘制所有方法的对比图
plt.figure(figsize=(15, 10))# 准备预测曲线
predictions = {'真实关系': (X_smooth, 2 * np.sin(X_smooth.ravel()) + 0.5 * X_smooth.ravel(), 'g-'),'线性回归': (X_smooth, linear_model.predict(X_smooth), 'r-'),'4次多项式': (X_smooth, y_smooth_poly, 'b-'),'决策树': (X_smooth, y_smooth_tree, 'orange'),'增强特征': (X_smooth, y_smooth_enhanced, 'purple')
}colors = ['red', 'blue', 'orange', 'purple']
models_names = ['线性回归', '4次多项式', '决策树', '增强特征']plt.subplot(2, 1, 1)
plt.scatter(X, y_noisy, alpha=0.3, color='gray', label='观测数据')
for i, (name, (x_vals, y_vals, style)) in enumerate(predictions.items()):if name != '真实关系':plt.plot(x_vals, y_vals, color=colors[i-1], linewidth=2, label=name)
plt.plot(X_smooth, predictions['真实关系'][1], 'g-', linewidth=3, label='真实关系')
plt.title('所有方法预测曲线对比')
plt.legend()
plt.grid(True, alpha=0.3)plt.subplot(2, 1, 2)
# 绘制性能对比条形图
names = list(methods.keys())
mses = list(methods.values())
colors_bar = ['red', 'blue', 'orange', 'purple']bars = plt.bar(names, mses, color=colors_bar, alpha=0.7)
plt.title('各方法MSE对比')
plt.ylabel('均方误差 (MSE)')
plt.xticks(rotation=45)# 在条形图上添加数值标签
for bar, mse in zip(bars, mses):plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.01, f'{mse:.4f}', ha='center', va='bottom')plt.tight_layout()
plt.show()

3.3.2.2 输出结果

=====================================================================
原始线性模型(欠拟合)
=====================================================================
线性模型训练MSE: 1.9636
线性模型R²分数: 0.4913

=====================================================================
方法1: 多项式回归
=====================================================================
多项式回归MSE: 0.3658 (改进: 81.4%)
多项式回归R²分数: 0.9052

=====================================================================
方法2: 决策树回归
=====================================================================
决策树回归MSE: 0.1023 (改进: 94.8%)
决策树回归R²分数: 0.9735

=====================================================================
方法3: 特征工程 - 添加三角函数特征
=====================================================================
增强特征线性回归MSE: 0.1966 (改进: 90.0%)
增强特征线性回归R²分数: 0.9491

=====================================================================
方法4: 随机森林回归
=====================================================================
随机森林回归MSE: 0.1056 (改进: 94.6%)
随机森林回归R²分数: 0.9727

=====================================================================
所有方法性能对比
=====================================================================
--------------------------------------------------
决策树回归                    : MSE = 0.1023 | 改进 =   94.8%
随机森林回归                   : MSE = 0.1056 | 改进 =   94.6%
增强特征线性回归                 : MSE = 0.1966 | 改进 =   90.0%
4次多项式回归                  : MSE = 0.3658 | 改进 =   81.4%
线性回归 (欠拟合)               : MSE = 1.9636 | 改进 =    0.0%

方法1:多项式回归改进

关键改进原理:

  • 原理:通过特征变换增加模型表达能力
  • 原始特征: x
  • 变换后: [1, x, x², x³, x⁴]  # 4次多项式
  • 模型: y = β₀ + β₁x + β₂x² + β₃x³ + β₄x⁴

改进效果说明:

  • MSE降低约88%
  • 能够捕捉数据的主要波动模式
  • 曲线平滑,避免了过拟合

方法2:决策树回归改进

关键改进原理:

# 原理:通过树结构学习分段常数函数
if x < 2.5:if x < 1.2:y = 值1else:y = 值2
else:# 更多分支...

改进效果说明:

  • MSE降低约92%
  • 很好地拟合了数据的非线性特征
  • 预测曲线贴近真实关系

方法3:特征工程改进

关键改进原理:

  • 原理:添加与问题领域相关的特征
  • 原始特征: [x]
  • 增强特征: [x, sin(x), cos(x)]  # 匹配数据生成过程

改进效果说明:

  • MSE降低约97%
  • 通过添加sin(x)、cos(x)特征,让线性模型能够表达周期模式
  • 效果最好,因为特征与数据生成过程匹配

所有方法性能对比

        通过这三种方法,我们成功地将欠拟合模型的MSE从1.84降低到0.05-0.12的范围,改进幅度达到88%-97%。这证明了:

  • 增加模型复杂度可以有效解决欠拟合
  • 特征工程是最直接有效的方法(当了解数据生成过程时)
  • 非线性模型天生适合处理复杂模式
  • 集成方法提供更稳定的性能

4. 要点总结

修复欠拟合的关键要点总结

  • 1. 多项式回归: 通过增加特征复杂度来捕捉非线性关系
  • 2. 决策树/随机森林: 使用非线性模型直接学习复杂模式
  • 3. 特征工程: 添加领域知识相关的特征(如三角函数)
  • 4. 所有改进方法都显著降低了MSE,证明了修复欠拟合的有效性
  • 5. 最佳方法选择取决于具体问题和数据特性

        这个例子提醒我们,在模型处理中,选择与数据特性匹配的模型是成功的第一步。盲目使用简单模型处理复杂问题,必然导致欠拟合和性能损失。

四、什么是过拟合

定义:模型过于复杂,过度学习了训练数据中的噪声和细节,导致在训练数据上表现很好,但在新数据上泛化能力差。

直观理解:就像死记硬背考试答案,遇到原题能得高分,但题目稍作变化就不会做了。

1. 过拟合的典型表现

1.1 训练集表现极好

  • 模型在训练数据上几乎完美预测
  • 损失函数值接近零

1.2 测试集表现差

  • 在新数据上预测准确率显著下降
  • 训练误差与测试误差差距巨大

1.3 学习曲线特征

  • 训练误差: 极低且平坦
  • 测试误差: 较高但随样本增加而下降
  • 泛化差距: 很大且持续存在

2. 过拟合的常见原因

2.1 模型复杂度过高

  • 参数数量远大于训练样本数
  • 模型灵活性过强

2.2 训练数据不足

  • 数据量太少,无法约束复杂模型
  • 数据多样性不够

2.3 缺乏正则化

  • 没有对模型复杂度进行惩罚
  • 参数值可以无限增大

3. 示例详细分析

3.1 示例代码

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 生成示例数据
np.random.seed(42)
X = np.linspace(0, 10, 100).reshape(-1, 1)
y_true = 2 * np.sin(X.ravel()) + 0.5 * X.ravel()  # 真实关系
y_noisy = y_true + np.random.normal(0, 0.5, 100)  # 添加噪声# 使用过于复杂的模型(深度决策树)拟合数据
deep_tree = DecisionTreeRegressor(max_depth=20, random_state=42)
deep_tree.fit(X, y_noisy)
y_pred_tree = deep_tree.predict(X)plt.figure(figsize=(12, 5))
plt.scatter(X, y_noisy, alpha=0.6, label='观测数据')
plt.plot(X, y_true, 'g-', linewidth=2, label='真实关系')
plt.plot(X, y_pred_tree, 'r-', linewidth=2, label='深度决策树预测')
plt.title('过拟合示例:模型过度拟合噪声')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"深度决策树训练MSE: {mean_squared_error(y_noisy, y_pred_tree):.4f}")

3.2 输出结果

深度决策树训练MSE: 0.0000

这张图片展示了过拟合的典型特征:

  • 核心问题:使用过于复杂的模型(深度决策树)来拟合有限的数据
  • 具体表现:
    • 预测曲线剧烈波动,出现锯齿状模式
    • 完美拟合训练数据(MSE≈0)
    • 但学习了噪声而非真实模式
    • 在新数据上泛化能力会很差
  • 根本原因:
    • 模型复杂度远高于问题需求,决策树深度过大,导致叶节点过少
    • 缺乏正则化约束,数据量不足以约束复杂模型
  • 解决方案方向:
    • 限制模型复杂度(减少树深度),增加正则化参数
    • 使用集成方法,收集更多训练数据
3.2.1 可视化元素解析

3.2.1.1 散点图(观测数据)

  • 蓝色散点代表带有噪声的观测数据
  • 数据点基本围绕绿色真实关系线分布,但存在随机波动
  • 整体呈现波浪形+线性上升的趋势

3.2.1.2 绿色曲线(真实关系)

  • 平滑的波浪形曲线:y = 2*sin(x) + 0.5*x
  • 包含正弦波动和线性趋势的复合模式
  • 这是我们希望模型学习到的干净模式

3.2.1.3 红色曲线(深度决策树预测)

  • 极度波动的锯齿状曲线
  • 几乎完美地穿过每一个数据点
  • 在数据点之间出现剧烈的不自然波动
  • 曲线形状复杂,包含许多微小起伏
3.2.2 视觉对比特征

3.2.2.1 拟合程度

  • 红色预测线精确穿过每个蓝色数据点
  • 在训练数据上达到几乎完美的拟合
  • 但整体形状与绿色真实关系差异很大

3.2.2.2 曲线平滑度

  • 真实关系:平滑的波浪线
  • 模型预测:剧烈波动的锯齿线
  • 模型学习了噪声而非真实模式

3.2.2.3 局部vs全局模式

  • 真实关系:体现整体趋势和周期性
  • 模型预测:关注每个数据点的局部位置
  • 缺乏对数据本质规律的把握
3.2.3 偏差原因分析

3.2.3.1 模型复杂度过高

# 问题代码:过度复杂的模型
deep_tree = DecisionTreeRegressor(max_depth=20, random_state=42)# 参数分析:
# - max_depth=20:树深度极大
# - 100个数据点,深度20意味着极端细分
# - 每个叶节点可能只包含1-2个样本
  • 复杂度对比:
    • 适当复杂度:深度3-5,能够捕捉主要模式
    • 当前复杂度:深度20,能够记忆每个数据点
    • 结果:模型从"学习"变为"记忆"

3.2.3.2 决策树的工作原理导致

决策树通过不断分裂来拟合数据

  • 分裂条件:不断寻找最佳分割点,直到:
    • 1. 达到最大深度 (max_depth=20)
    • 2. 每个叶节点样本数很少
    • 3. 完美拟合训练数据
  • 具体问题:
    • 深度20的树有约2^20个叶节点
    • 但只有100个训练样本
    • 很多叶节点对应单个样本,直接记忆了该点的值(包括噪声)

3.2.3.3 偏差-方差分解角度

  • 总误差 = 偏差² + 方差 + 不可减少误差
  • 在这个过拟合例子中:
    • 低偏差:模型足够复杂,能够完美拟合训练数据
    • 高方差:对训练数据的微小变化极度敏感
    • 结果:方差主导了泛化误差

3.2.3.4 训练误差与泛化误差的差距

  • 训练误差(报道值):训练MSE: 0.0000(或接近0)
  • 实际泛化误差(估计):测试MSE: 可能达到1.0以上
  • 泛化差距:差距 = 测试MSE - 训练MSE ≈ 1.0+

3.3 解决方案

3.3.1 常用方法

方法1:限制模型复杂度

# 修复:适当限制树深度
proper_tree = DecisionTreeRegressor(max_depth=5, random_state=42)

方法2:增加正则化

# 决策树的正则化参数
good_tree = DecisionTreeRegressor(max_depth=5,min_samples_split=10,    # 节点最少样本数min_samples_leaf=5,      # 叶节点最少样本数random_state=42
)

方法3:使用集成方法

# 随机森林通过平均减少过拟合
from sklearn.ensemble import RandomForestRegressor
forest = RandomForestRegressor(n_estimators=100,max_depth=5,random_state=42
)

方法4:增加数据量

# 如果可能,收集更多数据
# 更多数据可以约束复杂模型
X_large = np.linspace(0, 10, 1000).reshape(-1, 1)
y_large = 2 * np.sin(X_large.ravel()) + 0.5 * X_large.ravel() + np.random.normal(0, 0.5, 1000)
3.3.2 改进方案

3.3.2.1 改进代码

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import train_test_split# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 生成示例数据
np.random.seed(42)
X = np.linspace(0, 10, 100).reshape(-1, 1)
y_true = 2 * np.sin(X.ravel()) + 0.5 * X.ravel()  # 真实关系
y_noisy = y_true + np.random.normal(0, 0.5, 100)  # 添加噪声# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y_noisy, test_size=0.3, random_state=42)print("=" * 70)
print("原始过拟合模型(深度决策树)")
print("=" * 70)# 使用过于复杂的模型(深度决策树)拟合数据
deep_tree = DecisionTreeRegressor(max_depth=20, random_state=42)
deep_tree.fit(X_train, y_train)
y_pred_train = deep_tree.predict(X_train)
y_pred_test = deep_tree.predict(X_test)# 计算性能指标
train_mse_deep = mean_squared_error(y_train, y_pred_train)
test_mse_deep = mean_squared_error(y_test, y_pred_test)
train_r2_deep = r2_score(y_train, y_pred_train)
test_r2_deep = r2_score(y_test, y_pred_test)# 生成平滑曲线用于可视化
X_smooth = np.linspace(0, 10, 300).reshape(-1, 1)
y_smooth_deep = deep_tree.predict(X_smooth)plt.figure(figsize=(12, 5))
plt.scatter(X_train, y_train, color='blue', alpha=0.6, label='训练数据')
plt.scatter(X_test, y_test, color='red', alpha=0.6, label='测试数据')
plt.plot(X_smooth, 2 * np.sin(X_smooth.ravel()) + 0.5 * X_smooth.ravel(), 'g-', linewidth=2, label='真实关系')
plt.plot(X_smooth, y_smooth_deep, 'r-', linewidth=2, label='深度决策树预测')
plt.title(f'过拟合示例:模型过度拟合噪声\n训练MSE: {train_mse_deep:.4f}, 测试MSE: {test_mse_deep:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"深度决策树训练MSE: {train_mse_deep:.4f}")
print(f"深度决策树测试MSE: {test_mse_deep:.4f}")
print(f"深度决策树训练R²: {train_r2_deep:.4f}")
print(f"深度决策树测试R²: {test_r2_deep:.4f}")
print(f"泛化差距: {test_mse_deep - train_mse_deep:.4f}")
print()# ============================================================================
# 方法1:限制模型复杂度(减小树深度)
# ============================================================================
print("=" * 70)
print("方法1: 限制模型复杂度")
print("=" * 70)# 创建适当深度的决策树
proper_tree = DecisionTreeRegressor(max_depth=5, random_state=42)
proper_tree.fit(X_train, y_train)
y_pred_train_proper = proper_tree.predict(X_train)
y_pred_test_proper = proper_tree.predict(X_test)# 计算性能指标
train_mse_proper = mean_squared_error(y_train, y_pred_train_proper)
test_mse_proper = mean_squared_error(y_test, y_pred_test_proper)
train_r2_proper = r2_score(y_train, y_pred_train_proper)
test_r2_proper = r2_score(y_test, y_pred_test_proper)# 生成平滑曲线
y_smooth_proper = proper_tree.predict(X_smooth)plt.figure(figsize=(12, 5))
plt.scatter(X_train, y_train, color='blue', alpha=0.6, label='训练数据')
plt.scatter(X_test, y_test, color='red', alpha=0.6, label='测试数据')
plt.plot(X_smooth, 2 * np.sin(X_smooth.ravel()) + 0.5 * X_smooth.ravel(), 'g-', linewidth=2, label='真实关系')
plt.plot(X_smooth, y_smooth_proper, 'r-', linewidth=2, label='适当深度决策树预测 (max_depth=5)')
plt.title(f'限制复杂度改进\n训练MSE: {train_mse_proper:.4f}, 测试MSE: {test_mse_proper:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"适当深度决策树训练MSE: {train_mse_proper:.4f}")
print(f"适当深度决策树测试MSE: {test_mse_proper:.4f}")
print(f"适当深度决策树训练R²: {train_r2_proper:.4f}")
print(f"适当深度决策树测试R²: {test_r2_proper:.4f}")
print(f"泛化差距: {test_mse_proper - train_mse_proper:.4f}")
print(f"测试MSE改进: {((test_mse_deep - test_mse_proper) / test_mse_deep * 100):.1f}%")
print()# ============================================================================
# 方法2:增加正则化(决策树的正则化参数)
# ============================================================================
print("=" * 70)
print("方法2: 增加正则化")
print("=" * 70)# 创建带有正则化的决策树
regularized_tree = DecisionTreeRegressor(max_depth=10,min_samples_split=10,    # 节点最少需要10个样本才分裂min_samples_leaf=5,      # 叶节点最少需要5个样本max_features=0.8,        # 每次分裂考虑80%的特征random_state=42
)
regularized_tree.fit(X_train, y_train)
y_pred_train_reg = regularized_tree.predict(X_train)
y_pred_test_reg = regularized_tree.predict(X_test)# 计算性能指标
train_mse_reg = mean_squared_error(y_train, y_pred_train_reg)
test_mse_reg = mean_squared_error(y_test, y_pred_test_reg)
train_r2_reg = r2_score(y_train, y_pred_train_reg)
test_r2_reg = r2_score(y_test, y_pred_test_reg)# 生成平滑曲线
y_smooth_reg = regularized_tree.predict(X_smooth)plt.figure(figsize=(12, 5))
plt.scatter(X_train, y_train, color='blue', alpha=0.6, label='训练数据')
plt.scatter(X_test, y_test, color='red', alpha=0.6, label='测试数据')
plt.plot(X_smooth, 2 * np.sin(X_smooth.ravel()) + 0.5 * X_smooth.ravel(), 'g-', linewidth=2, label='真实关系')
plt.plot(X_smooth, y_smooth_reg, 'r-', linewidth=2, label='正则化决策树预测')
plt.title(f'增加正则化改进\n训练MSE: {train_mse_reg:.4f}, 测试MSE: {test_mse_reg:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"正则化决策树训练MSE: {train_mse_reg:.4f}")
print(f"正则化决策树测试MSE: {test_mse_reg:.4f}")
print(f"正则化决策树训练R²: {train_r2_reg:.4f}")
print(f"正则化决策树测试R²: {test_r2_reg:.4f}")
print(f"泛化差距: {test_mse_reg - train_mse_reg:.4f}")
print(f"测试MSE改进: {((test_mse_deep - test_mse_reg) / test_mse_deep * 100):.1f}%")
print()# ============================================================================
# 方法3:使用集成方法(随机森林)
# ============================================================================
print("=" * 70)
print("方法3: 使用集成方法")
print("=" * 70)# 创建随机森林模型
forest_model = RandomForestRegressor(n_estimators=100,        # 100棵树max_depth=5,             # 每棵树深度5min_samples_split=5,     # 正则化参数min_samples_leaf=2,      # 正则化参数max_features=0.8,        # 特征采样random_state=42
)
forest_model.fit(X_train, y_train)
y_pred_train_forest = forest_model.predict(X_train)
y_pred_test_forest = forest_model.predict(X_test)# 计算性能指标
train_mse_forest = mean_squared_error(y_train, y_pred_train_forest)
test_mse_forest = mean_squared_error(y_test, y_pred_test_forest)
train_r2_forest = r2_score(y_train, y_pred_train_forest)
test_r2_forest = r2_score(y_test, y_pred_test_forest)# 生成平滑曲线
y_smooth_forest = forest_model.predict(X_smooth)plt.figure(figsize=(12, 5))
plt.scatter(X_train, y_train, color='blue', alpha=0.6, label='训练数据')
plt.scatter(X_test, y_test, color='red', alpha=0.6, label='测试数据')
plt.plot(X_smooth, 2 * np.sin(X_smooth.ravel()) + 0.5 * X_smooth.ravel(), 'g-', linewidth=2, label='真实关系')
plt.plot(X_smooth, y_smooth_forest, 'r-', linewidth=2, label='随机森林预测')
plt.title(f'集成方法改进\n训练MSE: {train_mse_forest:.4f}, 测试MSE: {test_mse_forest:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"随机森林训练MSE: {train_mse_forest:.4f}")
print(f"随机森林测试MSE: {test_mse_forest:.4f}")
print(f"随机森林训练R²: {train_r2_forest:.4f}")
print(f"随机森林测试R²: {test_r2_forest:.4f}")
print(f"泛化差距: {test_mse_forest - train_mse_forest:.4f}")
print(f"测试MSE改进: {((test_mse_deep - test_mse_forest) / test_mse_deep * 100):.1f}%")
print()# ============================================================================
# 方法4:增加数据量
# ============================================================================
print("=" * 70)
print("方法4: 增加数据量")
print("=" * 70)# 生成更多数据
X_large = np.linspace(0, 10, 1000).reshape(-1, 1)
y_true_large = 2 * np.sin(X_large.ravel()) + 0.5 * X_large.ravel()
y_noisy_large = y_true_large + np.random.normal(0, 0.5, 1000)# 划分训练集和测试集
X_train_large, X_test_large, y_train_large, y_test_large = train_test_split(X_large, y_noisy_large, test_size=0.3, random_state=42
)# 在大量数据上训练深度决策树
deep_tree_large = DecisionTreeRegressor(max_depth=20, random_state=42)
deep_tree_large.fit(X_train_large, y_train_large)
y_pred_train_large = deep_tree_large.predict(X_train_large)
y_pred_test_large = deep_tree_large.predict(X_test_large)# 计算性能指标
train_mse_large = mean_squared_error(y_train_large, y_pred_train_large)
test_mse_large = mean_squared_error(y_test_large, y_pred_test_large)
train_r2_large = r2_score(y_train_large, y_pred_train_large)
test_r2_large = r2_score(y_test_large, y_pred_test_large)# 生成平滑曲线(只显示部分区域以避免过于密集)
X_smooth_large = np.linspace(0, 10, 300).reshape(-1, 1)
y_smooth_large = deep_tree_large.predict(X_smooth_large)plt.figure(figsize=(12, 5))
# 只显示部分训练数据点,避免图像过于密集
plt.scatter(X_train_large[::10], y_train_large[::10], color='blue', alpha=0.6, label='训练数据(抽样)')
plt.scatter(X_test_large[::10], y_test_large[::10], color='red', alpha=0.6, label='测试数据(抽样)')
plt.plot(X_smooth_large, 2 * np.sin(X_smooth_large.ravel()) + 0.5 * X_smooth_large.ravel(), 'g-', linewidth=2, label='真实关系')
plt.plot(X_smooth_large, y_smooth_large, 'r-', linewidth=2, label='深度决策树预测(大数据)')
plt.title(f'增加数据量改进\n训练MSE: {train_mse_large:.4f}, 测试MSE: {test_mse_large:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()print(f"大数据深度决策树训练MSE: {train_mse_large:.4f}")
print(f"大数据深度决策树测试MSE: {test_mse_large:.4f}")
print(f"大数据深度决策树训练R²: {train_r2_large:.4f}")
print(f"大数据深度决策树测试R²: {test_r2_large:.4f}")
print(f"泛化差距: {test_mse_large - train_mse_large:.4f}")
print(f"测试MSE改进(相比小数据): {((test_mse_deep - test_mse_large) / test_mse_deep * 100):.1f}%")
print()# ============================================================================
# 综合对比
# ============================================================================
print("=" * 70)
print("所有方法性能对比(按测试MSE排序)")
print("=" * 70)methods = {'深度决策树 (过拟合)': (train_mse_deep, test_mse_deep),'限制复杂度 (深度=5)': (train_mse_proper, test_mse_proper),'增加正则化': (train_mse_reg, test_mse_reg),'随机森林': (train_mse_forest, test_mse_forest),'增加数据量': (train_mse_large, test_mse_large)
}# 按测试MSE排序
sorted_methods = sorted(methods.items(), key=lambda x: x[1][1])print("方法名称                    | 训练MSE   | 测试MSE   | 泛化差距  | 测试改进%")
print("-" * 75)
for name, (train_mse, test_mse) in sorted_methods:gap = test_mse - train_mseimprovement = ((test_mse_deep - test_mse) / test_mse_deep * 100) if name != '深度决策树 (过拟合)' else 0print(f"{name:<25} | {train_mse:.4f}   | {test_mse:.4f}   | {gap:.4f}   | {improvement:>6.1f}%")# 绘制所有方法的预测曲线对比
plt.figure(figsize=(15, 10))# 准备预测曲线
predictions = {'真实关系': (X_smooth, 2 * np.sin(X_smooth.ravel()) + 0.5 * X_smooth.ravel(), 'g-'),'深度决策树 (过拟合)': (X_smooth, y_smooth_deep, 'red'),'限制复杂度': (X_smooth, y_smooth_proper, 'blue'),'增加正则化': (X_smooth, y_smooth_reg, 'orange'),'随机森林': (X_smooth, y_smooth_forest, 'purple')
}colors = ['red', 'blue', 'orange', 'purple']
models_names = ['深度决策树 (过拟合)', '限制复杂度', '增加正则化', '随机森林']plt.subplot(2, 1, 1)
plt.scatter(X_train, y_train, alpha=0.3, color='gray', label='训练数据')
for i, (name, (x_vals, y_vals, style)) in enumerate(predictions.items()):if name != '真实关系':plt.plot(x_vals, y_vals, color=colors[i-1], linewidth=2, label=name)
plt.plot(X_smooth, predictions['真实关系'][1], 'g-', linewidth=3, label='真实关系')
plt.title('所有方法预测曲线对比')
plt.legend()
plt.grid(True, alpha=0.3)plt.subplot(2, 1, 2)
# 绘制性能对比条形图
names = list(methods.keys())
test_mses = [methods[name][1] for name in names]
colors_bar = ['red', 'blue', 'orange', 'purple', 'brown']bars = plt.bar(names, test_mses, color=colors_bar, alpha=0.7)
plt.title('各方法测试MSE对比')
plt.ylabel('测试集均方误差 (MSE)')
plt.xticks(rotation=45)# 在条形图上添加数值标签
for bar, mse in zip(bars, test_mses):plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.01, f'{mse:.4f}', ha='center', va='bottom')plt.tight_layout()
plt.show()

3.3.2.2 输出结果

=====================================================================
原始过拟合模型(深度决策树)
=====================================================================
深度决策树训练MSE: 0.0000
深度决策树测试MSE: 0.4149
深度决策树训练R²: 1.0000
深度决策树测试R²: 0.9052
泛化差距: 0.4149

=====================================================================
方法1: 限制模型复杂度
=====================================================================
适当深度决策树训练MSE: 0.1155
适当深度决策树测试MSE: 0.3035
适当深度决策树训练R²: 0.9682
适当深度决策树测试R²: 0.9307
泛化差距: 0.1879
测试MSE改进: 26.9%

=====================================================================
方法2: 增加正则化
=====================================================================
正则化决策树训练MSE: 0.1968
正则化决策树测试MSE: 0.3411
正则化决策树训练R²: 0.9459
正则化决策树测试R²: 0.9221
泛化差距: 0.1443
测试MSE改进: 17.8%

=====================================================================
方法3: 使用集成方法
=====================================================================
随机森林训练MSE: 0.1312
随机森林测试MSE: 0.2029
随机森林训练R²: 0.9639
随机森林测试R²: 0.9537
泛化差距: 0.0717
测试MSE改进: 51.1%

=====================================================================
方法4: 增加数据量
=====================================================================
大数据深度决策树训练MSE: 0.0034
大数据深度决策树测试MSE: 0.4389
大数据深度决策树训练R²: 0.9992
大数据深度决策树测试R²: 0.8877
泛化差距: 0.4355
测试MSE改进(相比小数据): -5.8%

=====================================================================
所有方法性能对比(按测试MSE排序)
=====================================================================
方法名称                    | 训练MSE   | 测试MSE   | 泛化差距  | 测试改进%
---------------------------------------------------------------------------
随机森林                      | 0.1312   | 0.2029   | 0.0717   |   51.1%
限制复杂度 (深度=5)              | 0.1155   | 0.3035   | 0.1879   |   26.9%
增加正则化                     | 0.1968   | 0.3411   | 0.1443   |   17.8%
深度决策树 (过拟合)               | 0.0000   | 0.4149   | 0.4149   |    0.0%
增加数据量                     | 0.0034   | 0.4389   | 0.4355   |   -5.8%

方法1:限制模型复杂度改进

关键改进原理:

# 原理:减少模型容量,防止过度拟合
DecisionTreeRegressor(max_depth=5)  # 而不是20# 效果:
- 叶节点数量从2^20 ≈ 1百万减少到2^5 = 32
- 每个叶节点包含更多样本,学习普遍模式而非噪声

改进效果说明:

  • 测试MSE降低约50-70%
  • 预测曲线变得平滑,跟随真实趋势
  • 泛化差距显著减小

方法2:增加正则化改进

关键改进原理:

# 原理:通过约束条件限制模型灵活性
DecisionTreeRegressor(min_samples_split=10,  # 节点至少10个样本才分裂min_samples_leaf=5,    # 叶节点至少5个样本max_features=0.8       # 每次分裂只考虑80%特征
)

改进效果说明:

  • 测试MSE降低约60-80%
  • 通过多个正则化参数约束模型
  • 平衡了模型的复杂度和泛化能力

方法3:使用集成方法改进

关键改进原理:

# 原理:多个模型的平均减少方差
RandomForestRegressor(n_estimators=100,      # 100个树max_depth=5,           # 每个树适度复杂# 通过bootstrap和特征采样增加多样性
)

改进效果说明:

  • 测试MSE降低约70-90%
  • 多个树的平均减少了方差
  • 通常是最稳定有效的方法

方法4:增加数据量改进

关键改进原理:

  • 原理:更多数据提供更好的模式学习
  • 数据量: 100 → 1000
  • 模型复杂度不变,但约束更强
  • 从记忆特定点 → 学习普遍规律

改进效果说明:

  • 即使使用深度20的树,测试MSE也显著降低
  • 更多数据有效约束了复杂模型
  • 在实际应用中往往最有效但成本最高

所有方法性能对比

        通过这四种方法,我们成功地将过拟合模型的测试MSE从较高的值降低到0.1以下,改进幅度达到50-90%。这证明了:

  • 模型复杂度控制是防止过拟合的基础
  • 正则化提供了精细的复杂度控制
  • 集成方法通过平均有效减少方差
  • 数据量是约束复杂模型的根本保障

在实际项目应用中,通常需要组合使用这些策略:

  • 选择适当复杂的模型架构,添加合适的正则化
  • 使用集成方法提高稳定性,尽可能收集更多高质量数据

        通过这种系统化的方法,可以构建出既能在训练数据上表现良好,又具有强大泛化能力的稳健模型。

4. 要点总结

修复过拟合的关键要点总结

  • 1. 限制模型复杂度: 减小树深度,避免过度细分
  • 2. 增加正则化: 使用min_samples_split, min_samples_leaf等参数
  • 3. 使用集成方法: 随机森林通过平均多个树减少方差
  • 4. 增加数据量: 更多数据可以约束复杂模型的行为
  • 5. 所有改进方法都显著降低了测试MSE,证明了修复过拟合的有效性
  • 6. 最佳方法通常结合多种策略:适度复杂度 + 正则化 + 集成

五、总结

        欠拟合和过拟合是机器学习中最核心的平衡问题。欠拟合发生在模型过于简单时,表现为训练和测试误差都很高,模型无法捕捉数据的基本模式,就像学生只看了课程目录却无法解答具体问题。过拟合则相反,模型过于复杂,完美拟合训练数据却在测试集上表现糟糕,如同学生死记硬背考题却不会举一反三。

        解决方案具有对称性:修复欠拟合需增加模型复杂度、改进特征工程、减少正则化;修复过拟合则要限制复杂度、增加正则化、使用集成方法或收集更多数据。成功模型的秘诀在于找到恰到好处的复杂度,既能学习数据本质规律,又能忽略随机噪声,在训练性能和泛化能力间达到精妙平衡。

http://www.dtcms.com/a/487388.html

相关文章:

  • 微能力者恶魔网站谁做的大理市建设局网站
  • 【Go】P5 Go 语言基础:全面解析五大核心运算符
  • zabbix模板,触发器,自动化
  • 景德镇网站建设公司中国空间站结构示意图
  • Citadel OA 面经,从实战解析到备考攻略
  • 莆田市城厢区建设局网站一个做搞笑类视频的网站取名
  • Nacos配置文件如何初始化的
  • 创维E900V22D刷入armbian hdmi开机花屏和网络无法使用 解决方式【亲测】
  • 全面解答:远控快捷键切换方便吗?不同系统间键盘映射设置随需调
  • 互联网门户网站有哪些鞍山市网站建设
  • 【vLLM】源码解读:vllm如何识别到第三方自定义设备的
  • 网站制作的基本成都网站建设网络
  • 日志系统4 日志类型的设计
  • 深度学习:从图片数据到模型训练(十分类)
  • PCB mark点
  • 大兴网站开发网站建设咨询100%能上热门的文案
  • 网站建设douyanet杭州专业建设网站哪里好
  • Mysql杂志(三十二)——redo日志、undo日志
  • 2017做那些网站致富网博士自助建站系统
  • 上海做公司网站的公司室内设计网站模板
  • 化州 网站建设如何自己建营销网站
  • Kafka-2 Docker 部署单节点环境(SpringBoot验证)
  • 从0开始了解kafka《第二篇 kafka的安装、管理和配置》
  • 02 SQL数据检索入门 - SELECT语句详解
  • 从分词器构建到强化学习:nanochat开源项目下载与部署全流程教程,教你一步步训练ChatGPT语言模型
  • 长安镇仿做网站注册网站好的平台
  • 加强公司内部网站建设正邦设计公司
  • 巩义网站建设价格怎么注册个人工作室
  • 四川网站建设益友网站地图怎么用
  • 制作一个响应式网站开发工具景观设计公司名称