diff --git a/.gitignore b/.gitignore index 0de90e72..6564ff4a 100644 --- a/.gitignore +++ b/.gitignore @@ -88,5 +88,3 @@ ENV/ # Rope project settings .ropeproject .vscode - - diff --git a/README.md b/README.md index 4aec5c83..83034041 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,11 @@ * 3) 决策树 * [决策树](./docs/3.决策树.md) * 4) 基于概率论的分类方法:朴素贝叶斯 + * [朴素贝叶斯](./docs/4.朴素贝叶斯.md) * 5) Logistic回归 * [Logistic回归](./docs/5.Logistic回归.md) * 6) 支持向量机 + * [支持向量机](./docs/6.支持向量机.md) * 7) 利用AdaBoost元算法提高分类 ## 第二部分 利用回归预测数值型数据 diff --git a/docs/10.k-means聚类.md b/docs/10.k-means聚类.md new file mode 100644 index 00000000..33d0a0f1 --- /dev/null +++ b/docs/10.k-means聚类.md @@ -0,0 +1,21 @@ + +# 10) k-means聚类 +* 聚类介绍 + * 聚类是一种无监督的学习,它将相似的对象归到一个簇中。 + * 聚类分析试图将相似对象归入同一簇,将不相似对象归到不同簇。相似这一概念取决于所选择的相似度计算方法。 +* K-均值聚类算法 + * 优点 : 容易实现 + * 缺点 : 可能收敛到局部最小值,在大规模数据集上收敛较慢。 + * 使用数据类型 : 数值型数据。 +* K-均值算法工作流程 + * 首先,随机确定 k 个初始点作为质心。 + * 然后,将数据集中的每个点分配到一个簇中。(为每个点找到距其最近的质心,并将其分配给该质心所对应的簇) + * 最后,每个簇的质心更新为该簇所有点的平均值。 +* K-均值算法伪代码如下 + * 创建 k 个点作为起始质心(通常是随机选择) + * 当任意一个点的簇分配结果发生改变时 + * 对数据集中的每个数据点 + * 对每个质心 + * 计算质心与数据点之间的距离 + * 将数据点分配到距其最近的簇 + * 对每一个簇,计算簇中所有点的均值并将均值作为质心 diff --git a/docs/4.朴素贝叶斯.md b/docs/4.朴素贝叶斯.md new file mode 100644 index 00000000..0c1f0f6e --- /dev/null +++ b/docs/4.朴素贝叶斯.md @@ -0,0 +1,50 @@ + +# 4) 朴素贝叶斯 + + + +* 假设: 特征之间强(朴素)独立 +* 概率模型 + + * P(C|F1F2...Fn) = P(F1F2...Fn|C)P(C) / P(F1F2...Fn) + + * 由于对于所有类别,P(F1F2...Fn)都是相同的,比较P(C|F1F2...Fn)只用比较P(F1F2...Fn|C)P(C)就好了 + +* 朴素贝叶斯的特点 + + * 优点:在数据较少的情况下仍然有效,可以处理多类别问题 + + * 缺点:对于输入数据的准备方式较为敏感 + + * 适用数据类型:标称型数据 + +* 朴素贝叶斯的一般过程 + + * 收集数据:可以使用任何方法 + + * 准备数据:需要数值型或者布尔型数据 + + * 分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好。 + + * 训练算法:计算不同的独立特征的条件概率 + + * 测试算法:计算错误率 + + * 使用算法:文本分类等 + +* 优化 + + * 为了避免一个概率为0导致P(F1|C)*P(F2|C)....P(Fn|C)整个为0,所以优化为将所有词的出现数都初始化为1,并将分母初始化为2. + + * 由于大部分因子比较小,乘积之后得到的数不易比较,程序误差较大。所以取对数后可将乘法转化为加法:P(F1|C)*P(F2|C)....P(Fn|C)P(C) -> log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C)) + +* 总结 + + * 这一块代码比较乱,最好先把公式理一理再看 + + * 可以参考一下[阮一峰的博客](http://www.ruanyifeng.com/blog/2013/12/naive_bayes_classifier.html) + + + + + diff --git a/docs/6.支持向量机.md b/docs/6.支持向量机.md new file mode 100644 index 00000000..021fa531 --- /dev/null +++ b/docs/6.支持向量机.md @@ -0,0 +1,25 @@ + +# 6) 支持向量机 + +* 基本概念 + + * 假设有两组数据,我们可以用一条线将这两个数据集分隔开,这条直线称为分隔超平面 + (当维数很高时称为分隔超平面)。 + * 我们希望找到离分隔超平面最近的点,确保它们离分隔面的距离尽可能远。 + * 支持向量就是离分隔超平面最近的那些点。 + +* 支持向量机特点 + + * 优点:泛化错误率低,计算开销不大,结果易解释。 + * 缺点:对参数调节和核函数的选择敏感,原始分类器不加修改仅适用于处理二类问题。 + * 适用数据类型:数值型和标称型数据。 + +* SVM应用的一般流程 + 1. 准备收集数据:可以使用任何方法。 + 2. 准备数据:需要数值型数据。 + 3. 分析数据:有助于可视化分隔超平面。 + 4. 训练算法:SVM的大部分时间都花在训练上,该过程主要实现两个参数的调优。 + 5. 测试算法:测试分类结果是否达到预期的目的。 + 6. 使用算法:几乎所有分类问题都可以使用SVM,值得一提的是,SVM本身是一个二类分类器, + 对多类问题应用SVM需要对代码做一些修改。 + diff --git a/docs/8.预测数值型数据:回归.md b/docs/8.预测数值型数据:回归.md new file mode 100644 index 00000000..90b975ad --- /dev/null +++ b/docs/8.预测数值型数据:回归.md @@ -0,0 +1,18 @@ + +# 8)Ԥֵݣع + +* Իعص + * ŵ㣺⣬ϲӡ + * ȱ㣺ԷԵϲá + * ݷΧֵͺͱݡ +* ԭ + * عĿԤֵ͵Ŀֱֵӵİ취ԼдһĿֵļ㹫ʽ +* عһ + * ռݣκη + * ׼ݣعҪֵݣݽתɶֵݡ + * ݣݵĿӶάͼڶͷڲ»عϵ֮󣬿Խ߻ͼΪԱȡ + * ѵ㷨ҵعϵ + * ݣʹRƽԤֵݵ϶ȣģ͵Ч + * ʹ㷨ʹûع飬ڸʱԤһֵǶԷ෽ΪԤݶɢǩ +* ܽ + * عϵĹ̾ǻع顣 diff --git a/src/python/08.Predictive numerical data regression/regression.py b/src/python/08.Predictive numerical data regression/regression.py new file mode 100644 index 00000000..be857aa7 --- /dev/null +++ b/src/python/08.Predictive numerical data regression/regression.py @@ -0,0 +1,258 @@ +''' +Create by ApacheCN-xy +Date from 2017-02-27 +''' + + +from numpy import * + +def loadDataSet(fileName): #解析以tab键分隔的文件中的浮点数 + numFeat = len(open(fileName).readline().split('\t')) - 1 #获得一行有几个字段 + dataMat = []; labelMat = [] + fr = open(fileName) + for line in fr.readlines(): #读取每一行 + lineArr =[] + curLine = line.strip().split('\t') #删除每一行的开头和结尾的tab + for i in range(numFeat):#从0到3,不包含3 + lineArr.append(float(curLine[i]))#将数据添加到lineArr List中 + dataMat.append(lineArr) + labelMat.append(float(curLine[-1])) + return dataMat,labelMat + +def standRegres(xArr,yArr): #线性回归 + xMat = mat(xArr); yMat = mat(yArr).T + xTx = xMat.T*xMat + if linalg.det(xTx) == 0.0: + print ("This matrix is singular, cannot do inverse") + return + ws = xTx.I * (xMat.T*yMat) + return ws + +def lwlr(testPoint,xArr,yArr,k=1.0): + xMat = mat(xArr); yMat = mat(yArr).T + m = shape(xMat)[0] + weights = mat(eye((m))) + for j in range(m): #下面两行创建权重矩阵 + diffMat = testPoint - xMat[j,:] # + weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2)) + xTx = xMat.T * (weights * xMat) + if linalg.det(xTx) == 0.0: + print ("This matrix is singular, cannot do inverse") + return + ws = xTx.I * (xMat.T * (weights * yMat)) + return testPoint * ws + +def lwlrTest(testArr,xArr,yArr,k=1.0): #循环所有的数据点,并将lwlr运用于所有的数据点 + m = shape(testArr)[0] + yHat = zeros(m) + for i in range(m): + yHat[i] = lwlr(testArr[i],xArr,yArr,k) + return yHat + +def lwlrTestPlot(xArr,yArr,k=1.0): #首先将 X 排序,其余的都与lwlrTest相同,这样更容易绘图 + yHat = zeros(shape(yArr)) + xCopy = mat(xArr) + xCopy.sort(0) + for i in range(shape(xArr)[0]): + yHat[i] = lwlr(xCopy[i],xArr,yArr,k) + return yHat,xCopy + +def rssError(yArr,yHatArr): #yArr 和 yHatArr 两者都需要是数组 + return ((yArr-yHatArr)**2).sum() + +def ridgeRegres(xMat,yMat,lam=0.2): #岭回归 + xTx = xMat.T*xMat + denom = xTx + eye(shape(xMat)[1])*lam + if linalg.det(denom) == 0.0: + print "This matrix is singular, cannot do inverse" + return + ws = denom.I * (xMat.T*yMat) + return ws + +def ridgeTest(xArr,yArr): + xMat = mat(xArr); yMat=mat(yArr).T + yMean = mean(yMat,0) + yMat = yMat - yMean #Y取平均值以消除X0 + #regularize X's(正则化 X的)??? + xMeans = mean(xMat,0) #计算平均值然后减去它 + xVar = var(xMat,0) #然后计算除以 Xi的方差 + xMat = (xMat - xMeans)/xVar + numTestPts = 30 + wMat = zeros((numTestPts,shape(xMat)[1])) + for i in range(numTestPts): + ws = ridgeRegres(xMat,yMat,exp(i-10)) + wMat[i,:]=ws.T + return wMat + +def regularize(xMat):#按列进行规范化 + inMat = xMat.copy() + inMeans = mean(inMat,0) #计算平均值然后减去它 + inVar = var(inMat,0) #计算除以Xi的方差 + inMat = (inMat - inMeans)/inVar + return inMat + +def stageWise(xArr,yArr,eps=0.01,numIt=100): + xMat = mat(xArr); yMat=mat(yArr).T + yMean = mean(yMat,0) + yMat = yMat - yMean #也可以规则化ys但会得到更小的coef + xMat = regularize(xMat) + m,n=shape(xMat) + #returnMat = zeros((numIt,n)) #测试代码删除 + ws = zeros((n,1)); wsTest = ws.copy(); wsMax = ws.copy() + for i in range(numIt): + print ws.T + lowestError = inf; + for j in range(n): + for sign in [-1,1]: + wsTest = ws.copy() + wsTest[j] += eps*sign + yTest = xMat*wsTest + rssE = rssError(yMat.A,yTest.A) + if rssE < lowestError: + lowestError = rssE + wsMax = wsTest + ws = wsMax.copy() + #returnMat[i,:]=ws.T + #return returnMat + +#def scrapePage(inFile,outFile,yr,numPce,origPrc): +# from BeautifulSoup import BeautifulSoup +# fr = open(inFile); fw=open(outFile,'a') #a is append mode writing +# soup = BeautifulSoup(fr.read()) +# i=1 +# currentRow = soup.findAll('table', r="%d" % i) +# while(len(currentRow)!=0): +# title = currentRow[0].findAll('a')[1].text +# lwrTitle = title.lower() +# if (lwrTitle.find('new') > -1) or (lwrTitle.find('nisb') > -1): +# newFlag = 1.0 +# else: +# newFlag = 0.0 +# soldUnicde = currentRow[0].findAll('td')[3].findAll('span') +# if len(soldUnicde)==0: +# print "item #%d did not sell" % i +# else: +# soldPrice = currentRow[0].findAll('td')[4] +# priceStr = soldPrice.text +# priceStr = priceStr.replace('$','') #strips out $ +# priceStr = priceStr.replace(',','') #strips out , +# if len(soldPrice)>1: +# priceStr = priceStr.replace('Free shipping', '') #strips out Free Shipping +# print "%s\t%d\t%s" % (priceStr,newFlag,title) +# fw.write("%d\t%d\t%d\t%f\t%s\n" % (yr,numPce,newFlag,origPrc,priceStr)) +# i += 1 +# currentRow = soup.findAll('table', r="%d" % i) +# fw.close() + +from time import sleep +import json +import urllib2 +def searchForSet(retX, retY, setNum, yr, numPce, origPrc): + sleep(10) + myAPIstr = 'AIzaSyD2cR2KFyx12hXu6PFU-wrWot3NXvko8vY' + searchURL = 'https://www.googleapis.com/shopping/search/v1/public/products?key=%s&country=US&q=lego+%d&alt=json' % (myAPIstr, setNum) + pg = urllib2.urlopen(searchURL) + retDict = json.loads(pg.read()) + for i in range(len(retDict['items'])): + try: + currItem = retDict['items'][i] + if currItem['product']['condition'] == 'new': + newFlag = 1 + else: newFlag = 0 + listOfInv = currItem['product']['inventories'] + for item in listOfInv: + sellingPrice = item['price'] + if sellingPrice > origPrc * 0.5: + print "%d\t%d\t%d\t%f\t%f" % (yr,numPce,newFlag,origPrc, sellingPrice) + retX.append([yr, numPce, newFlag, origPrc]) + retY.append(sellingPrice) + except: print 'problem with item %d' % i + +def setDataCollect(retX, retY): + searchForSet(retX, retY, 8288, 2006, 800, 49.99) + searchForSet(retX, retY, 10030, 2002, 3096, 269.99) + searchForSet(retX, retY, 10179, 2007, 5195, 499.99) + searchForSet(retX, retY, 10181, 2007, 3428, 199.99) + searchForSet(retX, retY, 10189, 2008, 5922, 299.99) + searchForSet(retX, retY, 10196, 2009, 3263, 249.99) + +def crossValidation(xArr,yArr,numVal=10): + m = len(yArr) + indexList = range(m) + errorMat = zeros((numVal,30))#create error mat 30columns numVal rows创建error mat 30columns numVal 行 + for i in range(numVal): + trainX=[]; trainY=[] + testX = []; testY = [] + random.shuffle(indexList) + for j in range(m):#create training set based on first 90% of values in indexList + #基于indexList中的前90%的值创建训练集 + if j < m*0.9: + trainX.append(xArr[indexList[j]]) + trainY.append(yArr[indexList[j]]) + else: + testX.append(xArr[indexList[j]]) + testY.append(yArr[indexList[j]]) + wMat = ridgeTest(trainX,trainY) #get 30 weight vectors from ridge + for k in range(30):#loop over all of the ridge estimates + matTestX = mat(testX); matTrainX=mat(trainX) + meanTrain = mean(matTrainX,0) + varTrain = var(matTrainX,0) + matTestX = (matTestX-meanTrain)/varTrain #regularize test with training params + yEst = matTestX * mat(wMat[k,:]).T + mean(trainY)#test ridge results and store + errorMat[i,k]=rssError(yEst.T.A,array(testY)) + #print errorMat[i,k] + meanErrors = mean(errorMat,0)#calc avg performance of the different ridge weight vectors + minMean = float(min(meanErrors)) + bestWeights = wMat[nonzero(meanErrors==minMean)] + #can unregularize to get model + #when we regularized we wrote Xreg = (x-meanX)/var(x) + #we can now write in terms of x not Xreg: x*w/var(x) - meanX/var(x) +meanY + xMat = mat(xArr); yMat=mat(yArr).T + meanX = mean(xMat,0); varX = var(xMat,0) + unReg = bestWeights/varX + print "the best model from Ridge Regression is:\n",unReg + print "with constant term: ",-1*sum(multiply(meanX,unReg)) + mean(yMat) + + + + + + + + + + + #test for xianxinghuigui + def regression1(): + xArr, yArr = loadDataSet("ex0.txt") + xMat = mat(xArr) + yMat = mat(yArr) + ws = standRegres(xArr, yArr) + fig = plt.figure() + ax = fig.add_subplot(111) + ax.scatter(xMat[:, 1].flatten(), yMat.T[:, 0].flatten().A[0]) + xCopy = xMat.copy() + xCopy.sort(0) + yHat = xCopy * ws + ax.plot(xCopy[:, 1], yHat) + plt.show() + +if __name__ == "__main__": + regression1() + + + #test for jiaquanhuigui + def regression1(): + xArr, yArr = loadDataSet("ex0.txt") + yHat = lwlrTest(xArr, xArr, yArr, 0.003) + xMat = mat(xArr) + srtInd = xMat[:,1].argsort(0) + xSort=xMat[srtInd][:,0,:] + fig = plt.figure() + ax = fig.add_subplot(111) + ax.plot(xSort[:,1], yHat[srtInd]) + ax.scatter(xMat[:,1].flatten().A[0], mat(yArr).T.flatten().A[0] , s=2, c='red') + plt.show() + +if __name__ == "__main__": + regression1() \ No newline at end of file diff --git a/src/python/10.kmeans/kMeans.py b/src/python/10.kmeans/kMeans.py new file mode 100644 index 00000000..b485ce14 --- /dev/null +++ b/src/python/10.kmeans/kMeans.py @@ -0,0 +1,50 @@ +#!/usr/bin/python +# coding:utf8 + +from numpy import * + +# 从文本中构建矩阵,加载文本文件,然后处理 +def loadDataSet(fileName): # 通用函数,用来解析以 tab 键分隔的 floats(浮点数) + dataMat = [] # assume last column is target value + fr = open(fileName) + for line in fr.readlines(): + curLine = line.strip().split('\t') + fltLine = map(float,curLine) # 映射所有的元素为 float(浮点数)类型 + dataMat.append(fltLine) + return dataMat + +# 计算两个向量的欧式距离(可根据场景选择) +def distEclud(vecA, vecB): + return sqrt(sum(power(vecA - vecB, 2))) # la.norm(vecA-vecB) + +# 为给定数据集构建一个包含 k 个随机质心的集合。随机质心必须要在整个数据集的边界之内,这可以通过找到数据集每一维的最小和最大值来完成。然后生成 0~1.0 之间的随机数并通过取值范围和最小值,以便确保随机点在数据的边界之内。 +def randCent(dataSet, k): + n = shape(dataSet)[1] # 列数 + centroids = mat(zeros((k,n))) # 创建质心矩阵 + for j in range(n): # 穿件随机簇质心,并且在每一维的边界内 + minJ = min(dataSet[:,j]) + rangeJ = float(max(dataSet[:,j]) - minJ) + centroids[:,j] = mat(minJ + rangeJ * random.rand(k,1)) # 随机生成 + return centroids + +# k-means 聚类算法 +def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent): + m = shape(dataSet)[0] + clusterAssment = mat(zeros((m,2))) # 创建矩阵来分配数据点到质心中 + centroids = createCent(dataSet, k) + clusterChanged = True + while clusterChanged: + clusterChanged = False + for i in range(m): # 循环每一个数据点并分配到最近的质心中去 + minDist = inf; minIndex = -1 + for j in range(k): + distJI = distMeas(centroids[j,:],dataSet[i,:]) + if distJI < minDist: + minDist = distJI; minIndex = j + if clusterAssment[i,0] != minIndex: clusterChanged = True + clusterAssment[i,:] = minIndex,minDist**2 + print centroids + for cent in range(k): # 重新计算质心 + ptsInClust = dataSet[nonzero(clusterAssment[:,0].A==cent)[0]] # 获取该簇中的所有点 + centroids[cent,:] = mean(ptsInClust, axis=0) # 分配质心 + return centroids, clusterAssment