K-近邻算法(KNN)概述
最简单最初级的分类器是将全部的训练数据所对应的类别都记录下来,当测试对象的属性和某个训练对象的属性完全匹配时,便可以对其进行分类。但是怎么可能所有测试对象都会找到与之完全匹配的训练对象呢,其次就是存在一个测试对象同时与多个训练对象匹配,导致一个训练对象被分到了多个类的问题,基于这些问题呢,就产生了KNN。
KNN是通过测量不同特征值之间的距离进行分类。它的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别,其中K通常是不大于20的整数。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
下面通过一个简单的例子说明一下:如下图,绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。
由此也说明了KNN算法的结果很大程度取决于K的选择。
在KNN中,通过计算对象间距离来作为各个对象之间的非相似性指标,避免了对象之间的匹配问题,在这里距离一般使用欧氏距离或曼哈顿距离:
同时,KNN通过依据k个对象中占优的类别进行决策,而不是单一的对象类别决策。这两点就是KNN算法的优势。
接下来对KNN算法的思想总结一下:就是在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较,找到训练集中与之最为相似的前K个数据,则该测试数据对应的类别就是K个数据中出现次数最多的那个分类,其算法的描述为:
1)计算测试数据与各个训练数据之间的距离;
2)按照距离的递增关系进行排序;
3)选取距离最小的K个点;
4)确定前K个点所在类别的出现频率;
5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。
分类器构造函数
KNeighborsClassifier(n_neighbors=5, weights='uniform',
algorithm='auto', leaf_size=30,
p=2, metric='minkowski',
metric_params=None, n_jobs=1, **kwargs)
n_neighbors: 默认值为5,表示查询k个最近邻的数目
algorithm: {‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’},指定用于计算最近邻的算法,auto表示试图采用最适合的算法计算最近邻
leaf_size: 传递给‘ball_tree’或‘kd_tree’的叶子大小
metric: 用于树的距离度量。默认'minkowski与P = 2(即欧氏度量)
n_jobs: 并行工作的数量,如果设为-1,则作业的数量被设置为CPU内核的数量
查看官方api:http://scikit-learn.org/dev/modules/generated/sklearn.neighbors.KNeighborsClassifier.html#sklearn.neighbors.KNeighborsClassifier
示例
# -*- coding: utf-8 -*-
import numpy as np
from sklearn import neighbors
import warnings
warnings.filterwarnings('ignore') # warning信息不打印,可有可无
knn = neighbors.KNeighborsClassifier( ) # 取得knn分类器
data = np.array([[1, 1, 1, 1],
[0.5, 1, 1, 1],
[0.1, 0.1, 0.1, 0.1],
[0.5, 0.5, 0.5, 0.5],
[1, 0.8, 0.3, 1],
[0.6, 0.5, 0.7, 0.5],
[1, 1, 0.9, 0.5],
[1, 0.6, 0.5, 0.8],
[0.5, 0.5, 1, 1],
[0.9, 1, 1, 1],
[0.6, 0.6, 1, 0.1],
[1, 0.8, 0.5, 0.5],
[1, 0.1, 0.1, 1],
[1, 1, 0.7, 0.3],
[0.2, 0.3, 0.4, 0.5],
[0.5, 1, 0.6, 0.6]])
labels = np.array(['美女',
'淑女',
'丑女',
'一般型',
'淑女',
'一般型',
'美女',
'一般型',
'淑女',
'美女',
'丑女',
'可爱型',
'可爱型',
'淑女',
'丑女',
'可爱型'])
knn.fit(data, labels) # 导入数据进行训练
print('预测类型为:', knn.predict([[0.8, 1, 1, 1]]))
结果:
下面是不借用sklearn库的一个KNN实现
#-*- coding: utf-8 -*-
from numpy import *
import operator
def classify(inputPoint,dataSet,labels,k):
dataSetSize = dataSet.shape[0] #已知分类的数据集(训练集)的行数
#先tile函数将输入点拓展成与训练集相同维数的矩阵,再计算欧氏距离
diffMat = tile(inputPoint,(dataSetSize,1))-dataSet #样本与训练集的差值矩阵
sqDiffMat = diffMat ** 2 #差值矩阵平方
sqDistances = sqDiffMat.sum(axis=1) #计算每一行上元素的和
distances = sqDistances ** 0.5 #开方得到欧拉距离矩阵
sortedDistIndicies = distances.argsort() #按distances中元素进行升序排序后得到的对应下标的列表
#选择距离最小的k个点
classCount = {}
for i in range(k):
voteIlabel = labels[ sortedDistIndicies[i] ]
classCount[voteIlabel] = classCount.get(voteIlabel,0)+1
#按classCount字典的第2个元素(即类别出现的次数)从大到小排序
sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True)
return sortedClassCount[0][0]
if __name__ == "__main__" :
dataset = array([[1.0, 1.1], [1.0, 1.0], [0.0, 0.0], [0.0, 0.1]])
labels = ['A', 'A', 'B', 'B']
X = array([1.2, 1.1])
Y = array([0.1, 0.1])
k = 3
labelX = classify(X,dataset,labels,k)
labelY = classify(Y,dataset,labels,k)
print "Your input is:", X, "and classified to class: ", labelX
print "Your input is:", Y, "and classified to class: ", labelY
结果:
Your input is: [ 1.2 1.1] and classified to class: A
Your input is: [ 0.1 0.1] and classified to class: B
SVM的资料非常多,我这里就不赘述了,可以看这篇参考资料
SVM(支持向量机)主要用于分类问题,主要的应用场景有字符识别、面部识别、行人检测、文本分类等领域。
通常SVM用于二元分类问题,对于多元分类通常将其分解为多个二元分类问题,再进行分类
SVM分为SVC(用于分类)和SVG(用于回归)
sklearn提供了三种基于svm的分类方法(SVC):
简书参考资料这里
IRIS介绍
iris.data.shape=(150, 4)
iris.target.shape=(150,)
def prn_obj(obj):
print '\n'.join(['%s:%s' % item for item in obj.__dict__.items()])
# -*- coding:utf-8 -*-
from sklearn import svm
from sklearn import datasets
from sklearn.model_selection import train_test_split as ts
def prn_obj(obj):
print ('\n'.join(['%s:%s' % item for item in obj.__dict__.items()]))
#import our data
iris = datasets.load_iris()
X = iris.data
y = iris.target
#split the data to 7:3
X_train,X_test,y_train,y_test = ts(X,y,test_size=0.3)
# print(X_test.shape)
# select different type of kernel function and compare the score
# kernel = 'rbf'
clf_rbf = svm.SVC(kernel='rbf')
clf_rbf.fit(X_train,y_train)
score_rbf = clf_rbf.score(X_test,y_test)
# prn_obj(clf_rbf)
print("The score of rbf is : %f"%score_rbf)
print("预测结果为", end=":")
print(clf_rbf.predict([[1,2.,3.,4.]])) # 注意要给二维的ndarray嗷
# kernel = 'linear'
clf_linear = svm.SVC(kernel='linear')
clf_linear.fit(X_train,y_train)
score_linear = clf_linear.score(X_test,y_test)
print("The score of linear is : %f"%score_linear)
# kernel = 'poly'
clf_poly = svm.SVC(kernel='poly')
clf_poly.fit(X_train,y_train)
score_poly = clf_poly.score(X_test,y_test)
print("The score of poly is : %f"%score_poly)