链接
sklearn函数实现
了解个knn是干什么,算法过程就管了,直接用sklearn库
from sklearn.neighbors import KNeightborsClassifier as KNN
from sklearn import datasets
kn = KNN() # 申明对象
iris = datasets.load_iris() # 导入数据,这里是导入CSV库里面自带的"iris.csv"文件
knn.fit(iris.data,iris.target) # 生成KNN模型
predicit = kn.predict([[2,3,3,2]]) # 预测
print(predicit)
knn
如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
找最近的样本,把未标签的分到多数类区
思路,过程
这是按下面代码的过程
- 首先有一堆数据,要读入;
- 把这些数组分为训练集和测试集,把训练集当成模板,在之后测试中把测试集中数据放入到模板中,得出预算值,接下来就看预算值与实际数值是否相同了;
- 有个计算两个样例之间的距离,用欧氏距离公式:
∑ ( t e s t d a t a − t r a i n d a t a ) 2 \sqrt{\sum(testdata-traindata)^2} ∑(testdata−traindata)2 - 对一个实例找到离他最近的K个实例,把所有的距离都算出来,排个序,就能找到最近的;
- 在距离最近的那几个实例中,把未标签的实例划分到多数那一类,就是“随大流”
- 接着把选出的测试集测试一遍,观察预测值与实际值,可以的话可以加个准确率
python代码
下面这个代码,用的库少嘞很,过程也比较详细,就是,额,过程,,看完都能了解Knn个大概,
import csv
import random
import math
import operator
#radio,按比例将数据划分为训练集和测试集
def loadDataSet(filename, split, trainSet=[], testSet=[]):
with open(filename, 'rt') as f:
lines = csv.reader(f)
dataset = list(lines)
next(dataset) #读取首行
for x in range(len(dataset)):
if(random.random() < split):
trainSet.append(dataset[x])
else:
testSet.append(dataset[x])
#计算两个样例之间的距离(欧式距离)
#length,表示数据的维度
def evaluateDistance(instance1, instance2, length):
distance = 0
for i in range(length):
distance += pow((eval(instance2[i])-eval(instance1[i])),2)
return math.sqrt(distance)
#找最近的K个实例
def getNeighbors(trainSet, testing_Set, k):
distance = []
length = len(testing_Set)-1 #最后一个数为标签,所以要去掉,计算有效数据
for i in range(len(train_Set)):
dist = evaluateDistance(trainSet[i], testing_Set, length)
distance.append((trainSet[i],dist)) #将每个训练实例与对应的测试实例放到一块
distance.sort(key=operator.itemgetter(1),reverse=False) #从小到大排序
neighbors = [] #存储一个实例最近的几个实例
for i in range(k):
neighbors.append(distance[i][0])
return neighbors
#”随大流“,以大多数类别为基准当作标签
def getResponse(neighbors):
classvotes = {} #定义个字典,用来记类别出现次数,以找到出现最多的类别
for i in range(len(neighbors)):
response = neighbors[i][-1]
if response in classvotes:
classvotes[response] += 1
else:
classvotes[response] = 1
sortedVotes = sorted(classvotes.items(), key=operator.itemgetter(1),reverse=True) #operator.itemgetter()函数是指定位置的域
return sortedVotes[0][0] #返回的是标签
#计算测试集精确度
def getAccuracy(testSet,predict):
correct = 0
for i in range(len(testSet)):
if(testSet[i][-1] == predict[i][-1]):
correct += 1
return (1.0*correct/len(testSet))*100
if __name__ == '__main__':
trainSet = []
testSet = []
radio = 0.8
with open('iris.csv','r') as csvfile:
lines = csv.reader(csvfile)
next(lines)
dataset = list(lines)
for x in range(len(dataset)):
if(random.random() < radio):
trainSet.append(dataset[x])
else:
testSet.append(dataset[x])
# loadDataSet('iris.csv',radio,trainSet,testSet)
predictions = []
k = 3 #选取前K个最近的实例
for i in range(len(testSet)):
neighbors = getNeighbors(trainSet,testSet[i],k) #找邻近数据函数
result = getResponse(neighbors) #预测标签函数
predictions.append(result)
print(">predicted={},actual={}".format(result,testSet[i][-1]))
ac = getAccuracy(testSet,predictions) #准确率函数
print("Accuracy:{:.2f}%".format(ac))
iris.csv文件来自于CSV库自带的,共有150个数据
//代码可直接运行,过程是很详细;
代码中用numpy存入数据的话操作会更简单;
这个代码运算量较大;
数值不稳定;