机器学习之K-近邻算法
什么是K-近邻算法?
答:官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居), 这K个实例的多数属于某个类,就把该输入实例分类到这个类中。
也就是说这个算法是用来分类的。
API:sklearn.neighbors.KNeighborsClassifier
来个例子:
电影可以按照题材分类,每个题材又是如何定义的呢?那么假如两种类型的电影,动作片和爱情片。动作片有哪些公共的特征?那么爱情片又存在哪些明显的差别呢?我们发现动作片中打斗镜头的次数较多,而爱情片中接吻镜头相对更多。当然动作片中也有一些接吻镜头,爱情片中也会有一些打斗镜头。所以不能单纯通过是否存在打斗镜头或者接吻镜头来判断影片的类别。那么现在我们有6部影片已经明确了类别,也有打斗镜头和接吻镜头的次数,还有一部电影类型未知。
现在有打斗镜头和接吻镜头两个特征可以帮助我们判断最后一部电影属于哪个类型。我们使用K-领近算法来算一下这个未知的电影与其他电影的距离,距离哪部电影最近,那么这个未知电影就和该电影类型相同。
通过结果,可以看出,未知电影与第二部电影《He's not Really into dues》的距离为18.7最近,那么可以推断出未知电影是属于爱情类。
问题来了,这个距离怎么算的呢?其实。这个距离是欧氏距离。其数学原理如下:√(x1-x2)²+(y1-y2)²
例如:输入变量有四个特征,例如(1,3,5,2)和(7,6,9,4)之间的欧式距离计算为:√(1-7)²+(3-6)²+(5-9)²+(2-4)² = 65
问题:如果不同特征之间的度量不一样会不会影响结果呢?比如上面的例子中如果打斗的镜头是几十个或者几百个,但是接吻的镜头动辄就几万个、十几万个。这样计算的欧氏距离中打斗镜头这个特征就会被忽略掉。
因此,如果遇到上述情况,那么就得对特征进行标准化。至于如何标准化,前面已经介绍过,这里不再赘述。
上一个代码示例:
使用最著名的”鸢尾“数据集,该数据集曾经被Fisher用在经典论文中,目前作为教科书般的数据样本预存在Scikit-learn的工具包中。
首先,查看以下该数据集的描述:
1 from sklearn.datasets import load_iris 2 # 使用加载器读取数据并且存入变量iris 3 iris = load_iris() 4 5 # 查验数据规模 6 iris.data.shape 7 8 # 查看数据说明 9 print(iris.DESCR)
通过上述代码对数据的查验以及数据本身的描述,我们了解到Iris数据集共有150朵鸢尾数据样本,并且均匀分布在3个不同的亚种;每个数据样本有总共4个不同的关于花瓣、花萼的形状特征所描述。由于没有制定的测试集合,因此按照惯例,我们需要对数据进行随即分割,25%的样本用于测试,其余75%的样本用于模型的训练。
完整代码:
1 from sklearn.datasets import load_iris 2 from sklearn.model_selection import train_test_split 3 from sklearn.preprocessing import StandardScaler 4 from sklearn.neighbors import KNeighborsClassifier 5 6 def knniris(): 7 """ 8 鸢尾花分类 9 :return: None 10 """ 11 12 # 数据集获取和分割 13 lr = load_iris() 14 15 #标准化 16 std = StandardScaler() 17 x = std.fit_transform(lr.data) 18 19 x_train, x_test, y_train, y_test = train_test_split(x, lr.target, test_size=0.25) 20 21 # estimator流程 22 knn = KNeighborsClassifier() 23 24 # 得出模型 25 knn.fit(x_train,y_train) 26 27 # 进行预测或者得出精度 28 y_predict = knn.predict(x_test) 29 print(y_predict) 30 31 print('准确度:',knn.score(x_test,y_test)) 32 33 return None 34 35 if __name__ == "__main__": 36 knniris()
94%的准确度,还是阔以的。