美文网首页
机器学习:K-近邻算法代码详细注释笔记

机器学习:K-近邻算法代码详细注释笔记

作者: Messix_1102 | 来源:发表于2021-01-17 21:34 被阅读0次

分类方法代码及注释

# 分类方法代码及注释
#inx 要分类的向量, dataset 数据集, labels 数据集分类, k 取最接近的前k个分类
def classify0(inx, dataSet, labels, k):
    # 获取数据集行数
    dataSetSize = dataSet.shape[0]
    # 复制输入向量,使其与数据集具有相同行数,做矩阵减法
    # 此处tile函数把inx向量复制 dataSetSize 行、1列,使之可以与数据集做矩阵减法
    # https://blog.csdn.net/cszhang570221322/article/details/85107935
    diffMat = tile(inx, (dataSetSize, 1)) - dataSet
    # 矩阵求平方
    sqDiffMat = diffMat**2
    # 每行相加
    # https://blog.csdn.net/laobai1015/article/details/85720875
    sqDistance = sqDiffMat.sum(axis=1)  
    # 取平方根
    distances = sqDistance ** 0.5
    # 取排序下标
    # argsort 方法举例
    # x=np.array([1,4,3,-1,6,9])
    #             0 1 2  3 4 5
    #             3 2 3  1 4 5        
    # x.argsort()
    # [3,0,2,1,4,5]
    sortedDistIndicies = distances.argsort()
    # 声明字典
    classCount = {}
    for i in range(k):
        # 获取对应的目标变量
        voteIlable = labels[sortedDistIndicies[i]]
        # 目标变量存入字典
        classCount[voteIlable] = classCount.get(voteIlable, 0) + 1
    # 根据目标变量出现频率倒序
    # 参数1 为排序的数据,参数 2 为用于比较大小的字段,参数3 表示是否倒序
    sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True)
    return sortedClassCount

读取文件内容转换为矩阵方法

# 读取文件中的数据,转换为训练集
def file2matrix(filename):
    fr = open(filename)
    arrayOline = fr.readlines()
    numberOfLines = len(arrayOline)
    # 创建 numberOfLines 行 3 列的局长
    returnMat = zeros((numberOfLines, 3))
    classLabelVector = []
    index = 0
    for line in arrayOline:
        # 行字符串去除前后空格
        line = line.strip()
        # 以table空格截取字符串
        listFormLine = line.split('\t')
        # 把解析后数组的前三项赋值给矩阵
        returnMat[index, :] = listFormLine[0:3]
        # 取解析后数组的最后一项 赋值给目标值
        classLabelVector.append(int(listFormLine[-1]))
        index += 1
    return returnMat, classLabelVector

利用matplotlib绘制散点图方法

# 创建散点图
# datingDataMat 矩阵, datingLabels 特征值, x1 x2 绘图所取的 矩阵列数据,
def showDot(datingDataMat, datingLabels, x1, x2):
    # 创建画布
    # num 散点图名称
    # figsize 画布宽 8 英寸长,高 8 英寸
    # dpi参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80 
    # facecolor 背景颜色
    # edgecolor 边框颜色
    # frameon 是否显示边框
    fig = plt.figure(num='约会对象分类散点图', figsize = [8, 8], dpi = 80)
    # 将画布分割成1行1列,图像画在从左到右从上到下的第1块
    # fig.add_subplot(349) 的含义
    # ----    
    # ----
    # +---
    # 其中 “+” 所在的位置为绘图位置
    ax = fig.add_subplot(111)
    # x、y 点的位置
    # s 点的大小
    # c 点的颜色
    ax.scatter(x = datingDataMat[:, x1], y = datingDataMat[:, x2], s = 15.0*array(datingLabels), c = 150.0*array(datingLabels))
    plt.show()

数据归一化方法

# 归一化,规范特征值,防之过大值影响计算结果
def autoNorm(dataSet):
    # 获取矩阵每一列最小值
    # eg: a = np.array([[1,1,3],[2,0,4],[3,5,1]])
    # dataSet.min() 获取矩阵所有元素最小值: 0
    # dataSet.min(0) 获取矩阵每一列最小值: [1,0,1]
    # dataSet.min(1) 获取矩阵每一行最小值: [1,0,1]
    minVals = dataSet.min(0)
    # 同上
    maxVals = dataSet.max(0)
    # 矩阵减法获取最大最小值范围
    ranges = maxVals - minVals
    # shape 函数获取矩阵 形状,比如 3 行 4 列 矩阵结果为 (3, 4)
    # zeros 函数获取跟dataSet同形状的0维数组
    # np.zeros(np.shape(a)) 结果为 [[0,0,0],[0,0,0],[0,0,0]]
    normDataSet = zeros(shape(dataSet))
    # a = np.array([[1,1,3],[2,0,4],[3,5,1],[4,5,6]])
    # a.shape[0] = 4 行数
    # a.shape[1] = 4 列数
    m = dataSet.shape[0]
    # 归一算法 (old - min) / (max - min)
    # tile(minVals, (m, 1)) 把最小值 向量复制 m 行 1 列
    normDataSet = dataSet - tile(minVals, (m, 1))
    # tile(ranges, (m, 1)) 把最大值 向量复制 m 行 1 列
    normDataSet = normDataSet / tile(ranges, (m, 1))
    return normDataSet, ranges, minVals

