




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章数据预处理与特征工程5.1数据预处理5.2特征提取5.3特征选择5.4降维5.5小结5.1数据预处理标准化归一化离散化对类别特征编码缺失值计算多项式特征标准化
对于一组数据来说,如果数据中存在少量的异常数据点,那么对于最后的结果就可能会产生一些偏差,为了尽可能减少这种偏差,我们就可以对数据进行标准化处理。
常用的标准化方法是:z-score,z-score利用的是scikit-learn中的StandardScaler,将离散的数据转化为标准差为1,均差为0范围内的数据。
具体的实现公式如下:
其中ave代表特征的平均值(average),n代表样本总量。
这样做的目的就是将离散化的数据缩放,但由于该变化是线性的,数据转换之后不会影响到原来数据的顺序,还可以使优化结果。代码实现:
先从sklearn库中的preprocessing分支中导入StandardScaler,实例化StandardScaler。fromsklearn.preprocessingimportStandardScalers=StandardScaler()test_data=[[780,40],[700,51],[740,45],[810,66]]standard_data=s.fit_transform(test_data)print(standard_data)输出结果归一化
在我们研究一些问题时,往往会遇到特征同等重要,但是彼此之间的单位不同的情况,如果不对其进行处理,就可能会对最终的结果造成相当大的影响。
例如,已知身高和体重,要你找出与“某人”体型相同的人。在这个问题中身高和体重的单位是不相同的,而且彼此之间也不能相互转换,这时如果你直接使用未经处理的数据集来预测和某人体型相同的人可能就会出现很大的偏差。
所以我们就要对数据进行归一化处理,将数据缩放到同一个区间,使得每个特征对于问题的影响是相同的。
常用的归一化的方法是:(极差变换法),即通过线性变换将数据映射到[0,1]之间,但数据的排列顺序由于是线性变化,所以并没有改变。数学公式:其中,Xi为特征值,min为最小值,max为最大值。
min-max方法利用的是scikit-learn库中的MinMaxScaler,具体的实现方法是:
先从sklearn库中的preprocessing分支中导入MinMaxScaler,实例化MinMaxScalerfromsklearn.preprocessingimportMinMaxScalers=MinMaxScaler()test_data=[[110,23],[434,10],[121,55],[999,90]]Minmax_data=s.fit_transform(test_data)print(Minmax_data)输出结果
从上述结果中我们可以看到所有数据都转化为[0,1]之间的数,使得数据更为方便的应用于你所构建你的模型。离散化 离散化,就是把无限空间中的有限个体映射到有限空间中去,通俗的说,离散化就是再不改变数据相对大小的条件下,对数据进行相应的缩小,以此来提高算法的时空效率,避免一些冗陈而又复杂的计算。
当数据只与它们之间的相对大小有关,而与具体是多少无关时,就可以应用离散化。离散化(又叫特征分箱),就是将根据数据输入的范围,将数据划分成一个一个的区间(又叫箱子),由于我们只考虑数据之间的相对大小,所以我们可以赋给每个区间一个能表示区间大小关系的一个简单的数值,这样就可以将数据简化,从而简化计算,提高模型的拟合效果。
要实现特征分箱,我们利用的是numpy库中的linspace函数和digitize函数,linspace函数的作用就是对于给定的[x,y]区间和所需要的划分段数k,linspace可以将这个区间划分成k-1个子区间,而digitize函数的作用就是可以计算出数据所在的区间的位置。importnumpyasnpx=[21,10,2,44,66,99]bins=np.linspace(0,100,11)print("bins:",bins)输出结果
为什么np.linspace(0,100,11)中要填“11”而不是“10”?
linspace(x,y,z)中z的作用是创建z个元素,而不是z个区间。接下来我们用numpy中的另一个函数digitize来计算x中每个元素所对应的区间的位置。
特别的对于一些定性数据,我们我们无法划定其区间长,而且机器学习是无法直接使用定性特征的,需要将定性特征转化成定量特征,这样才能用于机器学习。例如学习成绩,如果我们只关心学生的学习成绩是“及格”还是“不及格”,那么学习成绩就是一个定性特征。我们不妨用“0”代替“不及格”,用“1”代替“及格”,那么我们的所有数据就可以用“0”和“1”来代替。这样做就不必存储一些无关特征,比如学生的成绩(低于60全为0,高于60全为1),极大地节省了空间并且简化了计算量,而这样的操作又叫二值化。
二值化利用的是sklearn库中preporccessing分支的Binarizer函数,Binarizer函数的作用是对于一个给定的阈值(threshold),Binarizer将大于这个阈值的数值变成1,小于这个数值的数值变成0,从而将整体数据二值化。fromsklearn.preprocessingimportBinarizerx=[[1,1],[21,12],[11,1],[102,211],[43,95]]x_trans=Binarizer(threshold=35).fit_transform(x)print("x_trans:\n",x_trans)对类别特征编码
对于“性别”、“城市”和“日期”等定性特征,我们所构建的模型是无法对其直接使用的。但就“城市”这个特征而言,可能有“北京”、“上海”、“杭州”和“济南”等多个变量,但是对于某一个确定的人来说,就只有一个确定的量。而且我们在对数据进行处理的时候也不可能直接将数据存成“北京”、“上海”、“济南”等。那在机器学习中这种定性特征该如何参与运算呢?
对于“性别”、“城市”和“日期”等定性变量,我们可以对它进行分类,就比如说“性别”。那么对于一个人我们就可以将性别分成两个特征,分别为“男性”和“女性”,如果这个人是男人,那么就可以将“男性”记为“1”,“女性”记为“0”,来表示这个人是男性。所以,对于某一个定性特征,我们可以将其分为N类,每一类作为一个新的特征,新特征的取值是“0”和“1”,这样做就可以将机器无法直接处理的定性特征转化成能直接处理的定量特征。One-hot编码
到目前为止,我们表示分类特征最常用的方法是one-hot编码,又称虚拟变量。其中心思想是,对于一个定性特征(分类特征),我们可以将其转化成一个或多个新的特征来替代原来的特征,新特征的取值为“0”和“1”。对于单独的数据而言,由原来的的分类特征转化成的N个新特征的取值只有1个为“1”,其余的N-1个特征的取值都为“0”。
One-hot编码的实现方式是利用sklearn库中preporcessing分支中的OneHotEncoder,OneHotEncoder的作用就是创建N-1个新特征,新特征的取值为0,而原先已有的特征取值为1。One-hot编码实现方式:fromsklearn.preprocessingimportOneHotEncoderimportnumpyasnpdata=np.array([["China"],["USA"],["Japan"],["England"],["Australia"]])data_OHE=OneHotEncoder(sparse=False).fit_transform(data)print(data_OHE)
One-hot编码的编码方式是按字典序进行编码的,所以我们可以看到输出的第一行(China)所对应的第一列不为1。由于Australia比China小,所以China排在第二位,即第一行对应的第二列为1。LabelEncoder编码
one-hot编码只能适用于我们不关心特征的取值的情况,如果定性特征的取值不能忽略,那么我们就不能使用one-hot编码将特征简单地赋值成0和1,这样做是没有任何意义的。就例如“尺码”这个定性特征,“尺码”特征可以取“L”、“XL”、“XXL”等,这是如果我们用one-hot编码将其转化成0和1,那么我们得出的结果将没有任何意义。所以这是我们就可以使用另一种编码方式,LabelEncoder。
LabelEncoder的实现是利用了sklearn库中preporcessing分支中的LabelEncoder。LabelEncoder的作用是对于不连续的文本或数字进行编号,假如一个定性特征可以分成N个新特征,而且新特征的取值是有要求的,那么这是我们就可以使用LabelEncoder对N个新特征分别赋值为[0,N-1],从而不影响新特征之间的相互关系。代码实现:importnumpyasnpfromsklearn.preprocessingimportLabelEncoderLE=LabelEncoder()data=np.array([["M"],["L"],["XL"],["XXL"],["XXXL"]])data_LE=LE.fit_transform(data)print(data_LE)缺失值计算
在现实生活中,十全十美的事很少,不尽如人意的的事却有很多,当然我们收集的数据也是如此。十分完美的数据是通常情况下都是很少见的,我们收集的数据中总是一些数据是缺失的,而且我们往往无法自己补全。原因有很多,可能是人为因素,比如由于疏忽导致输入时数据缺失或被别的数据覆盖、误删达到,又比如历史的故意隐瞒或者调查时人们拒绝回答。还可能是客观原因如硬盘损坏、机器故障造成的数据缺失。所以,我们应该对我们所收集的数据的缺失值进行处理,使得数据更适合我们所构建的模型。目前常见的几种缺失值处理方法:1.直接使用含有缺失值的数据2.直接删除含有缺失值的数据3.计算并补全缺失值方法一:直接使用含有缺失值的数据,如果缺失的数据是一些无关紧要的特征,那么我们就忽略这些特征,直接使用缺失数据。但如果缺失的是一些非常重要的数据,那么我们直接使用的话,就可能影响结果的准确性。方法二:直接删除含有缺失值的数据,这种方法一般使用的不多,原因是在未进行机器学习之前,你也不知道哪种特征对于我们所构建的模型的重要性,如果贸然将数据直接删除的话,可能就会对我们构建的模型产生一些不可估计的影响。缺失值删除代码实现:importpandasaspdimportnumpyasnpdata=pd.DataFrame({"name":['A','B','C'],"sex":[np.nan,"Male","Female"],"born":[pd.NaT,pd.Timestamp("2000-1-1"),pd.NaT]})DataFrame.dropna(axis=0,how='any',thresh=None,subset=None,inplace=False)
我们可以通过修改括号中的参数来实现任意的删除功能axis的取值为“0”(index)、“1”(columns),axis=0时表示对行的删除,axis=1时表示对列的删除,一般dropna默认axis=0。how的取值为‘any’或‘all’,how=‘any’时表示删除只要有任何NA存在的行或列,how=‘all’时表示删除该行或该列全为NA的行或列。thresh参数的作用是保留数据,防止一些数据被错误的删除,其取值为int整数数据类型。thresh与axis结合使用便可实现对任意N行或M列的保留,而且thresh保留的是含有缺失值最少的一行或一列。subset参数的作用是删除含有缺失值的指定列,其取值为数据中所有特征。方法三:计算并补全缺失值。缺失值补全是现实生活中实际工程使用的最广泛的方法,其中心思想是:计算出最可能的值,来代替缺失值。这种方法多用于缺失值较少或者缺失值比较重要的情况。我们以一下数据作为样例data=pd.DataFrame({"name":["A","B","C","D"],"sex":[np.nan,np.nan,"Male","Female"],"height":[155,pd.NaT,167,190],"weight":[pd.NaT,55,60,77]})DataFrame.fillna(value=None,method=None,axis=None,inplace=False,limit=None,downcast=None)fillna的作用是在将缺失值替换为我们所指定的值。value参数的作用是fillna用来替换缺失值的值。value的取值为任意实数,当然我们也可以用字典来填充缺失值。method参数的作用是指定填充缺失值的方法,其取值为“ffill/pad”或“bfill/backfill”。method=“ffill/pad”表示用该列数据的前一个非缺失值来填充缺失值,method=“bfill/backfill”表示用该列数据的后一个非缺失值来填充缺失值。inplace参数,inplace的作用是是否创建副本,其取值为True或False,inplace=True表示不创建副本,直接在原数据上进行修改,inplace=False表示创建副本,在副本上进行修改而不改变原数据的值。limit参数,limit参数的作用是限制填充缺失值的个数,limit长与method和value一起用。当然,我们使用sklearn.preprocessing中的Imputer也可以做到以上的效果,接下来我们介绍几种常见的缺失值补全的方法。均值插补
对于可以度量的量,如果数据中存在缺失值,那么我们通常会用该列数据的平均值来代替缺失值,例如身高、体重、学生成绩等。
但是,如果对于不可以度量的数据,例如“性别”、“国籍”、“政治面貌”等,我们无法将数据的平均值或中位数来替代缺失值。这时,比较好的方法是用数据的众数(即出现次数最多的数)来替代缺失值。多重插补对于数据中的缺失值来说,我们可以做这样一个假设:认为所有待补全的缺失值的值是随机的,且待补全的缺失值的值全部来源于我们已知的值。具体实现:1.机器首先通过已有的值预测(或估计)出待补全的缺失值的值。2.给预测出的数据加上多组干扰值,形成N多种不同的组合。3.根据某种选择方式,选取出最合适的值。多项式特征
对于一个数据集而言通常会有多个特征,但是有些时候我们直接使用这些特征对问题进行分析,得出的结果可能就会差强人意。但是如果我们对于这些特征进行了一个处理(平方、开方、加减乘除等)就会构成一些新的特征,生成的这些新的特征即为这些特征的变量的有机组合。如果我们使用数据集中的特征所构建的模型对于问题的求解不够理想,那么我们将一些特征进行一些结合或对其本身进行一些操作使其构成一些新的特征,再将其用于问题的求解,那么我们就可能会得到我们想要的结果。
多项式特征在前面多项式回归时有涉及,多项式回归就是采用了多项式特征的自动添加新特征的方式,接下来对多项式特征进行详细讲解。
我们使用Python以这个函数构造一组数据,并且用多项式来拟合。importnumpyasnpimportmathimportrandomimportmatplotlib.pyplotaspltx=np.random.uniform(0.01,2.5,100)x=x.reshape(-1,1)y=[i**2-3*i+random.uniform(-0.25,0.25)+math.log(i)foriinx]plt.scatter(x,y)plt.show()这里我们可以看出y-x的关系并不是线性的关系
这时候直接用线性模型进行拟合
几乎大部分的点都不在直线上。所以,这时候我们就可以尝试一下添加一个新特征——x²。
那么如何添加新特征呢?
两种方法:1.手动添加new_x=np.hstack([x,x**2]).reshape(-1,1)2.sklearn自动添加fromsklearn.preprocessingimportPolynomialFeaturespf=PolynomialFeatures(degree=2)new_x=pf.fit_transform(x)
这里,PolynomialFeatures是sklearn.preprocessing中的一个方法,其作用是对数据进行预处理,给数据添加新的特征。其中,degree的作用是控制多项式中最高项的维度,例如degree=3,最高项就是x^3。下面我们来看看新添加了x²这一项后的拟合情况fromsklearn.preprocessingimportPolynomialFeaturespf=PolynomialFeatures(degree=2)new_x=pf.fit_transform(x)log.fit(new_x,y)fit_x=np.linspace(start=0.01,stop=2.5,num=100).reshape(-1,1)plt.scatter(x,y,c='g')plt.plot(fit_x,log.predict(pf.fit_transform(fit_x)),'b-')plt.show()
根据前后两次的图像对比,我们可以看到新添加x²的曲线的拟合效果要好于原始数据曲线的效果当degree=12时,图像已经大致和原函数吻合我们可以查看各项的系数和截距。print("coef_:\n{}".format(log.coef_))print("intercept_:\n{}".format(ercept_))我们用R²决定系数检验拟合的效果fromsklearn.metricsimportr2_scoreprint("score:{}".format(r2_score(y,log.predict(pf.fit_transform(x)))))输出结果:R3-score:0.9461278631787718
degree=12,R3-score≈0.94,相对来说这是一个非常不错的成功率了。所以如果你搜集到的数据特征比较少或者去除冗沉特征后特征数量稀少,再或者拟合效果差强人意,你都可以尝试这用多项式特征来扩充你的特征数量。5.2特征提取
特征提取主要是指字典特征提取、文本特征提取和图像特征提取这三个方面。万物皆可为特征。因此,特征的种类千变万化,特征的数量无穷无尽。针对不同种类的特征采取不同的特征提取方法,往往会对你所研究的问题有所益处。字典特征提取
如果你要对你所需要的数据进行特诊提取,但这些数据恰巧都单独成一个字典,例如学生的成绩、城市的一些数据、书籍的版号等等。如果对这些数据进行直接提取,那么过程就会非常的复杂。特别是当数据量非常大的时候,稍有不慎,可能你所提取出的数据就会出错,导致你所研究的问题的结果错误。
所以,这时候我们就可以借助sklearn库中feature_extraction分支中的DictVectorizer。DictVectorizer(字典矢量器)的作用是对特征进行特征值化,即保留连续特征并对离散特征为其创建虚拟变量。例如以下数据(随机数据):{'neme':'gxml','sex':'Female','score':61}{'neme':'ecnk','sex':'Male','score':50}{'neme':'selq','sex':'Male','score':83}{'neme':'pjow','sex':'Male','score':67}{'neme':'ziqi','sex':'Male','score':19}{'neme':'tqub','sex':'Female','score':64}{'neme':'vcms','sex':'Female','score':64}{'neme':'oigc','sex':'Male','score':71}{'neme':'jlim','sex':'Male','score':62}{'neme':'itau','sex':'Male','score':68}
我们可以看到,对于每一个学生的信息,都是存放在一个单独的字典里。因此,我们首先将所有学生的信息都存放在一个列表当中(即转化成字典列表),然后就可以用DictVectorizer方法对其进行特征提取。
由于DictVectorizer默认返回的是一个sparse矩阵,为了方便直观,我们将sparse的值设置为False。fromsklearn.feature_extractionimportDictVectorizerdv=DictVectorizer(sparse=False)new=dv.fit_transform(dit)print(new)print(dv.get_feature_names())其中dit中存放的是由每个学生信息所构成的字典列表。结果如下:在这里我们可以看到,输出的每一行即为一个学生的信息,例如第一行的学生的姓名是“gxml”,性别是“Female”,成绩是“61”分。文本特征提取
在特征提取中,文本特征提取所占有的地位非常重要。文字是人类文化传承的重要载体,所以如果想要在机器学习中有所建树,那么文本特征提取便是你必不可少的技能之一。
文本是由单词、短语和句子组成的一种自由化的组合,其形式多种多样,但总是可以将其转换为结构化数据属性的存在。同过文本特征提取,我们可以分析两个不同文本间的相似度,还可以提取整片文章的关键词和主题,更可以对文章进行感情色彩分析等等。
在进行文本特征提取时,我们首先要对文本进行预处理,使得我们所提取的特征能更好的被我们使用。下面一段短文,我们对其进行文本特征提取Spidersarenotinsects,asmanypeoplethink,norevennearlyrelatedtothem.Onecantellthedifferencealmostataglance,foraspideralwayshaseightlegsandinsectnevermorethansix.Howmanyspidersareengagedinthisworknoourbehalf?OneauthorityonspidersmadeacensusofthespidersingrassfieldinthesouthofEngland,andheestimatedthatthereweremorethan2250000inoneacre;thatissomethinglike6000000spidersofdifferentkindsonafootballpitch.首先,我们要将这一段话读入,并利用正则表达式将其分割importres=input()ss=re.sub(r'\,|\.','',s)s=re.sub(r'[0-9]','',s)s=re.split(r'\s+',s)
将这一整段文字分割成单词后,我们发现其中有一些词语是我们所不需要的,例如“is”、“of”等,所以我们需对其做一些预处理,使得文本仅保留我们所需要的单词。step_words=['is','am','are','of','on','the','more','than','nor','and','this','these','that','those','not','as','can','at','a','an','for','to','nearly','almost','even','many','always','has','have','in','no','our','was','were']s=[''ifiinstep_wordselseiforiins]while''ins:s.remove('')结果:['spiders','insects','people','think','related','them','one','tell','difference','glance','spider','eight','legs','insect','never','six','how','spiders','engaged','work','behalf?','one','authority','spiders','made','census','spiders','grass','field','south','england','he','estimated','there','one','acre;','something','like','spiders','different','kinds','football','pitch','']
可能读者看到这种处理方式会觉得非常麻烦,别担心,这只是一种简单的处理方法,如果真的要对文章进行处理的话,还要用到Python中的nltk库。Nltk库是专门用来处理自然语言的工具,如果有需要的读者可以翻到本书的第八章来进行学习。词袋模型
我们可以将文本装进词袋模型中去处理文本。词袋模型可以形象化的理解成把句子或文件用一个袋子来装着这些词,这种表现方式不考虑文法以及词的顺序,接下来我们将介绍三种词袋模型。
CountVectorizer是sklearn库中feature_extraction分支中的一个常见的特征数值计数类,其作用是将文本转化成词频矩阵。N-Grams袋模型
N-Grams袋模型是词袋模型的一个扩展,被用来统计按顺序出现的单词或短语的出现频率。N-Grams的初始化是一个m*n的矩阵,m为文档的数量,n是短语的长度。例如,我们想调查一个有三个单词组成的短语在文章中的出现频率,我们就可以通过设置CountVectorizer中ngram_range=(3,3)来实现。但是要注意,N-Grams统计的是文章中去除关键词后连续的词。TF-IDF模型
TF-IDF模型,被用来解决文档中某些出现频率较少的特征被出现频率较大的特征掩盖的问题,是信息检索和自然语言处理领域中一个不可或缺的模型。举个例子,给你大量谈论A喜欢吃什么的文章,让你从中提取A这个人喜欢吃的都有什么。假设A喜欢吃烤鸭、白菜、油条、豆浆、西红柿和馒头,且A顿顿都吃馒头。所以在一篇文章中,通常馒头这个词出现的频率是高于其他几个特征出现的频率。那么,在文章足够多的情况下,可能馒头这个词的出现频率会高达99%,从而认为馒头是A喜欢吃的,而烤鸭、白菜等则被作为干扰项而排除。图像特征提取
在我们日常生活中,图像是继文字外又一重要的信息承载体,当下的图片处理技术同样也离不开图像特征提取。不过在讲解如何提取图像特征之前,我们首先要知道什么是图像以及图像在机器中是如何存储的。
以上面这张图为例,我们可以看到这张图是由64个小方格组成的(8*8),这每一个小方格我们称之为像素,上面这张图的像素就是64像素。仔细看这张图,我们会发现白色的地方有的白一点,有的黑一点,我们可以用一个数值来量化它们,越黑的地方数值越小(纯黑为零),越白的地方数值越大,这样整张图就可以转化成一个二维矩阵的形式来在机器中存储,这就是黑白图像在机器中的存储方式,矩阵中的数值我们称之为灰度。[[0.0.0.12.13.0.0.0.][0.0.5.16.8.0.0.0.][0.0.13.16.3.0.0.0.][0.0.14.13.0.0.0.0.][0.0.15.12.7.2.0.0.][0.0.13.16.13.16.3.0.][0.0.7.16.11.15.8.0.][0.0.1.9.15.11.3.0.]]
上面这个二维矩阵就是图片在机器中存储的结果,其中的数值代表灰度。如果图片是一张黑白图片,那么我们通常会称之为灰度图。
对于彩色图片在机器中的存储,我们以上面这张图为例。彩色图的存储不同于灰度图,对于灰度图来说,像素只需要一个二维矩阵就可以储存,但对于彩色图来说,一个像素就需要不止一个矩阵来保存,矩阵中的列会包含多个子列,即含有多个颜色通道,例如RGB图像就有红、绿、蓝三个颜色通道。对于多通道图来说,有N个通道,其存储就需要N维矩阵。
上面4个图片分别是三通道图、“B”通道图、“R”通道图和“G”通道图。[[251251251...255255255][251251251...255255255][251251251...255255255]...[249250250...255255255][249250250...255255255][249250250...255255255]]这里只展示“B”通道的存储矩阵。
了解了图片在机器中是如何存储的之后,我们来熟悉一下简单的图片操作。对图像的的处理本书采用的是Python中的OpenCV库首先让我们来了解一下基本操作:importcv2ascv读入图片:tp=cv.imread('D:\s.jpg')输出图片:cv.imshow('tp',tp)cv.waitKey()waitKey的作用是使图片延时关闭,括号中可自定义关闭时间。保存图片:cv.imwrite("D:\\a.jpg",tp)显示某个颜色通道:tp=cv.imread('D:\s.jpg')B,G,R=cv.split(tp)cv.imshow('B',B)cv.imshow('G',G)cv.imshow('R',R)cv.waitKey()转化成灰度图:importcv2ascvtp=cv.imread('D:\s.jpg')t=cv.cvtColor(tp,cv.COLOR_BGR2GRAY)cv.imshow('t',t)cv.waitKey()我们知道,对于jpg彩色图来说,其存储方式都是RBG三色通道(即三维矩阵),但是在cv2中,图片的颜色通道的排列顺序却是BGR排列,我们把它转化成灰度图(二维矩阵),就要对其进行压缩,而cv.cvtColor(tp,cv.COLOR_BGR2GRAY)的作用就是将图片压缩成二维矩阵(转化成灰度图)。我们以这章灰度图为例,讲解如何提取像素值特征首先,我们要将这张灰度图读入tp=cv.imread('D:\s.jpg',0)0的作用是以灰度图的形式读入。我们知道,一张图是由若干个像素做成的,且每个像素都有自己的值(灰度)。所以我们可以将每一个像素看做是一个单独的特征,那么这一张图片就有N*M个特征(N代指图片的长,M代指图片的宽),所以我们接下来只要知道这个图片有多少像素就可以知道这张图片有多少像素值特征。查看图片大小:print(tp.shape)结果:(728,728)所以这张图片就有728*728即529984个特征。提取:Feature_tp=np.reshape(tp,(728*728))print(feature_tp.shape)print(feature_tp)输出:(529984,)[0.570101570.570101570.5686949...0.552929410.568615690.57645882]5.3特征选择
当特征经过特征提取和预处理之后,我们就应该思考一个问题:如何选择对我们最有意义的特征?在未进行模型训练之前,我们可不可以剔除一些无关紧要的特征使得我们所构建的模型具有更好的泛化能力?而这就是我们即将要学习的特征选择。FilterFilter过滤法,根据特征在各种统计检验中的得分以及与目标的相关性来进行特征选择。从方差的角度考虑,如果一个特征的方差为0,那么我们就可以毫不客气的把这个特征移除。一个特征的方差越小,说明这个特征在我们所研究的模型中基本相同,甚至取值也相同,那么我们就可以把这个无关特征剔除。VarianceThreshold方差过滤,是Filter中常用的一个方法,是sklearn.feature_selection中的一个方法。以如下数据为例:[[100000][110000][111000][111100][111110][111111]]fromsklearn.feature_selectionimportVarianceThresholdvt=VarianceThreshold(threshold=.6*(1-.6))data=vt.fit_transform(data)print(data)结果:[[0][0][0][1][1][1]]我们可以看到,VarianceThreshold删除了出现概率大于0.6(方差小于0.6*(1-0.6)=0.24)的特征。如果我们从相关性的角度考虑,研究单一特征对于目标的相关性来进行特征选择。那么我们将从以下两个方面进行考虑:对于研究目标为连续特征(分类问题):我们可以使用皮尔森相关系数和最大信息系数来进行特征选择;对于研究目标为离散特征(回归问题):我们可以使用卡方检验来进行特征选择;接下来我们分别演示上述方法的代码实现。卡方检验:我们以sklearn自带的cancer数据集为例;fromsklearn.datasetsimportload_breast_cancerfromsklearn.feature_selectionimportchi2,SelectKBestcancer=load_breast_cancer()x,y=cancer.data,cancer.targetprint(x.shape)x_after_chi2=SelectKBest(chi2,k=3).fit_transform(x,y)print(x_after_chi2.shape)输出:(569,30)(569,3)我们可以看到,经过卡方检验后,选择出了三个最优的特征,其中SelectKBest中k的作用是调节选出特征的数量,这里作者设置的是k=3。皮尔森相关系数:fromscipy.statsimportpearsonrimportpandasaspdcancer=load_breast_cancer()data=cancer.dataname=cancer.feature_namesdf_data=pd.DataFrame(data,columns=name)mean_radius=df_data['meanradius'].valuesmean_area=df_data['meanarea'].valuesprint(pearsonr(mean_radius,cancer.target))print(pearsonr(mean_area,cancer.target))print(pearsonr(1/mean_radius,cancer.target))print(pearsonr(mean_radius,mean_area))print(pearsonr(1/mean_radius,mean_area))输出:(-0.7300285113754555,8.465940572265007e-96)(-0.708983836585389,4.734564310308523e-88)(0.6963446864460401,1.008218724950505e-83)(0.9873571700566124,0.0)(-0.8949235983985604,7.361249768074129e-201)Pearsonr输出的是一个二元组(score,p-value),其中score的取值为[-1,1],score的值越接近1表示具有正相关,0表示不相关,-1表示具有负相关。但是,皮尔森相关系数还有一个明显的缺陷:只对线性相关敏感,对于非线性相关则不敏感。例如:x=np.random.randint(-100,100,1000)y=x**xprint(pearsonr(x,y))输出:(-0.023685330149289394,0.4543611970681528)最大信息系数,弥补了皮尔森相关系数对非线性相关不敏感的缺点fromminepyimportMINEm=MINE()x=np.random.randint(-100,100,1000)y=x**2pute_score(x,y)print(m.mic())输出:0.9999663372141733WrapperWrapper包装法,其原理是根据一个目标函数进行训练,每次选择若干特征或排除若干特征,常用的方法是递归消除特征法(RecursiveFeatureElimination,RFE)。递归消除特征法(RFE),选定一个基模型进行多轮训练,每轮训练过后,移除若干权重系值的特征,新的特征重新开始下轮训练。实现:我们以sklearn自带的鸢尾花iris数据集为例fromsklearn.datasetsimportload_irisfromsklearn.model_selectionimporttrain_test_splitfromsklearn.linear_modelimportLinearRegression,LogisticRegressionfromsklearn.feature_selectionimportRFEiris=load_iris()rfe=RFE(estimator=LogisticRegression(),n_features_to_select=2)rfe.fit(iris.data,iris.target)new_data=rfe.transform(iris.data)tr_x,te_x,tr_y,te_y=train_test_split(new_data,iris.target)reg=LinearRegression()reg.fit(tr_x,tr_y)print("score_ref:{}".format(reg.score(te_x,te_y)))输出:score_ref:0.9520066024532783如果我们不进行特征选择,结果:score:0.9111603863444916我们可以看到,我们使用了RFE进行递归消除特征,得到的结果比没有递归得到的结果反而要好上许多,这里n_feature_to_select的取值为[1,特征数],estimator为所选择的基函数。当然我们也可以查看递归消除特征后选择的新特征print(rfe.ranking_)利用RFE中的ranking_函数查看。结果:[3211]我们可以从中看出,RFE之后,新特征保留了第三列和第二列的特征,删除了第一列和第零列的特征。EmbeddedEmbedded嵌入法,让特征选择和算法同时训练,让算法选择去使用那些特征。其原理是先特征在模型中训练,利用训练得到的各项特征的权值系数按照从大到小原则去选择特征,一般选取能对特征进行打分的模型来进行特征选择。这里,我们利用sklearn.feature_selection中SelectFromModel进行特征选择。实现:基于L1的特征选择我们以sklearn中的wine数据集为例fromsklearn.svmimportLinearSVCfromsklearn.datasetsimportload_winefromsklearn.feature_selectionimportSelectFromModelfromsklearn.linear_modelimportLinearRegressionfromsklearn.model_selectionimporttrain_test_splitwine=load_wine()model=SelectFromModel(LinearSVC(C=0.06,penalty='l1',dual=False).fit(wine.data,wine.target),prefit=True)new_data=model.transform(wine.data)print(new_data.shape)tr_x,te_x,tr_y,te_y=train_test_split(new_data,wine.target)reg=LinearRegression().fit(tr_x,tr_y)print(reg.score(te_x,te_y))我们可以比对一下结果:score_L1:0.900416686283543score:0.8777617089374858这里我们也可以查看L1特征选择后新特征的个数print(wine.data.shape)print(new_data.shape)输出:(178,13)(178,8)可以看到,L1选择后舍弃了5个特征。基于随机森林的特征选择fromsklearn.ensembleimportRandomForestClassifiernew_data=SelectFromModel(RandomForestClassifier(n_estimators=10),threshold=0.02).fit_transform(wine.data,wine.target)tr_x,te_x,tr_y,te_y=train_test_split(new_data,wine.target)reg=LinearRegression().fit(tr_x,tr_y)print(reg.score(te_x,te_y))对比结果:score_randomforest:0.9197384294818963score:0.8762378048776154当然还有很多模型可供选择5.4降维
通常情况下,我们通过特征提取得到的特征往往都是比较冗沉和复杂的,特征数量达到几十或者几百。在这种情况下,即使我们对特征进行预处理和特征选择,用所得到的新特征进行机器学习,但模型的泛化能力可能仍然达不到理想的标准。再者说,特征(维度)越多,所能用于机器学习的样本就越少,而且在高维情形下计算也成了很大一个难题。
降维,就是将高维度的数据经过有限次的变换,转变成低维度的数据。从而使得数据能更好的应用在机器学习上,得到一个更好的结果。降维对高维度特征数据预处理方法,将高维度的数据保留下最重要的一些特征,去除噪声和不重要的特征,从而实现提升数据处理速度的目的。在实际的生产和应用中,降维在一定的信息损失范围内,可以为我们节省大量的时间和成本。降维也成为应用非常广泛的数据预处理方法。降维的优点有:使得数据集更易使用,降低算法的计算开销,去除噪声,使得结果容易理解。
降维的算法有很多,比如主成分分析(PCA)、独立成分分析(ICA)、线性辨别分析(LDA),主成分分析和独立成分分析是无监督学习,而线性辨别分析是监督学习。本节只对PCA进行详细讲解,并对ICA和LDA进行简单介绍。PCA
PCA是最常用的线性降维方法,它的目标是通过某种线性投影,将高维的数据映射到低维的空间中表示,并期望在所投影的维度上数据的方差最大,以此使用较少的数据维度,同时保留住较多的原数据点的特性。
通俗的理解,如果把所有的点都映射到一起,那么几乎所有的信息都丢失了,而如果映射后方差尽可能的大,那么数据点则会分散开来,以此来保留更
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 老婆撕掉协议书
- 电梯分配协议书
- 退休移交协议书
- 药店收购协议书
- 夫妻打架离婚后协议书
- 肺癌补偿协议书
- 电线拆除协议书
- 股票操盘协议书
- 那个离婚协议书
- 桌球厅承包合同协议书
- 西铁计202119号 中国铁路西安局集团有限公司关于印发《西安局集团公司地方涉铁工程建设管理办法》的通知2021-01-25
- 光伏发电项目试验计划
- 2023年全国青少年航天知识大赛题库
- 《一棵小桃树》阅读
- 病理检验技术试题+答案
- 髋臼及股骨骨缺损的分型及评价-课件
- 互联网+医疗远程母婴健康管理平台建设方案
- 施工单位关键岗位人员到岗履职检查记录表
- 上海市华师大二附中2022-2023高二下学期期中政治试卷
- 加工中心点检表
- 国开电大本科《管理英语 4》 形考任务(单元自测 1 至 8) 试题及答案
评论
0/150
提交评论