一、概述
1.1、什么是knn算法
1、定义
K最近邻(k-Nearest Neighbor,KNN)分类算法 可以说是最简单的机器学习算法了。它采用测量不同特征值之间的距离方法进行分类。它的思想很简单:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
2、KNN三要素
K值的选择 :K值的确定与样本最终的判定结果有很大的关系;K 值太小会使得 KNN 算法容易过拟合。反之,太大则会欠拟合。因此,一般采用交叉验证的方式选取 K 值。距离的度量 :通过什么样的距离理论确定最近邻的样本数据。一般使用欧氏距离(欧几里得距离);决策规则 :以什么样的决策规则来确定最终的输出结果。在分类预测时,一般采用“多数表决法”或“加权多数表决法”;而在做回归预测时,一般采用“平均值法”或“加权平均值法”,这也是KNN做分类与回归最主要的区别。这里所说的加权一般情况下采用权重和距离成反比的方式来计算。
3、举例
训练样本集中包含一系列数据,这个数据包括样本空间位置(特征)和分类信息(即目标变量,属于红色三角形还是蓝色正方形),要对中心的绿色数据的分类。运用kNN算法思想,距离最近的k个样本的分类来代表测试数据的分类,那么: 1、当k=3时 ,距离最近的3个样本在实线内,具有2个红色三角和1个蓝色正方形,因此将它归为红色三角。 2、当k=5时 ,距离最近的5个样本在虚线内,具有2个红色三角和3个蓝色正方形,因此将它归为蓝色正方形。
1.2、代码实战
1、knn.py
knn_classifier :1、使用欧几里得法算出离测试数据x离X_train中每一个数据点的距离;2、取k个距离最近的y_train值坐标;3、统计k个y_train值类型的统计结果,统计概率高的类型就是最终的结果。import numpy as np
import matplotlib. pyplot as plt
from collections import Counter
from math import sqrt
def knn_classifier ( X_train, y_train, x, k) :
assert k >= 1 and k <= X_train. shape[ 0 ] , 'KNN算法的k值必须合法!!!'
assert X_train. shape[ 0 ] == y_train. shape[ 0 ] , 'X_train训练数据集和y_train训练数据集的行数必须一样'
assert X_train. shape[ 1 ] == x. shape[ 1 ] , '测试数据x的列数必须和X_train数据集的列数保持一致'
'''
使用欧几里得法算出x到X_train所有点的举例,取最近k个y_train的值
'''
distances = [ sqrt( np. sum ( ( x_train - x) ** 2 ) ) for x_train in X_train]
nearest = np. argsort( distances)
nearK_y = [ y_train[ i] for i in nearest[ : k] ]
votes = Counter( nearK_y)
predict = votes. most_common( 1 ) [ 0 ] [ 0 ]
return predict
2、main.py
from knn import knn_classifier
import numpy as np
import matplotlib. pyplot as plt
'''
1、训练数据集:X_train(特征数据集)和y_train(标记向量)
2、测试数据集:x
'''
X_list = [ [ 3 , 1 ] ,
[ 3 , 2 ] ,
[ 2 , 3 ] ,
[ 2 , 1 ] ,
[ 1 , 2 ] ,
[ 4 , 4 ] ,
[ 5 , 3 ] ,
[ 6 , 2 ] ,
[ 7 , 4 ] ,
[ 5 , 6 ] ]
y_list = [ 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 ]
X_train = np. array( X_list)
y_train = np. array( y_list)
x = np. array( [ [ 6.5 , 7.1 ] ] )
'''
1、X_train数据集中对应y_train值:为0的标记为绿色,良性肿瘤;为1标记为红色,恶性肿瘤
2、x测试数据集标记为蓝色
'''
plt. scatter( x[ 0 , 0 ] , x[ 0 , 1 ] , color = "blue" )
plt. scatter( X_train[ y_train == 0 , 0 ] , X_train[ y_train == 0 , 1 ] , color= "green" )
plt. scatter( X_train[ y_train == 1 , 0 ] , X_train[ y_train == 1 , 1 ] , color= "red" )
plt. show( )
'''
使用knn算法判断测试数据集的分类:0(良性肿瘤)或者1(恶性肿瘤)
'''
knn_predict = knn_classifier( X_train, y_train, x, 6 )
print ( knn_predict)
3、测试结果
测试knn算法:结果为1,恶性肿瘤
1.3、使用sklearn里的knn算法
1、机器学习过程
fit:训练数据集通过机器学习算法fit(建模)一个模型,输入样例通过模型预测出最后的输出结果;但是knn算法比较特殊,KNN是一个不需要训练过程的算法,可以认为KNN算法的训练数据集就是模型本身。
2、代码实战
from sklearn. neighbors import KNeighborsClassifier
from knn import knn_classifier
import numpy as np
import matplotlib. pyplot as plt
'''
1、训练数据集:X_train(特征数据集)和y_train(标记向量)
2、测试数据集:x
'''
X_list = [ [ 3 , 1 ] ,
[ 3 , 2 ] ,
[ 2 , 3 ] ,
[ 2 , 1 ] ,
[ 1 , 2 ] ,
[ 4 , 4 ] ,
[ 5 , 3 ] ,
[ 6 , 2 ] ,
[ 7 , 4 ] ,
[ 5 , 6 ] ]
y_list = [ 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 ]
X_train = np. array( X_list)
y_train = np. array( y_list)
x = np. array( [ [ 6.5 , 7.1 ] ] )
'''
1、X_train数据集中对应y_train值:为0的标记为绿色,良性肿瘤;为1标记为红色,恶性肿瘤
2、x测试数据集标记为蓝色
'''
plt. scatter( x[ 0 , 0 ] , x[ 0 , 1 ] , color = "blue" )
plt. scatter( X_train[ y_train == 0 , 0 ] , X_train[ y_train == 0 , 1 ] , color= "green" )
plt. scatter( X_train[ y_train == 1 , 0 ] , X_train[ y_train == 1 , 1 ] , color= "red" )
plt. show( )
'''
使用sklearn的knn算法处理上面的训练数据:
1、初始化KNeighborsClassifier类,传入k值为6
2、fit建模
3、predict通过模型预测出最终结果
4、输出结果值
'''
kneighbordclassifier = KNeighborsClassifier( 6 )
kneighbordclassifier. fit( X_train, y_train)
predict_y = kneighbordclassifier. predict( x)
print ( "sklearn的knn算法输出结果:predict_y = " , predict_y)
二、KNN算法优化
2.1、修改knn.py
import numpy as np
import matplotlib. pyplot as plt
from collections import Counter
from math import sqrt
'''
模仿sklearn的knn算法:
1、初始化KnnClassifier类:指明k值
2、fir建模
3、predict预测出结果
'''
class KnnClassifier :
def __init__ ( self, k) :
'''
初始化KnnClassifier
:param k:knn算法中的k值
'''
assert k >= 1 , '请输入有效k值'
self. k = k
self. X_train = None
self. y_train = None
def fit ( self, X_train, y_train) :
'''
knn算法建模fit
:param X_train:训练特征数据集
:param y_train:训练标记向量(label)
:return: 返回KnnClassifier类本身
'''
assert X_train. shape[ 0 ] == y_train. shape[ 0 ] , 'X_train训练数据集和y_train训练数据集的行数必须一样'
self. X_train = X_train
self. y_train = y_train
return self
def predict ( self, X_predict) :
'''
预测测试数据集
:param X_predict: 测试数据集,必须是一个矩阵格式
:return:返回预测结果集y_predicts
'''
assert self. X_train is not None and self. y_train is not None , 'train data must be fit before predict'
assert self. X_train. shape[ 1 ] == X_predict. shape[ 1 ] , '测试数据集X_predict的列数必须和X_train数据集的列数保持一致'
assert X_predict. ndim >= 2 , '测试数据集必须是矩阵格式'
y_predicts = [ self. _predict( x) for x in X_predict]
return np. array( y_predicts)
def _predict ( self, x) :
'''
私有方法:knn算法的主要实现逻辑
:param x:测试数据
:return:返回单个预测结果predict
'''
distances = [ sqrt( np. sum ( ( x_train - x) ** 2 ) ) for x_train in self. X_train]
nearest = np. argsort( distances)
nearK_y = [ self. y_train[ i] for i in nearest[ : self. k] ]
votes = Counter( nearK_y)
predict = votes. most_common( 1 ) [ 0 ] [ 0 ]
return predict
2.2、修改main.py的调用逻辑
from knn import KnnClassifier
import numpy as np
import matplotlib. pyplot as plt
'''
1、训练数据集:X_train(特征数据集)和y_train(标记向量)
2、测试数据集:x
'''
X_list = [ [ 3 , 1 ] ,
[ 3 , 2 ] ,
[ 2 , 3 ] ,
[ 2 , 1 ] ,
[ 1 , 2 ] ,
[ 4 , 4 ] ,
[ 5 , 3 ] ,
[ 6 , 2 ] ,
[ 7 , 4 ] ,
[ 5 , 6 ] ]
y_list = [ 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 ]
X_train = np. array( X_list)
y_train = np. array( y_list)
x = np. array( [ [ 6.5 , 7.1 ] ] )
'''
1、X_train数据集中对应y_train值:为0的标记为绿色,良性肿瘤;为1标记为红色,恶性肿瘤
2、x测试数据集标记为蓝色
'''
plt. scatter( x[ 0 , 0 ] , x[ 0 , 1 ] , color = "blue" )
plt. scatter( X_train[ y_train == 0 , 0 ] , X_train[ y_train == 0 , 1 ] , color= "green" )
plt. scatter( X_train[ y_train == 1 , 0 ] , X_train[ y_train == 1 , 1 ] , color= "red" )
plt. show( )
'''
使用knn算法判断测试数据集的分类:0(良性肿瘤)或者1(恶性肿瘤)
'''
knn_classifier = KnnClassifier( 6 )
knn_classifier. fit( X_train, y_train)
y_predicts = knn_classifier. predict( x)
print ( "自定义knn算法预测结果:y_predicts = " + str ( y_predicts) )
2.3、测试结果