IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 机器学习02 k近邻法(通俗讲解) -> 正文阅读

[人工智能]机器学习02 k近邻法(通俗讲解)

机器学习02 k近邻法(通俗分析理解)

一、 实验内容

(1) 问题描述

k近邻法(KNN)是一种基本分类与回归算法。其核心思想就是对新的输入实例,在训练数据中找到与该实例最邻近的k个实例,然后少数服从多数,归属于多数属于的类。

(2) 数据集描述

数据集的第一列数据为带划分样本数据的结果(标签),除了第一列数据之外的数据为样本数据。该数据集共有42000个样本数据,每个样本由784个数据组成,数据类型为整型

(3) 实验环境(软硬件)

硬件:联想小新air13

软件:Windows10操作系统;Python 3.7;Pycharm Community

二、算法原理

其实这个算法原理非常之简单,取之于一个非常简单的思想,比如说咱输入好多周氏张氏王氏李氏列祖列宗的照片,然后再输入一个后辈的照片,咱怎么看这个孩子是哪家的呢,当然是看他和谁像啦,找出和他最像的k个人,如果这些人都是周氏,就是周的概率大些咯。道理咱都懂,落在代码上咋实现呢,咋告诉机器这个规则呢?

咱抽象出了这个思想的核心基本要素:距离度量(如何判断相似),k值选择,还有分类决策规则(怎么科学合理地得出结论)

1、距离度量

咋科学合理地判断相似度呢?你总得看眼睛像不像鼻子像不像嘴巴像不像,咱的输入训练集有n维的特征空间,那我们就要结合n维来看,同一维上数值越接近在这一维度就越像,像的多的维度越多总体就越像。就使用距离啦,我喜欢传统的欧氏距离,当然其他的距离也可以,定义为
L p ( x i , x j ) = ( ∑ l = 1 n ∣ x i ( l ) ? x j ( l ) ∣ p ) 1 p L_p(x_i,x_j)=(\sum_{l=1}^{n}|x_i^{(l)}-x_j^{(l)}|^p)^{\frac{1}{p}} Lp?(xi?,xj?)=(l=1n?xi(l)??xj(l)?p)p1?
p>=1,p=2,欧氏距离,p=1,曼哈顿距离,p=无穷大,各个坐标距离最大值。距离越小,两个样本之间就越像!

2、k值选择

k值的选择是个好问题,k肯定不能取所有人,k也不能只取一个人,万一碰巧有个人和他最像但他和他不是一个祖辈,这就很容易出错呀,当然还是有一个比较小的值是最好的,通常采用交叉验证法来选取最优的k值,就是将原始输入的训练集分出一部分测试集,然后不同的k带进去训练,训练出结果模型参数后哪个模型测试集准确率高就选哪个。

3、分类决策

在你选出的k个人里,k个人中哪个族的人多就选哪个族。意思浅显明了,但从数学角度,你得有个科学合理的说法吧。

假如正确的分类为c_j,N_k(x)是你挑出的k个样本点,那你的误分类率
1 k ∑ x i ∈ N k ( x ) I ( y i ≠ c j ) = 1 ? 1 k ∑ x i ∈ N k ( x ) I ( y i = c j ) \frac{1}{k}\sum_{x_i\in N_k(x)}I(y_i\neq c_j)=1-\frac{1}{k}\sum_{x_i\in N_k(x)}I(y_i=c_j) k1?xi?Nk?(x)?I(yi??=cj?)=1?k1?xi?Nk?(x)?I(yi?=cj?)
要使误分类率最小,则经验风险最小,使 ∑ x i ∈ N k ( x ) I ( y i = c j ) \sum_{x_i\in N_k(x)}I(y_i=c_j) xi?Nk?(x)?I(yi?=cj?)最大,即多数投票

