书上的代码看不懂,自己写了一个,就是太麻烦,书上才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算法识别手写数字**********************
看完书之后按照自己的理解实现了一下,可是为什么我运行不出来啊,是我的电脑有问题,嗯,我逻辑是对的~~~
是电脑配置太低了嘛,,,
接下来直接附上代码啦~~
扫描二维码关注公众号,回复:
474127 查看本文章
# -*- 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))
明天也要加油鸭~~
今天不开心。