学习笔记——Kaggle_Digit Recognizer (KNN算法 Python实现)

本文是个人学习笔记,该篇主要学习KNN算法理论和应用范围,并应用KNN算法解决Kaggle入门级Digit Recognizer,也是个人入坑ML和Kaggle的开端,希望能够有始有终。

  • KNN算法
  • 距离计算算法
  • Python 代码

KNN算法

K最近邻分类算法(K-NearestNeighbor),由Cover和Hart在1968年提出,是最简单的机器学习算法之一,主要被应用于文本分类、相似推荐

基本原理:
从训练样本集中选择k个与测试样本“距离”最近的样本,该k个样本中出现频率最高的类别即作为测试样本的类别,其中参数k的取值通常不大于20。

实现流程:
算法目标:未知类别样本集分类;
输入信息:待分类目标样本集和已分类学习样本集;
输出结果:已分类目标样本集;

算法步骤:
(a) 确定k值,即每个待分类样本要到它k个已分类样本邻居;
(b) 根据距离度量公式(如:欧氏距离),确定待分类样本集和已分类样本集中,距离该样本点最近的k个样本;
(c) 统计该k个邻居样本中,各类别的数量。最终将待分类样本点定义为数量最多的类别;

优缺点:
算法简单,易于实现,不需要参数估计,不需要事先训练;但由于不进行事先训练,而在输入待分类样本集时才开始,导致KNN计算量特别大;同时训练样本必须存储在本地,消耗大量内存。


距离计算算法

在数据分析和数据挖掘中,个体间的“距离”实际是对个体间差异大小的空间衡量,距离越远说明个体间的差异越大,然后根据实际差异情况进行相关性分析

假设:X个体和Y个体都包含了N个维的特征,即X=( x1x2x3xnY=y1y2y3yn

欧几里得距离(欧式距离):
欧式距离是最常用的距离度量,计算多维空间中各点之间的绝对距离。因为距离计算是基于各维度特征的绝对数值,所以需要保证各维度指标在相同的刻度级别。

公式:

dist(X,Y)=i=1n(xiyi)2

马哈拉诺比斯距离(马氏距离):
马氏距离是欧式距离的改进版本,即基于各指标维度进行标准化后再使用欧氏距离,规避了指标度量的差异;


曼哈顿距离:
曼哈顿距离来源于城市区块距离,是将多个维度上的距离进行求和后的结果;

公式:

dist(X,Y)=i=1n|xiyi|


切比雪夫距离:
切比雪夫距离起源于国际象棋中国王的走法,国际象棋国王每次只能往周围的8格中走一步,那么如果要从棋盘中A格 x1y1 走到B格 x2y2 最少需要走几步。

公式:

dist(X,Y)=limp(i=1n|xiyi|p)1/p


明可夫斯基距离(明氏距离):
明氏距离是欧式距离的推广版本,是多个距离度量公式的概括性表述。

公式:

dist(X,Y)=(i=1n|xiyi|p)1/p

当p值为1时,即为曼哈顿距离,p值为2时,即为欧式距离,而当p趋向于无穷时,即为切比雪夫距离;


Python 代码

Python 代码1:

import pandas as pd
import numpy as np
import time
import operator

def data_load():

    # 利用pandas读取csv文件内容
    train_ttl=pd.read_csv('/Users/Sweet-home/PycharmProjects/Kaggle/reco data/train.csv')
    train_label=pd.DataFrame(train_ttl['label'])
    train_data=pd.DataFrame(train_ttl.ix[:,1:])
    test_data=pd.read_csv('/Users/Sweet-home/PycharmProjects/Kaggle/reco data/test.csv')

    # dataframe归整化
    train_data[train_data!=0]=1
    test_data[test_data!=0]=1

    return train_data,train_label,test_data


    #inX:1*n  dataSet:m*n labels:m*1
def classify(inX, dataSet, labels, k): #确定类别

    diffmats = (dataSet-inX)**2#计算KNN 欧式距离
    sumdiffs=diffmats.sum(axis=1)
    distances=sumdiffs**0.5

    sortedDistIndicies = distances.argsort()#根据距离排序

    classcount={}
    for i in range(k):#统计各标签值count
        votelabel = labels.ix[sortedDistIndicies[i],0]
        classcount[votelabel] = classcount.get(votelabel,0) + 1

    # 根据字典值降序排序
    sortedClassCount = sorted(classcount.items(), key=operator.itemgetter(1), reverse=True)
    # 返回最相似label值
    return sortedClassCount[0][0]


if __name__=='__main__':
    start = time.clock()
    traindata,trainlabel,testdata=data_load()#加载raw data

    m,n=testdata.shape
    result_labels=[]
    result={}

    for i in range(m):#对test样本一次确定其类别
        result_label=classify(testdata.ix[i],traindata,trainlabel,8)
        result_labels.append(result_label)

    #将结果转化成Dataframe结构
    ImageId=np.arange(m)+1
    result['Label']=result_labels
    result_frame=pd.DataFrame(result,index=ImageId)

    #导出结果
    result_frame.to_csv('/Users/Sweet-home/PycharmProjects/Kaggle/reco data/result.csv')
    end = time.clock()
    print('总耗时:', end - start)

Python 代码2:

import pandas as pd
import numpy as np
import time
from sklearn.neighbors import KNeighborsClassifier

def data_load():

    # 利用pandas读取csv文件内容
    train_ttl=pd.read_csv('D:\Program files\JetBrains\digit recognizer\Raw data\\train.csv')
    train_label=pd.DataFrame(train_ttl['label'])
    train_data=pd.DataFrame(train_ttl.ix[:,1:])
    test_data=pd.read_csv('D:\Program files\JetBrains\digit recognizer\Raw data\\test.csv')

    # dataframe归整化
    test_data[test_data!=0]=1

    # train_data[train_data!=0]=1
    m,n=train_data.shape#这里似乎因为dataframe太大,用bool判断更改时总会异常跳出,所以选择循环更改
    for i in range(m):
        for j in range(n):
            if train_data.ix[i,j]!=0:
                train_data.ix[i,j]=1

    return train_data,train_label,test_data

#利用Python Sklearn包,进行test样本集分类判别
def knn_classify(traindata,trainlabel,testdata):

    knn_clf = KNeighborsClassifier(n_neighbors=5, algorithm='kd_tree', weights='distance', p=3)#设置参数
    knn_clf.fit(traindata,trainlabel.values.ravel())#训练Train样本
    knn_result=knn_clf.predict(testdata)#预测Test样本

    return knn_result

if __name__=='__main__':
    start = time.clock()
    traindata,trainlabel,testdata=data_load()#加载raw data

    m,n=testdata.shape
    result_labels=knn_classify(traindata,trainlabel,testdata)

    #将结果转化成Dataframe结构
    result={}
    ImageId=np.arange(m)+1
    result['Label']=result_labels
    result_frame=pd.DataFrame(result,index=ImageId)

    #导出结果
    result_frame.to_csv('D:\Program files\JetBrains\digit recognizer\Raw data\\result.csv')
    end = time.clock()
    print('总耗时:', end - start)#接近5小时

你可能感兴趣的:(python学习笔记)