Python案例如何用Scikit-learn做F1分数

wen python案例 2

本文目录导读:

Python案例如何用Scikit-learn做F1分数

  1. F1分数基础
  2. 基础案例:二分类问题
  3. 多分类案例:F1的多种计算方式
  4. 实战案例:不平衡分类问题
  5. 交叉验证中优化F1分数
  6. 可视化F1分数与阈值的关系
  7. 实用技巧总结
  8. 关键要点:

我来为你详细讲解如何使用Scikit-learn计算F1分数,包括多个实际案例。

F1分数基础

F1分数是精确率(Precision)和召回率(Recall)的调和平均数:

  • F1 = 2 × (Precision × Recall) / (Precision + Recall)

基础案例:二分类问题

from sklearn.metrics import f1_score, precision_score, recall_score
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_classification
import numpy as np
# 创建示例数据
X, y = make_classification(n_samples=1000, n_features=20, 
                          n_classes=2, random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
# 训练模型
model = LogisticRegression(random_state=42)
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 计算各个指标
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
print(f"精确率 (Precision): {precision:.3f}")
print(f"召回率 (Recall): {recall:.3f}")
print(f"F1分数: {f1:.3f}")

多分类案例:F1的多种计算方式

from sklearn.metrics import classification_report
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
# 加载鸢尾花数据集(3分类)
iris = load_iris()
X, y = iris.data, iris.target
# 划分数据
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)
# 训练随机森林
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
# 预测
y_pred = rf.predict(X_test)
# 1. 微平均 (Micro) - 计算所有样本的总体F1
f1_micro = f1_score(y_test, y_pred, average='micro')
print(f"微平均F1: {f1_micro:.3f}")
# 2. 宏平均 (Macro) - 计算每个类别的F1然后取平均
f1_macro = f1_score(y_test, y_pred, average='macro')
print(f"宏平均F1: {f1_macro:.3f}")
# 3. 加权平均 (Weighted) - 按样本数量加权
f1_weighted = f1_score(y_test, y_pred, average='weighted')
print(f"加权平均F1: {f1_weighted:.3f}")
# 4. 每个类别的F1分数
f1_per_class = f1_score(y_test, y_pred, average=None)
for i, f1_c in enumerate(f1_per_class):
    print(f"类别 {i} 的F1分数: {f1_c:.3f}")
# 5. 完整的分类报告
print("\n完整分类报告:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))

实战案例:不平衡分类问题

from sklearn.metrics import f1_score, make_scorer
from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC
from imblearn.datasets import make_imbalance  # 需要安装imbalanced-learn
# 创建不平衡数据集
X, y = make_classification(n_samples=1000, n_classes=2, 
                          weights=[0.9, 0.1],  # 90%负类,10%正类
                          random_state=42)
# 划分数据
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)
print(f"训练集正类比例: {y_train.mean():.3f}")
print(f"测试集正类比例: {y_test.mean():.3f}")
# 使用不同模型比较F1分数
models = {
    '逻辑回归': LogisticRegression(random_state=42),
    '随机森林': RandomForestClassifier(n_estimators=100, random_state=42),
    'SVM': SVC(random_state=42)
}
for name, model in models.items():
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    f1 = f1_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred)
    recall = recall_score(y_test, y_pred)
    print(f"\n{name}:")
    print(f"  精确率: {precision:.3f}")
    print(f"  召回率: {recall:.3f}")
    print(f"  F1分数: {f1:.3f}")

交叉验证中优化F1分数

from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# 创建pipeline
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('svm', SVC(random_state=42))
])
# 参数网格
param_grid = {
    'svm__C': [0.1, 1, 10, 100],
    'svm__gamma': [0.01, 0.1, 1, 10],
    'svm__kernel': ['rbf', 'linear']
}
# 使用F1分数作为评分标准
f1_scorer = make_scorer(f1_score, average='weighted')
# 网格搜索
grid_search = GridSearchCV(
    pipeline, 
    param_grid, 
    scoring=f1_scorer,
    cv=5,
    n_jobs=-1,
    verbose=1
)
grid_search.fit(X_train, y_train)
print(f"最佳参数: {grid_search.best_params_}")
print(f"最佳交叉验证F1分数: {grid_search.best_score_:.3f}")
# 测试最佳模型
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
final_f1 = f1_score(y_test, y_pred)
print(f"测试集F1分数: {final_f1:.3f}")

可视化F1分数与阈值的关系

import matplotlib.pyplot as plt
from sklearn.metrics import precision_recall_curve
from sklearn.calibration import CalibratedClassifierCV
# 使用概率预测
model = LogisticRegression(random_state=42)
model.fit(X_train, y_train)
# 获取预测概率
y_prob = model.predict_proba(X_test)[:, 1]
# 计算不同阈值下的精确率和召回率
precisions, recalls, thresholds = precision_recall_curve(y_test, y_prob)
# 计算不同阈值下的F1分数
f1_scores = 2 * (precisions[:-1] * recalls[:-1]) / (precisions[:-1] + recalls[:-1] + 1e-10)
# 找到最优阈值
best_threshold_idx = np.argmax(f1_scores)
best_threshold = thresholds[best_threshold_idx]
best_f1 = f1_scores[best_threshold_idx]
print(f"最优阈值: {best_threshold:.3f}")
print(f"最优F1分数: {best_f1:.3f}")
# 可视化
plt.figure(figsize=(10, 6))
plt.plot(thresholds, f1_scores, 'b-', label='F1 Score')
plt.axvline(x=best_threshold, color='r', linestyle='--', 
            label=f'Best Threshold: {best_threshold:.2f}')
plt.xlabel('Threshold')
plt.ylabel('F1 Score')'F1 Score vs Threshold')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

实用技巧总结

def evaluate_model_with_f1(y_true, y_pred, model_name="Model"):
    """
    完整的模型评估函数
    """
    # 计算各类F1分数
    f1_micro = f1_score(y_true, y_pred, average='micro')
    f1_macro = f1_score(y_true, y_pred, average='macro')
    f1_weighted = f1_score(y_true, y_pred, average='weighted')
    # 对于二分类,获取正类的F1
    if len(np.unique(y_true)) == 2:
        f1_binary = f1_score(y_true, y_pred, average='binary')
        print(f"{model_name} - 二分类F1: {f1_binary:.3f}")
    print(f"{model_name} - 微平均F1: {f1_micro:.3f}")
    print(f"{model_name} - 宏平均F1: {f1_macro:.3f}")
    print(f"{model_name} - 加权平均F1: {f1_weighted:.3f}")
    return {
        'micro': f1_micro,
        'macro': f1_macro,
        'weighted': f1_weighted
    }
# 使用示例
y_true = [0, 1, 2, 0, 1, 2]
y_pred = [0, 1, 1, 0, 2, 2]
evaluate_model_with_f1(y_true, y_pred, "示例模型")

关键要点:

  1. 选择合适的average参数

    • 'binary': 二分类默认
    • 'micro': 适合不平衡数据
    • 'macro': 所有类别同等重要
    • 'weighted': 考虑类别分布
  2. 阈值优化:对于概率预测,可以调整阈值优化F1分数

  3. 交叉验证:使用F1作为评分标准进行模型选择

  4. 多分类问题:注意选择合适的average策略

这些案例覆盖了F1分数的常见使用场景,你可以根据具体需求选择合适的方法。

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