kNN 约会网站总代码 在kaggle上写的

import numpy as np
from matplotlib.font_manager import FontProperties
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
import time
import pandas as pd
import  operator#引入运算符模块
start_time = time.time()
"""
Parameters:
    filename - 文件名
Returns:
    returnMat - 特征矩阵
    datingLabels - 分类Label向量
"""
# 函数说明:打开并解析文件,对数据进行分类:1代表不喜欢,2代表魅力一般,3代表极具魅力
def file2matrix(filename):
    arrayOfLines=pd.read_table(filename,sep="\t",header=None)#打开文件
    numberOflines=len(arrayOfLines)#得到文件的行数
    datingDataMat=np.zeros((numberOflines,3))#创建返回的NumPy矩阵
    datingLabels=[]#返回分类标签向量
    #循环处理每一行的文件
    #print(type(arrayOfLines))
    for index, row in arrayOfLines.iterrows():
        datingDataMat[index,:]=row[0:3]#选取前三列元素,每次循环是一行
        label=row[3]#输出标签的文本
        ####根据文本中标记的喜欢的程度进行分类,1代表不喜欢,2代表魅力一般,3代表极具魅力
        if label == 'didntLike':
            datingLabels.append(1)
        elif label == 'smallDoses':
            datingLabels.append(2)
        elif label == 'largeDoses':
            datingLabels.append(3)
    return datingDataMat,datingLabels

#归一化数据
def autoNorm(dataSet):
    minVals=dataSet.min(0)#参数0:从列中选取最小值
    maxVals=dataSet.max(0)
    ranges=maxVals-minVals#取值范围
    normDataSet=np.zeros(np.shape(dataSet))#创建新的返回矩阵
    m=dataSet.shape[0]#返回dataSet的行数
    #计算归一化特征值
    normDataSet=dataSet-np.tile(minVals,(m,1))#原值-最小值,tile将minVals的行复制m次,列复制一次(即列数不变)
    normDataSet=normDataSet/np.tile(ranges,(m,1))#计算归一化特征值
    #return normDataSet,ranges,minVals#返回
    return normDataSet,minVals,ranges

    
####为每组数据值分类,函数的功能是使用k-近邻算法将 每组数据划分到某个类中
def classify0(inX,dataSet,labels,K):
    #numpy函数shape[0]返回dataSet的行数
    dataSetSize=dataSet.shape[0]#获取数组的形状信息,0返回行数,1返回列数
    # 在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向)
    diffMat=np.tile(inX,(dataSetSize,1))-dataSet#测试集和训练集之前的x,y上的差值,新(x,y)=(x_测-x_训练,y_测-y_训)
    """
    c = np.array([[1, 2], [3, 4]])
        d = np.tile(c, (2, 3))
        print(d)
        # 输出:
        # [[1 2 1 2 1 2]
        #  [3 4 3 4 3 4]
        #  [1 2 1 2 1 2]
        #  [3 4 3 4 3 4]]
    """
    ##计算欧式距离
    sqDiffMat= diffMat ** 2#计算距离的平方
    sqDistances=sqDiffMat.sum(axis=1)#(x_测-x_训练)^2+y_测-y_训)^2
    distances=pow(sqDistances,1/3)#开根号
    ##返回distances中元素从小到大排序后的索引值
    sortedDistIndicies=distances.argsort()#argsort,返回数组排序后的索引,先从小到大排序然后再按照各个顺序返回数值没有排序前的索引
    #argsort()返回最小的的数值的索引,之后返回第二小的索引
    """distances=[129.0736224 , 127.28314892, 117.13667231, 10. ,15.13274595,18.24828759])
        sortedDistIndicies=[3, 4, 5, 2, 1, 0]
    """
    classCount={}#创建空字典
    for i in range(K):
        # 取出前k个元素的类别
        voteIlabel=labels[sortedDistIndicies[i]]
        #计算类别次数
        #classCount.get(voteIlabel, 0) 表示获取字典 classCount 中键为 voteIlabel 的值,如果不存在则返回0
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    #对键值进行排序
    #classCount.items() 返回字典 classCount 中所有键值对的视图
    # python3中用items()替换python2中的iteritems()
    # key=operator.itemgetter(1)根据字典的值进行排序
    # key=operator.itemgetter(0)根据字典的键进行排序
    #reverse = True
    #是排序函数的关键字参数,表示按照降序进行排序
    sortedClassCount=sorted(classCount.items(),#sorted排序,并返回一个列表
                            key=operator.itemgetter(1),reverse=True)
    #print(sortedClassCount[0][0])
    return sortedClassCount[0][0]
    #return distances,sortedDistIndicies

