最近几年机器学习的热潮冲昏了许多人的头脑,其中就包括我的领导以及我。。。

神说:要有光
于是世界上有了光
我的领导说: 我们需要机器学习的噱头来吓唬一下客户,你来搞吧
于是我便开始了跌跌撞撞的机器学习
我说:我需要机器
领导说有个毛要不要

好了废话不说了,这个系列主要是为了监督自己的学习过程。我本身是一个非常没有自制力的人,为了避免三天打鱼两天晒网,于是把学习过程分享出来,希望我自己能碍于这张老脸坚持下去!!!

作为开始,先从 KNN 开始,据说这个比较简单,我也不知道是不是真的。。。希望不要坑。至于什么有监督学习无监督学习之类的介绍。。。算了,跳过吧。

什么是 KNN

KNN是通过测量不同特征值之间的距离进行分类的一种有监督分类方法。即,训练数据是需要区分正负样本的。

KNN 学习过程

前期准备

因为 KNN 是有监督学习,所以我们需要准备 正负样本 数据,需要准备测试数据,我们通常的做法是把数据集拆分为两部分,其中一部分作为训练集,另外一部分作为测试集。

KNN 原理

knn是通过计算不同特征值之间的距离来进行分类的,总体思路为:计算测试数据与每一个样本数据的距离,如果距离最近的 K 个样本中大部分属于某一个类别,则测试数据就属于这个类别。

knn 中最重要的算法就是距离计算算法,通常我们采用两种距离计算方法,欧氏距离或者曼哈顿距离,公式如下:

代码实现

分类器代码

#!/usr/bin/env python  
# encoding: utf-8  

"""
@version: v1.0 
@author: zhangyw
@site: http://blog.zhangyingwei.com
@software: PyCharm 
@file: knn.py 
@time: 2017/11/17 16:38 
"""
from collections import Counter
import numpy as np

class Knn:
    def __init__(self):
        pass

    def fit(self,x,y):
        self.x = x
        self.y = y
        # self.do_study()

    def predict(self,x,k = 19):
        data_arr = np.array(x)
        items = self.x
        x_arr = np.array(items)
        data_arr = np.tile(data_arr, (x_arr.shape[0], 1))
        diff_arr = x_arr - data_arr # ai-bi
        sqdiff = diff_arr**2 # (ai-bi)平方
        sumdiff = np.sum(sqdiff,axis=1) # 平方和
        result = sumdiff**0.5 # 开方
        # 获取排序后的数据 index(索引) 列表
        args = np.argsort(result)
        # 以下为获取距离最近的前 K 个数据并求出类型最多的数据类型
        values = []
        for index in range(k):
            values.append(self.y[args[index]])
        values_count = Counter(values)
        arg_values = np.argsort(list(values_count.values()))
        # print("values{0},chrose{1}".format(str(values),list(values_count.keys())[arg_values[-1]]))
        return list(values_count.keys())[arg_values[-1]]

测试代码

我们使用 sklearn 提供的鸢尾花数据进行测试。

#!/usr/bin/env python  
# encoding: utf-8  

"""
@version: v1.0 
@author: zhangyw
@site: http://blog.zhangyingwei.com
@software: PyCharm 
@file: test.py 
@time: 2017/11/17 17:00 
"""
from sklearn import datasets
from sklearn.cross_validation import train_test_split
import ml.classify.knn.knn as knn

def test():
    iris = datasets.load_iris()
    data = iris.data
    target = iris.target

    x_train,x_test,y_train,y_test = train_test_split(data,target,test_size=0.2)

    model = knn.Knn()
    model.fit(x_train,y_train)
    succ = 0
    err = 0
    for index,item in enumerate(x_test):
        res = model.predict(item)
        tt = y_test[index]
        if res == tt:
            succ += 1
        else:
            err += 1
            print("实际上是{0},识别为{1}".format(tt,res))
    print(succ/(succ+err))
test()

这里我们打印出识别错误的数据,并在最后打印识别的正确率。结果如下:

0.9666666666666667

多测试几次可以发现正确率基本上维持在 百分之九十以上甚至还会出现 百分之百的情况,说明我们这个分类器还是比较成功的。

接下来我们会使用这个分类器来做一下手写数字识别的 demo。