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 ...
随机推荐
- <<精通正在表达式>> 书评
IT产业新技术日新月异,令人目不暇给,然而在这其中,真正称得上伟大东西的却寥寥无几.1998年,被誉为“软件世界的爱迪生”,发明了BSD. TCP/IP.csh.vi和NFS的SUN首席科学家Bil ...
- 设计模式初学者笔记:Abstract Factory模式
首先啰嗦下创建迷宫所用的Room类.这个类并不直接保存Room四周的构造,而是通过MapSite* _sides[4]这个私有数组成员指向Room四周的构造.那么什么时候将四周构造直接放在Room中, ...
- 手动安装Android Support Library(23.0.1)
在搭建React-Native开发环境的时候,使用Android Sdk Manager无法找到Android Support Library这一项. 所以google了一下,找到了解决办法. 访问A ...
- Docker 1
1.Docker安装 下载地址:https://download.docker.com/mac/edge/Docker.dmg 验证Docker信息 docker --version docker-c ...
- scrapy 抓取拉勾网数据
其实很简单,却因为一些小问题,折腾不少时间,简要记录一下,以备后需. >> scrapy startproject lagou >> cd lagou >> scr ...
- zabbix批量添加SNMP监听H3C端口检测以及流量图
由于之前网络设备不是很多,监控网络设备接口就直接使用模版中的item来实现了,可是现在公司上线了一大批网络设备,如果要每个网络设备都做模板,添加item......那就该废了,于是迫于压力今天来测试使 ...
- 怎样使用 css 的@media print控制打印
怎样使用 css 的@media print控制打印? <HTML> <HEAD> <TITLE> New Document </TITLE> < ...
- word2vec 的理解
1.CBOW 模型 CBOW模型包括输入层.投影层.输出层.模型是根据上下文来预测当前词,由输入层到投影层的示意图如下: 这里是对输入层的4个上下文词向量求和得到的当前词向量,实际应用中,上下文窗口大 ...
- [Python] 拉格朗日插值
#-*— coding:utf-8 -*- #Program 0.3 Lagrange Interpolation import matplotlib.pyplot as plt import num ...
- HTML|CSS总结与补充
知识内容: 1.HTML总结 2.CSS总结 一.HTML总结 详细内容见:http://www.cnblogs.com/wyb666/p/8733699.html 1.HTML介绍及前端入门 (1) ...