本文目录导读:

我来详细介绍如何使用Scikit-learn计算R²分数,包括多个实际案例。
基础案例:线性回归的R²分数
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
# 生成示例数据
np.random.seed(42)
X = np.linspace(0, 10, 100).reshape(-1, 1)
y = 2 * X.ravel() + 1 + np.random.normal(0, 2, 100)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 训练线性回归模型
model = LinearRegression()
model.fit(X_train, y_train)
# 预测并计算R²分数
y_pred = model.predict(X_test)
r2 = r2_score(y_test, y_pred)
print(f"R² Score: {r2:.4f}")
print(f"模型解释的方差比例: {r2*100:.2f}%")
# 可视化
plt.figure(figsize=(10, 6))
plt.scatter(X_test, y_test, alpha=0.7, label='实际值')
plt.scatter(X_test, y_pred, alpha=0.7, label='预测值')
plt.plot(X_test, y_pred, 'r-', label='回归线')
plt.xlabel('X')
plt.ylabel('y')f'线性回归结果 (R² = {r2:.4f})')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
多元线性回归的R²分数
from sklearn.datasets import load_diabetes
from sklearn.preprocessing import StandardScaler
# 加载糖尿病数据集(包含多个特征)
data = load_diabetes()
X, y = data.data, data.target
feature_names = data.feature_names
print(f"数据集形状: {X.shape}")
print(f"特征名称: {feature_names}")
# 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
# 训练多元线性回归模型
model = LinearRegression()
model.fit(X_train, y_train)
# 预测并计算R²
y_pred = model.predict(X_test)
r2 = r2_score(y_test, y_pred)
print(f"\n多元线性回归 R² Score: {r2:.4f}")
print(f"调整后的R²: {1 - (1-r2) * (len(y_test)-1) / (len(y_test)-X_test.shape[1]-1):.4f}")
# 分析每个特征的重要性
for i, (name, coef) in enumerate(zip(feature_names, model.coef_)):
print(f"特征 {name}: 系数 = {coef:.4f}")
比较不同模型的R²分数
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.svm import SVR
from sklearn.metrics import mean_squared_error, mean_absolute_error
# 加载波士顿房价数据集
from sklearn.datasets import fetch_california_housing
housing = fetch_california_housing()
X, y = housing.data, housing.target
# 划分数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 定义要比较的模型
models = {
'Linear Regression': LinearRegression(),
'Random Forest': RandomForestRegressor(n_estimators=100, random_state=42),
'Gradient Boosting': GradientBoostingRegressor(n_estimators=100, random_state=42),
'SVR': SVR(kernel='rbf')
}
# 训练和评估每个模型
results = {}
for name, model in models.items():
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
r2 = r2_score(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
results[name] = {'R²': r2, 'MSE': mse, 'MAE': mae}
print(f"{name}:")
print(f" R² = {r2:.4f}")
print(f" MSE = {mse:.4f}")
print(f" MAE = {mae:.4f}\n")
# 可视化比较
plt.figure(figsize=(12, 6))
models_names = list(results.keys())
r2_scores = [results[name]['R²'] for name in models_names]
bars = plt.bar(models_names, r2_scores, color=['blue', 'green', 'orange', 'red'])
plt.xlabel('模型')
plt.ylabel('R² Score')'不同模型的R²分数比较')
plt.xticks(rotation=45)
# 在柱状图上显示数值
for bar, score in zip(bars, r2_scores):
plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.01,
f'{score:.4f}', ha='center', va='bottom')
plt.tight_layout()
plt.show()
交叉验证中的R²分数
from sklearn.model_selection import cross_val_score, KFold
from sklearn.preprocessing import PolynomialFeatures
# 创建非线性数据
np.random.seed(42)
X = np.linspace(-3, 3, 100).reshape(-1, 1)
y = 0.5 * X.ravel() ** 2 + X.ravel() + 2 + np.random.normal(0, 1, 100)
# 多项式特征转换
poly = PolynomialFeatures(degree=2)
X_poly = poly.fit_transform(X)
# 使用交叉验证评估R²分数
kfold = KFold(n_splits=5, shuffle=True, random_state=42)
cv_scores = cross_val_score(LinearRegression(), X_poly, y,
cv=kfold, scoring='r2')
print("交叉验证R²分数:")
print(f"每次CV的R²: {cv_scores}")
print(f"平均R²: {cv_scores.mean():.4f} ± {cv_scores.std():.4f}")
# 可视化交叉验证结果
plt.figure(figsize=(10, 5))
plt.plot(range(1, 6), cv_scores, 'bo-', markersize=8)
plt.axhline(y=cv_scores.mean(), color='r', linestyle='--', label=f'平均R² = {cv_scores.mean():.4f}')
plt.fill_between(range(1, 6), cv_scores - cv_scores.std(), cv_scores + cv_scores.std(),
alpha=0.2, color='blue')
plt.xlabel('Fold')
plt.ylabel('R² Score')'5折交叉验证R²分数')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
实际案例:房价预测的R²分析
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
# 创建一个模拟的房价数据集
np.random.seed(42)
n_samples = 1000
data = pd.DataFrame({
'area': np.random.uniform(50, 200, n_samples),
'bedrooms': np.random.randint(1, 5, n_samples),
'age': np.random.uniform(0, 50, n_samples),
'location': np.random.choice(['center', 'suburb', 'rural'], n_samples),
'price': np.random.uniform(100, 500, n_samples)
})
# 创建特征和目标
X = data.drop('price', axis=1)
y = data['price']
# 划分数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建预处理管道
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), ['area', 'bedrooms', 'age']),
('cat', OneHotEncoder(drop='first'), ['location'])
])
# 创建完整的管道
pipeline = Pipeline([
('preprocessor', preprocessor),
('regressor', LinearRegression())
])
# 训练模型
pipeline.fit(X_train, y_train)
# 预测并计算R²
y_pred = pipeline.predict(X_test)
r2 = r2_score(y_test, y_pred)
print(f"房价预测模型 R² Score: {r2:.4f}")
print(f"模型解释的变异: {r2*100:.2f}%")
# 残差分析
residuals = y_test - y_pred
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.scatter(y_pred, residuals, alpha=0.6)
plt.axhline(y=0, color='r', linestyle='--')
plt.xlabel('预测值')
plt.ylabel('残差')f'残差图 (R² = {r2:.4f})')
plt.grid(True, alpha=0.3)
plt.subplot(1, 2, 2)
plt.scatter(y_test, y_pred, alpha=0.6)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
plt.xlabel('实际值')
plt.ylabel('预测值')'实际值 vs 预测值')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
R²分数的诊断工具
def r2_analysis(y_true, y_pred, model_name="Model"):
"""
综合分析R²分数及相关指标
"""
r2 = r2_score(y_true, y_pred)
n = len(y_true)
p = 1 # 假设有一个特征
# 调整R²
adj_r2 = 1 - (1 - r2) * (n - 1) / (n - p - 1)
# 其他性能指标
mse = mean_squared_error(y_true, y_pred)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_true, y_pred)
# 计算预测准确性
mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100
print(f"{'='*50}")
print(f"{model_name} 性能分析")
print(f"{'='*50}")
print(f"样本数量: {n}")
print(f"特征数量: {p}")
print(f"\nR²分数: {r2:.4f}")
print(f"调整R²: {adj_r2:.4f}")
print(f"MSE: {mse:.4f}")
print(f"RMSE: {rmse:.4f}")
print(f"MAE: {mae:.4f}")
print(f"MAPE: {mape:.2f}%")
print(f"\n解释: R² = {r2:.4f} 意味着模型可以解释 {r2*100:.2f}% 的方差")
return {
'r2': r2,
'adj_r2': adj_r2,
'mse': mse,
'rmse': rmse,
'mae': mae,
'mape': mape
}
# 使用示例
results = r2_analysis(y_test, y_pred, "房价预测模型")
# 诊断信息
if results['r2'] < 0.5:
print("\n⚠️ 警告: R²分数较低,模型性能较差")
elif results['r2'] < 0.8:
print("\n⚠️ 提示: R²分数中等,模型性能可接受")
else:
print("\n✅ R²分数优秀,模型性能良好")
这些案例涵盖了:
- 基础线性回归的R²计算
- 多元线性回归的R²分析
- 不同模型的R²比较
- 交叉验证中的R²评估
- 实际案例应用
- R²诊断工具
记得R²分数的解释:
- R² = 1:完美拟合
- R² > 0.8:优秀拟合
- R² = 0.5-0.8:中等拟合
- R² < 0.5:较差拟合
- R² < 0:模型比简单平均还差