# -*- coding: UTF-8 -*- import numpy as np import operator import collections """ 函數說明:建立數據集 Parameters: 無 Returns: group - 數據集 labels - 分類標籤 """ def createDataSet(): #四組二維特徵 group = np.array([[1,101],[5,89],[108,5],[115,8]]) #四組特徵的標籤 labels = ['愛情片','愛情片','動做片','動做片'] return group, labels """ 函數說明:kNN算法,分類器 Parameters: inX - 用於分類的數據(測試集) dataSet - 用於訓練的數據(訓練集) labes - 分類標籤 k - kNN算法參數,選擇距離最小的k個點 Returns: sortedClassCount[0][0] - 分類結果 """ def classify0(inx, dataset, labels, k): # 計算距離 dist = np.sum((inx - dataset)**2, axis=1)**0.5 # k個最近的標籤 k_labels = [labels[index] for index in dist.argsort()[0 : k]] # 出現次數最多的標籤即爲最終類別 label = collections.Counter(k_labels).most_common(1)[0][0] return label if __name__ == '__main__': #建立數據集 group, labels = createDataSet() #測試集 test = [101,20] #kNN分類 test_class = classify0(test, group, labels, 3) #打印分類結果 print(test_class)
# -*- coding: UTF-8 -*- import numpy as np """ 函數說明:打開並解析文件,對數據進行分類:1表明不喜歡,2表明魅力通常,3表明極具魅力 Parameters: filename - 文件名 Returns: returnMat - 特徵矩陣 classLabelVector - 分類Label向量 """ def file2matrix(filename): #打開文件 fr = open(filename) #讀取文件全部內容 arrayOLines = fr.readlines() #獲得文件行數 numberOfLines = len(arrayOLines) #返回的NumPy矩陣,解析完成的數據:numberOfLines行,3列 returnMat = np.zeros((numberOfLines,3)) #返回的分類標籤向量 classLabelVector = [] #行的索引值 index = 0 for line in arrayOLines: #s.strip(rm),當rm空時,默認刪除空白符(包括'\n','\r','\t',' ') line = line.strip() #使用s.split(str="",num=string,cout(str))將字符串根據'\t'分隔符進行切片。 listFromLine = line.split('\t') #將數據前三列提取出來,存放到returnMat的NumPy矩陣中,也就是特徵矩陣 returnMat[index,:] = listFromLine[0:3] #根據文本中標記的喜歡的程度進行分類,1表明不喜歡,2表明魅力通常,3表明極具魅力 if listFromLine[-1] == 'didntLike': classLabelVector.append(1) elif listFromLine[-1] == 'smallDoses': classLabelVector.append(2) elif listFromLine[-1] == 'largeDoses': classLabelVector.append(3) index += 1 return returnMat, classLabelVector """ 函數說明:main函數 Parameters: 無 Returns: 無 """ if __name__ == '__main__': #打開的文件名 filename = "datingTestSet.txt" #打開並處理數據 datingDataMat, datingLabels = file2matrix(filename) print(datingDataMat) print(datingLabels)
""" 函數說明:可視化數據 Parameters: datingDataMat - 特徵矩陣 datingLabels - 分類Label Returns: 無 """ def showdatas(datingDataMat, datingLabels): #設置漢字格式 font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14) #將fig畫布分隔成1行1列,不共享x軸和y軸,fig畫布的大小爲(13,8) #當nrow=2,nclos=2時,表明fig畫布被分爲四個區域,axs[0][0]表示第一行第一個區域 fig, axs = plt.subplots(nrows=2, ncols=2,sharex=False, sharey=False, figsize=(13,8)) numberOfLabels = len(datingLabels) LabelsColors = [] for i in datingLabels: if i == 1: LabelsColors.append('black') if i == 2: LabelsColors.append('orange') if i == 3: LabelsColors.append('red') #畫出散點圖,以datingDataMat矩陣的第一(飛行常客例程)、第二列(玩遊戲)數據畫散點數據,散點大小爲15,透明度爲0.5 axs[0][0].scatter(x=datingDataMat[:,0], y=datingDataMat[:,1], color=LabelsColors,s=15, alpha=.5) #設置標題,x軸label,y軸label axs0_title_text = axs[0][0].set_title(u'每一年得到的飛行常客里程數與玩視頻遊戲所消耗時間佔比',FontProperties=font) axs0_xlabel_text = axs[0][0].set_xlabel(u'每一年得到的飛行常客里程數',FontProperties=font) axs0_ylabel_text = axs[0][0].set_ylabel(u'玩視頻遊戲所消耗時間佔',FontProperties=font) plt.setp(axs0_title_text, size=9, weight='bold', color='red') plt.setp(axs0_xlabel_text, size=7, weight='bold', color='black') plt.setp(axs0_ylabel_text, size=7, weight='bold', color='black') #畫出散點圖,以datingDataMat矩陣的第一(飛行常客例程)、第三列(冰激凌)數據畫散點數據,散點大小爲15,透明度爲0.5 axs[0][1].scatter(x=datingDataMat[:,0], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5) #設置標題,x軸label,y軸label axs1_title_text = axs[0][1].set_title(u'每一年得到的飛行常客里程數與每週消費的冰激淋公升數',FontProperties=font) axs1_xlabel_text = axs[0][1].set_xlabel(u'每一年得到的飛行常客里程數',FontProperties=font) axs1_ylabel_text = axs[0][1].set_ylabel(u'每週消費的冰激淋公升數',FontProperties=font) plt.setp(axs1_title_text, size=9, weight='bold', color='red') plt.setp(axs1_xlabel_text, size=7, weight='bold', color='black') plt.setp(axs1_ylabel_text, size=7, weight='bold', color='black') #畫出散點圖,以datingDataMat矩陣的第二(玩遊戲)、第三列(冰激凌)數據畫散點數據,散點大小爲15,透明度爲0.5 axs[1][0].scatter(x=datingDataMat[:,1], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5) #設置標題,x軸label,y軸label axs2_title_text = axs[1][0].set_title(u'玩視頻遊戲所消耗時間佔比與每週消費的冰激淋公升數',FontProperties=font) axs2_xlabel_text = axs[1][0].set_xlabel(u'玩視頻遊戲所消耗時間佔比',FontProperties=font) axs2_ylabel_text = axs[1][0].set_ylabel(u'每週消費的冰激淋公升數',FontProperties=font) plt.setp(axs2_title_text, size=9, weight='bold', color='red') plt.setp(axs2_xlabel_text, size=7, weight='bold', color='black') plt.setp(axs2_ylabel_text, size=7, weight='bold', color='black') #設置圖例 didntLike = mlines.Line2D([], [], color='black', marker='.', markersize=6, label='didntLike') smallDoses = mlines.Line2D([], [], color='orange', marker='.', markersize=6, label='smallDoses') largeDoses = mlines.Line2D([], [], color='red', marker='.', markersize=6, label='largeDoses') #添加圖例 axs[0][0].legend(handles=[didntLike,smallDoses,largeDoses]) axs[0][1].legend(handles=[didntLike,smallDoses,largeDoses]) axs[1][0].legend(handles=[didntLike,smallDoses,largeDoses]) #顯示圖片 plt.show()
""" 函數說明:對數據進行歸一化 Parameters: dataSet - 特徵矩陣 Returns: normDataSet - 歸一化後的特徵矩陣 ranges - 數據範圍 minVals - 數據最小值 """ def autoNorm(dataSet): #得到數據的最小值 minVals = dataSet.min(0) maxVals = dataSet.max(0) #最大值和最小值的範圍 ranges = maxVals - minVals #shape(dataSet)返回dataSet的矩陣行列數 normDataSet = np.zeros(np.shape(dataSet)) #返回dataSet的行數 m = dataSet.shape[0] #原始值減去最小值 normDataSet = dataSet - np.tile(minVals, (m, 1)) #除以最大和最小值的差,獲得歸一化數據 normDataSet = normDataSet / np.tile(ranges, (m, 1)) #返回歸一化數據結果,數據範圍,最小值 return normDataSet, ranges, minVals
# -*- coding: UTF-8 -*- import numpy as np import operator """ 函數說明:kNN算法,分類器 Parameters: inX - 用於分類的數據(測試集) dataSet - 用於訓練的數據(訓練集) labes - 分類標籤 k - kNN算法參數,選擇距離最小的k個點 Returns: sortedClassCount[0][0] - 分類結果 """ def classify0(inX, dataSet, labels, k): #numpy函數shape[0]返回dataSet的行數 dataSetSize = dataSet.shape[0] #在列向量方向上重複inX共1次(橫向),行向量方向上重複inX共dataSetSize次(縱向) diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet #二維特徵相減後平方 sqDiffMat = diffMat**2 #sum()全部元素相加,sum(0)列相加,sum(1)行相加 sqDistances = sqDiffMat.sum(axis=1) #開方,計算出距離 distances = sqDistances**0.5 #返回distances中元素從小到大排序後的索引值 sortedDistIndices = distances.argsort() #定一個記錄類別次數的字典 classCount = {} for i in range(k): #取出前k個元素的類別 voteIlabel = labels[sortedDistIndices[i]] #dict.get(key,default=None),字典的get()方法,返回指定鍵的值,若是值不在字典中返回默認值。 #計算類別次數 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #python3中用items()替換python2中的iteritems() #key=operator.itemgetter(1)根據字典的值進行排序 #key=operator.itemgetter(0)根據字典的鍵進行排序 #reverse降序排序字典 sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #返回次數最多的類別,即所要分類的類別 return sortedClassCount[0][0] """ 函數說明:分類器測試函數 Parameters: 無 Returns: normDataSet - 歸一化後的特徵矩陣 ranges - 數據範圍 minVals - 數據最小值 """ def datingClassTest(): #打開的文件名 filename = "datingTestSet.txt" #將返回的特徵矩陣和分類向量分別存儲到datingDataMat和datingLabels中 datingDataMat, datingLabels = file2matrix(filename) #取全部數據的百分之十 hoRatio = 0.10 #數據歸一化,返回歸一化後的矩陣,數據範圍,數據最小值 normMat, ranges, minVals = autoNorm(datingDataMat) #得到normMat的行數 m = normMat.shape[0] #百分之十的測試數據的個數 numTestVecs = int(m * hoRatio) #分類錯誤計數 errorCount = 0.0 for i in range(numTestVecs): #前numTestVecs個數據做爲測試集,後m-numTestVecs個數據做爲訓練集 classifierResult = classify0(normMat[i,:], normMat[numTestVecs:m,:], datingLabels[numTestVecs:m], 4) print("分類結果:%d\t真實類別:%d" % (classifierResult, datingLabels[i])) if classifierResult != datingLabels[i]: errorCount += 1.0 print("錯誤率:%f%%" %(errorCount/float(numTestVecs)*100))
""" 函數說明:經過輸入一我的的三維特徵,進行分類輸出 Parameters: 無 Returns: 無 """ def classifyPerson(): #輸出結果 resultList = ['討厭','有些喜歡','很是喜歡'] #三維特徵用戶輸入 precentTats = float(input("玩視頻遊戲所耗時間百分比:")) ffMiles = float(input("每一年得到的飛行常客里程數:")) iceCream = float(input("每週消費的冰激淋公升數:")) #打開的文件名 filename = "datingTestSet.txt" #打開並處理數據 datingDataMat, datingLabels = file2matrix(filename) #訓練集歸一化 normMat, ranges, minVals = autoNorm(datingDataMat) #生成NumPy數組,測試集 inArr = np.array([ffMiles, precentTats, iceCream]) #測試集歸一化 norminArr = (inArr - minVals) / ranges #返回分類結果 classifierResult = classify0(norminArr, normMat, datingLabels, 3) #打印結果 print("你可能%s這我的" % (resultList[classifierResult-1]))
2.2.1 html
2.2.2 KNeighborsClassifier函數8個參數python
2.2.3 實例git
# -*- coding: UTF-8 -*- import numpy as np import operator from os import listdir from sklearn.neighbors import KNeighborsClassifier as kNN """ 函數說明:將32x32的二進制圖像轉換爲1x1024向量。 Parameters: filename - 文件名 Returns: returnVect - 返回的二進制圖像的1x1024向量 """ def img2vector(filename): #建立1x1024零向量 returnVect = np.zeros((1, 1024)) #打開文件 fr = open(filename) #按行讀取 for i in range(32): #讀一行數據 lineStr = fr.readline() #每一行的前32個元素依次添加到returnVect中 for j in range(32): returnVect[0, 32*i+j] = int(lineStr[j]) #返回轉換後的1x1024向量 return returnVect """ 函數說明:手寫數字分類測試 Parameters: 無 Returns: 無 """ def handwritingClassTest(): #測試集的Labels hwLabels = [] #返回trainingDigits目錄下的文件名 trainingFileList = listdir('trainingDigits') #返回文件夾下文件的個數 m = len(trainingFileList) #初始化訓練的Mat矩陣,測試集 trainingMat = np.zeros((m, 1024)) #從文件名中解析出訓練集的類別 for i in range(m): #得到文件的名字 fileNameStr = trainingFileList[i] #得到分類的數字 classNumber = int(fileNameStr.split('_')[0]) #將得到的類別添加到hwLabels中 hwLabels.append(classNumber) #將每個文件的1x1024數據存儲到trainingMat矩陣中 trainingMat[i,:] = img2vector('trainingDigits/%s' % (fileNameStr)) #構建kNN分類器 neigh = kNN(n_neighbors = 3, algorithm = 'auto') #擬合模型, trainingMat爲訓練矩陣,hwLabels爲對應的標籤 neigh.fit(trainingMat, hwLabels) #返回testDigits目錄下的文件列表 testFileList = listdir('testDigits') #錯誤檢測計數 errorCount = 0.0 #測試數據的數量 mTest = len(testFileList) #從文件中解析出測試集的類別並進行分類測試 for i in range(mTest): #得到文件的名字 fileNameStr = testFileList[i] #得到分類的數字 classNumber = int(fileNameStr.split('_')[0]) #得到測試集的1x1024向量,用於訓練 vectorUnderTest = img2vector('testDigits/%s' % (fileNameStr)) #得到預測結果 # classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3) classifierResult = neigh.predict(vectorUnderTest) print("分類返回結果爲%d\t真實結果爲%d" % (classifierResult, classNumber)) if(classifierResult != classNumber): errorCount += 1.0 print("總共錯了%d個數據\n錯誤率爲%f%%" % (errorCount, errorCount/mTest * 100)) """ 函數說明:main函數 Parameters: 無 Returns: 無 """ if __name__ == '__main__': handwritingClassTest()