机器学习实战之KNN算法

书上的代码看不懂,自己写了一个,就是太麻烦,书上才15行,我用了26行代码,,可是我为什么看不懂别人的代码啊!哭唧唧

主要是思路,这里我用的数据特别简单,就是自己写了四个点,然后给他们标签,来一个新的数据,通过计算该点与已知数据点(带有标签的那种)的距离,选取K个最近的点,统计这K个点的标签,选取最多类别的那一个作为最后该新输入数据集的标签,其实原理类似于说,你周围的点是什么样子,其实大概率决定了你以后是什么样子。

接下来直接附上代码。

# -*- coding: utf-8 -*-
"""
Created on Sun Apr 29 13:55:48 2018

@author: xuanxuan
"""
import numpy as np

#计算两点之间的距离,把距离作为key以及训练数据的标签作为value存成一个字典
def comp_dis(X,L,Y):  #这里传的参数都是数组类型的
    D={}  #存储计算的距离
    for i in range(len(X)):
        d=np.sqrt((X[i][0]-Y[0][0])**2+(X[i][1]-Y[0][1])**2)
        D[d]=L[i][0]

    #将存成的字典按照Key进行排序  返回一个数组,每一项第一个元素都是距离,另一个是相应的标签;
    #只不过第一项是已经排好序的
    D_sorted=sorted(D.items(),key=lambda x:x[0])
    #print(D_sorted)
    return D_sorted


def Knn(D_sorted,k=2):
    d={}
    for i in range(k):
        key=D_sorted[i][1]
        if key not in d:
            d[key]=0
        else:
            d[key]+=1
    d_sorted=sorted(d.items(),key=lambda x:x[1],reverse=True)
    label=d_sorted[0][0]
    return label




if __name__=="__main__":
    train_data=np.array([[10,1],[10,2],[1,10],[1,8]])
    train_label=np.array([['A'],['A'],['B'],['B']])
    test_data=np.array([[5,1]])
    D_sorted=comp_dis(train_data,train_label,test_data)
    label=Knn(D_sorted,3)
    print("对该输入数据的分类为:\n{}".format(label))


************************下面是一个约会网站预测的例子**********************

这个数据集是机器学习实战里面的数据集。我看了一遍书,有了思路之后,然后用自己的方法实现了一下,其实主要还是对算法理解了才行,实现方式可以有很多种,还有就是对于书上的代码顺着敲一遍是没有任何意义的,嘻嘻

可是,书上预测的错误率才0.024,我的竟然0.36,,,,哭唧唧
还有就是参数我选的80%训练,20%测试,然后K选的10,好像是最好的了,按照课本的90%训练 10%测试,K=3更不忍直视,能怎么办,宝宝也很绝望啊

下面是代码:

# -*- coding: utf-8 -*-
"""
Created on Sun Apr 29 18:57:19 2018

@author: xuanxuan
"""
#knn算法应用在约会网站上

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cross_validation import train_test_split


#首先导入数据
def getdata():
    dataarr=[]
    labelarr=[]
    file=open("E:/pyhtonworkspace/py3-pratice/book_practice_python/mechinelearning_in_action/chapter02/datingTestSet2.txt")
    for line in file:
        linearr=line.strip().split()
        L=[]
        for s in linearr:
            L.append(float(s))
        dataarr.append(L[:-1])  
        labelarr.append(L[-1])  
    datamat=np.mat(dataarr)      #把训练数据转变为1000*3的矩阵
    labelmat=np.mat(labelarr).T  #把测试数据转变为1000*1的矩阵
    return datamat,labelmat 


def draw(datamat,labelmat):

    m=np.shape(datamat)[0]
    for i in range(m):
        plt.scatter(datamat[i,0],datamat[i,1],10*labelmat[i,0],4*labelmat[i,0])

    plt.show()

#主要是对数据进行归一化处理
def norm(datamat0):
    m,n=np.shape(datamat0)
    max=datamat0.max(0)  #1*3的矩阵
    min=datamat0.min(0)  #1*3的矩阵
    #print(max,min)
    dataarr=[]
    for i in range(m):
        L=[]
        for j in range(n):
            a=(datamat0[i,j]-min[0,j])/(max[0,j]-min[0,j])
            L.append(float(a))
        dataarr.append(L)
    datamat=np.mat(dataarr)
    #print(datamat[:10])
    return datamat  #返回归一化之后的数据矩阵

def predict(d_new,k):  #这里的d_new是一个列表 里边的元素是tuple!!
    d={}
    for i in range(k):
        key=d_new[i][1]
        if key not in d:
            d[key]=0
        else:
            d[key]+=1

    #现在的d是key-value:标签-个数的字典,现在需要按照value进行排序(降序主要是多数表决着最多的类别数作为该测试点最终的样本标签)
    d_sorted=sorted(d.items(),key=lambda x:x[1],reverse=True)
    return d_sorted[0][0]  #返回的是最终对该样本预测的标签


def KNN(train_data,train_label,test_data,test_label,k=15):
    m=np.shape(test_data)[0]    #测试数据集的维度 m*3
    n=np.shape(train_data)[0] #训练数据集的维度 n*3
    num=0  #用来统计预测错误率的
    for i in range(m):
        d={}  #用来存放测试集中该样本与训练集中相应点之间的距离,以及相应的标签
        for j in range(n):
            dis=np.sqrt((test_data[i,0]-train_data[j,0])**2+(test_data[i,1]-train_data[j,1])**2+(test_data[i,2]-train_data[j,2]**2))
            d[dis]=train_label[j,0]  #存成一个字典,key-value:距离,标签
        d_new=sorted(d.items(),key=lambda x:x[0])  #对字典的key进行排序(升序,主要是着距离最近的k个点) 返回一个tuple!!!而不再是字典了不过对应的仍然是距离-标签 的形式
        pre=predict(d_new,k)
        if pre!=test_label[i]:
            num+=1
    error=num/m
    return error




