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

wen python案例 2

我将通过一个综合的Python案例来比较神经网络与传统机器学习方法(如逻辑回归、随机森林)在不同场景下的表现,这个案例将涵盖数据生成、模型训练、评估和可视化。

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

完整案例:信用卡欺诈检测

环境准备和数据生成

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
from sklearn.metrics import confusion_matrix, roc_curve
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import warnings
warnings.filterwarnings('ignore')
# 设置随机种子
np.random.seed(42)
tf.random.set_seed(42)
# 生成模拟的信用卡交易数据
def generate_fraud_data(n_samples=10000, fraud_ratio=0.02):
    """
    生成模拟的信用卡交易数据
    """
    n_fraud = int(n_samples * fraud_ratio)
    n_normal = n_samples - n_fraud
    # 正常交易
    normal_amounts = np.random.normal(50, 30, n_normal)
    normal_amounts = np.abs(normal_amounts) + 1
    # 欺诈交易(金额通常较大)
    fraud_amounts = np.random.normal(500, 200, n_fraud)
    fraud_amounts = np.abs(fraud_amounts)
    # 其他特征
    normal_features = np.random.normal(0, 1, (n_normal, 20))
    fraud_features = np.random.normal(2, 1.5, (n_fraud, 20))
    # 组合数据
    X = np.vstack([normal_features, fraud_features])
    y = np.hstack([np.zeros(n_normal), np.ones(n_fraud)])
    amounts = np.hstack([normal_amounts, fraud_amounts])
    # 添加一些交易时间特征
    transaction_hours = np.random.randint(0, 24, n_samples)
    X = np.hstack([X, amounts.reshape(-1, 1), transaction_hours.reshape(-1, 1)])
    # 打乱数据
    indices = np.random.permutation(n_samples)
    X, y = X[indices], y[indices]
    return X, y
# 生成数据
X, y = generate_fraud_data()
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)
# 标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
print(f"训练集大小: {X_train.shape}")
print(f"测试集大小: {X_test.shape}")
print(f"欺诈交易比例: {y.sum()/len(y):.4f}")

传统方法实现

# 逻辑回归
def train_logistic_regression(X_train, y_train, X_test, y_test):
    """训练逻辑回归模型"""
    lr_model = LogisticRegression(max_iter=1000, random_state=42)
    lr_model.fit(X_train, y_train)
    y_pred = lr_model.predict(X_test)
    y_pred_proba = lr_model.predict_proba(X_test)[:, 1]
    return y_pred, y_pred_proba, lr_model
# 随机森林
def train_random_forest(X_train, y_train, X_test, y_test):
    """训练随机森林模型"""
    rf_model = RandomForestClassifier(
        n_estimators=100, 
        max_depth=10, 
        random_state=42,
        n_jobs=-1
    )
    rf_model.fit(X_train, y_train)
    y_pred = rf_model.predict(X_test)
    y_pred_proba = rf_model.predict_proba(X_test)[:, 1]
    return y_pred, y_pred_proba, rf_model
# 训练传统模型
lr_pred, lr_pred_proba, lr_model = train_logistic_regression(
    X_train_scaled, y_train, X_test_scaled, y_test
)
rf_pred, rf_pred_proba, rf_model = train_random_forest(
    X_train_scaled, y_train, X_test_scaled, y_test
)

神经网络实现

# 构建神经网络模型
def build_neural_network(input_dim):
    """构建神经网络模型"""
    model = keras.Sequential([
        layers.Dense(64, activation='relu', input_shape=(input_dim,)),
        layers.Dropout(0.3),
        layers.Dense(32, activation='relu'),
        layers.Dropout(0.3),
        layers.Dense(16, activation='relu'),
        layers.Dense(1, activation='sigmoid')
    ])
    model.compile(
        optimizer=keras.optimizers.Adam(learning_rate=0.001),
        loss='binary_crossentropy',
        metrics=['accuracy', keras.metrics.AUC(name='auc')]
    )
    return model
# 训练神经网络
def train_neural_network(X_train, y_train, X_test, y_test):
    """训练神经网络模型"""
    input_dim = X_train.shape[1]
    model = build_neural_network(input_dim)
    # 早停和模型检查点
    early_stopping = keras.callbacks.EarlyStopping(
        monitor='val_loss',
        patience=10,
        restore_best_weights=True
    )
    reduce_lr = keras.callbacks.ReduceLROnPlateau(
        monitor='val_loss',
        factor=0.5,
        patience=5,
        min_lr=1e-6
    )
    history = model.fit(
        X_train, y_train,
        validation_data=(X_test, y_test),
        epochs=50,
        batch_size=32,
        callbacks=[early_stopping, reduce_lr],
        verbose=0
    )
    y_pred = (model.predict(X_test) > 0.5).astype(int)
    y_pred_proba = model.predict(X_test).flatten()
    return y_pred, y_pred_proba, model, history
