本文目录导读:

我来详细介绍如何使用Scikit-learn绘制学习曲线(Learning Curve):
学习曲线的基本概念
学习曲线展示了模型性能随训练样本数量变化的趋势,可以帮助我们:
- 判断模型是否存在过拟合或欠拟合
- 确定是否需要收集更多数据
- 评估模型的学习能力
完整案例代码
1 基础实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import learning_curve
from sklearn.svm import SVC
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
# 加载数据集
digits = load_digits()
X, y = digits.data, digits.target
# 创建学习曲线
def plot_learning_curve(estimator, X, y, cv=5, train_sizes=np.linspace(0.1, 1.0, 10)):
"""
绘制学习曲线
"""
# 计算学习曲线
train_sizes, train_scores, test_scores = learning_curve(
estimator, X, y, cv=cv,
train_sizes=train_sizes,
scoring='accuracy',
n_jobs=-1
)
# 计算平均值和标准差
train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)
# 绘制图形
plt.figure(figsize=(10, 6))
# 绘制训练集曲线
plt.plot(train_sizes, train_mean, 'o-', color='blue', label='Training score')
plt.fill_between(train_sizes, train_mean - train_std,
train_mean + train_std, alpha=0.1, color='blue')
# 绘制验证集曲线
plt.plot(train_sizes, test_mean, 'o-', color='red', label='Cross-validation score')
plt.fill_between(train_sizes, test_mean - test_std,
test_mean + test_std, alpha=0.1, color='red')
plt.title('Learning Curve')
plt.xlabel('Training examples')
plt.ylabel('Score')
plt.legend(loc='best')
plt.grid(True)
return plt
# 使用SVM模型
svm = SVC(kernel='rbf', gamma=0.001)
plot_learning_curve(svm, X, y)
plt.show()
2 比较不同模型的學習曲线
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
# 定义要比较的模型
models = {
'SVM (RBF)': SVC(kernel='rbf', gamma=0.001),
'Logistic Regression': LogisticRegression(max_iter=1000),
'Random Forest': RandomForestClassifier(n_estimators=100)
}
# 绘制多个学习曲线进行比较
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
for idx, (name, model) in enumerate(models.items()):
train_sizes, train_scores, test_scores = learning_curve(
model, X, y, cv=5,
train_sizes=np.linspace(0.1, 1.0, 10),
scoring='accuracy',
n_jobs=-1
)
train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)
ax = axes[idx]
ax.plot(train_sizes, train_mean, 'o-', color='blue', label='Training')
ax.fill_between(train_sizes, train_mean - train_std,
train_mean + train_std, alpha=0.1, color='blue')
ax.plot(train_sizes, test_mean, 'o-', color='red', label='Validation')
ax.fill_between(train_sizes, test_mean - test_std,
test_mean + test_std, alpha=0.1, color='red')
ax.set_title(f'{name}\nLearning Curve')
ax.set_xlabel('Training examples')
ax.set_ylabel('Accuracy')
ax.legend(loc='best')
ax.grid(True)
plt.tight_layout()
plt.show()
3 参数调优与学习曲线
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# 创建包含预处理的pipeline
pipeline = Pipeline([
('scaler', StandardScaler()),
('svm', SVC(kernel='rbf'))
])
# 不同gamma值的学习曲线
gamma_values = [0.001, 0.01, 0.1]
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
for idx, gamma in enumerate(gamma_values):
pipeline.set_params(svm__gamma=gamma)
train_sizes, train_scores, test_scores = learning_curve(
pipeline, X, y, cv=5,
train_sizes=np.linspace(0.1, 1.0, 10),
scoring='accuracy',
n_jobs=-1
)
train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)
ax = axes[idx]
ax.plot(train_sizes, train_mean, 'o-', color='blue', label='Training')
ax.fill_between(train_sizes, train_mean - train_std,
train_mean + train_std, alpha=0.1, color='blue')
ax.plot(train_sizes, test_mean, 'o-', color='red', label='Validation')
ax.fill_between(train_sizes, test_mean - test_std,
test_mean + test_std, alpha=0.1, color='red')
ax.set_title(f'gamma={gamma}')
ax.set_xlabel('Training examples')
ax.set_ylabel('Accuracy')
ax.legend(loc='best')
ax.grid(True)
ax.set_ylim([0, 1.1])
plt.suptitle('SVM with different gamma values', fontsize=14)
plt.tight_layout()
plt.show()
4 实际应用示例 - 房价预测
from sklearn.datasets import fetch_california_housing
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
# 加载房价数据集
housing = fetch_california_housing()
X_housing, y_housing = housing.data, housing.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X_housing, y_housing, test_size=0.2, random_state=42
)
# 标准化数据
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 创建学习曲线
from sklearn.linear_model import Ridge
def plot_learning_curve_with_rmse(estimator, X, y, cv=5):
"""绘制学习曲线(使用RMSE)"""
train_sizes, train_scores, test_scores = learning_curve(
estimator, X, y, cv=cv,
train_sizes=np.linspace(0.1, 1.0, 10),
scoring='neg_mean_squared_error',
n_jobs=-1
)
# 转换为RMSE
train_rmse = np.sqrt(-train_scores)
test_rmse = np.sqrt(-test_scores)
train_mean = np.mean(train_rmse, axis=1)
train_std = np.std(train_rmse, axis=1)
test_mean = np.mean(test_rmse, axis=1)
test_std = np.std(test_rmse, axis=1)
plt.figure(figsize=(10, 6))
plt.plot(train_sizes, train_mean, 'o-', color='blue', label='Training RMSE')
plt.fill_between(train_sizes, train_mean - train_std,
train_mean + train_std, alpha=0.1, color='blue')
plt.plot(train_sizes, test_mean, 'o-', color='red', label='Validation RMSE')
plt.fill_between(train_sizes, test_mean - test_std,
test_mean + test_std, alpha=0.1, color='red')
plt.title('Learning Curve (RMSE) - Ridge Regression')
plt.xlabel('Training examples')
plt.ylabel('RMSE')
plt.legend(loc='best')
plt.grid(True)
return plt
# 使用Ridge回归
ridge = Ridge(alpha=1.0)
plot_learning_curve_with_rmse(ridge, X_train_scaled, y_train)
plt.show()
自定义学习曲线分析器
class LearningCurveAnalyzer:
"""学习曲线分析器"""
def __init__(self, estimator, cv=5, train_sizes=np.linspace(0.1, 1.0, 10)):
self.estimator = estimator
self.cv = cv
self.train_sizes = train_sizes
self.results = {}
def fit(self, X, y, scoring='accuracy'):
"""拟合学习曲线"""
train_sizes, train_scores, test_scores = learning_curve(
self.estimator, X, y, cv=self.cv,
train_sizes=self.train_sizes,
scoring=scoring,
n_jobs=-1
)
self.results = {
'train_sizes': train_sizes,
'train_scores': train_scores,
'test_scores': test_scores,
'train_mean': np.mean(train_scores, axis=1),
'train_std': np.std(train_scores, axis=1),
'test_mean': np.mean(test_scores, axis=1),
'test_std': np.std(test_scores, axis=1)
}
return self
def assess_bias_variance(self):
"""评估偏差和方差"""
final_test_score = self.results['test_mean'][-1]
final_train_score = self.results['train_mean'][-1]
# 计算偏差(1减去最终测试分数)
bias = 1 - final_test_score
# 计算方差(训练分数和测试分数的差距)
variance = final_train_score - final_test_score
return {
'bias': bias,
'variance': variance,
'final_train_score': final_train_score,
'final_test_score': final_test_score
}
def plot(self, title='Learning Curve'):
"""绘制学习曲线"""
plt.figure(figsize=(10, 6))
plt.plot(self.results['train_sizes'], self.results['train_mean'],
'o-', color='blue', label='Training score')
plt.fill_between(self.results['train_sizes'],
self.results['train_mean'] - self.results['train_std'],
self.results['train_mean'] + self.results['train_std'],
alpha=0.1, color='blue')
plt.plot(self.results['train_sizes'], self.results['test_mean'],
'o-', color='red', label='Cross-validation score')
plt.fill_between(self.results['train_sizes'],
self.results['test_mean'] - self.results['test_std'],
self.results['test_mean'] + self.results['test_std'],
alpha=0.1, color='red')
plt.title(title)
plt.xlabel('Training examples')
plt.ylabel('Score')
plt.legend(loc='best')
plt.grid(True)
return plt
# 使用示例
analyzer = LearningCurveAnalyzer(SVC(kernel='rbf', gamma=0.001))
analyzer.fit(X, y)
analyzer.plot(title='SVM Learning Curve')
# 分析偏差和方差
assess = analyzer.assess_bias_variance()
print("偏差-方差分析结果:")
print(f"偏差 (Bias): {assess['bias']:.3f}")
print(f"方差 (Variance): {assess['variance']:.3f}")
print(f"最终训练分数: {assess['final_train_score']:.3f}")
print(f"最终测试分数: {assess['final_test_score']:.3f}")
# 自动判断
if assess['bias'] > 0.3:
print("建议: 模型存在高偏差(欠拟合)")
elif assess['variance'] > 0.2:
print("建议: 模型存在高方差(过拟合)")
else:
print("建议: 模型拟合情况良好")
学习曲线分析技巧
def analyze_learning_curve_patterns(train_scores, test_scores):
"""分析学习曲线模式"""
train_final = train_scores[:, -1].mean()
test_final = test_scores[:, -1].mean()
gap = train_final - test_final
# 判断曲线趋势
test_trend = test_scores.mean(axis=0)
if test_trend[-1] - test_trend[0] > 0.05:
trend = "上升"
elif test_trend[-1] - test_trend[0] < -0.05:
trend = "下降"
else:
trend = "稳定"
print(f"训练集最终分数: {train_final:.3f}")
print(f"验证集最终分数: {test_final:.3f}")
print(f"分数差距: {gap:.3f}")
print(f"验证曲线趋势: {trend}")
if gap > 0.2:
print("⚠️ 模型可能过拟合")
print("建议: 增加正则化或减少模型复杂度")
elif test_final < 0.6:
print("⚠️ 模型可能欠拟合")
print("建议: 增加模型复杂度或特征工程")
else:
print("✅ 模型表现良好")
# 使用示例
from sklearn.model_selection import learning_curve
train_sizes, train_scores, test_scores = learning_curve(
SVC(kernel='rbf', gamma=0.001), X, y, cv=5,
train_sizes=np.linspace(0.1, 1.0, 10), scoring='accuracy'
)
analyze_learning_curve_patterns(train_scores, test_scores)
注意事项
- 训练集大小选择:通常从10%到100%,步长均匀
- 交叉验证折数:一般使用5折或10折
- 评分指标选择:根据问题类型选择(准确率、RMSE、F1分数等)
- 正则化参数:过拟合时增加正则化,欠拟合时减少
- 数据预处理:确保在交叉验证中正确处理数据标准化
通过这些代码示例,你可以灵活地使用Scikit-learn创建和分析学习曲线,从而更好地理解模型的学习行为和性能特征。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播