KNN识别手写数字
一、问题描述
手写数字被存储在EXCEL表格中,行表示一个数字的标签和该数字的像素值,有多少行就有多少个样本。
一共42000个样本
二、KNN
KNN最邻近规则,主要应用领域是对未知事物的识别,即判断未知事物属于哪一类,判断思想是,基于欧几里得定理,判断未知事物的特征和哪一类已知事物的的特征最接近;
K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的权值(weight),如权值与距离成正比(组合函数)。
该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。 该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进。该方法的另一个不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。
K-NN可以说是一种最直接的用来分类未知数据的方法。基本通过下面这张图跟文字说明就可以明白K-NN是干什么的
简单来说,K-NN可以看成:有那么一堆你已经知道分类的数据,然后当一个新数据进入的时候,就开始跟训练数据里的每个点求距离,然后挑离这个训练数据最近的K个点看看这几个点属于什么类型,然后用少数服从多数的原则,给新数据归类。
算法步骤:
step.1---初始化距离为最大值
step.2---计算未知样本和每个训练样本的距离dist
step.3---得到目前K个最临近样本中的最大距离maxdist
step.4---如果dist小于maxdist,则将该训练样本作为K-最近邻样本
step.5---重复步骤2、3、4,直到未知样本和所有训练样本的距离都算完
step.6---统计K-最近邻样本中每个类标号出现的次数
step.7---选择出现频率最大的类标号作为未知样本的类标号
三、分析
从训练集中找到和新数据最接近的k条记录,根据他们的主要分类来决定新数据的类别。
要点:
1.如何判断他们最接近,怎么决定他们的距离(非常决定性能的因素)
欧式距离、余弦定理求相似度……
2.按照k个里最邻近的那个还是类别最多的那个还是权重加权的?
类别最多、权重加权、最近……
手写识别存储文件MNIST train.csv 中,0:label(数字具体是什么),1-784pixels(灰度值)
余弦定理——判断他们之间的相似度。
两个向量,当两个向量夹角比较小的时候,会比较相似,夹角比较大的时候,不相似。
四、实现
# -*- coding: utf-8 -*-
# CopyRight by heibanke import pandas as pd
import numpy as np
import time def normalize(x):
"""
linalg.norm(x), return sum(abs(xi)**2)**0.5
apply_along_axis(func, axis, x),
"""
#归一化——公式的被除数
#这里的1表示,x按照行传递给np.linalg.norm,因为np.linalg.norm没有参数
#所以,默认是求它的二范式,因为是二范式,所以就是平方和
norms = np.apply_along_axis(np.linalg.norm, 1, x) + 1.0e-7
#这里返回的实际上就是求角度的公式中分式下边的值,因为测试机的值不影响,所以只求训练集的
#就可以,所以在nearest_neighbor里边没有求值这一项,因为这里计算了已经
return x / np.expand_dims(norms, -1)#-1表示最后一个轴 #作者自己想到的一个归一化的方法
def normalize2(x):
"""
linalg.norm(x), return sum(abs(xi)**2)**0.5
apply_along_axis(func, axis, x),
"""
norms = np.apply_along_axis(np.mean, 1, x) + 1.0e-7
return x - np.expand_dims(norms, -1) def nearest_neighbor(norm_func,train_x, train_y, test_x):
train_x = norm_func(train_x)
test_x = norm_func(test_x) # cosine
#test_x就是测试数据,train_x是训练数据,分别相当于j,i
corr = np.dot(test_x, np.transpose(train_x))
argmax = np.argmax(corr, axis=1)
#然后找一个最大值作为预测值
preds = train_y[argmax] #上边如果采用for循环的形式会更好看一些,但是运行速度会慢一些。
#采用矩阵的形式会快
return preds def validate(preds, test_y):
count = len(preds)
#对所有正确的进行sum()求和
correct = (preds == test_y).sum()
#然后对争取的的总和除以数据总和
return float(correct) / count if __name__=='__main__':
TRAIN_NUM = 2200
TEST_NUM = 4200
# Read data 42000
data = pd.read_csv('train.csv')
train_data = data.values[0:TRAIN_NUM,1:]
train_label = data.values[0:TRAIN_NUM,0]
test_data = data.values[TRAIN_NUM:TEST_NUM,1:]
test_label = data.values[TRAIN_NUM:TEST_NUM,0]
#这里采用三种方式,一种是公式型的归一化,第二种是减去均值的归一化,第三种没有归一化,直接就是两个向量相关
norm_funcs = [normalize,normalize2,lambda x:x]
for norm_f in norm_funcs:
t = time.time() preds = nearest_neighbor(norm_f,train_data, train_label, test_data)
#acc求出来的就是准确率
acc = validate(preds, test_label)
print("%s Validation Accuracy: %f, %.2fs" % (norm_f.__name__,acc, time.time() - t))
这是黑板课老师给的代码,他提出了三种归一化方法。再次我提出异议,最好的归一化方法1,实际上就是公式的一部分,而归一化2和3实际上都不对,没有正确运用公式,因为在nearest_neighbor函数中使用的并不是完整的公式,没有除以他们的平方和,加上归一化1,才正好拼出来公式的形态。所以,正确做法只有一个,那就归一化1,甚至不应该叫做归一化,而是正常的正确的一个阶梯步骤。
下边用库函数的knn和svm试一下:
# -*- coding: utf-8 -*-
# CopyRight by heibanke import pandas as pd
from sklearn.decomposition import PCA
from sklearn.neighbors import KNeighborsClassifier
from sklearn import svm
import time if __name__=='__main__':
# maximum num is 42000
TRAIN_NUM = 22000
TEST_NUM = 42000
"""
train_data: 训练数据
train_label: 训练数据的正确输出
test_data: 测试数据
test_label: 测试数据的正确输出
"""
data = pd.read_csv('train.csv')
train_data = data.values[0:TRAIN_NUM,1:]
train_label = data.values[0:TRAIN_NUM,0]
test_data = data.values[TRAIN_NUM:TEST_NUM,1:]
test_label = data.values[TRAIN_NUM:TEST_NUM,0] t = time.time()
# PCA, principal components analysis
# http://blog.jobbole.com/86905/
# http://ufldl.stanford.edu/wiki/index.php/%E4%B8%BB%E6%88%90%E5%88%86%E5%88%86%E6%9E%90
pca = PCA(n_components=0.8)
train_x = pca.fit_transform(train_data)
test_x = pca.transform(test_data) #knn regression
neighbor = KNeighborsClassifier(n_neighbors=4)
neighbor.fit(train_x, train_label)
preds = neighbor.predict(test_x) acc = float((preds == test_label).sum())/len(test_x)
print("KNN Validation Accuracy: %f, %.2fs" % (acc, time.time() - t)) # 22000, 96.7% #svm(Support Vector Machine) regression
# 统计学习方法
# PRML t = time.time()
pca = PCA(n_components=0.8,whiten=True)
train_x = pca.fit_transform(train_data)
test_x = pca.transform(test_data) svc = svm.SVC(kernel='rbf',C=10)
svc.fit(train_x, train_label)
preds = svc.predict(test_x) acc = float((preds == test_label).sum())/len(test_x)
print("SVM Validation Accuracy: %f, %.2fs" % (acc, time.time() - t)) # 22000, 97.8%
参考:http://www.cnblogs.com/sunshinewang/p/6893503.html
KNN识别手写数字的更多相关文章
- KNN实现手写数字识别
KNN实现手写数字识别 博客上显示这个没有Jupyter的好看,想看Jupyter Notebook的请戳KNN实现手写数字识别.ipynb 1 - 导入模块 import numpy as np i ...
- KNN 算法-实战篇-如何识别手写数字
公号:码农充电站pro 主页:https://codeshellme.github.io 上篇文章介绍了KNN 算法的原理,今天来介绍如何使用KNN 算法识别手写数字? 1,手写数字数据集 手写数字数 ...
- 使用神经网络来识别手写数字【译】(三)- 用Python代码实现
实现我们分类数字的网络 好,让我们使用随机梯度下降和 MNIST训练数据来写一个程序来学习怎样识别手写数字. 我们用Python (2.7) 来实现.只有 74 行代码!我们需要的第一个东西是 MNI ...
- 学习笔记TF024:TensorFlow实现Softmax Regression(回归)识别手写数字
TensorFlow实现Softmax Regression(回归)识别手写数字.MNIST(Mixed National Institute of Standards and Technology ...
- TensorFlow实战之Softmax Regression识别手写数字
关于本文说明,本人原博客地址位于http://blog.csdn.net/qq_37608890,本文来自笔者于2018年02月21日 23:10:04所撰写内容(http://blog.c ...
- 一文全解:利用谷歌深度学习框架Tensorflow识别手写数字图片(初学者篇)
笔记整理者:王小草 笔记整理时间2017年2月24日 原文地址 http://blog.csdn.net/sinat_33761963/article/details/56837466?fps=1&a ...
- python手写神经网络实现识别手写数字
写在开头:这个实验和matlab手写神经网络实现识别手写数字一样. 实验说明 一直想自己写一个神经网络来实现手写数字的识别,而不是套用别人的框架.恰巧前几天,有幸从同学那拿到5000张已经贴好标签的手 ...
- 3 TensorFlow入门之识别手写数字
------------------------------------ 写在开头:此文参照莫烦python教程(墙裂推荐!!!) ---------------------------------- ...
- 用BP人工神经网络识别手写数字
http://wenku.baidu.com/link?url=HQ-5tZCXBQ3uwPZQECHkMCtursKIpglboBHq416N-q2WZupkNNH3Gv4vtEHyPULezDb5 ...
随机推荐
- Git密钥生成步骤SSH Key
顺便推荐下自己的网站: 一个php后台极速开发框架 https://www.lotusadmin.top/ 一个有趣的网站 https://www.waytomilky.com/ Git是分布式的代码 ...
- IO测试工具之fio详解(转)
http://www.cnblogs.com/raykuan/p/6914748.html 目前主流的第三方IO测试工具有fio.iometer和Orion,这三种工具各有千秋. fio在Linux系 ...
- 专访TK教主于旸:原来那些搞安全的说的都是真的(图灵访谈)
引用:http://www.ituring.com.cn/article/196609 于旸,网名“tombkeeper”,在国内黑客界被尊称为“TK教主”,现任腾讯玄武实验室总监.于旸从事信息安全研 ...
- 在ASP.NET应用程序中使用身份模拟(Impersonation)
摘要 缺省情况下,ASP.NET应用程序以本机的ASPNET帐号运行,该帐号属于普通用户组,权限受到一定的限制,以保障ASP.NET应用程序运行的安全.但是有时需要某个ASP.NET应用程序或者程 ...
- linux 信号处理 三 (信号集的使用)
sigprocmask系统调用 使用条件: 1.有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延时一段时间去调用信号处理函数.这种情况是通过阻塞信号实现的. 2. ...
- js jquery 设置cookie
转自http://yaoqianglilan.blog.163.com/blog/static/70978316201091810435251/ 本人亲测setcookie() getcookie() ...
- jmeter 参数化方法
1.csv 看异步图书 JMeter实战60页
- 关于attr("checked")的输出
同样的一段代码,在不同的文件输出不同的答案,好神奇. console.log($("#never").attr("checked")); 一个输出checked ...
- pyplot 绘图与可视化
1. 基本使用 #!/usr/bin/env python # coding=utf-8 import matplotlib.pyplot as plt from numpy.random impor ...
- 配置Samba(CIFS)
试验环境:一台CentOS 7.0的虚拟机,一台Windows 的普通台式机. 注意:网络一定能够ping通 关闭SeLinux # setenforce 0 # getenforce 关闭防火墙 # ...