综合python案例,神经网络比传统方法好?

wen python案例 2

我将通过一个完整的Python案例来比较神经网络与传统机器学习方法的性能差异。

综合python案例,神经网络比传统方法好?

综合案例:房价预测模型对比

我们将使用真实的波士顿房价数据集,对比三种方法:

  1. 传统方法:线性回归、随机森林
  2. 神经网络:多层感知机(MLP)

完整代码实现

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.neural_network import MLPRegressor
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
import warnings
warnings.filterwarnings('ignore')
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1. 数据加载和预处理
print("="*60)
print("1. 数据加载和预处理")
print("="*60)
# 使用加利福尼亚房价数据集(比波士顿数据集更新)
data = fetch_california_housing()
X = data.data
y = data.target
feature_names = data.feature_names
print(f"数据集大小: {X.shape}")
print(f"特征名称: {feature_names}")
print(f"目标变量范围: {y.min():.2f} - {y.max():.2f}")
# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
print(f"训练集大小: {X_train.shape}, 测试集大小: {X_test.shape}")
# 数据标准化(对神经网络很重要)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 2. 定义模型
print("\n" + "="*60)
print("2. 模型定义")
print("="*60)
models = {
    '线性回归': LinearRegression(),
    '岭回归': Ridge(alpha=1.0),
    'Lasso': Lasso(alpha=0.1),
    '随机森林': RandomForestRegressor(n_estimators=100, random_state=42),
    '梯度提升': GradientBoostingRegressor(n_estimators=100, random_state=42),
    '神经网络(浅层)': MLPRegressor(
        hidden_layer_sizes=(64, 32),
        activation='relu',
        solver='adam',
        max_iter=1000,
        random_state=42
    ),
    '神经网络(深层)': MLPRegressor(
        hidden_layer_sizes=(128, 64, 32),
        activation='relu',
        solver='adam',
        max_iter=1000,
        random_state=42,
        alpha=0.001  # L2正则化
    )
}
# 3. 模型训练和评估
print("\n" + "="*60)
print("3. 模型训练和评估")
print("="*60)
results = {}
for name, model in models.items():
    # 对神经网络使用标准化数据
    if '神经网络' in name:
        X_train_model = X_train_scaled
        X_test_model = X_test_scaled
    else:
        X_train_model = X_train
        X_test_model = X_test
    # 训练模型
    model.fit(X_train_model, y_train)
    # 预测
    y_pred = model.predict(X_test_model)
    # 评估指标
    mse = mean_squared_error(y_test, y_pred)
    rmse = np.sqrt(mse)
    mae = mean_absolute_error(y_test, y_pred)
    r2 = r2_score(y_test, y_pred)
    results[name] = {
        'MSE': mse,
        'RMSE': rmse,
        'MAE': mae,
        'R2': r2,
        '模型': model,
        '预测值': y_pred
    }
    print(f"\n{name}:")
    print(f"  RMSE: {rmse:.4f}")
    print(f"  MAE:  {mae:.4f}")
    print(f"  R²:   {r2:.4f}")
# 4. 交叉验证
print("\n" + "="*60)
print("4. 5折交叉验证")
print("="*60)
cv_results = {}
for name, model in models.items():
    if '神经网络' in name:
        X_model = X_train_scaled
    else:
        X_model = X_train
    scores = cross_val_score(model, X_model, y_train, cv=5, scoring='r2')
    cv_results[name] = scores
    print(f"{name}: 平均R²={scores.mean():.4f} (±{scores.std():.4f})")
# 5. 可视化比较
print("\n" + "="*60)
print("5. 可视化结果")
print("="*60)
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
# 5.1 预测值 vs 实际值
ax1 = axes[0, 0]
for name, result in results.items():
    ax1.scatter(y_test, result['预测值'], alpha=0.5, s=10, label=name)
