网站首页 > 技术文章 正文
一、为什么要做特征选择?
如果一个模型在训练数据上的表现比在测试数据上要好很多,这就表示这个模型过拟合了。过拟合是指模型的参数对于训练数据的特定观测值拟合的非常接近,而训练数据的分布于真实数据的分布并不一致,所以模型具有较高的方差。产生过拟合的原因是因为,对于训练数据集上的模型过于复杂,通常我们可以通过以下几种方式来降低过拟合:
1、收集更多的训练数据
2、通过正则化引入罚项
3、选择一个参数相对较少的简单模型
4、降低数据的维度
特征选择除了防止模型过拟合降低模型的泛化误差之外,它还可以减少硬件资源的损耗,降低模型的开发成本,减少训练的时间。下面我们会介绍通过正则化、随机森林算法进行特征选择。
二、使用L1正则化进行特征选择
常用的正则化有L1正则化和L2正则化,L1正则化和L2正则化都是为代价函数添加罚项,不同的是L1正则化增加的罚项是使用权重绝对值的和而L2正则化增加的罚项时权重的平方和。L1正则化生成的是一个稀疏的特征向量,且大多数的权值为0。如果数据集中包含了许多不相关的特征,尤其是不相关的特征数量大于样本的数量时,通过L1正则化处理之后能降低模型的复杂度。
import pandas as pd from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler if __name__ == "__main__": data = pd.read_csv("G:/dataset/wine.csv") #将data分为特征和类标 x,y = data.ix[:,1:],data.ix[:,0] #对特征进行标准化处理 std = StandardScaler() x_std = std.fit_transform(x) #将数据集分为训练集和测试集 train_x,test_x,train_y,test_y = train_test_split(x_std,y,test_size=0.3,random_state=1) #使用L1正则化进行特征选择 L1_model = LogisticRegression(penalty="l1",C=0.1) L1_model.fit(train_x,train_y) #判断模型在训练数据上的准确率 print("training accuracy:",L1_model.score(train_x,train_y)) #判断模型在测试数据上的准确率 print("test accuracy:",L1_model.score(test_x,test_y))
通过模型在训练集和测试集上的准确率可以发现,模型没有产生过拟合,因为训练集和测试集的准确率差不多。
1、查看模型的截距
#查看logistic模型的截距 print(L1_model.intercept_)
2、查看模型的权重系数
#查看模型的权重系数 print(L1_model.coef_)
因为我们使用的是多类别分类的logistic回归,所以它使用一对多(one-vs-Rest,OvR)的方法。第一个权重表示类别1相对于类别2和3的匹配结果,第二个权重表示的是类别2相对于类别1和3的匹配结果,第三个权重表示的是类别3相对于类别1和2的匹配结果。可以发现每一个权重都有13数,其中有很多项的值都为0,这是因为通过L1正则化之后产生的,这13个数表示模型在13个权重上的比重,对应不为0的特征系数,表示是选择的特征。
3、获取L1正则化所选择的列名
#获取特征的列名,因为第一列表示的酒的类别 data_cols_name = data.columns[1:] #获取第一个特征的系数 coef1 = L1_model.coef_[0] #获取一个特征系数的bool类型的数组,不为0为true coef1_bool = coef1 != 0 print(data_cols_name[coef1_bool]) #获取第二个特征的系数 coef2 = L1_model.coef_[1] coef2_bool = coef2 != 0 print(data_cols_name[coef2_bool]) #获取第三个特征的系数 coef3 = L1_model.coef_[2] coef3_bool = coef3 != 0 print(data_cols_name[coef3_bool])
3、参数C对于L1正则化的影响
if __name__ == "__main__": data = pd.read_csv("G:/dataset/wine.csv") # 将data分为特征和类标 x, y = data.ix[:, 1:], data.ix[:, 0] # 对特征进行标准化处理 std = StandardScaler() x_std = std.fit_transform(x) # 将数据集分为训练集和测试集 train_x, test_x, train_y, test_y = train_test_split(x_std, y, test_size=0.3, random_state=1) fig = plt.figure() ax = plt.figure(111) colors = ["blue","green","red","cyan", "magenta","yellow","black","pink", "lightgreen","lightblue","gray","indigo", "indigo","organge"] weights,params = [],[] for c in np.arange(-4,6): model = LogisticRegression(penalty="l1",C=float(10)**c,random_state=0) model.fit(train_x,train_y) weights.append(model.coef_[1]) params.append(float(10)**c) weights = np.array(weights) for column,color in zip(range(weights.shape[1]),colors): plt.plot(params,weights[:,column],label=data.columns[column+1],color=color) plt.axhline(0,color="black",linestyle="--",linewidth=3) plt.xlim([10**(-5),10**5]) plt.ylabel("weight coefficent") plt.xlabel("C") plt.xscale("log") plt.legend(loc="upper left") plt.show()
参数C是正则化参数
的倒数,,当C越小的时候,所有参数的权重都接近0。通过上面的图,我们可以发现特征与参数C的变化关系。
三、使用随机森林判断特征的重要性
使用随机森林来判断特征的重要性的时候,不需要考虑特征是否是线性可分的,也不需要对特征做归一化或者标准化处理。通过随机森林算法之后,可以知道每一个特征的重要性,特征的重要性之和为1。
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier import matplotlib.pyplot as plt import numpy as np if __name__ == "__main__": data = pd.read_csv("G:/dataset/wine.csv") #将data分为特征和类标 x,y = data.ix[:,1:],data.ix[:,0] #将数据集分为训练集和测试集 train_x,test_x,train_y,test_y = train_test_split(x,y,test_size=0.3,random_state=1) #定义一个由10000颗决策树组成的随机森林模型 rf_model = RandomForestClassifier(n_estimators=10000,random_state=0,n_jobs=-1) #训练 rf_model.fit(train_x,train_y) #获取特征的重要性 importances = rf_model.feature_importances_ #对特征的重要性进行排序 indices = np.argsort(importances)[::-1] cols_name = data.columns[1:] for f in range(train_x.shape[1]): print("%2d) %-*s %f" % (f + 1,30,cols_name[f],importances[indices[f]])) plt.title("特征的重要性") plt.bar(range(train_x.shape[1]),importances[indices],color="lightblue",align="center") plt.xticks(range(train_x.shape[1]),cols_name,rotation=90) plt.xlim([-1,train_x.shape[1]]) plt.show()
猜你喜欢
- 2024-10-26 如何用不同长度的观测数据对数据集进行分类
- 2024-10-26 机器学习入门教程-第十一课:特征工程的魔法装备
- 2024-10-26 机器学习:学习机器学习时应避免的 10 个常见错误
- 2024-10-26 如何使用 Python 进行超参调参和调优
- 2024-10-26 特征选择:11 种特征选择策略总结(特征选择的三种方法适用范围)
- 2024-10-26 决策树的高级概述(决策树的基本步骤)
- 2024-10-26 硬核干货!基于机器学习分类算法的钢材缺陷检测分类,一文掌握
- 2024-10-26 从实践的角度理解主成分分析(简述实践主客体之间的相互关系)
- 2024-10-26 python中标准化可反复利用的函数——StandarScaler()
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)