机器学习实战之 k近邻算法 原理及代码实现
来源:互联网 发布:知几是什么意思 编辑:程序博客网 时间:2024/05/19 05:40
基本概念:
近邻学习是一种监督学习算法,在给定的训练样本集中,基于某种距离度量,找出与训练集最靠近的k个训练样本,然后基于这k个邻居信息来进行预测。
投票法:通常在分类任务中使用,判别方法是选择这k个样本中出现最多的雷冰标记作为预测结果。
平均法:通常在回归任务中使用,判别方法是将这k个样本的实值输出标记的平均值最为预测结果。
平均法:通常在回归任务中使用,判别方法是将这k个样本的实值输出标记的平均值最为预测结果。
加权平均或加权投票:根据距离远近来决定权重,距离越近,权重越大
KNN算法没有显式的学习过程,事实上,它是“懒惰学习”的代表:在训练阶段仅仅是把样本保存起来,训练时间开销为0
待收到测试样本后再进行处理, 相应的,那些在训练阶段就对样本进行学习处理的方法,称为“急切学习”
定理:最近邻分类器(k=1),泛化错误率不超过贝叶斯分类器错误率的两倍
代码实现:
(平均法):
import numpy as np
def knnclassify(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=lambda classCount : classCount[1], reverse=True)
return sortedClassCount[0][0]
(加权投票法)
设权值 从 1.5 等比 降到 0.5
例如:1.5 ,1.39 ,1.28 ,1.17 ,1.06 ,0.94 ,0.83 ,0.72 ,0.61 ,0.5
classCount[votelabel] = classCount.get(votelabel, 0) + round((1.5 - i / (k-1)), 2)
在实例3中,分别用两种方法测试
k
错误总数(平均投票)
错误总数(加权投票)
1
13
13
2
13
13
3
10
13
4
11
10
5
17
11
6
17
14
7
21
18
8
18
16
9
21
19
可以看出:
- 并不是 K 越大,分类准确率越高。
- 当 K 越大时,加权投票的分类 优势越明显
参考实例:
例1:
import numpy as np
from knn.KNNclassifier import knnclassify
# 导入当前文件夹下的文件,(如果不加入"knn.",则会出现红色波浪线,但可正常运行)
def creatrDateSet():
group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels = ['A','A','B','B']
return group, labels
group, labels = creatrDateSet()
print(knnclassify([0, 0], group, labels, 3)) # 结果B
print(knnclassify([1, 1], group, labels, 4)) # 结果A
print(knnclassify([0.5, 0.5], group, labels, 4)) # 结果B
代码解释:
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0] #4
diffMat = np.tile(inX, (dataSetSize,1)) - dataSet
# np.tile(inX, (dataSetSize,1) 结果为 [[0,0],[0,0],[0,0],[0,0]]
# 减去dataSet 后每行为每个点的距离差
sqDiffMat = diffMat**2
# 将每个距离差平方
sqDistances = sqDiffMat.sum(axis=1)
# #axis=0表述列 ,axis=1表述行, 横项相加
distances = sqDistances**0.5
# 开根号得到距离:[ 1.48660687 1.41421356 0. 0.1 ]
sortedDistIndicies = distances.argsort() # 返回结果从头到尾为非降序排序的index:[2 3 1 0]
classCount={}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
# 循环取出排序从近到远的labels : B B A
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 # 构建字典,最终得到频次{'B': 2, 'A': 1}
sortedClassCount = sorted(classCount.items(), key= lambda classCount:classCount[1], reverse=True)
# operator模块提供的itemgetter函数用于获取对象的哪些维的数据
# sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
'''在Python2.x中,items( )用于 返回一个字典的拷贝列表【Returns a copy of the list of all items (key/value pairs) in D】,占额外的内存。
iteritems() 用于返回本身字典列表操作后的迭代【Returns an iterator on all items(key/value pairs) in D】,不占用额外的内存。
Python 3.x 里面,iteritems() 和 viewitems() 这两个方法都已经废除了,而 items() 得到的结果是和 2.x 里面 viewitems() 一致的。
在3.x 里 用 items()替换iteritems() ,以列表返回可遍历的(键, 值) 元组数组'''
print(sortedClassCount)
return sortedClassCount[0][0]
# sortedClassCount 得到的值为列表,列表元素为每个标签和频次,由频次从高到底排序 ,本例中为[('B', 2), ('A', 1)]
group, labels = creatrDateSet()
print(classify0([0, 0], group, labels, 3)) # 结果B
print(classify0([1, 1], group, labels, 4)) # 结果A
print(classify0([0.5, 0.5], group, labels, 4)) # 结果B
例2:约会对象是否合适
样本特征:1. 玩游戏消耗时间百分比 2. 飞行里程数 3.每周吃冰激凌升数
标签分类:1.不喜欢 2.有一点喜欢 3.比较喜欢
import numpy as np
from knn.KNNclassifier import knnclassify
# 将 文本记录 转换为 NumPy
def file2matrix(filename, dim):
fr = open(filename)
numberOfLines = len(fr.readlines()) #get the number of lines in the file
returnMat = np.zeros((numberOfLines,dim)) #prepare matrix to return
classLabelVector = [] #prepare labels return
fr = open(filename)
index = 0
for line in fr.readlines():
line = line.strip()
listFromLine = line.split('\t')
returnMat[index,:] = listFromLine[0:dim]
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat,classLabelVector
def normalize(dataSet):
minVals = dataSet.min(0) # 每列最小值
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = np.zeros(np.shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - np.tile(minVals, (m, 1))
normDataSet = normDataSet/np.tile(ranges, (m, 1))
return normDataSet , ranges, minVals
def dataplot(dataSet, labels):
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(dataSet[:,1], dataSet[:,2], 15.0*np.array(labels), np.array(labels))
ax.set_ylabel('Ice Cream Consumption')
ax.set_xlabel('Time of Playing Games')
# 后面两个参数分别控制散点大小和颜色
plt.show()
def classifytest(dataset, datalabel, k, testRatio):
m = dataset.shape[0] # 数据列数
numTestVecs = int(m * testRatio) #此次测试所用的样本数目
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = knnclassify(dataset[i, :], dataset[numTestVecs:m, :], datalabel[numTestVecs:m], k)
#print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datalabel[i]))
# dataset 前 测试率*数据总数目 用于测试, 使用 余下的作为分类依据
if (classifierResult != datalabel[i]):
errorCount += 1.0
print("the total error rate is: %f" % (errorCount / float(numTestVecs)))
def main():
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt',3)
normMat, ranges, minVals = normalize(datingDataMat)
dataplot(normMat, datingLabels)
#classifytest(normMat,datingLabels,3,0.1) # 第三个参数为分类器的k值
# 第四个系数为测试样本比例,系数越高 分类准确率越低(用于测试的越多,用于分类的越少)
resultList = ['not at all', 'in small dose', 'in large doses']
timeofgame = float(input("percentage of time spend playing video games:"))
flymiles = float(input("frequent flier miles earner per year:"))
icecream = float(input("liters of ice cream consumed per year:"))
inarr = np.array([timeofgame, flymiles, icecream])
norminput = (inarr - minVals) / ranges
result = knnclassify(norminput, normMat, datingLabels, 3)
print("you will probable like this person", resultList[result - 1])
if __name__=="__main__":
main()
例3
import numpy as np
from os import listdir
from knn.KNNclassifier import knnclassify
# 将 32*32 的数组,转化为一维 nd.array 矩阵
def img2vector(filename):
returnVect = np.zeros((1,1024))
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
def handwritingClassTest():
hwLabels = []
trainingFileList = listdir('digits/trainingDigits') #load the training set
m = len(trainingFileList) # 文件数目,同时也是训练样本数目 本例中为1934
trainingMat = np.zeros((m,1024))
for i in range(m):
fileNameStr = trainingFileList[i]
fileStr = fileNameStr.split('.')[0] #take off .txt
classNumStr = int(fileStr.split('_')[0])
hwLabels.append(classNumStr) # 得到训练样本的真实标签
trainingMat[i,:] = img2vector('digits/trainingDigits/%s' % fileNameStr)
# 对每个文件进行 向量化处理,得到 m * 1024 的矩阵
testFileList = listdir('digits/testDigits') #iterate through the test set
errorCount = 0.0
mTest = len(testFileList)
for i in range(mTest):
fileNameStr = testFileList[i]
fileStr = fileNameStr.split('.')[0] # 去掉 .txt 的后缀
classNumStr = int(fileStr.split('_')[0]) # _ 前为该数字的正确值
vectorUnderTest = img2vector('digits/testDigits/%s' % fileNameStr)
classifierResult = knnclassify(vectorUnderTest, trainingMat, hwLabels, 3) #对每个测试样本进行分类
#print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr))
if (classifierResult != classNumStr): errorCount += 1.0
print("\nthe total number of errors is: %d" % errorCount)
print("\nthe total error rate is: %f" % (errorCount/float(mTest)))
handwritingClassTest()
# 约会选择中,将一份数据一分为2位训练集和测试集,而此例中为分开好的
# 由于数据只能为 0 和 1, 因此无需归一化处理
阅读全文
0 0
- 机器学习实战之 k近邻算法 原理及代码实现
- 机器学习:K-近邻算法原理与Python代码实现
- 机器学习实战之K-近邻算法
- 《机器学习实战》之K-近邻算法
- 机器学习实战之k-近邻算法
- 机器学习实战之K近邻算法
- 机器学习之K-近邻算法代码实现
- 机器学习实战代码学习(K-近邻算法)
- 机器学习实战学习,代码详解(K-近邻算法)
- 《机器学习实战》代码片段学习1 k-近邻算法
- 读懂《机器学习实战》代码—K-近邻算法
- 《机器学习实战》K-近邻算法代码解析(1)
- 机器学习实战ch02 KNN k-近邻算法代码注释
- 《机器学习实战》学习笔记:k-近邻算法实现
- 《机器学习实战》学习笔记之k-近邻算法1
- 《机器学习实战》学习笔记之k-近邻算法2
- 《机器学习实战》学习笔记之k-近邻算法3
- 《机器学习实战》学习笔记(三)之K-近邻算法
- 机器学习——决策树算法
- 对n个数字右移k位
- assertRegex的报错
- java
- Oracle数据库sysdba、sysoper权限问题
- 机器学习实战之 k近邻算法 原理及代码实现
- 通过SWIG生成jni代码
- ICPC2017网络赛(沈阳)number number number
- 【BashuOJ2276】月饼盒-矩阵型DP
- Github使用教程(二)------ Github客户端使用方法
- 树莓派(中级篇)--Java环境搭建
- mongodb之lnmp初体验
- RecyclerView的局部刷新
- 如何解决Win10系统下自带IE11无法使用IE10、IE9、IE8等在线考试报名