约会数据分类测试

# 约会数据分类测试
def datingClassTest():
    hoRatio = 0.10
    # 从 datingTestSet2 文件中获取矩阵和目标值
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    # 归一化
    normMat, ranges, minVals = autoNorm(datingDataMat)
    # 行数
    m = normMat.shape[0]
    # 列数
    n = normMat.shape[1]
    # 获取10%的数据
    numTestVecs = int(m * hoRatio)
    errorCount = 0.0

    # 遍历计算每条数据
    for i in range(numTestVecs):
        # eg: nmArr = np.array([[1,2,3],
        #                       [4,5,6],
        #                       [7,8,9],
        #                       [10,11,12]])
        # X[i,j] 取矩阵X的第i行第j列的元素 nmArr[2,2] = 9
        # X[-1, -1]为数组X中位于最后一行,最后一列的元素

        # X[:,j] 从第0行开始到最后一行结束,取矩阵X的第 i 列的元素              nmArr[:,1] = [2,5,8,11]
        # X[a:, j]---->从第 a 行开始到最后一行结束,取矩阵X的第 j 列的元素      nmArr[1:,1] = [5,8,11]
        # X[:b, j]---->从第 0 行开始到第b-1行结束,取矩阵X的第 j 列的元素       nmArr[:2,1] = [2,5]
        # X[a:b, j]---->从第 a 行开始到第b-1行结束,取矩阵X的第 j 列的元素      nmArr[1:2,1] = [5]
        # X[:, i:j]---->从第0行开始到最后一行结束,取矩阵X的第 i 列到 j-1 列的元素    nmArr[:,1:3] = [[2,3],[5,6],[8,9],[11,12]]
        # X[:, i:j]---->从第0行开始到最后一行结束,取矩阵X的第 i 列到 j-1 列的元素    nmArr[1:,1:3] = [[5,6],[8,9],[11,12]]
        classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
        # 获取分类结果
        resultLabel = classifierResult[0][0]
        print ("the classifer came back with: %d, the real anwser is: %d" % (resultLabel, datingLabels[i]))

        if (resultLabel != datingLabels[i]): 
            print("   %d X", (i))
            errorCount += 1.0

    print ("the total error rate is %f" % (errorCount / float(numTestVecs)))

约会对象分类

# 约会对象分类
def classifyPerson():
    resultList = ['not at all', 'in small doses', 'in large doses']
    # input('XXX') 为输入提示信息
    # float(input('XXX')) 把输入的信息 转换为float
    ffMiles = float(input("frequent flier miles eaarned per year?"))
    percentTags = float(input("percentage of time spent playing video games?"))
    iceCream = float(input("liters of ice cream consumed per year?"))

    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    # 输入转换为计算向量
    inArr = array([ffMiles, percentTags, iceCream])
    # 输入向量 先归一,然后分类
    classifierResult = classify0((inArr - minVals) / ranges, normMat, datingLabels, 3)
    # 获取分类结果
    resultMark = classifierResult[0][0]
    print ("You will probably like this person: %s" % (resultList[resultMark - 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] = int(lineStr[j])
    return returnVect

手写输入测试

# 手写数字测试
def handwritingClassTest():
    hwLabels = []
    # 从文件夹加载文件列表
    trainingFileList = listdir('machinelearninginaction/Ch02/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('machinelearninginaction/Ch02/trainingDigits/%s' % fileNameStr)
    
    # 加载测试文件
    testFileList = listdir('machinelearninginaction/Ch02/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('machinelearninginaction/Ch02/testDigits/%s' % fileNameStr)
        # 分类结果
        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)[0][0]
        print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr))

        if(classifierResult != classNumStr):
            errorCount += 1.0

        print("the total number of errors is: %d" % errorCount)
        print("the total error rate is: %f" % (errorCount/float(mTest)))

相关文章

网友评论

      本文标题:机器学习:K-近邻算法代码详细注释笔记

      本文链接:https://www.haomeiwen.com/subject/hspzaktx.html