过拟合的定义
过拟合指机器学习模型在训练数据上表现优异,但在未见过的测试数据上性能显著下降的现象。其本质是模型过度学习了训练数据中的噪声或特定模式,导致泛化能力不足。
过拟合的常见原因
- 模型复杂度过高:参数过多,远超数据真实规律的复杂度。
- 训练数据不足:数据量小或多样性不足,模型难以捕捉普遍规律。
- 噪声干扰:数据包含大量无关特征或错误标签。
- 训练时间过长:某些迭代式算法(如深度学习)过度优化训练集损失。
解决过拟合的方法
增加训练数据
- 收集更多数据或通过数据增强(如图像旋转、裁剪)扩充数据集。
- 使用生成对抗网络(GAN)或合成数据技术生成合理样本。
降低模型复杂度
- 减少神经网络层数或节点数。
- 选择更简单的模型(如线性回归替代多项式回归)。
- 决策树模型中限制树的最大深度或叶子节点数。
正则化技术
- L1/L2正则化:在损失函数中添加权重惩罚项。
- L1正则化公式:
( J(\theta) = \text{MSE}(\theta) + \lambda \sum_{i=1}^n |\theta_i| ) - L2正则化公式:
( J(\theta) = \text{MSE}(\theta) + \lambda \sum_{i=1}^n \theta_i^2 )
- L1正则化公式:
- Dropout:在神经网络训练中随机丢弃部分神经元,防止对特定特征的依赖。
交叉验证
- 使用k折交叉验证评估模型泛化能力,选择最优超参数。
早停法(Early Stopping)
- 监控验证集性能,当损失不再下降时提前终止训练。
集成方法
- Bagging(如随机森林):通过多个模型的平均降低方差。
- Boosting(如XGBoost):逐步修正错误,同时控制复杂度。
过拟合的检测方法
- 训练集与测试集性能差距大:训练集准确率高,测试集显著下降。
- 学习曲线分析:观察训练集和验证集损失随数据量或迭代次数的变化趋势。
- 混淆矩阵:检查模型是否在特定类别上过度自信。
实际应用建议
- 优先尝试数据扩充和简化模型。
- 结合业务场景选择正则化方法(L1适合特征选择,L2适合平滑权重)。
- 深度学习推荐使用Dropout+早停法+数据增强组合策略。
下采样方法
下采样(Downsampling)是指降低数据采样率或减少数据量的过程,常用于信号处理、图像处理和机器学习等领域。以下是几种常见的下采样方法:
信号处理中的下采样
在信号处理中,下采样通常指降低信号的采样率。假设原始信号的采样率为 ( f_s ),下采样因子为 ( D ),则新的采样率为 ( f_s / D )。
数学表达式为: [ y[n] = x[nD] ] 其中 ( x[n] ) 是原始信号,( y[n] ) 是下采样后的信号。
为避免混叠效应,下采样前通常需要先进行抗混叠滤波(低通滤波),截止频率为 ( f_s / (2D) )。
图像处理中的下采样
在图像处理中,下采样通常指降低图像的分辨率。常见方法包括:
- 最近邻插值:直接取原始图像中最近的像素值作为下采样后的像素值。
- 双线性插值:通过周围四个像素的加权平均计算下采样后的像素值。
- 双三次插值:利用周围16个像素的加权平均计算,效果更平滑。
下采样后的图像尺寸计算公式为: [ \text{新宽度} = \lfloor \text{原始宽度} / k \rfloor ] [ \text{新高度} = \lfloor \text{原始高度} / k \rfloor ] 其中 ( k ) 为下采样因子。
机器学习中的下采样
在机器学习中,下采样常用于处理类别不平衡问题。例如,在二分类问题中,若负样本远多于正样本,可以通过随机丢弃部分负样本实现类别平衡。
实现代码示例(Python):
from sklearn.utils import resample
# 假设 X 是特征矩阵,y 是标签
X_majority = X[y == 0]
X_minority = X[y == 1]
# 下采样多数类
X_majority_downsampled = resample(X_majority, n_samples=len(X_minority), random_state=42)
# 合并下采样后的数据
X_downsampled = np.vstack([X_majority_downsampled, X_minority])
y_downsampled = np.hstack([np.zeros(len(X_minority)), np.ones(len(X_minority))])
其他领域的下采样
- 时间序列下采样:通过均值、最大值或最小值等聚合函数降低时间序列的分辨率。
- 点云下采样:在3D点云处理中,使用体素网格或随机采样减少点云数量。
下采样的选择需根据具体应用场景和数据特性决定,避免信息丢失或引入噪声。
案例:
import pandas as pd
from numpy.ma.core import count
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
#导入文件
data=pd.read_csv(r'creditcard.csv')
#标准化数据,压缩Amount数据
scaler = StandardScaler()
data["Amount"]=scaler.fit_transform(data[['Amount']])
import pandas as pd
#分割数据,取30%为训练集
train_data,test_data=train_test_split(data,test_size=0.3,random_state=1000)
#取class为1和0的数据
pe=train_data[train_data['Class'] == 1]
ne=train_data[train_data['Class'] == 0]
#将1和0的数据数取一样的
d1 = ne.sample(len(pe))
#拼接数据
train_data = pd.concat([d1,pe])
train_X=train_data.drop(["Time","Class"],axis=1)
train_y=train_data["Class"]
test_X=test_data.drop(["Time","Class"],axis=1)
test_y=test_data["Class"]
#交叉验证
from sklearn.model_selection import cross_val_score
import numpy as np
scores=[]
pe=[0.01,0.1,1,10,100]
for p in pe:
lr=LogisticRegression(C=p,penalty ='l2',random_state=42,max_iter=1000)
score=cross_val_score(lr,train_X,train_y,cv=8,scoring='recall')
scores_mean=sum(score)/len(score)
scores.append(scores_mean)
print(scores_mean)
best_c=pe[np.argmax(scores)]
print('最优系数:',best_c)
model=LogisticRegression(C=best_c,penalty ='l2',random_state=42,max_iter=1000)
model.fit(train_X,train_y)
print(model.score(test_X,test_y))
from sklearn import metrics
print(metrics.classification_report(test_y,model.predict(test_X)))
过采样的基本概念
过采样是一种处理数据不平衡问题的技术,通过增加少数类样本的数量来平衡数据集。其核心目标是避免模型因多数类样本主导而忽略少数类的学习。
常见的过采样方法
随机过采样(Random Oversampling)
通过简单复制少数类样本实现平衡。缺点是可能导致过拟合,尤其是样本数量较少时。
SMOTE(Synthetic Minority Oversampling Technique)
基于插值生成合成样本:
- 对少数类样本随机选择最近邻样本。
- 在特征空间中线性插值生成新样本。
公式表示:
x_new = x_i + λ × (x_j − x_i)
其中 ( x_i ) 为原始样本,( x_j ) 为最近邻样本,λ ∈ [0,1] 为随机数。
ADASYN(Adaptive Synthetic Sampling)
改进的SMOTE,根据样本密度自适应生成更多合成样本。对分类边界附近的少数类样本赋予更高权重,生成更多数据。
Borderline-SMOTE
针对边界样本的过采样,仅对靠近分类边界的少数类样本生成合成数据,提升模型对边界区域的识别能力。
过采样的优缺点
优点
- 直接缓解数据不平衡问题。
- 与欠采样结合可进一步提升效果。
缺点
- 可能引入噪声或过拟合(如随机过采样)。
- 计算成本较高(如SMOTE需计算最近邻)。
实践建议
- 优先尝试SMOTE及其变体(如Borderline-SMOTE)。
- 结合交叉验证评估过采样效果。
- 对于高维数据,建议先降维再应用过采样。
代码示例(使用imbalanced-learn库):
from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)
案例:
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn import metrics
from imblearn.over_sampling import SMOTE
# 读取数据
data = pd.read_csv(r'creditcard.csv')
print(f"欺诈样本数量: {len(data[data['Class'] == 1])}")
print(f"正常样本数量: {len(data[data['Class'] == 0])}")
# 数据预处理 - 标准化Amount特征
scaler = StandardScaler()
data["Amount"] = scaler.fit_transform(data[['Amount']])
# 划分特征和目标变量
X = data.drop(["Time", "Class"], axis=1)
y = data["Class"]
# 划分训练集和测试集
train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.2, random_state=42)
# 使用SMOTE处理类别不平衡
oversampler = SMOTE(random_state=0)
train_X_resampled, train_y_resampled = oversampler.fit_resample(train_X, train_y)
print(f"重采样后训练集中欺诈样本数量: {sum(train_y_resampled)}")
print(f"重采样后训练集中正常样本数量: {len(train_y_resampled) - sum(train_y_resampled)}")
# 交叉验证选择最优参数C
scores = []
C_values = [0.01, 0.1, 1, 10, 100]
for C in C_values:
lr = LogisticRegression(C=C, penalty='l2', random_state=42, max_iter=1000)
cv_scores = cross_val_score(lr, train_X_resampled, train_y_resampled, cv=8, scoring='recall')
scores_mean = cv_scores.mean()
scores.append(scores_mean)
print(f"C={C} 交叉验证召回率: {scores_mean:.4f}")
# 选择最优参数
best_C = C_values[np.argmax(scores)]
print(f'最优正则化系数: {best_C}')
# 训练最优模型
model = LogisticRegression(C=best_C, penalty='l2', random_state=42, max_iter=1000)
model.fit(train_X_resampled, train_y_resampled)
# 预测概率(而非直接预测类别)
y_proba = model.predict_proba(test_X)[:, 1] # 获取正类(欺诈)的概率
# 设置不同阈值并评估
thresholds = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
for threshold in thresholds:
print(f"\n阈值: {threshold}")
y_pred = (y_proba >= threshold).astype(int) # 根据阈值判断类别
print(f"准确率: {metrics.accuracy_score(test_y, y_pred):.4f}")
print(f"召回率: {metrics.recall_score(test_y, y_pred):.4f}")
print(f"精确率: {metrics.precision_score(test_y, y_pred):.4f}")
print(f"F1分数: {metrics.f1_score(test_y, y_pred):.4f}")
print("分类报告:")
print(metrics.classification_report(test_y, y_pred))
# 可以选择一个最佳阈值进行最终预测
best_threshold = 0.3 # 示例:选择0.3作为阈值
final_pred = (y_proba >= best_threshold).astype(int)
print(f"\n使用最佳阈值 {best_threshold} 的最终分类报告:")
print(metrics.classification_report(test_y, final_pred))

被折叠的 条评论
为什么被折叠?