ax1.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=2)
ax1.set_xlabel('实际值')
ax1.set_ylabel('预测值')
ax1.set_title('预测值 vs 实际值对比')
ax1.legend(loc='upper left', fontsize=8)
# 5.2 RMSE对比
ax2 = axes[0, 1]
names = list(results.keys())
rmses = [results[name]['RMSE'] for name in names]
bars = ax2.bar(np.arange(len(names)), rmses)
bars[5].set_color('red')
bars[6].set_color('red')
ax2.set_xticks(np.arange(len(names)))
ax2.set_xticklabels(names, rotation=45)
ax2.set_ylabel('RMSE')
ax2.set_title('各模型RMSE对比')
for i, v in enumerate(rmses):
    ax2.text(i, v + 0.01, f'{v:.3f}', ha='center', fontsize=8)
# 5.3 R²对比
ax3 = axes[1, 0]
r2s = [results[name]['R2'] for name in names]
bars = ax3.bar(np.arange(len(names)), r2s)
bars[5].set_color('red')
bars[6].set_color('red')
ax3.set_xticks(np.arange(len(names)))
ax3.set_xticklabels(names, rotation=45)
ax3.set_ylabel('R²')
ax3.set_title('各模型R²对比')
ax3.axhline(y=0, color='black', linestyle='-', alpha=0.3)
for i, v in enumerate(r2s):
    ax3.text(i, v + 0.01, f'{v:.3f}', ha='center', fontsize=8)
# 5.4 交叉验证箱线图
ax4 = axes[1, 1]
cv_names = list(cv_results.keys())
cv_data = [cv_results[name] for name in cv_names]
bp = ax4.boxplot(cv_data, labels=cv_names)
ax4.set_xticklabels(cv_names, rotation=45)
ax4.set_ylabel('R²')
ax4.set_title('5折交叉验证R²分布')
plt.tight_layout()
plt.savefig('model_comparison.png', dpi=100, bbox_inches='tight')
plt.show()
# 6. 特征重要性分析(针对神经网络)
print("\n" + "="*60)
print("6. 神经网络特征重要性分析")
print("="*60)
# 使用排列重要性方法
from sklearn.inspection import permutation_importance
# 获取最优神经网络模型(深层)
best_nn = results['神经网络(深层)']['模型']
# 计算排列重要性
perm_importance = permutation_importance(
    best_nn, X_test_scaled, y_test, n_repeats=10, random_state=42
)
# 排序特征重要性
sorted_idx = perm_importance.importances_mean.argsort()
plt.figure(figsize=(10, 6))
plt.barh(range(len(sorted_idx)), perm_importance.importances_mean[sorted_idx])
plt.yticks(range(len(sorted_idx)), [feature_names[i] for i in sorted_idx])
plt.xlabel('排列重要性')'神经网络特征重要性')
plt.tight_layout()
plt.savefig('feature_importance.png', dpi=100, bbox_inches='tight')
plt.show()
# 7. 模型性能总结
print("\n" + "="*60)
print("7. 模型性能总结")
print("="*60)
# 创建性能对比表
performance_df = pd.DataFrame({
    '模型': names,
    'RMSE': rmses,
    'R²': r2s,
    'MAE': [results[name]['MAE'] for name in names]
})
performance_df['R²排名'] = performance_df['R²'].rank(ascending=False)
performance_df['RMSE排名'] = performance_df['RMSE'].rank(ascending=True)
performance_df['综合排名'] = (performance_df['R²排名'] + performance_df['RMSE排名']).rank()
print("\n模型综合性能排名:")
print(performance_df.sort_values('综合排名').to_string(index=False))
# 8. 不同数据规模下的比较
print("\n" + "="*60)
print("8. 不同数据规模下性能比较")
print("="*60)
sizes = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]
models_to_compare = ['线性回归', '随机森林', '神经网络(深层)']
size_results = {name: [] for name in models_to_compare}
for size in sizes:
    n_samples = int(len(X_train) * size)
    X_sub = X_train[:n_samples]
    y_sub = y_train[:n_samples]
    X_sub_scaled = X_train_scaled[:n_samples]
    for name in models_to_compare:
        if '神经网络' in name:
            model = MLPRegressor(
                hidden_layer_sizes=(128, 64, 32),
                activation='relu',
                solver='adam',
                max_iter=1000,
                random_state=42
            )
            model.fit(X_sub_scaled, y_sub)
            y_pred = model.predict(X_test_scaled)
        elif name == '随机森林':
            model = RandomForestRegressor(n_estimators=100, random_state=42)
            model.fit(X_sub, y_sub)
            y_pred = model.predict(X_test)
        else:
            model = LinearRegression()
            model.fit(X_sub, y_sub)
            y_pred = model.predict(X_test)
        r2 = r2_score(y_test, y_pred)
        size_results[name].append(r2)
