diff --git "a/docs/1.\346\234\272\345\231\250\345\255\246\344\271\240\345\237\272\347\241\200.md" "b/docs/1.\346\234\272\345\231\250\345\255\246\344\271\240\345\237\272\347\241\200.md" index 433d938b9..7833fabea 100644 --- "a/docs/1.\346\234\272\345\231\250\345\255\246\344\271\240\345\237\272\347\241\200.md" +++ "b/docs/1.\346\234\272\345\231\250\345\255\246\344\271\240\345\237\272\347\241\200.md" @@ -1,5 +1,6 @@ +# 第1章 机器学习基础 -# 1. 机器学习基础 +![机器学习基础_首页](/images/1.MLFoundation/机器学习基础-首页.jpg) 我们会利用计算机来彰显数据背后的真实含义,这才是机器学习的真实含义。 diff --git "a/docs/2.k-\350\277\221\351\202\273\347\256\227\346\263\225.md" "b/docs/2.k-\350\277\221\351\202\273\347\256\227\346\263\225.md" index 94b14b26e..6deccb78d 100644 --- "a/docs/2.k-\350\277\221\351\202\273\347\256\227\346\263\225.md" +++ "b/docs/2.k-\350\277\221\351\202\273\347\256\227\346\263\225.md" @@ -1,20 +1,94 @@ -# 2. k-近邻算法 - -* 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) +# 第2章 k-近邻算法 +<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script> + +![k-近邻算法_首页](/images/2.KNN/knn-0-headpage.jpg) + +众说周知,电影可以按照题材分类的;而我们的确知道每部电影在风格上的确可能和同题材的电影相近。 +那么动作片和爱情片是否存在着明显的差别呢? +例如: 1.打斗次数 2.亲吻次数 +使用k-近邻算法构造程序,自动划分电影的题材类型。 + +## k-近邻分类算法 + +> k-近邻(kNN,k-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() +``` + +## 归一化数值(将数值转化到:0~1之间) + +样本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) diff --git "a/docs/6.\346\224\257\346\214\201\345\220\221\351\207\217\346\234\272.md" "b/docs/6.\346\224\257\346\214\201\345\220\221\351\207\217\346\234\272.md" index 83f1a5dfd..db200c71b 100644 --- "a/docs/6.\346\224\257\346\214\201\345\220\221\351\207\217\346\234\272.md" +++ "b/docs/6.\346\224\257\346\214\201\345\220\221\351\207\217\346\234\272.md" @@ -1,4 +1,4 @@ -# 6) 支持向量机 +# 第6章 支持向量机 <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script> ![支持向量机_首页](/images/6.SVM/SVM_1.jpg) diff --git "a/images/1.MLFoundation/\346\234\272\345\231\250\345\255\246\344\271\240\345\237\272\347\241\200-\351\246\226\351\241\265.jpg" "b/images/1.MLFoundation/\346\234\272\345\231\250\345\255\246\344\271\240\345\237\272\347\241\200-\351\246\226\351\241\265.jpg" new file mode 100644 index 000000000..a2f2a2423 Binary files /dev/null and "b/images/1.MLFoundation/\346\234\272\345\231\250\345\255\246\344\271\240\345\237\272\347\241\200-\351\246\226\351\241\265.jpg" differ diff --git a/images/2.KNN/knn-0-headpage.jpg b/images/2.KNN/knn-0-headpage.jpg new file mode 100644 index 000000000..13c6c4dc2 Binary files /dev/null and b/images/2.KNN/knn-0-headpage.jpg differ diff --git a/images/2.KNN/knn-1-movie.png b/images/2.KNN/knn-1-movie.png new file mode 100644 index 000000000..ee0c06092 Binary files /dev/null and b/images/2.KNN/knn-1-movie.png differ diff --git a/images/2.KNN/knn-2-date.png b/images/2.KNN/knn-2-date.png new file mode 100644 index 000000000..649db7626 Binary files /dev/null and b/images/2.KNN/knn-2-date.png differ diff --git a/src/python/2.KNN/kNN.py b/src/python/2.KNN/kNN.py index 6b4de3374..9de7cd897 100644 --- a/src/python/2.KNN/kNN.py +++ b/src/python/2.KNN/kNN.py @@ -38,7 +38,7 @@ def classify0(inX, dataSet, labels, k): dataSetSize = dataSet.shape[0] # tile生成和训练样本对应的矩阵,并与训练样本求差 """ - tile: 列-3表示复制的行树, 行-1/2表示对inx的重复的次数 + tile: 列-3表示复制的行数, 行-1/2表示对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. 导入测试数据