本文目录导读:

我来详细讲解如何使用Scikit-learn进行特征缩放,包含多个实际案例。
特征缩放的主要方法
1 标准化 (StandardScaler)
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
# 创建示例数据
data = {
'年龄': [25, 30, 35, 40, 45, 50, 55, 60],
'收入': [30000, 45000, 55000, 80000, 120000, 150000, 200000, 300000],
'工作经验': [1, 3, 5, 8, 12, 15, 20, 25]
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)
# StandardScaler: 减去均值,除以标准差
scaler_standard = StandardScaler()
df_standard = scaler_standard.fit_transform(df)
df_standard = pd.DataFrame(df_standard, columns=df.columns)
print("\n标准化后的数据 (均值=0, 标准差=1):")
print(df_standard)
print(f"均值: {df_standard.mean().round(2)}")
print(f"标准差: {df_standard.std().round(2)}")
2 最大最小缩放 (MinMaxScaler)
# MinMaxScaler: 缩放到 [0, 1] 区间
scaler_minmax = MinMaxScaler()
df_minmax = scaler_minmax.fit_transform(df)
df_minmax = pd.DataFrame(df_minmax, columns=df.columns)
print("\nMinMax缩放后的数据 (范围0-1):")
print(df_minmax)
print(f"最小值: {df_minmax.min().round(2)}")
print(f"最大值: {df_minmax.max().round(2)}")
3 鲁棒缩放 (RobustScaler)
# RobustScaler: 对异常值不敏感
scaler_robust = RobustScaler()
df_robust = scaler_robust.fit_transform(df)
df_robust = pd.DataFrame(df_robust, columns=df.columns)
print("\n鲁棒缩放后的数据 (基于中位数和IQR):")
print(df_robust)
实际案例:客户信用评分预测
# 完整的机器学习案例
from sklearn.datasets import make_classification
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report
import warnings
warnings.filterwarnings('ignore')
# 生成模拟数据集
X, y = make_classification(n_samples=1000, n_features=5,
n_informative=3, n_redundant=1,
random_state=42)
# 创建特征名称
feature_names = ['年龄', '收入', '负债率', '工作年限', '信用历史']
X = pd.DataFrame(X, columns=feature_names)
# 添加一些异常值
X.loc[0, '收入'] = 1000000 # 异常高收入
X.loc[1, '负债率'] = -100 # 异常负值
print("数据统计信息:")
print(X.describe())
# 拆分数据集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 比较不同缩放方法的效果
scalers = {
'无缩放': None,
'标准化': StandardScaler(),
'MinMax缩放': MinMaxScaler(),
'鲁棒缩放': RobustScaler()
}
results = {}
for name, scaler in scalers.items():
if scaler:
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
else:
X_train_scaled = X_train.values
X_test_scaled = X_test.values
# 训练SVM模型(对特征尺度敏感)
model = SVC(kernel='rbf', random_state=42)
model.fit(X_train_scaled, y_train)
y_pred = model.predict(X_test_scaled)
accuracy = accuracy_score(y_test, y_pred)
results[name] = accuracy
print(f"\n{name} - SVM准确率: {accuracy:.4f}")
# 显示最佳缩放方法
best_scaler = max(results, key=results.get)
print(f"\n最佳缩放方法: {best_scaler} (准确率: {results[best_scaler]:.4f})")
案例:房价预测中的数据预处理
# 房价预测案例
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt
# 创建房价数据集
np.random.seed(42)
n_samples = 500
data = {
'面积': np.random.normal(100, 30, n_samples), # 平方米
' bedrooms': np.random.randint(1, 6, n_samples), # 卧室数量
'楼层': np.random.randint(1, 20, n_samples), # 楼层
'房龄': np.random.randint(0, 50, n_samples), # 房龄
'距离地铁站': np.random.exponential(1, n_samples), # 公里
'价格': np.random.normal(500000, 200000, n_samples) # 价格
}
df_housing = pd.DataFrame(data)
# 添加一些异常值
df_housing.loc[0, '面积'] = 1000 # 异常大
df_housing.loc[1, '价格'] = 50000000 # 异常高
print("房价数据统计:")
print(df_housing.describe())
# 特征和目标变量
X = df_housing[['面积', ' bedrooms', '楼层', '房龄', '距离地铁站']]
y = df_housing['价格']
# 拆分数据
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 可视化缩放效果
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
scalers_viz = {
'原始数据': None,
'标准化': StandardScaler(),
'MinMax缩放': MinMaxScaler(),
'鲁棒缩放': RobustScaler()
}
for idx, (name, scaler) in enumerate(scalers_viz.items()):
row, col = idx // 2, idx % 2
if scaler:
X_scaled = scaler.fit_transform(X_train)
else:
X_scaled = X_train.values
# 绘制前两个特征的散点图
axes[row, col].scatter(X_scaled[:, 0], X_scaled[:, 4],
c=y_train, alpha=0.6, cmap='viridis')
axes[row, col].set_title(f'{name}')
axes[row, col].set_xlabel('面积')
axes[row, col].set_ylabel('距离地铁站')
plt.tight_layout()
plt.show()
# 使用随机森林(对尺度不敏感)作为对照
rf_model = RandomForestRegressor(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
y_pred_rf = rf_model.predict(X_test)
print(f"\n随机森林 (无缩放) - MSE: {mean_squared_error(y_test, y_pred_rf):.2f}")
print(f"R2得分: {r2_score(y_test, y_pred_rf):.4f}")
实际案例:特征缩放流水线
from sklearn.pipeline import Pipeline
from sklearn.decomposition import PCA
from sklearn.neighbors import KNeighborsClassifier
# 创建完整的预处理流水线
def create_ml_pipeline(scaler_type='standard'):
"""
创建机器学习流水线
参数:
scaler_type: 'standard', 'minmax', 'robust'
"""
# 选择缩放器
scalers = {
'standard': StandardScaler(),
'minmax': MinMaxScaler(),
'robust': RobustScaler()
}
scaler = scalers.get(scaler_type, StandardScaler())
# 创建流水线
pipeline = Pipeline([
('scaler', scaler),
('pca', PCA(n_components=0.95)), # 保留95%方差
('classifier', KNeighborsClassifier(n_neighbors=5))
])
return pipeline
# 使用流水线
pipeline = create_ml_pipeline('standard')
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print("流水线模型性能:")
print(f"准确率: {accuracy_score(y_test, y_pred):.4f}")
保存和加载缩放器
import joblib
# 训练并保存缩放器
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_train)
# 保存缩放器
joblib.dump(scaler, 'standard_scaler.pkl')
# 在实际应用中使用
def predict_new_data(new_data):
"""
对新数据进行预测
参数:
new_data: 新的输入数据 (DataFrame或数组)
"""
# 加载缩放器
loaded_scaler = joblib.load('standard_scaler.pkl')
# 缩放新数据
new_data_scaled = loaded_scaler.transform(new_data)
# 进行预测(这里假设有训练好的模型)
predictions = model.predict(new_data_scaled)
return predictions
选择缩放方法的建议
def recommend_scaler(data, has_outliers=True):
"""
根据数据特征推荐缩放方法
参数:
data: 输入数据
has_outliers: 是否包含异常值
"""
print("特征缩放建议:")
print("=" * 50)
# 检查数据特征
skewness = data.skew()
has_negative = (data.min() < 0).any()
print(f"数据偏度: {skewness.round(2)}")
print(f"包含负值: {has_negative}")
print(f"包含异常值: {has_outliers}")
# 推荐建议
if has_outliers:
print("\n推荐: RobustScaler - 对异常值不敏感")
elif has_negative:
print("\n推荐: StandardScaler - 适合包含负值的数据")
else:
print("\n推荐: MinMaxScaler - 简单且有效")
if (skewness.abs() > 1).any():
print("注意: 数据偏度较大,考虑使用对数变换")
print("建议: 结合PowerTransformer或QuantileTransformer")
# 使用建议函数
recommend_scaler(X)
关键要点
- StandardScaler: 适用于大部分情况,假设数据服从正态分布
- MinMaxScaler: 适用于边界明确的场景,如神经网络
- RobustScaler: 数据包含异常值时的首选
- 始终:先fit训练集,再transform测试集
- 注意:缩放器需要保存以便对新数据使用相同的缩放参数
这些案例涵盖了特征缩放的常见应用场景,你可以根据实际需求选择合适的方法。