# 绘制学习曲线
plt.figure(figsize=(12, 8))
for name in models_to_compare:
    plt.plot(sizes, size_results[name], marker='o', label=name, linewidth=2)
plt.xlabel('训练数据比例')
plt.ylabel('R² Score')'不同模型的学习曲线对比')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('learning_curves.png', dpi=100, bbox_inches='tight')
plt.show()
# 9. 最终结论输出
print("\n" + "="*60)
print("9. 最终结论")
print("="*60)
print("""
【模型性能排名(综合R²和RMSE)】""")
print(performance_df.sort_values('综合排名')[['模型', 'R²', 'RMSE']].to_string(index=False))
print("""
【优势分析】
1. 传统方法(线性回归、随机森林):
   √ 训练速度快,解释性强
   √ 数据量小或线性关系明显时表现良好
   √ 不需要大量调参
2. 神经网络:
   √ 能够捕捉复杂的非线性关系
   √ 数据量充足时表现更好
   √ 特征较多时优势明显
   √ 深层网络可以学习更复杂的模式
【适用场景建议】
- 数据量小(<1000) → 传统方法更可靠
- 线性关系明显 → 简单线性模型即可
- 数据量大且复杂 → 神经网络优势明显
- 需要解释模型 → 随机森林或线性模型
- 追求最高精度 → 深度学习模型
【关键发现】
1. 神经网络在数据充足时通常优于传统方法
2. 数据标准化对神经网络至关重要
3. 深度网络不一定比浅层网络好(需要调参)
4. 集成方法(随机森林、梯度提升)是强基线
5. 模型选择应基于具体问题,没有绝对最好
""")
# 保存结果
performance_df.to_csv('model_performance.csv', index=False)
print("\n结果已保存到当前目录")

运行结果示例

数据集大小: (20640, 8)
特征名称: ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']
线性回归:
  RMSE: 0.7396
  MAE:  0.5332
  R²:   0.5758
随机森林:
  RMSE: 0.5055
  MAE:  0.3289
  R²:   0.8018
神经网络(深层):
  RMSE: 0.5012
  MAE:  0.3224
  R²:   0.8052

可视化图表说明

程序生成的图表包括:

  1. 预测值对比图:各模型的预测效果
  2. 模型性能对比图:RMSE和R²对比
  3. 特征重要性图:神经网络中哪些特征最重要
  4. 学习曲线图:不同数据规模下的性能变化

这个综合案例展示了:

  1. 神经网络并不总是最好的

    • 在小数据集或简单问题上,传统方法可能更好
    • 过拟合风险需要正则化控制
  2. 神经网络的真正优势

    • 大数据集(>10,000样本)表现更佳
    • 能够学习复杂的非线性关系
    • 特征交互自动学习
  3. 实践建议

    • 先尝试简单模型作为基线
    • 数据量足够时再尝试深度学习
    • 必须进行标准化和调参
    • 使用交叉验证避免过度乐观
  4. 性能权衡

    • 神经网络训练时间更长(可能数十倍)
    • 但预测精度有时只提升1-2%
    • 需要考虑计算资源和时间成本

这个案例展示了现代机器学习实践中模型选择的复杂性,强调了"没有免费午餐"定理的重要性。

抱歉,评论功能暂时关闭!