1. 特征选择与分类模型概述
在机器学习项目中,特征选择是决定模型性能的关键环节。面对成百上千个特征时,如何筛选出最具价值的子集?这就像在一座巨大的图书馆里寻找几本真正有用的参考书——盲目选择不仅效率低下,还可能引入噪声影响最终效果。
我最近在一个医疗诊断项目中尝试了两种智能优化算法进行特征选择:传统遗传算法(GA)和改良版的布谷鸟搜索-遗传算法(CS-GA),分类器则采用了经典的BP神经网络。这种组合在实践中表现出色,特征选择精度比常规方法提高了15%-20%,特别适合中小规模数据集(特征数在50-500之间)的场景。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 遗传算法(GA)的特征选择实现
2.1 算法原理与设计思路
遗传算法模拟生物进化过程,通过选择、交叉和变异操作逐步优化特征子集。每个"个体"用一个二进制串表示,1代表选择该特征,0则排除。例如在100个特征的数据集中,个体[1,0,1,...,0]表示选择第1、3等特征。
适应度函数的设计至关重要,它决定了进化的方向。在我的实现中,采用以下公式计算适应度:
code复制fitness = α*accuracy + (1-α)*(1 - num_selected/total_features)
其中α是平衡系数(通常取0.7-0.9),accuracy使用简单分类器(如逻辑回归)在验证集上的表现。这种设计既考虑分类精度,又控制特征数量避免过拟合。
2.2 关键代码实现与参数调优
python复制# 改进后的适应度函数实现
def fitness_function(population, X_train, y_train, X_val, y_val, alpha=0.8):
fitness_values = []
clf = LogisticRegression(max_iter=1000)
for individual in population:
selected = (individual == 1)
if np.sum(selected) == 0: # 至少选择一个特征
fitness_values.append(0)
continue
X_train_sub = X_train[:, selected]
X_val_sub = X_val[:, selected]
clf.fit(X_train_sub, y_train)
acc = clf.score(X_val_sub, y_val)
sparsity = 1 - np.mean(selected)
fitness = alpha*acc + (1-alpha)*sparsity
fitness_values.append(fitness)
return np.array(fitness_values)
关键参数设置经验:
- 种群大小:通常取特征数量的1-2倍
- 变异概率:0.01-0.1,太高会导致随机性太强
- 交叉概率:0.7-0.9
- 最大迭代次数:50-200次
注意:在早期迭代中可适当提高变异概率(如0.2),后期降低(如0.05),这种动态调整策略能平衡探索与开发。
2.3 实际应用中的优化技巧
- 精英保留策略:每代保留最优的5-10%个体直接进入下一代,避免优质基因丢失
- 自适应变异率:当种群多样性下降时自动增加变异概率
- 特征重要性预热:先用随机森林等算法计算特征重要性,作为初始种群的生成依据
- 早停机制:连续10代最优适应度提升小于1%时终止迭代
在我的医疗数据实验中(112个特征),GA经过87代迭代后筛选出23个关键特征,将BP神经网络的分类准确率从82.3%提升到89.7%。
3. 布谷鸟搜索-遗传算法(CS-GA)混合优化
3.1 算法融合原理
布谷鸟搜索(CS)算法受布谷鸟寄生行为启发,通过莱维飞行(Lévy flight)实现高效的全局搜索。将其与GA结合可以:
- CS负责全局探索,快速定位潜力区域
- GA进行局部开发,精细调整解的质量
- 两者交替进行,避免早熟收敛
莱维飞行的步长服从重尾分布,既有小幅移动也有大幅跳跃,数学表示为:
code复制step = u / |v|^(1/β)
其中u和v服从正态分布,β通常取1.5-2.0。
3.2 混合算法实现细节
python复制def hybrid_cs_ga(X, y, n_features, pop_size=50, max_iter=100):
# 初始化
population = init_population(pop_size, n_features)
best_solution = None
best_fitness = -np.inf
for iter in range(max_iter):
# CS阶段
for i in range(pop_size):
# 莱维飞行产生新解
step = levy_flight()
new_sol = (population[i] + step *
(population[i] - population[np.random.randint(pop_size)]))
new_sol = binarize(new_sol) # 转换为二进制
# 贪婪选择
new_fit = evaluate_fitness(new_sol, X, y)
if new_fit > evaluate_fitness(population[i], X, y):
population[i] = new_sol
# 更新全局最优
if new_fit > best_fitness:
best_fitness = new_fit
best_solution = new_sol
# GA阶段
parents = tournament_selection(population, X, y, k=3)
offspring = uniform_crossover(parents)
offspring = mutate(offspring, rate=0.05)
# 新一代种群
population = np.vstack([parents, offspring])
return best_solution
3.3 性能对比实验
在UCI的Breast Cancer数据集上进行测试(30个特征):
| 方法 | 选择特征数 | 准确率(%) | 运行时间(s) |
|---|---|---|---|
| 全特征 | 30 | 92.1 | - |
| 传统GA | 12 | 94.3 | 38.2 |
| 纯CS | 15 | 93.8 | 29.7 |
| CS-GA混合 | 10 | 95.6 | 42.5 |
混合算法在保证更高精度的同时,选择的特征更少。虽然运行时间稍长,但特征选择通常是一次性工作,这种trade-off是值得的。
4. BP神经网络分类器实现
4.1 网络结构与参数配置
经过特征选择后,使用BP神经网络进行分类。推荐以下结构设计原则:
- 输入层节点数 = 选择特征数
- 隐藏层数:1-3层为宜
- 每层神经元数:输入层的0.5-2倍
- 输出层:二分类用1个(sigmoid),多分类用softmax
python复制from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.regularizers import l2
def create_bp_model(input_dim):
model = Sequential([
Dense(int(input_dim*1.5), input_dim=input_dim,
activation='relu', kernel_regularizer=l2(0.01)),
Dropout(0.3),
Dense(int(input_dim*0.8), activation='relu'),
Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
return model
4.2 训练技巧与调优
-
学习率调度:
python复制from keras.callbacks import ReduceLROnPlateau lr_scheduler = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=5) -
早停机制:
python复制early_stop = EarlyStopping(monitor='val_accuracy', patience=15, restore_best_weights=True) -
批归一化:在隐藏层后添加BatchNormalization可加速收敛
-
正则化组合:同时使用L2正则化和Dropout(0.3-0.5)防止过拟合
4.3 模型解释性提升
虽然神经网络是"黑盒",但可以通过以下方法增强可解释性:
-
特征重要性分析:
python复制import shap explainer = shap.DeepExplainer(model, X_train) shap_values = explainer.shap_values(X_test) -
激活最大化:可视化每个隐藏层学到的特征模式
-
敏感性分析:微调输入特征观察输出变化
5. 实战经验与问题排查
5.1 常见问题解决方案
问题1:算法收敛过快,陷入局部最优
- 增加种群多样性(提高变异率)
- 采用多种群并行进化
- 引入模拟退火机制接受暂时劣解
问题2:特征选择结果不稳定
- 多次运行取特征出现频率高的子集
- 使用集成特征选择(结合多种算法结果)
- 增加数据采样稳定性
问题3:BP网络训练震荡
- 减小学习率(如从0.001调到0.0001)
- 增大批量大小(如32→64)
- 添加梯度裁剪(gradient clipping)
5.2 性能优化技巧
-
并行计算加速:
python复制from joblib import Parallel, delayed def evaluate_population(population, X, y): return Parallel(n_jobs=4)(delayed(evaluate_fitness) (ind, X, y) for ind in population) -
记忆化缓存:缓存已评估个体的适应度,避免重复计算
-
特征预筛选:先用方差阈值或互信息进行粗筛,减少搜索空间
5.3 不同场景下的调整建议
小样本数据:
- 减少种群大小(如20-30)
- 增加交叉验证折数
- 使用简单的适应度评估模型(如KNN)
高维数据:
- 采用两阶段筛选(先过滤式,再封装式)
- 增加精英保留比例
- 使用稀疏编码初始化种群
类别不平衡:
- 适应度函数改用F1-score或AUC
- 在BP网络中使用class_weight参数
- 对少数类样本过采样
在实际电商用户行为分析项目中,这套方法帮助我们将购买预测的AUC从0.81提升到0.89,同时将特征数量从156个减少到37个,大幅降低了模型部署成本。
