更新完k-近邻算法的md文件

This commit is contained in:
jiangzhonglian
2017-04-24 21:59:38 +08:00
parent 7523f61dc8
commit 4e7a420985
4 changed files with 97 additions and 22 deletions

View File

@@ -1,20 +1,92 @@
# 2. k-近邻算法
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script>
* k-近邻算法的特点
* 优点:精度高、对异常值不敏感、无数据输入假定
* 缺点:计算复杂度高、空间复杂度高
* 适用数据范围:数值型和标称型
* 工作原理
* 已知样本数据集的每一个数据的特征和所属分类,将新数据的特征与样本数据进行比较,找到最相似(最近邻)的k(通常k <= 20)个数据。选择k个数据中出现次数最多的分类作为新数据的分类。
* k-近邻算法的一般流程
* 收集数据:任何方法
* 准备数据:距离计算所需要的数值,最好是结构化的数据格式
* 分析数据:任何方法
* 测试数据:计算错误率
* 使用算法输入样本数据和结构化的输出结果然后运行k-近邻算法判断输入数据分类属于哪个分类,最后对计算出的分类执行后续处理
* 总结
* 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)
众说周知,电影可以按照题材分类的;而我们的确知道每部电影在风格上的确可能和同题材的电影相近。
那么动作片和爱情片是否存在着明显的差别呢?
例如: 1.打斗次数 2.亲吻次数
使用k-近邻算法构造程序,自动划分电影的题材类型。
## k-近邻分类算法
> k-近邻(kNNk-NearestNeighbor)算法的工作原理
```
存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。
输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本中特征最相似数据(最近邻)的分类
标签。一般来说我们只选择样本数据集中前k个最相似的数据这就是k-近邻算法中k的来历。通常k是一个不大于20的整数。
最后选择k个最相似数据中出现次数最多的分类作为新数据的分类
```
![电影视频案例](/images/2.KNN/knn-1-movie.png)
> k-近邻算法的特点
```
优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型和标称型
```
> k-近邻算法的一般流程
```
收集数据:任何方法
准备数据:距离计算所需要的数值,最好是结构化的数据格式
分析数据:任何方法
训练算法此步骤不适用于k-近邻算法
测试算法:计算错误率
使用算法输入样本数据和结构化的输出结果然后运行k-近邻算法判断输入数据分类属于哪个分类,最后对计算出的分类执行后续处理
```
> kNN算法伪代码
```
对未知类别属性的数据集中的每个点一次执行一下操作:
(1)计算已知类别数据集中的点与当前点之间的距离
(2)按照距离递增次序排序
(3)选取与当前点距离最小的k个点
(4)确定前k个点所在类别的出现频率
(5)返回前k个点出现频率最高的类别作为当前点的预测分类
```
## 从文本文件中解析和导入数据
> 示例在约会网站上使用k-近邻算法
```
收集数据:提供文本文件
准备数据使用Python解析文本文件
分析数据使用Mapplotlib画二维扩散图
训练算法此步骤不适用于k-近邻算法
测试算法:使用海伦提供的部分数据作为测试样本。
测试样本和非测试样本的区别在于:
测试样本是意境完成分类的数据,如果预测分类与实际类别不同,则标记为一个错误。
使用算法:产生简单的命令行程序,然后海伦可以输入一些特征数据以判断对方是否为自己喜欢的类型。
```
## 使用Matplotlib创建扩散图
```Python
import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2])
plt.show()
```
## 归一化数值(将数值转化到01之间)
样本3和样本4的距离
$$\sqrt{(0-67)^2 + (20000-32000)^2 + (1.1-0.1)^2 }$$
我们很容易发现: 上面方程中数字差值最大的属性对计算结果的影响最大。
![约会网站案例](/images/2.KNN/knn-2-date.png)
## 总结
* 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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

BIN
images/2.KNN/knn-2-date.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

View File

@@ -38,7 +38,7 @@ def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
# tile生成和训练样本对应的矩阵并与训练样本求差
"""
tile: 列-3表示复制的行 行-12表示对inx的重复的次数
tile: 列-3表示复制的行 行-12表示对inx的重复的次数
In [8]: tile(inx, (3, 1))
Out[8]:
@@ -69,8 +69,10 @@ def classify0(inX, dataSet, labels, k):
sqDistances = sqDiffMat.sum(axis=1)
# 开方
distances = sqDistances ** 0.5
# 距离排序
# 根据距离排序从小到大的排序,返回对应的索引位置
# print 'distances=', distances
sortedDistIndicies = distances.argsort()
# print 'distances.argsort()=', sortedDistIndicies
# 2. 选择距离最小的k个点
classCount = {}
@@ -127,7 +129,7 @@ def autoNorm(dataSet):
:return: 归一化后的数据集normDataSet,ranges和minVals即最小值与范围并没有用到
归一化公式:
Y = (X-Xmin)-(Xmax-Xmin)
Y = (X-Xmin)/(Xmax-Xmin)
"""
# 计算每种属性的最大值、最小值、范围
minVals = dataSet.min(0)
@@ -160,7 +162,7 @@ def datingClassTest():
print 'numTestVecs=', numTestVecs
errorCount = 0.0
for i in range(numTestVecs):
# 对数据测试
# 对数据测试
classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])
if (classifierResult != datingLabels[i]): errorCount += 1.0
@@ -195,6 +197,7 @@ def handwritingClassTest():
fileStr = fileNameStr.split('.')[0] # take off .txt
classNumStr = int(fileStr.split('_')[0])
hwLabels.append(classNumStr)
# 将 32*32的矩阵->1*1024的矩阵
trainingMat[i, :] = img2vector('input/2.KNN/trainingDigits/%s' % fileNameStr)
# 2. 导入测试数据