# 训练神经网络
nn_pred, nn_pred_proba, nn_model, nn_history = train_neural_network(
    X_train_scaled, y_train, X_test_scaled, y_test
)

模型评估函数

def evaluate_models(y_true, predictions_dict):
    """评估多个模型"""
    metrics = {}
    for name, (y_pred, y_proba) in predictions_dict.items():
        metrics[name] = {
            'accuracy': accuracy_score(y_true, y_pred),
            'precision': precision_score(y_true, y_pred),
            'recall': recall_score(y_true, y_pred),
            'f1_score': f1_score(y_true, y_pred),
            'auc': roc_auc_score(y_true, y_proba)
        }
    return metrics
# 准备预测结果
predictions = {
    'Logistic Regression': (lr_pred, lr_pred_proba),
    'Random Forest': (rf_pred, rf_pred_proba),
    'Neural Network': (nn_pred, nn_pred_proba)
}
# 评估所有模型
results = evaluate_models(y_test, predictions)
# 显示结果
print("="*60)
print("模型性能对比")
print("="*60)
for model_name, metrics in results.items():
    print(f"\n{model_name}:")
    print(f"  Accuracy:  {metrics['accuracy']:.4f}")
    print(f"  Precision: {metrics['precision']:.4f}")
    print(f"  Recall:    {metrics['recall']:.4f}")
    print(f"  F1-Score:  {metrics['f1_score']:.4f}")
    print(f"  AUC-ROC:   {metrics['auc']:.4f}")

可视化对比

# 创建对比图
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
# 1. 混淆矩阵
for idx, (model_name, (y_pred, _)) in enumerate(predictions.items()):
    ax = axes[0, idx]
    cm = confusion_matrix(y_test, y_pred)
    sns.heatmap(cm, annot=True, fmt='d', ax=ax, cmap='Blues')
    ax.set_title(f'{model_name} - Confusion Matrix')
    ax.set_xlabel('Predicted')
    ax.set_ylabel('Actual')
# 2. ROC曲线对比
ax = axes[1, 0]
colors = ['blue', 'green', 'red']
for idx, (model_name, (_, y_proba)) in enumerate(predictions.items()):
    fpr, tpr, _ = roc_curve(y_test, y_proba)
    ax.plot(fpr, tpr, color=colors[idx], label=f'{model_name} (AUC={results[model_name]["auc"]:.3f})')
ax.plot([0, 1], [0, 1], 'k--')
ax.set_xlabel('False Positive Rate')
ax.set_ylabel('True Positive Rate')
ax.set_title('ROC Curves Comparison')
ax.legend()
ax.grid(True)
# 3. 性能柱状图
ax = axes[1, 1]
model_names = list(results.keys())
scores = {
    'precision': [results[name]['precision'] for name in model_names],
    'recall': [results[name]['recall'] for name in model_names],
    'f1_score': [results[name]['f1_score'] for name in model_names],
    'auc': [results[name]['auc'] for name in model_names]
}
x = np.arange(len(model_names))
width = 0.2
for i, (metric, values) in enumerate(scores.items()):
    ax.bar(x + i*width, values, width, label=metric.capitalize())
ax.set_xlabel('Model')
ax.set_ylabel('Score')
ax.set_title('Model Performance Comparison')
ax.set_xticks(x + width*1.5)
ax.set_xticklabels(model_names, rotation=15)
ax.legend()
ax.grid(True, alpha=0.3)
# 4. 神经网络训练曲线
ax = axes[1, 2]
ax.plot(nn_history.history['loss'], label='Training Loss')
ax.plot(nn_history.history['val_loss'], label='Validation Loss')
ax.set_xlabel('Epoch')
ax.set_ylabel('Loss')
ax.set_title('Neural Network Training')
ax.legend()
ax.grid(True)
# 5. 特征重要性对比
ax = axes[0, 2]
# 使用随机森林的特征重要性
feature_importance = rf_model.feature_importances_
top_features = np.argsort(feature_importance)[-10:]
ax.barh(range(10), feature_importance[top_features])
ax.set_yticks(range(10))
ax.set_yticklabels([f'Feature {i}' for i in top_features])
ax.set_xlabel('Importance')
ax.set_title('Random Forest Feature Importance')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

扩展实验:非线性数据

