通过遗传算法来优化特征工程
2021-07-01 本文已影响0人
zidea
ai_cover.jpeg
了解数据集
这里数据集是根据breast cancer
检查报告来推测样本是否患有 breast cancer
。569 个样本,每个样本有 30 项指标供参考,我们学习出一个模型根据输入样本给出一个分类,也就是 2 分类问题,也就是样本是否患有 breath cancer。
基本思路
其实这里遗传算法解决问题是模型参数空间内搜索到一组最优参数来作为 LR 模型参数,问题和方法都比较简单,主要是打开大家的思路。数据每个样本有 30 特征,其实这些特征可能有些特征间是相关的,或者有些特征对最终结果并没有多大帮助,甚至有可能对预测结果起到反作用。
初始化种群
- chromesome 可以看成个体,每一个样本都是对样本一个特征选择方案
- population 是由一定数量的个体组成,我们接下来就是通过不断循环、选择、交叉和变异这个过程不断去优化种群,也就是优化方案。
def initilization_of_population(size,n_feat):
population = []
for i in range(size):
chromosome = np.ones(n_feat,dtype=np.bool)
chromosome[:int(0.3*n_feat)]=False
np.random.shuffle(chromosome)
population.append(chromosome)
return population
所谓群体就是解集,种群则由经过基因(gene)编码的一定数目的个体(individual)组成,所谓个体就是这里颜色体(chromosome)。这里 n_feat 需要和数据特征维数保持一致,
有关上面代码出现语法给出点解释
temp = np.ones(10,dtype=bool)
temp[:int(0.3*10)] = False
print(temp)
np.random.shuffle(temp)
print(temp)
[False False False True True True True True True True]
[ True True True True False False True True False True]
评估种群个体适应度
这个函数有点类似机器学习中目标函数,遗传算法中每一条染色体,对应着遗传算法的一个解决方案,用适应性函数(fitness function)来衡量这个解决方案的优劣
def fitness_score(population):
scores = []
for chromosome in population:
#
logmodel.fit(X_train.iloc[:,chromosome],y_train)
predictions = logmodel.predict(X_test.iloc[:,chromosome])
scores.append(accuracy_score(y_test,predictions))
scores, population = np.array(scores), np.array(population)
inds = np.argsort(scores)
return list(scores[inds][::-1]), list(population[inds,:][::-1])
这里个体主要从样本众多特征中选择一些特征进行分析,然后经过特征筛选的样本投入到logistic 分类器进行训练,从而得到一个分类器,用这个分类器进行预测的结果和真实值进行对比来评估每个个体。
选择
选择这里比较简单,通常不会仅选取最优的个体,而是进行随机选取只不过选取不适应环境个体概率会小一些
def selection(pop_after_fit,n_parents):
population_nextgen = []
for i in range(n_parents):
population_nextgen.append(pop_after_fit[i])
return population_nextgen
交叉
在生物学中,就是基因重组,这里就是用个体某一个片段与其他个体同一个位置片段进行对调产生新的个体。
def crossover(pop_after_sel):
population_nextgen=pop_after_sel
for i in range(len(pop_after_sel)):
child=pop_after_sel[i]
child[3:7]=pop_after_sel[(i+1)%len(pop_after_sel)][3:7]
population_nextgen.append(child)
return population_nextgen
变异
这里所谓变异还是比较好理解,也就是将个体(染色体)某一个位置进行取反,也就是如果原来 True 变异后为 False 反之亦然
def mutation(pop_after_cross,mutation_rate):
population_nextgen = []
for i in range(0,len(pop_after_cross)):
chromosome = pop_after_cross[i]
for j in range(len(chromosome)):
if random.random() < mutation_rate:
chromosome[j]= not chromosome[j]
population_nextgen.append(chromosome)
#print(population_nextgen)
return population_nextgen
迭代过程
迭代过程也是进化的过程,种群通过一次次迭代不断进化,优化参数
def generations(size,n_feat,n_parents,mutation_rate,n_gen,X_train,
X_test, y_train, y_test):
best_chromo= []
best_score= []
# 初始化迭代
population_nextgen=initilization_of_population(size,n_feat)
for i in range(n_gen):
# 200
scores, pop_after_fit = fitness_score(population_nextgen)
print(scores[:2])
# 200 -> 100
pop_after_sel = selection(pop_after_fit,n_parents)
# 100 -> 200
pop_after_cross = crossover(pop_after_sel)
# 200 -> 200
population_nextgen = mutation(pop_after_cross,mutation_rate)
best_chromo.append(pop_after_fit[0])
best_score.append(scores[0])
return best_chromo,best_score
运行代码
chromo,score=generations(size=200,n_feat=30,n_parents=100,mutation_rate=0.10,
n_gen=38,X_train=X_train,X_test=X_test,y_train=y_train,y_test=y_test)
logmodel.fit(X_train.iloc[:,chromo[-1]],y_train)
predictions = logmodel.predict(X_test.iloc[:,chromo[-1]])
print("Accuracy score after genetic algorithm is= "+str(accuracy_score(y_test,predictions)))