KNN实现

from array import array
from os import listdir
from numpy import *
import operator


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


#k-邻近算法核心
#inX:用于分类的输入向量。即将对其进行分类。
#dataSet:训练样本集
#labels:标签向量
def classify0(inX, dataSet, labels,k):
        dataSetSize = dataSet.shape[0] #得到数组的行数
        diffMat= tile(inX, (dataSetSize,1)) - dataSet
        sqDiffMat = diffMat**2
        sqDistances = sqDiffMat.sum(axis=1)
        distances = sqDistances**0.5
        sortedDisIndicies = distances.argsort()
        classCount = {}
        for i in range(k):
                voteIlabel = labels[sortedDisIndicies[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 = zeros((numberOfLines, 3))
        d = {'didntLike': 1, 'smallDoses': 2, 'largeDoses': 3}
        classLabelVector = []
        index =0
        for line in arrayOLines:
                line = line.strip()
                listFromLine = line.split('\t')
                returnMat[index,:] = listFromLine[0:3]
                #classLabelVector.append(d[listFromLine[-1]])  # 取到字典中对应的label值
                classLabelVector.append(listFromLine[-1])  # 取到字典中对应的label值
                index += 1
        return returnMat, classLabelVector


#归一化特征值:处理不同范围的特征值
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
        datingDataMat, datingLabels = file2matrix('datingTestSet.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: %s, the real answer is: %s" % (classifierResult, datingLabels[i]))
            if (classifierResult != datingLabels[i]): errorCount += 1.0
        print("the total error rate is : %f " %(errorCount/float(numTestVecs)))


#appointment site预测函数
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('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[int(classifierResult)- 1])


#图像转测试向量
def img2vector(filename):
    returnVect = zeros((1,1024))
    fr = open(filename)
    for i in range(32):
        lineStr =fr.readline()
        for j in  range(32):
            returnVect[0,32*i+j] = lineStr[j]
    return returnVect


def handwritingClassTest():
    hwLabels = []
    trainingFileList = listdir('digits/trainingDigits')
    m = len(trainingFileList)
    trainingMat = zeros((m, 1024))
    for i in range(m):
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        hwLabels.append(classNumStr)
        trainingMat[i,:] = img2vector('digits/trainingDigits/%s' % fileNameStr)
    testFileList = listdir('digits/testDigits')
    errorCount = 0.0
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        vectorUnderTest = img2vector('digits/testDigits/%s' % fileNameStr)
        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
        print("the classifier came back with: %d ,the real answer is : %d"%(int(classifierResult),int(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)))


<think>好的,用户想用KNN算法实现海伦公式的计算或分类。首先,我需要理清楚海伦公式和KNN算法之间的关系。海伦公式是用于计算三角形面积的,公式是$S = \sqrt{p(p-a)(p-b)(p-c)}$,其中$p$是半周长。而KNN是一种分类算法,通常用于根据特征向量进行分类,比如海伦约会数据集中的分类问题。 用户可能混淆了“海伦公式”和“海伦约会数据集”。根据提供的引用[3]和[4],海伦约会问题是一个分类任务,使用KNN算法来预测约会对象的吸引力等级。因此,用户可能实际上是想应用KNN到海伦约会数据集,而不是数学上的海伦公式。 接下来需要确定用户的需求。如果用户确实想用KNN进行三角形分类,比如根据三边长度判断三角形类型(等边、等腰、不等边),那么需要构建相应的数据集和特征。但根据引用中的信息,更可能的情况是用户希望复现海伦约会问题的KNN实现,可能打字错误导致“公式”出现。 需要确认示例代码的结构。引用[3]提到了数据预处理,计算差值矩阵,整合标签。引用[4]展示了数据可视化的代码。因此,正确的步骤应包括数据读取、归一化、距离计算、分类和评估。 可能用户需要的是如何用Python实现KNN在海伦约会数据集上的分类,包括数据加载、特征归一化、KNN算法实现、测试评估等步骤。需要按照这些步骤组织代码,并解释关键部分,比如距离计算、投票机制等。 最后,确保代码符合Python语法,使用pandas和numpy进行数据处理,matplotlib进行可视化,并引用提供的参考文献来支持说明。</think>以下是使用KNN算法实现海伦约会问题分类的完整实现方案: ### 一、KNN算法实现步骤 1. **数据准备** 读取包含飞行里程数、游戏时间占比、冰淇淋消费量和吸引力等级的数据集,格式为: $特征1,特征2,特征3,标签$ 例如:`40920,8.326976,0.953952,3`[^4] 2. **特征归一化** 采用最小-最大归一化公式: $$x_{norm} = \frac{x - x_{min}}{x_{max} - x_{min}}$$ 消除特征量纲差异[^4] ```python import pandas as pd import numpy as np def autoNorm(data): minVals = data.min(0) maxVals = data.max(0) ranges = maxVals - minVals normData = (data - minVals) / ranges return normData, ranges, minVals ``` 3. **距离计算** 使用欧氏距离公式: $$d = \sqrt{\sum_{i=1}^n (x_i - y_i)^2}$$ 计算测试样本与所有训练样本的距离[^3] ```python def classify(inX, dataset, labels, k): # 计算差值矩阵 diffMat = np.tile(inX, (dataset.shape[0],1)) - dataset # 计算欧式距离 distances = np.sqrt((diffMat**2).sum(axis=1)) # 整合距离和标签 distLabels = pd.DataFrame({'dist': distances, 'label': labels}) # 按距离排序并取前k个 kLabels = distLabels.sort_values(by='dist').iloc[:k,1] # 投票选出最高频率标签 return kLabels.value_counts().idxmax() ``` ### 二、完整实现示例 ```python from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 数据读取 def file2matrix(filename): data = pd.read_csv(filename, sep='\t', header=None) return data.iloc[:,:3], data.iloc[:,3] # 主程序 if __name__ == '__main__': # 加载数据 features, labels = file2matrix('datingTestSet.txt') # 数据归一化 normFeatures, _, _ = autoNorm(features) # 划分数据集 X_train, X_test, y_train, y_test = train_test_split(normFeatures, labels, test_size=0.2) # 预测并评估 predictions = [classify(X_test.iloc[i], X_train.values, y_train.values, 3) for i in range(len(X_test))] print(f"准确率: {accuracy_score(y_test, predictions):.2%}") ``` ### 三、关键点说明 1. **数据可视化** 使用Matplotlib可绘制特征分布图: ```python import matplotlib.pyplot as plt plt.scatter(normFeatures[:,0], normFeatures[:,1], c=labels) plt.xlabel('飞行里程') plt.ylabel('游戏时间') plt.show() ``` 2. **参数优化** 通过交叉验证选择最佳k值: $$k = \arg\max_{k} \sum_{i=1}^n I(y_i = \hat{y}_i^{(k)})$$ 通常k取3-10的奇数[^2] 3. **算法特点** - 时间复杂度:$O(n^2)$(每次预测需计算全部距离) - 空间复杂度:$O(n)$(需存储全部训练数据)[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值