# 生成更复杂的数据来展示神经网络的优越性
def generate_complex_data(n_samples=5000):
    """
    生成具有复杂非线性关系的数据
    """
    X = np.random.uniform(-3, 3, (n_samples, 20))
    # 创建复杂的非线性关系
    y = np.zeros(n_samples)
    # 非线性决策边界
    complex_relation = (
        np.sin(X[:, 0] * X[:, 1]) +
        np.exp(-X[:, 2]**2) * X[:, 3] +
        np.abs(X[:, 4] - X[:, 5]) +
        (X[:, 6] * X[:, 7] * X[:, 8]) / 10 +
        np.log1p(np.abs(X[:, 9]))
    )
    # 添加噪声
    complex_relation += np.random.normal(0, 0.5, n_samples)
    # 生成标签
    threshold = np.percentile(complex_relation, 80)
    y[complex_relation > threshold] = 1
    # 标准化
    scaler = StandardScaler()
    X = scaler.fit_transform(X)
    return X, y
# 生成并测试复杂数据
X_complex, y_complex = generate_complex_data()
X_train_c, X_test_c, y_train_c, y_test_c = train_test_split(
    X_complex, y_complex, test_size=0.3, random_state=42, stratify=y_complex
)
# 训练模型(比例如前所述,为简化此处只评估部分指标)
print("\n" + "="*60)
print("复杂非线性数据对比")
print("="*60)
# 传统方法
lr_model_c = LogisticRegression(max_iter=1000, random_state=42)
lr_model_c.fit(X_train_c, y_train_c)
lr_pred_c = lr_model_c.predict(X_test_c)
print(f"\n逻辑回归准确率: {accuracy_score(y_test_c, lr_pred_c):.4f}")
rf_model_c = RandomForestClassifier(n_estimators=100, random_state=42)
rf_model_c.fit(X_train_c, y_train_c)
rf_pred_c = rf_model_c.predict(X_test_c)
print(f"随机森林准确率: {accuracy_score(y_test_c, rf_pred_c):.4f}")
# 神经网络
nn_model_c = build_neural_network(X_train_c.shape[1])
early_stopping = keras.callbacks.EarlyStopping(
    monitor='val_loss', patience=15, restore_best_weights=True
)
history_c = nn_model_c.fit(
    X_train_c, y_train_c,
    validation_split=0.2,
    epochs=100,
    batch_size=32,
    callbacks=[early_stopping],
    verbose=0
)
nn_pred_c = (nn_model_c.predict(X_test_c) > 0.5).astype(int)
print(f"神经网络准确率: {accuracy_score(y_test_c, nn_pred_c):.4f}")

详细性能总结

# 创建性能对比表格
print("\n" + "="*80)
print("综合性能对比表")
print("="*80)
metrics_df = pd.DataFrame(results).T
print("\n主要评估指标:")
print(metrics_df.round(4))
# 计算相对优势
print("\n" + "="*80)
print("模型相对优势分析")
print("="*80)
best_model = metrics_df['f1_score'].idxmax()
print(f"F1分数最高的模型: {best_model}")
print(f"F1分数: {metrics_df.loc[best_model, 'f1_score']:.4f}")
# 综合评分
metrics_df['综合评分'] = (
    metrics_df['accuracy'] + 
    metrics_df['precision'] + 
    metrics_df['recall'] + 
    metrics_df['f1_score'] + 
    metrics_df['auc']
) / 5
print("\n综合评分排名:")
ranked_models = metrics_df['综合评分'].sort_values(ascending=False)
for model, score in ranked_models.items():
    print(f"{model}: {score:.4f}")
# 最终结论
print("\n" + "="*80)
print("quot;)
print("="*80)
conclusions = """
1. 在数据量充足且特征复杂的情况下,神经网络通常表现更好
2. 神经网络能够自动学习特征间的非线性关系
3. 但传统方法在某些场景下仍有优势:
   - 计算资源消耗小
   - 可解释性强
   - 小样本数据表现稳定
   - 训练时间短
4. 选择模型时应考虑:
   - 数据规模和复杂性
   - 计算资源限制
   - 模型可解释性需求
   - 实时性要求
"""
print(conclusions)
# 保存最佳模型
import joblib
best_model_name = metrics_df['f1_score'].idxmax()
print(f"最佳模型: {best_model_name}")
if best_model_name == "Neural Network":
    nn_model.save('best_neural_network_model.h5')
    print("神经网络模型已保存")
else:
    joblib.dump(rf_model, 'best_rf_model.pkl')
    print(f"{best_model_name}模型已保存为 best_model.pkl")

这个综合案例展示了:

  1. 神经网络的优势

    • 自动特征学习
    • 处理非线性关系
    • 大数据集表现更好
    • 泛化能力强
  2. 传统方法的优势

    • 训练速度快
    • 可解释性强
    • 小样本表现稳定
    • 资源消耗低
  3. 选择建议

    • 任务复杂性决定
    • 资源限制
    • 业务需求
    • 部署环境

通过这个案例可以看出,神经网络并非在所有情况下都优于传统方法,需要根据具体场景进行选择,在实际应用中,往往需要结合多种方法才能达到最优效果。

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