强烈推荐机器学习之算法篇
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了强烈推荐机器学习之算法篇相关的知识,希望对你有一定的参考价值。
机器学习算法
数据类型:
不同类型的数据集采用的算法是不一样的。总体来说,生活场景中只有两种类型的数据,一种是离散型,一种是连续型:
- 离散型数据:由记录不同类别个体的数目所得到的数据,又称计数数据,所有这些数据全部都是整数,而且不能再细分,也不能进一步提高他们的精确度。比如分类就是离散型数据。
- 连续型数据:变量可以在某个范围内取任一数,即变量的取值可以是连续的。如,长度、时间、质量值等,这类数通常是非整数,含有小数部分。
可用数据集:
Kaggle
:一个大数据竞赛平台,上面的数据都是真实的,并且有很多数据集。网址是https://www.kaggle.com/datasets
UCI
:收录了360个数据集,覆盖了科学、生活、经济等领域。网址是http://archive.ics.uci.edu/ml/
scikit-learn
数据集:用于学习的数据集,数据量比较小,但是方便获取和学习。网址http://scikit-learn.org/stable/datasets/index.html#datasets
。
监督学习和无监督学习:
- 监督学习(英语:Supervised learning),可以由输入数据中学到或建立一个模型,并依此模式推测新的结果。输入数据是由输入特征值和目标值所组成。函数的输出可以是一个连续的值(称为回归),或是输出是有限个离散值(称作分类)。
- 无监督学习(英语:Supervised learning),可以由输入数据中学到或建立一个模型,并依此模式推测新的结果。输入数据是由输入特征值所组成。
算法分类:
- 监督学习:
- 分类:K近邻算法、贝叶斯分类、决策树与随机森林、逻辑回归、神经网络。
- 回归:线性回归、岭回归。
- 无监督学习:
- 聚类:
k-means
。
- 聚类:
scikit-learn数据集
获取数据集:
sklearn
内部提供了一些数据集,用于学习使用。在使用他之前,首先对他进行一些了解。
获取数据集方式:
获取数据集的方式有两种,有load_*
和fetch_*
。以下:
sklearn.datasets.load_*()
:获取小规模的数据集,数据集已经随着scikit-learn
安装而下载了。sklearn.datasets.fetch_*(data_home=None)
:用于从远程获取大规模的数据集,函数的第一个参数是data_home
,表示数据集下载的目录,默认是~/scikit_learn_data/
。
两种方式返回的结果都是sklearn.utils.Bunch
类型,这种数据类型有以下方法和属性:
data
:特征数据数组,是[n_samples * n_features]
的二维numpy.ndarray
数组。target
:标签数组,是n_samples
的一维numpy.ndarray
数组。DESCR
:数据描述。feature_names
:特征名,新闻数据、手写数字、回归数据集没有。target_names
:标签名,回归数据集没有。
数据集的划分:
我们拿到数据集后,一般会采用75%
的用于训练,25%
的用来测试。因此在把数据进行训练之前,先要对数据进行划分。我们可以使用sklearn.model_selection.train_test_split
进行分割,train_test_split
中的常用参数如下:
x
:数据集的特征值。y
:数据集的目标值。test_size
:测试的数据的占比,用小数表示。
返回值如下:
x_train
:训练部分的特征值。x_test
:测试部分的特征值。y_train
:训练部分的特征值。y_test
:测试部分的目标值。
示例代码如下:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
def dataset_split():
li = load_iris()
x_train,x_test,y_train,y_test = train_test_split(li.data,li.target,test_size=0.25)
print("训练集的数据:",x_train,y_train)
print("测试集的数据:",x_train,x_test)
本地数据集:
分类数据集:
load_iris
:鸢尾花花瓣数据集。load_digits
:手写数字数据集。load_wine
:红酒数据集。load_breast_cancer
:乳腺癌数据集。
回归数据集:
load_boston
:波士顿房价数据集。load_diabetes
:糖尿病数据集。load_linnerud
:体能训练数据集。
以上所有的数据集的网址为:https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_boston.html#sklearn.datasets.数据集函数名
。
远程数据集:
远程数据集是一些真实的数据,一般都比较大,因此在需要的时候进行加载即可。
分类数据集:
fetch_olivetti_faces
:面孔数据集。fetch_20newsgroups
:20个新闻组数据集。fetch_lfw_people
:户外人脸识别数据集。fetch_lfw_pairs
:户外人脸对(同一个人两个图片)数据集。fetch_covtype
:美国一块30*30m的森林斑块土地,上面覆盖了不同类型的树木。fetch_rcv1
:路透社文集I (RCV1)。由路透社有限公司为研究目的提供的80多万篇手动分类的新闻专线报道的存档。fetch_california_housing
:加利福尼亚房子数据集。
K近邻算法
K近邻算法原理:
K
近邻算法是如果一个样本在特征空间中的K
个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
他的原理就是求两点之间的距离,看距离谁是最近的,以此来区分我们要预测的这个数据是属于哪个分类:
比如有两点,要求他们的距离,a(a1,a2,a3)
,b(b1,b2,b3)
,则计算公式为:
√((𝑎1−𝑏1)^2+(𝑎2−𝑏2)^2+(𝑎3−𝑏3)^2)
这个公式叫做欧式距离公式。
使用sklearn
实现K
近邻算法:
sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,algorithm='auto')
:
-
n_neighbors
:int
,可选(默认= 5),k_neighbors
查询默认使用的邻居数。 -
algorithm
:可选用于计算最近邻居的算法。ball_tree
:将会使用BallTree
。kd_tree
:将使用KDTree
。auto
:将尝试根据传递给fit方法的值来决定最合适的算法。 (不同实现方式影响效率)
案例:
使用FaceBook
生成的一个选址的数据集为例。
网站为:https://www.kaggle.com/c/facebook-v-predicting-check-ins/data
。
代码如下:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
train_data = pd.read_csv("data/FBlocation/train.csv")
time_value = pd.to_datetime(train_data['time'],unit='s')
time_value = pd.DatetimeIndex(time_value)
# 将时间戳变成周几,几点。因为不同的时间可能会影响选址
train_data['week'] = time_value.week
train_data['hour'] = time_value.hour
place_count = train_data.groupby("place_id").count()
temp_data = place_count[place_count['row_id'] > 10].reset_index().head()
train_data = train_data[train_data['place_id'].isin(temp_data['place_id'])]
train_data = train_data.reset_index().drop(['index','row_id'],axis=1)
y = train_data['place_id']
x = train_data.drop(['place_id'],axis=1)
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)
# 因为不同的数据大小单位不一样,为了避免造成太大的影响,都做一个标准化。
scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.fit_transform(x_test)
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(x_train,y_train)
y_predict = knn.predict(x_test)
# print("预测的位置:",y_predict)
print("预测的准确率:",knn.score(x_test,y_test))
其中正确率达到98%
。
K
(也就是n_neighbors
)值该去多大?
K
值不能取太少,也不能取太多。如果取太少,则容易受异常点的影响,如果取太多,则容易产生过拟合的现象,也会影响分类的准确性。因此要不断的调参数,来看下参数对最终结果的影响。
K近邻算法的优缺点:
- 优点:简单,易于理解,无需估计参数,无需训练。
- 缺点:懒惰算法,对测试样本分类时的计算量大,内存开销大。
K
值要不断的调整来达到最优的效果。
基于以上优缺点,在小数据场景,几千~几万的数据量的时候,可以使用K
近邻算法。
作业:
使用sklearn
自带的数据集load_wine
,来预测酒的分类。
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_wine
# 加载数据
wine = load_wine()
# 标准化
scaler = StandardScaler()
features = scaler.fit_transform(wine.data)
targets = wine.target
# 训练数据求得分
X_train,X_test,y_train,y_test = train_test_split(features,targets,test_size=0.25)
knn = KNeighborsClassifier()
knn.fit(X_train,y_train)
knn.score(X_test,y_test)
朴素贝叶斯
贝叶斯:
贝叶斯全名托马斯·贝叶斯(Thomas Bayes,1702-1761),是一名英国数学家,贝叶斯公式是源于他生前写的一篇“逆概率”问题的文章。贝叶斯公式在生前并不被认可,在去世后被他的朋友整理才公诸于世被世人所认可。
概率计算小案例:
在学习朴素贝叶斯基础之前,先要学习一下数学中关于概率的计算。比如有以下表:
症状 | 职业 | 疾病 |
---|---|---|
打喷嚏 | 护士 | 感冒 |
打喷嚏 | 农夫 | 过敏 |
头痛 | 建筑工人 | 脑震荡 |
头痛 | 建筑工人 | 感冒 |
打喷嚏 | 教师 | 感冒 |
头痛 | 教师 | 脑震荡 |
根据以上数据,回答以下问题:
- 得感冒的人概率是多少?(3/6)
- 有头痛症状,并且是教师的概率是多少?(1/6)
- 在感冒的疾病中,是护士的概率是多少?(1/3)
- 在感冒的疾病中,打喷嚏并且是护士的概率是多少?((1/3)*(2/3)=2/9)
联合概率和条件概率:
联合概率:
联合概率是包含多个条件,且所有的条件同时成立的概率,以上第二点就是联合概率。这种概率计算的方式有专门的公式,记作P(AB)
,其中P(A)
表示A
这个特征出现的概率,同理P(B)
也是,在特征条件独立的情况下存在公式P(AB)=P(A)*P(B)
。所以以上第二题的答案是:P(头痛)*P(教师)=(3/6)*(2/6)=1/6
。
条件概率:
条件概率就是事件A
在另外一个事件B
已经发生的前提下发生的概率。计算的公式为:P(A|B)
,如果有多个条件,那记作P(A1,A2|B)=P(A1|B)*P(A2|B)
。所以以上第四题的答案是:P(打喷嚏|感冒)*P(护士|感冒)=(2/3)*(1/3)=2/9
。
注意:以上的计算公式,是在以各个特征是条件独立的基础之上才成立的!
朴素贝叶斯公式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mPgK2OkD-1634893566974)(/assets/chapter03/朴素贝叶斯公式.svg)]
推导过程:
# 因为在概率论中有一个乘法定理
P(AB) = P(A|B)*P(B)
# 这个公式同样适合B在A条件下发生的概率,因此:
P(AB) = P(B|A)*P(A)
# 以上两个等式相等,所以
P(A|B) = P(B|A)*P(A)/P(B)
贝叶斯公式例子:
假如现在学校有N
个学生,男生占60%,女生占40%,其中男生都穿长裤,女生有一半是穿长裤,一半是穿裙子,那么以下两个问题:
- 随机选择一个学生,知道性别的前提下,他(她)穿长裤的概率是多少?(男:1,女:0.5)
- 走来一个学生,只看到他穿长裤,求他是男生的概率是多少?(3/4=0.75)
文档分类:
以上便是朴素贝叶斯的公式。一般朴素贝叶斯经常用到文档分类上,文档分类是根据已经分类的文档中提取关键词,在以后遇到新的文档分类的时候,就从这些关键词中预测是属于哪个类别。在文档分类中可以把贝叶斯公式改成以下:
针对每个进行一个讲解:
P(C|W)
:某个关键词属于某个分类的概率。P(W|C)
:某个分类下,某个关键词出现的概率。P(C)
:某个类别的概率(某个类别的文档个数/总文档数)。P(W)
:这个关键词在需要预测的文档中出现的概率。
朴素贝叶斯预测文档分类的原理是:根据以上公式,可以计算出某篇文档下出现得比较多的词,然后把这些词去每个分类下求下概率,在哪个分类下的概率高,那么就意味着这篇文章是属于哪个分类。
比如现在有以下表格:
特征 | 科技类 | 娱乐类 | 汇总 |
---|---|---|---|
明星 | 9 | 51 | 60 |
影院 | 8 | 56 | 64 |
云计算 | 63 | 0 | 63 |
支付宝 | 20 | 15 | 35 |
汇总 | 100 | 121 | 221 |
假如现在有一篇文章包含“影院”、“支付宝”、“云计算”,要计算属于科技类和娱乐类的概率。计算方式如下:
P(科技|影院,支付宝,云计算)=P(影院,支付宝,云计算|科技)*P(科技) = (8/100)*(20/100)*(63/100)*(100/221)
P(娱乐|影院,支付宝,云计算)=P(影院,支付宝,云计算|娱乐)*P(娱乐) = (8/121)*(15/121)*(0/121)*(121/221)
拉普拉斯平滑系数:
可以看到上面的演示中,娱乐类在计算完成后,概率为0,这肯定是不对的,因为他只要里面包含了任何一个跟娱乐相关的词,都有可能是属于娱乐。因此为了避免出现0的情况,可以使用拉普拉斯系数,将P(W|C)
改为如下:
𝑃(W│𝐶)=(𝑁𝑖+𝛼)/(𝑁+𝛼𝑚)
其中
𝑁𝑖
为该W
词在C
类别所有文档中出现的次数。N
为所属类别C
下的文档所有词出现的次数和。𝛼
就是为指定的系数,一般为1。m
为训练文档中统计出的特征词个数。
这样计算出来虽然结果稍微有些不同,但是不会影响每个词对文档分类的概率大小,大小没改变,那么分类结果也不会被改变。
文章分类实战:
可以使用sklearn.navie_bayes.MultinomialNB(alpha=0.1)
来实现。
我们用sklearn
库中提供的fetch_20newsgroups
来做分类,这个数据总共有20个类别,总共有18000篇新闻。
from sklearn.naive_bayes import MultinomialNB
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
newsgroups = fetch_20newsgroups(data_home="./data")
X_train,X_test,y_train,y_test = train_test_split(newsgroups.data,newsgroups.target,test_size=0.25)
tf = CountVectorizer()
X_train = tf.fit_transform(X_train)
X_test = tf.transform(X_test)
mnb = MultinomialNB()
mnb.fit(X_train,y_train)
mnb.score(X_test,y_test)
朴素贝叶斯模型:
针对不同的数据,我们有不同的朴素贝叶斯模型来进行分类。如果特征是离散型数据,比如文本这些,那么推荐使用多项式模型来实现;如果特征是连续型数据,比如具体的数字,那么推荐使用高斯模型来实现;如果特征是连续型数据并且值只有0
和1
两种情况,那么推荐使用伯努利模型。虽然模型不同,但是原理都是朴素贝叶斯公式,只不过不同的模型,在计算概率的时候采用的方式不一样,比如高斯模型,那么是通过高斯分布函数来计算而已。
多项式模型:
离散型数据应该使用多项式模型来实现。比如文档分类、垃圾邮件识别等。使用的类是sklearn.navie_bayes.MultinomialNB
。
高斯模型:
连续型数据应该使用高斯模型来实现。公式依然是使用之前的朴素贝叶斯公式,但是在计算条件概率的时候用的是高斯分布函数:
在sklearn
中,使用的类是sklearn.navie_bayes.GaussianNB
来实现的。比如有一组心脏病患者的数据,心脏病患者的一些特性,都是具体的数值,也就是连续型数据,因此这种情况下应该使用高斯模型。示例代码如下:
hearts = pd.read_csv("data/heart.csv")
features = hearts.drop(columns=['target'],axis=0)
targets = hearts['target']
X_train,X_test,y_train,y_test = train_test_split(features,targets,test_size=0.25)
gaus = GaussianNB()
gaus.fit(X_train,y_train)
gaus.score(X_test,y_test)
伯努利模型:
伯努利模型,一般在特征的值,都是0和1的情况下使用。在sklearn
中,使用的类是sklearn.navie_bayes.BernoulliNB
来实现。
朴素贝叶斯算法总结:
优点:
- 朴素贝叶斯发源于古典数学,有稳定的分类效率。
- 对数据缺失不太敏感,算法也比较简单,常用于文本分类。
- 分类准确度高,速度快。
缺点:
由于使用了样本特性条件独立性,如果样本特性有关联的时候,会影响算法的效果。
决策树
决策树理解:
假如现在有一个母亲给女儿找相亲对象的这么一段对话:
女儿:多大年纪了?
母亲:26。
女儿:长的帅不帅?
母亲:挺帅的。
女儿:收入高不?
母亲:不算很高,中等情况。
女儿:是公务员不?
母亲:是,在税务局上班呢。
女儿:那好,我去见见。
那么转换成图便是这样:
以上这个就是决策树的原理。通过不断的划分条件来进行分类。其中决策树最关键的,是找出那些对结果影响最大的条件,放到前面。比如以上如果年龄是女儿最看重的,那么就应该把年龄放到最前面,这样可以节省查找的次数。
信息熵:
信息熵是1948年美国数学家香农提出的概念,他是用来表示随机数据不确定性的度量。信息熵越大,也就意味着越不稳定,信息熵越小,说明数据是越稳定(越接近或者类似)。
信息熵的公式是:
其中H(x)
就表示信息熵,P(F1,F2...)
表示数据在整个数据集中出现的概率。
比如有两组数据:
A = [1,1,1,1,1,1,1,1,2,2]
B = [1,2,3,4,5,6,7,8,9,10]
我们先不去算信息熵,从数据上就能看出,A
是更稳定的,B
的数据更杂,猜想A
的信息熵比B
的信息熵要小。那么通过计算信息熵来确定是不是真的:
H(A) = -(8/10*log(8/10)+2/10*log(2/10)) = 0.7219280948873623
H(B) = -(1/10*log(1/10)*10) = 3.321928094887362
可以看出B
的信息熵明显比A
的信息熵大很多。
信息熵的补充:
- 信息熵的单位是比特(bit)就是我们在编程中用来计算数据大小的单位。
1位=8比特
。 - 公式中的
log2
的理解:我们先看下log2
的图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CaJUTq6y-1634893628622)(/assets/chapter03/log2.png)]
其中x就是概率,y就是log2(x)的值,0<x<1
,如果x越大,那么信息熵也就越小,而x越小,则信息熵越大。正好是和我们期望的是一样的。
信息增益:
信息增益表示特征X
使得类Y
的不确定性减少的程度。因此信息增益越大,那么表示对不确定性减少得越多,也就越能更清晰的分类。特征A
对训练数据集D的信息增益记作g(D,A)
,定义为集合D
的信息熵H(D)
与特征A
给定条件下D
的经验条件熵H(D|A)之差,即公式为:
g(D,A)=H(D)−H(D∣A)
# 其中的H(D|A),A特征中可能有N种值(A1,A2...),计算方式如下
H(D|A) = P(A1)*H(D|A1) + P(A2)*H(D|A2)...
根据信息增益的准则的特征选择方法是:对于训练数据集D,计算其每个特征的信息增益,并比较它们的信息增益,选择信息增益最大的特征。
贷款案例信息增益:
以上数据集中,有年龄
、是否有工作
、是否有房子
、信贷情况
4个特征来判断是否应该给这个用户贷款,当时放到决策树中,我们应该要把哪个特性放到前面,哪个特性放到后面,就应该通过计算信息增益来决定。
H(贷款) = -(6/15*log2(6/15)+9/15*log2(9/15)) = 0.97
H(贷款|年龄) = H(贷款) - H(贷款|青年) - H(贷款|中年) - H(贷款|老年)
H(贷款|青年) = -5/15*(2/5*log2(2/5) + 3/5*log2(3/5)) = 0.32
H(贷款|中年) = -5/15*(2/5*log2(2/5) + 3/5*log2(3/5)) = 0.32
H(贷款|老年) = -5/15*(1/5*log2(1/5) + 4/5*log2(4/5)) = 0.24
因此H(贷款|年龄) = 0.97 - (0.32+0.32+0.24) = 0.09
同理我们也可以计算出是否有工作
的信息增益为0.32
、是否有房子的信息增益为0.42
、信贷情况的信息增益为0.363
。因此在建立决策树的时候就可以根据信息增益的从大到小排序了。
决策树算法选择:
ID3:
ID3
算法采用的是信息增益来进行决策树的创建的。信息增益虽然效果不错,但是他是偏向选择分支多的属性,会导致过度拟合,因此一般不会采用此算法。
C4.5:
ID3
会导致过度拟合,那么我们能想到的解决办法自然就是对分支过多的情况进行惩罚。于是我们有了信息增益比,或者说信息增益率,信息增益率:
gr = 某特征的信息增益/某特征的信息熵
gr=(H(c)−H(c|X))/H(X)
从上述公式我们可以看到,如果某特征分类特别多,那么会导致信息熵会非常大,从而信息增益也会变得比较大,因此最后得出的信息增益率会变小,这样就对他进行了有效抑制。
CART:
C4.5
已经是比较好的构建决策树的算法了,但是他计算的时候需要不断的求对数(log),对算法的效率有一定的影响,因此在CART
中采用了一个叫做基尼(Gini)系数的东西来进行分类。Gini
系数是一种与信息熵类似的做特征选择的方式,可以用来数据的不纯度。Gini
系数的计算方式如下:
Gini(p)=1−(P1^2+P2^2+...)
其中P(n)
代表的是第几个特征出现的概率。
预剪枝和后剪枝:
树的层级和叶子节点不能过于复杂,如果过于复杂,那么容易导致过拟合现象(过拟合:在训练的时候得分很高,但是测试的时候得分很低)。而预剪枝和后剪枝手段,都是为了防止决策树太复杂的手段:
预剪枝:
预剪枝就是在决策树的建立过程中不断的调节,可以调节的条件有:
- 数的深度:如果在决策树建立过程中,发现深度超过指定的值,那么就不再分了。
- 叶子节点个数:同上。
- 叶子节点样本数:如果某个叶子节点的个数已经低于指定的值,那么就不会再分了。
- 信息增益量/Gini系数:计算信息增益量或者Gini系数,如果小于指定的值,那么也不会再分了。
以上的参数,都需要在建模的过程中,不断的调节,来达到最优。
预剪枝可以有效的降低过拟合现象,并且因为是在决策树建立的过程中进行调节,因此显著的减少了训练时间开销和测试时间的开销。另外因为预剪枝是通过限制一些建树的条件来实现的,这种方式容易导致(欠拟合:模型训练得不够好)的现象。
后剪枝:
后剪枝就是在决策树建立完成后再进行的,根据以下公式:
C = gini*samples + α*叶子节点个数
C
表示损失,C
越大,表示损失越多,我们要选择损失小的。
其中的α
我们是可以调节的,如果α
越大,那么叶子结点个数越多的,损失越大。因此α
值越大,那么偏向叶子节点少的。α
越小,那么偏向叶子节点多的。
后剪枝通常比预剪枝保留更多的分支,因此欠拟合风险比预剪枝要小,但是因为后剪枝是在树建立完成后再自底向上对所有非叶子节点进行逐一考察,因此训练时间开销比预剪枝要大得多。
sklearn实现决策树:
在sklearn
中,可以通过sklearn.tree.DecisionTreeClassifier
来实现决策树,这个类有以下参数:
- criterion:
gini
或者entropy
的方式。 splitter
:best
或random
。best
是在所有特种中找最好的切分点,random
是随机的找一些特征来进行切分(数据量大的时候用random
)- max_depth:树的最大深度。当特征或者数据量比较小的时候可以不用管这个值。特征比较多的时候可以尝试限制一下。
- min_samples_split:决策树中某个叶子节点的样本最小个数。如果数据量不大,不需要管这个值,如果样本量比较大,则推荐增大这个值。
min_weight_fraction_leaf
:叶子节点所有样本权重和的最小值。如果小于这个值,则会和兄弟节点一起被剪枝,默认是0,也就是不考虑权重的问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。- max_leaf_nodes:最大的叶子节点的个数。默认是
None
,即不限制叶子节点的个数。如果设置了这个值,那么在决策树建立的过程中优化叶子节点的个数。如果特征不多,可以不考虑这个值,但是如果特征分多的话,可以加以限制。 class_weight
:指定样本各特征的权重,主要是为了方式某些特征的样本过多导致偏向这些特征。默认是balance
,也就是算法会自动的调节权重。- min_impurity_decrease:最小的不纯度(基尼系数、信息增益等)。如果小于这个数,那么就不会再往下生成叶子节点了。
决策树案例-泰坦尼克号获救预测:
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
import numpy as np
titanic = pd.read_csv("data/titanic.txt")
features = titanic[['pclass','age','sex']]
features['age'].fillna(features['age'].mean(),inplace=True)
targets = titanic['survived']
X_train,X_test,y_train,y_test = train_test_split(features,targets,test_size=0.25)
vect = DictVectorizer(sparse=False)
X_train = vect.fit_transform(X_train.to_dict(orient='records'))
X_test = vect.transform(X_test.to_dict(orient="records"))
tree = DecisionTreeClassifier()
tree.fit(X_train,y_train)
tree.score(X_test,y_test)
绘制决策树:
决策树训练完成后,如果能直观的看到树的结构,那么会帮助我们更好的理解树的构建情况以及帮助我们做一些剪枝的操作。在sklearn
中,可以通过sklearn.tree.export_graphviz
来将树结构导出为.dot
文件,然后再到这个网站:https://www.graphviz.org/download/
下载graphviz
软件,这个软件可以将.dot
文件转为png
格式。graphviz
安装完成后,记得把安装路径下的bin
目录,添加到环境变量PATH
中。然后再在cmd终端使用命令dot -Tpng 生成的dot文件.dot -o tree.png
将dot
文件转换为png
文件。
其中sklearn.tree.export_graphviz
函数有许多参数,我们了解下以下几个参数:
decision_tree
:决策树,就是DecisionTreeClassifier
的对象。out_file
:生成.dot
文件的路径。feature_names
:特征名称,方便在生成树的时候能在节点看到特征名称。通过get_feature_names
来获取,不能乱填。class_names
:分类的类名。如果设置了,他是按照target
分类的数值从小到大进行排序,所以在指定具体名称的时候,应该根据排序的顺序来。
示例代码如下:
export_graphviz(classifier,"tree.dot",feature_names=['age', '1st', '2nd', '3rd', 'female', 'male'],class_names=['die','live'])
集成算法之随机森林
集成算法包含(bagging/boosting/stacking)在机器学习中,随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。利用相同的训练数搭建多个独立的分类模型,然后通过投票的方式,以少数服从多数的原则作出最终的分类决策。例如, 如果你训练了5
个树, 其中有4
个树的结果是True
, 1个数的结果是False
, 那么最终结果会是True
.
在前面的决策当中我们提到,一个标准的决策树会根据每维特征对预测结果的影响程度进行排序,进而决定不同的特征从上至下构建分裂节点的顺序,如此以来,所有在随机森林中的决策树都会受这一策略影响而构建的完全一致,从而丧失的多样性。所以在随机森林分类器的构建过程中,每一棵决策树都会放弃这一固定的排序算法,转而随机选取特征。
学习算法:
- 用
N
来表示训练用例(样本)的个数,M
表示特征数目。 - 输入特征数目
m
,用于确定决策树上一个节点的决策结果;其中m
应远小于M
。 - 从
N
个训练用例(样本)中以有放回抽样的方式,取样N
次,形成一个训练集(即bootstrap
取样),并用未抽到的用例(样本)作预测,评估其误差。 - 对于每一个节点,随机选择
m
个特征,决策树上每个节点的决定都是基于这些特征确定的。根据这m
个特征,计算其最佳的分裂方式。
理解:
为什么要随机抽样训练集?
如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样的
为什么要有放回地抽样?
如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是“有偏的”,都是绝对“片面的”(当然这样说可能不对),也就是说每棵树训练出来都是有很大的差异的;而随机森林最后分类取决于多棵树(弱分类器)的投票表决。
sklearn实现随机森林:
class sklearn.ensemble.RandomForestClassifier(n_estimators=10, criterion=’gini’,max_depth=None, bootstrap=True, random_state=None)
参数介绍:
n_estimators
:integer
,optional(default = 10)
森林里的树木数量。criteria
:string
,可选(default =“gini”)分割特征的测量方法。max_depth
:integer
或None
,可选(默认=无)树的最大深度 。bootstrap
:boolean
,optional(default = True)
是否在构建树时使用放回抽样。
加油!
感谢!
努力!
以上是关于强烈推荐机器学习之算法篇的主要内容,如果未能解决你的问题,请参考以下文章