#分类器,计算错误次数比例
def datingClassTest(normDataSet, datingLabels):
    hoRatio=0.10
    m=normDataSet.shape[0]#输出normDataSet的行数
    numTestVecs=int(m*hoRatio)#计算测试集的数量
    errorCount=0.0#错误率
    for i in range(numTestVecs):
        #每行数据的分类结果
        classifierResult=classify0(normDataSet[i,:],normDataSet[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        #print("分类器返回值:{},真实标签:{}".format(classifierResult,datingLabels[i]))
        #错误次数计算
        if classifierResult != datingLabels[i]:
            errorCount+=1.0
    print("错误率为{:.2f}%".format((errorCount/m)*100))#输出错误率

"""
minVals--------训练集里面的最小值
ranges---------训练集范围
normDataSet--------归一化后的训练集
datingLabels---训练集标签
"""
#函数说明:通过输入一个人的三维特征,进行分类输出
def classifyPerson(minVals,ranges,normDataSet,datingLabels):
    #输出结果
    resultList=["讨厌","有些喜欢","非常喜欢"]
    #三维特征用户输入
    precentTats = float(input("玩视频游戏所耗时间百分比:"))
    ffMiles = float(input("每年获得的飞行常客里程数:"))
    iceCream = float(input("每周消费的冰激淋公升数:"))
    inArr = np.array([precentTats, ffMiles, iceCream])#将输入特征转为测试集格式
    norminArr = (inArr - minVals) / ranges#测试集归一化
    #返回分类结果
    classifierResult = classify0(norminArr, normDataSet, datingLabels, 3)
    #打印结果,-1是因为分类结果是1,2,3,但是对应索引是0,1,2
    print("你可能{}这个人" .format(resultList[classifierResult-1]))
    
#函数说明:可视化数据

def showdata(datingDataMat, datingLabels):
    font=FontProperties(fname=r"/kaggle/input/use-font/Excalidraw.ttf", size=14)#前缀为r的字符串表示原始字符串(raw string)。使用原始字符串时,反斜杠\不会被解释为转义字符,而是作为普通字符处理
    #将fig画布分布nrows行ncols列,不共享x、y,axs[0][0]表示第一行第一个区域
    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")
    ##画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第二列(玩游戏)数据画散点数据,散点大小为15,透明度为0.5
    axs[0][0].scatter(x=datingDataMat[:,0],y=datingDataMat[:,1],color=labelsColors,s=15,alpha=0.5)
    #设置标题,x轴label,y轴label
    axs0_title_text  = axs[0][0].set_title(u'每年获得的飞行常客里程数与玩视频游戏所消耗时间占比', fontproperties=font)#fontproperties参数不能大写首字母为FontProertise
    axs0_xlabel_text = axs[0][0].set_xlabel(u'每年获得的飞行常客里程数', fontproperties=font)
    axs0_ylabel_text = axs[0][0].set_ylabel(u'玩视频游戏所消耗时间占', fontproperties=font)
    plt.setp(axs0_title_text,size=9,weight='bold',color='red')#setp是matplotlib.pyplot模块的一种方法,批量设置对象属性,weight(字体粗细)
    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=font)
    axs1_xlabel_text = axs[0][1].set_xlabel(u'每年获得的飞行常客里程数', fontproperties=font)
    axs1_ylabel_text = axs[0][1].set_ylabel(u'每周消费的冰激淋公升数', fontproperties=font)
    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=font)
    axs2_xlabel_text = axs[1][0].set_xlabel(u'玩视频游戏所消耗时间占比', fontproperties=font)
    axs2_ylabel_text = axs[1][0].set_ylabel(u'每周消费的冰激淋公升数', fontproperties=font)
    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')
    #设置图例
    #mlines.line2D给图表设置属性
    didntLike=mlines.Line2D([],[],color="black",marker=".",markersize=6,label='didntLike')
    smallDoes=mlines.Line2D([],[],color="orange",marker=".",markersize=6,label="smallDoes")
    largeDoses = mlines.Line2D([], [], color='red', marker='.',
                               markersize=6, label='largeDoses')
    #添加图例
    #legend在图形中添加图例的方法,handles 参数是一个包含要显示在图例中的线条或其他图形对象的列表
    axs[0][0].legend(handles=[didntLike, smallDoes, largeDoses])
    axs[0][1].legend(handles=[didntLike, smallDoes, largeDoses])
    axs[1][0].legend(handles=[didntLike, smallDoes, largeDoses])
    #显示图片
    plt.show()


if __name__=="__main__":
    #打开的文件名
    filename="/kaggle/input/datingtestset/datingTestSet.txt"
    #打开并处理数据
    datingDataMat, datingLabels=file2matrix(filename)
    #数据归一化
    normDataSet,minVals,ranges=autoNorm(datingDataMat)
    # kNN,并计算数据分类正确率
    datingClassTest(normDataSet, datingLabels)
    #数据可视化
    showdata(normDataSet, datingLabels)
    #计算运行时间
    end_time = time.time()
    execution_time = end_time - start_time
    print(f"代码执行时间:{execution_time} 秒")
    #自己输入数据来获得输出结果
    classifyPerson(minVals,ranges,normDataSet,datingLabels)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值