注:此系列文章里的部分算法和深度学习笔记系列里的内容有重合的地方,深度学习笔记里是看教学视频做的笔记,此处文章是看《机器学习实战》这本书所做的笔记,虽然算法相同,但示例代码有所不同,多敲一遍没有坏处,哈哈。(里面用到的数据集、代码可以到网上搜索,很容易找到。)Python版本3.6
机器学习十大算法系列文章:
机器学习实战笔记1—k-近邻算法
机器学习实战笔记2—决策树
机器学习实战笔记3—朴素贝叶斯
机器学习实战笔记4—Logistic回归
机器学习实战笔记5—支持向量机
机器学习实战笔记6—AdaBoost
机器学习实战笔记7—K-Means
机器学习实战笔记8—随机森林
机器学习实战笔记9—人工神经网络
此系列源码在我的GitHub里:https://github.com/yeyujujishou19/Machine-Learning-In-Action-Codes
一,算法原理:
1)计算测试数据与各个训练数据之间的距离;
2)按照距离的递增关系进行排序;
3)选取距离最小的K个点;
4)确定前K个点所在类别的出现频率;
5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。
参考之前写的文章:深度学习基础课程1笔记-最近邻规则分类(KNN)
二,KNN算法的优缺点:
优点:
1)思想简单,理论成熟,既可以用来做分类也可以用来做回归;
2)可用于非线性分类;
3)训练时间复杂度为O(n);
4)准确度高,对数据没有假设,对outlier不敏感;
缺点:
1)计算量大;
2)样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少);
3)需要大量的内存;
三,实例代码:
代码一:一个小示例
from numpy import *
import operator
'''
函数功能 分类
inX 待分类数据
dataSet 练样本集
labels 样本集标签
k 选取前k个值
'''
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0] #获取训练样本集大小
diffMat = tile(inX, (dataSetSize,1)) - dataSet #title()的作用是将待分类数据复制成和样本集同样大小的数据维度
sqDiffMat = diffMat**2 #平方
sqDistances = sqDiffMat.sum(axis=1) #求和
distances = sqDistances**0.5 #开方
sortedDistIndicies = distances.argsort() # argsort()的作用是对distances排序,返回排序后的数组下标列表
classCount={}
for i in range(k): #获取前k个值
voteIlabel = labels[sortedDistIndicies[i]] #提取第i个数据集对应的标签
b=classCount.get(voteIlabel,0) #get() 函数返回指定键的值,如果值不在字典中返回默认值。
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #统计各类的数目
# classCount.items()返回可遍历的(键, 值)元组数组。
# operator.itemgetter函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值
# key为函数,指定取待排序元素的哪一项进行排序
# 下面两行是测试sorted()函数功能的例子
# students = [('john', 'C', 15), ('jane', 'B', 19), ('dave', 'A', 10)]
# rst = sorted(students, key=lambda student: student[0])
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0] #返回预测的类型
#产生数据
def createDataSet():
group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) #样本数据
labels = ['A','A','B','B'] #样本标签
return group, labels
group, labels=createDataSet() #获得样本数据和样本标签
inX=[1.0,1.1] #待分类数据
rst=classify0(inX, group, labels, 3) #计算分类,得到分类结果
print(rst) #打印结果
代码一运行结果:
综合性示例:使用k-近邻算法改进约会网址的匹配效果
使用Matplotlib创建散点图
from numpy import *
import operator
from os import listdir
import matplotlib
import matplotlib.pyplot as plt
'''
函数功能:读取文件中的数据,并将其转换成列表
'''
def file2matrix(filename):
fr = open(filename) #打开文件
numberOfLines = len(fr.readlines()) #获取文件的行数
returnMat = zeros((numberOfLines,3)) #根据文件的行数,初始化一个元组
classLabelVector = [] #初始化标签列表
index = 0
for line in fr.readlines(): #逐行读取
line = line.strip()
# strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
#注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。
listFromLine = line.split('\t') #split()函数的功能是按()里的内容进行拆分字符串
returnMat[index,:] = listFromLine[0:3] #将每行的前3列装入元组
classLabelVector.append(int(listFromLine[-1])) #将每行最后一列装入标签类列表中
index += 1 #下标索引
return returnMat,classLabelVector #返回数据和标签
filename=r'F:\codes\python\机器学习实战代码\datingTestSet2.txt'
returnMat,classLabelVector=file2matrix(filename)#得到数据和标签
fig=plt.figure() #创建一张图
ax=fig.add_subplot(111) #在一张figure里面生成多张子图。
#ax.scatter我有一篇文章专门讲它的,可过去参考一下
ax.scatter(returnMat[:,1],returnMat[:,2],15.0*array(classLabelVector),15.0*array(classLabelVector))
plt.show()
注意倒数第二行代码为:ax.scatter(returnMat[:,1],returnMat[:,2],...)时画出的图如下
注意倒数第二行代码为:ax.scatter(returnMat[:,0],returnMat[:,1],...)时画出的图如下
归一化数值:
处理不同取值返回的特征值时,通常将数值归一化处理,如将取值范围处理为0到1或者-1到1之间。转化为0-1的公式如下:
newValue=(oldValue-min)/(max-min)
归一化函数如下:
#归一化函数
def autoNorm(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))
normDataSet = normDataSet/tile(ranges, (m,1))
return normDataSet, ranges, minVals 返回归一化后的数据,最大值最小值差,最小值
测试函数代码:
def datingClassTest():
hoRatio = 0.10 #hold out 10%
datingDataMat,datingLabels = file2matrix('F:\codes\python\机器学习实战代码\datingTestSet2.txt') #读取文件并转换成列表格式
normMat, ranges, minVals = autoNorm(datingDataMat) #将数据归一化处理
m = normMat.shape[0] #获取数据集的大小
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3) #对数据集进行分类
print ("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])) #打印分类结果
if (classifierResult != datingLabels[i]): errorCount += 1.0 #如果预测结果和标签不相等,则错误数加1
print ("the total error rate is: %f" % (errorCount/float(numTestVecs))) #打印错误率
print (errorCount) #打印错误数
测试函数运行结果:
欢迎扫码关注我的微信公众号