From 60c922ea4593f9799ca28a2f2846baaece0aada6 Mon Sep 17 00:00:00 2001 From: jiangzhonglian Date: Mon, 27 Mar 2017 16:19:35 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0=207=20AdaBoost=E7=9A=84?= =?UTF-8?q?=20bagging=E5=92=8Cboosting=20=E9=80=9A=E4=BF=97=E6=A1=88?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/7.利用AdaBoost元算法提高分类.md | 2 ++ docs/9.树回归.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/7.利用AdaBoost元算法提高分类.md b/docs/7.利用AdaBoost元算法提高分类.md index 69036809..e9cdc3a7 100644 --- a/docs/7.利用AdaBoost元算法提高分类.md +++ b/docs/7.利用AdaBoost元算法提高分类.md @@ -11,6 +11,7 @@ * 2. 每个数据集都是通过在原始数据集中随机选择一个样本来进行替换(替换:意味着可以多次选择同一个样本,也就有重复值)而得到的。 * 3. 该算法作用的数据集就会得到S个分类器,与此同时,选择分类器投票结果中最多的类别作为最后的分类结果。 * 4. 例如:随机森林(random forest) + * 追美女:美女选择择偶对象的时候,会问几个闺蜜的建议,最后选择一个综合得分最高的一个作为男朋友 * boosting * boosting是一种与bagging很类似的技术。不论是boosting还是bagging当中,所使用的多个分类器的类型都是一致的。 * 区别是什么? @@ -19,6 +20,7 @@ * 3. 由于boosting分类的结果是基于所有分类器的加权求和结果的,因此boosting与bagging不太一样。 * 4. bagging中的分类器权重是相等的,而boosting中的分类器权重并不相等,每个权重代表的是其对应分类器在上一轮迭代中的成功度。 * 目前boosting方法最流行的版本是: AdaBoost。 + * 追美女:第1个帅哥失败->(传授经验:姓名、家庭情况) 第2个帅哥失败->(传授经验:兴趣爱好、性格特点) 第3个帅哥成功 * AdaBoost(adaptive boosting: 自适应boosting) * 能否使用弱分类器和多个实例来构建一个强分类器? 这是一个非常有趣的理论问题。 * 优点:泛化错误率低,易编码,可以应用在大部分分类器上,无参数调节。 diff --git a/docs/9.树回归.md b/docs/9.树回归.md index e3f23582..91acba04 100644 --- a/docs/9.树回归.md +++ b/docs/9.树回归.md @@ -3,7 +3,7 @@ * 树回归是什么? * 分类回归树(Classification and Regression Tree,CART)是一种典型的决策树算法,CART算法不仅可以应用于分类问题,而且可以用于回归问题。 - * CART算法构建的回归树并介绍其中的树剪枝技术(该技术主要的目的是防止数的过拟合) + * CART算法构建的回归树并介绍其中的树剪枝技术(该技术主要的目的是防止树的过拟合) * 树回归的构建 * 优点:可以对复杂和非线性的数据建模。 * 缺点:结果不易理解。 From a383e83d5fd87ac20b12e850f8f2609bc9e65f41 Mon Sep 17 00:00:00 2001 From: jiangzhonglian Date: Wed, 29 Mar 2017 23:08:09 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=9B=B4=E6=96=B09=20=E6=A0=91=E5=9B=9E?= =?UTF-8?q?=E5=BD=92=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/python/09.RegTrees/regTrees.py | 65 ++++++++++++++++----------- src/python/09.RegTrees/treeExplore.py | 2 +- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/python/09.RegTrees/regTrees.py b/src/python/09.RegTrees/regTrees.py index c95dcf54..c6077e0f 100644 --- a/src/python/09.RegTrees/regTrees.py +++ b/src/python/09.RegTrees/regTrees.py @@ -77,10 +77,10 @@ def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)): """chooseBestSplit(用最佳方式切分数据集 和 生成相应的叶节点) Args: - dataSet 数据集 - leafType 计算叶子节点的函数 - errType 求总方差 - ops [容许误差下降值,切分的最少样本数] + dataSet 加载的原始数据集 + leafType 建立叶子点的函数 + errType 误差计算函数(求总方差) + ops [容许误差下降值,切分的最少样本数] Returns: bestIndex feature的index坐标 bestValue 切分的最优值 @@ -128,6 +128,16 @@ def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)): # assume dataSet is NumPy Mat so we can array filtering def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)): + """createTree(获取回归树) + + Args: + dataSet 加载的原始数据集 + leafType 建立叶子点的函数 + errType 误差计算函数 + ops=(1, 4) [容许误差下降值,切分的最少样本数] + Returns: + retTree 决策树最后的结果 + """ # 选择最好的切分方式: feature索引值,最优切分值 # choose the best split feat, val = chooseBestSplit(dataSet, leafType, errType, ops) @@ -137,7 +147,7 @@ def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)): retTree = {} retTree['spInd'] = feat retTree['spVal'] = val - # 大于在右边,小于在左边 + # 大于在右边,小于在左边,分为2个数据集 lSet, rSet = binSplitDataSet(dataSet, feat, val) # 递归的进行调用 retTree['left'] = createTree(lSet, leafType, errType, ops) @@ -161,21 +171,25 @@ def getMean(tree): # 检查是否适合合并分枝 def prune(tree, testData): - # 判断是否测试数据集没有数据 + # 判断是否测试数据集没有数据,如果没有,就直接返回tree本身的均值 if shape(testData)[0] == 0: return getMean(tree) - # 对测试进行分支,看属于哪只分支,然后返回tree结果的均值 + + # 判断分枝是否是dict字典,如果是就将测试数据集进行切分 if (isTree(tree['right']) or isTree(tree['left'])): lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal']) + # 如果是左边分枝是字典,就传入左边的数据集和左边的分枝,进行递归 if isTree(tree['left']): tree['left'] = prune(tree['left'], lSet) + # 如果是右边分枝是字典,就传入左边的数据集和左边的分枝,进行递归 if isTree(tree['right']): tree['right'] = prune(tree['right'], rSet) - # 如果左右两边无子分支,那么计算一下总方差 和 该结果集的本身不分枝的总方差比较 - # 1.如果测试数据集足够大,将tree进行分支到最后 - # 2.如果测试数据集不够大,那么就无法进行合并 - # 注意返回的结果: 是合并后对原来为字典tree进行赋值,相当于进行了合并 + # 如果左右两边同时都不是dict字典,那么分割测试数据集。 + # 1. 如果正确 + # * 那么计算一下总方差 和 该结果集的本身不分枝的总方差比较 + # * 如果 合并的总方差 < 不合并的总方差,那么就进行合并 + # 注意返回的结果: 如果可以合并,原来的dict就变为了 数值 if not isTree(tree['left']) and not isTree(tree['right']): lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal']) # power(x, y)表示x的y次方 @@ -274,27 +288,28 @@ if __name__ == "__main__": # mat0, mat1 = binSplitDataSet(testMat, 1, 0.5) # print mat0, '\n-----------\n', mat1 - # 回归树 + # # 回归树 # myDat = loadDataSet('testData/RT_data1.txt') - # myDat = loadDataSet('testData/RT_data2.txt') + # # myDat = loadDataSet('testData/RT_data2.txt') # myMat = mat(myDat) # myTree = createTree(myMat) + # print myTree - # 1. 预剪枝就是,提起设置最大误差数和最少元素数 + # # 1. 预剪枝就是:提起设置最大误差数和最少元素数 # myDat = loadDataSet('testData/RT_data3.txt') # myMat = mat(myDat) # myTree = createTree(myMat, ops=(0, 1)) # print myTree - # 2.后剪枝 + # # 2.后剪枝就是:通过测试数据,对预测模型进行合并判断 # myDatTest = loadDataSet('testData/RT_data3test.txt') # myMat2Test = mat(myDatTest) # myFinalTree = prune(myTree, myMat2Test) # print '\n\n\n-------------------' # print myFinalTree - # -------- - # 模型树求解 + # # -------- + # # 模型树求解 # myDat = loadDataSet('testData/RT_data4.txt') # myMat = mat(myDat) # myTree = createTree(myMat, modelLeaf, modelErr) @@ -315,11 +330,11 @@ if __name__ == "__main__": print myTree2 print "模型树:", corrcoef(yHat2, testMat[:, 1],rowvar=0)[0, 1] - # 线性回归 - ws, X, Y = linearSolve(trainMat) - print ws - m = len(testMat[:, 0]) - yHat3 = mat(zeros((m, 1))) - for i in range(shape(testMat)[0]): - yHat3[i] = testMat[i, 0]*ws[1, 0] + ws[0, 0] - print "线性回归:", corrcoef(yHat3, testMat[:, 1],rowvar=0)[0, 1] + # # 线性回归 + # ws, X, Y = linearSolve(trainMat) + # print ws + # m = len(testMat[:, 0]) + # yHat3 = mat(zeros((m, 1))) + # for i in range(shape(testMat)[0]): + # yHat3[i] = testMat[i, 0]*ws[1, 0] + ws[0, 0] + # print "线性回归:", corrcoef(yHat3, testMat[:, 1],rowvar=0)[0, 1] diff --git a/src/python/09.RegTrees/treeExplore.py b/src/python/09.RegTrees/treeExplore.py index aa394f5d..a426a342 100644 --- a/src/python/09.RegTrees/treeExplore.py +++ b/src/python/09.RegTrees/treeExplore.py @@ -5,7 +5,7 @@ Created on 2017-03-08 Update on 2017-03-08 Tree-Based Regression Methods Source Code for Machine Learning in Action Ch. 9 -@author: jiangzhonglian +@author: Peter/片刻 ''' import regTrees from Tkinter import * From 1b4514cc0aa4b5be05fbf08af025dcddc11d5bcf Mon Sep 17 00:00:00 2001 From: jiangzhonglian Date: Wed, 29 Mar 2017 23:11:43 +0800 Subject: [PATCH 3/3] =?UTF-8?q?14.svd=20=09=E6=B7=BB=E5=8A=A0=E5=8E=8B?= =?UTF-8?q?=E7=BC=A9=E5=9B=BE=E7=89=87=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/python/14.SVD/svdRec.py | 122 +++++++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 17 deletions(-) diff --git a/src/python/14.SVD/svdRec.py b/src/python/14.SVD/svdRec.py index 1cb6b482..1c877e05 100644 --- a/src/python/14.SVD/svdRec.py +++ b/src/python/14.SVD/svdRec.py @@ -1,11 +1,13 @@ #!/usr/bin/python +# -*- coding: utf-8 -*- # encoding: utf-8 -from numpy import * from numpy import linalg as la +from numpy import * def loadExData(): + """ # 利用SVD提高推荐效果,菜肴矩阵 return[[2, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5], @@ -18,7 +20,7 @@ def loadExData(): [0, 0, 0, 0, 0, 0, 5, 0, 0, 5, 0], [0, 0, 0, 3, 0, 0, 0, 0, 4, 5, 0], [1, 1, 2, 1, 1, 2, 1, 0, 4, 5, 0]] -""" + # 推荐引擎示例矩阵 return[[4, 4, 0, 2, 2], [4, 0, 0, 3, 3], @@ -27,8 +29,8 @@ def loadExData(): [2, 2, 2, 0, 0], [1, 1, 1, 0, 0], [5, 5, 5, 0, 0]] - - 原矩阵 + """ + # 原矩阵 return[[1, 1, 1, 0, 0], [2, 2, 2, 0, 0], [1, 1, 1, 0, 0], @@ -36,25 +38,24 @@ def loadExData(): [1, 1, 0, 2, 2], [0, 0, 0, 3, 3], [0, 0, 0, 1, 1]] -""" -# 欧氏距离相似度,假定inA和inB 都是列向量 -# 计算向量的第二范式,相当于计算了欧氏距离 +# 相似度计算,假定inA和inB 都是列向量 +# 基于欧氏距离 def ecludSim(inA, inB): return 1.0/(1.0 + la.norm(inA - inB)) # pearsSim()函数会检查是否存在3个或更多的点。 -# corrcoef直接计算皮尔逊相关系数 +# corrcoef直接计算皮尔逊相关系数,范围[-1, 1],归一化后[0, 1] def pearsSim(inA, inB): # 如果不存在,该函数返回1.0,此时两个向量完全相关。 if len(inA) < 3: return 1.0 - return 0.5 + 0.5*corrcoef(inA, inB, rowvar=0)[0][1] + return 0.5 + 0.5 * corrcoef(inA, inB, rowvar = 0)[0][1] -# 计算余弦相似度 +# 计算余弦相似度,如果夹角为90度,相似度为0;如果两个向量的方向相同,相似度为1.0 def cosSim(inA, inB): num = float(inA.T*inB) denom = la.norm(inA)*la.norm(inB) @@ -80,10 +81,11 @@ def standEst(dataMat, user, simMeas, item): # 变量overLap 给出的是两个物品当中已经被评分的那个元素 overLap = nonzero(logical_and(dataMat[:, item].A>0, dataMat[:, j].A>0))[0] # 如果相似度为0,则两着没有任何重合元素,终止本次循环 - if len(overLap) == 0:similarity =0 + if len(overLap) == 0: + similarity = 0 # 如果存在重合的物品,则基于这些重合物重新计算相似度。 - else: similarity = simMeas(dataMat[overLap,item], \ - dataMat[overLap,j]) + else: + similarity = simMeas(dataMat[overLap, item], dataMat[overLap, j]) # print 'the %d and %d similarity is : %f'(iten,j,similarity) # 相似度会不断累加,每次计算时还考虑相似度和当前用户评分的乘积 # similarity 用户相似度, userRating 用户评分 @@ -105,8 +107,9 @@ def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst): # 如果不存在未评分物品,那么就退出函数 if len(unratedItems) == 0: return 'you rated everything' - # 在所有的未评分物品上进行循环 + # 物品的编号和评分值 itemScores = [] + # 在未评分物品上进行循环 for item in unratedItems: estimatedScore = estMethod(dataMat, user, simMeas, item) # 寻找前N个未评级物品,调用standEst()来产生该物品的预测得分,该物品的编号和估计值会放在一个元素列表itemScores中 @@ -118,10 +121,12 @@ def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst): # 基于SVD的评分估计 # 在recommend() 中,这个函数用于替换对standEst()的调用,该函数对给定用户给定物品构建了一个评分估计值 def svdEst(dataMat, user, simMeas, item): + # 物品数目 n = shape(dataMat)[1] # 对数据集进行SVD分解 simTotal = 0.0 ratSimTotal = 0.0 + # 奇异值分解 # 在SVD分解之后,我们只利用包含了90%能量值的奇异值,这些奇异值会以NumPy数组的形式得以保存 U, Sigma, VT = la.svd(dataMat) # 如果要进行矩阵运算,就必须要用这些奇异值构建出一个对角矩阵 @@ -138,7 +143,7 @@ def svdEst(dataMat, user, simMeas, item): similarity = simMeas(xformedItems[item, :].T,xformedItems[j, :].T) # for 循环中加入了一条print语句,以便了解相似度计算的进展情况。如果觉得累赘,可以去掉 print 'the %d and %d similarity is: %f' % (item, j, similarity) - # 对相似度求和 + # 对相似度不断累加求和 simTotal += similarity # 对相似度及对应评分值的乘积求和 ratSimTotal += similarity * userRating @@ -149,7 +154,90 @@ def svdEst(dataMat, user, simMeas, item): return ratSimTotal/simTotal +# 图像压缩函数 +# 打印矩阵 +def printMat(inMat, thresh=0.8): + # 由于矩阵保护了浮点数,因此定义浅色和深色,遍历所有矩阵元素,当元素大于阀值时打印1,否则打印0 + for i in range(32): + for k in range(32): + if float(inMat[i, k]) > thresh: + print 1, + else: + print 0, + print '' + + +# 实现图像压缩,允许基于任意给定的奇异值数目来重构图像 +def imgCompress(numSV=3, thresh=0.8): + # 构建一个列表 + myl = [] + # 打开文本文件,并从文件以数组方式读入字符 + for line in open('testData/testDigits/0_5.txt').readlines(): + newRow = [] + for i in range(32): + newRow.append(int(line[i])) + myl.append(newRow) + # 矩阵调入后,就可以在屏幕上输出该矩阵 + myMat = mat(myl) + print "****original matrix****" + # 对原始图像进行SVD分解并重构图像e + printMat(myMat, thresh) + # 通过Sigma 重新构成SigRecom来实现 + # Sigma是一个对角矩阵,因此需要建立一个全0矩阵,然后将前面的那些奇异值填充到对角线上。 + U, Sigma, VT = la.svd(myMat) + SigRecon = mat(zeros((numSV, numSV))) + for k in range(numSV): + SigRecon[k, k] = Sigma[k] + reconMat = U[:, :numSV] * SigRecon * VT[:numSV, :] + print "****reconstructed matrix using %d singular values *****" % numSV + printMat(reconMat, thresh) + + if __name__ == "__main__": + """ + # 对矩阵进行SVD分解 + Data = loadExData() + U, Sigma, VT = linalg.svd(Data) + # 打印Sigma的结果,因为前3个数值比其他的值大了很多,为9.72140007e+00,5.29397912e+00,6.84226362e-01 + # 后两个值比较小,每台机器输出结果可能有不同可以将这两个值去掉 + # print Sigma + + # 重构一个3x3的矩阵Sig3 + # Sig3 = mat([[Sigma[0], 0, 0], [0, Sigma[1], 0], [0, 0, Sigma[2]]]) + # print U[:, :3] * Sig3 * VT[:3, :] + """ + + """ + # 计算欧氏距离 myMat = mat(loadExData()) - print myMat - print recommend(myMat, 1, estMethod=svdEst) + # print myMat + print ecludSim(myMat[:, 0], myMat[:, 4]) + print ecludSim(myMat[:, 0], myMat[:, 0]) + + # 计算余弦相似度 + print cosSim(myMat[:, 0], myMat[:, 4]) + print cosSim(myMat[:, 0], myMat[:, 0]) + + # 计算皮尔逊相关系数 + print pearsSim(myMat[:, 0], myMat[:, 4]) + print pearsSim(myMat[:, 0], myMat[:, 0]) + + """ + + """ + # 默认推荐 + print recommend(myMat, 2) + """ + + """ + # 计算相似度的方法 + # 计算相似度的第一种方式 + # print recommend(myMat, 1, estMethod=svdEst) + # 计算相似度的第二种方式 + print recommend(myMat, 1, estMethod = svdEst, simMeas=pearsSim) + """ + + """ + # 压缩图片 + # imgCompress(2) + """