mirror of
https://github.com/apachecn/ailearning.git
synced 2026-11-05 06:48:35 +08:00
Merge pull request #121 from jiangzhonglian/master
更新 7.集成方法 md文档+ 更新 3.决策树 md+更新 13.PCA md文档
This commit is contained in:
@@ -2,14 +2,7 @@
|
||||
|
||||

|
||||
|
||||
> 场景描述:
|
||||
|
||||
* 我们正通过电视而非现场观看体育比赛,在电视的纯平显示器上有一个球。
|
||||
* 显示器大概包含了100万像素,而球则可能是由较少的像素组成,例如说一千个像素。
|
||||
* 人们实时的将显示器上的百万像素转换成为一个三维图像,该图像就给出运动场上球的位置。
|
||||
* 在这个过程中,人们已经将数据从一百万维降至了三维。这就被称为`降维(dimensionality reduction)`
|
||||
|
||||
## 降维技术
|
||||
## 降维技术 概述
|
||||
|
||||
> 数据显示并非大规模特征下的唯一难题,对数据进行简化还有如下一系列的原因:
|
||||
|
||||
@@ -48,25 +41,49 @@
|
||||
* 假设数据为多个数据源的混合观察结果,这些数据源之间在统计上是相互独立的,而在PCA中只假设数据是不相关的。
|
||||
* 同因子分析一样,如果数据源的数目少于观察数据的数目,则可以实现降维过程。
|
||||
|
||||
## 主成分分析(PCA)
|
||||
|
||||
> PCA的优缺点
|
||||
## 降维技术 场景
|
||||
|
||||
* 优点:降低数据的复杂性,识别最重要的多个特征。
|
||||
* 缺点:不一定需要,且可能损失有用信息。
|
||||
* 适用数据类型:数值型数据。
|
||||
* 我们正通过电视而非现场观看体育比赛,在电视的纯平显示器上有一个球。
|
||||
* 显示器大概包含了100万像素,而球则可能是由较少的像素组成,例如说一千个像素。
|
||||
* 人们实时的将显示器上的百万像素转换成为一个三维图像,该图像就给出运动场上球的位置。
|
||||
* 在这个过程中,人们已经将数据从一百万维降至了三维。这就被称为`降维(dimensionality reduction)`
|
||||
|
||||
> 通过PCA进行降维处理,我们就可以同时获得SVM和决策树的优点:
|
||||
|
||||
* 一方面,得到了和决策树一样简单的分类器,同时分类间隔和SVM一样好。
|
||||
* 1.第一个主成分就是来自于数据差异性最大(即 方差最大)的方向提取出来
|
||||
* 2.第二个主成分就是来自于数据差异性次大的方向,并且该方向于第一个主成分方向正交。
|
||||
* 3.通过数据集的协方差矩阵及其特征值分析,我们就可以得到这些主成分的值。
|
||||
* 一旦得到了协方差矩阵的特征向量,我们就可以保留最大的N个值。这些特征向量也给出了N个最重要特征的真实结构。我们可以通过将数据乘上这N个特征向量而将它转换到新的空间。
|
||||
* 例如下图:
|
||||
* 
|
||||
## PCA
|
||||
|
||||
## 对半导体数据进行降维处理
|
||||
### PCA 概述
|
||||
|
||||
主成分分析(Principal Component Analysis, PCA):`通俗理解:就是找出一个最主要的特征,然后进行分析。`
|
||||
|
||||
### PCA 场景
|
||||
|
||||
`例如: 考察一个人的智力情况,就直接看数学成绩就行(存在:数学、语文、英语成绩)`
|
||||
|
||||
### PCA 原理
|
||||
|
||||
> PCA 工作原理
|
||||
|
||||
通过PCA进行降维处理,我们就可以同时获得SVM和决策树的优点:(得到了和决策树一样简单的分类器,同时分类间隔和SVM一样好)
|
||||
1. 第一个主成分就是来自于数据差异性最大(即: `方差最大`)的方向提取出来
|
||||
2. 第二个主成分就是来自于数据差异性次大的方向,并且该方向于第一个主成分方向`正交(orthogonal 如果是二维空间就叫垂直)`。
|
||||
3. 通过数据集的协方差矩阵及其特征值分析,我们就可以得到这些主成分的值。
|
||||
4. 一旦得到了协方差矩阵的特征向量,我们就可以保留最大的N个值。这些特征向量也给出了N个最重要特征的真实结构。
|
||||
我们可以通过将数据乘上这N个特征向量而将它转换到新的空间。
|
||||
|
||||
例如下图:
|
||||
|
||||