if __name__=="__main__":
    datamat0,labelmat=getdata()
    datamat=norm(datamat0)  #将数据及逆行归一化之后返回的数据矩阵
    #draw(datamat,labelmat)
    train_data,test_data,train_label,test_label=train_test_split(datamat,labelmat,test_size=0.25,random_state=33)
    error=KNN(train_data,train_label,test_data,test_label,10)
    print("使用KNN算法预测的错误率为:\n{}".format(error))


还有就是,我实现一个算法要好久,三个小时,怎么肥si?
明天也要加油鸭~~~

******************************KNN算法识别手写数字**********************

看完书之后按照自己的理解实现了一下,可是为什么我运行不出来啊,是我的电脑有问题,嗯,我逻辑是对的~~~
是电脑配置太低了嘛,,,

接下来直接附上代码啦~~

# -*- coding: utf-8 -*-
"""
Created on Sun Apr 29 21:56:21 2018

@author: xuanxuan
"""

#识别手写数字,使用K近邻算法
import numpy as np
from os import listdir

#读取其中一个文件比如0_0.txt 把该文件作为一个样本,共有1024个特征
def openfile(filename):
    file=open(filename)
    dataarr=[]
    for i in range(32):
        line=file.readline()
        for j in range(32):
            dataarr.append(int(line[j]))

    return dataarr  #返回的是一个列表 里面由1024个元素,代表一个文件样本的1024个特征



def get_data1():

    filenames=listdir("E:/pyhtonworkspace/py3-pratice/book_practice_python/mechinelearning_in_action/chapter02/digits/trainingDigits" )
    m=len(filenames)  #训练数据集中文件个数(样本数)
    labels=[]
    datas=[]
    for i in range(m):
        L=[]
        filename=filenames[i]
        filenamenum=filename.split('.')[0]
        label=filenamenum.split('_')[0]
        L.append(label)  #对于每一个样本都有一个label标签,把所有的label存在一个列表labels
        labels.append(L)
        data=openfile("E:/pyhtonworkspace/py3-pratice/book_practice_python/mechinelearning_in_action/chapter02/digits/trainingDigits" +'/'+filename)
        datas.append(data)
    datamat=np.mat(datas)
    labelmat=np.mat(labels)
    #print(np.shape(labelmat))  #维度是(1934,1)
    #print(np.shape(datamat))   #维度是(1934,1024)
    return datamat,labelmat    


#get_data()
def get_data2():

    filenames=listdir("E:/pyhtonworkspace/py3-pratice/book_practice_python/mechinelearning_in_action/chapter02/digits/testDigits" )
    m=len(filenames)  #训练数据集中文件个数(样本数)
    labels=[]
    datas=[]
    for i in range(m):
        L=[]
        filename=filenames[i]
        filenamenum=filename.split('.')[0]
        label=filenamenum.split('_')[0]
        L.append(label)  #对于每一个样本都有一个label标签,把所有的label存在一个列表labels
        labels.append(L)
        data=openfile("E:/pyhtonworkspace/py3-pratice/book_practice_python/mechinelearning_in_action/chapter02/digits/testDigits" +'/'+filename)
        datas.append(data)
    datamat=np.mat(datas)
    labelmat=np.mat(labels)
    #print(np.shape(labelmat))  #维度是(946,1)
    #print(np.shape(datamat))   #维度是(946,1024)
    return datamat,labelmat    

def predict(D,K):
    D_list=sorted(D.items(),key=lambda x:x[0])  #对D按照key(距离)进行排序(升序)  得到的结果是一个列表!!列表中每一个元素都是一个tuple对应着距离和标签
    D1={}
    for i in range(K):
        key=D_list[i][1]
        if key not in D1:
            D1[key]=0
        else:
            D1[key]+=1  #D2是一个字典 key-value 是标签-该标签出现的次数
    D1_list=sorted(D1.items(),key=lambda x:x[1],reverse=True)  #对D1按照value进行排序 ,也就是距离最小的k个训练样本中出现标签最多的那个作为该测试样本的标签
    pred=D1_list[0][0]  #作为最终的预测标签
    return pred






def KNN(test_datamat,test_labelmat,train_datamat,train_labelmat,K=9):
    m1,n=np.shape(test_datamat)  #测试样本数和特征数
    m2=np.shape(train_datamat)[0] #训练样本数
    num_error=0
    for i in range(m1):
        D={}
        for j in range(m2):
            d=0
            for k in range(n):
                d+=(test_datamat[i,k]-train_datamat[j,k])**2
            d=d**0.5
            D[d]=train_labelmat[j,0]   #D字典key-value:测试集合中的一个样本和训练集中每一个样本的距离-和训练集中对应样本的标签
        pred=predict(D,K)
        if pred!=test_labelmat[i,0]:
            num_error+=1
    error=num_error/m1
    return error





if __name__=="__main__":
    train_datamat,train_labelmat=get_data1()
    test_datamat,test_labelmat=get_data2()
    error=KNN(test_datamat,test_labelmat,train_datamat,train_labelmat)
    print("使用KNN算法的错误率为:\n{}".format(error))


明天也要加油鸭~~

今天不开心。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值