diff --git a/docs/2.k-近邻算法.md b/docs/2.k-近邻算法.md
index 6deccb78..a34614dd 100644
--- a/docs/2.k-近邻算法.md
+++ b/docs/2.k-近邻算法.md
@@ -1,12 +1,13 @@
# 第2章 k-近邻算法
-
+
-众说周知,电影可以按照题材分类的;而我们的确知道每部电影在风格上的确可能和同题材的电影相近。
-那么动作片和爱情片是否存在着明显的差别呢?
-例如: 1.打斗次数 2.亲吻次数
-使用k-近邻算法构造程序,自动划分电影的题材类型。
+众说周知,电影可以按照题材分类的;而我们却知道每部电影在风格上的确可能和同题材的电影相近。
+那么动作片具有哪些共有特征,使得动作片之间非常相似,而与爱情片存在着明显的差别呢?
+例如: 1.打斗次数 2.亲吻次数
+动作片中也会存在接吻镜头,爱情片中也会存在打斗场景,我们不能单纯依靠是否是否存在打斗或者亲吻镜头,爱情片中也会存在打斗场景,动作片中的打斗场景也更频繁,基于此类场景在某部电影中出现的次数可以用来进行电影分类。
+基于电影中出现的亲吻、打斗出现的次数,使用k-近邻算法构造程序,自动划分电影的题材类型。
## k-近邻分类算法
@@ -19,14 +20,18 @@
最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
```
-
+```
+ 回想上面我们提到的电影分类的例子,使用 k-近邻算法 分类爱情片和动作片。下图显示了6部电影的打斗和接吻镜头数。
+ 假如有一部未看过的电影,如何确定它是爱情片还是动作片呢?接下来,我们使用 kNN 来解决这个问题。
+```
-> k-近邻算法的特点
+
+
```
-优点:精度高、对异常值不敏感、无数据输入假定
-缺点:计算复杂度高、空间复杂度高
-适用数据范围:数值型和标称型
+ 现在根据上面我们得到的样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到k个距离最近的电影。
+ 假定k=3,则三个最靠近的电影依次是, He's Not Really into Dudes 、 Beautiful Woman 和 California Man。
+ k-近邻算法按照距离最近的三部电影的类型,决定未知电影的类型,而这三部电影全是爱情片,因此我们判定未知电影是爱情片。
```
> k-近邻算法的一般流程
@@ -51,14 +56,22 @@
(5)返回前k个点出现频率最高的类别作为当前点的预测分类
```
+> k-近邻算法的特点
+
+```
+优点:精度高、对异常值不敏感、无数据输入假定
+缺点:计算复杂度高、空间复杂度高
+适用数据范围:数值型和标称型
+```
+
## 从文本文件中解析和导入数据
-> 示例:在约会网站上使用k-近邻算法
+> 示例:使用 k-近邻算法改进约会网站的配对效果
```
收集数据:提供文本文件
准备数据:使用Python解析文本文件
-分析数据:使用Mapplotlib画二维扩散图
+分析数据:使用Matlotlib画二维扩散图
训练算法:此步骤不适用于k-近邻算法
测试算法:使用海伦提供的部分数据作为测试样本。
测试样本和非测试样本的区别在于:
@@ -66,6 +79,33 @@
使用算法:产生简单的命令行程序,然后海伦可以输入一些特征数据以判断对方是否为自己喜欢的类型。
```
+> 将文本记录转换为NumPy的解析程序
+
+```Python
+def file2matrix(filename):
+ fr = open(filename)
+ arrayOLines = fr.readlines()
+ numberOfLines = len(arrayOLines)
+ returnMat = zeros((numberOfLines,3))
+ classLabelVector = []
+ index = 0
+ for line in arrayOLines:
+ line = line.strip()
+ listFromLine = line.split('\t')
+ returnMat[index,:] = listFromLine[0:3]
+ classLabelVector.append(int(listFromLine[-1]))
+ index += 1
+ return returnMat,classLabelVector
+```
+
+> NumPy数组和Python数组
+
+```
+ 本教程以后将大量使用NumPy数组,你既可以直接在Python命令行环境中输入 from numpy import array 将其导入,
+也可以通过直接导入所有NumPy库内容来将其导入。由于NumPy库提供的数组操作并不支持Python自带的数组类型,因此在编写代码时要注意不要使用错误的数组类型。
+```
+
+
## 使用Matplotlib创建扩散图
```Python
@@ -82,13 +122,14 @@ plt.show()
样本3和样本4的距离:
$$\sqrt{(0-67)^2 + (20000-32000)^2 + (1.1-0.1)^2 }$$
-我们很容易发现: 上面方程中数字差值最大的属性对计算结果的影响最大。
-
+我们很容易发现: 上面方程中数字差值最大的属性对计算结果的影响最大。所以我们进行归一化处理是必不可少的。
+
+
## 总结
* k-近邻算法其实就是根据空间两个向量距离来判断类别性,关键的是引入k值,保证了一定的稳定性,很明显的缺点就是每次都要与所有样本数据进行对比。
* 文中处理约会数据时,归一化的方法是对于消除影响很十分重要的
* 阅读本章之前建议阅读一下numpy的文档
- * [numpy英文文档](https://docs.scipy.org/doc/numpy-dev/user/quickstart.html)
- * [numpy中文文档](http://old.sebug.net/paper/books/scipydoc/numpy_intro.html)
+ * [numpy英文文档](https://docs.scipy.org/doc/numpy-dev/user/quickstart.html "NumPy英文文档")
+ * [numpy中文文档](http://old.sebug.net/paper/books/scipydoc/numpy_intro.html "NumPy中文文档")
diff --git a/docs/3.决策树.md b/docs/3.决策树.md
index bc553344..a4914a7b 100644
--- a/docs/3.决策树.md
+++ b/docs/3.决策树.md
@@ -2,19 +2,85 @@
# 第3章 决策树
-
+
## 决策树简介
-
+
+> 决策树的任务
+
+```
+ 第二章的k-近邻算法可以完成很多分类任务,但是它最大的缺点就是无法给出数据的内在含义。
+ 决策树的主要优势就在于数据形式非常容易理解。
+ 接下来构造的决策树算法能够读取数据集合,构建类似于上图的决策树。决策树的一个重要任务是为了理解数据中所蕴含的知识信息,
+ 因此决策树可以使用不熟悉的数据集合,并从中提取出一系列规则,这些机器根据数据集创建规则的过程,就是机器学习的过程。
+ 专家系统中经常使用决策树,而且决策树给出结果往往可以匹敌在当前领域具有几十年工作经验的人类专家。
+```
+
+> 决策树的特点
+
+```
+ 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。
+ 缺点:可能会产生过度匹配问题。
+ 适用数据类型:数值型和标称型。
+```
## 在数据集中度量一致性
## 使用递归构造决策树
+> 构造决策树时需要解决的第一个问题
+
+```
+ 在构造决策树时,我们需要解决的第一个问题就是,当前的数据集上哪个特征在划分数据分类时起决定性作用。
+为了找到决定性的特征,划分出最好的结果,我们必须评估每个特征。完成测试之后,原始数据集就被划分为几个数据子集。
+这些数据子集会分布在第一个决策点的所有分支上。如果某个分支下的数据属于同一类型,则当前无需阅读的垃圾邮件已经正确地划分数据分类,
+无需进一步对数据集进行分割。如果数据子集内的数据不属于同一类型,则需要重复划分数据子集的过程。划分数据子集的算法和划分原始数据及的方法相同,
+直到所有具有相同类型的数据均在一个数据子集内。
+```
+
+> 创建分支的伪代码函数createBranch()
+
+```
+ 检测数据集中的每个子项是否属于同一分类:
+ If so return 类标签
+ Else
+ 寻找划分数据集的最好特征
+ 划分数据集
+ 创建分支节点
+ for 每个划分的子集
+ 调用函数createBranch并增加返回结果到分支节点中
+ return 分支节点
+```
+
+> 决策树的一般流程
+
+```
+ (1)收集数据:可以使用任何方法。
+ (2)准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化。
+ (3)分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期。
+ (4)训练算法:构造树的数据结构。
+ (5)测试算法:使用经验树计算错误率。
+ (6)使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。
+```
+
+> 划分数据集时的数据路径
+
+```
+ 得到原始数据集,然后基于最好的属性值划分数据集,由于特征值可能多于两个,因此可能存在大于两个分支的数据集划分。
+ 第一次划分之后,数据将被向下传递到树分支的下一个节点,在这个节点上,我们可以再次划分数据。因此我们可以采用递归的原则处理数据集。
+ 递归结束的条件是:程序遍历完所有划分数据集的属性,或者每个分支下的所有实例都具有相同的分类。如果所有实例具有相同的分类,
+ 则得到一个叶子节点或者终止块。任何到达叶子节点的数据必然属于叶子节点的分类,如下图所示:
+```
+
+
+
## 使用Matplotlib绘制树形图
+> Matplotlib绘制树形图示例
+
+
* 决策树是什么?
* 顾名思义,是一种树,一种依托于策略抉择而建立起来的树。
diff --git a/docs/4.朴素贝叶斯.md b/docs/4.朴素贝叶斯.md
index 23f985e4..796a818a 100644
--- a/docs/4.朴素贝叶斯.md
+++ b/docs/4.朴素贝叶斯.md
@@ -1,5 +1,114 @@
-# 4) 朴素贝叶斯
+# 第4章 基于概率论的分类方法:朴素贝叶斯
+
+
+
+
+## 使用概率分布进行分类
+
+> 朴素贝叶斯简介
+
+```
+ 前两章我们要求分类器做出艰难决策,给出“该数据实例属于哪一类”这类问题的明确答案。不过,分类器有时候会产生错误的结果,
+ 这时可以要求分类器给出一个最优的类别猜测结果,同时给出这个猜测的概率估计值。
+ 在这里我们先统计特征在数据集中取某个特定值的次数,然后除以数据集的实例总数,就得到了特征取该值的概率。
+ 下面我们会给出一些使用概率论进行分类的方法。首先从一个最简单的概率分类器开始,然后给出一些假设来学习朴素贝叶斯分类器。
+ 我们称之为“朴素”,是因为整个形式化过程只做最原始、最简答的假设。
+```
+
+> 贝叶斯决策理论
+
+```
+ 朴素贝叶斯是贝叶斯决策理论的一部分,所以讲述朴素贝叶斯之前有必要快速了解一下贝叶斯决策理论。
+ 假设我们有一个数据集,它由两类数据组成,数据分布如下图所示:
+```
+
+
+
+```
+ 我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中用圆点表示的类别)的概率,用p2(x,y)表示数据点(x,y)属于类别2(图中三角形表示的类别)的概率,
+ 那么对于一个新数据点(x,y),可以用下面的规则来判断它的类别:
+ * 如果 p1(x,y) > p2(x,y) ,那么类别为1
+ * 如果 p2(x,y) > p1(x,y) ,那么类别为2
+ 也就是说,我们会选择高概率对应的类别。这就是贝叶斯决策理论的核心思想,即选择具有最高概率的决策。
+```
+
+> 朴素贝叶斯特点
+
+```
+ 优点:在数据较少的情况下仍然有效,可以处理多类别问题。
+ 缺点:对于输入数据的准备方式较为敏感。
+ 适用于数据类型:标称型数据。
+```
+
+> 朴素贝叶斯的一般过程
+
+```
+ (1)收集数据:可以使用任何方法。本章使用RSS源。
+ (2)准备数据:需要数值型或者布尔型数据。
+ (3)分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好。
+ (4)训练算法:计算不同的独立特征的条件概率。
+ (5)测试算法:计算错误率。
+ (6)使用算法:一个常见的朴素贝叶斯应用是文档分类。可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要是文本。
+```
+
+## 学习朴素贝叶斯分类器
+
+> 条件概率
+
+
+
+> 计算上述概率
+
+```
+ 要计算 P(gray) 或者 P(black) ,事先得知道石头所在桶的信息会不会改变结果?你有可能已经想到计算从 B 桶中取到灰色石头的概率的办法,
+ 这就是所谓的条件概率 (conditional probability)。假定计算的是从 B 桶取到灰色石头的概率,这个概率可以记作 P(gray|bucketB),
+ 我们称之为“在已知石头出自B桶的条件下,取出灰色石头的概率”。不难得到,P(gray|bucketA)值为2/4,P(gray|bucketB)的值为1/3。
+ 条件概率的计算公式如下所示:
+ P(gray|bucketB) = P(gray and bucketB) / P(bucketB)
+```
+> 贝叶斯准则
+
+```
+ 贝叶斯准则告诉我们如何交换条件概率中的条件和结果,即如果已知 P(x|c) ,要求 P(c|x) ,那么可以使用下面的计算方法:
+ p(c|x) = p(x|c)·p(c)/p(x)
+```
+
+> 使用条件概率来分类
+
+上面提到的贝叶斯决策理论要求计算两个概率 p1(x,y) 和 p2(x,y):
+* 如果 p1(x,y) > p2(x,y) ,那么属于类型1;
+* 如果 p2(x,y) > p1(x,y) ,那么属于类型2;
+但这两个准则并不是贝叶斯决策理论的所有内容。使用 p1() 和 p2() 只是为了尽可能简化描述,而真正需要计算和比较的是 p(c1|x,y) 和 p(c2|x,y)。
+这些符号代表的具体意义是:给定某个由x,y表示的数据点,那么该数据点来自类别c1的概率是多少?数据点来自类别c2的概率又是多少?
+注意这些概率与刚才给出的概率p(x,y|c1)并不一样,不过可以使用贝叶斯准则来交换概率中条件和结果。具体地,应用贝叶斯准则得到:
+p(ci|x,y) = p(x,y|ci)·p(ci)/p(x,y)
+
+使用这些定义,可以定义贝叶斯分类准则为:
+* 如果 P(c1|x,y) > P(c2|x,y) ,那么属于类别c1;
+* 如果 P(c1|x,y) < P(c2|x,y) ,那么属于类别c2;
+使用贝叶斯准则,可以通过已知的三个概率值来计算未知的概率值。后面就会给出利用贝叶斯准则来计算概率并对数据进行分类的代码。现在介绍了一些概率理论,
+你也了解了基于这些理论构建分类器的方法,接下来就要将它们付诸实践。
+
+## 解析RSS源数据
+
+机器学习的一个重要应用就是文档的自动分类。在文档分类中,整个文档(如一封电子邮件)是实例,而电子邮件中的某些元素则构成特征。
+虽然电子邮件是一种会不断增加的文本,但我们同样也可以对新闻报道、用户留言、政府公文等其他任何类型的文本进行分类。
+我们可以观察文档中出现的词,并把每个词的出现或者不出现作为一个特征,这样得到的特征数目就会跟词汇表中的词目一样多。
+朴素贝叶斯是上节介绍的贝叶斯分类器的一个扩展,是用于文档分类的常用算法。
+
+## 使用朴素贝叶斯来分析不同地区的态度
+
+> 示例:使用朴素贝叶斯来发现低于相关的用词
+
+```
+ (1) 收集数据:从RSS源收集内容,这里需要对RSS源构建一个接口。
+ (2) 准备数据:将文本文件解析成词条向量。
+ (3) 分析数据:检查词条确保解析的正确性。
+ (4) 训练算法:使用我们之前建立的 trainNB0()函数。
+ (5) 测试算法:观察错误率,确保分类器可用。可以修改切分程序,以降低错误率,提高分类结果。
+ (6) 使用算法:构建一个完整的程序,封装所有内容。给定两个RSS源,该程序会显示最常用的公共词。
+```
* 假设: 特征之间强(朴素)独立
* 概率模型
diff --git a/docs/5.Logistic回归.md b/docs/5.Logistic回归.md
index a3da78b3..1364628c 100644
--- a/docs/5.Logistic回归.md
+++ b/docs/5.Logistic回归.md
@@ -1,7 +1,89 @@
+# 第5章 Logistic回归
+
-# 5) 逻辑回归基础
+
- * 逻辑回归(Logistic Regression)
+## Sigmoid函数和Logistic回归分类器
+
+> 回归简介
+
+```
+ 假设现在有一些数据点,我们用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作回归。
+ 利用 Logistic回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。这里的“回归”一词源于最佳拟合,
+ 表示要找到最佳拟合参数集,其背后的数学分析将在下一部分介绍。训练分类器时的做法就是寻找最佳拟合参数,使用的是最优化算法。
+```
+
+> Logistic回归特点
+
+```
+ 优点:计算代价不高,易于理解和实现。
+ 缺点:容易欠拟合,分类精度可能不高。
+ 适用数据类型:数值型和标称型数据。
+```
+
+> Sigmoid函数简介
+
+```
+ Sigmoid函数具体的计算公式如下:
+ f(z) = 1 / (1 + e ^(-z))
+ 图5-1 给出了Sigmoid函数在不同坐标尺度下的两条曲线图。当x为0时,Sigmoid函数值为0.5。随着x的增大,对应的Sigmoid值将逼近1;而随着x的减小,Sigmoid值将逼近0。
+ 如果横坐标刻度足够大(图5-1下图),Sigmoid函数看起来很像一个阶跃函数。
+ 因此,为了实现Logistic回归分类器,我们可以在每个特征上都乘以一个回归系数,然后把所有的结果值相加,将这个总和带入Sigmoid函数中,进而得到一个范围在0~1之间的数值。
+ 任何大于0.5的数据被分入1类,小于0.5即被归入0类。所以,Logistic回归也可以被看成是一种概率估计。
+```
+
+
+## 最优化理论初步
+
+> 梯度上升法
+
+```
+ 梯度上升法基于的思想是:要找到某函数的最大值,最好的方法是沿着该函数的梯度方向探寻。如果梯度记为▽,则函数f(x,y)的梯度由下式表示:
+```
+
+
+
+梯度上升法的伪代码如下:
+ 某个回归系数初始化为1
+ 重复R次:
+ 计算整个数据集的梯度
+ 使用 alpha X grandient 更新回归系数的向量
+ 返回回归系数
+
+梯度上升算法在每次回归系数时都需要遍历整个数据集,该方法在处理100个左右的数据集时尚可,但如果有数十亿样本和成千上万的特征,
+那么该方法的计算复杂度就太高了。一种改进方法是一次仅用一个样本点来更新回归系数,该方法称为随机梯度上升算法。
+由于可以在新样本到来时对分类器进行增量式更新,因而随机梯度上升算法是一个在线学习算法。与“在线学习”相对应,
+一次处理所有数据被称作是“批处理”。
+ 随机梯度上升算法可以写成如下的伪代码:
+
+ 所有回归系数初始化为1
+ 对数据集中每个样本
+ 计算该样本的梯度
+ 使用 alpha X gradient 更新回归系数值
+ 返回回归系数值
+
+## 梯度下降最优化算法
+
+你最经常听到的应该是梯度下降算法,它与这里的梯度上升算法是一样的,只是公式中的加法需要变成减法。因此,对应的公式可以写成:
+ w:=w-a▽f(w)
+梯度上升算法用来求函数的最大值,而梯度下降算法用来求函数的最小值。
+
+## 数据中的缺失项处理
+
+数据中的缺失值是个非常棘手的问题,有很多文献都致力于解决这个问题。这个问题没有标准答案,取决于实际应用中的需求。
+那么,数据缺失究竟带来了什么问题?假设有100个样本和20个特征,
+这些数据都是机器手机回来的。若机器上的某个传感器损坏导致一个特征无效时该怎么办?此时是否要扔掉整个数据?这种情况下,另外19个特征怎么办?
+它们是否还可以用?答案是肯定的。因为有时候数据相当昂贵,扔掉和重新获取都是不可取的,所以必须采用一些方法来解决这个问题。
+* 下面给出了一些可选的做法:
+ * 使用可用特征的均值来填补缺失值;
+ * 使用特殊值来填补缺失值,如 -1;
+ * 忽略有缺失值的样本;
+ * 使用有相似样本的均值添补缺失值;
+ * 使用另外的机器学习算法预测缺失值。
+
+## Logistic 回归总结
+
+* 逻辑回归(Logistic Regression)
* 5.1 分类问题
* 在分类问题中,尝试预测的是结果是否属于某一个类(例如正确或错误)。
* 分类问题的例子有:
@@ -15,6 +97,7 @@
* 5.3 判定边界
* 在逻辑回归中,我们预测:
+
当 hθ 大于等于 0.5 时,预测 y=1
当 hθ 小于 0.5 时,预测 y=0
* 根据上面绘制出的 S 形函数图像,我们知道当
diff --git a/docs/8.预测数值型数据:回归.md b/docs/8.预测数值型数据:回归.md
index 62f1daff..dc586ecd 100644
--- a/docs/8.预测数值型数据:回归.md
+++ b/docs/8.预测数值型数据:回归.md
@@ -1,18 +1,166 @@
+# 第8章 预测数值型数据:回归
+
-# 8)预测数值型数据:回归
+
-* 线性回归的特点
- * 优点:结果易于理解,计算上不复杂。
- * 缺点:对非线性的数据拟合不好。
- * 适用数据范围:数值型和标称型数据。
-* 工作原理
- * 回归的目的是预测数值型的目标值。最直接的办法是以及输入写出一个目标值的计算公式。
-* 回归的一般流程
- * 收集数据:任何方法
- * 准备数据:回归需要数值型数据,标称型数据将被转成二值型数据。
- * 分析数据:绘出数据的可视二维图将有助于对数据做出理解和分析,在采用缩减法求得新回归系数之后,可以将新拟合线绘在图上作为对比。
- * 训练算法:找到回归系数。
- * 测试数据:使用R的平方或者预测值和数据的拟合度,来分析模型的效果。
- * 使用算法:使用回归,可以在给定输入的时候预测出一个数值,这是对分类方法的提升,因为这样可以预测连续型数据而不仅仅是离散的类别标签。
-* 总结
- * 求回归系数的过程就是回归。
+## 线性回归
+
+> 回归简介
+
+```
+ 回归的目的是预测数值型的目标值。最直接的办法是依据输入写出一个目标值的计算公式。
+ 假如你想要预测姐姐男友汽车的功率大小,可能会这么计算:
+ HorsePower = 0.0015 * annualSalary - 0.99 * hoursListeningToPublicRadio
+ 这就是所谓的回归方程(regression equation),其中的0.0015和-0.99称作回归系数(regression weights),求这些回归系数的过程就是回归。
+ 一旦有了这些回归系数,再给定输入,做预测就非常容易了。具体的做法是用回归系数乘以输入值,再将结果全部加在一起,就得到了预测值。
+ 说到回归,一般都是指线性回归(linear regression),所以本章里的回归和线性回归代表同一个意思。线性回归意味着可以将输入项分别乘以一些常量,
+ 再将结果加起来得到输出。需要说明的是,存在另一种称为非线性回归的回归模型,该模型不认同上面的做法,比如认为可能是输入的乘积。
+ 这样,上面的功率计算公式也可以写做:
+ HorsePower = 0.0015 * annualSalary / hoursListeningToPublicRadio
+ 这就是一个非线性回归的例子,但是对此不进行深入讨论。
+```
+
+> 线性回归特点
+
+```
+ 优点:结果易于理解,计算上不复杂。
+ 缺点:对非线性的数据拟合不好。
+ 适用于数据类型:数值型和标称型数据。
+```
+
+> 回归的一般方法
+
+```
+ (1) 收集数据:采用任意方法收集数据。
+ (2) 准备数据:回归需要数值型数据,标称型数据将被转换成二值型数据。
+ (3) 分析数据:绘出数据的可视化二维图将有助于对数据做出理解和分析,在采用缩减法求得新回归系数之后,可以将新拟合线绘在图上作为对比。
+ (4) 训练算法:找到回归系数。
+ (5) 测试算法:使用 R^2 或者预测值和数据的拟合度,来分析模型的效果。
+ (6) 使用算法:使用回归,可以在给定输入的时候预测出一个数值,这是对分类方法的提升,因为这样可以预测连续型数据而不仅仅是离散的类别标签。
+```
+
+> 线性回归的效果图
+
+
+
+## 局部加权线性回归
+
+> 局部加权线性回归简介
+
+```
+ 线性回归的一个问题是有可能出现欠拟合现象,因为它求的是具有最小均方误差的无偏估计。显而易见,如果模型欠拟合将不能取得最好的预测效果。
+所以有些方法允许在估计中引入一些偏差,从而降低预测的均方差。
+ 其中的一个方法是局部加权线性回归(Locally Weighted Linear Regression, LWLR)。在该算法中,我们给带预测点附近的每个点赋予一定的权重,
+在这个子集上基于最小均方差来进行普通的回归。与kNN一样,这种算法每次预测均需要实现选取出对应的数据子集。该算法解出回归系数w的形式如下:
+ w = (X^T W X)^(-1)X^T Wy
+其中 w 是一个矩阵,用来给每个数据点赋予权重。
+```
+
+> 局部加权线性回归效果图
+
+
+
+
+## 岭回归和逐步线性回归
+
+> 缩减系数来“理解”数据
+
+```
+ 如果数据的特征比样本点还多应该怎么办?是否还可以使用线性回归和之前的方法来做预测?答案是否定的,即不能再使用前面介绍的方法。
+这是因为在计算 (x^TX)^(-1) 的时候会出错。
+ 如果特征比样本点还多(n > m),也就是说输入数据的矩阵X不是满秩矩阵。非满秩矩阵在求逆时会出现问题。
+ 为了解决这个问题,统计学家引入了岭回归(ridge regression)的概念,这就是本节将要介绍的第一种缩减方法。
+```
+
+> 岭回归
+
+```
+ 简单来说,岭回归就是在矩阵 X^TX 上加一个 λI 从而使得矩阵非奇异,进而能对 X^TX+λI 求逆。其中矩阵I是一个 m*m 的单位矩阵,
+ 对角线上元素全为1,其他元素全为0。而λ是一个用户定义的数值,后面会做介绍。在这种情况下,回归系数的计算公式将变成:
+ w = (X^TX + λI)^(-1)X^Ty
+ 岭回归最先用来处理特征数多于样本数的情况,现在也用于在估计中加入偏差,从而得到更好的估计。这里通过引入λ来限制了所有w之和,通过引入该惩罚项,
+ 能够减少不重要的参数,这个技术在统计学中也叫作缩减(shrinkage)。
+```
+
+> 岭回归中的岭是什么
+
+```
+ 岭回归使用了单位矩阵乘以常量λ,我们观察其中的单位矩阵I,可以看到值1贯穿整个对角线,其余元素全是0.形象地,在0构成的平面上有一条1组成的“岭”,
+ 这就是岭回归中的“岭”的由来。
+```
+> 岭回归示例图
+
+
+
+> 前向逐步回归简介
+
+```
+ 前向逐步回归算法可以得到与 lasso 差不多的效果,但更加简单。它属于一种贪心算法,即每一步都尽可能减少误差。
+ 一开始,所有的权重都设为1,然后每一步所做的决策是对某个权重增加或减少一个很小的值。
+```
+
+> 前向逐步回归伪代码
+
+```
+ 数据标准化,使其分布满足0均值和单位方差
+ 在每轮迭代过程中:
+ 设置当前最小误差lowestError为正无穷
+ 对每个特征:
+ 增大或缩小:
+ 改变一个系数得到一个新的w
+ 计算新w下的误差
+ 如果误差Error小于当前最小误差lowestError:设置Wbest等于当前的w
+ 将W设置为新的Wbest
+```
+
+```
+ 贪心算法在所有特征上运行两次for循环,分别计算增加或减少该特征对误差的影响。这里使用的是平方误差,通过之前的函数rssError()得到。
+ 该误差初始值设为正无穷,经过与所有的误差比较后取最小的误差。整个过程循环迭代进行。
+```
+
+> 逐步线性回归示例图
+
+
+
+## 预测鲍鱼年龄和玩具售价
+
+> 示例:预测鲍鱼的年龄
+
+```
+ 鲍鱼年龄可以从鲍鱼壳的层数推算得到。
+ 为了分析预测误差的大小,可以用函数rssError()计算出这一指标,下面是三种不同的预测误差:
+ >>> regression.rssError(abY[0:99],yHat01.T)
+ 56.842594430533545
+ >>> regression.rssError(abY[0:99],yHat1.T)
+ 429.89056187006685
+ >>> regression.rssError(abY[0:99],yHat10.T)
+ 549.11817088257692
+ 可以看到,使用较小的核将得到较低的误差。那么,为什么不在所有数据集上都使用最小的核呢?
+ 这是因为使用最小的核将造成过拟合,对新数据不一定能达到最好的预测效果。
+
+ 简单线性回归达到了与局部线性回归类似的效果。这也表明一点,必须在未知数据上比较效果才能选取到最佳模型。那么最佳的核大小是10吗?
+ 或许是,但如果想得到最好的效果,应该用10个不同的样本集做10次测试来比较结果。
+```
+
+> 示例:预测乐高玩具套装的价格
+
+> 用回归法预测乐高套装的价格的一般过程
+
+```
+ (1) 收集数据:用 Google Shopping 的API收集数据。
+ (2) 准备数据:从返回的JSON数据中抽取价格。
+ (3) 分析数据:可视化并观察数据。
+ (4) 训练算法:构建不同的模型,采用逐步线性回归和直接的线性回归模型。
+ (5) 测试算法:使用交叉验证来测试不同的模型,分析哪个效果最好。
+ (6) 使用算法:这次练习的目标就是生成数据模型。
+```
+
+## 预测数值型数据:回归 小结
+
+ 与分类一样,回归也是预测目标值的过程。回归与分类的不同点在于,前者预测连续型变量,而后者预测离散型变量。回归是统计学中最有力的的工具之一。
+在回归方程里,求得特征对应的最佳回归系数的方法是最小化误差的平方和。给定输入矩阵x,如果 x^Tx的逆存在并可以求得的话,回归法都可以直接使用。
+数据集上计算出的回归方程并不一定意味着它是最佳的,可以使用预测值yHat和原始值y的相关性来度量回归方程的好坏。
+ 当数据的样本数比特征数还少的时候,矩阵x^Tx的逆不能直接计算。即便当样本数比特征数多时,x^Tx的逆仍有可能无法直接计算,这是因为特征有可能高度相关。
+这时可以考虑使用岭回归,因为当x^Tx的逆不能计算时,它仍保证能求得回归系数。
+ 岭回归是缩减法的一种,相当于对回归系数的大小施加了限制。另一种很好的缩减法是lasso。Lasso难以理解,但可以使用计算简便的逐步线性回归方法来求得近似结果。
+ 缩减法还可以看做是对一个模型增加偏差的同时减少方差。偏差方差折中是一个重要的概念,可以帮助我们理解现有模型并做出改进,从而得到最好的模型。
\ No newline at end of file
diff --git a/docs/9.树回归.md b/docs/9.树回归.md
index 91acba04..7777bc0f 100644
--- a/docs/9.树回归.md
+++ b/docs/9.树回归.md
@@ -1,17 +1,158 @@
+# 第9章 树回归
+
-# 9) 树回归
+
-* 树回归是什么?
- * 分类回归树(Classification and Regression Tree,CART)是一种典型的决策树算法,CART算法不仅可以应用于分类问题,而且可以用于回归问题。
- * CART算法构建的回归树并介绍其中的树剪枝技术(该技术主要的目的是防止树的过拟合)
-* 树回归的构建
- * 优点:可以对复杂和非线性的数据建模。
- * 缺点:结果不易理解。
- * 适用数据类型:数值型和标称型数据。
-* 那么问题来了,如何计算连续型数值的混乱度呢?
- * `误差`:也就是计算平均差的总值(总方差=方差*样本数)
- * 二元切分方式
-* 回归树
-* 模型树(线性模型)
-* 树回归方法在预测复杂数据时 会比 简单的线性模型 更有效。
-* Tkinter 和 matplotlib的集成,构建更强大的GUI
+## CART 算法
+
+> CART 算法简介
+
+```
+ CART(Classification And Regression Trees,分类回归树)的树构建算法。该算法既可以用于分类还可以用于回归,因此非常值得学习。
+ CART 是十分著名的且广泛记载的树构建算法,它使用二元切分来处理连续型变量。对CART稍作修改就可以处理回归问题。
+```
+
+> CART与ID3的一些不同
+
+```
+ 第三章使用决策树来进行分类。决策树不断将数据切分成小数据集,直到所有的目标变量完全相同,或者数据不能再切分为止。决策树是一种贪心算法,
+它要在给定的时间内做出最佳选择,但并不关心能否达到全局最优。
+ 第3章使用的树构建算法是ID3.ID3的做法是每次选取当前最佳的特征来分割数据,并按照该特征的所有可能取值来切分。也就是说,
+如果一个特征有4种取值,那么数据将被切成4份。一旦按某特征切分后,该特征在之后的算法执行过程中将不会再起作用,所有有观点认为这种切分方式过于迅速。
+另外一种方法是二元切分法,即每次把数据集切成两份。如果数据的某特征值等于切分所要求的值,那么这些数据就进入树的左子树,反之则进入树的右子树。
+ 除了切分过于迅速外,ID3算法还存在另一个问题,它不能直接处理连续型特征。只有事先将连续型特征转换成离散型,才能在ID3算法中使用。
+但这种转换过程会破坏连续型变量的内在性质。而使用二元切分法则易于对树构建过程进行调整以处理连续型特征。
+ 上面说到了一点,对CART稍作修改就可以处理回归问题。第3章中使用香农熵来度量集合的无组织程度。如果选用其他方法来代替香农熵,就可以使用树构建算法来完成回归。
+```
+
+## 回归树
+
+> 树回归的特点
+
+```
+ 优点:可以对复杂和非线性的数据建模。
+ 缺点:结果不易理解。
+ 适用数据类型:数值型和标称型数据。
+```
+
+> 树回归的一般方法
+
+```
+ (1) 收集数据:采用任意方法收集数据。
+ (2) 准备数据:需要数值型数据,标称型数据应该映射成二值型数据。
+ (3) 分析数据:绘出数据的二维可视化显示结果,以字典方式生成树。
+ (4) 训练算法:大部分时间都花费在叶节点树模型的构建上。
+ (5) 测试算法:使用测试数据上的R^2值来分析模型的效果。
+ (6) 使用算法:使用训练处的树做预测,预测结果还可以用来做很多事情。
+```
+
+> 连续和离散型特征的树的构建
+
+```
+ 在树的构建过程中,需要解决多种类型数据的存储问题,这里将使用一部字典来存储树的数据结构,该字典将包含以下4个元素。
+ * 待切分的特征
+ * 待切分的特征值
+ * 右子树。当不再需要切分的时候,也可以是单个值。
+ * 左子树。与右子树类似。
+```
+
+下面我们要构建两种树:第一种是 回归树(regression tree),其每个叶节点包含单个值;第二种是 模型树(model tree),其每个叶节点包含一个线性方程。
+下面给出两种树构建算法中的一些共用代码:
+ 函数createTree() 的伪代码大致如下:
+ 找到最佳的待切分特征:
+ 如果该节点不能再分,将该节点存为叶节点
+ 执行二元切分
+ 在右子树调用createTree()方法
+ 在左子树调用createTree()方法
+
+
+> 将 CART 算法用于回归
+
+```
+ 回归树假设叶节点是常数值,这种策略认为数据中的复杂关系可以用树结构来概括。
+ 为成功构建以分段常数为叶节点的树,需要度量出数据的一致性。第3章使用树进行分类,会在给点节点时计算数据的混乱度。那么如何计算连续型数值的混乱度呢?
+事实上,在数据集上计算混乱度是非常简单的。首先计算所有数据的均值,然后计算每条数据的值到均值的差值。为了对正负差值同等看待,一般使用绝对值或平方值来代替上述差值。
+上述做法有点类似于前面介绍过的统计学中常用的方差计算。唯一不同就是,方差是平方误差的均值(均方差),而这里需要的是平方误差的总值(总方差)。
+总方差可以通过均方差乘以数据集中样本点的个数来得到。
+```
+
+> 将回归树运用到下面的数据中,目标是从该数据生成一棵回归树
+
+
+
+
+
+## 模型树
+
+ 用树来对数据建模,除了把叶节点简单地设定为常数值之外,还有一种方法是把叶节点设定为分段线性函数,这里所谓的分段线性(piecewise linear)是指模型由多个
+先行片段组成。参考下图中的数据,如果使用两条直线拟合是否比使用一组常数来建模好呢?答案显而易见。可以设计两条分别从0.0~0.3、从0.3~1.0的直线,于是就可以
+得到两个线性模型。因为数据集里的一部分数据(0.0~0.3)以某个线性模型建模,而另一部分数据(0.3~1.0)则以另一个线性模型建模,因此我们说采用了所谓的分段线性模型。
+ 决策树相比于其他机器学习算法的优势之一在于结果更易理解。很显然,两条直线比很多节点组成一棵大树更容易解释。模型树的可解释性是它优于回归树的特点之一。
+另外,模型树也具有更高的预测准确度。
+
+
+
+
+## 树剪枝(tree pruning)算法
+
+一棵树如果节点过多,表明该模型可能对数据进行了“过拟合”。那么,如何判断是否发生了过拟合?前面章节中使用了测试集上某种交叉验证技术来发现过拟合,决策树亦是如此。
+通过降低决策树的复杂度来避免过拟合的过程称为“剪枝(pruning)”。
+
+> 预剪枝
+
+```
+ 本章前面已经进行过剪枝处理。在函数chooseBestSplit()中提前终止条件,实际上是在进行一种所谓的预剪枝(prepruning)操作。
+```
+
+> 后剪枝
+
+```
+ 利用测试集来对树进行剪枝。由于不需要用户指定参数,后剪枝是一个更理想化的剪枝方法。
+ 使用后剪枝方法需要将数据集分成测试集和训练集。首先指定参数,使得构建出的树足够大,足够复杂便于剪枝。
+ 下面是从上而下找到叶节点,用测试集来判断将这些叶节点合并是否能降低误差。如果是的话就合并。
+ 函数prune()的伪代码如下:
+ 基于已有的树切分测试数据:
+ 如果存在任一子集是一棵树,则在该子集递归剪枝过程
+ 计算将当前两个叶节点合并后的误差
+ 计算不合并的误差
+ 如果合并会降低误差的话,就将叶节点合并
+```
+## Python中GUI的使用
+
+> 使用 Python 的 Tkinter 库创建 GUI
+
+```
+ 如果能让用户不需要任何指令就可以按照他们自己的方式来分析数据,就不需要对数据做出过多解释。其中一个能同时支持数据呈现和用户交互的方式就是
+构建一个图形用户界面(GUI,Graphical User Interface),如图9-7所示。
+```
+
+
+
+> 用 Tkinter 创建 GUI
+
+```
+ Python 有很多 GUI 框架,其中一个易于使用的 Tkinter,是随 Python 的标准版编译版本发布的。Tkinter 可以在 Windows、Mac OS和大多数的 Linux 平台上使用。
+```
+
+> 集成 Matplotlib 和 Tkinter
+
+```
+ MatPlotlib 的构建程序包含一个前端,也就是面向用户的一些代码,如 plot() 和 scatter() 方法等。事实上,它同时创建了一个后端,用于实现绘图和不同应用之间接口。
+通过改变后端可以将图像绘制在PNG、PDF、SVG等格式的文件上。下面将设置后端为 TkAgg (Agg 是一个 C++ 的库,可以从图像创建光栅图)。TkAgg可以在所选GUI框架上调用Agg,
+把 Agg 呈现在画布上。我们可以在Tk的GUI上放置一个画布,并用 .grid()来调整布局。
+```
+
+> 用treeExplore 的GUI构建的模型树示例图
+
+
+
+
+## 树回归小结
+
+ 数据集中经常包含一些复杂的相关关系,使得输入数据和目标变量之间呈现非线性关系。对这些复杂的关系建模,一种可行的方式是使用树来对预测值分段,
+包括分段常数或分段直线。一般采用树结构来对这种数据建模。相应地,若叶节点使用的模型是分段常数则称为回归树,若叶节点使用的模型师线性回归方程则称为模型树。
+ CART算法可以用于构建二元树并处理离散型或连续型数据的切分。若使用不同的误差准则,就可以通过CART算法构建模型树和回归树。该算法构建出的树会倾向于
+对数据过拟合。一棵过拟合的树常常十分复杂,剪枝技术的出现就是为了解决这个问题。两种剪枝方法分别是预剪枝(在树的构建过程中就进行剪枝)和后剪枝(当树
+构建完毕再进行剪枝),预剪枝更有效但需要用户定义一些参数。
+ Tkinter 是 Python 的一个 GUI 工具包。虽然并不是唯一的包,但它最常用。利用 Tkinter ,我们可以轻轻松松绘制各种部件并安排它们的位置。另外,可以为
+Tkinter 构造一个特殊的部件来显示 Matplotlib 绘出的图。所以,Matplotlib 和 Tkinter 的集成可以构建出更强大的 GUI ,用户可以以更自然的方式来探索机器学习算法的奥妙。
\ No newline at end of file
diff --git a/images/3.DecisionTree/Matplotlib绘制树形图.png b/images/3.DecisionTree/Matplotlib绘制树形图.png
new file mode 100644
index 00000000..77346689
Binary files /dev/null and b/images/3.DecisionTree/Matplotlib绘制树形图.png differ
diff --git a/images/3.DecisionTree/决策树划分数据集时的数据路径.png b/images/3.DecisionTree/决策树划分数据集时的数据路径.png
new file mode 100644
index 00000000..35da61d6
Binary files /dev/null and b/images/3.DecisionTree/决策树划分数据集时的数据路径.png differ
diff --git a/images/4.NaiveBayesian/朴素贝叶斯_首页.png b/images/4.NaiveBayesian/朴素贝叶斯_首页.png
new file mode 100644
index 00000000..4643335c
Binary files /dev/null and b/images/4.NaiveBayesian/朴素贝叶斯_首页.png differ
diff --git a/images/4.NaiveBayesian/朴素贝叶斯示例数据分布.png b/images/4.NaiveBayesian/朴素贝叶斯示例数据分布.png
new file mode 100644
index 00000000..52568fbc
Binary files /dev/null and b/images/4.NaiveBayesian/朴素贝叶斯示例数据分布.png differ
diff --git a/images/4.NaiveBayesian/贝叶斯条件概率.png b/images/4.NaiveBayesian/贝叶斯条件概率.png
new file mode 100644
index 00000000..9e0abb26
Binary files /dev/null and b/images/4.NaiveBayesian/贝叶斯条件概率.png differ
diff --git a/images/5.Logistic/Logistic回归Sigmoid函数.png b/images/5.Logistic/Logistic回归Sigmoid函数.png
new file mode 100644
index 00000000..a35fc097
Binary files /dev/null and b/images/5.Logistic/Logistic回归Sigmoid函数.png differ
diff --git a/images/5.Logistic/Logistic回归首页.png b/images/5.Logistic/Logistic回归首页.png
new file mode 100644
index 00000000..f81687d7
Binary files /dev/null and b/images/5.Logistic/Logistic回归首页.png differ
diff --git a/images/5.Logistic/梯度上升算法.png b/images/5.Logistic/梯度上升算法.png
new file mode 100644
index 00000000..701e19e6
Binary files /dev/null and b/images/5.Logistic/梯度上升算法.png differ
diff --git a/images/8.Regression/局部加权线性回归效果图.png b/images/8.Regression/局部加权线性回归效果图.png
new file mode 100644
index 00000000..13293b8c
Binary files /dev/null and b/images/8.Regression/局部加权线性回归效果图.png differ
diff --git a/images/8.Regression/岭回归示例图.png b/images/8.Regression/岭回归示例图.png
new file mode 100644
index 00000000..a77f39c1
Binary files /dev/null and b/images/8.Regression/岭回归示例图.png differ
diff --git a/images/8.Regression/线性回归效果图.png b/images/8.Regression/线性回归效果图.png
new file mode 100644
index 00000000..4a241d14
Binary files /dev/null and b/images/8.Regression/线性回归效果图.png differ
diff --git a/images/8.Regression/逐步线性回归示例图.png b/images/8.Regression/逐步线性回归示例图.png
new file mode 100644
index 00000000..dbbffe45
Binary files /dev/null and b/images/8.Regression/逐步线性回归示例图.png differ
diff --git a/images/8.Regression/预测数值型数据回归首页.png b/images/8.Regression/预测数值型数据回归首页.png
new file mode 100644
index 00000000..581d3483
Binary files /dev/null and b/images/8.Regression/预测数值型数据回归首页.png differ
diff --git a/images/9.TreeRegression/CART构建数据集回归树的简单数据集.png b/images/9.TreeRegression/CART构建数据集回归树的简单数据集.png
new file mode 100644
index 00000000..a74bc5cb
Binary files /dev/null and b/images/9.TreeRegression/CART构建数据集回归树的简单数据集.png differ
diff --git a/images/9.TreeRegression/GUI更好的示例图.png b/images/9.TreeRegression/GUI更好的示例图.png
new file mode 100644
index 00000000..dac18e2c
Binary files /dev/null and b/images/9.TreeRegression/GUI更好的示例图.png differ
diff --git a/images/9.TreeRegression/GUI示例图.png b/images/9.TreeRegression/GUI示例图.png
new file mode 100644
index 00000000..f268dc85
Binary files /dev/null and b/images/9.TreeRegression/GUI示例图.png differ
diff --git a/images/9.TreeRegression/树回归首页.png b/images/9.TreeRegression/树回归首页.png
new file mode 100644
index 00000000..5d91a22b
Binary files /dev/null and b/images/9.TreeRegression/树回归首页.png differ
diff --git a/images/9.TreeRegression/模型树示例图.png b/images/9.TreeRegression/模型树示例图.png
new file mode 100644
index 00000000..790a3606
Binary files /dev/null and b/images/9.TreeRegression/模型树示例图.png differ
diff --git a/images/9.TreeRegression/测试回归树的分段常数数据集.png b/images/9.TreeRegression/测试回归树的分段常数数据集.png
new file mode 100644
index 00000000..46a00980
Binary files /dev/null and b/images/9.TreeRegression/测试回归树的分段常数数据集.png differ