|
||||
|
||||
> PCA 优缺点
|
||||
|
||||
```
|
||||
优点:降低数据的复杂性,识别最重要的多个特征。
|
||||
缺点:不一定需要,且可能损失有用信息。
|
||||
适用数据类型:数值型数据。
|
||||
```
|
||||
|
||||
### 项目案例: 对半导体数据进行降维处理
|
||||
|
||||
```
|
||||
半导体是在一些极为先进的工厂中制造出来的。设备的生命早期有限,并且话费极其巨大。
|
||||
@@ -79,6 +96,7 @@
|
||||
目前该章节处理的方案是:将缺失值NaN(Not a Number缩写),全部用平均值来替代(如果用0来处理的策略就太差劲了)。
|
||||
```
|
||||
|
||||
|
||||
## 本章小节
|
||||
|
||||
```
|
||||
|
||||
126
docs/3.决策树.md
126
docs/3.决策树.md
@@ -89,11 +89,11 @@
|
||||
|
||||
```
|
||||
收集数据:可以使用任何方法
|
||||
准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化。
|
||||
分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期。
|
||||
准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化
|
||||
分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期
|
||||
训练算法:构造树的数据结构
|
||||
测试算法:使用经验树计算错误率
|
||||
使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。
|
||||
测试算法:使用决策树执行分类
|
||||
使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义
|
||||
```
|
||||
|
||||
> 收集数据:可以使用任何方法
|
||||
@@ -102,7 +102,7 @@
|
||||
|
||||
我们利用 createDataSet() 函数输入数据
|
||||
|
||||
```Python
|
||||
```python
|
||||
def createDataSet():
|
||||
dataSet = [[1, 1, 'yes'],
|
||||
[1, 1, 'yes'],
|
||||
@@ -112,13 +112,17 @@ def createDataSet():
|
||||
labels = ['no surfacing', 'flippers']
|
||||
return dataSet, labels
|
||||
```
|
||||
> 准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化。
|
||||
> 准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化
|
||||
|
||||
此处,由于我们输入的数据本身就是离散化数据,所以这一步就省略了。
|
||||
|
||||
计算给定数据集的香农熵
|
||||
> 分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期
|
||||
|
||||
```Python
|
||||

|
||||
|
||||
计算给定数据集的香农熵的函数
|
||||
|
||||
```python
|
||||
def calcShannonEnt(dataSet):
|
||||
# 求list的长度,表示计算参与训练的数据量
|
||||
numEntries = len(dataSet)
|
||||
@@ -145,20 +149,55 @@ def calcShannonEnt(dataSet):
|
||||
|
||||
按照给定特征划分数据集
|
||||
|
||||
```Python
|
||||
def splitDataSet(dataSet, axis, value):
|
||||
`将指定特征的特征值等于 value 的行剩下列作为子数据集。`
|
||||
|
||||
```python
|
||||
def splitDataSet(dataSet, index, value):
|
||||
"""splitDataSet(通过遍历dataSet数据集,求出index对应的colnum列的值为value的行)
|
||||
就是依据index列进行分类,如果index列的数据等于 value的时候,就要将 index 划分到我们创建的新的数据集中
|
||||
Args:
|
||||
dataSet 数据集 待划分的数据集
|
||||
index 表示每一行的index列 划分数据集的特征
|
||||
value 表示index列对应的value值 需要返回的特征的值。
|
||||
Returns:
|
||||
index列为value的数据集【该数据集需要排除index列】
|
||||
"""
|
||||
retDataSet = []
|
||||
for featVec in dataSet:
|
||||
if featVec[axis] == value:
|
||||
reducedFeatVec = featVec[:axis]
|
||||
reducedFeatVec.extend(featVec[axis+1:])
|
||||
for featVec in dataSet:
|
||||
# index列为value的数据集【该数据集需要排除index列】
|
||||
# 判断index列的值是否为value
|
||||
if featVec[index] == value:
|
||||
# chop out index used for splitting
|
||||
# [:index]表示前index行,即若 index 为2,就是取 featVec 的前 index 行
|
||||
reducedFeatVec = featVec[:index]
|
||||
'''
|
||||
请百度查询一下: extend和append的区别
|
||||
list.append(object) 向列表中添加一个对象object
|
||||
list.extend(sequence) 把一个序列seq的内容添加到列表中
|
||||
1、使用append的时候,是将new_media看作一个对象,整体打包添加到music_media对象中。
|
||||
2、使用extend的时候,是将new_media看作一个序列,将这个序列和music_media序列合并,并放在其后面。
|
||||
result = []
|
||||
result.extend([1,2,3])
|
||||
print result
|
||||
result.append([4,5,6])
|
||||
print result
|
||||
result.extend([7,8,9])
|
||||
print result
|
||||
结果:
|
||||
[1, 2, 3]
|
||||
[1, 2, 3, [4, 5, 6]]
|
||||
[1, 2, 3, [4, 5, 6], 7, 8, 9]
|
||||
'''
|
||||
reducedFeatVec.extend(featVec[index+1:])
|
||||
# [index+1:]表示从跳过 index 的 index+1行,取接下来的数据
|
||||
# 收集结果值 index列为value的行【该行需要排除index列】
|
||||
retDataSet.append(reducedFeatVec)
|
||||
return retDataSet
|
||||
```
|
||||
|
||||
选择最好的数据集划分方式
|
||||
|
||||
```Python
|
||||
```python
|
||||
def chooseBestFeatureToSplit(dataSet):
|
||||
"""chooseBestFeatureToSplit(选择最好的特征)
|
||||
|
||||
@@ -169,14 +208,14 @@ def chooseBestFeatureToSplit(dataSet):
|
||||
"""
|
||||
# 求第一行有多少列的 Feature, 最后一列是label列嘛
|
||||
numFeatures = len(dataSet[0]) - 1
|
||||
# label的信息熵
|
||||
# 数据集的原始信息熵
|
||||
baseEntropy = calcShannonEnt(dataSet)
|
||||
# 最优的信息增益值, 和最优的Featurn编号
|
||||
bestInfoGain, bestFeature = 0.0, -1
|
||||
# iterate over all the features
|
||||
for i in range(numFeatures):
|
||||
# create a list of all the examples of this feature
|
||||
# 获取每一个实例的第i+1个feature,组成list集合
|
||||
# 获取对应的feature下的所有数据
|
||||
featList = [example[i] for example in dataSet]
|
||||
# get a set of unique values
|
||||
# 获取剔重后的集合,使用set对list数据进行去重
|
||||
@@ -187,7 +226,9 @@ def chooseBestFeatureToSplit(dataSet):
|
||||
# 遍历当前特征中的所有唯一属性值,对每个唯一属性值划分一次数据集,计算数据集的新熵值,并对所有唯一特征值得到的熵求和。
|
||||
for value in uniqueVals:
|
||||
subDataSet = splitDataSet(dataSet, i, value)
|
||||
# 计算概率
|
||||
prob = len(subDataSet)/float(len(dataSet))
|
||||
# 计算信息熵
|
||||
newEntropy += prob * calcShannonEnt(subDataSet)
|
||||
# gain[信息增益]: 划分数据集前后的信息变化, 获取信息熵最大的值
|
||||
# 信息增益是熵的减少或者是数据无序度的减少。最后,比较所有特征中的信息增益,返回最好特征划分的索引值。
|
||||
@@ -199,11 +240,17 @@ def chooseBestFeatureToSplit(dataSet):
|
||||
return bestFeature
|
||||
```
|
||||
|
||||
```
|
||||
问:上面的 newEntropy 为什么是根据子集计算的呢?
|
||||
答:因为我们在根据一个特征计算香农熵的时候,该特征的分类值是相同,这个特征这个分类的香农熵为 0;
|
||||
这就是为什么计算新的香农熵的时候使用的是子集。
|
||||
```
|
||||
|
||||
> 训练算法:构造树的数据结构
|
||||
|
||||
创建树的函数代码
|
||||
创建树的函数代码如下:
|
||||
|
||||
```Python
|
||||
```python
|
||||
def createTree(dataSet, labels):
|
||||
classList = [example[-1] for example in dataSet]
|
||||
# 如果数据集的最后一列的第一个值出现的次数=整个集合的数量,也就说只有一个类别,就只直接返回结果就行
|
||||
@@ -237,7 +284,36 @@ def createTree(dataSet, labels):
|
||||
return myTree
|
||||
```
|
||||
|
||||
> 测试算法:使用经验树计算错误率
|
||||
> 测试算法:使用决策树执行分类
|
||||
|
||||
```python
|
||||
def classify(inputTree, featLabels, testVec):
|
||||
"""classify(给输入的节点,进行分类)
|
||||
|
||||
Args:
|
||||
inputTree 决策树模型
|
||||
featLabels Feature标签对应的名称
|
||||
testVec 测试输入的数据
|
||||
Returns:
|
||||
classLabel 分类的结果值,需要映射label才能知道名称
|
||||
"""
|
||||
# 获取tree的根节点对于的key值
|
||||
firstStr = inputTree.keys()[0]
|
||||
# 通过key得到根节点对应的value
|
||||
secondDict = inputTree[firstStr]
|
||||
# 判断根节点名称获取根节点在label中的先后顺序,这样就知道输入的testVec怎么开始对照树来做分类
|
||||
featIndex = featLabels.index(firstStr)
|
||||
# 测试数据,找到根节点对应的label位置,也就知道从输入的数据的第几位来开始分类
|
||||
key = testVec[featIndex]
|
||||
valueOfFeat = secondDict[key]
|
||||
print '+++', firstStr, 'xxx', secondDict, '---', key, '>>>', valueOfFeat
|
||||
# 判断分枝是否结束: 判断valueOfFeat是否是dict类型
|
||||
if isinstance(valueOfFeat, dict):
|
||||
classLabel = classify(valueOfFeat, featLabels, testVec)
|
||||
else:
|
||||
classLabel = valueOfFeat
|
||||
return classLabel
|
||||
```
|
||||
|
||||
> 使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。
|
||||
|
||||
@@ -247,7 +323,7 @@ def createTree(dataSet, labels):
|
||||
|
||||
#### 项目概述
|
||||
|
||||
隐形眼镜类型包括应材质、软材质以及不适合佩戴隐形眼镜。我们需要使用决策树预测患者需要佩戴的隐形眼镜类型。
|
||||
隐形眼镜类型包括硬材质、软材质以及不适合佩戴隐形眼镜。我们需要使用决策树预测患者需要佩戴的隐形眼镜类型。
|
||||
|
||||
#### 开发流程
|
||||
|
||||
@@ -270,20 +346,20 @@ presbyopic myope no reduced no lenses
|
||||
|
||||
> 解析数据:解析 tab 键分隔的数据行
|
||||
|
||||
```Python
|
||||
```python
|
||||
lecses = [inst.strip().split('\t') for inst in fr.readlines()]
|
||||
lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']
|
||||
```
|
||||
|
||||
> 分析数据:快速检查数据,确保正确地解析数据内容,使用 createPlot() 函数绘制最终的树形图。
|
||||
|
||||
```Python
|
||||
```python
|
||||
>>> treePlotter.createPlot(lensesTree)
|
||||
```
|
||||
|
||||
> 训练算法:使用 createTree() 函数
|
||||
|
||||
```Python
|
||||
```python
|
||||
>>> lensesTree = trees.createTree(lenses, lensesLabels)
|
||||
>>> lensesTree
|
||||
{'tearRate': {'reduced': 'no lenses', 'normal': {'astigmatic':{'yes':
|
||||
@@ -299,7 +375,7 @@ lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']
|
||||
|
||||
使用 pickle 模块存储决策树
|
||||
|
||||
```Python
|
||||
```python
|
||||
def storeTree(inputTree, filename):
|
||||
impory pickle
|
||||
fw = open(filename, 'w')
|
||||
|
||||
@@ -84,26 +84,24 @@
|
||||
适用数据范围:数值型和标称型
|
||||
```
|
||||
|
||||
### 项目案例: 随机森林
|
||||
|
||||

