转载: https://blog.csdn.net/fontthrone/article/details/78824242
<div id="article_content" class="article_content clearfix csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post">
<div class="article-copyright">
版权声明:如果您觉得本文不错,麻烦鼠标右转点下赞,谢谢.如果有什么问题,请直接留言.转载请标明作者与本文链接: https://blog.csdn.net/FontThrone/article/details/78824242 </div>
<div class="markdown_views">
<!-- flowchart 箭头图标 勿删 -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg>
<h2 id="决策树"><a name="t0"></a>决策树</h2>
<h3 id="决策树简介"><a name="t1"></a>决策树简介</h3>
<p>决策树是一种使用if-then-else的决策规则的监督学习方法.</p>
<p><strong>其三要素为,枝节点,叶节点与分支条件,同时为了减少过拟合还有剪枝方法</strong> <br>
<strong>为了便于记忆,可以称其为一方法三要素</strong></p>
<h2 id="决策树的优势"><a name="t2"></a>决策树的优势</h2>
<ul>
<li>便于理解和解释。树的结构可以可视化出来。</li>
<li>训练需要的数据少。其他机器学习模型通常需要数据规范化,比如构建虚拟变量和移除缺失值,不过请注意,这种模型不支持缺失值。</li>
<li>由于训练决策树的数据点的数量导致了决策树的使用开销呈指数分布(训练树模型的时间复杂度是参与训练数据点的对数值)。</li>
<li>能够处理数值型数据和分类数据。其他的技术通常只能用来专门分析某一种变量类型的数据集。详情请参阅算法。</li>
<li>能够处理多路输出的问题。</li>
<li>使用白盒模型。如果某种给定的情况在该模型中是可以观察的,那么就可以轻易的通过布尔逻辑来解释这种情况。相比之下,在黑盒模型中的结果就是很难说明清 楚地。</li>
<li>可以通过数值统计测试来验证该模型。这对事解释验证该模型的可靠性成为可能。</li>
<li>即使该模型假设的结果与真实模型所提供的数据有些违反,其表现依旧良好。</li>
</ul>
<h3 id="决策树的缺点"><a name="t3"></a>决策树的缺点</h3>
<ul>
<li>决策树模型容易产生一个过于复杂的模型,这样的模型对数据的泛化性能会很差。这就是所谓的过拟合.一些策略像剪枝、设置叶节点所需的最小样本数或设置数的最大深度是避免出现 该问题最为有效地方法。</li>
<li>决策树可能是不稳定的,因为数据中的微小变化可能会导致完全不同的树生成。这个问题可以通过决策树的集成来得到缓解</li>
<li>在多方面性能最优和简单化概念的要求下,学习一棵最优决策树通常是一个NP难问题。因此,实际的决策树学习算法是基于启发式算法,例如在每个节点进 行局部最优决策的贪心算法。这样的算法不能保证返回全局最优决策树。这个问题可以通过集成学习来训练多棵决策树来缓解,这多棵决策树一般通过对特征和样本有放回的随机采样来生成。</li>
<li>有些概念很难被决策树学习到,因为决策树很难清楚的表述这些概念。例如XOR,奇偶或者复用器的问题。</li>
<li>如果某些类在问题中占主导地位会使得创建的决策树有偏差。因此,我们建议在拟合前先对数据集进行平衡。</li>
</ul>
<h3 id="分类"><a name="t4"></a>分类</h3>
<pre class="prettyprint" name="code"><code class="language-python hljs has-numbering">%matplotlib inline
<span class="hljs-keyword">from</span> sklearn <span class="hljs-keyword">import</span> tree
X = [[<span class="hljs-number">0</span>, <span class="hljs-number">0</span>], [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>]]
Y = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>]
clf = tree.DecisionTreeClassifier()
clf = clf.fit(X, Y)</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre>
<p><strong>predict the class of samples</strong></p>
<pre class="prettyprint" name="code"><code class="language-python hljs has-numbering">print(clf.predict([[<span class="hljs-number">2</span>,<span class="hljs-number">2</span>]]))</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre>
<pre class="prettyprint"><code class="has-numbering">[1]
</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre>
<p><strong>show the probability and log_probability of each class be predicted</strong></p>
<pre class="prettyprint" name="code"><code class="language-python hljs has-numbering">print(clf.predict_proba([[<span class="hljs-number">2</span>,<span class="hljs-number">2</span>]]))
print(clf.predict_log_proba([[<span class="hljs-number">2</span>,<span class="hljs-number">2</span>]]))</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre>
<pre class="prettyprint"><code class="has-numbering">[[ 1. 0. 0.]]
[[ 0. -inf -inf]]
/home/fonttian/anaconda3/lib/python3.6/site-packages/sklearn/tree/tree.py:864: RuntimeWarning: divide by zero encountered in log
return np.log(proba)
</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre>
<p>在刚开始的时候我提出了三要素一方法,其中三要素不仅对应着决策树的构成方式,还对应着一方法也就是剪枝</p>
<p>决策树因为其实算法的特殊性,除非存在不同的两个点或者以上在完全一致的特征下,分类标签不一致的情况, <br>
决策树可以做到对数据集的完全拟合.也正是决策树的这一特性,使得完全的决策树会产生严重的过拟合.</p>
<p>因此我们需要减掉过多的分支,从而提高决策树的泛化能力.其中的方法虽然很多,但是整体而言都是围绕着枝节点与叶节点展开的</p>
<p>在sklearn中我们可以用来提高决策树泛化能力的超参数主要有 <br>
- max_depth:树的最大深度,也就是说当树的深度到达max_depth的时候无论还有多少可以分支的特征,决策树都会停止运算. <br>
- min_samples_split: 分裂所需的最小数量的节点数.当叶节点的样本数量小于该参数后,则不再生成分支.该分支的标签分类以该分支下标签最多的类别为准 <br>
- min_samples_leaf; 一个分支所需要的最少样本数,如果在分支之后,某一个新增叶节点的特征样本数小于该超参数,则退回,不再进行剪枝.退回后的叶节点的标签以该叶节点中最多的标签你为准 <br>
- min_weight_fraction_leaf: 最小的权重系数 <br>
- max_leaf_nodes:最大叶节点数,None时无限制,取整数时,忽略max_depth</p>
<h3 id="分支方式"><a name="t5"></a>分支方式</h3>
<p>对于决策树而言,常见的决策树分支方式一共有三种,前两种是基于信息熵的,ID3(信息增益),C4.5(信息增益比),以及基于基尼系数的CART决策树</p>
<p>但是因为到目前为止,sklearn中只实现了ID3与CART决策树,所以我们暂时只能使用这两种决策树,分支方式由超参数criterion决定: <br>
- gini:默认参数,基于基尼系数 <br>
- entropy: 基于信息熵,也就是我们的ID3</p>
<p><em>* 下面在鸢尾花数据集上使用分类决策树 *</em></p>
<p><em>* 加载数据 *</em></p>
<pre class="prettyprint" name="code"><code class="language-python hljs has-numbering"><span class="hljs-keyword">from</span> sklearn <span class="hljs-keyword">import</span> datasets,model_selection
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load_data</span><span class="hljs-params">()</span>:</span>
iris=datasets.load_iris() <span class="hljs-comment"># scikit-learn 自带的 iris 数据集</span>
X_train=iris.data
y_train=iris.target
<span class="hljs-keyword">return</span> model_selection.train_test_split(X_train, y_train,test_size=<span class="hljs-number">0.25</span>,random_state=<span class="hljs-number">0</span>,stratify=y_train)</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre>
<p><em>* 使用基尼(CART决策树)与信息熵(ID3)进行测试,可以发现在iris dataset上,gini的表现要好一些 *</em></p>
<p><em>* 同时可以发现,对于决策树而言,完全拟合数据并不困难,最多只需要 lg(n_samples)即可,对于iris的150个样本而言,只需要max_depth就足够了,但是max_depth的过度提高一般代表着泛化能力的降低 *</em></p>
<pre class="prettyprint" name="code"><code class="language-python hljs has-numbering">X_train,X_test,y_train,y_test=load_data()
criterions=[<span class="hljs-string">'gini'</span>,<span class="hljs-string">'entropy'</span>]
<span class="hljs-keyword">for</span> criterion <span class="hljs-keyword">in</span> criterions:
clf = DecisionTreeClassifier(criterion=criterion)
clf.fit(X_train, y_train)
print(criterion,<span class="hljs-string">"Training score:%f"</span>%(clf.score(X_train,y_train)))
print(criterion,<span class="hljs-string">"Testing score:%f"</span>%(clf.score(X_test,y_test)))</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li></ul></pre>
<pre class="prettyprint"><code class="has-numbering">gini Training score:1.000000
gini Testing score:0.947368
entropy Training score:1.000000
entropy Testing score:0.947368
</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre>
<p><em>* 下面是绘制的train_error 与test_error曲线,你也可容易通过修改其他几个可以控制枝节点与叶节点的超参数对决策树的生成进行控制 *</em> </p>
<pre class="prettyprint" name="code"><code class="language-python hljs has-numbering">maxdepth = <span class="hljs-number">40</span>
X_train,X_test,y_train,y_test=load_data()
depths=np.arange(<span class="hljs-number">1</span>,maxdepth)
training_scores=[]
testing_scores=[]
<span class="hljs-keyword">for</span> depth <span class="hljs-keyword">in</span> depths:
clf = DecisionTreeClassifier(max_depth=depth)
clf.fit(X_train, y_train)
training_scores.append(clf.score(X_train,y_train))
testing_scores.append(clf.score(X_test,y_test))
<span class="hljs-comment">## 绘图</span>
fig=plt.figure()
ax=fig.add_subplot(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>)
ax.plot(depths,training_scores,label=<span class="hljs-string">"traing score"</span>,marker=<span class="hljs-string">'o'</span>)
ax.plot(depths,testing_scores,label=<span class="hljs-string">"testing score"</span>,marker=<span class="hljs-string">'*'</span>)
ax.set_xlabel(<span class="hljs-string">"maxdepth"</span>)
ax.set_ylabel(<span class="hljs-string">"score"</span>)
ax.set_title(<span class="hljs-string">"Decision Tree Classification"</span>)
ax.legend(framealpha=<span class="hljs-number">0.5</span>,loc=<span class="hljs-string">'best'</span>)
plt.show()</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li></ul></pre>
<p><img src="https://img-blog.csdn.net/20171217115256082" alt="不同最大深度的gini决策树的测试训练误差曲线" title=""></p>
<h3 id="参考资料"><a name="t6"></a>参考资料</h3>
<ul>
<li><a href="http://scikit-learn.org/stable/modules/tree.html" rel="nofollow" target="_blank">sklearn官方文档:决策树</a></li>
</ul> </div>
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-8cccb36679.css" rel="stylesheet">
</div>