赞
踩
注:本篇文章参考:
1、机器学习的种类介绍
2、机器学习两种方法——监督学习和无监督学习
3、决策树回归
监督学习指:从给定的训练数据集中学习出一个函数(模型参数),当新的数据到来时,可以根据这个函数预测结果。
监督学习的训练集要求包括输入输出,也可以说是特征和目标。训练集中的目标是由人标注的。
监督学习就是最常见的分类问题,通过已有的训练样本去训练得到一个最优模型,再利用这个模型将所有的输入映射为相应的输出,对输出进行简单的判断从而实现分类的目的。也就具有了对未知数据分类的能力。监督学习的目标往往是让计算机去学习我们已经创建好的分类系统(模型)。
在监督学习中,提供给算法的包含所需解决方案的训练数据,称为标签或标记。
监督学习是包含自变量和因变量(有Y),同时可以用于分类和回归。下来常见的算法都是监督学习算法。
1、K近邻算法(KNN)
2、线性回归
3、logistic回归
4、支持向量机(SVM)
5、决策树和随机森林
6、神经网络
非监督学习:输入数据没有被标记,也没有确定的结果。样本数据类别未知,需要根据样本间的相似性对样本集进行分类试图使类内差距最小化,类间差距最大化。
非监督学习目标不是告诉计算机怎么做,而是让它自己去学习怎样做事情。
无监督学习的方法分为两大类:
(1) 一类为基于概率密度函数估计的直接方法:指设法找到各类别在特征空间的分布参数,再进行分类。
(2) 另一类是称为基于样本间相似性度量的简洁聚类方法:其原理是设法定出不同类别的核心或初始内核,然后依据样本与核心之间的相似性度量将样本聚集成不同的类别。
有监督学习和无监督学习的区别:
有监督学习方法必须要有训练集与测试样本。在训练集中找规律,而对测试样本使用这种规律。而非监督学习没有训练集,只有一组数据,在该组数据集内寻找规律。
有监督学习的方法就是识别事物,识别的结果表现在给待识别数据加上了标签。因此训练样本集必须由带标签的样本组成。而非监督学习方法只有要分析的数据集的本身,预先没有什么标签。如果发现数据集呈现某种聚集性,则可按自然的聚集性分类,但不予以某种预先分类标签对上号为目的。
非监督学习方法在寻找数据集中的规律性,这种规律性并不一定要达到划分数据集的目的,也就是说不一定要“分类”。
有训练样本则考虑采用监督学习方法;无训练样本,则一定不能用监督学习方法。
半监督学习:将大量的无类标签的样例加入到少量的有类标签的样本中一起训练来进行学习,期望能对学习性能起到改进的作用,由此产生了半监督学习。半监督学习避免了数据和资源的浪费,同时解决了监督学习的模型泛化能力不强和无监督学习的模型不精确等问题。
如照片识别就是很好的例子。在线相册可以指定识别同一个人的照片(无监督学习),当你把这些同一个人增加一个标签的后,新的有同一个人的照片就自动帮你加上标签了。
强化学习是一个非常与众不同的算法,它的学习系统能够观测环境,做出选择,执行操作并获得回报,或者是以负面回报的形式获得惩罚。它必须自行学习什么是最好的策略,从而随着时间推移获得最大的回报。
强化学习是一个非常与众不同的算法,它的学习系统能够观测环境,做出选择,执行操作并获得回报,或者是以负面回报的形式获得惩罚。它必须自行学习什么是最好的策略,从而随着时间推移获得最大的回报。
决策树(Desicion Tree)
节点:
4. 根节点:没有进边,只有出边,包含最初的,针对特征的提问。
5. 中间节点:既有进边也有出边,进边只有一条,出边可以很多条,都是针对特征的提问。
6. 叶子节点:有进边,无出边,每个叶子节点都是一个类别标签。
7. 子节点与父节点:两个相连的节点当中,更接近根节点的是父节点,另一个是子节点。
关键问题:
8. 找出最佳节点和分支
9. 如何让决策树适时停止生长,防止过拟合
对比:在图数据库当中,每个节点都是平等的,没有所谓的根节点的概念。
接下来看一个小例子来了解一下节点:
graph={
'A':['B','C'],
'B':['A','C','D'],
'C':['A','B','D','E'],
'D':['B','C','E','F'],
'E':['C','D'],
'F':['D']
}
用图像表示:
def BFS(graph,s):#graph图 s指的是开始结点
#需要一个队列
queue=[]
queue.append(s)
seen=set()#看是否访问过该结点
seen.add(s)
while (len(queue)>0):
vertex=queue.pop(0)#保存第一结点,并弹出,方便把他下面的子节点接入
nodes=graph[vertex]#子节点的数组
for w in nodes:
if w not in seen:#判断是否访问过,使用一个数组
queue.append(w)
seen.add(w)
print(vertex)
def DFS(graph,s):#图 s指的是开始结点
#需要一个队列
stack=[]
stack.append(s)
seen=set()#看是否访问过
seen.add(s)
while (len(stack)>0):
#拿出邻接点
vertex=stack.pop()#这里pop参数没有0了,最后一个元素
nodes=graph[vertex]
for w in nodes:
if w not in seen:#如何判断是否访问过,使用一个数组
stack.append(w)
seen.add(w)
print(vertex)
def DFS_2(graph, s): # graph是图,s是开始结点 stack = [] # 栈 stack.append(s) # 开始结点入栈 v = set() v.add(s) # 无序添加 # print(s, end=' ') flag = 0 # 标记 while len(stack) > 0: # 栈非空 flag = 0 vertex = stack[-1] # 查看尾元素 nodes = graph[vertex] # 访问结点相连的结点列表 for w in nodes: if w not in v: stack.append(w) # 未被访问的相连的下一个结点入栈 v.add(w) # 标记已访问 flag = 1 # 存在未被访问的相连结点 # print(w, end=' ') print(vertex + '->' + w) break if flag == 0: # 不存在未被访问的相连结点,回溯 stack.pop()
以节点‘E’为例子,来说明定义的三个函数的例子:
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split #训练集与测试集分割
wine=load_wine()
wine.target
wine.data
import pandas as pd
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
from sklearn.model_selection import train_test_split
# 利用红酒代码
Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)
# 30%作为测试集,且这里参数的顺序不要改变,系统会自动进行训练集和测试集的划分
wine.feature_names # 特征名称
wine.target_names # 标签名称
最佳节点和最佳分枝方法衡量指标:不纯度。不纯度越低,最训练集的拟合越好。决策树有不同的算法:
Criterion这个参数正是用来决定不纯度计算方法的。sklearn提供了两张选择:
【1】输入“entropy”,使用信息熵
【2】输入“gini”,使用基尼系数
【3】信息增益:Information Gain=父节点信息熵-子节点信息熵
【4】信息增益率
三步骤:
使用信息熵参数:
clf = tree.DecisionTreeClassifier(criterion="entropy") # 信息熵 # 实例化
clf = clf.fit(Xtrain, Ytrain) # 训练模型
score = clf.score(Xtest, Ytest) # 返回预测的准确度 accuracy
使用基尼系数参数:
clf = tree.DecisionTreeClassifier(criterion="gini") # 基尼系数
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
画图绘制决策树:
%matplotlib inline
import numpy as np
import pandas as pd
from scipy import stats, integrate
import seaborn as sns
import matplotlib.pyplot as plt
# seaborn中文乱码解决方案
from matplotlib.font_manager import FontProperties
myfont=FontProperties(fname=r'C:\Windows\Fonts\simhei.ttf',size=20)
sns.set(font=myfont.get_name(), color_codes=True)
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸'] #13个特征都使用了吗?
import graphviz
dot_data = tree.export_graphviz(clf
# ,out_file="Tree.dot"
,feature_names = feature_name
,class_names=["1","2","3"] #三分类
,filled=True
,rounded=True
# ,font_name="KaiTi"
)
graph = graphviz.Source(dot_data)
graph
利用python的graphviz直接得到决策树:
import graphviz
dot_data = tree.export_graphviz(clf
# ,out_file="Tree.dot"
,feature_names = wine.feature_names# feature_name
,class_names=["1","2","3"] #三分类
,filled=True
,rounded=True
# ,font_name="KaiTi"
)
graph = graphviz.Source(dot_data)
graph
clf.feature_importances_
显示重要程度:
[*zip(feature_name,clf.feature_importances_)]
clf = tree.DecisionTreeClassifier(criterion="entropy"
,random_state=3
# 当数据很少时,random_state只能为None,所有都要当成重要的
,splitter="random"
)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
score
(1)max_depth
限制树的最大深度,超过设定深度的树枝全部剪掉。
通过限制深度来限制过拟合。
这是用得最广泛的剪枝参数,在高维度低样本量时非常有效。决策树多生长一层,对样本量的需求会增加一倍,所以限制树深度能够有效地限制过拟合。在集成算法中也非常实用。实际使用时,建议从=3开始尝试,看看拟合的效果再决定是否增加设定深度。
(2)min_samples_leaf & min_samples_split
min_samples_leaf:一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生,或者,分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生
一般搭配max_depth使用,在回归树中有神奇的效果,可以让模型变得更加平滑。这个参数的数量设置得太小会引起过拟合,设置得太大就会阻止模型学习数据。一般来说,建议从=5开始使用。如果叶节点中含有的样本量变化很大,建议输入浮点数作为样本量的百分比来使用。同时,这个参数可以保证每个叶子的最小尺寸,可以在回归问题中避免低方差,过拟合的叶子节点出现。对于类别不多的分类问题,=1通常就是最佳选择。
min_samples_split限定,一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则分枝就不会发生。
(3)max_features& min_impurity_decrease
一般max_depth使用,用作树的”精修“
max_features限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。和max_depth异曲同工
max_features是用来限制高维度数据的过拟合的剪枝参数,但其方法比较暴力,是直接限制可以使用的特征数量而强行使决策树停下的参数,在不知道决策树中的各个特征的重要性的情况下,强行设定这个参数可能会导致模型学习不足。如果希望通过降维的方式防止过拟合,建议使用PCA,ICA或者特征选择模块中的降维算法。
min_impurity_decrease限制信息增益(父子节点之间的信息熵之差)的大小,信息增益小于设定数值的分枝不会发生。这是在0.19版本中更新的功能,在0.19版本之前时使用min_impurity_split。
clf = tree.DecisionTreeClassifier(criterion="entropy" ,random_state=30 ,splitter="random" ,max_depth=6 # ,min_samples_leaf=10 # ,min_samples_split=25 ) clf = clf.fit(Xtrain, Ytrain) dot_data = tree.export_graphviz(clf ,feature_names= feature_name ,class_names=["琴酒","雪莉","贝尔摩德"] ,filled=True ,rounded=True ) graph = graphviz.Source(dot_data) graph
【1】这里选择最大深度为6,max_depth=6
。
【2】注意此代码的规范化写法:将逗号写在前面,这样当需要注释参数的时候,就可以直接注释,而不用担心逗号不匹配的问题了
【3】得到的结果如下图,此时决策树有6层
此时的得分:
score=clf.score(Xtest,Ytest)
score
Xtrain.shape
# 修枝 clf = tree.DecisionTreeClassifier(criterion="gini" ,random_state=30 ,splitter="random" ,max_depth=6 #最大层数不超过6层 ,min_samples_leaf=10 # 表示叶子节点的样本数必须》=10 ,min_samples_split=25 # 表示如果样本小于25就不在继续分枝下去 ) clf = clf.fit(Xtrain, Ytrain) dot_data = tree.export_graphviz(clf ,feature_names= feature_name ,class_names=["琴酒","雪莉","贝尔摩德"] ,filled=True ,rounded=True ) graph = graphviz.Source(dot_data) graph
修改参数之后发现正确率下降了
信息熵:
# 使用学习曲线判断最佳深度——信息熵
import matplotlib.pyplot as plt
test = []
for i in range(10):
clf = tree.DecisionTreeClassifier(max_depth=i+1 #1-10层
,criterion="entropy"
,random_state=30
,splitter="random"
)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #分别计算测试集上的表现
test.append(score)
plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()
由下图可以看出:使用信息熵得到的最佳深度应该是3
# 使用学习曲线判断最佳深度——基尼系数
import matplotlib.pyplot as plt
test = []
for i in range(10):
clf = tree.DecisionTreeClassifier(max_depth=i+1 #1-10层
,criterion="gini" # 使用gini系数
,random_state=30
,splitter="random"
)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #分别计算测试集上的表现
test.append(score)
plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()
由下图可以看出:使用基尼系数得到的最佳深度应该是5
2. 使用学习曲线判断最佳的最小叶子节点样本个数
选取的最小样本从1到30
信息熵:
# 使用学习曲线判断最佳的最小叶子节点样本个数 # 选取的最小样本从1到30 import matplotlib.pyplot as plt plt.figure(figsize=(15,8)) test = [] for i in range(30): clf = tree.DecisionTreeClassifier(min_samples_leaf=i+1 #1-10层 ,criterion="entropy" # 使用gini系数 ,random_state=30 ,splitter="random" ) clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) #分别计算测试集上的表现 test.append(score) plt.plot(range(1,31),test,color="red",label="min_samples_leaf") plt.legend() plt.show()
基尼系数:
# 使用学习曲线判断最佳的最小叶子节点样本个数 # 选取的最小样本从1到30 import matplotlib.pyplot as plt plt.figure(figsize=(15,8)) test = [] for i in range(30): clf = tree.DecisionTreeClassifier(min_samples_leaf=i+1 #1-10层 ,criterion="gini" # 使用gini系数 ,random_state=30 ,splitter="random" ) clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) #分别计算测试集上的表现 test.append(score) plt.plot(range(1,31),test,color="red",label="min_samples_leaf") plt.legend() plt.show()
3. 使用学习曲线判断最佳的最小分枝样本数
这里如果直接按照最小叶子节点样本个数的方法,会报如下的错误,
因此要把min_samples_split对应的范围调整在0~1之间:
信息熵:
# 使用学习曲线判断最佳的最小分枝样本数 # 选取的最小样本从1到30 import matplotlib.pyplot as plt plt.figure(figsize=(15,8)) test = [] for i in range(30): clf = tree.DecisionTreeClassifier(min_samples_split=float(i+1)/100 #1-10层 ,criterion="entropy" # 使用gini系数 ,random_state=30 ,splitter="random" ) clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) #分别计算测试集上的表现 test.append(score) plt.plot(range(1,31),test,color="red",label="min_samples_split") plt.legend() plt.show()
基尼系数:
# 使用学习曲线判断最佳的最小分枝样本数 # 选取的最小样本从1到30 import matplotlib.pyplot as plt plt.figure(figsize=(15,8)) test = [] for i in range(30): clf = tree.DecisionTreeClassifier(min_samples_split=float(i+1)/100 #1-10层 ,criterion="gini" # 使用gini系数 ,random_state=30 ,splitter="random" ) clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) #分别计算测试集上的表现 test.append(score) plt.plot(range(1,31),test,color="red",label="max_depth") plt.legend() plt.show()
【1】class_weight & min_weight_fraction_leaf
完成样本标签平衡的参数。样本不平衡是指在一组数据集中,标签的一类天生占有很大的比例。
比如说,在银行要判断“一个办了信用卡的人是否会违约”,就是是vs否(1%:99%)的比例。这种分类状况下,即便模型什么也不做,全把结果预测成“否”,正确率也能有99%。
因此我们要使用class_weight
参数对样本标签进行一定的均衡,给少量的标签更多的权重,让模型更偏向少数类,向捕获少数类的方向建模。该参数默认None,此模式表示自动给与数据集中的所有标签相同的权重。
有了权重之后,样本量就不再是单纯地记录数目,而是受输入的权重影响了,因此这时候剪枝,就需要搭配min_weight_fraction_leaf
这个基于权重的剪枝参数来使用。
另请注意,基于权重的剪枝参数(例如min_weight_fraction_leaf
)将比不知道样本权重的标准(比如min_samples_leaf
)更少偏向主导类。如果样本是加权的,则使用基于权重的预修剪标准来更容易优化树结构,这确保叶节点至少包含样本权重的总和的一小部分。
【2】class_weight
目标类型的权重,其数据类型为dict或者列表内的dict,或者为"balanced"
【3】min_weight_fraction_leaf
权重剪枝参数,搭配目标权重使用,比min_samples_leaf更偏向于主导类
import matplotlib.pyplot as plt plt.figure(figsize=(15,8)) test = [] for i in range(10): clf = tree.DecisionTreeClassifier(max_depth=i+1 #1-10层 ,criterion="entropy" ,random_state=30 ,splitter="random" ,class_weight="balanced" ,min_weight_fraction_leaf=0.005 ) clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) #分别计算测试集上的表现 test.append(score) plt.plot(range(1,11),test,color="red",label="max_depth") plt.legend() plt.show()
属性是在模型训练之后,能够调用查看的模型的各种性质。对决策树来说,最重要的是feature_importances_
,能够查看各个特征对模型的重要性。
sklearn中许多算法的接口都是相似的,比如之前已经用到的fit
和score
,几乎对每个算法都可以使用。
除了这两个接口之外,决策树最常用的接口还有apply
和predict
。
【1】apply
中输入测试集返回每个测试样本所在的叶子节点的索引。
【2】predict
输入测试集返回每个测试样本的标签。
所有接口中要求输入X_train
和X_test
的部分,输入的特征矩阵必须至少是一个二维矩阵。sklearn不接受任何一维矩阵作为特征矩阵被输入。
如果你的数据的确只有一个特征,那必须用reshape(-1,1)
来给矩阵增维;如果你的数据只有一个特征和一个样本,使用reshape(1,-1)
来给你的数据增维。
Xtest.shape
clf
八个参数:Criterion,两个随机性相关的参数(random_state,splitter),五个剪枝参数(max_depth,
min_samples_split,min_samples_leaf,max_feature,min_impurity_decrease)
一个属性:feature_importances_
四个接口:fit(拟合),score(评分),apply,predict(样本预测)
回归树衡量分枝质量的指标,支持的标准有三种:
【1】使用均方误差MSE,父节点和叶子节点之间的均方误差的差额将被用来作为特征选择的标准,这种方法通过使用叶子结点的均值来最小化损失。
【2】在回归树当中,MSE不仅是我们分枝质量衡量指标,也是我们最常用的衡量回归树回归质量的指标,当我们在使用交叉验证,或者其他方式获取回归树的结果时,我们往往选择均方误差作为评估。
【3】MSE的本质其实是样本真实数据与回归结果的差异。
CART算法:Classification And Regression Tree
CART,分类与回归树,是一个二分类法,结点的内部特征取值只有是与否。
回归树就是将特定的空间划分为若干个单元,每个特定的单元都有特定的输出。
因为只有是与否两个取值,因此是平行于坐标轴的。
使用波士顿房价的数据:
#简单用法——波士顿房价
from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeRegressor
boston = load_boston()
regressor = DecisionTreeRegressor(random_state=0)
cross_val_score(regressor, boston.data, boston.target, cv=10,scoring = "neg_mean_squared_error")
一维回归的图像绘制
# 一维回归的图像绘制
from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeRegressor
boston.data.shape
实例化,得到第一次交叉验证的平均值
regressor = DecisionTreeRegressor(random_state=0) #实例化
cross_val_score(regressor, boston.data, boston.target, cv=10).mean()
#### 01 导入库
import numpy as np
from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt
创建含有噪声的正弦曲线
先创建一组随机的,分布在0~5上的横坐标轴的取值(x),然后将这一组值放到sin函数中去生成纵坐标的值(y),接着再到y上去添加噪声。全程使用numpy库来生成这个正弦曲线。
rng = np.random.RandomState(1)
X = np.sort(5 * rng.rand(80,1), axis=0)
y = np.sin(X).ravel()
y[::5] += 3 * (0.5 - rng.rand(16)) #噪声
np.random.random((2,1))
np.random.random((2,1)).ravel() # ravel将多维数组变成一维数组
np.random.random((2,1)).ravel().shape
plt.figure()
plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data")
将这句话注释掉,则绘制出来的就是没有噪声的正弦曲线
# y[::5] += 3 * (0.5 - rng.rand(16)) #噪声
#### 03 实例化&训练模型
#创建两个模型,在不同拟合情况下的观察
regr_1 = DecisionTreeRegressor(max_depth=1) # 最大深度为2
regr_2 = DecisionTreeRegressor(max_depth=3)
regr_1.fit(X, y) # y是存在噪声的
regr_2.fit(X, y)
# (4)测试集导入模型,预测结果
X_test = np.arange(0.0, 5.0, 0.01)[:, np.newaxis]
y_1 = regr_1.predict(X_test)
y_2 = regr_2.predict(X_test)
#(5)绘制图像
plt.figure(figsize=(16,13))
plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data")
plt.plot(X_test, y_1, color="cornflowerblue",label="max_depth=1", linewidth=2)
plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=3", linewidth=2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。