对了,
I = { 1 ????? ( y i = c j ) 0 ????? ( y i ≠ c j ) I=\begin{cases}1\,\,\,\,\,(y_i=c_j)\\0\,\,\,\,\,(y_i \neq c_j) \end{cases} I={1(yi?=cj?)0(yi??=cj?)?

4、kd树搜索(以最近邻为例)

当我们训练集特别特别多,我们不可能逐一比对,太耗时了,我们应该怎样才能找到最接近的样本呢?(可扩展为K个)

咱想想看,假如咱看人先看眼睛,那咱要构建一棵树,把眼睛最大众最中等的放在树的顶端。

第一排,咱挂上去就因为它是所有类里面从某一维度上看它是最大众脸的,因为它既然最大众那它的参考价值肯定是最小的,比大众脸眼睛大的先放在左边,比大众脸眼睛小的放在右边,

第二看鼻子,然后把在眼睛大的那一类中找到鼻子最一般的放在第二排,然后鼻子比大众脸大的放在右边,比大众脸小的放在左边,眼睛小的也是同理。

然后咱每一个维度挂着挂着挂到最后,发现没人可以挂的时候呢,诶,发现最后一排都是非常特殊的,因为大众的在前面已经被你们挂完了,这时候孩子的照片来了,你先和所有的特殊的比对一下,找到最接近的,把他放在包里,然后顺着那个人的线索往上找。

毕竟那么特殊的人不可能一找就准,但是能给你一个大概的方向,然后你再顺着往上找呀,有点大众的,大众的,非常大众的。突然诶咱看到这个第四排某一个大众的和他真的很像,那咱就把原来那个人丢了,把他装包里。

咱发现诶这个和他很像的人,发现那个人竟然比那个原来特殊的人更像了,那肯定是某一维度更像了,咱从咱爬上来那一枝没找到,咱就从咱发现这个最像的节点,从另一枝搜下一排有没有人更像,诶如果有,继续放包里,然后从这个点继续往下搜,直到搜到最像的点,停住。

如果没有或者停住了,那我们继续一步步回退往上搜,一直搜到根节点为止,说明我们没有错过漏过啥重要消息。

官方话语:

输入:已构造的kd树;目标点x;

输出:x的最近邻。

(1)在kd树中找出包含目标点x的叶结点:从根结点出发,递归地向下访问kd树。若 目标点x当前维的坐标小于切分点的坐标,则移动到左子结点,否则移动到右子结点。直到子结点为叶结点为止。

(2)以此叶结点为“当前最近点”。

(3)递归地向上回退,在每个结点进行以下操作:

? (a)如果该结点保存的实例点比当前最近点距离目标点更近,则以该实例点为“当前 最近点”。

? (b)当前最近点一定存在于该结点一个子结点对应的区域。检查该子结点的父结点的另一子结点对应的区域是否有更近的点。具体地,检查另一子结点对应的区域是否与以 目标点为球心、以目标点与“当前最近点”间的距离为半径的超球体相交。如果相交,可能在另一个子结点对应的区域内存在距目标点更近的点,移动到另一个子结点。接着,递归地进行最近邻搜索;

如果不相交,向上回退。

(4)当回退到根结点时,搜索结束。最后的“当前最近点”即为x的最近邻点。

三、代码分析

暴力搜索!

import pandas as pd
import numpy as np
import cv2
import random
import time

from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score


# 利用opencv获取图像hog特征
def get_hog_features(trainset):
    features = []

    hog = cv2.HOGDescriptor('hog.xml')

    for img in trainset:
        img = np.reshape(img,(28,28))
        cv_img = img.astype(np.uint8)#转化数据类型

        hog_feature = hog.compute(cv_img)#324
        # hog_feature = np.transpose(hog_feature)
        features.append(hog_feature)
    #此时feature为list类型有42000个元素
    features = np.array(features)#42000,324
    features = np.reshape(features,(-1,324))

    return features

def Predict(testset,trainset,train_labels):
    predict = []
    count = 0

    for test_vec in testset:
        
        print (count)
        count += 1

        knn_list = []       # 当前k个最近邻居
        max_index = -1      # 当前k个最近邻居中距离最远点的坐标
        max_dist = 0        # 当前k个最近邻居中距离最远点的距离

        
        for i in range(k):##i在10中遍历
            label = train_labels[i]
            train_vec = trainset[i]

            dist = np.linalg.norm(train_vec - test_vec) #求测试样本和训练样本i之间的距离

            knn_list.append((dist,label))#10,2?

        # 剩下的点
        for i in range(k,len(train_labels)):#遍历剩下的点
            label = train_labels[i]
            train_vec = trainset[i]

            dist = np.linalg.norm(train_vec - test_vec)         

            #在初始10个样本中找到距离最远的点,初始化max_index,max_dist
            if max_index < 0:
                for j in range(k):
                    if max_dist < knn_list[j][0]:
                        max_index = j
                        max_dist = knn_list[max_index][0]

            
            if dist < max_dist:
                #找到了比最远的那个点更近的点,更新10邻居
                knn_list[max_index] = (dist,label)
                #更新了以后再重新更新最远的点
                max_index = -1
                max_dist = 0


        # 统计选票
      # 填写代码
        result=np.zeros((k,1))
        for i in range(k):
            (dist,label)=knn_list[i]
            result[label]=result[label]+1;
        single_predict=np.argmax(result)
        print(single_predict)
        predict.append(single_predict)

    return np.array(predict)

k = 10

if __name__ == '__main__':

    print ('Start read data')

    time_1 = time.time()

    raw_data = pd.read_csv('train_binary.csv',header=0)
    data = raw_data.values

    imgs = data[0::,1::]
    labels = data[::,0]

    features = get_hog_features(imgs)

    # 选取 2/3 数据作为训练集, 1/3 数据作为测试集
    train_features, test_features, train_labels, test_labels = train_test_split(features[0:4000,:], labels[0:4000], test_size=0.1, random_state=23323)
    print (test_features.shape)
    # print train_features.shape

    time_2 = time.time()
    print('read data cost ',time_2 - time_1,' second','\n')

    print ('Start training')
    print ('knn do not need to train')
    time_3 = time.time()
    print ('training cost ',time_3 - time_2,' second','\n')

    print ('Start predicting')
    test_predict = Predict(test_features,train_features,train_labels)
    time_4 = time.time()
    print ('predicting cost ',time_4 - time_3,' second','\n')

    score = accuracy_score(test_labels,test_predict)
    print ("The accruacy socre is ", score)
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 20:50:48  更:2022-03-21 20:55:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:32:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码