(一)kNN
1. kNN概述
k近鄰法(k-nearest neighbor, k-NN)是1967年由Cover T和Hart P提出的一
種基本分類與迴歸方法。它的工作原理是:存在一個樣本資料集合,也稱作 為訓練樣本集,並且樣本集中每個資料都存在標籤,即我們知道樣本
集中每一個資料與所屬分類的對應關係。輸入沒有標籤的新資料後,將新的資料的每個特徵與樣本集中資料對應的特徵進行比較,然後演算法提取樣
本最相似資料(最近鄰)的分類標籤。一般來說,我們只選擇樣本資料集中
前k個最相似的資料,這就是k-近鄰演算法中k的出處,通常k是不大於20的
整數。最後,選擇k個最相似資料中出現次數最多的分類,作為新資料的
分類。
- 看到這裡,有人可能會問:“分類器何種情況下會出錯?”或者“答案是否總是正確的?”答案是否定的,分類器並不會得到百分百正確的結果,我們可以使用多種方法檢測分類器的正確率。
- 此外分類器的效能也會受到多種因素的影響,如分類器設定和資料集等。不同的演算法在不同資料集上的表現可能完全不同。
- 為了測試分類器的效果,我們可以使用已知答案的資料,當然答案不能告訴分類器,檢驗分類器給出的結果是否符合預期結果。通過大量的測試資料,我們可以得到分類器的錯誤率-分類器給出錯誤結果的次數除以測試執行的總數。錯誤率是常用的評估方法,主要用於評估分類器在某個資料集上的執行效果。完美分類器的錯誤率為0,最差分類器的錯誤率是1.0。
- 同時,我們也不難發現,
k-近鄰演算法沒有進行資料的訓練,直接使用未知的資料與已知的資料進行比較,得到結果
。因此,可以說k-鄰近演算法不具有顯式的學習過程
。
1.1 kNN演算法的優點
- 簡單好用,容易理解,精度高,理論成熟,既可以用來做分類也可以用來做迴歸
- 可用於數值型資料和離散型資料
- 訓練時間複雜度為 O(n); 無資料輸入假定
- 對異常值不敏感
1.2 kNN 演算法的缺點
- 計算複雜度高;空間複雜度高
- 樣本不平衡問題(有些類別的樣本數量很多,而其他樣本的數量很少);
- 一般數值很大的時候不適用該演算法,計算量太大。但是單個樣本又不能太少,否則容易發生誤分
- 最大的缺點是無法給出資料的內在含義。
2. kNN程式碼實現
2.1 kNN
2.2 演算法實戰——海倫約會
收集資料
準備資料(資料解析、資料歸一化)
分析資料()
測試演算法
使用演算法
2.2.1 收集資料集
2.2.2 準備資料:資料解析
import numpy as np
def file2matrix(filename):
fr = open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
returnMat = np.zeros((numberOfLines, 3))
classLabelVector = []
index = 0
for line in arrayOLines:
line = line.strip() # 擷取掉所有的回車字元
listFromLine = line.split('\t')
returnMat[index, :] = listFromLine[0: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
if __name__ == '__main__':
filename = 'datingTestSet.txt'
datingDataMat, datingLabels = file2matrix(filename)
print(datingDataMat)
print('--------------------------------------')
print(datingLabels)
2.2.3 分析資料:資料視覺化
import numpy as np
import operator
#from matplotlib.font_manager import FontProperties
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
def file2matrix(filename):
fr = open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
returnMat = np.zeros((numberOfLines, 3))
classLabelVector = []
index = 0
for line in arrayOLines:
line = line.strip() # 擷取掉所有的回車字元
listFromLine = line.split('\t')
returnMat[index, :] = listFromLine[0: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
def showdatas(datingDataMat, datingLabels):
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')
axs[0][0].scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 1], color=LabelsColors, s=15, alpha=0.5)
axs0_title_text = axs[0][0].set_title(u'每年獲得的飛行常客里程數與玩視訊遊戲所消耗時間佔比',fontProperties='SimHei', fontsize=14)
axs0_xlabel_text = axs[0][0].set_xlabel(u'每年獲得的飛行常客里程數',fontProperties='SimHei', fontsize=14)
axs0_ylabel_text = axs[0][0].set_ylabel(u'玩視訊遊戲所消耗時間佔',fontProperties='SimHei', fontsize=14)
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='SimHei', fontsize=14)
axs1_xlabel_text = axs[0][1].set_xlabel(u'每年獲得的飛行常客里程數',fontProperties='SimHei', fontsize=14)
axs1_ylabel_text = axs[0][1].set_ylabel(u'每週消費的冰激淋公升數',fontProperties='SimHei', fontsize=14)
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='SimHei', fontsize=14)
axs2_xlabel_text = axs[1][0].set_xlabel(u'玩視訊遊戲所消耗時間佔比',fontProperties='SimHei', fontsize=14)
axs2_ylabel_text = axs[1][0].set_ylabel(u'每週消費的冰激淋公升數',fontProperties='SimHei', fontsize=14)
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()
if __name__ == '__main__':
filename = 'datingTestSet.txt'
datingDataMat, datingLabels = file2matrix(filename)
print(datingDataMat)
print('--------------------------------------')
print(datingLabels)
showdatas(datingDataMat, datingLabels)
2.2.4 準備資料:資料歸一化
import numpy as np
import operator
#from matplotlib.font_manager import FontProperties
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
def file2matrix(filename):
fr = open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
returnMat = np.zeros((numberOfLines, 3))
classLabelVector = []
index = 0
for line in arrayOLines:
line = line.strip() # 擷取掉所有的回車字元
listFromLine = line.split('\t')
returnMat[index, :] = listFromLine[0: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
def autoNorm(dataSet):
# dataSet --- 1000*3
# minVals --- 1*3
# maxVals --- 1*3
minVals = dataSet.min(0) # 0 表示從當前列中選取最小值
maxVals = dataSet.max(0)
range = maxVals - minVals
normDataSet = np.zeros(np.shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - np.tile(minVals, (m, 1))
normDataSet = normDataSet / np.tile(range, (m, 1))
return normDataSet, range, minVals
if __name__ == '__main__':
filename = 'datingTestSet.txt'
datingDataMat, datingLabels = file2matrix(filename)
print('--------------------------------------')
normDataSet, ranges, minVals = autoNorm(datingDataMat)
print(normDataSet)
print('--------------------------------------')
print(ranges)
print('--------------------------------------')
print(minVals)
#showdatas(datingDataMat, datingLabels)
2.2.5 測試演算法:驗證分類器
import numpy as np
import operator
#from matplotlib.font_manager import FontProperties
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
# kNN演算法,分類器
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat ** 2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances ** 0.5
sortedDistIndicies = distances.argsort()
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
# 解析資料
def file2matrix(filename):
fr = open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
returnMat = np.zeros((numberOfLines, 3))
classLabelVector = []
index = 0
for line in arrayOLines:
line = line.strip() # 擷取掉所有的回車字元
listFromLine = line.split('\t')
returnMat[index, :] = listFromLine[0: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
# 歸一化資料
def autoNorm(dataSet):
# dataSet --- 1000*3
# minVals --- 1*3
# maxVals --- 1*3
minVals = dataSet.min(0) # 0 表示從當前列中選取最小值
maxVals = dataSet.max(0)
range = maxVals - minVals
normDataSet = np.zeros(np.shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - np.tile(minVals, (m, 1))
normDataSet = normDataSet / np.tile(range, (m, 1))
return normDataSet, range, minVals
def datingClassTest():
filename = 'datingTestSet.txt'
datingDataMat, datingLabels = file2matrix(filename)
hoRatio = 0.10
normMat, ranges, minVals = autoNorm(datingDataMat)
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))
if __name__ == '__main__':
datingClassTest()
2.2.6 使用演算法:構建完整可用系統
我們可以給海倫一個小段程式,通過該程式海倫會在約會網站上找到某個人並輸入他的資訊。程式會給出她對男方喜歡程度的預測值。
import numpy as np
import operator
#from matplotlib.font_manager import FontProperties
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
# kNN演算法,分類器
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat ** 2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances ** 0.5
sortedDistIndicies = distances.argsort()
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
# 解析資料
def file2matrix(filename):
fr = open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
returnMat = np.zeros((numberOfLines, 3))
classLabelVector = []
index = 0
for line in arrayOLines:
line = line.strip() # 擷取掉所有的回車字元
listFromLine = line.split('\t')
returnMat[index, :] = listFromLine[0: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
# 歸一化資料
def autoNorm(dataSet):
# dataSet --- 1000*3
# minVals --- 1*3
# maxVals --- 1*3
minVals = dataSet.min(0) # 0 表示從當前列中選取最小值
maxVals = dataSet.max(0)
range = maxVals - minVals
normDataSet = np.zeros(np.shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - np.tile(minVals, (m, 1))
normDataSet = normDataSet / np.tile(range, (m, 1))
return normDataSet, range, minVals
# 輸入一個人的三維特徵,進行分類輸出
def classifyPerson():
resultList = ['討厭', '有些喜歡', '非常喜歡']
#使用者輸入三維特徵
percentTats = float(input('玩視訊遊戲所耗時間百分比:'))
ffMiles = float(input("每年獲得的飛行常客里程數:"))
iceCream = float(input("每週消費的冰激淋公升數:"))
filename = 'datingTestSet.txt'
datingDataMat, datingLabels = file2matrix(filename)
normMat, ranges, minVals = autoNorm(datingDataMat)
#生成Numpy陣列,測試集
inArr = np.array([percentTats, ffMiles, iceCream])
norminArr = (inArr - minVals) / ranges
#返回分類結果
classifierResult = classify0(norminArr, normMat, datingLabels, 3)
print('你可能%s這個人' % (resultList[classifierResult-1]))
if __name__ == '__main__':
classifyPerson()
2.3 演算法實戰——sklearn手寫數字識別
相關文章
- sklearn學習 第一篇:knn分類KNN
- KNN演算法的資料歸一化--Feature ScalingKNN演算法
- KNN演算法實驗KNN演算法
- Python底層實現KNNPythonKNN
- 演算法金 | 再見!!!KNN演算法KNN
- KNN演算法——分類部分KNN演算法
- KNN演算法推理與實現KNN演算法
- K-最近鄰法(KNN)簡介KNN
- 機器學習——KNN(K近鄰)機器學習KNN
- scikit-learn中KNN演算法資料歸一化的分裝KNN演算法
- educoder 機器學習 --- kNN演算法機器學習KNN演算法
- sklearn調包俠之KNN演算法KNN演算法
- 機器學習演算法-K近鄰(KNN)演算法(三):馬絞痛資料--kNN資料預處理+kNN分類pipeline(程式碼附詳細註釋)機器學習演算法KNN
- 機器學習 第5篇:knn迴歸機器學習KNN
- 機器學習——KNN近鄰演算法機器學習KNN演算法
- 最基礎的分類演算法(KNN)演算法KNN
- 機器學習筆記(KNN演算法)機器學習筆記KNN演算法
- 演算法(八):圖解KNN演算法演算法圖解KNN
- 機器學習-K近鄰演算法-KNN機器學習演算法KNN
- 機器學習經典演算法之KNN機器學習演算法KNN
- 演算法實踐:KNN分類(day08)演算法KNN
- opencv python 基於KNN的手寫體識別OpenCVPythonKNN
- python機器學習演算法——KNN演算法Python機器學習演算法KNN
- 機器學習分享——KNN演算法及numpy實現機器學習KNN演算法
- 資料探勘——KNN演算法(手寫數字分類)KNN演算法
- 計算機視覺—kNN識別手寫數字(10)計算機視覺KNN
- KNN 演算法-實戰篇-如何識別手寫數字KNN演算法
- 資料結構與演算法-kd二叉樹(kNN)資料結構演算法二叉樹KNN
- 機器學習演算法——kNN(k-近鄰演算法)機器學習演算法KNN
- KNN 演算法-理論篇-如何給電影進行分類KNN演算法
- 機器學習——線性迴歸-KNN-決策樹(例項)機器學習KNN
- 機器學習入門實戰——基於knn的airbnb房租預測機器學習KNNAI
- 一看就懂的K近鄰演算法(KNN),K-D樹,並實現手寫數字識別!演算法KNN
- 機器學習實踐篇第二篇-KNN演算法學習機器學習KNN演算法
- 《資料探勘導論》實驗課——實驗四、資料探勘之KNN,Naive BayesKNNAI
- 【火爐煉AI】機器學習031-KNN迴歸器模型的構建AI機器學習KNN模型
- 手勢識別演算法: 資料濾波演算法、資料分演算法——KNN演算法KNN
- R語言邏輯迴歸、GAM、LDA、KNN、PCA主成分分類分析預測房價及交叉驗證R語言邏輯迴歸GAMLDAKNNPCA