0 的就是 A 类, x+y-2<0 的就是 B 类。
+
+以此类推,还有三维的,四维的,N维的 属性的分类,这样构造的也许就不是直线,而是平面,超平面。
+
+一个三维的函数分类 :x+y+z-2=0,这就是个分类的平面了。
+
+有时候,分类的那条线不一定是直线,还有可能是曲线,我们通过某些函数来转换,就可以转化成刚才的哪种多维的分类问题,这个就是核函数的思想。
+
+例如:分类的函数是个圆形 x^2+y^2-4=0 。这个时候令 x^2=a ; y^2=b ,还不就变成了a+b-4=0 这种直线问题了。
+
+这就是支持向量机的思想。
+
+### 3、引用 [@胡KF](https://www.zhihu.com/people/hu-kf/answers) 大佬的回答(这个需要一些数学知识):
+
+如图的例子,(训练集)红色点是我们已知的分类1,(训练集)蓝色点是已知的分类2,我们想寻找一个分界超平面(图中绿线)(因为示例是二维数据点,所以只是一条线,如果数据是三维的就是平面,如果是三维以上就是超平面)把这两类完全分开,这样的话再来一个样本点需要我们预测的话,我们就可以根据这个分界超平面预测出分类结果。
+
+
+
+那我们如何选择这个分类超平面呢?从数学上说,超平面的公式是,也就是说如何选取这个 (是个向量)。
+
+传统方法是根据最小二乘错误法(least squared error),首先随便定选取一个随机平面,也就是随机选取  和 ,然后想必会在训练集中产生大量的错误分类,也就是说, 结果应该大于 0 的时候小于 0 ,应该小于 0 的时候大于 0 。这时候有一个错误损失,也就是说对于所有错误的分类,他们的平方和(least squared error) 为:  , 最小二乘法的目标就是让这个值趋于最小,对  求导取 0 ,采用梯度下降算法,可以求出错误平方和的极值,求出最优的  ,也就是求出最优的超平面。(可以证明,如果基函数是指数族函数,求出的超平面是全局最优的)。
+
+那我们 SVM 算法的思路是怎样的呢?
+
+不同于传统的最小二乘策略的思想,我们采用一种新的思路,这个分界面有什么样的特征呢?
+
+第一,它 “夹” 在两类样本点之间;第二,它离两类样本点中所有 “离它最近的点” ,都离它尽可能的远。如图所示:
+
+
+
+在虚线上的点,就是我们所找到的离分解超平面最近的样本点,X 类中找到了一个,O 类找到了两个。我们需要分类超平面离这三个样本点都尽可能的远,也就是说,它处在两条虚线的中间。这就是我们找到的分界超平面。
+
+另外,这里我们就可以解释什么是 “支持向量” 了,支持向量就是虚线上的离分类超平面最近的样本点,因为每一个样本点都是一个多维的向量,向量的每一个维度都是这个样本点的一个特征。比如在根据身高,体重,特征进行男女分类的时候,每一个人是一个向量,向量有两个维度,第一维是身高,第二维是体重。
+
+介绍完 SVM 的基本思想,我们来探讨一下如何用数学的方法进行 SVM 分类。
+
+首先我们需要把刚刚说的最大间隔分类器的思想用数学公式表达出来。先定义几何间隔的概念,几何间隔就是在多维空间中一个多维点到一个超平面的距离,根据向量的知识可以算出来:
+
+
+
+然后对于所有的支持向量,使他们到超平面  的距离最大,也就是
+
+
+
+因为对于所有支持向量,他们  的值都是一定的,我们假设恒等于 1 ,那么上式变成了  ,并且对于所有的样本点,满足  的约束,因此,可以利用拉格朗日乘数法计算出它的极值。也就是求出这个超平面。
+
+推导过程略为复杂,详细了解可以参考凸二次规划知识,结合 SMO 算法理解 SVM 计算超平面的详细过程。
+
+总之,在计算的过程中,我们不需要了解支持向量以外的其他样本点,只需要利用相对于所有样本点来说为数不多的支持向量,就可以求出分类超平面,计算复杂度大为降低。
+
+### 4、引用知乎 [@靠靠靠谱](https://www.zhihu.com/people/kao-kao-kao-pu/answers) 大佬的理解(这个需要的数学知识更加厉害一点):
+
+先看思维导图:
+
+* 左边是求解基本的SVM问题
+* 右边是相关扩展
+
+
+
+什么是 SVM ?
+
+Support Vector Machine, 一个普通的 SVM 就是一条直线罢了,用来完美划分 linearly separable 的两类。但这又不是一条普通的直线,这是无数条可以分类的直线当中最完美的,因为它恰好在两个类的中间,距离两个类的点都一样远。而所谓的 Support vector 就是这些离分界线最近的『点』。如果去掉这些点,直线多半是要改变位置的。可以说是这些 vectors (主,点点) support (谓,定义)了 machine (宾,分类器)...
+
+
+
+所以谜底就在谜面上啊朋友们,只要找到了这些最靠近的点不就找到了 SVM 了嘛。
+
+如果是高维的点,SVM 的分界线就是平面或者超平面。其实没有差,都是一刀切两块,我就统统叫直线了。
+
+怎么求解 SVM ?
+
+关于这条直线,我们知道
+
+(1)它在离两边一样远,(2)最近距离就是到support vector,其他距离只能更远。
+
+于是自然而然可以得到重要表达 I. direct representation
+
+
+
+(可以把 margin 看作是 boundary 的函数,并且想要找到使得是使得 margin 最大化的boundary,而 margin(*) 这个函数是:输入一个 boundary ,计算(正确分类的)所有苹果和香蕉中,到 boundary 的最小距离。)
+
+又有最大又有最小看起来好矛盾。实际上『最大』是对这个整体使用不同 boundary 层面的最大,『最小』是在比较『点』的层面上的最小。外层在比较 boundary 找最大的 margin ,内层在比较点点找最小的距离。
+
+其中距离,说白了就是点到直线的距离;只要定义带正负号的距离,是 {苹果+1} 面为正 {香蕉-1} 面为负的距离,互相乘上各自的 label  ,就和谐统一民主富强了。
+
+
+
+到这里为止已经说完了所有关于SVM的直观了解,如果不想看求解,可以跳过下面一大段直接到 objective function 。
+
+直接表达虽然清楚但是求解无从下手。做一些简单地等价变换(分母倒上来)可以得到 II. canonical representation (敲黑板)
+
+
+
+要得到 III. dual representation 之前需要大概知道一下拉格朗日乘子法 (method of lagrange multiplier),它是用在有各种约束条件(各种 "subject to" )下的目标函数,也就是直接可以求导可以引出 dual representation(怎么还没完摔)
+
+
+
+稍微借用刚刚数学表达里面的内容看个有趣的东西:
+
+还记得我们怎么预测一个新的水果是苹果还是香蕉吗?我们代入到分界的直线里,然后通过符号来判断。
+
+刚刚w已经被表达出来了也就是说这个直线现在变成了: 
+
+看似仿佛用到了所有的训练水果,但是其中  的水果都没有起到作用,剩下的就是小部分靠边边的 Support vectors 呀。
+
+III. dual representation
+
+
+
+如果香蕉和苹果不能用直线分割呢?
+
+
+
+Kernel trick.
+
+其实用直线分割的时候我们已经使用了 kernel ,那就是线性 kernel , 
+
+如果要替换 kernel 那么把目标函数里面的内积全部替换成新的 kernel function 就好了,就是这么简单。
+
+第一个武侠大师的比喻已经说得很直观了,低维非线性的分界线其实在高维是可以线性分割的,可以理解为——『你们是虫子!』分得开个p...(大雾)
+
+如果香蕉和苹果有交集呢?
+
+
+
+
+
+如果还有梨呢?
+
+
+
+可以每个类别做一次 SVM:是苹果还是不是苹果?是香蕉还是不是香蕉?是梨子还是不是梨子?从中选出可能性最大的。这是 one-versus-the-rest approach。
+
+也可以两两做一次 SVM:是苹果还是香蕉?是香蕉还是梨子?是梨子还是苹果?最后三个分类器投票决定。这是 one-versus-one approace。
+
+但这其实都多多少少有问题,比如苹果特别多,香蕉特别少,我就无脑判断为苹果也不会错太多;多个分类器要放到一个台面上,万一他们的 scale 没有在一个台面上也未可知。
+
+课后题:
+1、vector 不愿意 support 怎么办?
+2、苹果好吃还是香蕉好吃?
+
+最后送一张图我好爱哈哈哈 (Credit: Burr Settles)
+
+
+
+[1] Bishop C M. Pattern recognition[J]. Machine Learning, 2006, 128.
+[2] Friedman J, Hastie T, Tibshirani R. The elements of statistical learning[M]. Springer, Berlin: Springer series in statistics, 2001.
+[3] James G, Witten D, Hastie T, et al. An introduction to statistical learning[M]. New York: springer, 2013.
+
+
+## 理解和应用
+
+### 1、DataMining (数据挖掘)
+做数据挖掘应用的一种重要算法,也是效果最好的分类算法之一。
+
+举个例子,就是尽量把样本中的从更高纬度看起来在一起的样本合在一起,比如在一维(直线)空间里的样本从二维平面上可以分成不同类别,而在二维平面上分散的样本如果从第三维空间上来看就可以对他们做分类。
+
+支持向量机算法目的是找出最优超平面,使分类间隔最大,要求不但正确分开,而且使分类间隔最大,在两类样本中离分类平面最近且位于平行于最优超平面的超平面上的点就是支持向量,为找到最优超平面只要找到所有支持向量即可。
+
+对于非线性支持向量机,通常做法是把线性不可分转化成线性可分,通过一个非线性映射将低维输入空间中的数据特性映射到高维线性特征空间中,在高维空间中求线性最优分类超平面。
+
+### 2、scikit-learn (sklearn)
+
+SVM 的基本原理基本上已经说的差不多了,下面咱们就来看看 SVM 在实际应用该如何使用了。幸运的是,在 python 下面,sklearn 提供了一个非常好用的机器学习算法,我们调用相关的包就好啦。
+
+
+
+
+## 小结
+
+学习 SVM 需要有耐心,当初研究这个部分的时候,炼哥(github [jiangzhonglian](https://github.com/jiangzhonglian)),法超大佬(github [geekidentity](https://github.com/geekidentity)),羊三大佬(github [sheepmen](https://github.com/sheepmen)),庭哥(github [wangyangting](https://github.com/wangyangting))都花费了好长时间,我只能躲在角落发抖....
\ No newline at end of file
diff --git a/images/6.SVM/alpha.png b/images/6.SVM/alpha.png
new file mode 100644
index 00000000..d869e752
Binary files /dev/null and b/images/6.SVM/alpha.png differ
diff --git a/images/6.SVM/b.png b/images/6.SVM/b.png
new file mode 100644
index 00000000..1e50d87e
Binary files /dev/null and b/images/6.SVM/b.png differ
diff --git a/images/6.SVM/hu_1.jpg b/images/6.SVM/hu_1.jpg
new file mode 100644
index 00000000..df43eae8
Binary files /dev/null and b/images/6.SVM/hu_1.jpg differ
diff --git a/images/6.SVM/hu_10.png b/images/6.SVM/hu_10.png
new file mode 100644
index 00000000..c82ae06c
Binary files /dev/null and b/images/6.SVM/hu_10.png differ
diff --git a/images/6.SVM/hu_2.jpg b/images/6.SVM/hu_2.jpg
new file mode 100644
index 00000000..a655b4c0
Binary files /dev/null and b/images/6.SVM/hu_2.jpg differ
diff --git a/images/6.SVM/hu_3.png b/images/6.SVM/hu_3.png
new file mode 100644
index 00000000..70d2895b
Binary files /dev/null and b/images/6.SVM/hu_3.png differ
diff --git a/images/6.SVM/hu_4.png b/images/6.SVM/hu_4.png
new file mode 100644
index 00000000..9c2f1600
Binary files /dev/null and b/images/6.SVM/hu_4.png differ
diff --git a/images/6.SVM/hu_5.png b/images/6.SVM/hu_5.png
new file mode 100644
index 00000000..3b283c50
Binary files /dev/null and b/images/6.SVM/hu_5.png differ
diff --git a/images/6.SVM/hu_6.png b/images/6.SVM/hu_6.png
new file mode 100644
index 00000000..b30e48d6
Binary files /dev/null and b/images/6.SVM/hu_6.png differ
diff --git a/images/6.SVM/hu_7.png b/images/6.SVM/hu_7.png
new file mode 100644
index 00000000..c82ae06c
Binary files /dev/null and b/images/6.SVM/hu_7.png differ
diff --git a/images/6.SVM/hu_8.png b/images/6.SVM/hu_8.png
new file mode 100644
index 00000000..d607f931
Binary files /dev/null and b/images/6.SVM/hu_8.png differ
diff --git a/images/6.SVM/hu_9.png b/images/6.SVM/hu_9.png
new file mode 100644
index 00000000..32d96ab6
Binary files /dev/null and b/images/6.SVM/hu_9.png differ
diff --git a/images/6.SVM/k_1.jpg b/images/6.SVM/k_1.jpg
new file mode 100644
index 00000000..37268b78
Binary files /dev/null and b/images/6.SVM/k_1.jpg differ
diff --git a/images/6.SVM/k_10.png b/images/6.SVM/k_10.png
new file mode 100644
index 00000000..5002d4dc
Binary files /dev/null and b/images/6.SVM/k_10.png differ
diff --git a/images/6.SVM/k_11.png b/images/6.SVM/k_11.png
new file mode 100644
index 00000000..59cd9827
Binary files /dev/null and b/images/6.SVM/k_11.png differ
diff --git a/images/6.SVM/k_12.png b/images/6.SVM/k_12.png
new file mode 100644
index 00000000..1a58471b
Binary files /dev/null and b/images/6.SVM/k_12.png differ
diff --git a/images/6.SVM/k_13.png b/images/6.SVM/k_13.png
new file mode 100644
index 00000000..57f76d8c
Binary files /dev/null and b/images/6.SVM/k_13.png differ
diff --git a/images/6.SVM/k_14.png b/images/6.SVM/k_14.png
new file mode 100644
index 00000000..de3fe640
Binary files /dev/null and b/images/6.SVM/k_14.png differ
diff --git a/images/6.SVM/k_15.png b/images/6.SVM/k_15.png
new file mode 100644
index 00000000..2546a540
Binary files /dev/null and b/images/6.SVM/k_15.png differ
diff --git a/images/6.SVM/k_16.png b/images/6.SVM/k_16.png
new file mode 100644
index 00000000..e4fd1322
Binary files /dev/null and b/images/6.SVM/k_16.png differ
diff --git a/images/6.SVM/k_2.jpg b/images/6.SVM/k_2.jpg
new file mode 100644
index 00000000..e35ea53d
Binary files /dev/null and b/images/6.SVM/k_2.jpg differ
diff --git a/images/6.SVM/k_3.jpg b/images/6.SVM/k_3.jpg
new file mode 100644
index 00000000..78866ce1
Binary files /dev/null and b/images/6.SVM/k_3.jpg differ
diff --git a/images/6.SVM/k_4.jpg b/images/6.SVM/k_4.jpg
new file mode 100644
index 00000000..8296b995
Binary files /dev/null and b/images/6.SVM/k_4.jpg differ
diff --git a/images/6.SVM/k_5.jpg b/images/6.SVM/k_5.jpg
new file mode 100644
index 00000000..00079596
Binary files /dev/null and b/images/6.SVM/k_5.jpg differ
diff --git a/images/6.SVM/k_6.png b/images/6.SVM/k_6.png
new file mode 100644
index 00000000..475a1d88
Binary files /dev/null and b/images/6.SVM/k_6.png differ
diff --git a/images/6.SVM/k_7.png b/images/6.SVM/k_7.png
new file mode 100644
index 00000000..0bd81d41
Binary files /dev/null and b/images/6.SVM/k_7.png differ
diff --git a/images/6.SVM/k_8.png b/images/6.SVM/k_8.png
new file mode 100644
index 00000000..cc7e38b0
Binary files /dev/null and b/images/6.SVM/k_8.png differ
diff --git a/images/6.SVM/k_9.png b/images/6.SVM/k_9.png
new file mode 100644
index 00000000..e5ec1209
Binary files /dev/null and b/images/6.SVM/k_9.png differ
diff --git a/images/6.SVM/ml_map.png b/images/6.SVM/ml_map.png
new file mode 100644
index 00000000..73ebd9c0
Binary files /dev/null and b/images/6.SVM/ml_map.png differ
diff --git a/images/6.SVM/story_1.png b/images/6.SVM/story_1.png
new file mode 100644
index 00000000..6d46680f
Binary files /dev/null and b/images/6.SVM/story_1.png differ
diff --git a/images/6.SVM/story_2.png b/images/6.SVM/story_2.png
new file mode 100644
index 00000000..16c6e0d4
Binary files /dev/null and b/images/6.SVM/story_2.png differ
diff --git a/images/6.SVM/story_3.png b/images/6.SVM/story_3.png
new file mode 100644
index 00000000..f52604df
Binary files /dev/null and b/images/6.SVM/story_3.png differ
diff --git a/images/6.SVM/story_4.png b/images/6.SVM/story_4.png
new file mode 100644
index 00000000..b00ef9e6
Binary files /dev/null and b/images/6.SVM/story_4.png differ
diff --git a/images/6.SVM/story_5.png b/images/6.SVM/story_5.png
new file mode 100644
index 00000000..deeca4b2
Binary files /dev/null and b/images/6.SVM/story_5.png differ
diff --git a/images/6.SVM/story_6.png b/images/6.SVM/story_6.png
new file mode 100644
index 00000000..b524a968
Binary files /dev/null and b/images/6.SVM/story_6.png differ
diff --git a/images/6.SVM/story_7.png b/images/6.SVM/story_7.png
new file mode 100644
index 00000000..141c667a
Binary files /dev/null and b/images/6.SVM/story_7.png differ
diff --git a/images/6.SVM/story_8.png b/images/6.SVM/story_8.png
new file mode 100644
index 00000000..b3a927a5
Binary files /dev/null and b/images/6.SVM/story_8.png differ
diff --git a/images/6.SVM/supportVector.png b/images/6.SVM/supportVector.png
new file mode 100644
index 00000000..bb63e161
Binary files /dev/null and b/images/6.SVM/supportVector.png differ
diff --git a/images/6.SVM/supportVector公式.jpg b/images/6.SVM/supportVector公式.jpg
new file mode 100644
index 00000000..401f66dd
Binary files /dev/null and b/images/6.SVM/supportVector公式.jpg differ
diff --git a/images/6.SVM/svm_2.png b/images/6.SVM/svm_2.png
new file mode 100644
index 00000000..deeca4b2
Binary files /dev/null and b/images/6.SVM/svm_2.png differ
diff --git a/images/6.SVM/w.png b/images/6.SVM/w.png
new file mode 100644
index 00000000..3b4e3413
Binary files /dev/null and b/images/6.SVM/w.png differ
diff --git a/src/python/8.Predictive numerical data regression/regression.py b/src/python/8.PredictiveNumericalDataRegression/regression.py
similarity index 99%
rename from src/python/8.Predictive numerical data regression/regression.py
rename to src/python/8.PredictiveNumericalDataRegression/regression.py
index 59304c5a..16f2bd00 100644
--- a/src/python/8.Predictive numerical data regression/regression.py
+++ b/src/python/8.PredictiveNumericalDataRegression/regression.py
@@ -66,7 +66,7 @@ def standRegres(xArr,yArr):
# 书中的公式,求得w的最优解
ws = xTx.I * (xMat.T*yMat)
return ws
-
+
# 局部加权线性回归
def lwlr(testPoint,xArr,yArr,k=1.0):
'''
diff --git a/src/python/8.PredictiveNumericalDataRegression/sklearn-regression-demo.py b/src/python/8.PredictiveNumericalDataRegression/sklearn-regression-demo.py
new file mode 100644
index 00000000..ffde9b74
--- /dev/null
+++ b/src/python/8.PredictiveNumericalDataRegression/sklearn-regression-demo.py
@@ -0,0 +1,191 @@
+#!/usr/bin/python
+# coding:utf8
+
+'''
+Created on Jan 8, 2011
+Update on 2017-05-18
+@author: Peter Harrington/小瑶
+《机器学习实战》更新地址:https://github.com/apachecn/MachineLearning
+'''
+
+
+# Isotonic Regression 等式回归
+print(__doc__)
+
+# Author: Nelle Varoquaux
+# Alexandre Gramfort
+# License: BSD
+
+import numpy as np
+import matplotlib.pyplot as plt
+from matplotlib.collections import LineCollection
+
+from sklearn.linear_model import LinearRegression
+from sklearn.isotonic import IsotonicRegression
+from sklearn.utils import check_random_state
+
+n = 100
+x = np.arange(n)
+rs = check_random_state(0)
+y = rs.randint(-50, 50, size=(n,)) + 50. * np.log(1 + np.arange(n))
+
+ir = IsotonicRegression()
+
+y_ = ir.fit_transform(x, y)
+
+lr = LinearRegression()
+lr.fit(x[:, np.newaxis], y) # 线性回归的 x 需要为 2d
+
+segments = [[[i, y[i]], [i, y_[i]]] for i in range(n)]
+lc = LineCollection(segments, zorder=0)
+lc.set_array(np.ones(len(y)))
+lc.set_linewidths(0.5 * np.ones(n))
+
+fig = plt.figure()
+plt.plot(x, y, 'r.', markersize=12)
+plt.plot(x, y_, 'g.-', markersize=12)
+plt.plot(x, lr.predict(x[:, np.newaxis]), 'b-')
+plt.gca().add_collection(lc)
+plt.legend(('Data', 'Isotonic Fit', 'Linear Fit'), loc='lower right')
+plt.title('Isotonic regression')
+plt.show()
+
+# Kernel ridge regression ( 内核岭回归 )
+
+# 2.1 Comparison of kernel ridge regression and SVR ( 内核岭回归与 SVR 的比较 )
+
+# Authors: Jan Hendrik Metzen
+# License: BSD 3 clause
+
+'''
+from __future__ import division
+import time
+
+import numpy as np
+
+from sklearn.svm import SVR
+from sklearn.model_selection import GridSearchCV
+from sklearn.model_selection import learning_curve
+from sklearn.kernel_ridge import KernelRidge
+import matplotlib.pyplot as plt
+
+rng = np.random.RandomState(0)
+
+# 生成样本数据
+X = 5 * rng.rand(10000, 1)
+y = np.sin(X).ravel()
+
+# 给目标增加噪音
+y[::5] += 3 * (0.5 - rng.rand(X.shape[0] // 5))
+
+X_plot = np.linspace(0, 5, 100000)[:, None]
+
+# Fit regression model ( 拟合 回归 模型 )
+train_size = 100
+svr = GridSearchCV(SVR(kernel='rbf', gamma=0.1), cv=5,
+ param_grid={"C": [1e0, 1e1, 1e2, 1e3],
+ "gamma": np.logspace(-2, 2, 5)})
+
+kr = GridSearchCV(KernelRidge(kernel='rbf', gamma=0.1), cv=5,
+ param_grid={"alpha": [1e0, 0.1, 1e-2, 1e-3],
+ "gamma": np.logspace(-2, 2, 5)})
+
+t0 = time.time()
+svr.fit(X[:train_size], y[:train_size])
+svr_fit = time.time() - t0
+print("SVR complexity and bandwidth selected and model fitted in %.3f s"
+ % svr_fit)
+
+t0 = time.time()
+kr.fit(X[:train_size], y[:train_size])
+kr_fit = time.time() - t0
+print("KRR complexity and bandwidth selected and model fitted in %.3f s"
+ % kr_fit)
+
+sv_ratio = svr.best_estimator_.support_.shape[0] / train_size
+print("Support vector ratio: %.3f" % sv_ratio)
+
+t0 = time.time()
+y_svr = svr.predict(X_plot)
+svr_predict = time.time() - t0
+print("SVR prediction for %d inputs in %.3f s"
+ % (X_plot.shape[0], svr_predict))
+
+t0 = time.time()
+y_kr = kr.predict(X_plot)
+kr_predict = time.time() - t0
+print("KRR prediction for %d inputs in %.3f s"
+ % (X_plot.shape[0], kr_predict))
+
+# 查看结果
+sv_ind = svr.best_estimator_.support_
+plt.scatter(X[sv_ind], y[sv_ind], c='r', s=50, label='SVR support vectors',
+ zorder=2)
+plt.scatter(X[:100], y[:100], c='k', label='data', zorder=1)
+plt.hold('on')
+plt.plot(X_plot, y_svr, c='r',
+ label='SVR (fit: %.3fs, predict: %.3fs)' % (svr_fit, svr_predict))
+plt.plot(X_plot, y_kr, c='g',
+ label='KRR (fit: %.3fs, predict: %.3fs)' % (kr_fit, kr_predict))
+plt.xlabel('data')
+plt.ylabel('target')
+plt.title('SVR versus Kernel Ridge')
+plt.legend()
+
+# 可视化训练和预测时间
+plt.figure()
+
+# 生成样本数据
+X = 5 * rng.rand(10000, 1)
+y = np.sin(X).ravel()
+y[::5] += 3 * (0.5 - rng.rand(X.shape[0] // 5))
+sizes = np.logspace(1, 4, 7, dtype=np.int)
+for name, estimator in {"KRR": KernelRidge(kernel='rbf', alpha=0.1,
+ gamma=10),
+ "SVR": SVR(kernel='rbf', C=1e1, gamma=10)}.items():
+ train_time = []
+ test_time = []
+ for train_test_size in sizes:
+ t0 = time.time()
+ estimator.fit(X[:train_test_size], y[:train_test_size])
+ train_time.append(time.time() - t0)
+
+ t0 = time.time()
+ estimator.predict(X_plot[:1000])
+ test_time.append(time.time() - t0)
+
+ plt.plot(sizes, train_time, 'o-', color="r" if name == "SVR" else "g",
+ label="%s (train)" % name)
+ plt.plot(sizes, test_time, 'o--', color="r" if name == "SVR" else "g",
+ label="%s (test)" % name)
+
+plt.xscale("log")
+plt.yscale("log")
+plt.xlabel("Train size")
+plt.ylabel("Time (seconds)")
+plt.title('Execution Time')
+plt.legend(loc="best")
+
+# 可视化学习曲线
+plt.figure()
+
+svr = SVR(kernel='rbf', C=1e1, gamma=0.1)
+kr = KernelRidge(kernel='rbf', alpha=0.1, gamma=0.1)
+train_sizes, train_scores_svr, test_scores_svr = \
+ learning_curve(svr, X[:100], y[:100], train_sizes=np.linspace(0.1, 1, 10),
+ scoring="neg_mean_squared_error", cv=10)
+train_sizes_abs, train_scores_kr, test_scores_kr = \
+ learning_curve(kr, X[:100], y[:100], train_sizes=np.linspace(0.1, 1, 10),
+ scoring="neg_mean_squared_error", cv=10)
+
+plt.plot(train_sizes, -test_scores_svr.mean(1), 'o-', color="r",
+ label="SVR")
+plt.plot(train_sizes, -test_scores_kr.mean(1), 'o-', color="g",
+ label="KRR")
+plt.xlabel("Train size")
+plt.ylabel("Mean Squared Error")
+plt.title('Learning curves')
+plt.legend(loc="best")
+
+plt.show()
+'''
diff --git a/src/python/9.RegTrees/regTrees.py b/src/python/9.RegTrees/regTrees.py
index 41cd60dc..44f56945 100644
--- a/src/python/9.RegTrees/regTrees.py
+++ b/src/python/9.RegTrees/regTrees.py
@@ -4,7 +4,7 @@
Created on Feb 4, 2011
Update on 2017-05-18
Tree-Based Regression Methods Source Code for Machine Learning in Action Ch. 9
-@author: Peter Harrington/片刻
+@author: Peter Harrington/片刻/小瑶
《机器学习实战》更新地址:https://github.com/apachecn/MachineLearning
'''
print(__doc__)
@@ -15,7 +15,7 @@ from numpy import *
# general function to parse tab -delimited floats
def loadDataSet(fileName):
"""loadDataSet(解析每一行,并转化为float类型)
-
+ Desc:该函数读取一个以 tab 键为分隔符的文件,然后将每行的内容保存成一组浮点数
Args:
fileName 文件名
Returns:
@@ -30,6 +30,7 @@ def loadDataSet(fileName):
curLine = line.strip().split('\t')
# 将所有的元素转化为float类型
# map all elements to float()
+ # map() 函数具体的含义,可见 https://my.oschina.net/zyzzy/blog/115096
fltLine = map(float, curLine)
dataMat.append(fltLine)
return dataMat
@@ -37,14 +38,14 @@ def loadDataSet(fileName):
def binSplitDataSet(dataSet, feature, value):
"""binSplitDataSet(将数据集,按照feature列的value进行 二元切分)
-
+ Description:在给定特征和特征值的情况下,该函数通过数组过滤方式将上述数据集合切分得到两个子集并返回。
Args:
dataMat 数据集
- feature 特征列
+ feature 待切分的特征列
value 特征列要比较的值
Returns:
- mat0 小于的数据集在左边
- mat1 大于的数据集在右边
+ mat0 小于等于 value 的数据集在左边
+ mat1 大于 value 的数据集在右边
Raises:
"""
# # 测试案例
@@ -61,11 +62,13 @@ def binSplitDataSet(dataSet, feature, value):
# 返回每一个叶子结点的均值
# returns the value used for each leaf
+# 我的理解是:regLeaf 是产生叶节点的函数,就是求均值,即用聚类中心点来代表这类数据
def regLeaf(dataSet):
return mean(dataSet[:, -1])
# 计算总方差=方差*样本数
+# 我的理解是:求这组数据的方差,即通过决策树划分,可以让靠近的数据分到同一类中去
def regErr(dataSet):
# shape(dataSet)[0] 表示行数
return var(dataSet[:, -1]) * shape(dataSet)[0]
@@ -80,18 +83,23 @@ def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
dataSet 加载的原始数据集
leafType 建立叶子点的函数
errType 误差计算函数(求总方差)
- ops [容许误差下降值,切分的最少样本数]
+ ops [容许误差下降值,切分的最少样本数]。
Returns:
bestIndex feature的index坐标
bestValue 切分的最优值
Raises:
"""
+
+ # ops=(1,4),非常重要,因为它决定了决策树划分停止的threshold值,被称为预剪枝(prepruning),其实也就是用于控制函数的停止时机。
+ # 之所以这样说,是因为它防止决策树的过拟合,所以当误差的下降值小于tolS,或划分后的集合size小于tolN时,选择停止继续划分。
+ # 最小误差下降值,划分后的误差减小小于这个差值,就不用继续划分
tolS = ops[0]
+ # 划分最小 size 小于,就不继续划分了
tolN = ops[1]
- # 如果结果集(最后一列为1个变量),就返回推出
+ # 如果结果集(最后一列为1个变量),就返回退出
# .T 对数据集进行转置
# .tolist()[0] 转化为数组并取第0列
- if len(set(dataSet[:, -1].T.tolist()[0])) == 1:
+ if len(set(dataSet[:, -1].T.tolist()[0])) == 1: # 如果集合size为1,不用继续划分。
# exit cond 1
return None, leafType(dataSet)
# 计算行列值
@@ -102,7 +110,7 @@ def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
# inf 正无穷大
bestS, bestIndex, bestValue = inf, 0, 0
# 循环处理每一列对应的feature值
- for featIndex in range(n-1):
+ for featIndex in range(n-1): # 对于每个特征
# [0]表示这一列的[所有行],不要[0]就是一个array[[所有行]]
for splitVal in set(dataSet[:, featIndex].T.tolist()[0]):
# 对该列进行分组,然后组内的成员的val值进行 二元切分
@@ -112,6 +120,7 @@ def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
continue
newS = errType(mat0) + errType(mat1)
# 如果二元切分,算出来的误差在可接受范围内,那么就记录切分点,并记录最小误差
+ # 如果划分后误差小于 bestS,则说明找到了新的bestS
if newS < bestS:
bestIndex = featIndex
bestValue = splitVal
@@ -122,15 +131,17 @@ def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
return None, leafType(dataSet)
mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue)
# 对整体的成员进行判断,是否符合预期
- if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN):
+ # 如果集合的 size 小于 tolN
+ if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): # 当最佳划分后,集合过小,也不划分,产生叶节点
return None, leafType(dataSet)
return bestIndex, bestValue
# assume dataSet is NumPy Mat so we can array filtering
+# 假设 dataSet 是 NumPy Mat 类型的,那么我们可以进行 array 过滤
def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
"""createTree(获取回归树)
-
+ Description:递归函数:如果构建的是回归树,该模型是一个常数,如果是模型树,其模型师一个线性方程。
Args:
dataSet 加载的原始数据集
leafType 建立叶子点的函数
@@ -143,6 +154,7 @@ def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
# choose the best split
feat, val = chooseBestSplit(dataSet, leafType, errType, ops)
# if the splitting hit a stop condition return val
+ # 如果 splitting 达到一个停止条件,那么返回 val
if feat is None:
return val
retTree = {}
@@ -150,7 +162,7 @@ def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
retTree['spVal'] = val
# 大于在右边,小于在左边,分为2个数据集
lSet, rSet = binSplitDataSet(dataSet, feat, val)
- # 递归的进行调用
+ # 递归的进行调用,在左右子树中继续递归生成树
retTree['left'] = createTree(lSet, leafType, errType, ops)
retTree['right'] = createTree(rSet, leafType, errType, ops)
return retTree
@@ -318,14 +330,14 @@ if __name__ == "__main__":
# myTree = createTree(myMat, modelLeaf, modelErr)
# print myTree
- # 回归树 VS 模型树 VS 线性回归
+ # # 回归树 VS 模型树 VS 线性回归
trainMat = mat(loadDataSet('input/9.RegTrees/bikeSpeedVsIq_train.txt'))
testMat = mat(loadDataSet('input/9.RegTrees/bikeSpeedVsIq_test.txt'))
- # 回归树
- myTree1 = createTree(trainMat, ops=(1, 20))
- print myTree1
- yHat1 = createForeCast(myTree1, testMat[:, 0])
- print "回归树:", corrcoef(yHat1, testMat[:, 1],rowvar=0)[0, 1]
+ # # 回归树
+ # myTree1 = createTree(trainMat, ops=(1, 20))
+ # print myTree1
+ # yHat1 = createForeCast(myTree1, testMat[:, 0])
+ # print "回归树:", corrcoef(yHat1, testMat[:, 1],rowvar=0)[0, 1]
# 模型树
myTree2 = createTree(trainMat, modelLeaf, modelErr, ops=(1, 20))
diff --git a/src/python/9.RegTrees/sklearn-regressTree-demo.py b/src/python/9.RegTrees/sklearn-regressTree-demo.py
new file mode 100644
index 00000000..93722e8c
--- /dev/null
+++ b/src/python/9.RegTrees/sklearn-regressTree-demo.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+# coding:utf8
+
+"""
+Created on 2017-07-13
+Updated on 2017-07-13
+RegressionTree:树回归
+@author: 小瑶
+《机器学习实战》更新地址:https://github.com/apachecn/MachineLearning
+"""
+
+print(__doc__)
+
+# 引入必要的模型和库
+import numpy as np
+from sklearn.tree import DecisionTreeRegressor
+import matplotlib.pyplot as plt
+
+# 创建一个随机的数据集
+# 参考 https://docs.scipy.org/doc/numpy-1.6.0/reference/generated/numpy.random.mtrand.RandomState.html
+rng = np.random.RandomState(1)
+# print 'lalalalala===', rng
+# rand() 是给定形状的随机值,rng.rand(80, 1)即矩阵的形状是 80行,1列
+# sort()
+X = np.sort(5 * rng.rand(80, 1), axis=0)
+# print 'X=', X
+y = np.sin(X).ravel()
+# print 'y=', y
+y[::5] += 3 * (0.5 - rng.rand(16))
+# print 'yyy=', y
+
+# 拟合回归模型
+# regr_1 = DecisionTreeRegressor(max_depth=2)
+# 保持 max_depth=5 不变,增加 min_samples_leaf=6 的参数,效果进一步提升了
+regr_2 = DecisionTreeRegressor(max_depth=5)
+regr_2 = DecisionTreeRegressor(min_samples_leaf=6)
+# regr_3 = DecisionTreeRegressor(max_depth=4)
+# regr_1.fit(X, y)
+regr_2.fit(X, y)
+# regr_3.fit(X, y)
+
+# 预测
+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)
+# y_3 = regr_3.predict(X_test)
+
+# 绘制结果
+plt.figure()
+plt.scatter(X, y, c="darkorange", label="data")
+# plt.plot(X_test, y_1, color="cornflowerblue", label="max_depth=2", linewidth=2)
+plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=5", linewidth=2)
+# plt.plot(X_test, y_3, color="red", label="max_depth=3", linewidth=2)
+plt.xlabel("data")
+plt.ylabel("target")
+plt.title("Decision Tree Regression")
+plt.legend()
+plt.show()
\ No newline at end of file