|
||||
### 项目案例: 声纳信号分类
|
||||
|
||||
#### 项目概述
|
||||
|
||||
这是 Gorman 和 Sejnowski 在研究使用神经网络的声纳信号分类中使用的数据集。任务是训练一个网络来区分声纳信号。
|
||||
这是 Gorman 和 Sejnowski 在研究使用神经网络的声纳信号分类中使用的数据集。任务是训练一个模型来区分声纳信号。
|
||||
|
||||
#### 开发流程
|
||||
|
||||
```
|
||||
收集数据:提供的文本文件。
|
||||
准备数据:转换样本集。
|
||||
分析数据:手工检查数据。
|
||||
训练算法:在数据上,利用 random_forest() 函数进行优化评估,返回模型的综合分类结果。
|
||||
测试算法:在采用自定义 n_folds 循环的随机重抽样就行测试评估,得出综合的预测评分。
|
||||
使用算法:本例没有完成此步骤,若你感兴趣可以构建完整的应用程序,从案例进行封装,就可以构造一个实际运行的类似系统
|
||||
收集数据:提供的文本文件
|
||||
准备数据:转换样本集
|
||||
分析数据:手工检查数据
|
||||
训练算法:在数据上,利用 random_forest() 函数进行优化评估,返回模型的综合分类结果
|
||||
测试算法:在采用自定义 n_folds 份随机重抽样 进行测试评估,得出综合的预测评分
|
||||
使用算法:若你感兴趣可以构建完整的应用程序,从案例进行封装,也可以参考我们的代码
|
||||
```
|
||||
|
||||
> 收集数据:提供的文本文件。
|
||||
> 收集数据:提供的文本文件
|
||||
|
||||
样本数据:sonar-all-data.txt
|
||||
|
||||
@@ -141,17 +139,17 @@ def loadDataSet(filename):
|
||||
|
||||
> 训练算法:在数据上,利用 random_forest() 函数进行优化评估,返回模型的综合分类结果
|
||||
|
||||
* 数据随机化
|
||||
* 样本数据随机无放回抽样-用于交叉验证
|
||||
|
||||
```python
|
||||
def cross_validation_split(dataset, n_folds):
|
||||
"""cross_validation_split(将数据集进行抽重抽样 n_folds 份,数据可以重复重复抽取,每一次list的元素是无重复的)
|
||||
"""cross_validation_split(将数据集进行抽重抽样 n_folds 份,数据可以重复重复抽取)
|
||||
|
||||
Args:
|
||||
dataset 原始数据集
|
||||
n_folds 数据集dataset分成n_flods份
|
||||
Returns:
|
||||
dataset_split list集合,存放的是:将数据集进行抽重抽样 n_folds 份,数据可以重复重复抽取,每一次list的元素是无重复的
|
||||
dataset_split list集合,存放的是:将数据集进行抽重抽样 n_folds 份,数据可以重复重复抽取
|
||||
"""
|
||||
dataset_split = list()
|
||||
dataset_copy = list(dataset) # 复制一份 dataset,防止 dataset 的内容改变
|
||||
@@ -163,13 +161,38 @@ def cross_validation_split(dataset, n_folds):
|
||||
index = randrange(len(dataset_copy))
|
||||
# 将对应索引 index 的内容从 dataset_copy 中导出,并将该内容从 dataset_copy 中删除。
|
||||
# pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。
|
||||
# fold.append(dataset_copy.pop(index)) # 无放回的方式
|
||||
fold.append(dataset_copy[index]) # 有放回的方式
|
||||
fold.append(dataset_copy.pop(index)) # 无放回的方式
|
||||
# fold.append(dataset_copy[index]) # 有放回的方式
|
||||
dataset_split.append(fold)
|
||||
# 由dataset分割出的n_folds个数据构成的列表,为了用于交叉验证
|
||||
return dataset_split
|
||||
```
|
||||
|
||||
* 训练数据集随机化
|
||||
|
||||
```python
|
||||
# Create a random subsample from the dataset with replacement
|
||||
def subsample(dataset, ratio): # 创建数据集的随机子样本
|
||||
"""random_forest(评估算法性能,返回模型得分)
|
||||
|
||||
Args:
|
||||
dataset 训练数据集
|
||||
ratio 训练数据集的样本比例
|
||||
Returns:
|
||||
sample 随机抽样的训练样本
|
||||
"""
|
||||
|
||||
sample = list()
|
||||
# 训练样本的按比例抽样。
|
||||
# round() 方法返回浮点数x的四舍五入值。
|
||||
n_sample = round(len(dataset) * ratio)
|
||||
while len(sample) < n_sample:
|
||||
# 有放回的随机采样,有一些样本被重复采样,从而在训练集中多次出现,有的则从未在训练集中出现,此则自助采样法。从而保证每棵决策树训练集的差异性
|
||||
index = randrange(len(dataset))
|
||||
sample.append(dataset[index])
|
||||
return sample
|
||||
```
|
||||
|
||||
* 特征随机化
|
||||
|
||||
```python
|
||||
@@ -226,7 +249,7 @@ def random_forest(train, test, max_depth, min_size, sample_size, n_trees, n_feat
|
||||
return predictions
|
||||
```
|
||||
|
||||
> 测试算法:在采用自定义 n_folds 循环的随机重抽样就行测试评估,得出综合的预测评分。
|
||||
> 测试算法:在采用自定义 n_folds 份随机重抽样 进行测试评估,得出综合的预测评分。
|
||||
|
||||
* 计算随机森林的预测结果的正确率
|
||||
|
||||
@@ -238,13 +261,13 @@ def evaluate_algorithm(dataset, algorithm, n_folds, *args):
|
||||
Args:
|
||||
dataset 原始数据集
|
||||
algorithm 使用的算法
|
||||
n_folds 树的个数
|
||||
n_folds 数据的份数
|
||||
*args 其他的参数
|
||||
Returns:
|
||||
scores 模型得分
|
||||
"""
|
||||
|
||||
# 将数据集进行抽重抽样 n_folds 份,数据可以重复重复抽取,每一次 list 的元素是无重复的
|
||||
# 将数据集进行随机抽样,分成 n_folds 份,数据无重复的抽取
|
||||
folds = cross_validation_split(dataset, n_folds)
|
||||
scores = list()
|
||||
# 每次循环从 folds 从取出一个 fold 作为测试集,其余作为训练集,遍历整个 folds ,实现交叉验证
|
||||
@@ -279,7 +302,7 @@ def evaluate_algorithm(dataset, algorithm, n_folds, *args):
|
||||
return scores
|
||||
```
|
||||
|
||||
> 使用算法:本例没有完成此步骤,若你感兴趣可以构建完整的应用程序,从案例进行封装,就可以构造一个实际运行的类似系统
|
||||
> 使用算法:若你感兴趣可以构建完整的应用程序,从案例进行封装,也可以参考我们的代码
|
||||
|
||||
[完整代码地址](https://github.com/apachecn/MachineLearning/blob/master/src/python/7.RandomForest/randomForest.py): <https://github.com/apachecn/MachineLearning/blob/master/src/python/7.RandomForest/randomForest.py>
|
||||
|
||||
@@ -343,7 +366,7 @@ def evaluate_algorithm(dataset, algorithm, n_folds, *args):
|
||||
|
||||
> 收集数据:提供的文本文件。
|
||||
|
||||
训练数据:horseColicTraining.txt
|
||||
训练数据:horseColicTraining.txt<br/>
|
||||
测试数据:horseColicTest.txt
|
||||
|
||||
```
|
||||
@@ -378,6 +401,10 @@ def loadDataSet(fileName):
|
||||
|
||||

|
||||
|
||||
* 通俗来说:就是把一些噪音数据也拟合进去的,如下图。
|
||||
|
||||

|
||||
|
||||
> 训练算法:在数据上,利用 adaBoostTrainDS() 函数训练出一系列的分类器。
|
||||
|
||||
```python
|
||||
@@ -501,10 +528,12 @@ print m, errArr[predicting10 != mat(labelArrTest).T].sum(), errArr[predicting10
|
||||
> ROC 评估方法
|
||||
|
||||
* ROC 曲线: 最佳的分类器应该尽可能地处于左上角
|
||||
* 
|
||||
* 对不同的 ROC 曲线进行比较的一个指标是曲线下的面积(Area Unser the Curve, AUC).
|
||||
* AUC 给出的是分类器的平均性能值,当然它并不能完全代替对整条曲线的观察。
|
||||
* 一个完美分类器的 AUC 为1,而随机猜测的 AUC 则为0.5。
|
||||
|
||||

|
||||
|
||||
* 对不同的 ROC 曲线进行比较的一个指标是曲线下的面积(Area Unser the Curve, AUC).
|
||||
* AUC 给出的是分类器的平均性能值,当然它并不能完全代替对整条曲线的观察。
|
||||
* 一个完美分类器的 AUC 为1,而随机猜测的 AUC 则为0.5。
|
||||
|
||||
> 代价函数
|
||||
|
||||
|
||||
BIN
images/3.DecisionTree/熵的计算公式.jpg
Normal file
BIN
images/3.DecisionTree/熵的计算公式.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
images/7.AdaBoost/过拟合图解.png
Normal file
BIN
images/7.AdaBoost/过拟合图解.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 85 KiB |
@@ -7,10 +7,9 @@ Update on 2017-05-18
|
||||
@author: Peter Harrington/片刻
|
||||
《机器学习实战》更新地址:https://github.com/apachecn/MachineLearning
|
||||
'''
|
||||
print(__doc__)
|
||||
from numpy import *
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
print(__doc__)
|
||||
|
||||
|
||||
def loadDataSet(fileName, delim='\t'):
|
||||
@@ -106,6 +105,32 @@ def show_picture(dataMat, reconMat):
|
||||
plt.show()
|
||||
|
||||
|
||||
def analyse_data(dataMat):
|
||||
meanVals = mean(dataMat, axis=0)
|
||||
meanRemoved = dataMat-meanVals
|
||||
covMat = cov(meanRemoved, rowvar=0)
|
||||
eigvals, eigVects = linalg.eig(mat(covMat))
|
||||
eigValInd = argsort(eigvals)
|
||||
|
||||
topNfeat = 20
|
||||
eigValInd = eigValInd[:-(topNfeat+1):-1]
|
||||
cov_all_score = sum(eigvals)
|
||||
sum_cov_score = 0
|
||||
for i in range(0, len(eigValInd)):
|
||||
line_cov_score = eigvals[eigValInd[i]]
|
||||
sum_cov_score += line_cov_score
|
||||
'''
|
||||
我们发现其中有超过20%的特征值都是0。
|
||||
这就意味着这些特征都是其他特征的副本,也就是说,它们可以通过其他特征来表示,而本身并没有提供额外的信息。
|
||||
|
||||
最前面15个值的数量级大于10^5,实际上那以后的值都变得非常小。
|
||||
这就相当于告诉我们只有部分重要特征,重要特征的数目也很快就会下降。
|
||||
|
||||
最后,我们可能会注意到有一些小的负值,他们主要源自数值误差应该四舍五入成0.
|
||||
'''
|
||||
print '主成分:%s, 方差占比:%s%%, 累积方差占比:%s%%' % (format(i+1, '2.0f'), format(line_cov_score/cov_all_score*100, '4.1f'), format(sum_cov_score/cov_all_score*100, '4.1f'))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# # 加载数据,并转化数据类型为float
|
||||
# dataMat = loadDataSet('input/13.PCA/testSet.txt')
|
||||
@@ -119,30 +144,8 @@ if __name__ == "__main__":
|
||||
# 利用PCA对半导体制造数据降维
|
||||
dataMat = replaceNanWithMean()
|
||||
print shape(dataMat)
|
||||
# # 分析数据
|
||||
# analyse_data(dataMat)
|
||||
lowDmat, reconMat = pca(dataMat, 20)
|
||||
print shape(lowDmat)
|
||||
show_picture(dataMat, reconMat)
|
||||
|
||||
# meanVals = mean(dataMat, axis=0)
|
||||
# meanRemoved = dataMat-meanVals
|
||||
# covMat = cov(meanRemoved, rowvar=0)
|
||||
# eigvals, eigVects = linalg.eig(mat(covMat))
|
||||
# eigValInd = argsort(eigvals)
|
||||
|
||||
# topNfeat = 20
|
||||
# eigValInd = eigValInd[:-(topNfeat+1):-1]
|
||||
# cov_all_score = sum(eigvals)
|
||||
# sum_cov_score = 0
|
||||
# for i in range(0, len(eigValInd)):
|
||||
# line_cov_score = eigvals[eigValInd[i]]
|
||||
# sum_cov_score += line_cov_score
|
||||
# '''
|
||||
# 我们发现其中有超过20%的特征值都是0。
|
||||
# 这就意味着这些特征都是其他特征的副本,也就是说,它们可以通过其他特征来表示,而本身并没有提供额外的信息。
|
||||
|
||||
# 最前面15个值的数量级大于10^5,实际上那以后的值都变得非常小。
|
||||
# 这就相当于告诉我们只有部分重要特征,重要特征的数目也很快就会下降。
|
||||
|
||||
# 最后,我们可能会注意到有一些小的负值,他们主要源自数值误差应该四舍五入成0.
|
||||
# '''
|
||||
# print '主成分:%s, 方差占比:%s%%, 累积方差占比:%s%%' % (format(i+1, '2.0f'), format(line_cov_score/cov_all_score*100, '4.1f'), format(sum_cov_score/cov_all_score*100, '4.1f'))
|
||||
|
||||
@@ -75,24 +75,24 @@ def calcShannonEnt(dataSet):
|
||||
return shannonEnt
|
||||
|
||||
|
||||
def splitDataSet(dataSet, axis, value):
|
||||
"""splitDataSet(通过遍历dataSet数据集,求出axis对应的colnum列的值为value的行)
|
||||
就是依据axis列进行分类,如果axis列的数据等于 value的时候,就要将 axis 划分到我们创建的新的数据集中
|
||||
def splitDataSet(dataSet, index, value):
|
||||
"""splitDataSet(通过遍历dataSet数据集,求出index对应的colnum列的值为value的行)
|
||||
就是依据index列进行分类,如果index列的数据等于 value的时候,就要将 index 划分到我们创建的新的数据集中
|
||||
Args:
|
||||
dataSet 数据集 待划分的数据集
|
||||
axis 表示每一行的axis列 划分数据集的特征
|
||||
value 表示axis列对应的value值 需要返回的特征的值。
|
||||
index 表示每一行的index列 划分数据集的特征
|
||||
value 表示index列对应的value值 需要返回的特征的值。
|
||||
Returns:
|
||||
axis列为value的数据集【该数据集需要排除axis列】
|
||||
index列为value的数据集【该数据集需要排除index列】
|
||||
"""
|
||||
retDataSet = []
|
||||
for featVec in dataSet:
|
||||
# axis列为value的数据集【该数据集需要排除axis列】
|
||||
# 判断axis列的值是否为value
|
||||
if featVec[axis] == value:
|
||||
# chop out axis used for splitting
|
||||
# [:axis]表示前axis行,即若 axis 为2,就是取 featVec 的前 axis 行
|
||||
reducedFeatVec = featVec[:axis]
|
||||
# index列为value的数据集【该数据集需要排除index列】
|
||||
# 判断index列的值是否为value
|
||||
if featVec[index] == value:
|
||||
# chop out index used for splitting
|
||||
# [:index]表示前index行,即若 index 为2,就是取 featVec 的前 index 行
|
||||
reducedFeatVec = featVec[:index]
|
||||
'''
|
||||
请百度查询一下: extend和append的区别
|
||||
list.append(object) 向列表中添加一个对象object
|
||||
@@ -109,11 +109,11 @@ def splitDataSet(dataSet, axis, value):
|
||||
结果:
|
||||
[1, 2, 3]
|
||||
[1, 2, 3, [4, 5, 6]]
|
||||
[1, 2, 3, [4, 5, 6], 7, 8, 9
|
||||
[1, 2, 3, [4, 5, 6], 7, 8, 9]
|
||||
'''
|
||||
reducedFeatVec.extend(featVec[axis+1:])
|
||||
# [axis+1:]表示从跳过 axis 的 axis+1行,取接下来的数据
|
||||
# 收集结果值 axis列为value的行【该行需要排除axis列】
|
||||
reducedFeatVec.extend(featVec[index+1:])
|
||||
# [index+1:]表示从跳过 index 的 index+1行,取接下来的数据
|
||||
# 收集结果值 index列为value的行【该行需要排除index列】
|
||||
retDataSet.append(reducedFeatVec)
|
||||
return retDataSet
|
||||
|
||||
@@ -250,6 +250,7 @@ def grabTree(filename):
|
||||
fr = open(filename)
|
||||
return pickle.load(fr)
|
||||
|
||||
|
||||
def fishTest():
|
||||
# 1.创建数据和结果标签
|
||||
myDat, labels = createDataSet()
|
||||
@@ -269,10 +270,11 @@ def fishTest():
|
||||
myTree = createTree(myDat, copy.deepcopy(labels))
|
||||
print myTree
|
||||
# [1, 1]表示要取的分支上的节点位置,对应的结果值
|
||||
# print classify(myTree, labels, [1, 1])
|
||||
print classify(myTree, labels, [1, 1])
|
||||
|
||||
# 画图可视化展现
|
||||
# dtPlot.createPlot(myTree)
|
||||
dtPlot.createPlot(myTree)
|
||||
|
||||
|
||||
def ContactLensesTest():
|
||||
"""
|
||||
@@ -294,10 +296,9 @@ def ContactLensesTest():
|
||||
lensesTree = createTree(lenses, lensesLabels)
|
||||
print lensesTree
|
||||
# 画图可视化展现
|
||||
# dtPlot.createPlot(lensesTree)
|
||||
dtPlot.createPlot(lensesTree)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
fishTest()
|
||||
# ContactLensesTest()
|
||||
|
||||
# fishTest()
|
||||
ContactLensesTest()
|
||||
|
||||
@@ -87,7 +87,7 @@ def plotTree(myTree, parentPt, nodeTxt):
|
||||
plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)
|
||||
# 并打印输入对应的文字
|
||||
plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))
|
||||
# plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD
|
||||
plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD
|
||||
|
||||
|
||||
def createPlot(inTree):
|
||||
|
||||
BIN
src/python/3.DecisionTree/decisionTreePlot.pyc
Normal file
BIN
src/python/3.DecisionTree/decisionTreePlot.pyc
Normal file
Binary file not shown.
@@ -163,7 +163,7 @@ def build_tree(train, max_depth, min_size, n_features):
|
||||
# Make a prediction with a decision tree
|
||||
def predict(node, row): # 预测模型分类结果
|
||||
if row[node['index']] < node['value']:
|
||||
if isinstance(node['left'], dict): # isinstance是Python中的一个内建函数。是用来判断一个对象是否是一个已知的类型。
|
||||
if isinstance(node['left'], dict): # isinstance 是 Python 中的一个内建函数。是用来判断一个对象是否是一个已知的类型。
|
||||
return predict(node['left'], row)
|
||||
else:
|
||||
return node['left']
|
||||
@@ -258,7 +258,7 @@ def evaluate_algorithm(dataset, algorithm, n_folds, *args):
|
||||
Args:
|
||||
dataset 原始数据集
|
||||
algorithm 使用的算法
|
||||
n_folds 树的个数
|
||||
n_folds 数据的份数
|
||||
*args 其他的参数
|
||||
Returns:
|
||||
scores 模型得分
|
||||
|
||||
Reference in New Issue
Block a user