数值特征标准化StandardScaler和类别不平衡SMOTE

数值特征标准化

标准差是衡量数据集中数值分散程度或变异程度的一个重要指标,标准差越大,表示数据点越分散;标准差越小,表示数据点越集中(方差是标准差的平方)

py 复制代码
import numpy as np

# 两组数据
group1 = [85, 90, 95, 100, 105, 110, 115]
group2 = [70, 80, 90, 100, 110, 120, 130]

print("Group1 均值:", np.mean(group1), "标准差:", np.std(group1, ddof=1))
print("Group2 均值:", np.mean(group2), "标准差:", np.std(group2, ddof=1))

# 输出:
# Group1 均值: 100.0 标准差: 11.83
# Group2 均值: 100.0 标准差: 21.60

标准化值 = (原始值 - 均值) / 标准差

py 复制代码
原始值: [25, 30, 35, 40, 45]
均值 = 35
标准差 ≈ 7.906

标准化计算:
(25-35)/7.906 = -1.2649
(30-35)/7.906 = -0.6325
(35-35)/7.906 = 0
(40-35)/7.906 = 0.6325
(45-35)/7.906 = 1.2649

实际意义:

  • 消除量纲影响:收入(几万元)和身高(厘米)不再因单位不同而影响模型
  • 加速收敛:对于梯度下降算法,标准化后收敛更快
  • 公平比较:所有特征在相同尺度上竞争,避免某些特征因数值大而主导模型
  • 模型稳定性:特别是对距离敏感的模型(如KNN、SVM)很重要
py 复制代码
# 手动计算标准差
data = [25, 30, 35, 40, 45]

# 1. 计算均值
mean = np.mean(data)  # 35.0

# 2. 计算每个数据点与均值的差
deviations = [x - mean for x in data]  # [-10, -5, 0, 5, 10]

# 3. 计算偏差平方
squared_deviations = [d**2 for d in deviations]  # [100, 25, 0, 25, 100]

# 4. 计算方差(样本方差)
variance = sum(squared_deviations) / (len(data) - 1)  # 250 / 4 = 62.5

# 5. 计算标准差
std_dev = np.sqrt(variance)  # 7.906

print("标准差:", std_dev)

类别不平衡

py 复制代码
# 假设二分类问题
原始数据形状: (1000, 20)  # 1000个样本,20个特征
原始目标分布: [800, 200]  # 类别0有800个样本,类别1有200个样本
不平衡比例: 4:1

应用SMOTE后

py 复制代码
过采样后数据形状: (1600, 20)  # 样本数增加
过采样后目标分布: [800, 800]  # 两个类别都变成800个样本
平衡比例: 1:1

# 具体变化:
# 类别0:保持800个原始样本(不变)
# 类别1:200个原始样本 + 600个合成样本 = 800个样本

优缺点

py 复制代码
# 优点
# 1. 有效缓解类别不平衡
# 2. 不会简单复制样本,减少过拟合风险
# 3. 提高少数类的分类性能
# 4. 易于实现和使用

# 缺点
# 1. 可能生成噪声样本
#   如果最近邻属于其他类别,合成的样本可能成为噪声

# 2. 不适用于高维稀疏数据
#   在高维空间中,最近邻可能不可靠

# 3. 计算成本较高
#   需要计算所有少数类样本的最近邻

# 4. 可能过拟合
#   如果少数类样本本身就很少,合成的样本可能只是"插值"结果

# 5. 不适用于多类别问题中的极端不平衡
#   可能需要特殊的变体如SMOTE-NC(针对分类特征)

替代方案

①、其他过采样方法

py 复制代码
from imblearn.over_sampling import(
	ADASYN,    # 自适应合成采样
    BorderlineSMOTE,  # 边界SMOTE
    SVMSMOTE,  # 基于SVM的SMOTE
    KMeansSMOTE  # 基于聚类的SMOTE
)

②、欠采样方法

py 复制代码
from imblearn.under_sampling import (
    RandomUnderSampler,  # 随机欠采样
    NearMiss,           # 近邻欠采样
    TomekLinks,         # 移除Tomek链接
    ClusterCentroids    # 聚类中心
)

③、结合过采样和欠采样

