KNN算法详解--(预测约会网站)一点自己的小见解

大体来讲讲KNN算法整个预测的流程

第一步

我们需要将我们获取大量的数据集文本进行处理,把一大堆杂乱的数据分出哪些是数据,哪些是标签,并把一些不需要无用的符号去除,形成数据矩阵和标签矩阵

#  解析文本
from numpy import *
def file2matrix(filename):  # 将文本记录转换为Numpy的解析程序
    fr = open(filename)
    arrayOLines = fr.readlines()  # 读取文件每行数据包括换行符转换为字符串,返回一个列表类似['123\n','siz']
    numberOfLines = len(arrayOLines)  # 得到这个列表的长度,也就是文件的行数
    returnMat = zeros((numberOfLines, 3))  # zeros函数创建数组numberoflines行3列的元素为0的numpy数组,其实是矩阵
    classLabelVector = []
    index = 0
    for line in arrayOLines:  # 列表从头遍历到尾
        line = line.strip()  # 默认头尾删除空白符(包括'\n', '\r',  '\t',  ' '),strip函数里有的话删除头尾指定字符
        listFromLine = line.split('\t')  # 根据\t划分元素,返回列表
        returnMat[index, :] = listFromLine[0:3]
        # 从0+1列到第3列数据赋值给returnMat矩阵的index列,因为这次数据的样本只有3个特征
        classLabelVector.append(int(listFromLine[-1]))  # 数据已经列好了,前3项为数据,最后一项为标签
        # classLabelVector新增最后一列
        # 将最后一列的数据添加到classLabelVector的最后一列
        index += 1
    return returnMat, classLabelVector

第二步

将数据矩阵里的数据全部变成0到1之间的特征值,权重统一
也可以权重不统一,这里我们统一权重


# 归一化特征值
def autoNorm(dataSet):  # 输入数据集
    minVals = dataSet.min(0)
    # min(0)返回该矩阵中每一列的最小值  min(1)返回该矩阵中每一行的最小值
    maxVals = dataSet.max(0)
    # max(0)返回该矩阵中每一列的最大值  max(1)返回该矩阵中每一行的最大值
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))  # 构造和dataSet一样大小的矩阵
    # shape 输出第一个为矩阵的行数,第二个为矩阵的列数
    m = dataSet.shape[0]  # 将矩阵行数输出,shape[1]将矩阵的列数输出
    normDataSet = dataSet - tile(minVals, (m, 1))  # 补全矩阵m行,列数不补,minvals自己自带列数
    normDataSet = normDataSet / tile(ranges, (m, 1))  # 数据集与最小值的差值除以最大值与最小值的差值
    # 将数字特征转化到0到1的区间
    return normDataSet, ranges, minVals

第三步

KNN算法原理:找三个特征值加权平均下权重最小的前k个元素(这里是通过曼哈顿距离公式找的)
西瓜书里评价为懒惰学习法,对于分类器是当场学习,当场预测的,虽然这个法子挺一般,但是简单好上手,方便理解。
PS:classify0函数是的参数是用户输入需要预测的数据已经处理的数据矩阵和数据标签矩阵,k值为选取前k个相关比重最大的

def classify0(inX, dataSet, labels, k):
    # inX是输入的需要判断的分量
    # dataSet为学习器的训练样本,
    # labels给上每个分量的标签,label数量与dataset的行数相同
    # k是离inX参数最近的参数数目
    dataSetSize = dataSet.shape[0]  # 返回dataset这个矩阵的行数
    diffMat = tile(inX, (dataSetSize, 1)) - dataSet  # diff一般是指差分的意思,前后做差
   # tile 可以把inX这个向量补成和dataset一样大小的矩阵,如果inX是[1,2]tile(inX,3)就变成([1,2,1,2,1,2])
    # tile这里是在行填充datasetsize次,在列不填充
    sqDiffMat = diffMat ** 2  # sq所得差值平方
    sqDistances = sqDiffMat.sum(axis=1)  # 将所有矩阵差值平方的数值相加起来
    # axis = 0为矩阵列求和 ,, =1 为矩阵行求和
    # 分别对训练集每列不同的特征值与inX这个相应分量的特征值做差之后平方相加在开根号
    distances = sqDistances ** 0.5  # 再开方使用欧式距离公式,即根号下两点差值的平方之和
    # 得到的Distances是n个特征值的权值测量矩阵
    sortedDistIndicies = distances.argsort()  # argsort返回从小到大的数组元素的数组号 arg可以理解为arguments参数
    # indicies其实indices(index的复数)不知道为什么书上打错了,
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]  # 将前k个权值最小的元素序号的标签记录在voteIlabel
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
        # get是返回字典键值指定的值,votelabel如果美丽对应的0,就get得到0,
        # 这里加1重新赋给字典是 因为原本是0到k-1个点变成1到k个点,将序号规范化
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    # 将前k个点排序
    return sortedClassCount[0][0]

第四步

约会网站预测函数,与用户之间的接口,用户需要输入自己的数据
有三项数据特征值:
1,每年的飞行里程数
2,玩视频游戏所耗时间百分比
3,每周消费冰激凌公升数


def classifyPerson():
    resultList = ['not at all', 'in small doses', 'in large doses']
    percentTats = float(input("percentage of time spent playing video games?"))
    ffMiles = float(input("frequent flier miles earned per year?"))
    iceCream = float(input("liters of ice cream consumed per year?"))
    datingDataMat, datingLabels = file2matrix('E:/machinelearingdatas/machinelearninginaction-master/Ch02'
                                              '/datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = array([ffMiles, percentTats, iceCream])
    classifierResult = classify0((inArr - minVals) / ranges, normMat, datingLabels, 3)
    print("You will probably like this person : ", resultList[classifierResult - 1])

所以最后调用这个函数就可以了,这个函数包含了之前所有的函数模块

附加图像

我们还可以将处理好的数据矩阵和数据标签矩阵进行处理
将数据集的数据和标签分布通过散点图表示出来

# 分析数据用Matplotlib创建散点图
import matplotlib
import matplotlib.pyplot as plt

datingDataMat, datingLabels = file2matrix('E:/machinelearingdatas/machinelearninginaction-master/Ch02'
                                          '/datingTestSet2.txt')
fig = plt.figure()
# figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True)
# num:图像编号或名称,数字为编号 ,字符串为名称
# figsize:指定figure的宽和高,单位为英寸;
# dpi参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80      1英寸等于2.5cm,A4纸是 21*30cm的纸张 
# facecolor:背景颜色
# edgecolor:边框颜色
# frameon:是否显示边框
ax = fig.add_subplot(111)  # 1*1的网格,第一子图,每subplot命令会创建一个子图
ax.scatter(datingDataMat[:, 0], datingDataMat[:, 1], 15 * array(datingLabels), array(datingLabels))
# 将二列的数据作为横坐标,第三列的数据作为纵坐标,第三个参数是大小,第四个参数是颜色,详见技术文档
plt.show()

pycharm里得到的散点图

pycharm里得到的散点图
发布了19 篇原创文章 · 获赞 4 · 访问量 503

猜你喜欢

转载自blog.csdn.net/qq_35050438/article/details/103086794