python機器學習實戰(zhàn)之最近鄰kNN分類器
更新時間:2021年10月28日 10:35:01 作者:大牙灣
這篇文章主要介紹了python機器學習實戰(zhàn)之最近鄰kNN分類器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
K近鄰法是有監(jiān)督學習方法,原理很簡單,假設我們有一堆分好類的樣本數據,分好類表示每個樣本都一個對應的已知類標簽,當來一個測試樣本要我們判斷它的類別是, 就分別計算到每個樣本的距離,然后選取離測試樣本最近的前K個樣本的標簽累計投票, 得票數最多的那個標簽就為測試樣本的標簽。
源代碼詳解:
#-*- coding:utf-8 -*-
#!/usr/bin/python
# 測試代碼 約會數據分類 import KNN KNN.datingClassTest1() 標簽為字符串 KNN.datingClassTest2() 標簽為整形
# 測試代碼 手寫字體分類 import KNN KNN.handwritingClassTest()
from numpy import * # 科學計算包
import operator # 運算符模塊
from os import listdir # 獲得指定目錄中的內容(手寫字體文件夾下樣本txt) 類型命令行 ls
import matplotlib # 畫圖可視化操作
import matplotlib.pyplot as plot
# 顯示一個 二維圖
def myPlot(x, y, labels):
fig = plot.figure()#創(chuàng)建一個窗口
ax = fig.add_subplot(111)# 畫一個圖
#ax.scatter(x,y)
ax.scatter(x,y,15.0*array(labels),15.0*array(labels)) # 支持 分類顏色顯示
ax.axis([-2,25,-0.2,2.0])
plot.xlabel('Percentage of Time Spent Playing Video Games')# 坐標軸名稱
plot.ylabel('Liters of Ice Cream Consumed Per Week')
plot.show()
# 創(chuàng)建假 的數據測試
def createDataSet():
groop = array([[1.0, 1.1],[1.0, 1.0],[0, 0],[0, 0.1]]) # numpy的array 數組格式
labels = ['A','A','B','B']# 標簽 list
return groop, labels
# 定義 KNN 分類函數
def knnClassify0(inX, dataSet, labels, k):
# inX 待分類的點 數據集和標簽 DataSet, label 最近領域個數 k
dataSetSize = dataSet.shape[0] # 數據集大?。ㄐ袛担?
# tile(A,(行維度,列維度)) A沿各個維度重復的次數
# 點A 重復每一行 到 數據集大小行
differeMat = tile(inX, (dataSetSize,1)) - dataSet # 求 待分類點 與個個數據集點的 差值
sqDiffMat = differeMat**2 # 求 平方
sqDistances = sqDiffMat.sum(axis=1) # 求 和(各行求和)
distances = sqDistances**0.5 # 開方 得到 點A 與 數據集個點 的歐式距離
sortedDistIndicies = distances.argsort() # 返回 遞增排序后 的 原位置序列(不是值)
# 取得最近的 k個點 統(tǒng)計 標簽類出現的頻率
classCount={} # 字典
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]#從小到大 對應距離 數據點 的標簽
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 # 對于類標簽 字典單詞 的 值 + 1
# 對 類標簽 頻率(字典的 第二列(operator.itemgetter(1))) 排序 從大到小排序 reverse=True
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0] # 返回 最近的 對應的標簽
# 真實數據的處理 輸入TXT文本文件 返回 數據集和標簽(已轉化成數字) 列表 list
def file2matrix(filename):
fr = open(filename) # 打開文件
numberOfLines = len(fr.readlines()) # 得到文件所有的行數
returnMat = zeros((numberOfLines,3))
# 創(chuàng)建一個用于存儲返回數據的矩陣 數據集 每個數據的大小根據實際情況!! 即是 3 列數應根據 數據維度確定
classLabelVector = [] # 對應標簽
fr = open(filename)
index = 0
for line in fr.readlines(): # 每一行
line = line.strip() # 默認刪除空白符(包括'\n', '\r', '\t', ' ')
listFromLine = line.split('\t') # 按 制表符(\t) 分割字符串 成 元素列表
returnMat[index,:] = listFromLine[0:3] # 前三個為 數據集數據
classLabelVector.append(int(listFromLine[-1])) # 最后一個 為 標簽 整形
index += 1
return returnMat,classLabelVector
# 真實數據的處理 輸入TXT文本文件 返回 數據集和標簽(為字符串) 列表 list
def file2matrix2(filename):
fr = open(filename) # 打開文件
numberOfLines = len(fr.readlines()) # 得到文件所有的行數
returnMat = zeros((numberOfLines,3))
# 創(chuàng)建一個用于存儲返回數據的矩陣 數據集 每個數據的大小根據實際情況??! 即是 3 列數應根據 數據維度確定
classLabelVector = [] # 對應標簽
fr = open(filename)
index = 0
for line in fr.readlines(): # 每一行
line = line.strip() # 默認刪除空白符(包括'\n', '\r', '\t', ' ')
listFromLine = line.split('\t') # 按 制表符(\t) 分割字符串 成 元素列表
returnMat[index,:] = listFromLine[0:3] # 前三個為 數據集數據
classLabelVector.append(str(listFromLine[-1])) # 最后一個 為 標簽 字符串型
index += 1
return returnMat,classLabelVector
# 數據集 各個類型數據歸一化 平等化 影響權值
def dataAutoNorm(dataSet):
minVals = dataSet.min(0) # 最小值 每一列的 每一種屬性 的最小值
maxVals = dataSet.max(0) # 最大值
ranges = maxVals - minVals # 數據范圍
normDataSet = zeros(shape(dataSet)) # 初始化輸出 數組
m = dataSet.shape[0] # 行維度 樣本總數
normDataSet = dataSet - tile(minVals, (m,1)) # 擴展 minVals 成 樣本總數行m行 1列(屬性值個數)
normDataSet = normDataSet/tile(ranges, (m,1)) # 矩陣除法 每種屬性值 歸一化 numpy庫 為(linalg.solve(matA,matB))
return normDataSet, ranges, minVals # 返回 歸一化后的數組 和 個屬性范圍以及最小值
# 約會數據 KNN分類 測試
# 標簽為 字符串型
def datingClassTest1(test_ret=0.1):
hoRatio = test_ret # 測試的樣本比例 剩下的作為 訓練集
datingDataMat,datingLabels = file2matrix2('datingTestSet.txt') #載入數據集
normMat, ranges, minVals = dataAutoNorm(datingDataMat)
m = normMat.shape[0] # 總樣本數量
numTestVecs = int(m*hoRatio) # 總測試樣本數
errorCount = 0.0 # 錯誤次數記錄
for i in range(numTestVecs): # 對每個測試樣本
# KNN 分類 測試樣本 剩下的作為數據集 數據集對應的標簽 最近 的三個
classifierResult = knnClassify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
print "分類結果: %s,\t真實標簽: %s" % (classifierResult, datingLabels[i])
if (classifierResult != datingLabels[i]): errorCount += 1.0
print "總錯誤次數: %d" % errorCount
print "測試總數: %d" % numTestVecs
print "總錯誤率: %f" % (errorCount/float(numTestVecs))
# 標簽為 整形 int
def datingClassTest2(test_ret=0.1):
hoRatio = test_ret # 測試的樣本比例 剩下的作為 訓練集
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #載入數據集
normMat, ranges, minVals = dataAutoNorm(datingDataMat)
m = normMat.shape[0] # 總樣本數量
numTestVecs = int(m*hoRatio) # 總測試樣本數
errorCount = 0.0 # 錯誤次數記錄
for i in range(numTestVecs): # 對每個測試樣本
# KNN 分類 測試樣本 剩下的作為數據集 數據集對應的標簽 最近 的三個
classifierResult = knnClassify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
print "分類結果: %d, 真實標簽: %d" % (classifierResult, datingLabels[i])
if (classifierResult != datingLabels[i]): errorCount += 1.0
print "總錯誤次數: %d" % errorCount
print "測試總數: %d" % numTestVecs
print "總錯誤率: %f" % (errorCount/float(numTestVecs))
# 根據用戶輸入的 樣本的屬性值 判斷用戶所傾向的類型(有點問題??)
def classifyPerson():
resultList = ['討厭','一般化','非常喜歡']
percent = float(raw_input("打游戲所花時間比例: "))
mile = float(raw_input("每年飛行的里程數量: "))
ice = float(raw_input("每周消費的冰淇淋量: "))
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #載入數據集
normMat, ranges, minVals = dataAutoNorm(datingDataMat)
# 新測試樣本 歸一化
print ranges, minVals
testSampArry = array([mile, percent, ice]) # 用戶輸入的 測試樣例
testSampArryNorm = (testSampArry-minVals)/ranges # 樣例歸一化
print testSampArry ,testSampArryNorm
# 分類
classifierResult = knnClassify0(testSampArryNorm,normMat,datingLabels,3)
print classifierResult
print "他是不是你的菜: ", resultList[classifierResult-1]
# 手寫字體 圖像 32*32 像素轉化成 1*1024 的向量
def img2vector(filename):
returnVect = zeros((1,1024)) # 創(chuàng)建空的 返回向量
fr = open(filename) # 打開文件
for i in range(32): # 對每一行
lineStr = fr.readline() # 每一行元素
for j in range(32): # 每一行的每個值
returnVect[0,32*i+j] = int(lineStr[j])
return returnVect
# 手寫字體的 KNN識別 每個數字圖片被轉換成 32*32 的 0 1 矩陣
def handwritingClassTest(k=3):
# 得到訓練數據集
hwLabels = [] # 識別的標簽
trainingFileList = listdir('trainingDigits') # 加載手寫字體訓練數據集 (所有txt文件列表)
m = len(trainingFileList) # 總訓練樣本數
trainingMat = zeros((m,1024)) # 訓練數據集
for i in range(m):
fileNameStr = trainingFileList[i] # 每個訓練數據樣本文件 0_0.txt 0_1.txt 0_2.txt
fileStr = fileNameStr.split('.')[0] # 以.分割 第一個[0]為文件名 第二個[1]為類型名 txt文件
classNumStr = int(fileStr.split('_')[0]) # 以_分割,第一個[0]為該數據表示的數字 標簽
hwLabels.append(classNumStr) # 訓練樣本標簽
trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr) # 訓練樣本數據
# 得到測試數據集
testFileList = listdir('testDigits') # 測試數據集
errorCount = 0.0 # 錯誤次數計數
mTest = len(testFileList) # 總測試 數據樣本個數
for i in range(mTest):
fileNameStr = testFileList[i] # 每個測試樣本文件
fileStr = fileNameStr.split('.')[0] # 得到文件名
classNumStr = int(fileStr.split('_')[0]) # 得到對應的真實標簽
vectorUnderTest = img2vector('testDigits/%s' % fileNameStr) # 測試樣本數據
classifierResult = knnClassify0(vectorUnderTest, trainingMat, hwLabels, k) # 分類
print "KNN分類標簽: %d, 真實標簽: %d" % (classifierResult, classNumStr)
if (classifierResult != classNumStr): errorCount += 1.0
print "\n總的錯誤次數: %d" % errorCount
print "\n總的錯誤比例: %f" % (errorCount/float(mTest))
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
關于torch.flatten()函數及x=x.view()函數的理解
這篇文章主要介紹了關于torch.flatten()函數及x=x.view()函數的理解,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04
關于Pycharm安裝第三方庫超時 Read time-out的問題
這篇文章主要介紹了關于Pycharm安裝第三方庫超時 Read time-out的問題, 找了幾個命令都不是很好用,最后找到解決的步驟,感興趣的朋友跟隨小編一起看看吧2021-10-10
Python 根據數據模板創(chuàng)建shapefile的實現
今天小編就為大家分享一篇Python 根據數據模板創(chuàng)建shapefile的實現,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11
python爬蟲實現POST request payload形式的請求
這篇文章主要介紹了python爬蟲實現POST request payload形式的請求,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04