py 复制代码
from imblearn.combine import SMOTETomek, SMOTEENN

适用场景

py 复制代码
# 适用场景:
# 1. 少数类样本数 > 50(太少的话SMOTE效果有限)
# 2. 类别不平衡比例 < 10:1
# 3. 特征空间相对密集(不是稀疏特征)
# 4. 对少数类的精确识别很重要(如医疗诊断、欺诈检测)

# 不适用场景:
# 1. 数据极度不平衡(如1:1000)
# 2. 少数类样本数 < 20
# 3. 多标签分类问题
# 4. 时间序列数据

实践

py 复制代码
# 1. 先划分训练集和测试集
#    在训练集上应用SMOTE,测试集保持原始分布

# 2. 使用交叉验证评估
#    在交叉验证的每个折叠内部应用SMOTE

# 3. 结合多种技术
#    SMOTE + 适当的欠采样

# 4. 监控合成样本的质量
#    可视化检查合成的样本是否合理

# 示例代码:
from sklearn.model_selection import train_test_split
from imblearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier

# 先划分数据
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# 创建包含SMOTE的管道
pipeline = Pipeline([
    ('smote', SMOTE(random_state=42)),
    ('classifier', RandomForestClassifier(random_state=42))
])

# 在训练集上训练(自动应用SMOTE)
pipeline.fit(X_train, y_train)

# 在原始测试集上评估
accuracy = pipeline.score(X_test, y_test)

改进:

py 复制代码
if self.config.get('handle_imbalance', False):
    print("\n4. 处理类别不平衡:")
    
    try:
        from imblearn.over_sampling import SMOTE
        
        # 检查少数类样本数是否足够
        class_counts = np.bincount(y)
        minority_class = np.argmin(class_counts)
        minority_count = class_counts[minority_class]
        
        if minority_count < 10:
            print("    警告:少数类样本过少(<10),跳过SMOTE")
            print("    考虑使用其他方法或收集更多数据")
        else:
            # 多分类时指定采样策略
            if len(class_counts) > 2:
                smote = SMOTE(
                    random_state=self.config.get('random_state', 42),
                    sampling_strategy='not majority'  # 对所有少数类过采样
                )
            else:
                smote = SMOTE(
                    random_state=self.config.get('random_state', 42)
                )
            
            X_processed, y = smote.fit_resample(X_processed, y)
            
            print(f"    过采样后数据形状: {X_processed.shape}")
            print(f"    过采样后目标分布: {np.bincount(y)}")
            print(f"    新增合成样本数: {len(y) - len(y_original)}")
    
    except ImportError:
        print("    错误:未安装imbalanced-learn库")
        print("    安装命令:pip install imbalanced-learn")
    except Exception as e:
        print(f"    SMOTE处理失败: {str(e)}")
相关推荐
人工智能AI技术2 小时前
【Agent从入门到实践】44 监控与日志:添加监控指标、日志记录,方便问题排查
人工智能·python
软件算法开发2 小时前
基于卷尾猴优化的LSTM深度学习网络模型(CSA-LSTM)的一维时间序列预测算法matlab仿真
深度学习·算法·matlab·lstm·一维时间序列预测·卷尾猴优化·csa-lstm
来两个炸鸡腿2 小时前
【Datawhale组队学习202601】Base-NLP task06 大模型训练与量化
人工智能·学习·自然语言处理
bylander2 小时前
【AI学习】TM Forum自智网络L4级标准体系
人工智能·学习·智能体·自动驾驶网络
高洁012 小时前
知识图谱如何在制造业实际落地应用
深度学习·算法·机器学习·数据挖掘·知识图谱
世优科技虚拟人2 小时前
从AI数字人讲解到MR数字人导览,数字人厂商革新文旅新服务
人工智能·大模型·数字人·智能交互
张小凡vip2 小时前
数据挖掘(七) ---Jupyter Notebook快捷方式和魔术命令(特殊命令)
人工智能·jupyter·数据挖掘
Luhui Dev2 小时前
MCP、Skills、Agents SDK 什么区别?AI 能力调度接口的 3 种范式解析
人工智能
才兄说2 小时前
机器人租售出场稳?到点就上台
人工智能·机器人